diff options
| author | Chris McDonough <chrism@agendaless.com> | 2009-01-11 02:20:52 +0000 |
|---|---|---|
| committer | Chris McDonough <chrism@agendaless.com> | 2009-01-11 02:20:52 +0000 |
| commit | 358dc276d28fb395a9a742ff53dc66ee115c58ad (patch) | |
| tree | c92dd9bdd24f4b473a7e56a7a498aac046dd4ed4 | |
| parent | be268487581bf94086ecc18904113d71237612e1 (diff) | |
| download | pyramid-358dc276d28fb395a9a742ff53dc66ee115c58ad.tar.gz pyramid-358dc276d28fb395a9a742ff53dc66ee115c58ad.tar.bz2 pyramid-358dc276d28fb395a9a742ff53dc66ee115c58ad.zip | |
Merge router-simplify branch. Changelog below.
Bug Fixes
---------
- Fix a bug where the Paste configuration's ``unicode_path_segments``
(and os.environ's ``BFG_UNICODE_PATH_SEGMENTS``) may have been
defaulting to false in some circumstances. It now always defaults
to true, matching the documentation and intent.
- The ``repoze.bfg.traversal.find_model`` API did not work properly
when passed a ``path`` argument which was unicode and contained
high-order bytes when the ``unicode_path_segments`` or
``BFG_UNICODE_PATH_SEGMENTS`` configuration variables were "true".
- A new module was added: ``repoze.bfg.settings``. This contains
deployment-settings-related code.
Behavior Changes
----------------
- The ``make_app`` callable within ``repoze.bfg.router`` now registers
the ``root_policy`` argument as a utility (unnamed, using the new
``repoze.bfg.interfaces.IRootFactory`` as a provides interface)
rather than passing it as the first argument to the
``repoze.bfg.router.Router`` class. As a result the
``repoze.bfg.router.Router`` router class only accepts a single
argument: ``registry``. The ``repoze.bfg.router.Router`` class
retrieves the root policy via a utility lookup now. The
``repoze.bfg.router.make_app`` API also now performs some important
application registrations that were previously handled inside
``repoze.bfg.registry.makeRegistry``.
- The ``repoze.bfg.settings.Settings`` class (an instance of which is
registered as a utility providing
``repoze.bfg.interfaces.ISettings`` when any application is started)
now automatically calls ``repoze.bfg.settings.get_options`` on the
options passed to its constructor. This means that usage of
``get_options`` within an application's ``make_app`` function is no
longer required (the "raw" ``options`` dict or None may be passed).
Deprecations
------------
- Moved the ``repoze.bfg.registry.Settings`` class. This has been
moved to ``repoze.bfg.settings.Settings``. A deprecation warning is
issued when it is imported from the older location.
- Moved the ``repoze.bfg.registry.get_options`` function This has been
moved to ``repoze.bfg.settings.get_options``. A deprecation warning
is issued when it is imported from the older location.
- The ``repoze.bfg.interfaces.IRootPolicy`` interface was renamed
within the interfaces package. It has been renamed to
``IRootFactory``. A deprecation warning is issued when it is
imported from the older location.
| -rw-r--r-- | CHANGES.txt | 55 | ||||
| -rw-r--r-- | repoze/bfg/interfaces.py | 41 | ||||
| -rw-r--r-- | repoze/bfg/registry.py | 100 | ||||
| -rw-r--r-- | repoze/bfg/router.py | 54 | ||||
| -rw-r--r-- | repoze/bfg/settings.py | 55 | ||||
| -rw-r--r-- | repoze/bfg/tests/test_registry.py | 129 | ||||
| -rw-r--r-- | repoze/bfg/tests/test_router.py | 111 | ||||
| -rw-r--r-- | repoze/bfg/tests/test_settings.py | 121 | ||||
| -rw-r--r-- | repoze/bfg/tests/test_template.py | 80 | ||||
| -rw-r--r-- | repoze/bfg/tests/test_traversal.py | 20 | ||||
| -rw-r--r-- | repoze/bfg/traversal.py | 8 |
11 files changed, 452 insertions, 322 deletions
diff --git a/CHANGES.txt b/CHANGES.txt index 09d399f8d..538c7c96d 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -28,6 +28,61 @@ Features - Projects generated by the paster templates now use the ``DummyTemplateRenderer.assert_`` method in their view tests. +Bug Fixes +--------- + +- Fix a bug where the Paste configuration's ``unicode_path_segments`` + (and os.environ's ``BFG_UNICODE_PATH_SEGMENTS``) may have been + defaulting to false in some circumstances. It now always defaults + to true, matching the documentation and intent. + +- The ``repoze.bfg.traversal.find_model`` API did not work properly + when passed a ``path`` argument which was unicode and contained + high-order bytes when the ``unicode_path_segments`` or + ``BFG_UNICODE_PATH_SEGMENTS`` configuration variables were "true". + +- A new module was added: ``repoze.bfg.settings``. This contains + deployment-settings-related code. + +Behavior Changes +---------------- + +- The ``make_app`` callable within ``repoze.bfg.router`` now registers + the ``root_policy`` argument as a utility (unnamed, using the new + ``repoze.bfg.interfaces.IRootFactory`` as a provides interface) + rather than passing it as the first argument to the + ``repoze.bfg.router.Router`` class. As a result the + ``repoze.bfg.router.Router`` router class only accepts a single + argument: ``registry``. The ``repoze.bfg.router.Router`` class + retrieves the root policy via a utility lookup now. The + ``repoze.bfg.router.make_app`` API also now performs some important + application registrations that were previously handled inside + ``repoze.bfg.registry.makeRegistry``. + +- The ``repoze.bfg.settings.Settings`` class (an instance of which is + registered as a utility providing + ``repoze.bfg.interfaces.ISettings`` when any application is started) + now automatically calls ``repoze.bfg.settings.get_options`` on the + options passed to its constructor. This means that usage of + ``get_options`` within an application's ``make_app`` function is no + longer required (the "raw" ``options`` dict or None may be passed). + +Deprecations +------------ + +- Moved the ``repoze.bfg.registry.Settings`` class. This has been + moved to ``repoze.bfg.settings.Settings``. A deprecation warning is + issued when it is imported from the older location. + +- Moved the ``repoze.bfg.registry.get_options`` function This has been + moved to ``repoze.bfg.settings.get_options``. A deprecation warning + is issued when it is imported from the older location. + +- The ``repoze.bfg.interfaces.IRootPolicy`` interface was renamed + within the interfaces package. It has been renamed to + ``IRootFactory``. A deprecation warning is issued when it is + imported from the older location. + 0.6.1 (2009-01-06) ================== diff --git a/repoze/bfg/interfaces.py b/repoze/bfg/interfaces.py index b05558c81..70d6648e3 100644 --- a/repoze/bfg/interfaces.py +++ b/repoze/bfg/interfaces.py @@ -1,9 +1,33 @@ from zope.interface import Interface from zope.interface import Attribute -from zope.deprecation import deprecated +from zope.deferredimport import deprecated from zope.component.interfaces import IObjectEvent +deprecated( + '(repoze.bfg.interfaces.ITemplate should now be imported ' + 'as repoze.bfg.interfaces.ITemplateRenderer)', + ITemplate = 'repoze.bfg.interfaces:INodeTemplateRenderer', + ) + +deprecated( + '(repoze.bfg.interfaces.INodeTemplate should now be imported ' + 'as repoze.bfg.interfaces.INodeTemplateRenderer)', + INodeTemplate = 'repoze.bfg.interfaces:INodeTemplateRenderer', + ) + +deprecated( + '(repoze.bfg.interfaces.ITemplateFactory should now be imported ' + 'as repoze.bfg.interfaces.ITemplateRendererFactory)', + ITemplateFactory = 'repoze.bfg.interfaces:ITemplateRendererFactory', + ) + +deprecated( + '(repoze.bfg.interfaces.IRootPolicy should now be imported ' + 'as repoze.bfg.interfaces.IRootFactory)', + IRootPolicy = "repoze.bfg.interfaces:IRootFactory", + ) + class IRequest(Interface): """ Marker interface for a request object """ @@ -16,7 +40,7 @@ class IView(Interface): def __call__(context, request): """ Must return an object that implements IResponse """ -class IRootPolicy(Interface): +class IRootFactory(Interface): def __call__(environ): """ Return a root object """ @@ -49,19 +73,6 @@ class INodeTemplateRenderer(Interface): def __call__(node, **kw): """ Return a string result given a node and a template path """ -ITemplate = ITemplateRenderer -deprecated('ITemplate', - ('repoze.bfg.interfaces.ITemplate should now be imported ' - 'as repoze.bfg.interfaces.ITemplateRenderer')) -INodeTemplate = INodeTemplateRenderer -deprecated('INodeTemplate', - ('repoze.bfg.interfaces.INodeTemplate should now be imported ' - 'as repoze.bfg.interfaces.INodeTemplateRenderer')) -ITemplateFactory = ITemplateRendererFactory -deprecated('ITemplateFactory', - ('repoze.bfg.interfaces.ITemplateFactory should now be imported ' - 'as repoze.bfg.interfaces.ITemplateRendererFactory')) - class ISecurityPolicy(Interface): """ A utility that provides a mechanism to check authorization using authentication data """ diff --git a/repoze/bfg/registry.py b/repoze/bfg/registry.py index cab95933b..f2f47a889 100644 --- a/repoze/bfg/registry.py +++ b/repoze/bfg/registry.py @@ -1,5 +1,3 @@ -import os -import sys import threading import zope.component @@ -10,12 +8,21 @@ from zope.component.interfaces import IComponentLookup from zope.component.registry import Components from zope.component import getSiteManager as original_getSiteManager -from zope.interface import implements +from zope.deferredimport import deprecated -from repoze.bfg.interfaces import ISettings -from repoze.bfg.interfaces import ILogger from repoze.bfg.zcml import zcml_configure -from repoze.bfg.log import make_stream_logger + +deprecated( + "('from repoze.bfg.registry import Settings' is now " + "deprecated; instead use 'from repoze.bfg.settings import Settings')", + Settings = "repoze.bfg.settings:Settings", + ) + +deprecated( + "('from repoze.bfg.registry import get_options' is now " + "deprecated; instead use 'from repoze.bfg.settings import get_options')", + get_options = "repoze.bfg.settings:get_options", + ) class ThreadLocalRegistryManager(threading.local): registry = getGlobalSiteManager() @@ -36,30 +43,26 @@ def setRegistryManager(manager): # for unit tests registry_manager = manager return old_registry_manager -def makeRegistry(filename, package, options=None, lock=threading.Lock()): - # We push our ZCML-defined configuration into an app-local - # component registry in order to allow more than one bfg app to - # live in the same process space without one unnecessarily - # stomping on the other's component registrations (although I - # suspect directives that have side effects are going to fail). - # The only way to do that currently is to override - # zope.component.getGlobalSiteManager for the duration of the ZCML - # includes. We acquire a lock in case another make_app runs in a - # different thread simultaneously, in a vain attempt to prevent - # mixing of registrations. There's not much we can do about - # non-make_app code that tries to use the global site manager API - # directly in a different thread while we hold the lock. Those - # registrations will end up in our application's registry. +def makeRegistry(filename, package, lock=threading.Lock()): + + """ We push our ZCML-defined configuration into an app-local + component registry in order to allow more than one bfg app to live + in the same process space without one unnecessarily stomping on + the other's component registrations (although I suspect directives + that have side effects are going to fail). The only way to do + that currently is to override zope.component.getGlobalSiteManager + for the duration of the ZCML includes. We acquire a lock in case + another make_app runs in a different thread simultaneously, in a + vain attempt to prevent mixing of registrations. There's not much + we can do about non-makeRegistry code that tries to use the global + site manager API directly in a different thread while we hold the + lock. Those registrations will end up in our application's + registry.""" + lock.acquire() try: registry = Components(package.__name__) registry_manager.set(registry) - if options is None: - options = {} - settings = Settings(options) - registry.registerUtility(settings, ISettings) - debug_logger = make_stream_logger('repoze.bfg.debug', sys.stderr) - registry.registerUtility(debug_logger, ILogger, 'repoze.bfg.debug') original_getSiteManager.sethook(getSiteManager) zope.component.getGlobalSiteManager = registry_manager.get zcml_configure(filename, package=package) @@ -69,15 +72,6 @@ def makeRegistry(filename, package, options=None, lock=threading.Lock()): lock.release() registry_manager.clear() -class Settings(object): - implements(ISettings) - reload_templates = False - debug_notfound = False - debug_authorization = False - unicode_path_segments = True - def __init__(self, options): - self.__dict__.update(options) - def getSiteManager(context=None): if context is None: return registry_manager.get() @@ -87,42 +81,6 @@ def getSiteManager(context=None): except TypeError, error: raise ComponentLookupError(*error.args) -def asbool(s): - s = str(s).strip() - return s.lower() in ('t', 'true', 'y', 'yes', 'on', '1') - -def get_options(kw, environ=os.environ): - """ Update PasteDeploy application settings keywords with - framework-specific key/value pairs (e.g. find - 'BFG_DEBUG_AUTHORIZATION' in os.environ and jam into keyword - args).""" - # environ is passed in for unit tests - eget = environ.get - config_debug_all = kw.get('debug_all', '') - effective_debug_all = asbool(eget('BFG_DEBUG_ALL', - config_debug_all)) - config_debug_auth = kw.get('debug_authorization', '') - effective_debug_auth = asbool(eget('BFG_DEBUG_AUTHORIZATION', - config_debug_auth)) - config_debug_notfound = kw.get('debug_notfound', '') - effective_debug_notfound = asbool(eget('BFG_DEBUG_NOTFOUND', - config_debug_notfound)) - config_reload_templates = kw.get('reload_templates', '') - effective_reload_templates = asbool(eget('BFG_RELOAD_TEMPLATES', - config_reload_templates)) - config_unicode_path_segments = kw.get('unicode_path_segments', '') - effective_unicode_path_segments = asbool(eget('BFG_UNICODE_PATH_SEGMENTS', - config_unicode_path_segments)) - update = { - 'debug_authorization': effective_debug_all or effective_debug_auth, - 'debug_notfound': effective_debug_all or effective_debug_notfound, - 'reload_templates': effective_reload_templates, - 'unicode_path_segments': effective_unicode_path_segments, - } - - kw.update(update) - return kw - from zope.testing.cleanup import addCleanUp try: addCleanUp(original_getSiteManager.reset) diff --git a/repoze/bfg/router.py b/repoze/bfg/router.py index 89101cb5e..a67cd1088 100644 --- a/repoze/bfg/router.py +++ b/repoze/bfg/router.py @@ -1,8 +1,11 @@ +import sys from cgi import escape from zope.component import getAdapter +from zope.component import getUtility from zope.component import queryUtility from zope.component.event import dispatch + from zope.interface import directlyProvides from zope.interface import implements @@ -18,10 +21,14 @@ from repoze.bfg.interfaces import ILogger from repoze.bfg.interfaces import ITraverserFactory from repoze.bfg.interfaces import IRequest from repoze.bfg.interfaces import IRouter +from repoze.bfg.interfaces import IRootFactory from repoze.bfg.interfaces import ISettings +from repoze.bfg.log import make_stream_logger + from repoze.bfg.registry import registry_manager from repoze.bfg.registry import makeRegistry +from repoze.bfg.settings import Settings from repoze.bfg.view import render_view_to_response from repoze.bfg.view import view_execution_permitted @@ -34,8 +41,7 @@ class Router(object): implements(IRouter) - def __init__(self, root_policy, registry): - self.root_policy = root_policy + def __init__(self, registry): self.registry = registry def __call__(self, environ, start_response): @@ -43,9 +49,10 @@ class Router(object): request = Request(environ) directlyProvides(request, IRequest) dispatch(NewRequest(request)) - root = self.root_policy(environ) + + root_factory = getUtility(IRootFactory) + root = root_factory(environ) traverser = getAdapter(root, ITraverserFactory) - settings = queryUtility(ISettings) context, name, subpath = traverser(environ) request.root = root @@ -54,6 +61,8 @@ class Router(object): request.subpath = subpath permitted = view_execution_permitted(context, request, name) + + settings = queryUtility(ISettings) debug_authorization = settings and settings.debug_authorization if debug_authorization: @@ -93,21 +102,29 @@ class Router(object): start_response(response.status, response.headerlist) return response.app_iter -def make_app(root_policy, package=None, filename='configure.zcml', +def make_app(root_factory, package=None, filename='configure.zcml', options=None): - """ Create a view registry based on the application's ZCML. and - return a Router object, representing a ``repoze.bfg`` WSGI - application. ``root_policy`` must be a callable that accepts a - WSGI environment and returns a graph root object. ``package`` is - a Python module representing the application's package, - ``filename`` is the filesystem path to a ZCML file (optionally - relative to the package path) that should be parsed to create the - view registry. ``options``, if used, should be a dictionary - containing bfg-specific runtime options, with each key - representing the option and the key's value representing the - specific option value, e.g. ``{'reload_templates':True}``""" - registry = makeRegistry(filename, package, options) - app = Router(root_policy, registry) + """ Return a Router object, representing a ``repoze.bfg`` WSGI + application. ``root_factory`` must be a callable that accepts a + WSGI environment and returns a root object. ``package`` is a + Python module representing the application's package, ``filename`` + is the filesystem path to a ZCML file (optionally relative to the + package path) that should be parsed to create the application + registry. ``options``, if used, should be a dictionary containing + runtime options (e.g. the key/value pairs in an app section of a + PasteDeploy file), with each key representing the option and the + key's value representing the specific option value, + e.g. ``{'reload_templates':True}``""" + if options is None: + options = {} + + registry = makeRegistry(filename, package) + settings = Settings(options) + registry.registerUtility(settings, ISettings) + debug_logger = make_stream_logger('repoze.bfg.debug', sys.stderr) + registry.registerUtility(debug_logger, ILogger, 'repoze.bfg.debug') + registry.registerUtility(root_factory, IRootFactory) + app = Router(registry) try: registry_manager.set(registry) @@ -117,4 +134,3 @@ def make_app(root_policy, package=None, filename='configure.zcml', return app - diff --git a/repoze/bfg/settings.py b/repoze/bfg/settings.py new file mode 100644 index 000000000..7cd19fcf7 --- /dev/null +++ b/repoze/bfg/settings.py @@ -0,0 +1,55 @@ +import os + +from zope.interface import implements + +from repoze.bfg.interfaces import ISettings + +class Settings(object): + implements(ISettings) + + # defaults + reload_templates = False + debug_notfound = False + debug_authorization = False + unicode_path_segments = True + + def __init__(self, options): + options = get_options(options) + self.__dict__.update(options) + +def asbool(s): + s = str(s).strip() + return s.lower() in ('t', 'true', 'y', 'yes', 'on', '1') + +def get_options(kw, environ=os.environ): + """ Update PasteDeploy application settings keywords with + framework-specific key/value pairs (e.g. find + 'BFG_DEBUG_AUTHORIZATION' in os.environ and jam into keyword + args).""" + # environ is passed in for unit tests + eget = environ.get + config_debug_all = kw.get('debug_all', '') + effective_debug_all = asbool(eget('BFG_DEBUG_ALL', + config_debug_all)) + config_debug_auth = kw.get('debug_authorization', '') + effective_debug_auth = asbool(eget('BFG_DEBUG_AUTHORIZATION', + config_debug_auth)) + config_debug_notfound = kw.get('debug_notfound', '') + effective_debug_notfound = asbool(eget('BFG_DEBUG_NOTFOUND', + config_debug_notfound)) + config_reload_templates = kw.get('reload_templates', '') + effective_reload_templates = asbool(eget('BFG_RELOAD_TEMPLATES', + config_reload_templates)) + config_unicode_path_segments = kw.get('unicode_path_segments', 't') + effective_unicode_path_segments = asbool(eget('BFG_UNICODE_PATH_SEGMENTS', + config_unicode_path_segments)) + update = { + 'debug_authorization': effective_debug_all or effective_debug_auth, + 'debug_notfound': effective_debug_all or effective_debug_notfound, + 'reload_templates': effective_reload_templates, + 'unicode_path_segments': effective_unicode_path_segments, + } + + kw.update(update) + return kw + diff --git a/repoze/bfg/tests/test_registry.py b/repoze/bfg/tests/test_registry.py index 9bf09399f..0d051c131 100644 --- a/repoze/bfg/tests/test_registry.py +++ b/repoze/bfg/tests/test_registry.py @@ -23,144 +23,15 @@ class TestMakeRegistry(unittest.TestCase, PlacelessSetup): old = repoze.bfg.registry.setRegistryManager(dummyregmgr) registry = makeRegistry('configure.zcml', fixtureapp, - options={'reload_templates':True, - 'debug_authorization':True}, lock=dummylock) from zope.component.registry import Components self.failUnless(isinstance(registry, Components)) self.assertEqual(dummylock.acquired, True) self.assertEqual(dummylock.released, True) self.assertEqual(dummyregmgr.registry, registry) - from zope.component import getUtility - from repoze.bfg.interfaces import ISettings - from repoze.bfg.interfaces import ILogger - settings = getUtility(ISettings) - logger = getUtility(ILogger, name='repoze.bfg.debug') - self.assertEqual(logger.name, 'repoze.bfg.debug') - self.assertEqual(settings.reload_templates, True) - self.assertEqual(settings.debug_authorization, True) finally: repoze.bfg.registry.setRegistryManager(old) -class TestGetOptions(unittest.TestCase): - def _getFUT(self): - from repoze.bfg.registry import get_options - return get_options - - def test_reload_templates(self): - get_options = self._getFUT() - result = get_options({}) - self.assertEqual(result['reload_templates'], False) - result = get_options({'reload_templates':'false'}) - self.assertEqual(result['reload_templates'], False) - result = get_options({'reload_templates':'t'}) - self.assertEqual(result['reload_templates'], True) - result = get_options({'reload_templates':'1'}) - self.assertEqual(result['reload_templates'], True) - result = get_options({}, {'BFG_RELOAD_TEMPLATES':'1'}) - self.assertEqual(result['reload_templates'], True) - result = get_options({'reload_templates':'false'}, - {'BFG_RELOAD_TEMPLATES':'1'}) - self.assertEqual(result['reload_templates'], True) - - def test_debug_authorization(self): - get_options = self._getFUT() - result = get_options({}) - self.assertEqual(result['debug_authorization'], False) - result = get_options({'debug_authorization':'false'}) - self.assertEqual(result['debug_authorization'], False) - result = get_options({'debug_authorization':'t'}) - self.assertEqual(result['debug_authorization'], True) - result = get_options({'debug_authorization':'1'}) - self.assertEqual(result['debug_authorization'], True) - result = get_options({}, {'BFG_DEBUG_AUTHORIZATION':'1'}) - self.assertEqual(result['debug_authorization'], True) - result = get_options({'debug_authorization':'false'}, - {'BFG_DEBUG_AUTHORIZATION':'1'}) - self.assertEqual(result['debug_authorization'], True) - - def test_debug_notfound(self): - get_options = self._getFUT() - result = get_options({}) - self.assertEqual(result['debug_notfound'], False) - result = get_options({'debug_notfound':'false'}) - self.assertEqual(result['debug_notfound'], False) - result = get_options({'debug_notfound':'t'}) - self.assertEqual(result['debug_notfound'], True) - result = get_options({'debug_notfound':'1'}) - self.assertEqual(result['debug_notfound'], True) - result = get_options({}, {'BFG_DEBUG_NOTFOUND':'1'}) - self.assertEqual(result['debug_notfound'], True) - result = get_options({'debug_notfound':'false'}, - {'BFG_DEBUG_NOTFOUND':'1'}) - self.assertEqual(result['debug_notfound'], True) - - def test_debug_all(self): - get_options = self._getFUT() - result = get_options({}) - self.assertEqual(result['debug_notfound'], False) - self.assertEqual(result['debug_authorization'], False) - result = get_options({'debug_all':'false'}) - self.assertEqual(result['debug_notfound'], False) - self.assertEqual(result['debug_authorization'], False) - result = get_options({'debug_all':'t'}) - self.assertEqual(result['debug_notfound'], True) - self.assertEqual(result['debug_authorization'], True) - result = get_options({'debug_all':'1'}) - self.assertEqual(result['debug_notfound'], True) - self.assertEqual(result['debug_authorization'], True) - result = get_options({}, {'BFG_DEBUG_ALL':'1'}) - self.assertEqual(result['debug_notfound'], True) - self.assertEqual(result['debug_authorization'], True) - result = get_options({'debug_all':'false'}, - {'BFG_DEBUG_ALL':'1'}) - self.assertEqual(result['debug_notfound'], True) - self.assertEqual(result['debug_authorization'], True) - - def test_unicode_path_segments(self): - get_options = self._getFUT() - result = get_options({}) - self.assertEqual(result['unicode_path_segments'], False) - result = get_options({'unicode_path_segments':'false'}) - self.assertEqual(result['unicode_path_segments'], False) - result = get_options({'unicode_path_segments':'t'}) - self.assertEqual(result['unicode_path_segments'], True) - result = get_options({'unicode_path_segments':'1'}) - self.assertEqual(result['unicode_path_segments'], True) - result = get_options({}, {'BFG_UNICODE_PATH_SEGMENTS':'1'}) - self.assertEqual(result['unicode_path_segments'], True) - result = get_options({'unicode_path_segments':'false'}, - {'BFG_UNICODE_PATH_SEGMENTS':'1'}) - self.assertEqual(result['unicode_path_segments'], True) - - def test_originals_kept(self): - get_options = self._getFUT() - result = get_options({'a':'i am so a'}) - self.assertEqual(result['a'], 'i am so a') - -class TestSettings(unittest.TestCase): - def _getTargetClass(self): - from repoze.bfg.registry import Settings - return Settings - - def _makeOne(self, **options): - klass = self._getTargetClass() - return klass(options) - - def test_no_options(self): - settings = self._makeOne() - self.assertEqual(settings.reload_templates, False) - self.assertEqual(settings.debug_notfound, False) - self.assertEqual(settings.debug_authorization, False) - self.assertEqual(settings.unicode_path_segments, True) - - def test_with_option(self): - settings = self._makeOne(reload_templates=True) - self.assertEqual(settings.reload_templates, True) - self.assertEqual(settings.debug_notfound, False) - self.assertEqual(settings.debug_authorization, False) - self.assertEqual(settings.unicode_path_segments, True) - class TestThreadLocalRegistryManager(unittest.TestCase, PlacelessSetup): def setUp(self): PlacelessSetup.setUp(self) diff --git a/repoze/bfg/tests/test_router.py b/repoze/bfg/tests/test_router.py index 43dc98176..3f52bd9cd 100644 --- a/repoze/bfg/tests/test_router.py +++ b/repoze/bfg/tests/test_router.py @@ -65,6 +65,12 @@ class RouterTests(unittest.TestCase, PlacelessSetup): gsm = zope.component.getGlobalSiteManager() gsm.registerHandler(listener, (iface,)) + def _registerRootFactory(self, root_factory): + import zope.component + gsm = zope.component.getGlobalSiteManager() + from repoze.bfg.interfaces import IRootFactory + gsm.registerUtility(root_factory, IRootFactory) + def _getTargetClass(self): from repoze.bfg.router import Router return Router @@ -84,13 +90,14 @@ class RouterTests(unittest.TestCase, PlacelessSetup): return environ def test_call_no_view_registered_no_isettings(self): - rootpolicy = make_rootpolicy(None) + rootfactory = make_rootfactory(None) environ = self._makeEnviron() context = DummyContext() traversalfactory = make_traversal_factory(context, '', []) self._registerTraverserFactory(traversalfactory, '', None) logger = self._registerLogger() - router = self._makeOne(rootpolicy, None) + self._registerRootFactory(rootfactory) + router = self._makeOne(None) start_response = DummyStartResponse() result = router(environ, start_response) headers = start_response.headers @@ -102,14 +109,15 @@ class RouterTests(unittest.TestCase, PlacelessSetup): self.assertEqual(len(logger.messages), 0) def test_call_no_view_registered_debug_notfound_false(self): - rootpolicy = make_rootpolicy(None) + rootfactory = make_rootfactory(None) environ = self._makeEnviron() context = DummyContext() traversalfactory = make_traversal_factory(context, '', []) self._registerTraverserFactory(traversalfactory, '', None) logger = self._registerLogger() self._registerSettings(debug_notfound=False) - router = self._makeOne(rootpolicy, None) + self._registerRootFactory(rootfactory) + router = self._makeOne(None) start_response = DummyStartResponse() result = router(environ, start_response) headers = start_response.headers @@ -121,14 +129,15 @@ class RouterTests(unittest.TestCase, PlacelessSetup): self.assertEqual(len(logger.messages), 0) def test_call_no_view_registered_debug_notfound_true(self): - rootpolicy = make_rootpolicy(None) + rootfactory = make_rootfactory(None) environ = self._makeEnviron() context = DummyContext() traversalfactory = make_traversal_factory(context, '', []) self._registerTraverserFactory(traversalfactory, '', None) self._registerSettings(debug_notfound=True) logger = self._registerLogger() - router = self._makeOne(rootpolicy, None) + self._registerRootFactory(rootfactory) + router = self._makeOne(None) start_response = DummyStartResponse() result = router(environ, start_response) headers = start_response.headers @@ -150,7 +159,7 @@ class RouterTests(unittest.TestCase, PlacelessSetup): self.failUnless("subpath: []" in message) def test_call_view_registered_nonspecific_default_path(self): - rootpolicy = make_rootpolicy(None) + rootfactory = make_rootfactory(None) context = DummyContext() traversalfactory = make_traversal_factory(context, '', []) response = DummyResponse() @@ -159,7 +168,8 @@ class RouterTests(unittest.TestCase, PlacelessSetup): environ = self._makeEnviron() self._registerTraverserFactory(traversalfactory, '', None) self._registerView(view, '', None, None) - router = self._makeOne(rootpolicy, None) + self._registerRootFactory(rootfactory) + router = self._makeOne(None) start_response = DummyStartResponse() result = router(environ, start_response) self.assertEqual(result, ['Hello world']) @@ -171,7 +181,7 @@ class RouterTests(unittest.TestCase, PlacelessSetup): self.assertEqual(environ['webob.adhoc_attrs']['root'], None) def test_call_view_registered_nonspecific_nondefault_path_and_subpath(self): - rootpolicy = make_rootpolicy(None) + rootfactory = make_rootfactory(None) context = DummyContext() traversalfactory = make_traversal_factory(context, 'foo', ['bar']) response = DummyResponse() @@ -180,7 +190,8 @@ class RouterTests(unittest.TestCase, PlacelessSetup): environ = self._makeEnviron() self._registerTraverserFactory(traversalfactory, '', None) self._registerView(view, 'foo', None, None) - router = self._makeOne(rootpolicy, None) + self._registerRootFactory(rootfactory) + router = self._makeOne(None) start_response = DummyStartResponse() result = router(environ, start_response) self.assertEqual(result, ['Hello world']) @@ -192,7 +203,7 @@ class RouterTests(unittest.TestCase, PlacelessSetup): self.assertEqual(environ['webob.adhoc_attrs']['root'], None) def test_call_view_registered_specific_success(self): - rootpolicy = make_rootpolicy(None) + rootfactory = make_rootfactory(None) from zope.interface import Interface from zope.interface import directlyProvides class IContext(Interface): @@ -207,7 +218,8 @@ class RouterTests(unittest.TestCase, PlacelessSetup): environ = self._makeEnviron() self._registerTraverserFactory(traversalfactory, '', None) self._registerView(view, '', IContext, IRequest) - router = self._makeOne(rootpolicy, None) + self._registerRootFactory(rootfactory) + router = self._makeOne(None) start_response = DummyStartResponse() result = router(environ, start_response) self.assertEqual(result, ['Hello world']) @@ -219,7 +231,7 @@ class RouterTests(unittest.TestCase, PlacelessSetup): self.assertEqual(environ['webob.adhoc_attrs']['root'], None) def test_call_view_registered_specific_fail(self): - rootpolicy = make_rootpolicy(None) + rootfactory = make_rootfactory(None) from zope.interface import Interface from zope.interface import directlyProvides class IContext(Interface): @@ -235,14 +247,15 @@ class RouterTests(unittest.TestCase, PlacelessSetup): environ = self._makeEnviron() self._registerTraverserFactory(traversalfactory, '', None) self._registerView(view, '', IContext, IRequest) - router = self._makeOne(rootpolicy, None) + self._registerRootFactory(rootfactory) + router = self._makeOne(None) start_response = DummyStartResponse() result = router(environ, start_response) self.assertEqual(start_response.status, '404 Not Found') self.failUnless('404' in result[0]) def test_call_view_registered_security_policy_permission_none(self): - rootpolicy = make_rootpolicy(None) + rootfactory = make_rootfactory(None) from zope.interface import Interface from zope.interface import directlyProvides class IContext(Interface): @@ -258,13 +271,14 @@ class RouterTests(unittest.TestCase, PlacelessSetup): self._registerView(view, '', IContext, IRequest) secpol = DummySecurityPolicy() self._registerSecurityPolicy(secpol) - router = self._makeOne(rootpolicy, None) + self._registerRootFactory(rootfactory) + router = self._makeOne(None) start_response = DummyStartResponse() result = router(environ, start_response) self.assertEqual(start_response.status, '200 OK') def test_call_view_registered_security_policy_permission_succeeds(self): - rootpolicy = make_rootpolicy(None) + rootfactory = make_rootfactory(None) from zope.interface import Interface from zope.interface import directlyProvides class IContext(Interface): @@ -282,14 +296,15 @@ class RouterTests(unittest.TestCase, PlacelessSetup): self._registerView(view, '', IContext, IRequest) self._registerSecurityPolicy(secpol) self._registerPermission(permissionfactory, '', IContext, IRequest) - router = self._makeOne(rootpolicy, None) + self._registerRootFactory(rootfactory) + router = self._makeOne(None) start_response = DummyStartResponse() result = router(environ, start_response) self.assertEqual(start_response.status, '200 OK') self.assertEqual(permissionfactory.checked_with, secpol) def test_call_view_permission_fails_nosettings(self): - rootpolicy = make_rootpolicy(None) + rootfactory = make_rootfactory(None) from zope.interface import Interface from zope.interface import directlyProvides class IContext(Interface): @@ -310,7 +325,8 @@ class RouterTests(unittest.TestCase, PlacelessSetup): self._registerView(view, '', IContext, IRequest) self._registerSecurityPolicy(secpol) self._registerPermission(permissionfactory, '', IContext, IRequest) - router = self._makeOne(rootpolicy, None) + self._registerRootFactory(rootfactory) + router = self._makeOne(None) start_response = DummyStartResponse() result = router(environ, start_response) self.assertEqual(start_response.status, '401 Unauthorized') @@ -319,7 +335,7 @@ class RouterTests(unittest.TestCase, PlacelessSetup): self.assertEqual(permissionfactory.checked_with, secpol) def test_call_view_permission_fails_no_debug_auth(self): - rootpolicy = make_rootpolicy(None) + rootfactory = make_rootfactory(None) from zope.interface import Interface from zope.interface import directlyProvides class IContext(Interface): @@ -341,7 +357,8 @@ class RouterTests(unittest.TestCase, PlacelessSetup): self._registerSecurityPolicy(secpol) self._registerPermission(permissionfactory, '', IContext, IRequest) self._registerSettings(debug_authorization=False) - router = self._makeOne(rootpolicy, None) + self._registerRootFactory(rootfactory) + router = self._makeOne(None) start_response = DummyStartResponse() result = router(environ, start_response) self.assertEqual(start_response.status, '401 Unauthorized') @@ -350,7 +367,7 @@ class RouterTests(unittest.TestCase, PlacelessSetup): self.assertEqual(permissionfactory.checked_with, secpol) def test_call_view_permission_fails_with_debug_auth(self): - rootpolicy = make_rootpolicy(None) + rootfactory = make_rootfactory(None) from zope.interface import Interface from zope.interface import directlyProvides class IContext(Interface): @@ -373,7 +390,8 @@ class RouterTests(unittest.TestCase, PlacelessSetup): self._registerPermission(permissionfactory, '', IContext, IRequest) self._registerSettings(debug_authorization=True) logger = self._registerLogger() - router = self._makeOne(rootpolicy, None) + self._registerRootFactory(rootfactory) + router = self._makeOne(None) start_response = DummyStartResponse() result = router(environ, start_response) self.assertEqual(start_response.status, '401 Unauthorized') @@ -395,7 +413,7 @@ class RouterTests(unittest.TestCase, PlacelessSetup): "for principals ['principals']" in logged) def test_call_eventsends(self): - rootpolicy = make_rootpolicy(None) + rootfactory = make_rootfactory(None) context = DummyContext() traversalfactory = make_traversal_factory(context, '', []) response = DummyResponse() @@ -414,7 +432,8 @@ class RouterTests(unittest.TestCase, PlacelessSetup): response_events.append(event) self._registerEventListener(handle_request, INewRequest) self._registerEventListener(handle_response, INewResponse) - router = self._makeOne(rootpolicy, None) + self._registerRootFactory(rootfactory) + router = self._makeOne(None) start_response = DummyStartResponse() result = router(environ, start_response) self.assertEqual(len(request_events), 1) @@ -429,17 +448,15 @@ class MakeAppTests(unittest.TestCase, PlacelessSetup): def tearDown(self): PlacelessSetup.tearDown(self) - def _getFUT(self): + def _callFUT(self, *arg, **kw): from repoze.bfg.router import make_app - return make_app + return make_app(*arg, **kw) def test_fixtureapp(self): from repoze.bfg.tests import fixtureapp - make_app = self._getFUT() - rootpolicy = make_rootpolicy(None) - app = make_app(rootpolicy, fixtureapp) + rootpolicy = make_rootfactory(None) + app = self._callFUT(rootpolicy, fixtureapp) self.assertEqual(app.registry.__name__, 'repoze.bfg.tests.fixtureapp') - self.assertEqual(app.root_policy, rootpolicy) def test_event(self): def subscriber(event): @@ -455,13 +472,35 @@ class MakeAppTests(unittest.TestCase, PlacelessSetup): ) try: from repoze.bfg.tests import fixtureapp - make_app = self._getFUT() - rootpolicy = make_rootpolicy(None) - app = make_app(rootpolicy, fixtureapp) + rootpolicy = make_rootfactory(None) + app = self._callFUT(rootpolicy, fixtureapp) assert app.created is True finally: repoze.bfg.router.registry_manager = old_registry_manager + def test_registrations(self): + options= {'reload_templates':True, + 'debug_authorization':True} + import repoze.bfg.router + old_registry_manager = repoze.bfg.router.registry_manager + repoze.bfg.router.registry_manager = DummyRegistryManager() + try: + from repoze.bfg.tests import fixtureapp + rootpolicy = make_rootfactory(None) + app = self._callFUT(rootpolicy, fixtureapp, options=options) + from repoze.bfg.interfaces import ISettings + from repoze.bfg.interfaces import ILogger + from repoze.bfg.interfaces import IRootFactory + settings = app.registry.getUtility(ISettings) + logger = app.registry.getUtility(ILogger, name='repoze.bfg.debug') + rootfactory = app.registry.getUtility(IRootFactory) + self.assertEqual(logger.name, 'repoze.bfg.debug') + self.assertEqual(settings.reload_templates, True) + self.assertEqual(settings.debug_authorization, True) + self.assertEqual(rootfactory, rootpolicy) + finally: + repoze.bfg.router.registry_manager = old_registry_manager + class DummyRegistryManager: def set(self, registry): pass @@ -516,7 +555,7 @@ def make_permission_factory(result): return 'permission' return DummyPermissionFactory -def make_rootpolicy(root): +def make_rootfactory(root): def rootpolicy(environ): return root return rootpolicy diff --git a/repoze/bfg/tests/test_settings.py b/repoze/bfg/tests/test_settings.py new file mode 100644 index 000000000..1d1eb08ea --- /dev/null +++ b/repoze/bfg/tests/test_settings.py @@ -0,0 +1,121 @@ +import unittest + +class TestSettings(unittest.TestCase): + def _getTargetClass(self): + from repoze.bfg.settings import Settings + return Settings + + def _makeOne(self, **options): + klass = self._getTargetClass() + return klass(options) + + def test_no_options(self): + settings = self._makeOne() + self.assertEqual(settings.reload_templates, False) + self.assertEqual(settings.debug_notfound, False) + self.assertEqual(settings.debug_authorization, False) + self.assertEqual(settings.unicode_path_segments, True) + + def test_with_option(self): + settings = self._makeOne(reload_templates=True) + self.assertEqual(settings.reload_templates, True) + self.assertEqual(settings.debug_notfound, False) + self.assertEqual(settings.debug_authorization, False) + self.assertEqual(settings.unicode_path_segments, True) + +class TestGetOptions(unittest.TestCase): + def _getFUT(self): + from repoze.bfg.settings import get_options + return get_options + + def test_reload_templates(self): + get_options = self._getFUT() + result = get_options({}) + self.assertEqual(result['reload_templates'], False) + result = get_options({'reload_templates':'false'}) + self.assertEqual(result['reload_templates'], False) + result = get_options({'reload_templates':'t'}) + self.assertEqual(result['reload_templates'], True) + result = get_options({'reload_templates':'1'}) + self.assertEqual(result['reload_templates'], True) + result = get_options({}, {'BFG_RELOAD_TEMPLATES':'1'}) + self.assertEqual(result['reload_templates'], True) + result = get_options({'reload_templates':'false'}, + {'BFG_RELOAD_TEMPLATES':'1'}) + self.assertEqual(result['reload_templates'], True) + + def test_debug_authorization(self): + get_options = self._getFUT() + result = get_options({}) + self.assertEqual(result['debug_authorization'], False) + result = get_options({'debug_authorization':'false'}) + self.assertEqual(result['debug_authorization'], False) + result = get_options({'debug_authorization':'t'}) + self.assertEqual(result['debug_authorization'], True) + result = get_options({'debug_authorization':'1'}) + self.assertEqual(result['debug_authorization'], True) + result = get_options({}, {'BFG_DEBUG_AUTHORIZATION':'1'}) + self.assertEqual(result['debug_authorization'], True) + result = get_options({'debug_authorization':'false'}, + {'BFG_DEBUG_AUTHORIZATION':'1'}) + self.assertEqual(result['debug_authorization'], True) + + def test_debug_notfound(self): + get_options = self._getFUT() + result = get_options({}) + self.assertEqual(result['debug_notfound'], False) + result = get_options({'debug_notfound':'false'}) + self.assertEqual(result['debug_notfound'], False) + result = get_options({'debug_notfound':'t'}) + self.assertEqual(result['debug_notfound'], True) + result = get_options({'debug_notfound':'1'}) + self.assertEqual(result['debug_notfound'], True) + result = get_options({}, {'BFG_DEBUG_NOTFOUND':'1'}) + self.assertEqual(result['debug_notfound'], True) + result = get_options({'debug_notfound':'false'}, + {'BFG_DEBUG_NOTFOUND':'1'}) + self.assertEqual(result['debug_notfound'], True) + + def test_debug_all(self): + get_options = self._getFUT() + result = get_options({}) + self.assertEqual(result['debug_notfound'], False) + self.assertEqual(result['debug_authorization'], False) + result = get_options({'debug_all':'false'}) + self.assertEqual(result['debug_notfound'], False) + self.assertEqual(result['debug_authorization'], False) + result = get_options({'debug_all':'t'}) + self.assertEqual(result['debug_notfound'], True) + self.assertEqual(result['debug_authorization'], True) + result = get_options({'debug_all':'1'}) + self.assertEqual(result['debug_notfound'], True) + self.assertEqual(result['debug_authorization'], True) + result = get_options({}, {'BFG_DEBUG_ALL':'1'}) + self.assertEqual(result['debug_notfound'], True) + self.assertEqual(result['debug_authorization'], True) + result = get_options({'debug_all':'false'}, + {'BFG_DEBUG_ALL':'1'}) + self.assertEqual(result['debug_notfound'], True) + self.assertEqual(result['debug_authorization'], True) + + def test_unicode_path_segments(self): + get_options = self._getFUT() + result = get_options({}) + self.assertEqual(result['unicode_path_segments'], True) + result = get_options({'unicode_path_segments':'false'}) + self.assertEqual(result['unicode_path_segments'], False) + result = get_options({'unicode_path_segments':'t'}) + self.assertEqual(result['unicode_path_segments'], True) + result = get_options({'unicode_path_segments':'1'}) + self.assertEqual(result['unicode_path_segments'], True) + result = get_options({}, {'BFG_UNICODE_PATH_SEGMENTS':'1'}) + self.assertEqual(result['unicode_path_segments'], True) + result = get_options({'unicode_path_segments':'false'}, + {'BFG_UNICODE_PATH_SEGMENTS':'1'}) + self.assertEqual(result['unicode_path_segments'], True) + + def test_originals_kept(self): + get_options = self._getFUT() + result = get_options({'a':'i am so a'}) + self.assertEqual(result['a'], 'i am so a') + diff --git a/repoze/bfg/tests/test_template.py b/repoze/bfg/tests/test_template.py index 31aa074d8..8d16972b8 100644 --- a/repoze/bfg/tests/test_template.py +++ b/repoze/bfg/tests/test_template.py @@ -1,18 +1,18 @@ import unittest -from zope.component.testing import PlacelessSetup +from zope.testing.cleanup import cleanUp -class Base(PlacelessSetup): +class Base(object): def setUp(self): - from zope.deprecation import __show__ - __show__.off() - PlacelessSetup.setUp(self) + cleanUp() + import warnings + warnings.simplefilter('ignore') def tearDown(self): - from zope.deprecation import __show__ - __show__.on() - PlacelessSetup.tearDown(self) - + cleanUp() + import warnings + warnings.resetwarnings() + def _zcmlConfigure(self): import repoze.bfg.includes import zope.configuration.xmlconfig @@ -24,42 +24,28 @@ class Base(PlacelessSetup): here = os.path.abspath(os.path.dirname(__file__)) return os.path.join(here, 'fixtures', name) -class RenderTemplateTests(unittest.TestCase, Base): - def setUp(self): - Base.setUp(self) - - def tearDown(self): - Base.tearDown(self) - - def _getFUT(self): +class RenderTemplateTests(Base, unittest.TestCase): + def _callFUT(self, *arg, **kw): from repoze.bfg.template import render_template - return render_template + return render_template(*arg, **kw) def test_it(self): self._zcmlConfigure() minimal = self._getTemplatePath('minimal.pt') - render = self._getFUT() - result = render(minimal) + result = self._callFUT(minimal) self.failUnless(isinstance(result, str)) self.assertEqual(result, '<div xmlns="http://www.w3.org/1999/xhtml">\n</div>') -class RenderTemplateToResponseTests(unittest.TestCase, Base): - def setUp(self): - Base.setUp(self) - - def tearDown(self): - Base.tearDown(self) - - def _getFUT(self): +class RenderTemplateToResponseTests(Base, unittest.TestCase): + def _callFUT(self, *arg, **kw): from repoze.bfg.template import render_template_to_response - return render_template_to_response + return render_template_to_response(*arg, **kw) def test_it(self): self._zcmlConfigure() minimal = self._getTemplatePath('minimal.pt') - render = self._getFUT() - result = render(minimal) + result = self._callFUT(minimal) from webob import Response self.failUnless(isinstance(result, Response)) self.assertEqual(result.app_iter, @@ -67,45 +53,37 @@ class RenderTemplateToResponseTests(unittest.TestCase, Base): self.assertEqual(result.status, '200 OK') self.assertEqual(len(result.headerlist), 2) -class GetTemplateTests(unittest.TestCase, Base): - def setUp(self): - Base.setUp(self) - - def tearDown(self): - Base.tearDown(self) - - def _getFUT(self): +class GetTemplateTests(Base, unittest.TestCase): + def _callFUT(self, *arg, **kw): from repoze.bfg.template import get_template - return get_template + return get_template(*arg, **kw) def test_nonabs_registered(self): self._zcmlConfigure() from zope.component import getGlobalSiteManager from zope.component import queryUtility from repoze.bfg.chameleon_zpt import ZPTTemplateFactory - from repoze.bfg.interfaces import ITemplate + from repoze.bfg.interfaces import ITemplateRenderer minimal = self._getTemplatePath('minimal.pt') utility = ZPTTemplateFactory(minimal) gsm = getGlobalSiteManager() - gsm.registerUtility(utility, ITemplate, name=minimal) - get = self._getFUT() - result = get(minimal) + gsm.registerUtility(utility, ITemplateRenderer, name=minimal) + result = self._callFUT(minimal) self.assertEqual(result.filename, minimal) - self.assertEqual(queryUtility(ITemplate, minimal), utility) + self.assertEqual(queryUtility(ITemplateRenderer, minimal), utility) def test_nonabs_unregistered(self): self._zcmlConfigure() from zope.component import getGlobalSiteManager from zope.component import queryUtility from repoze.bfg.chameleon_zpt import ZPTTemplateFactory - from repoze.bfg.interfaces import ITemplate + from repoze.bfg.interfaces import ITemplateRenderer minimal = self._getTemplatePath('minimal.pt') - self.assertEqual(queryUtility(ITemplate, minimal), None) + self.assertEqual(queryUtility(ITemplateRenderer, minimal), None) utility = ZPTTemplateFactory(minimal) gsm = getGlobalSiteManager() - gsm.registerUtility(utility, ITemplate, name=minimal) - get = self._getFUT() - result = get(minimal) + gsm.registerUtility(utility, ITemplateRenderer, name=minimal) + result = self._callFUT(minimal) self.assertEqual(result.filename, minimal) - self.assertEqual(queryUtility(ITemplate, minimal), utility) + self.assertEqual(queryUtility(ITemplateRenderer, minimal), utility) diff --git a/repoze/bfg/tests/test_traversal.py b/repoze/bfg/tests/test_traversal.py index dcb47e6ed..12c7d3741 100644 --- a/repoze/bfg/tests/test_traversal.py +++ b/repoze/bfg/tests/test_traversal.py @@ -292,6 +292,24 @@ class FindModelTests(unittest.TestCase): self.assertRaises(KeyError, self._callFUT, baz, '/') self.assertEqual(dummy.wascontext, True) + def test_unicode_pathinfo_converted_to_utf8(self): + la = unicode('LaPe\xc3\xb1a', 'utf-8') + + dummy = DummyContext() + dummy.__parent__ = None + dummy.__name__ = None + baz = DummyContext() + baz.__parent__ = dummy + baz.__name__ = la + + traverser = make_traverser(baz, '', []) + self._registerTraverserFactory(traverser) + path = '/' + la + result = self._callFUT(baz, path) + self.assertEqual(result, baz) + self.assertEqual(dummy.wascontext, True) + self.assertEqual(dummy.environ['PATH_INFO'], path.encode('utf-8')) + class ModelPathTests(unittest.TestCase): def _callFUT(self, model, *elements): from repoze.bfg.traversal import model_path @@ -335,8 +353,10 @@ class ModelPathTests(unittest.TestCase): def make_traverser(*args): class DummyTraverser(object): def __init__(self, context): + self.context = context context.wascontext = True def __call__(self, environ): + self.context.environ = environ return args return DummyTraverser diff --git a/repoze/bfg/traversal.py b/repoze/bfg/traversal.py index a89518eaa..5960663c8 100644 --- a/repoze/bfg/traversal.py +++ b/repoze/bfg/traversal.py @@ -111,7 +111,13 @@ def find_model(model, path): if path.startswith('/'): model = find_root(model) - + + if path.__class__ is unicode: + # the traverser factory expects PATH_INFO to be a string, + # not unicode (it's the same traverser which accepts PATH_INFO + # from user agents; user agents always send strings). + path = path.encode('utf-8') + ob, name, path = ITraverserFactory(model)({'PATH_INFO':path}) if name: raise KeyError('%r has no subelement %s' % (ob, name)) |
