Share values between objects in the same Python module [closed] - python

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Closed 9 years ago.
Improve this question
File engine.py:
class Engine(object):
def __init__(self, variable):
self.variable = variable
class Event(object):
def process(self):
variable = '123' # this should be the value of engine.variable
Python
>>> from engine import Engine, Event
>>> engine = Engine('123')
>>> e = Event()
>>> e.process()
What's the best way to accomplish this? Because of limitations with the Event class (it's actually a subclass of a third-party library that I'm splicing new functionality into) I can't do something like e = Event(engine).
In depth explanation:
Why am I not using e = Event(engine)?
Because Event is actually a subclass of a third-party library. Additionally, process() is an internal method. So the class actually looks like this:
class Event(third_party_library_Event):
def __init__(*args, **kwargs):
super(Event, self).__init__(*args, **kwargs)
def _process(*args, **kwargs):
variable = engine.variable
# more of my functionality here
super(Event, self)._process(*args, **kwargs)
My new module also has to run seamlessly with existing code that uses the Event class already. So I can't add pass the engine object to each _process() call or to the init method either.

functools.partial might help:
#UNTESTED
class Engine(object):
def __init__(self, variable):
self.variable = variable
class Event(object):
def __init__(self, engine):
super().__init__()
self.engine = engine
def process(self):
print self.engine.variable
engine = Engine('123')
Event = functools.partial(Event, engine)
ThirdPartyApiThatNeedsAnEventClass(Event)
Now, when the 3rd-party library creates an Event, it is automatically passed engine.

"Because of limitations with the Event class (it's actually a subclass
of a third-party library that I'm splicing new functionality into) I
can't do something like e = Event(engine)."
It appears that you're concerned that Event is inheriting some other class and you are therefore unable to alter the constructor method for the class.
Your question is similar to this other one. Fortunately, the super().__init__() method does this for you.
Consider the following example:
>>> class C(object):
def __init__(self):
self.b = 1
>>> class D(C):
def __init__(self):
super().__init__()
self.a = 1
>>> d = D()
>>> d.a
1
>>> d.b # This works because of the call to super's init
1

Why not pass the variable in to the process function? You said the class's constructor can't be changed, but it seems like you are defining process. Just make it:
def process(self, engine):
variable = engine.variable
<do stuff>
or
def process(self, variable):
<do stuff>

Related

How should I properly log my class container?

I have the following situation:
class A():
def __init__(self, log = True):
self.log = log
def __call__(self):
if self.log:
self.log ='\n' # whatever no-Null string to reinitialize the log attribute at each call
do_things()
self.log += 'I did things'
class B()
def __init__(self):
self.a = A(log = True)
self.log_master = []
def __call__(self):
for i in range(num):
self.a()
self.log_master.append(a.log)
self.log_master.append('other things')
save_to_file(self.log_master)
So I have a class B which is initialized with an instance of class A. B calls A. When the class A is called it initializes a string which serve as a container to log the operations. When call ends, B checks A's log string and append it to log_master, besides other things. At the end of everything log_master is saved to file. Basically I have two classes, one of which serve as a container for an instance of the other. Both 'collaborate' at writing a log file.
I can feel the horror with this approach. My A code is cluttered with ugly "if self.log: ..". What is the right approach to produce a decent and customizable logfile?

How to verify when an unknown object created by the code under test was called as expected (pytest) (unittest)

I have some code that creates instances from a list of classes that is passed to it. This cannot change as the list of classes passed to it has been designed to be dynamic and chosen at runtime through configuration files). Initialising those classes must be done by the code under test as it depends on factors only the code under test knows how to control (i.e. it will set specific initialisation args). I've tested the code quite extensively through running it and manually trawling through reams of output. Obviously I'm at the point where I need to add some proper unittests as I've proven my concept to myself. The following example demonstrates what I am trying to test:
I would like to test the run method of the Foo class defined below:
# foo.py
class Foo:
def __init__(self, stuff):
self._stuff = stuff
def run():
for thing in self._stuff:
stuff = stuff()
stuff.run()
Where one (or more) files would contain the class definitions for stuff to run, for example:
# classes.py
class Abc:
def run(self):
print("Abc.run()", self)
class Ced:
def run(self):
print("Ced.run()", self)
class Def:
def run(self):
print("Def.run()", self)
And finally, an example of how it would tie together:
>>> from foo import Foo
>>> from classes import Abc, Ced, Def
>>> f = Foo([Abc, Ced, Def])
>>> f.run()
Abc.run() <__main__.Abc object at 0x7f7469f9f9a0>
Ced.run() <__main__.Abc object at 0x7f7469f9f9a1>
Def.run() <__main__.Abc object at 0x7f7469f9f9a2>
Where the list of stuff to run defines the object classes (NOT instances), as the instances only have a short lifespan; they're created by Foo.run() and die when (or rather, sometime soon after) the function completes. However, I'm finding it very tricky to come up with a clear method to test this code.
I want to prove that the run method of each of the classes in the list of stuff to run was called. However, from the test, I do not have visibility on the Abc instance which the run method creates, therefore, how can it be verified? I can't patch the import as the code under test does not explicitly import the class (after all, it doesn't care what class it is). For example:
# test.py
from foo import Foo
class FakeStuff:
def run(self):
self.run_called = True
def test_foo_runs_all_stuff():
under_test = Foo([FakeStuff])
under_test.run()
# How to verify that FakeStuff.run() was called?
assert <SOMETHING>.run_called, "FakeStuff.run() was not called"
It seems that you correctly realise that you can pass anything into Foo(), so you should be able to log something in FakeStuff.run():
class Foo:
def __init__(self, stuff):
self._stuff = stuff
def run(self):
for thing in self._stuff:
stuff = thing()
stuff.run()
class FakeStuff:
run_called = 0
def run(self):
FakeStuff.run_called += 1
def test_foo_runs_all_stuff():
under_test = Foo([FakeStuff, FakeStuff])
under_test.run()
# How to verify that FakeStuff.run() was called?
assert FakeStuff.run_called == 2, "FakeStuff.run() was not called"
Note that I have modified your original Foo to what I think you meant. Please correct me if I'm wrong.

How to pass outer function class to inner class? [duplicate]

This question already has an answer here:
How to access outer attribute class within inner class?
(1 answer)
Closed 3 years ago.
As a title, I have a versatility function in parent class that will share use in child class A.k.A inner class. In below, I need to pass outer_send function from parent class. then, use it with call inner_send function inside Identify class alias child class. The result will output Test.
class Device:
def __init__(self):
self.identify = self.Identify(self.outer_send())
def outer_send(message):
print(message)
def last_error(self):
return self.identify.error_info
class Identify:
def __init__(self, send):
self.inner_send() = send()
def set_error(self, error):
self.error_info = error
device = Device()
device.identify.inner_send('test')
I don't like the pattern and I would recommend designing it differently. However, this does what I think you want to do:
class Device:
def __init__(self):
self.identify = self.Identify(self._send)
def _send(self, message):
print(message)
class Identify:
def __init__(self, _send):
self.send = _send
device = Device()
device.identify.send('test')
A few notes: I renamed outer_send to _send, as I assume you don't want people calling that directly on the Device object - if you do, just rename it send and it still works; the error bit seemed superfluous, so left it out; your outer_send was missing self as a parameter - it doesn't need it, but if you do want to leave it out, annotate the method with #staticmethod to avoid warnings.

How to mock class instance in unit test of this class instance method

Im trying to unittest some_function which is MyClass instance method that requires someapi.api instance . How do I patch self.api.something1.something2(foo) with some return value?
import someapi
class MyClass(object):
def __init__(self,a,b):
self.a = a
self.b = b
self.api = someapi.api(self.a, self.b)
def some_function(self, foo):
result = self.api.something1.something2(foo)
new_result = dosomething(result)
return new_result
So really what I want is to mock response of this api so I can test that dosomething(result) does what I want.
#mock.patch('self.api.something1.something2', side_effect='something')
def testGet_circuits(self,pymock):
result = some_function('foobar')
expected_result= 'something'
self.assertEqual(result, 'expected_result')
I tried
#mock.patch('someapi.api')
def testSome_function(self,someapi_mock):
api = MyClass('a','b')
result = api.some_function('foo')
self.assertEqual(result,'newfoo')
What I'm strugling with is how to mock self.api.something1.something2(foo) inside some_function :(
You are not setting up your mock properly. I crafted an example using your code and managed to put together a test method that works. Ultimately, what is happening here is that you are not telling your mocks how to behave when the code runs. You start off probably mocking in the right place, but beyond that, the mock itself no longer has any of the attributes you are trying to access in order to allow the code to run. I'll go through the code to help illustrate:
class TestStuff(unittest.TestCase):
#mock.patch('real_code.someapi.api', autospec=True)
def testSome_function(self, someapi_mock):
someapi_mock.return_value.something1 = mock.Mock(spec=Something)
someapi_mock.return_value.something1.something2.return_value = 'newfoo'
api = MyClass('a', 'b')
result = api.some_function('foo')
self.assertEqual(result, 'newfoo')
First thing, notice that I'm mocking more with respect to where I am testing, which is important to keep in mind, and you should read about here.
For the mock configuration issue, I can only assume from your real code, api.something1.something2 indicates that something1 is holding the instance of some other class that gives you access to the something2 method. So, the example is being illustrated with that assumption.
Now, as you can see within the first line of the method, what I'm doing is telling my mock to ensure it has the something1 attribute. It is important to remember that when you are mocking, and even when you set the spec and/or autospec (as I have used in my example), you don't get access to the attributes created in your __init__. So you need to provide them in your mock per my example.
The second line now goes the next step to mock out the something2 method behaviour you are trying to get a result from. With this done, when your real code is called, it should go through the expected behaviour you set up and return the expected newfoo value.
To further help, here is the exact code I used to help put together that functional test:
real_code.py
import someapi
class MyClass(object):
def __init__(self,a,b):
self.a = a
self.b = b
self.api = someapi.api(self.a, self.b)
def some_function(self, foo):
result = self.api.something1.something2(foo)
new_result = dosomething(result)
return new_result
def dosomething(foo):
return foo
someapi.py
class api:
def __init__(self, a, b):
self.a = a
self.b = b
self.something1 = Something()
class Something:
def something2(self, some_arg):
return some_arg
Thanks for all the answers definitely helped me
I ended up doing below and worked like a charm . This whole mock thing looks like rabbit hole and i need to go deeper to fully understand.
#mock.patch('someapi.api')
def testSome_function(self,someapi_mock):
someapi_mock = return_value.something1.something2.return_value = 'mocked_value'
api = MyClass('a','b')
result = api.some_function('foo')
self.assertEqual(result,'newfoo')

Patching built-in method or class

I would like to find all instances in the code where np.random.seed is called (without using grep). In order to set a breakpoint in ipdb, I tried to find the source file with
import inspect; inspect.getsourcefile(np.random.seed)
but it throws a TypeError because it is a built-in method (because it is coded in C).
Is it possible to watch any calls to np.random.seed by modifying something in the main source file?
Additionally, it would be suitable to patch this method, e.g. additionally logging it (or calling a debugger):
def new_random_seed(seed):
"""
This method should be called instead whenever np.random.seed
is called in any module that is invoked during the execution of
the main script
"""
print("Called with seed {}".format(seed))
#or: import ipdb; ipdb.set_trace()
return np.random.seed()
Maybe using a mock framework is the way to go?
The second question concerns the scenario in which a class B inherits from a class A in a library and I want to use the functionality of class B, but overwrite a function it uses from class A without modifying classes A and B. Probably, I should use mocking, but I am not sure about the overhead, so I wrote the following:
#in library
class A():
def __init__(self, name):
self.name = name
def work(self):
print("{} working".format(self.name))
class B():
def __init__(self):
self.A = A("Machine")
def run_task(self):
self.A.work()
# in main script
# Cannot change classes A and B, so make a subclass C
import types
class C(B):
def __init__(self, modified_work):
super().__init__()
self.A.work = types.MethodType(modified_work, self.A) #MethodType for self
b = B()
b.run_task()
modified_work = lambda self: print("{} working faster".format(self.name))
c = C(modified_work)
c.run_task()
The output is:
Machine working
Machine working faster
Is this good style?
This might be a simpler solution to your second question:
# lib.py
class A():
def work(self):
print('working')
class B():
def __init__(self):
self.a = A()
def run(self):
self.a.work()
Then in your code:
import lib
class A(lib.A):
def work(self):
print('hardly working')
lib.A = A
b = lib.B()
b.run()
Or:
import lib
class AA(lib.A):
def work(self):
print('hardly working')
class BB(lib.B):
def __init__(self):
self.a = AA()
b = lib.B()
b.run()
b = BB()
b.run()

Categories

Resources