I am using pyke3-1.1.1, how do you write a rule whose 'assert' contains another rule defined before? I want to do this in the forward chaining type.
Example:
Rule1
foreach
questions.test_question(True)
Assert
Python print("rule 1 called")
Rule2
foreach
questions.test_question2(True)
assert
(How to call rule1 here?)
Related
I want to implement a test that looks like this :
def test_some_function(snapshot):
my_unsortable_list = my_function()
assert my_unsortable_list == snapshot
However the my_unsortable_list variable is of type List[Dict] and there is no easy way to sort it.
Also, the values inside my_unsortable_list are always the same but the order is random.
Therefore the assertion assert my_unsortable_list == snapshot fails if we run this test.
I was wondering if there is a way to get rid of snapshot order and do something like this :
assert len(my_unsortable_list) == len(snapshot) # Compare number of elements in lists
assert all([x in my_unsortable_list for x in snapshot]) # Assert all elements are in both lists
The code above fails, is there a way to use advanced features of pytest-snapshot so that works ?
If I make a code like:
lists = ["a='1'", "b='2'", "c=a+b"]
returned_list = []
for x in lists:
exec(x)
print(c)
It works, and It print "12". but, If I use exec() in function:
lists = ["a='1'", "b='2'", "c=a+b"]
def test(lst):
for x in lists:
exec(x)
print(c)
test(lists)
It returns NameError: name 'c' is not defined. How could I use exec() in function?
When you assign a new variable in a function, you are actually assigning a variable in a scope which will be closed after the function is closed.
Imagine it as a bubble with an item inside, which after the bubble blows, the item blows and disappears as well. It means, using exec() in a function would create a temporary local variable. But since functions have a predefined code, adding new variables to them without changing the code directly, would not be possible. in that case we need to use global keyword for each new variable in exec to make the variable save in the main and not in function. Therefor, your list would like this:
lists = ["global a\na='1'"]
also I'm not quite sure if you like the output of a+b be 12, if not, you can just remove the single quotes around each number such as "a=1" to make them integers
for further information check this and this
I have the following function:
def test(crew):
crew1 = crew_data['CrewEquipType1']
crew2 = crew_data['CrewEquipType2']
crew3 = crew_data['CrewEquipType3']
return
test('crew1')
I would like to be able to use any one of the 3 variables as an argument and return the output accordingly to use as a reference later in my code. FYI, each of the variables above is a Pandas series from a DataFrame.
I can create functions without a parameter, but for reason I can't quite get the concept of how to use parameters effectively such as that above, instead I find myself writing individual functions rather then writing a single one and adding a parameter.
If someone could provide a solution to the above that would be greatly appreciated.
Assumption: You problem seems to be that you want to return the corresponding variable crew1, crew2 or crew3 based on your input to the function test.
Some test cases based on my understanding of your problem
test('crew1') should return crew_data['CrewEquipType1']
test('crew2') should return crew_data['CrewEquipType2']
test('crew3') should return crew_data['CrewEquipType3']
To accomplish this you can implement a function like this
def test(crew):
if crew=='crew1':
return crew_data['CrewEquipType1']
elif crew=='crew2':
return crew_data['CrewEquipType2']
elif crew=='crew3':
return crew_data['CrewEquipType3']
...
... # add as many cases you would like
...
else:
# You could handle incorrect value for `crew` parameter here
Hope this helps!
Drop a comment if not
I am new to Python and am at a lost as to what I'm doing wrong. I am trying to use the fqdn variable that is being returned to the caller which is main() but I'm getting NameError: name 'fqdn' is not defined
I'm betting this is some type of global variable statement issue or something like that, but I've been researching this and can't figure it out.
If a function from a module returns a value, and the caller is main(), shouldn't main() be able to use that returned value???
Here's the layout:
asset.py
def import_asset_list():
# Open the file that contains FQDNs
openfile = open(r"FQDN-test.txt")
if openfile.mode == 'r':
# Remove CR from end of each item
fqdn = openfile.read().splitlines()
# Add https to the beginning of every item in list
fqdn = ["https://" + item for item in fqdn]
openfile.close()
return fqdn
tscan.py
def main():
import asset
asset.import_asset_list()
# Iterate through list
for i in fqdn:
if SCHEDULED_SCAN == 1:
create_scheduled_scan(fqdn)
launch_scan(sid)
check_status_scan(uuid)
else:
create_scan(fqdn)
launch_scan(sid)
check_status_scan(uuid)
Short Explanation
Yes, main() should be able to use the returned value, but it's only the value that is returned, not the variable name. You have to define a variable of your own name, to receive the value, and use that instead.
Long Explanation
The name of a variable inside any function is simply a "label" valid only within the scope of this function. A function is an abstraction which means "Give me some input(s), and I will give you some output(s)". Within the function, you need to reference the inputs somehow and, potentially, assign some additional variables to perform whatever it is you would like to. These variable names have no meaning whatsoever outside the function, other than to, at most, convey some information as to the intended use of the function.
When a function returns a value, it does not return the "name" of the variable. Only the value (or the reference in memory) of the variable. You can define your own variable at the point where you call the function, give it your own name and assign to it the returned result of the function, so you simply have to write:
def main():
import asset
my_asset_list = asset.import_asset_list()
# Iterate through list
for i in my_asset_list:
if SCHEDULED_SCAN == 1:
create_scheduled_scan(my_asset_list)
launch_scan(sid)
check_status_scan(uuid)
else:
create_scan(my_asset_list)
launch_scan(sid)
check_status_scan(uuid)
I don't know where the uuid and the sid variables are defined.
To make sure you have understood this properly, remember:
You can have multiple functions in the same file, and use identically-named variables within all those functions, this will be no problem because a variable (with its name) only exists within each specific function scope.
Variable names do not "cross" the boundaries of the scope, only variable values/references and to do this, a special construct is used, i.e. the return [something] statement.
I am writing a framework in Python. When a user declares a function, they do:
def foo(row, fetch=stuff, query=otherStuff)
def bar(row, query=stuff)
def bar2(row)
When the backend sees query= value, it executes the function with the query argument depending on value. This way the function has access to the result of something done by the backend in its scope.
Currently I build my arguments each time by checking whether query, fetch and the other items are None, and launching it with a set of args that exactly matches what the user asked for. Otherwise I got the "got an unexpected keyword argument" error. This is the code in the backend:
#fetch and query is something computed by the backend
if fetch= None and query==None:
userfunction(row)
elif fetch==None:
userunction (row, query=query)
elif query == None:
userfunction (row, fetch=fetch)
else:
userfunction (row,fetch=fetch,query=query)
This is not good; for each additional "service" the backend offers, I need to write all the combinations with the previous ones.
Instead of that I would like to primarily take the function and manually add a named parameter, before executing it, removing all the unnecessary code that does these checks. Then the user would just use the stuff it really wanted.
I don't want the user to have to modify the function by adding stuff it doesn't want (nor do I want them to specify a kwarg every time).
So I would like an example of this if this is doable, a function addNamedVar(name, function) that adds the variable name to the function function.
I want to do that that way because the users functions are called a lot of times, meaning that it would trigger me to, for example, create a dict of the named var of the function (with inspect) and then using **dict. I would really like to just modify the function once to avoid any kind of overhead.
This is indeed doable in AST and that's what I am gonna do because this solution will suit better for my use case . However you could do what I asked more simply by having a function cloning approach like the code snippet I show. Note that this code return the same functions with different defaults values. You can use this code as example to do whatever you want.
This works for python3
def copyTransform(f, name, **args):
signature=inspect.signature(f)
params= list(signature.parameters)
numberOfParam= len(params)
numberOfDefault= len(f.__defaults__)
listTuple= list(f.__defaults__)
for key,val in args.items():
toChangeIndex = params.index(key, numberOfDefault)
if toChangeIndex:
listTuple[toChangeIndex- numberOfDefault]=val
newTuple= tuple(listTuple)
oldCode=f.__code__
newCode= types.CodeType(
oldCode.co_argcount, # integer
oldCode.co_kwonlyargcount, # integer
oldCode.co_nlocals, # integer
oldCode.co_stacksize, # integer
oldCode.co_flags, # integer
oldCode.co_code, # bytes
oldCode.co_consts, # tuple
oldCode.co_names, # tuple
oldCode.co_varnames, # tuple
oldCode.co_filename, # string
name, # string
oldCode.co_firstlineno, # integer
oldCode.co_lnotab, # bytes
oldCode.co_freevars, # tuple
oldCode.co_cellvars # tuple
)
newFunction=types.FunctionType(newCode, f.__globals__, name, newTuple, f.__closure__)
newFunction.__qualname__=name #also needed for serialization
You need to do that weird stuff with the names if you want to Pickle your clone function.