I would like to create a mock.Mock() object, then add a method called session that acts like an instance method, which is passed a self reference to the mock object, allowing the method to add state to the mock object. Is this possible (without manually using types.MethodType, e.g., using mock's built-in API), or should I just find a way around it?
Note, I found this question, which is for Ruby and seems to cover something similar, if not the same thing. Unfortunately, I don't know Ruby very well at all.
mock_answer = Mock()
def session():
mock_answer.b = 1
mock_answer.session = session
mock_answer.session()
print(mock_answer.b) # 1
You don't need self actually.
If you want to enhance the capabilities of the mock.Mock class, just subclass Mock and add your own methods.
class MyMock(Mock):
def session(self):
# Save session data here?
The mock documentation explains that when a new mock is to be created, it will be the same type as the parent. This means that the session function will also be available on any other mocks which are created during mocking.
This doesn't cover the case where you need to dynamically attach a session function to an existing mock object.
Related
I have a class
class A:
def sample_method():
I would like to decorate class A sample_method() and override the contents of sample_method()
class DecoratedA(A):
def sample_method():
The setup above resembles inheritance, but I need to keep the preexisting instance of class A when the decorated function is used.
a # preexisting instance of class A
decorated_a = DecoratedA(a)
decorated_a.functionInClassA() #functions in Class A called as usual with preexisting instance
decorated_a.sample_method() #should call the overwritten sample_method() defined in DecoratedA
What is the proper way to go about this?
There isn't a straightforward way to do what you're asking. Generally, after an instance has been created, it's too late to mess with the methods its class defines.
There are two options you have, as far as I see it. Either you create a wrapper or proxy object for your pre-existing instance, or you modify the instance to change its behavior.
A proxy defers most behavior to the object itself, while only adding (or overriding) some limited behavior of its own:
class Proxy:
def __init__(self, obj):
self.obj = obj
def overridden_method(self): # add your own limited behavior for a few things
do_stuff()
def __getattr__(self, name): # and hand everything else off to the other object
return getattr(self.obj, name)
__getattr__ isn't perfect here, it can only work for regular methods, not special __dunder__ methods that are often looked up directly in the class itself. If you want your proxy to match all possible behavior, you probably need to add things like __add__ and __getitem__, but that might not be necessary in your specific situation (it depends on what A does).
As for changing the behavior of the existing object, one approach is to write your subclass, and then change the existing object's class to be the subclass. This is a little sketchy, since you won't have ever initialized the object as the new class, but it might work if you're only modifying method behavior.
class ModifiedA(A):
def overridden_method(self): # do the override in a normal subclass
do_stuff()
def modify_obj(obj): # then change an existing object's type in place!
obj.__class__ = ModifiedA # this is not terribly safe, but it can work
You could also consider adding an instance variable that would shadow the method you want to override, rather than modifying __class__. Writing the function could be a little tricky, since it won't get bound to the object automatically when called (that only happens for functions that are attributes of a class, not attributes of an instance), but you could probably do the binding yourself (with partial or lambda if you need to access self.
First, why not just define it from the beginning, how you want it, instead of decorating it?
Second, why not decorate the method itself?
To answer the question:
You can reassign it
class A:
def sample_method(): ...
pass
A.sample_method = DecoratedA.sample_method;
but that affects every instance.
Another solution is to reassign the method for just one object.
import functools;
a.sample_method = functools.partial(DecoratedA.sample_method, a);
Another solution is to (temporarily) change the type of an existing object.
a = A();
a.__class__ = DecoratedA;
a.sample_method();
a.__class__ = A;
I use an external pacakge which I bring in via pip.
This package has a structure as follows:
class OuterThing:
field: Innerthing
def outer_method1(self...
class InnerThing():
def inner_method1(self,...
def inner_method2(self,...
def inner_method3(self,...
I instantiate only OuterThing objects (which then internally instantiate InnerThing objects).
I want the inner thing objects to have all the normal fields and methods, just inner_method1 I need to customise a bit for my use.
What is the shortest way (i.e. the way with the least code) to do this?
I do not want to copy the whole package into my source tree if possible, just "inject" the changes at runtime (but possibly before all instantiations) to the specified method in InnerThing.
In Python, a method is just an attribute of the class object that happens to be a function having self as its first parameter. That means that you can easily replace it by your own function, provided you keep the same signature. You can even call the original method from your own one:
# after having imported InnerThing
_orig_inner_method1 = InnerThing.inner_method1
def _patched_inner_method1(self, ...):
# your own code
...
_orig_inner_method1(self, ...) # eventually call the original method
...
InnerThing.inner_method1 = _patched_inner_method1
From that point, any InnerThing object created will use your patched method.
Python allows you to Monkey Patch code simply by assigning a different function pointer to the function you're trying to replace. This can be done as long as you can grab a reference to the instance of InnerThing at runtime.
In your case, it seems like OuterThing does have a reference to InnerThing so you can do something like this:
def your_implementation_of_inner_method1(self, ...):
# Do stuff
outerThing = OuterThing()
outerThing.field.inner_method1 = your_implementation_of_inner_method1
If you want to dig deeper as to why this is possible, I recommend having a look at the Python documentation for classes. The tl;dr is that methods are actually objects and are stored as fields in instances of the class.
I want to write a mock for a library object without inheriting from it in order to properly test, however without having to stub all non used functions of the original object.
To be specific I want to write a ContextMock for the invoke library.
class ContextMock:
...
The main problem here is that I therefor call a #task function which then calls my code that I want to test. However the #task decorator checks whether the context object is an instance of a Context, like this:
def __call__(self, *args, **kwargs):
# Guard against calling tasks with no context.
if not isinstance(args[0], Context):
err = "Task expected a Context as its first arg, got {} instead!"
# TODO: raise a custom subclass _of_ TypeError instead
raise TypeError(err.format(type(args[0])))
Therefor my question is, can I somehow change the isinstance function of my ContextMock, or make it look like its an instance of Context without inheriting its attributes?
Or would it be possible to somehow mock the isinstance function?
How does the default implementation of instancecheck work? Is there perhabs a baseclass attribute that can be overwritten?
I already tried to provide a custom metaclass with an custom instancecheck function, which of course does not work as the instancecheck of the Context is called, right?
Also Note that I'm well aware that any hacky solution should not belong in production code, and is only used for testing.
Edit:
To add a generic example of what I want to archive:
class Context:
pass
class ContextMock:
pass
mock = ContextMock
... do magic with mock
assert isinstance(mock, Context)
I am struggling to understand when it makes sense to use an instance method versus a static method. Also, I don't know if my functions are static since there is not a #staticmethod decorator. Would I be able to access the class functions when I make a call to one of the methods?
I am working on a webscraper that sends information to a database. It’s setup to run once a week. The structure of my code looks like this
import libraries...
class Get:
def build_url(url_paramater1, url_parameter2, request_date):
return url_with_parameters
def web_data(request_date, url_parameter1, url_parameter2): #no use of self
# using parameters pull the variables to look up in the database
for a in db_info:
url = build_url(a, url_parameter2, request_date)
x = requests.Session().get(url, proxies).json()
#save data to the database
return None
#same type of function for pulling the web data from the database and parsing it
if __name__ == ‘__main__’:
Get.web_data(request_date, url_parameter1, url_parameter2)
Parse.web_data(get_date, parameter) #to illustrate the second part of the scrapper
That is the basic structure. The code is functional but I don’t know if I am using the methods (functions?) correctly and potentially missing out on ways to use my code in the future. I may even be writing bad code that will cause errors down the line that are impossibly hard to debug only because I didn’t follow best practices.
After reading about when class and instance methods are used. I cannot see why I would use them. If I want the url built or the data pulled from the website I call the build_url or get_web_data function. I don’t need an instance of the function to keep track of anything separate. I cannot imagine when I would need to keep something separate either which I think is part of the problem.
The reason I think my question is different than the previous questions is: the conceptual examples to explain the differences don't seem to help me when I am sitting down and writing code. I have not run into real world problems that are solved with the different methods that show when I should even use an instance method, yet instance methods seem to be mandatory when looking at conceptual examples of code.
Thank you!
Classes can be used to represent objects, and also to group functions under a common namespace.
When a class represents an object, like a cat, anything that this object 'can do', logically, should be an instance method, such as meowing.
But when you have a group of static functions that are all related to each other or are usually used together to achieve a common goal, like build_url and web_data, you can make your code clearer and more organized by putting them under a static class, which provides a common namespace, like you did.
Therefore in my opinion the structure you chose is legitimate. It is worth considering though, that you'd find static classes more in more definitively OOP languages, like Java, while in python it is more common to use modules for namespace separation.
This code doesn't need to be a class at all. It should just be a pair of functions. You can't see why you would need an instance method because you don't have a reason to instantiate the object in the first place.
The functions you have wrote in your code are instance methods but they were written incorrectly.
An instance method must have self as first parameter
i.e def build_url(self, url_paramater1, url_parameter2, request_date):
Then you call it like that
get_inst = Get()
get_inst.build_url(url_paramater1, url_parameter2, request_date)
This self parameter is provided by python and it allow you to access all properties and functions - static or not - of your Get class.
If you don't need to access other functions or properties in your class then you add #staticmethod decorator and remove self parameter
#staticmethod
def build_url(url_paramater1, url_parameter2, request_date):
And then you can call it directly
Get.build_url(url_paramater1, url_parameter2, request_date)
or call from from class instance
get_inst = Get()
get_inst.build_url(url_paramater1, url_parameter2, request_date)
But what is the problem with your current code you might ask?
Try calling it from an instance like this and u will see the problem
get_inst = Get()
get_inst.build_url(url_paramater1, url_parameter2, request_date)
Example where creating an instance is useful:
Let's say you want to make a chat client.
You could write code like this
class Chat:
def send(server_url, message):
connection = connect(server_url)
connection.write(message)
connection.close()
def read(server_url):
connection = connect(server_url)
message = connection.read()
connection.close()
return message
But a much cleaner and better way to do it:
class Chat:
def __init__(server_url):
# Initialize connection only once when instance is created
self.connection = connect(server_url)
def __del__()
# Close connection only once when instance is deleted
self.connection.close()
def send(self, message):
self.connection.write(message)
def read(self):
return self.connection.read()
To use that last class you do
# Create new instance and pass server_url as argument
chat = Chat("http://example.com/chat")
chat.send("Hello")
chat.read()
# deleting chat causes __del__ function to be called and connection be closed
delete chat
From given example, there is no need to have Get class after all, since you are using it just like a additional namespace. You do not have any 'state' that you want to preserve, in either class or class instance.
What seems like a good thing is to have separate module and define these functions in it. This way, when importing this module, you get to have this namespace that you want.
I have to serialise a dynamically created class hierarchy. And a bunch of objects - instances of the latter classes.
Python pickle is not of big help, its wiki says "Classes ... cannot be pickled". O there may be some trick that I cannot figure.
Performance requirement:
Deserialization should be pretty fast, because the serialised staff serves for cache and should save me the work of creating the same class hierarchy.
Details:
classes are created dynamically using type and sometimes meta-classes.
If you provide a custom object.__reduce__() method I believe you can still use pickling.
Normally, when pickling, the class import path is stored, plus instance state. On unpickling, the class is imported, and a new instance is created using the stored state. This is why pickling cannot work with dynamic classes, there is nothing to import.
The object.__reduce__() method lets you store a different instance factory. The callable returned by this function is stored (again by import path), and called with specified arguments to produce an instance. This instance is then used to apply state to, in the same way a regular instance would be unpickled:
def class_factory(name):
return globals()[name]()
class SomeDynamicClass(object):
def __reduce__(self):
return (class_factory, (type(self).__name__,), self.__dict__)
Here __reduce__ returns a function, the arguments for the function, and the instance state.
All you need to do then, is provide the right arguments to the factory function to recreate the class, and return an instance of that class. It'll be used instead of importing the class directly.
Classes are normal python objects, so, in theory, should be picklable, if you provide __reduce__ (or implement other pickle protocol methods) for them. Try to define __reduce__ on their metaclass.