In my Django application I have a module installed via pip. I need to override some method located in site-packages/module/views.py. I assume, I need to import this module in my custom modules directory, and simply inherit class and override method.
What is the best approach? How can I do it correctly without writing code in site-packages directory?
What you are after is often referred to as monkey patching.
import some_module
def my_method(self):
pass
some_module.SomeClass.a_method = my_method
Be careful though depending on the nature of the method and library initialization it may be too late to patch the method. For example if a method that you would like to patch is invoked as the module is loaded you will never be able to patch it before it is called.
Try and patch the class in question as early as possible in your application startup
Related
I'm a bit new to Python's unittest library and I'm currently looking at setting up my Flask server before running any of my integration tests. I know that the unittest.TestCase class allows you to use setUp() before every test cases in the class. I also know that the same class has another method called setUpClass() that runs only once for the entire class.
What I'm actually interested is trying to figure out how to do something similar like setUpClass(), but done on an entire unittest.TestSuite. However, I'm having no luck at it.
Sure, I could set up the server for every TestCase, but I would like to avoid doing this.
There is an answer on a separate question that suggests that by overriding unittest.TestResult's startTestRun(), you could have a set up function that covers the entire test suite. However, I've tried to passed in the custom TestResult object into unittest. TextTestRunner with no success.
So, how exactly can I do a set up for an entire test suite?
This is not well documented, but I recently needed to do this as well.
The docs mention that TestResult.startTestRun is "Called once before any tests are executed."
As you can see, in the implementation, the method doesn't do anything.
I tried subclassing TestResult and all kinds of things. I couldn't make any of that work, so I ended up monkey patching the class.
In the __init__.py of my test package, I did the following:
import unittest
OLD_TEST_RUN = unittest.result.TestResult.startTestRun
def startTestRun(self):
# whatever custom code you want to run exactly once before
# any of your tests runs goes here:
...
# just in case future versions do something in this method
# we'll call the existing method
OLD_TEST_RUN(self)
unittest.result.TestResult.startTestRun = startTestRun
There is also a stopTestRun method if you need to run cleanup code after all tests have run.
Note that this does not make a separate version of TestResult. The existing one is used by the unittest module as usual. The only thing we've done is surgically graft on our custom implementation of startTestRun
class A():
def __init__(self):
install_package('abc')
import abc
def sq(self):
print(abc.sqrt(5))
Background
I am writing helper classes (all stored in a helper.py) for my clients who use python to run a application(which I send them). These helper classes help the application function. To allow for quicker deployment on client side, I wrote a function called install_package that implicitly calls pip install.
All clients receive the same helper.py file but a different application. The application I send them usually use a subset of classes from helper.py.
Motive
So the reason I use the above class structure is now pretty obvious, I do not want to load all the libraries in the start of the helper.py as the libraries will have a corresponding install_package() with them. So for a client who's application may not use all the classes, there is no need to install all the unnecessary libraries
Issue
Now the issue is that using the above structure to A() seems like a feasible option but the package that I import in the __init__ function does not get globally imported and hence sq() cannot use functions in the abc library. What's the best way to fix this? One way would be to store the library in a variable local to the class. How would I go about doing it? Suggestions to change the class structure also welcome!
What about something like this:
import importlib
class A():
def __init__(self):
install_package('abc')
self.abc = importlib.import_module('abc')
def sq(self):
print(self.abc.sqrt(5))
So, the main question is on the title. I'm trying to find out if it is correct to say that python mock module uses dependency injection pattern for mocking object calls.
I'm not familiar with DI pattern but from what I've read and what I saw with debugger in mock module underhood look like mock() uses DI.
Am I right and mock() is DI or I'm missing something about this pattern and mocking?
The mock module does not use dependency injection.
mock replaces some objects with customized ones.
For dependency injection to be used, there would have to be some top level process, which would search for functions to be called, detected arguments to pass to them, instantiate them and finally made the call.
mock only modifies the object and the call to this objects is done as usual - direct call to that object.
If you want to find example of dependency injection, check pytest and it's fixtures - they use it a lot and it is fun to use that.
I suppose you are primarily concerned with mocking out an object's attributes with unittest.mock.patch.
patch is a function which does little more than return an instance of the class unittest.mock._patch. _patch is a context manager, which monkeypatches an attribute upon __enter__ and unpatches it upon __exit__.
I have a python Presenter class that has a method which creates an instance of a different Presenter class:
class MainPresenter(object):
def showPartNumberSelectionDialog(self, pn):
view = self.view.getPartNumberSelectionDialog(pn)
dialog = SecondPresenter(self.model, view)
dialog.show()
my intent was to write a separate Presenter class for each window in my application, in order to keep things orderly. Unfortunately, I find it difficult to test the showPartNuberSelectionDialog method, particularly to test that dialog.show() was called, because the instance is created within the method call. So, even if I patch SecondPresenter using python's mock framework, it still doesn't catch the call to the local dialog instance.
So, I have a two questions:
How can I change my approach in order to make this code more testable?
Is it considered good practice to test simple code blocks such as this?
Is it possible to patch SecondPresenter and check both how you call it and if your code call show() too.
By use mock framework and patch you should replace SecondPresenter class instance by a Mock object. Take care the dialog instance will be the return value of the mock used to replace the original class instance. Moreover you should take care of where to patch, now I can just guess how to do it but it will not far from the final test version:
#patch("mainpresentermodule.SecondPresenter", autospec=True)
def test_part_number_selection_dialog(self, mock_second_presenter_class):
main = MainPresenter()
main.showPartNumberSelectionDialog(123456)
dialog = mock_second_presenter_class.return_value
dialog.show.assert_called_with()
I used autospec=True just because I consider it a best practice, take a look to Autospeccing for more details.
You can also patch main.view and main.model to test how your code call dialog's constructor... but you should use mock and not abuse of it, more things you mock and patch and more your tests will be tangled to the code.
For the second question I think it is a good practice test these kind of block also, but try to patch and mock too far as possible and just what you can not use in testing environment: you will have a more flexible tests and you'll can refactor your code by rewriting less test code.
I need to perform some fairly simple tasks after my Django environment has been "fully loaded".
More specifically I need to do things like Signal.disconnect() some Django Signals that are setup by my third party library by default and connect my own Signals and I need to do some "monkey patching" to add convenience functions to some Django models from another library.
I've been doing this stuff in my Django app's __init__.py file, which seems to work fine for the monkey patching, but doesn't work for my Signal disconnecting. The problem appears to be one of timing--for whatever reason the Third Party Library always seems to call its Signal.connect() after I try to Signal.disconnect() it.
So two questions:
Do I have any guarantee based on the order of my INSTALLED_APPS the order of when my app's __init__.py module is loaded?
Is there a proper place to put logic that needs to run after Django apps have been fully loaded into memory?
In Django 1.7 Apps can implement the ready() method: https://docs.djangoproject.com/en/dev/ref/applications/#django.apps.AppConfig.ready
My question is a more poorly phrased duplicate of this question: Where To Put Django Startup Code. The answer comes from that question:
Write middleware that does this in init and afterwards raise django.core.exceptions.MiddlewareNotUsed from the init, django will remove it for all requests...
See the Django documentation on writing your own middleware.
I had to do the following monkey patching. I use django 1.5 from github branch. I don't know if that's the proper way to do it, but it works for me.
I couldn't use middleware, because i also wanted the manage.py scripts to be affected.
anyway, here's this rather simple patch:
import django
from django.db.models.loading import AppCache
django_apps_loaded = django.dispatch.Signal()
def populate_with_signal(cls):
ret = cls._populate_orig()
if cls.app_cache_ready():
if not hasattr(cls, '__signal_sent'):
cls.__signal_sent = True
django_apps_loaded.send(sender=None)
return ret
if not hasattr(AppCache, '_populate_orig'):
AppCache._populate_orig = AppCache._populate
AppCache._populate = populate_with_signal
and then you could use this signal like any other:
def django_apps_loaded_receiver(sender, *args, **kwargs):
# put your code here.
django_apps_loaded.connect(django_apps_loaded_receiver)
As far as I know there's no such thing as "fully loaded". Plenty of Django functions include import something right in the function. Those imports will only happen if you actually invoke that function. The only way to do what you want would be to explicitly import the things you want to patch (which you should be able to do anywhere) and then patch them. Thereafter any other imports will re-use them.