Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Monkey patching Django app in another app

We have a third party lib that we use in our Django 1.9 app. We would like to amend that application with some functionality not in the original app (targeting MongoDB). We currently do this via our own fork of the original lib, but would like to make the changes a bit more orthogonal, so that they might be pulled upstream eventually.

We've tried patching during the app config ready() but model imports are handled before this call in django.apps.registry.populate(), and performing it in the \__init__ suffers from apps_ready == False. What is the best part of the lifecycle to perform this?

class MongoConfig(AppConfig):
    def __init__(self, app_name, app_module):
        super(MongoConfig, self).__init__(app_name, app_module)

        for p in patches:
            patch(*p)

def patch(old, new):
    old_module, old_item = split_mod(old)
    new_module, new_item = split_mod(new)

    print('patching {0} with {1}'.format(old, new))

    old_module = import_module(old_module)
    new_module = import_module(new_module)
    setattr(old_module, old_item, getattr(new_module, new_item))
like image 499
mwjackson Avatar asked May 06 '16 13:05

mwjackson


People also ask

What is monkey patching in Django?

Monkey patching is a technique to modify module functions or class methods in Python and other dynamic languages run-time. It differs from the traditional source code patching that it does not need separate utility or compilation process to become effective.

What is monkey patching in Python explain with suitable example?

Monkey patching can only be done in dynamic languages, of which python is a good example. Changing a method at runtime instead of updating the object definition is one example;similarly, adding attributes (whether methods or variables) at runtime is considered monkey patching.

What is monkey patching in Javascript?

Monkey patching is more a way for debugging, experiencing, patching, or hacking existing code than rather a long-term solution for a code base, even if it could be used as a natural solution in a few specific cases.


2 Answers

I am really not for monkey patching (except during test cases, even then I believe mock is better).

Why don't you try the simpler option? Create a proxy of the app within your project (it will be called first, due to Python's lookup system) and then simply patch the methods you want, and bypass the ones you don't to the original app.

So if the component is called "FooProject" you would create another app called "FooProject" in your project, in this app's __init__.py:

from originalproject import FooProject as OriginalFoo

class FooProject(OriginalFoo):
    def override_method_here(self, foo):
       return my_own_magic(foo)
like image 56
Burhan Khalid Avatar answered Oct 28 '22 04:10

Burhan Khalid


I ended up doing this in the wsgi portion of initialization

In wsgi.py

# Monkey Patch a few things
from huey_monitor.apps import HueyMonitorConfig
HueyMonitorConfig.verbose_name = 'Task Monitor'
like image 43
Kevin Parker Avatar answered Oct 28 '22 02:10

Kevin Parker