Code

Ticket #5685: ticket_5685__revision_6453.patch

File ticket_5685__revision_6453.patch, 7.8 KB (added by __hawkeye__, 7 years ago)

First-pass implementation of this functionality. Lacks documentation.

  • django/conf/global_settings.py

     
    129129EMAIL_HOST_PASSWORD = '' 
    130130EMAIL_USE_TLS = False 
    131131 
     132# List of functions to be called to setup the runtime environment 
     133RUNTIME_SETUP_FUNCTIONS = () 
     134 
    132135# List of strings representing installed apps. 
    133136INSTALLED_APPS = () 
    134137 
  • django/core/handlers/wsgi.py

     
    178178    raw_post_data = property(_get_raw_post_data) 
    179179 
    180180class WSGIHandler(BaseHandler): 
    181     initLock = Lock() 
    182  
    183181    def __call__(self, environ, start_response): 
    184182        from django.conf import settings 
    185183 
    186         # Set up middleware if needed. We couldn't do this earlier, because 
    187         # settings weren't available. 
    188         if self._request_middleware is None: 
    189             self.initLock.acquire() 
    190             # Check that middleware is still uninitialised. 
    191             if self._request_middleware is None: 
    192                 self.load_middleware() 
    193             self.initLock.release() 
     184        # Perform state setup to ensure middleware is registered, among 
     185        # other things. 
     186        self.state.ensure_state() 
    194187 
    195188        dispatcher.send(signal=signals.request_started) 
    196189        try: 
  • django/core/handlers/base.py

     
    11from django.core import signals 
    22from django.dispatch import dispatcher 
     3from django.utils.setup import setup_runtime 
    34from django import http 
    45import sys 
     6import threading 
     7import logging 
    58 
    6 class BaseHandler(object): 
     9class HandlerState(object): 
     10    """ 
     11    A cache that stores/ensures state required for handling requests. 
     12    """ 
     13    # Use the Borg pattern to share state between all instances. Details at 
     14    # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66531. 
     15    __shared_state = dict( 
     16        request_middleware = [], 
     17        view_middleware = [], 
     18        response_middleware = [], 
     19        exception_middleware = [], 
     20        runtime_setup = False,  # Flag to monitor whether generic runtime environment setup has occured 
     21 
     22        # -- Variables used to setup the state -- 
     23        loaded = False,         # Flag to monitor the state of the cache 
     24        write_lock = threading.RLock(), 
     25    ) 
     26     
    727    def __init__(self): 
    8         self._request_middleware = self._view_middleware = self._response_middleware = self._exception_middleware = None 
     28        self.__dict__ = self.__shared_state 
     29     
     30    def ensure_state(self): 
     31        """ 
     32        Fill in all the cache information, and perform any setup that is 
     33        necessary. This method is threadsafe, in the sense that every caller 
     34        will see the same state upon return, and if the cache is already 
     35        initialised, it does no work. 
     36        """ 
     37        if self.loaded: 
     38            return 
     39        self.write_lock.acquire() 
     40        try: 
     41            if self.loaded: 
     42                return 
    943 
     44            setup_runtime() 
     45            self.runtime_setup = True 
     46 
     47            self.load_middleware() 
     48 
     49            self.loaded = True 
     50        finally: 
     51            self.write_lock.release() 
     52 
    1053    def load_middleware(self): 
    1154        """ 
    1255        Populate middleware lists from settings.MIDDLEWARE_CLASSES. 
     
    1558        """ 
    1659        from django.conf import settings 
    1760        from django.core import exceptions 
    18         self._request_middleware = [] 
    19         self._view_middleware = [] 
    20         self._response_middleware = [] 
    21         self._exception_middleware = [] 
     61 
    2262        for middleware_path in settings.MIDDLEWARE_CLASSES: 
    2363            try: 
    2464                dot = middleware_path.rindex('.') 
     
    4080                continue 
    4181 
    4282            if hasattr(mw_instance, 'process_request'): 
    43                 self._request_middleware.append(mw_instance.process_request) 
     83                self.request_middleware.append(mw_instance.process_request) 
    4484            if hasattr(mw_instance, 'process_view'): 
    45                 self._view_middleware.append(mw_instance.process_view) 
     85                self.view_middleware.append(mw_instance.process_view) 
    4686            if hasattr(mw_instance, 'process_response'): 
    47                 self._response_middleware.insert(0, mw_instance.process_response) 
     87                self.response_middleware.insert(0, mw_instance.process_response) 
    4888            if hasattr(mw_instance, 'process_exception'): 
    49                 self._exception_middleware.insert(0, mw_instance.process_exception) 
     89                self.exception_middleware.insert(0, mw_instance.process_exception) 
    5090 
     91handler_state = HandlerState() 
     92 
     93class BaseHandler(object): 
     94    state = handler_state 
     95    _request_middleware = handler_state.request_middleware 
     96    _view_middleware = handler_state.view_middleware 
     97    _response_middleware = handler_state.response_middleware 
     98    _exception_middleware = handler_state.exception_middleware 
     99 
    51100    def get_response(self, request): 
    52101        "Returns an HttpResponse object for the given HttpRequest" 
    53102        response = self._real_get_response(request) 
  • django/core/handlers/modpython.py

     
    144144        # that use settings now can work 
    145145        from django.conf import settings 
    146146 
    147         # if we need to set up middleware, now that settings works we can do it now. 
    148         if self._request_middleware is None: 
    149             self.load_middleware() 
     147        # Perform state setup to ensure middleware is registered, among 
     148        # other things. 
     149        self.state.ensure_state() 
    150150 
    151151        dispatcher.send(signal=signals.request_started) 
    152152        try: 
  • django/core/management/commands/shell.py

     
    11import os 
    22from django.core.management.base import NoArgsCommand 
     3from django.utils.setup import setup_runtime 
    34from optparse import make_option 
    45 
    56class Command(NoArgsCommand): 
     
    1213    requires_model_validation = False 
    1314 
    1415    def handle_noargs(self, **options): 
     16        setup_runtime() # Perform some setup that may be necessary to get the runtime environment ready 
     17 
    1518        # XXX: (Temporary) workaround for ticket #1796: force early loading of all 
    1619        # models from installed apps. 
    1720        from django.db.models.loading import get_models 
  • django/utils/setup.py

     
     1def setup_runtime(): 
     2    from django.conf import settings 
     3     
     4    functions = [] 
     5 
     6    for fn in settings.RUNTIME_SETUP_FUNCTIONS: 
     7        i = fn.rfind('.') 
     8        module, attr = fn[:i], fn[i+1:] 
     9        try: 
     10            mod = __import__(module, globals(), locals(), [attr]) 
     11        except ImportError, e: 
     12            raise ImproperlyConfigured, 'Error importing module %s during runtime setup: "%s"' % (module, e) 
     13        try: 
     14            func = getattr(mod, attr) 
     15            if not callable(func): raise AttributeError 
     16        except AttributeError: 
     17            raise ImproperlyConfigured, 'Module "%s" does not define a callable attribute "%s".' % (module, attr) 
     18        else: 
     19            try: 
     20                ret_val = func() 
     21            except Exception, e: 
     22                raise ImproperlyConfigured, 'Exception occurred while running %s: "%s"' % (fn, e)