Python: Correct use of Click with __main__ and __init__ - python

I have been playing around with the Click package and I can't get the following snippit of code to work properly.
import numpy as np
import click
#click.command()
#click.option('--get_print', default = True)
class CustomClass():
def __init__(s, get_print):
s.data = np.random.normal(0, 1, 10)
s.get_print = get_print
if s.get_print:
print("get_print =", s.get_print)
def print_mean(s):
print("Printing mean:")
mean_ = np.mean(s.data)
if s.get_print:
print(mean_)
if __name__ == '__main__':
CustomClass().print_mean()
It seems that the print_mean function never gets called. If I comment out the #Click decorator, and manually set get_print=True, the print_mean method gets called just fine.
My suspicion is that #Click somehow sets __main__ and so when I do if __name__ == '__main__' it just calls Click again - but perhaps I'm wrong?
In either case, what is the correct way of using Click, when you want the __init__ method to inherit all the options, and if __name__ == '__main__'to actually be able to call functions inside the class, where the __init__ is defined?

This is just to illustrate what I mean in my comments. Decorate a function with the click functions and have that function instantiate your class and execute whatever member function you need. This is what the click docs suggests:
import numpy as np
import click
class CustomClass:
def __init__(self, get_print):
self.data = np.random.normal(0, 1, 10)
self.get_print = get_print
if self.get_print:
print("get_print =", self.get_print)
def print_mean(self):
print("Printing mean:")
mean_ = np.mean(self.data)
if self.get_print:
print(mean_)
#click.command()
#click.option('--get_print', default=True)
def cli(get_print):
cc = CustomClass(get_print)
cc.print_mean()
if __name__ == '__main__':
cli()
...and you probably want get_print to be a flag with default False:
#click.command()
#click.option('--get_print', default=False, is_flag=True, required=False)
def cli(get_print):
cc = CustomClass(get_print)
cc.print_mean()

Related

call class method but only generator being returned

I am trying to debug a method in a class. So in the iterative console I have imported my class using the line below.
from email_reader import MyClass
I then thought I just had to set an instance of my class like below.
ma_cls = MyClass('MyFolder')
Then I could call the function get_email like below,
ma_cls.get_email(filename, date_from, date_to)
When I run it the breakpoints never get hit and all that is returned is below.
Out[353]:
What am I doing wrong?
class MyClass:
def __init__(self,
outlook_folder: str):
self.__outlook_folder = outlook_folder
def get_email(self,
csv_filename: str,
emails_since: dt.datetime,
emails_to: dt.datetime = None,
unread_only: bool = False
):
breakpoint()
# some logic
if __name__ == "__main__":
breakpoint()
sse = MyClass("MyFolder")
for wt in sse.get_email(
'some_file_name.CSV',
emails_since=dt.datetime(2020, 2, 4),
emails_to=dt.datetime(2020, 2, 5),
unread_only=False):
pass
Code block in
if __name__ == "__main__":
is executed only when the script is run directly (when you directly execute the script that contains your MyClass). If you are importing the above file then everything that is inside the above if-statement is simply ignored.

Mock inner methods Python2

I'm new to mock and really strugling with it. Mostly in documentation and most of SO pages it shows how to get the mock result_value, but I want to check if the values I'm getting from methods are correct, not the result_value's. Here's the example:
#!/usr/bin/env python
class Example:
def one(self):
return 1
def two(self, one):
print(one + 1) # basically any void method, ex: result = one + 1 and check result value if correct
def main(self):
self.two(self.one())
if __name__ == '__main__':
e = Example()
e.main()
Test:
#!/usr/bin/env python
import unittest
import example
from mock import patch
class Example(unittest.TestCase):
def test_one(self):
self.assertEqual(1, et.one())
def test_two(self):
with patch('example.Example.two'):
self.assertEqual(2, et.two(et.one())) # ..the part I'm stuck
# whick ofc throws AssertionError: 2 != <MagicMock name='two()' id='blablabla'>
def test_main(self):
# unknown part..
if __name__ == '__main__':
et = example.Example()
unittest.main()
How to achieve void method check with unittest?
UPDATE:
so the print I figured out with chepner's help:
def test_twoi3(self):
mock_print = MagicMock()
with patch('sys.stdout', mock_print):
print(2)
expected = call.write('2')
self.assertEqual(mock_print.mock_calls[0], expected)
and for main I'm not quite sure if it is a good solution...:
def test_main(self):
with patch ('example.Example.main') as m:
et.main(et.two(1))
m.assert_called_with(et.two(1))
but I want to check not by passing the methods and values, but if main calls other two methods. How to achieve this?
You don't need to mock anything (directly, anyway); you want to capture standard output and verify that it is what you expect.
from contextlib import redirect_stdout
from io import StringIO
def test_two(self):
stdout = StringIO()
with redirect_stdout(stdout):
et.two(et.one())
self.assertEqual(stdout.getvalue(), "2\n")
Or, you can mock the print and check that it is called with the expected arguments.
def test_two(self):
with patch('__builtin__.print') as p:
et.two(et.one())
p.assert_called_with(2)
I have figured out how to test if main methods have been called. Test looks like this:
#!/usr/bin/env python
import unittest
import example
from mock import patch, MagicMock, call
class Example(unittest.TestCase):
def setUp(self):
self.et = example.Example()
def test_one(self):
self.assertEqual(1, self.et.one())
def test_two(self):
mock_print = MagicMock()
with patch('sys.stdout', mock_print):
print(2)
expected = call.write('2')
self.assertEqual(mock_print.mock_calls[0], expected)
def test_main(self):
self.et.two = MagicMock(side_effect=self.et.two)
self.et.one = MagicMock(side_effect=self.et.one)
self.et.main()
self.et.one.assert_called()
self.et.two.assert_called()
self.et.one.__str__ = self.et.one
self.assertEqual(1, int(self.et.one))
if __name__ == '__main__':
unittest.main()
Upon mocking methods that are in main (all of them) and calling main methods one and two have been successfully called. For one you can return value by using __str__

Why does my function throw a TypeError; num() got an unexpected keyword argument 'ip'?

My goal is to create a random int (1-254) but keep getting the unexpected keyword argument error when trying to use click. What am I doing wrong?
import click
from random import randint as r
#click.command()
#click.option("--ip", default="192.168.0.1", help="IP Address")
#click.option('--host', default="www.google.com" , help="Host URL")
def num(self):
x = r(1,254)
click.echo(x)
if __name__ == "__main__":
num()
Your click-decorated function needs to accept the options you've defined as parameters. Also, self is idiomatically the name of the parameter for the object on which instance methods are called but you've defined a free function.
Note my changes to your def line:
import click
from random import randint as r
#click.command()
#click.option("--ip", default="192.168.0.1", help="IP Address")
#click.option('--host', default="www.google.com" , help="Host URL")
def num(ip, host):
x = r(1,254)
click.echo(x)
if __name__ == "__main__":
num()

python mock global function that is used in class

I can't seem to get my head around mocking in Python. I have a global function:
a.py:
def has_permission(args):
ret_val = ...get-true-or-false...
return ret_val
b.py:
class MySerializer(HyperlinkedModelSerializer):
def get_fields():
fields = super().get_fields()
for f in :
if has_permission(...):
ret_val[f.name] = fields[f]
return ret_val
c.py:
class CountrySerializer(MySerializer):
class Meta:
model = Country
Question: Now i want to test c.py, but i want to mock the has_permission function that is defined in a.py, but is called in the get_fields-method of the class MySerializer that is defined in b.py ... How do i do that?
I've tried things like:
#patch('b.MySerializer.has_permission')
and
#patch('b.MySerializer.get_fields.has_permission')
and
#patch('a.has_permission')
But everything i try either just doesn't work and has_permission is still executed, or python complains about that it can't find the attribute 'has_permission'
with the patching done in:
test.py
class TestSerializerFields(TestCase):
#patch(... the above examples....)
def test_my_country_serializer():
s = CountrySerializer()
self..assertTrue(issubclass(my_serializer_fields.MyCharField, type(s.get_fields()['field1'])))
You need to patch the global in the b module:
#patch('b.has_permission')
because that's where your code looks for it.
Also see the Where to patch section of the mock documentation.
You need to patch the method where it exists at the time your test runs. If you try and patch the method where it is defined after the test code has already imported it, then the patch will have no effect. At the point where the #patch(...) executes, the test code under test has already grabbed the global method into its own module.
Here is an example:
app/util/config.py:
# This is the global method we want to mock
def is_search_enabled():
return True
app/service/searcher.py:
# Here is where that global method will be imported
# when this file is first imported
from app.util.config import is_search_enabled
class Searcher:
def __init__(self, api_service):
self._api_service = api_service
def search(self):
if not is_search_enabled():
return None
return self._api_service.perform_request('/search')
test/service/test_searcher.py:
from unittest.mock import patch, Mock
# The next line will cause the imports of `searcher.py` to execute...
from app.service.searcher import Searcher
# At this point, searcher.py has imported is_search_enabled into its module.
# If you later try and patch the method at its definition
# (app.util.config.is_search_enabled), it will have no effect because
# searcher.py won't look there again.
class MockApiService:
pass
class TestSearcher:
# By the time this executes, `is_search_enabled` has already been
# imported into `app.service.searcher`. So that is where we must
# patch it.
#patch('app.service.searcher.is_search_enabled')
def test_no_search_when_disabled(self, mock_is_search_enabled):
mock_is_search_enabled.return_value = False
mock_api_service = MockApiService()
mock_api_service.perform_request = Mock()
searcher = Searcher(mock_api_service)
results = searcher.search()
assert results is None
mock_api_service.perform_request.assert_not_called()
# (For completeness' sake, make sure the code actually works when search is enabled...)
def test_search(self):
mock_api_service = MockApiService()
mock_api_service.perform_request = mock_perform_request = Mock()
searcher = Searcher(mock_api_service)
expected_results = [1, 2, 3]
mock_perform_request.return_value = expected_results
actual_results = searcher.search()
assert actual_results == expected_results
mock_api_service.perform_request.assert_called_once_with('/search')

Why attribute doesn't update in traitsui on user input

I have a simple program that gets an text input from the user, and displays it on an instrument (Keithley). However, the attribute does not seem to change. That is, when I run the Start method, the output is "Wowee", even if I change Display in a pop-up window. Do I have to make it editable? I didn't think so. I am basically following Gael Varoquaux's intro to traits.
COntrolPanel.py:
from traits.api import *
from traitsui.api import *
import Keithley3706A_module
class ControlPanel(HasTraits):
keithley2430settings = Instance(Keithley2430.Keithley2430Settings, ())
keithley3706Asettings = Instance(Keithley3706A_module.Keithley3706ASettings, ())
start = Button("Start Measurements")
clear_3706A_display = Button("Clear K3706A Display")
k3706A_settings = Keithley3706A_module.Keithley3706ASettings()
k3706A = Keithley3706A_module.Keithley3706A()
view = View(Item('start', show_label=False,style='custom' ),
Item('clear_3706A_display', show_label=False,style='custom' ),
Item('keithley2430settings',style='custom'),
Item('keithley3706Asettings',style='simple'))
def _start_fired(self):
print "hello %s" % self.k3706A_settings.display
self.k3706A.message(self.k3706A_settings.display)
def _clear_3706A_display_fired(self):
self.k3706A.clear()
if __name__ == '__main__':
ControlPanel().configure_traits()
Keithley3706A.py:
from traits.api import *
from traitsui.api import *
import visa
import time
class Keithley3706ASettings(HasTraits):
display = String("Wowee")
class Keithley3706A(HasTraits):
def __init__(self):
self.Keithley3706AUSB = visa.instrument("USB0::0x05E6::0x3706::04019447::INSTR")
def message(self,foo):
s="display.settext('%s')" % foo
self.Keithley3706AUSB.write("display.clear()")
self.Keithley3706AUSB.write(s)
def clear(self):
self.Keithley3706AUSB.write("display.clear()")
In the ControlPanel class, you have created two different instances of Keithley3706ASettings, namely keithley3706Asettings and k3706A_settings. If I delete the latter, and replace the use of k3706A_settings with keithley3706Asettings, it works. Here's my version (with references to the 2430 device removed, the k3706A trait declared as an Instance of Keithley3706A, and a few other irrelevant UI changes):
class ControlPanel(HasTraits):
keithley3706Asettings = Instance(Keithley3706A_module.Keithley3706ASettings, ())
k3706A = Instance(Keithley3706A_module.Keithley3706A, ())
start = Button("Start Measurements")
clear_3706A_display = Button("Clear K3706A Display")
view = View(UItem('start'),
UItem('clear_3706A_display'),
Item('keithley3706Asettings', style='simple'))
def _start_fired(self):
print "hello %s" % self.keithley3706Asettings.display
self.k3706A.message(self.keithley3706Asettings.display)
def _clear_3706A_display_fired(self):
self.k3706A.clear()

Categories

Resources