Correctly suppress comments - pyparsing

I want to filter out comments starting with a hash # out of a text file, before I run a larger parser over it.
For this I make use of suppress as mentioned here.
pythonStyleComment does not work, because it ignores quotations and removes stuff within it. A hash in a quoted string is not a comment. It is part of the string and therefore should be preserved.
Here is my pytest which I already implemented to test the expected behavior.
def test_filter_comment():
teststrings = [
'# this is comment', 'Option "sadsadlsad#this is not a comment"'
]
expected = ['', 'Option "sadsadlsad#this is not a comment"']
for i, teststring in enumerate(teststrings):
result = filter_comments.transformString(teststring)
assert result == expected[i]
My current implementation breaks somewhere in pyparsing. I probably do something which was not intended:
filter_comments = Regex(r"#.*")
filter_comments = filter_comments.suppress()
filter_comments = filter_comments.ignore(QuotedString)
fails with:
*****/lib/python3.7/site-packages/pyparsing.py:4480: in ignore
super(ParseElementEnhance, self).ignore(other)
*****/lib/python3.7/site-packages/pyparsing.py:2489: in ignore
self.ignoreExprs.append(Suppress(other.copy()))
E TypeError: copy() missing 1 required positional argument: 'self'
Any help how to ignore comments correctly, would be helpful.

Ah I was so close. I have of course to properly instantiate the QuotedString class.The following works as expected:
filter_comments = Regex(r"#.*")
filter_comments = filter_comments.suppress()
qs = QuotedString('"') | QuotedString("'")
filter_comments = filter_comments.ignore(qs)
Here are some more tests.
def test_filter_comment():
teststrings = [
'# this is comment', 'Option "sadsadlsad#this is not a comment"',
"Option 'sadsadlsad#this is not a comment'",
"Option 'sadsadlsad'#this is a comment"
]
expected = [
'', 'Option "sadsadlsad#this is not a comment"',
"Option 'sadsadlsad#this is not a comment'",
"Option 'sadsadlsad'"
]
for i, teststring in enumerate(teststrings):
result = filter_comments.transformString(teststring)
assert result == expected[i]

The regex you're using is not correct.
I think you meant:
^\#.*
or
^(?:.*)\#.*

Related

Using dag_run.conf in an operator

I am passing the following as the json
{“name”: “john”}
when triggering, with this operator:
do_stuff = DatabricksSubmitRunOperator(
task_id=“do_stuff”,
spark_python_task={“python_file”: “…”,
“parameters”: f"{uid}", '\'{{ dag_run.conf["name"] if dag_run else "" }}\''},
existing_cluster_id=cluster_id
)
I’m getting a syntax error, but I am thinking it’s related to escaping characters… I have not used templating before.
do_stuff = DatabricksSubmitRunOperator(
task_id=“do_stuff”,
spark_python_task={“python_file”: “…”,
“parameters”: [f"{uid}",'{{ (dag_run.conf["name"] if dag_run else "") | tojson }}']},
existing_cluster_id=cluster_id
)

Get pre-existing variable through user input

I'm making a script that asks for input. Few variables has been set according to number of option.
option1 = '.\\Folder'
userChoice = input()
def func(userChoice):
pyautogui.locateOnScreen(userChoice)
But if user type option1 then userChoice = 'option1' instead '.\Folder' which lead to 'No such file or directory' error.
How could i solve the problem?
You can use python's try-except. An example from official docs:
import sys
try:
f = open('myfile.txt')
s = f.readline()
i = int(s.strip())
except OSError as err:
print("OS error: {0}".format(err))
except ValueError:
print("Could not convert data to an integer.")
except:
print("Unexpected error:", sys.exc_info()[0])
raise
Update: Based on your comment, I think you need to do something like this:
choices={'option1' : './/Folder'}
userChoice = input()
try:
function=choices[userChoice]
except KeyError:
raise ValueError('invalid input')

Matching dict key to text file and returning Test Pass/fail

I'm a novice at Python, and am currently working on a small test case assignment where I am to find and match the dictionary keys to a small text file, and see if the keys are present in the text file.
As follows, the dictionary goes:
dict = {"description, translation": "test_translation(serial,",
"unit": "test_unit(",}
The text in text file, henceforth called "requirement.txt" as follows:
The description shall display the translation of XXX.
The unit shall be hidden.
The value is read from the file "version.txt".
To the key, I am to find and match if they are present or absent - a match should return a "test pass", no match would return a skip.
Keys from dictionary are to be sorted to a list, then iterated and matched to text. (Values from dictionary are to be sorted to a seperate list and iterated over a seperate file, to which I shall not delve into it here.)
This is the code that I currently have (and stuck):
list = sorted(key_words.keys(), key=lambda d: d[0])
with open('C:/Users-------/requirement.txt', 'r') as outfile:
lines = outfile.readlines()
for line in lines:
line = line.strip()
if line == '':
continue
line_strings = line.split(' ')
for word in list:
if word in line:
print("Test Pass")
print(word)
break
else:
print("Test Fail")
print(line + "\n")
Result currently obtained:
Test Fail
Test Pass
display
The description shall display the translation of XXX.
Test Fail
Test Fail
Test Fail
Test Pass
unit
The unit shall be hidden.
Test Fail
Test Fail
Test Fail
Test Fail
The value is read from the file "version.txt".
Using the current code which I have, (and I am stuck), running the code returned multiple times of "Test pass" and "Test fail", suggesting that the keys are iterated multiple times over each line and the results returned for each multiple iteration.
I am stuck at two fronts:
After seperating the key into a list, how to order them in the sequence of "description, translation", "unit)?
How to modify the code so as to ensure that result is returned once as "Test pass" or "test fail"
Results should ideally return in the following format:
Ideal outcome:
('Text:', "The description shall display the translation of XXX.
('Key:', 'description, translation')
Test Pass
('Text:', 'The unit shall be hidden.')
('Key:', 'unit')
Test Pass
('Text:', 'The value is read from the file "version.txt".')
('Key:', (none))
Test Fail
For your kind enlightenment please, thank you!
Try with this:
list = sorted(key_words.keys(), key=lambda d: d[0])
with open('C:/Users-------/requirement.txt', 'r') as outfile:
lines = outfile.readlines()
for line in lines:
line = line.strip()
if line == '':
continue
# Create an empty list which will contain all the word that match
words_found = []
for word in list:
# if the word match then add it to the list words_found
if word in line:
words_found.append(word)
print("(\'Text:\',\"{}\"")' ".format(line))
print("(\'Keys:\',\"{}\"")' ".format(words_found))
# if the list of words found it's not empty then the test passed
if(words_found):
print("Test Passed")
else:
print("Test Failed")
the idea is to create a list of the words founds and then print them all
I'm using the format Operation and you can find a guide on how to use it here. And the line if(words_found): check if the list is empty.
Additional Notes
In this case, you won't need it but if you wanted to solve only the second point you can use the for else statement as explained in the docs
4.4 break and continue Statements, and else Clauses on Loops
Loop statements may have an else clause; it is executed when the loop terminates through exhaustion of the list (with for) or when the condition becomes false (with while), but not when the loop is terminated by a break statement.
Reducing by one tab the indentation the else of your if statement it became the else of the for statement so it will be executed only if the for never had a break the problem is solved.
list = sorted(key_words.keys(), key=lambda d: d[0])
with open('C:/Users-------/requirement.txt', 'r') as outfile:
lines = outfile.readlines()
for line in lines:
line = line.strip()
if line == '':
continue
line_strings = line.split(' ')
for word in list:
if word in line:
print(word)
print("Test Pass")
break
else:
print("Test Fail")
print(line + "\n")
Edit
To split the key into description and translation we just have to split the two word at the comma with the builtin function split
list = sorted(key_words.keys(), key=lambda d: d[0])
with open('C:/Users-------/requirement.txt', 'r') as outfile:
lines = outfile.readlines()
for line in lines:
line = line.strip()
if line == '':
continue
# Create an empty list which will contain all the word that match
words_found = []
for word in list:
description, translation = word.split(",")
# if the word match then add it to the list words_found
if description in line:
words_found.append(description)
print("(\'Text:\',\"{}\"")' ".format(line))
print("(\'Keys:\',\"{}\"")' ".format(words_found))
# if the list of words found it's not empty then the test passed
if(words_found):
print("Test Passed")
else:
print("Test Failed")

python for loop getting letters in a word by using return

I'm trying to make a function which will operate like this:
input:
make_nametag('apple')
output:
'a*p*p*l*e*'
this is my code:
def make_nametag(name):
for letter in name:
print(letter + '*', end='')
Are there any ways that I can use return instead? Thanks!
Thanks !
I actually figured this out by using:
def make_nametag(name):
get = int(len(name))
a = ''
for letter in name:
a+=str(letter + "*")
return a
if there are any better solutions, please share.

Groovy Map Issue with Variable Properties and String INterpolation

I have been navigating map structures fine for a long time now. Yet, for some reason, the root of this problem escapes me. I've tried bracket notation as well, no luck.
Why doesn't the final output (null) return "[serverinfo:[listenPort:19001]]"
If I replace the two instances of ' "$instanceName" ' with simply ' services ', it works.
String instanceName = "Services"
Map serverNode = [
instances:[
"$instanceName":[
serverinfo:[
listenPort:19001
]
]
]
]
println "$instanceName"
println serverNode.instances
println serverNode.instances."$instanceName"
//output
Services
[Services:[serverinfo:[listenPort:19001]]]
null
The type of "$instanceName" is GStringImpl, not String. It's a common mistake (and hard to find!)
def serverNode = [
instances:[
("$instanceName" as String):[
serverinfo:[
listenPort:19001
]
]
]
]
as stated by #tim_yates in comment, if your interpolated string is as simple as in this example (ie ,"${property}"), then you can use the (property) syntax : Groovy put the value of the property as a key, not the word "property"

Resources