Pastebin launched a little side project called VERYVIRAL.com, check it out ;-) Want more features on Pastebin? Sign Up, it's FREE!
Guest

MonkeyPatches to Django

By: a guest on Sep 20th, 2010  |  syntax: Python  |  size: 3.83 KB  |  views: 79  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. ##########################################
  2. # WARNING! MONKEYPATCHES AHEAD! WARNING! #
  3. ##########################################
  4.  
  5. """
  6. There are several changes I have made over time to the core Django code.
  7. Some of these fix bugs/inconsistencies in the core code and some
  8. are to add functionality.
  9.  
  10. Unfortunately, there are a few changes that I do not know how to make
  11. with a Monkey Patch. These require direct modification of the core
  12. code and are enumerated at the end of this file.
  13. """
  14.  
  15. #######################################################################
  16. # This should be a relatively safe MonkeyPatch because it only adds
  17. # new functionality on top of the most basic calls in the class.
  18. # If this breaks, then the BaseCache class must have morphed into Godzilla.
  19. #
  20. # The following adds a function to Django's BaseCache class
  21. # 'name' is the normal cache element name.
  22. # 'expr' is a string containing an expression eval-able in the
  23. #       caller's scope.
  24. #
  25. # If 'name' is not currently in the cache, the expression is
  26. # eval-ed and the results saved under that name.
  27. # The cached element is returned.
  28. #######################################################################
  29. def add_cache_get_or_eval():
  30.     import sys
  31.     from django.core.cache.backends.base import BaseCache
  32.  
  33.     def cache_get_or_eval(self, name, expr, timeout=None):
  34.         val = self.get(name)
  35.         if val is None:
  36.             caller = sys._getframe(1) # use caller's scope
  37.             val = eval(expr, caller.f_locals, caller.f_globals)
  38.             self.set(name, val, timeout)
  39.         return val
  40.     # cache_or_eval
  41.     BaseCache.get_or_eval = cache_get_or_eval
  42. # add_cache_get_or_eval()
  43. add_cache_get_or_eval()
  44.  
  45. #######################################################################
  46. # The template variable evaluation does not check for
  47. # call-ability on a simple variable, only on an object
  48. # method or list/dict element.
  49. #
  50. # I.e. if class Foo has method bar, then {{some_foo.bar}}
  51. # will call bar on some_foo and use the result.
  52. # OTOH, if mumble is a procedure, then {{mumble}} does NOT
  53. # do the obvious thing, but instead returns a meaningless
  54. # Python function object.
  55. #
  56. # This patch fixes this behavior (although it could use some work).
  57. #######################################################################
  58. def fix_resolve_lookup():
  59.     from django.template import Variable
  60.     from django.conf import settings
  61.  
  62.     old_resolve_lookup = Variable._resolve_lookup
  63.     def new_resolve_lookup(self, context):
  64.         current = old_resolve_lookup(self, context)
  65.  
  66.         if callable(current):
  67.           try: # call function (assuming no args required)
  68.               current = current()
  69.           except TypeError: # arguments *were* required
  70.               # GOTCHA: This will also catch any TypeError
  71.               # raised in the function itself.
  72.               current = settings.TEMPLATE_STRING_IF_INVALID # invalid method call
  73.           except Exception, e:
  74.               if getattr(e, 'silent_variable_failure', False):
  75.                   current = settings.TEMPLATE_STRING_IF_INVALID
  76.               else:
  77.                   raise
  78.  
  79.         return current
  80.     # new_resolve_lookup
  81.  
  82.     Variable._resolve_lookup = new_resolve_lookup
  83. # fix_resolve_lookup
  84. fix_resolve_lookup()
  85.  
  86. ############################################################
  87. # The following cannot be easily monkeypatched and so
  88. # requires direct modification of the core code.
  89. ############################################################
  90.  
  91. """
  92. # Show IP in log message from development server
  93. # core/servers/basehttp.py ~ 614 in WSGIRequestHandler.log_message()
  94. # change this
  95.    msg = "[%s] %s\n" % (self.log_date_time_string(), format % args)
  96. # to this
  97.    msg = "[%s] %s %s\n" % (self.log_date_time_string(),
  98.                       self.client_address[0], format % args)
  99. """