How can I test how many times a function is called? - python

I have used the following suggestion to set up my code: Checking whether function has been called multiple times with different parameters
I would like to test how many times the function write_standalone_end_of_event is called.
#exchanges.impl.bats.mcformat.py
def delete_data(...):
exg = exchanges.impl.bate.parser.Exchange
securities = [one_item]
for security in securities:
exg.write_standalone_end_of_event
#unit_test_package
with patch('exchanges.impl.bate.parser.Exchange.write_standalone_end_of_event') as function:
bats.protocol.sec_id_in_batch = {1: 'dummy1'}
bats.protocol.transaction_end(exg, fields, values, msgtype, sequence)
assert function.gacs.call_count == 1
When I run the above, i get an asserTion error that 0 != 1.
I can't seem to figure out why the function is not picking up the one call to it, even though when I debug it, it does seem to call write_standalone_end_of_event one time.

Related

Define stubs in python

I am stuck on this homework problem. This is the assignment question and prompt:
"Define stubs for the functions get_user_num() and compute_avg(). Each stub should print "FIXME: Finish function_name()" followed by a newline, and should return -1. Each stub must also contain the function's parameters.
Sample output with two calls to get_user_num() and one call to compute_avg():
FIXME: Finish get_user_num()
FIXME: Finish get_user_num()
FIXME: Finish compute_avg()
Avg: -1"
I have tried a bunch of different things, but I just keep getting errors. I'm completely lost on this one. This is what I have so far:
def get_user_num(user_num1, user_num2):
get_user_num = -1
avg = user_num1 + user_num2
return get_user_num
user_num1 = 0
user_num2 = 0
avg_result = 0
user_num1 = get_user_num()
user_num2 = get_user_num()
avg_result = compute_avg(user_num1, user_num2)
print('Avg:', avg_result)
And I am just getting error message after error message. I know I have to use def to define something, but I'm lost.
So let's start simple, you got some statement, let's parse it into simple parts and connect it into the Python world.
Define stubs
noun Something cut short or arrested in development. (source)
for the functions get_user_num() and compute_avg()
The keyword def introduces a function definition. It must be followed by the function name and the parenthesized list of formal parameters. The statements that form the body of the function start at the next line, and must be indented. (source)
Each stub should print
Check how to output something with Python to the console.
followed by a newline
As in do not make two FIXME lines collapse onto each other like this: FIXME: somethingFIXME: something else.
the Unix end-of-line convention '\n', the Windows convention '\r\n', and the old Macintosh convention '\r'...
(source)
and should return -1
Each stub must also contain the function's parameters.
Undefined anywhere. So either use something you'd normally use for a let's say maths function or likes
Sample output with two calls to get_user_num() and one call to compute_avg(): ...
This is how the final program should behave once executed. A function is called by first being ensuring it's been defined previously, then writing its name + () e.g. func().
Judging by the undefined func arguments and two related functions, you might want to connect the two functions either directly or with an intermediary item holding the result.
After these steps you should be able to create the final program. Do not try to create it at once, utilize the bullet points as small steps and always check if the file still works (executes properly). Create multiple files (copy-paste) when necessary.
Nobody cares how it looks like while developing. You're learning, you'll become better eventually.
I found the solution!!! Thank you all for the help. It really did just take trial and error and making sense of the error messages.
'''
def get_user_num():
print('FIXME: Finish get_user_num()')
return -1
def compute_avg(user_num1, user_num2):
print('FIXME: Finish compute_avg()')
return -1
user_num1 = 0
user_num2 = 0
avg_result = 0
user_num1 = get_user_num()
user_num2 = get_user_num()
avg_result = compute_avg(user_num1, user_num2)
print('Avg:', avg_result)
'''

How to take data from a pytest function(monekypath)

I have developed a program that contains many functions. I am now testings these functions. To do this, I have needed to use a monkeypath approach because the function tested calls input.
Because to test the functions I need to get the data of the previous tests, with the monkeypath function I have found difficulties.
data_to_test_1 = test_load_sample() # I take the data from the previous test here
# SECOND TEST
def test_take_sample(monkeypatch):
'''
take_sample() requests the name of the column
and take that input to split the data in new columns
This can be tested by checking some ofthe first values of that
columns (GT:AD:DP:GQ:PL)
monkeypatch simulate the input of the user
'''
monkeypatch.setattr('builtins.input', lambda _: "373978487") # The 9th sample in the file
data_to_test_2 = take_sample(data_to_test_1,NAME_FILE_1)
return data_to_test_2
assert data_to_test_2["GT"] == "0/1" # What I test
assert data_to_test_2["AD"] == "28,46"
assert data_to_test_2["DP"] == "74:99"
# Now, I want the output of the test_take_sample()
data_to_test_3 = test_take_sample()
def test_filter_1():
... # this function will use data_to_test_3
I have followed the same approach with previous functions to concatenated the data from one test to the following one but with this that involves the monkeypath thing I got
test_take_sample() missing 1 required positional argument: 'monkeypatch'
For the first case, I think function test_load_sample() did not need parameter. So you allocate 'data_to_test_1' about the value of the function 'test_load_sample()'
if you make
data_to_test_1 = test_load_sample()
data_to_test_1 receive return value of test_load_sample() not function itself
I think you think that you are allocating function to data_to_test_1 but it is not. you just allocate value of the function.
If you wanna allocate function to some variable, Use 'class' type
I have solve the issue with this
data_to_test_2,Name_sample = take_sample(data_to_test_1,NAME_FILE_1)
I have jumped the test test_take_sample() and I have just run the function take_sample. This has asked me the input and I have introduce the input adding -s when the test has been run like this: pythest test_1.py -s

Clean way to variable check + continue in while loop

I have a relatively large main() function where I need to check a variable several times at different places in the function and then decide if I should continue the loop accordingly, like so:
def main():
while True:
...
if foo.check():
reset()
continue
...
Where foo is working as a time keeper of sorts, therefore I need to check it at certain intervals. These 3 lines appear about 3 to 5 times within the function.
I hate how dirty this is, so is there a cleaner way to do this?
You haven't specified enough information. I have two questions:
Is the call foo.check() idempotent meaning it always returns the same value and has no side-effects?
Is there a path through the code where you can reach the nth call to foo.check() in the same block governed by the continue statement without first calling the n-1th occurrence?
If, for example, the answer to the answer is yes and the second question were no, then you could remove all but the first occurrence of the call to foo.check() because the return value is clearly False or else you would never reach the second occurence.
If the answer to the first question is yes and the second is yes, then if the call to foo_check() is expensive, I might consider up front setting:
check_result = foo.check()
and then replacing every call to foo_check() with check_result. But ultimately you still need to do all the checks. But in all cases you can create a function check_and_reset:
def check_and_reset():
if foo_check():
reset()
return True
return False
Then your code becomes:
if check_and_reset(): continue
I have two suggestions:
Suggestion 1:
Create another function and call wherever you want.
Suggestion 2:
Make it as a one-liner
if foo.check():reset();continue
If it is just a complex way to control some timing while running a set of tasks, I'd suggest to introduce a loop over the tasks. You can even easily pass partial results around:
def task_a():
...
def task_c(some_input):
...
tasks = [lambda x: task_a(), task_c]
last_stage_output = None
while True:
reset()
for task in tasks:
if not foo.check():
break
last_stage_output = task(last_stage_output)
This way, you make it clear that it is just a series of tasks to be done, it's simple to add, remove of reshuffle them, and the timing logic is concentrated in a single point.

Does accessing a methods returned value re-run the method?

As I am learning Python, and programming in general, I've come across a concept I'm not very sure of. I am working on a script and I am curious on if I have already created object and if I want to access the returned value from one of that object's methods, will it rerun the method, or will it simply reply back with those values. For example:
class ClassOne():
def oneMethod(self):
x = 2
y = 10
return x, y
class ClassTwo():
def twoMethod(self, x, y):
...
newObject = ClassOne()
newObject.oneMethod()
secondObject = ClassTwo()
# My question is, will the lines below re-execute newObject.oneMethod()
# or will it simply pull the already returned value
secondObject.twoMethod(newObject.oneMethod()[0],
newObject.oneMethod()[1])
While my script isn't necessarily large enough to be super worried about performance, it's just something I'm wondering and couldn't find much info about online.
Your title asks a different question from the text body.
No, accessing the result of a method won't rerun the method. But that's not what you're doing here; you explicitly call the method twice, so of course it will run twice.
The normal thing to do is to assign the returned value to a variable and use that as many times as you want.
The answer is yes, the method will re-execute each time it is called.
You could verify that by adding a call to print() in oneMethod() to see whether its code is executed every time it is called. You will find that it is.
You can avoid re-execution by binding the return value to some variable(s), e.g.
a, b = newObject.oneMethod() # will call and execute the code in oneMethod()
secondObject = ClassTwo()
secondObject.twoMethod(a, b)
Here the tuple (2, 10) will be returned from oneMethod() and it will be unpacked into the variables a and b such that a = 2 and b = 10. You could also use a single tuple variable, and then access individual elements via indexing:
t = newObject.oneMethod()
secondObject.twoMethod(t[0], t[1])
# secondObject.twoMethod(*t) # also works, see below...
Another way, without having to save the return value first, is to pass the return value of oneMethod() directly into twoMethod() using tuple unpacking with the * operator:
secondObject = ClassTwo()
secondObject.twoMethod(*newObject.oneMethod())

Alternative to exec

I'm currently trying to code a Python (3.4.4) GUI with tkinter which should allow to fit an arbitrary function to some datapoints. To start easy, I'd like to create some input-function and evaluate it. Later, I would like to plot and fit it using curve_fit from scipy.
In order to do so, I would like to create a dynamic (fitting) function from a user-input-string. I found and read about exec, but people say that (1) it is not safe to use and (2) there is always a better alternative (e.g. here and in many other places). So, I was wondering what would be the alternative in this case?
Here is some example code with two nested functions which works but it's not dynamic:
def buttonfit_press():
def f(x):
return x+1
return f
print(buttonfit_press()(4))
And here is some code that gives rise to NameError: name 'f' is not defined before I can even start to use xval:
def buttonfit_press2(xval):
actfitfunc = "f(x)=x+1"
execstr = "def {}:\n return {}\n".format(actfitfunc.split("=")[0], actfitfunc.split("=")[1])
exec(execstr)
return f
print(buttonfit_press2(4))
An alternative approach with types.FunctionType discussed here (10303248) wasn't successful either...
So, my question is: Is there a good alternative I could use for this scenario? Or if not, how can I make the code with exec run?
I hope it's understandable and not too vague. Thanks in advance for your ideas and input.
#Gábor Erdős:
Either I don't understand or I disagree. If I code the same segment in the mainloop, it recognizes f and I can execute the code segment from execstr:
actfitfunc = "f(x)=x+1"
execstr = "def {}:\n return {}\n".format(actfitfunc.split("=")[0], actfitfunc.split("=")[1])
exec(execstr)
print(f(4))
>>> 5
#Łukasz Rogalski:
Printing execstr seems fine to me:
def f(x):
return x+1
Indentation error is unlikely due to my editor, but I double-checked - it's fine.
Introducing my_locals, calling it in exec and printing in afterwards shows:
{'f': <function f at 0x000000000348D8C8>}
However, I still get NameError: name 'f' is not defined.
#user3691475:
Your example is very similar to my first example. But this is not "dynamic" in my understanding, i.e. one can not change the output of the function while the code is running.
#Dunes:
I think this is going in the right direction, thanks. However, I don't understand yet how I can evaluate and use this function in the next step? What I mean is: in order to be able to fit it, I have to extract fitting variables (i.e. a in f(x)=a*x+b) or evaluate the function at various x-values (i.e. print(f(3.14))).
The problem with exec/eval, is that they can execute arbitrary code. So to use exec or eval you need to either carefully parse the code fragment to ensure it doesn't contain malicious code (an incredibly hard task), or be sure that the source of the code can be trusted. If you're making a small program for personal use then that's fine. A big program that's responsible for sensitive data or money, definitely not. It would seem your use case counts as having a trusted source.
If all you want is to create an arbitrary function at runtime, then just use a combination of the lambda expression and eval. eg.
func_str = "lambda x: x + 1" # equates to f(x)=x+1
func = eval(func_str)
assert func(4) == 5
The reason why your attempt isn't working is that locals(), in the context of a function, creates a copy of the local namespace. Mutations to the resulting dictionary do not effect the current local namespace. You would need to do something like:
def g():
src = """
def f(x):
return x + 1
"""
exec_namespace = {} # exec will place the function f in this dictionary
exec(src, exec_namespace)
return exec_namespace['f'] # retrieve f
I'm not sure what exactly are you trying to do, i.e. what functions are allowed, what operations are permitted, etc.
Here is an example of a function generator with one dynamic parameter:
>>> def generator(n):
def f(x):
return x+n
return f
>>> plus_one=generator(1)
>>> print(plus_one(4))
5

Categories