Files
edx-platform/common/djangoapps/monkey_patch/__init__.py
Usman Khalid 6cb62f2697 Rebase upgrade Django to v1.8.5
Please note that this is a squshed commit and the work of:
Symbolist, macdiesel, nedbat, doctoryes, muzaffaryousaf and muhammad-ammar
2015-11-10 15:00:19 -05:00

81 lines
2.7 KiB
Python

"""
Monkey-patch the edX platform
Here be dragons (and simians!)
* USE WITH CAUTION *
No, but seriously, you probably never really want to make changes here.
This module contains methods to monkey-patch [0] the edx-platform.
Patches are to be applied as early as possible in the callstack
(currently lms/startup.py and cms/startup.py). Consequently, changes
made here will affect the entire platform.
That said, if you've decided you really need to monkey-patch the
platform (and you've convinced enough people that this is best
solution), kindly follow these guidelines:
- Reference django_18_upgrade.py for a sample implementation.
- Name your module by replacing periods with underscores for the
module to be patched:
- patching 'django.utils.translation'
becomes 'django_utils_translation'
- patching 'your.module'
becomes 'your_module'
- Implement argumentless function wrappers in
monkey_patch.your_module for the following:
- is_patched
- patch
- unpatch
- Add the following code where needed (typically cms/startup.py and
lms/startup.py):
```
from monkey_patch import your_module
your_module.patch()
```
- Write tests! All code should be tested anyway, but with code that
patches the platform runtime, we must be extra sure there are no
unintended consequences.
[0] http://en.wikipedia.org/wiki/Monkey_patch
"""
# Use this key to store a reference to the unpatched copy
__BACKUP_ATTRIBUTE_NAME = '__monkey_patch'
def is_patched(module, attribute_name):
"""
Check if an attribute has been monkey-patched
"""
attribute = getattr(module, attribute_name)
return hasattr(attribute, __BACKUP_ATTRIBUTE_NAME)
def patch(module, attribute_name, attribute_replacement):
"""
Monkey-patch an attribute
A backup of the original attribute is preserved in the patched
attribute (see: __BACKUP_ATTRIBUTE_NAME).
"""
attribute = getattr(module, attribute_name)
setattr(attribute_replacement, __BACKUP_ATTRIBUTE_NAME, attribute)
setattr(module, attribute_name, attribute_replacement)
return is_patched(module, attribute_name)
def unpatch(module, attribute_name):
"""
Un-monkey-patch an attribute
Restore a backup of the original attribute from the patched
attribute, iff it exists (see: __BACKUP_ATTRIBUTE_NAME).
Return boolean whether or not the attribute could be unpatched
"""
was_patched = False
attribute = getattr(module, attribute_name)
if hasattr(attribute, __BACKUP_ATTRIBUTE_NAME):
attribute_old = getattr(attribute, __BACKUP_ATTRIBUTE_NAME)
setattr(module, attribute_name, attribute_old)
was_patched = True
return was_patched