I am trying to set/unset some of the debug flags while my code is running. Below is the snippet of the function
class ABC:
def __init__(self,debugFlag):
self.debugFlag = False
def some_function()
if self.debugFlag is True:
print "Some debug logs"
Above is the code snippet. I want to set this debugFlag while my program is running and depends on the situation want to set/unset its value. Based on the current value of debugFlag it should print debug logs or not
How to do this in python
Explaining my problem again : Suppose I am having a script that takes 60 mins to run. I executed the script with debugFlag False. After 15 mins, I want to enable the debug logs. How can I do this without interrupting my execution.
How about:
class ABC:
def __init__(self,debugFlag):
self.debugFlag = False
def some_function():
if self.debugFlag is True:
print "Some debug logs"
def set_flag():
self.debugFlag = True
You can change the value of self.debugFlag when a condition is met, yes.
class ABC:
def __init__(self,debugFlag):
self.debugFlag = debugFlag # or omit that arg and always false
def some_function(self): # Need self
if self.debugFlag:
print "Some debug logs"
def condition_setter(self):
# Do some checks here then set debugflag to False
self.debugFlag = False
One way to accomplish this is to declare var in your modules root, and import/reference them in the same scope when you set and reference.
Imagine the directory structure of your modules like so
my_module/
- __init__.py
- another_module.py
- utils/
- __init__.py
- and_so_on.py
in my_module/__init__.py declare your __debug__ var
__debug__ = False
In your example code
import my_module
class ABC:
def __init__(self):
pass
def some_function()
if my_module.__debug__ is True:
print "Some debug logs"
Then before you actually execute the code, set your debug flag to False importing and referencing in the same fashion
import my_module
my_module.__debug__ = True
As long as you import and reference the variable the same IE:
import my_module
if my_module.__debug__ is True:
print("IN DEBUG")
It will retain its value throughout your execution
Try something like this :
class ABC():
def __init__(self, debugFlag):
self.debugFlag = debugFlag
def some_function(self):
if self.debugFlag:
print('Debug on\n')
else:
print('Debug off\n')
abc_object = ABC(False)
def check_choice():
if str(choice) == '1':
abc_object.debugFlag = True
abc_object.some_function()
elif str(choice) == '2':
abc_object.debugFlag = False
abc_object.some_function()
else :
print('Invalid input')
while True:
choice = input('Type 1 to enable debugging, 2 to disable debuigging : ')
check_choice()
Summary:
When you initialize the class it takes 1 mandatory argument debugFlag, either True or False.
When you define a function from within the class you should use the 'self' argument.
Explanation as to of why this is
'if self.debugFlag' is the same as if 'self.debugFlag is True :' The former should be used as it is more concise.
We instantiate an instance of ABC and store it in the variable abc_object. We pass it a default value for debugFlag, in this case False.
We then introduce some logic to check the state of debugFlag, and then perform some function based on the outcome of our logic.
Hope this helps. Let me know if you need further clarification.
I dont think you can do this directly from variables, but you can, for example, create a file (debug.txt for example) and check if it exists for your triggering. For example, create an empty file called debug.txt and check, inside your script, if the file exists.
Untested code:
import os
class ABC:
def __init__(self,debugFlag):
self.debugFlag = False
def some_function()
if os.path.exists("debug.txt"):
print "Some debug logs"
This way you can trigger/untrigger debug by creating/deleting the file "debug.txt".
With a slight modification of your class:
class ABC:
def __init__(self,debugFlag=False):
self.debugFlag = debugFlag # initialize the flag here or use default
def some_function()
if self.debugFlag is True:
print "Some debug logs"
After you create the object you will be able to change its attributes, like:
obj_abc = ABC() # debug off by default
obj_abc.some_function() # no debug print
obj_abc.debugFlag = True # enable debug
obj_abc.some_function() # now with debug print
obj_abc.debugFlag = False # disable debug
obj_abc.some_function() # now without debug print
Related
I'm having some issue while creating unittest for internal parameter.
My structure is:
[1] my_animal.py contains Myclass and method: do_bite()
my_animal.py
class Myclass():
def do_bite(self):
return 1
[2] my_module.py contains jobMain("") which is using the method from my_animal.py
my_module.py
import sys
from someclass import Myclass
def jobMain(directoryPath):
flag = -1
result = Myclass()
if result.do_bite() is None:
flag = 0
if result.do_bite() is 1:
flag = 1
if result.do_bite() is 2:
flag = 2
[3] my_test.py contains the unittest to test jobMain in my_module.py
my_test.py
# Mock Myclass.dobite to None
#pytest.fixture
def mock_dobite0():
with mock.patch('my_module.Myclass') as mocked_animal:
mocked_animal.return_value.do_bite.return_value = None
yield
# Mock Myclass.dobite to 1
#pytest.fixture
def mock_dobite1():
with mock.patch('my_module.Myclass') as mocked_animal:
mocked_animal.return_value.do_bite.return_value = 1
yield
# Mock Myclass.dobite to 2
#pytest.fixture
def mock_dobite2():
with mock.patch('my_module.Myclass') as mocked_animal:
mocked_animal.return_value.do_bite.return_value = 2
yield
# My unittest to test dobite() method
def test_dobite0(mock_Myclass, mock_dobite0):
jobMain("")
def test_dobite1(mock_Myclass, mock_dobite1):
jobMain("")
def test_dobite2(mock_Myclass, mock_dobite2):
jobMain("")
My question is: How to test 'flag' parameter inside JobMain?
'flag' para must be assigned the correct value.( eg: dobite = 1 => flag = 1)
The variable para only exists in the scope of jobMain. If you want to use the variable outside jobMain the most common ways are
1) return the value
This is quite obvious. Since jobMain is a function, it returns a value. Without an explicit return statement you return None. You could just
def jobmain(pth):
# do stuff and assign flag
return flag
# and inside tests
assert jobmain("") == 1
2) Use a class instead
If you want the jobMain to remember some state, then it is common practice to use objects. Then flag would be attribute of the object and could be accessed from outside, after you call any method (function) of JobMain. For example
class JobMain:
def __init__(self):
self.flag = -1
def run(self, pth):
result = Myclass()
if result.do_bite() is None:
self.flag = 0
if result.do_bite() is 1:
self.flag = 1
if result.do_bite() is 2:
self.flag = 2
# and inside test
job = JobMain()
job.run()
assert job.flag == 1
Note
I just copy-pasted your code for setting the flag. Note that you call do_bite() many times, if the resulting value is None or 1. Also, when testing against a number, one should use == instead of is.
How to test 'flag' parameter inside JobMain?
You don't. It's an internal variable. Testing it would be glass-box testing; the test will break if the implementation changes.
Instead, test the effect of flag. This is black-box testing. Only the interface is tested. If the implementation changes the test still works allowing the code to be aggressively refactored.
Note: If you don't hard code result = Myclass() you don't need to mock. Pass it in as an argument with the default being Myclass().
def jobMain(directoryPath, result=Myclass()):
Then you don't need to patch Myclass(). Instead, pass in a mock object.
# I don't know unittest.mock very well, but something like this.
mock = Mock(Myclass)
mock.do_bite.return_value = 2
jobMain('', result=mock)
This also makes the code more flexible outside of testing.
I have a use case where a function seeks user confirmation to proceed. This is basically:
def abc()
response = click.confirm("Do you want to continue?")
Based on this response, it either aborts or proceeds.
The problem is to test this function abc.
#click.option('--yes', prompt=True)
def test_abc():
with mock.patch.object(click.confirm, input="n"):
click.echo("Aborted")
Old question but I had the same issue, I decided to mock the click.confirm which allowed me to simulate someone selecting [y/N]
lets say your abc() looked like this:
def abc():
if click.confirm("do you want to continue?", abort=True):
return "Confirmed"
return "Aborted"
and then your tests mock the click.confirm to y/n
#mock.patch("click.confirm")
def test_abc_aborted(mock_click):
mock_click.return_value = False
assert abc() == "Aborted"
#mock.patch("click.confirm")
def test_abc_confirmed(mock_click):
mock_click.return_value = "y"
assert abc() == "Confirmed"
i have a new property in my model however I'd like to assign a test value in it for my test script.
this is my code:
models.py
mycode = models.UUIDField(null=True)
#property
def haveCode(self):
if self.mycode == uuid.UUID('{00000000-0000-0000-0000-000000000000}'):
return False
else
return True
and this is the test script that i am working on. I wanted to have a test value for haveCode:
test = Test()
test.mycode = uuid.UUID('{00000000-0000-0000-0000-000000000000}')
test.save()
checkTest = Test()
#this is only to pass the test
#delete this when start coding
checkTest.haveCode = True
assertEqual(test.haveCode, True)
however I got an error in checkTest.haveCode = True since this is just a property and not an attribute.
how to assign True to it? I appreciate your help
You can 'mock' that property using the mock library
from mock import patch, PropertyMock
#patch.object(Test, 'haveCode', new_callable=PropertyMock)
def myTest(test_haveCode_mock):
test_haveCode_mock.return_value = True
checkTest = Test()
assertEqual(checkTest.haveCode, True)
patch.stopall() # when you want to release all mocks
I have a class:
class AccountBusiness:
def save(self, account) -> Account:
if not account.account_number_is_valid():
return False
return True
and a test as:
#mock.patch.object(AccountBusiness, 'save')
def test_can_save_valid_account(self, mock_save):
mock_account = mock.create_autospec(Account)
mock_account.account_number_is_valid.return_value = False
account_business = AccountBusiness()
result = account_business.save(mock_account)
self.assertEqual(result.return_value, True)
but it shows an exception like:
AssertionError: <MagicMock name='save()()' id='48830448'> != True
I want to set the return value of account.account_number_is_valid() to False and run the test.
You are using a patch object on the instance method you are looking to test. However, you are looking to test the logic inside the save method. So mocking that out will not test any of the logic inside that method. So, the output you are actually getting here:
AssertionError: <MagicMock name='save()()' id='48830448'> != True
Should be the first hint that something is not right. Your save method is coming back as a MagicMock. You don't want this. What you actually want to do is only mock the Account class, and go accordingly from there. So, your patching here:
#mock.patch.object(AccountBusiness, 'save')
should actually only be:
#mock.patch('path.to.AccountBusiness.Account', return_value=Mock(), autospec=True)
The path.to.AccountBusiness.Account is the location of the Account class with respect to the AccountBusiness class.
So, with that patching, then the return_value of calling Account will now be your mock object that you can use for your account_number_is_valid. So, the code will actually look like this:
class MyTest(unittest.TestCase):
def setUp(self):
self.account_business = AccountBusiness()
#mock.patch('path.to.AccountBusiness.Account', return_value=Mock(), autospec=True)
def test_can_save_valid_account(self, mock_account):
mock_account_obj = mock_account.return_value
mock_account_obj.account_number_is_valid.return_value = False
self.assertFalse(self.account_business.save(mock_account_obj))
Also, pay close attention to the assertion at the end. It was changed to make use of the available assertFalse. Also, look over your own logic, as returning False for account_number_is_valid will actually return False in your save method.
How can I use external variables in Python, like extern int x; in C?
For example,
main1.py:
from myfunc import print_a
a = 10
print a
print_a()
myfunc.py:
def print_a():
global a
print a
Simply re-assign the variable in the module:
import myfunc
from myfunc import print_a
a = 10
print a
myfunc.a = a
print_a()
Otherwise it is not possible.
Rememeber that python treats modules in a way that is quite different from C.
The import in python does not "copy the contents" of the file in that place,
but it executes the code in the given file and creates a module object.
The global variable of the module are the module object attributes, which can be modified as I've shown. There is no such notion as "global variable" except for built-ins.
I'd suggest to refactor your code in such a way that you don't have to modify this global variable at all, moving the code that uses myfunc.a from main1 to myfunc.
The fact that you need such global variable is already a code smell that there's something wrong with your code and you should try to fix it.
Actually there is a way to affect the "global scope" but it is so hackish that I don't even want to mention it. Trust me: you don't want to use it. If people see your code using such a hack you may be in physical danger.
Unlike C, variables declared at global scope are still limited in scope to the module they are created in, so you need to qualify the name a with the module it lives in.
The global keyword is used when you are going to modify a global variable by reassigning, you do not need it when you are just referencing a global variable.
If you are trying to access a variable of another file, you must import that module, and because of the way your files are structured you have a couple of ways to resolve issues:
Option 1) Move the referencing of myfunc.print_a inside of a function and import main1 inside myfunc to see a
main1.py
import myfunc
a = 10
def main():
print a
myfunc.print_a()
if __name__ == '__main__':
main()
myfunc.py
import main1
def print_a():
print main1.a
Option 2) recommended Move the variable(s) into another module and have both myfunc and main1 import it.
vals.py
a = 20
main1.py
import vals
from myfunc import print_a
vals.a = 10
print vals.a
print_a()
myfunc.py
import vals
def print_a():
print vals.a
This is a workaround to this problem by using a common external file. In this example I am storing an index variable to flag in each application whether a file is being accessed. The variable indxOpen in ext1.py and indxO in ext2.py are being updated and stored in a common external text file "externalVars.txt"
lead application ext1.py
# lead application ext1.py
#this alternately flips the value of indxOpen on prime number intervals
import time
def update(d,v1):
f=open(d+'externalVars.txt','r+')
f.write(str( v1))
f.truncate()
f.close()
# ensure variable is initialised and made available to external apps
indxOpen = False
var_dir = "<your external var directory>/"
try:
f =open(var_dir+'externalVars.txt','r')
except:
f= open(var_dir+'externalVars.txt','w')
f.close()
# this alternately flips the value of indxOpen on prime number intervals
update(var_dir,indxOpen)
i = 0
while True:
while indxOpen:
i += 1
if (i % 13) ==0:
indxOpen = indxOpen ^ True
update(var_dir,indxOpen)
f=open(var_dir+'externalVars.txt','r+')
t=f.readline()
print "app1",t," ",i
if t=='False':
print "app1 updated"
update(var_dir,indxOpen)
indxOpen = False
else:
time.sleep(1.4)
while not indxOpen:
f=open(var_dir+"externalVars.txt","r+")
t=f.readline()
print "app1",t
if t=='True':
indxOpen = True
else:
time.sleep(1)
ext2.py following application
# ext2.py this alternately flips the value of indxO on prime number intervals but it is initialised by the lead application
# in this case ext1.py
# python 2.7.12
import time
def update(d,v1):
f=open(d+'externalVars.txt','r+')
f.write(str( v1))
f.truncate()
f.close()
var_dir = "<your external var directory>/"
# intialise external variable
f=open(var_dir+'externalVars.txt','r+')
t=f.readline()
if t=='True':
indxO= True
if t=='False':
indxO= False
i=0
while True:
while indxO:
f=open(var_dir+"externalVars.txt","r+")
t=f.readline()
print "app2",t
if t=='False':
indxO = False
update(var_dir,indxO)
else:
time.sleep(1.5)
while not indxO:
i += 1
if (i % 17) ==0:
indxO = indxO ^ True
update(var_dir,indxO)
f=open(var_dir+"externalVars.txt","r+")
t=f.readline()
print "app2",t," ",i
if t=='True':
indxO = True
print "apt2 updated"
update(var_dir,indxO)
else:
time.sleep(1.3)