<commit_before>"""WSGI App Creator

This module is responsible for creating the basic Pylons WSGI application. It's generally
assumed that it will be called by Paste, though any WSGI application server could create
and call the WSGI app as well.

"""
import sys
import re
import inspect
import urllib
import warnings

import paste.wsgiwrappers
import paste.httpexceptions as httpexceptions
from paste.registry import RegistryManager
from paste.wsgiwrappers import WSGIRequest

from routes import request_config

import pylons
import pylons.templating
import pylons.legacy
from pylons.util import ContextObj, AttribSafeContextObj, _Translator, class_name_from_module_name
from pylons.controllers import Controller, WSGIController

class PylonsBaseWSGIApp(object):
    """Basic Pylons WSGI Application

    This basic WSGI app is provided should a web developer want to
    get access to the most basic Pylons web application environment
    available. By itself, this Pylons web application does little more
    than dispatch to a controller and setup the context object, the
    request object, and the globals object.
    
    Additional functionality like sessions, and caching can be setup by
    altering the ``environ['pylons.environ_config']`` setting to indicate
    what key the ``session`` and ``cache`` functionality should come from.
    
    Resolving the URL and dispatching can be customized by sub-classing or
    "monkey-patching" this class. Subclassing is the preferred approach.
    
    """
    def __init__(self, mapper, package_name, globals, default_charset=None):
        self.mapper = mapper
        self.globals = globals
        self.package_name = package_name
        config = globals.pylons_config
        if default_charset:
            warnings.warn(
                "The 'default_charset' keyword argument to the PylonsBaseWSGIApp "
                "constructor is deprecated. Please specify 'default_charset' to the Config "
                'object in your config/environment.py file instead, e.g.:\n'
                'return pylons.config.Config(myghty, map, paths, '
                "default_charset='%s')" % default_charset, DeprecationWarning, 2)
            config.default_charset = default_charset
        self.settings = dict(content_type='text/html', charset=config.default_charset)
        
        # Create the redirect function we'll use and save it
        def redirect_to(url):
            raise httpexceptions.HTTPFound(url)
        self.redirect_to = redirect_to
        
        # Initialize Buffet and all our template engines, default engine is the
        # first in the template_engines list
        def_eng = config.template_engines.pop(0)
        self.buffet = pylons.templating.Buffet(def_eng['engine'], 
            template_root=def_eng['template_root'], **def_eng['template_options'])
        for e in config.template_engines:
            self.buffet.prepare(e['engine'], template_root=e['template_root'], 
                alias=e['alias'], **e['template_options'])
    
    def __call__(self, environ, start_response):
        self.setup_app_env(environ, start_response)
        if environ.get('paste.testing'):
            self.load_test_env(environ)
        
        # Change our HTTP_METHOD if _method is present, try GET first to avoid
        # parsing POST unless absolutely necessary.
        req = pylons.request._current_obj()
        old_method = None
        if '_method' in environ['QUERY_STRING'] and req.GET.has_key('_method'):
            old_method = environ['REQUEST_METHOD']
            environ['REQUEST_METHOD'] = req.GET['_method']
        elif environ['REQUEST_METHOD'] == 'POST' and req.POST.has_key('_method'):
            old_method = environ['REQUEST_METHOD']
            environ['REQUEST_METHOD'] = req.POST['_method']
        
        controller = self.resolve(environ, start_response)
        if old_method: environ['REQUEST_METHOD'] = old_method            
        response = self.dispatch(controller, environ, start_response)
        
        if environ.get('paste.testing') and hasattr(response, 'wsgi_response'):
            environ['paste.testing_variables']['response'] = response
        
        # Transform HttpResponse objects into WSGI response
        if hasattr(response, 'wsgi_response'):
            status, response_headers, content = response.wsgi_response()
            start_response(status, response_headers)
            return content
        elif response:
            return response
            
        # Apparently we returned absolutely nothing, use the response
        # object if in legacy mode, otherwise raise an exception
        if environ.get('pylons.legacy'):
            resp = pylons.legacy.response
            if hasattr(pylons.legacy.response, 'wsgicall'):
                # Legacy app using run_wsgi
                return resp.content
            status, response_headers, content = resp.wsgi_response()
            start_response(status, response_headers)
            return content
        else:
            raise Exception, "No content returned by controller: %s" % controller.__name__
    
    def setup_app_env(self, environ, start_response):
        """Setup and register all the Pylons objects with the registry"""
        req = WSGIRequest(environ)
        
        # This is a legacy test for pre-0.9.2 projects to continue using the old
        # style Helper. New style directly uses the projects lib.helpers module
        # for 'normal' Python import usage with no surprises.
        __import__(self.package_name + '.lib.base')
        their_h = getattr(sys.modules[self.package_name + '.lib.base'], 'h', None)

        try: 
            helpers_name = self.package_name + '.config.helpers' 
            __import__(helpers_name) 
        except: 
            helpers_name = self.package_name + '.lib.helpers' 
            __import__(helpers_name)
        if their_h != pylons.h and their_h is not None:
            # We're using the new Helper import style
            req._h = sys.modules[helpers_name]
        else:
            # We still need to keep a reference to their helpers for the old
            # Helpers object.
            req._oldh = sys.modules[helpers_name]
        
        # Setup the translator global object
        trans = dict(translator=_Translator())
        trans['CONFIG'] = dict(app_conf=self.globals.pylons_config.app_conf,
            global_conf=self.globals.pylons_config.global_conf)
        if self.globals.pylons_config.app_conf.has_key('lang'):
            trans['translator'](self.globals.pylons_config.app_conf['lang'])
        else:
            trans['lang'] = None
        environ['paste.registry'].register(pylons.translator, trans)
        
        # Setup the basic pylons global objects
        environ['paste.registry'].register(paste.wsgiwrappers.settings, self.settings)
        environ['paste.registry'].register(pylons.request, req)
        if self.globals.pylons_config.strict_c:
            environ['paste.registry'].register(pylons.c, ContextObj())
        else:
            environ['paste.registry'].register(pylons.c, AttribSafeContextObj())
        environ['paste.registry'].register(pylons.g, self.globals)
        environ['paste.registry'].register(pylons.buffet, self.buffet)
        
        # Setup legacy globals
        if environ.get('pylons.legacy'):
            # Legacy mixed dictionary instead of MultiDict
            req._legacy_params = req.params.mixed()
            environ['paste.registry'].register(pylons.legacy.response, WSGIResponse())
            environ['paste.registry'].register(pylons.m, 
                pylons.legacy.Myghty_Compat(environ, start_response))
            environ['paste.registry'].register(pylons.params, req._legacy_params)
        
        econf = environ['pylons.environ_config']
        if econf.get('session'):
            environ['paste.registry'].register(pylons.session, environ[econf['session']])
        if econf.get('cache'):
            environ['paste.registry'].register(pylons.cache, environ[econf['cache']])
    
    def resolve(self, environ, start_response):
        """Implements Routes-based dispatching"""
        config = request_config()
        config.mapper = self.mapper
        config.environ = environ
        config.redirect = self.redirect_to
        match = config.mapper_dict
        if not match:
            return None
        environ['pylons.routes_dict'] = match
        controller = match.get('controller')
        if not controller:
            return None
        
        # Pull the controllers class name, import controller
        # @@ TODO: Encapsulate in try/except to raise error if controller
        #          doesn't exist, or class in controller file doesn't exist.
        full_module_name = self.package_name + '.controllers.' \
            + controller.replace('/', '.').replace('-', '_')
        
        __import__(full_module_name)
        module_name = full_module_name.split('.')[-1]
        class_name = class_name_from_module_name(module_name) + 'Controller'
        return getattr(sys.modules[full_module_name], class_name)
        
    def dispatch(self, controller, environ, start_response):
        """Dispatches to a controller, will instantiate the controller if
        necessary"""
        if not controller:
            raise httpexceptions.HTTPNotFound()
        match = environ['pylons.routes_dict']<commit_msg>[svn] Removed replace on controller name as Routes isn't passing it. Refs #107.<commit_after>"""WSGI App Creator

This module is responsible for creating the basic Pylons WSGI application. It's generally
assumed that it will be called by Paste, though any WSGI application server could create
and call the WSGI app as well.

"""
import sys
import re
import inspect
import urllib
import warnings

import paste.wsgiwrappers
import paste.httpexceptions as httpexceptions
from paste.registry import RegistryManager
from paste.wsgiwrappers import WSGIRequest

from routes import request_config

import pylons
import pylons.templating
import pylons.legacy
from pylons.util import ContextObj, AttribSafeContextObj, _Translator, class_name_from_module_name
from pylons.controllers import Controller, WSGIController

class PylonsBaseWSGIApp(object):
    """Basic Pylons WSGI Application

    This basic WSGI app is provided should a web developer want to
    get access to the most basic Pylons web application environment
    available. By itself, this Pylons web application does little more
    than dispatch to a controller and setup the context object, the
    request object, and the globals object.
    
    Additional functionality like sessions, and caching can be setup by
    altering the ``environ['pylons.environ_config']`` setting to indicate
    what key the ``session`` and ``cache`` functionality should come from.
    
    Resolving the URL and dispatching can be customized by sub-classing or
    "monkey-patching" this class. Subclassing is the preferred approach.
    
    """
    def __init__(self, mapper, package_name, globals, default_charset=None):
        self.mapper = mapper
        self.globals = globals
        self.package_name = package_name
        config = globals.pylons_config
        if default_charset:
            warnings.warn(
                "The 'default_charset' keyword argument to the PylonsBaseWSGIApp "
                "constructor is deprecated. Please specify 'default_charset' to the Config "
                'object in your config/environment.py file instead, e.g.:\n'
                'return pylons.config.Config(myghty, map, paths, '
                "default_charset='%s')" % default_charset, DeprecationWarning, 2)
            config.default_charset = default_charset
        self.settings = dict(content_type='text/html', charset=config.default_charset)
        
        # Create the redirect function we'll use and save it
        def redirect_to(url):
            raise httpexceptions.HTTPFound(url)
        self.redirect_to = redirect_to
        
        # Initialize Buffet and all our template engines, default engine is the
        # first in the template_engines list
        def_eng = config.template_engines.pop(0)
        self.buffet = pylons.templating.Buffet(def_eng['engine'], 
            template_root=def_eng['template_root'], **def_eng['template_options'])
        for e in config.template_engines:
            self.buffet.prepare(e['engine'], template_root=e['template_root'], 
                alias=e['alias'], **e['template_options'])
    
    def __call__(self, environ, start_response):
        self.setup_app_env(environ, start_response)
        if environ.get('paste.testing'):
            self.load_test_env(environ)
        
        # Change our HTTP_METHOD if _method is present, try GET first to avoid
        # parsing POST unless absolutely necessary.
        req = pylons.request._current_obj()
        old_method = None
        if '_method' in environ['QUERY_STRING'] and req.GET.has_key('_method'):
            old_method = environ['REQUEST_METHOD']
            environ['REQUEST_METHOD'] = req.GET['_method']
        elif environ['REQUEST_METHOD'] == 'POST' and req.POST.has_key('_method'):
            old_method = environ['REQUEST_METHOD']
            environ['REQUEST_METHOD'] = req.POST['_method']
        
        controller = self.resolve(environ, start_response)
        if old_method: environ['REQUEST_METHOD'] = old_method            
        response = self.dispatch(controller, environ, start_response)
        
        if environ.get('paste.testing') and hasattr(response, 'wsgi_response'):
            environ['paste.testing_variables']['response'] = response
        
        # Transform HttpResponse objects into WSGI response
        if hasattr(response, 'wsgi_response'):
            status, response_headers, content = response.wsgi_response()
            start_response(status, response_headers)
            return content
        elif response:
            return response
            
        # Apparently we returned absolutely nothing, use the response
        # object if in legacy mode, otherwise raise an exception
        if environ.get('pylons.legacy'):
            resp = pylons.legacy.response
            if hasattr(pylons.legacy.response, 'wsgicall'):
                # Legacy app using run_wsgi
                return resp.content
            status, response_headers, content = resp.wsgi_response()
            start_response(status, response_headers)
            return content
        else:
            raise Exception, "No content returned by controller: %s" % controller.__name__
    
    def setup_app_env(self, environ, start_response):
        """Setup and register all the Pylons objects with the registry"""
        req = WSGIRequest(environ)
        
        # This is a legacy test for pre-0.9.2 projects to continue using the old
        # style Helper. New style directly uses the projects lib.helpers module
        # for 'normal' Python import usage with no surprises.
        __import__(self.package_name + '.lib.base')
        their_h = getattr(sys.modules[self.package_name + '.lib.base'], 'h', None)

        try: 
            helpers_name = self.package_name + '.config.helpers' 
            __import__(helpers_name) 
        except: 
            helpers_name = self.package_name + '.lib.helpers' 
            __import__(helpers_name)
        if their_h != pylons.h and their_h is not None:
            # We're using the new Helper import style
            req._h = sys.modules[helpers_name]
        else:
            # We still need to keep a reference to their helpers for the old
            # Helpers object.
            req._oldh = sys.modules[helpers_name]
        
        # Setup the translator global object
        trans = dict(translator=_Translator())
        trans['CONFIG'] = dict(app_conf=self.globals.pylons_config.app_conf,
            global_conf=self.globals.pylons_config.global_conf)
        if self.globals.pylons_config.app_conf.has_key('lang'):
            trans['translator'](self.globals.pylons_config.app_conf['lang'])
        else:
            trans['lang'] = None
        environ['paste.registry'].register(pylons.translator, trans)
        
        # Setup the basic pylons global objects
        environ['paste.registry'].register(paste.wsgiwrappers.settings, self.settings)
        environ['paste.registry'].register(pylons.request, req)
        if self.globals.pylons_config.strict_c:
            environ['paste.registry'].register(pylons.c, ContextObj())
        else:
            environ['paste.registry'].register(pylons.c, AttribSafeContextObj())
        environ['paste.registry'].register(pylons.g, self.globals)
        environ['paste.registry'].register(pylons.buffet, self.buffet)
        
        # Setup legacy globals
        if environ.get('pylons.legacy'):
            # Legacy mixed dictionary instead of MultiDict
            req._legacy_params = req.params.mixed()
            environ['paste.registry'].register(pylons.legacy.response, WSGIResponse())
            environ['paste.registry'].register(pylons.m, 
                pylons.legacy.Myghty_Compat(environ, start_response))
            environ['paste.registry'].register(pylons.params, req._legacy_params)
        
        econf = environ['pylons.environ_config']
        if econf.get('session'):
            environ['paste.registry'].register(pylons.session, environ[econf['session']])
        if econf.get('cache'):
            environ['paste.registry'].register(pylons.cache, environ[econf['cache']])
    
    def resolve(self, environ, start_response):
        """Implements Routes-based dispatching"""
        config = request_config()
        config.mapper = self.mapper
        config.environ = environ
        config.redirect = self.redirect_to
        match = config.mapper_dict
        if not match:
            return None
        environ['pylons.routes_dict'] = match
        controller = match.get('controller')
        if not controller:
            return None
        
        # Pull the controllers class name, import controller
        # @@ TODO: Encapsulate in try/except to raise error if controller
        #          doesn't exist, or class in controller file doesn't exist.
        full_module_name = self.package_name + '.controllers.' \
            + controller.replace('/', '.')
        
        __import__(full_module_name)
        module_name = controller.split('/')[-1]
        class_name = class_name_from_module_name(module_name) + 'Controller'
        return getattr(sys.modules[full_module_name], class_name)
        
    def dispatch(self, controller, environ, start_response):
        """Dispatches to a controller, will instantiate the controller if
        necessary"""
        if not controller:
            raise httpexceptions.HTTPNotFound()
        match = environ['pylons.routes_dict']
{'fraction_non_alphanumeric': 0.08886418968984863, 'fraction_numerical': 0.0007939028262940616, 'mean_word_length': 2.6308608762490393, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5748485', 'n_tokens_mistral': 5156, 'n_tokens_neox': 5076, 'n_words': 1366}