diff options
| -rw-r--r-- | CHANGES.txt | 37 | ||||
| -rw-r--r-- | repoze/bfg/chameleon_text.py | 15 | ||||
| -rw-r--r-- | repoze/bfg/chameleon_zpt.py | 20 | ||||
| -rw-r--r-- | repoze/bfg/configuration.py | 104 | ||||
| -rw-r--r-- | repoze/bfg/renderers.py | 301 | ||||
| -rw-r--r-- | repoze/bfg/resource.py | 2 | ||||
| -rw-r--r-- | repoze/bfg/testing.py | 2 | ||||
| -rw-r--r-- | repoze/bfg/tests/test_configuration.py | 67 | ||||
| -rw-r--r-- | repoze/bfg/tests/test_renderers.py | 227 | ||||
| -rw-r--r-- | repoze/bfg/tests/test_resource.py | 10 | ||||
| -rw-r--r-- | repoze/bfg/tests/test_testing.py | 4 |
11 files changed, 443 insertions, 346 deletions
diff --git a/CHANGES.txt b/CHANGES.txt index 283ae3db6..3e57e0c62 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -33,9 +33,46 @@ Features ``relative_spec`` is not a string, the value is returned unconditionally without any resolution attempted. +Backwards Incompatibilities +--------------------------- + +- The functions in ``repoze.bfg.renderers`` named ``render`` and + ``render_to_response`` introduced in 1.3a6 previously took a set of + ``**values`` arguments for the values to be passed to the renderer. + This was wrong, as renderers don't need to accept only dictionaries + (they can accept any type of object). Now, the value sent to the + renderer must be supplied as a positional argument named ``value``. + The ``request`` argument is still a keyword argument, however. + +- The functions in ``repoze.bfg.renderers`` named ``render`` and + ``render_to_response`` now accept an additonal keyword argument + named ``package``. + +- The ``get_renderer`` API in ``repoze.bfg.renderers`` now accepts a + ``package`` argument. + Internal -------- +- The ``repoze.bfg.res08rce.resolve_resource_spec`` function can now + accept a package object as its ``pname`` argument instead of just a + package name. + +- The ``_renderer_factory_from_name`` and ``_renderer_from_name`` + methods of the Configurator were removed. These were never APIs. + +- The ``_render``, ``_render_to_response`` and ``_make_response`` + functions with ``repoze.bfg.render`` (added in 1.3a6) have been + removed. + +- A new helper class ``repoze.bfg.renderers.RendererHelper`` was + added. + +- The _map_view function of ``repoze.bfg.configuration`` now takes + only a renderer_name argument instead of both a ``renderer`` and + ``renderer``_name argument. It also takes a ``package`` argument + now. + - Use ``imp.get_suffixes`` indirection in ``repoze.bfg.path.package_name`` instead of hardcoded ``.py`` ``.pyc`` and ``.pyo`` to use for comparison when attemtping to diff --git a/repoze/bfg/chameleon_text.py b/repoze/bfg/chameleon_text.py index bbf15ead1..cdfda93f4 100644 --- a/repoze/bfg/chameleon_text.py +++ b/repoze/bfg/chameleon_text.py @@ -86,7 +86,8 @@ def get_renderer(path): :func:`repoze.bfg.renderers.get_renderer` instead. """ package = caller_package() - return renderers.renderer_from_name(path, package) + factory = renderers.RendererHelper(path, package=package) + return factory.get_renderer() def get_template(path): """ Return the underyling object representing a :term:`Chameleon` @@ -99,8 +100,8 @@ def get_template(path): :func:`repoze.bfg.renderers.get_renderer` instead. """ package = caller_package() - renderer = renderers.renderer_from_name(path, package) - return renderer.implementation() + factory = renderers.RendererHelper(path, package=package) + return factory.get_renderer().implementation() def render_template(path, **kw): """ Render a :term:`Chameleon` text template using the template @@ -114,7 +115,9 @@ def render_template(path, **kw): :func:`repoze.bfg.renderers.render` instead. """ package = caller_package() - return renderers._render(path, None, kw, {}, None, package) + request = kw.pop('request', None) + renderer = renderers.RendererHelper(path, package=package) + return renderer.render(kw, None, request=request) def render_template_to_response(path, **kw): """ Render a :term:`Chameleon` text template using the template @@ -129,4 +132,6 @@ def render_template_to_response(path, **kw): :func:`repoze.bfg.renderers.render_to_response` instead. """ package = caller_package() - return renderers._render_to_response(path, None, kw, {}, None, package) + request = kw.pop('request', None) + renderer = renderers.RendererHelper(path, package=package) + return renderer.render_to_response(kw, None, request=request) diff --git a/repoze/bfg/chameleon_zpt.py b/repoze/bfg/chameleon_zpt.py index 494db43d2..716ae4b85 100644 --- a/repoze/bfg/chameleon_zpt.py +++ b/repoze/bfg/chameleon_zpt.py @@ -64,15 +64,16 @@ def get_renderer(path): ``path`` argument. The ``path`` argument may be a package-relative path, an absolute path, or a :term:`resource specification`. - + .. warning:: This API is deprecated in :mod:`repoze.bfg` 1.3. Use :func:`repoze.bfg.renderers.get_renderer` instead. """ package = caller_package() - return renderers.renderer_from_name(path, package) + factory = renderers.RendererHelper(path, package=package) + return factory.get_renderer() def get_template(path): - """ Return the underlying object representing a :term:`Chameleon` + """ Return the underyling object representing a :term:`Chameleon` ZPT template using the template implied by the ``path`` argument. The ``path`` argument may be a package-relative path, an absolute path, or a :term:`resource specification`. @@ -82,8 +83,8 @@ def get_template(path): :func:`repoze.bfg.renderers.get_renderer` instead. """ package = caller_package() - renderer = renderers.renderer_from_name(path, package) - return renderer.implementation() + factory = renderers.RendererHelper(path, package=package) + return factory.get_renderer().implementation() def render_template(path, **kw): """ Render a :term:`Chameleon` ZPT template using the template @@ -97,7 +98,9 @@ def render_template(path, **kw): :func:`repoze.bfg.renderers.render` instead. """ package = caller_package() - return renderers._render(path, None, kw, {}, None, package) + request = kw.pop('request', None) + renderer = renderers.RendererHelper(path, package=package) + return renderer.render(kw, None, request=request) def render_template_to_response(path, **kw): """ Render a :term:`Chameleon` ZPT template using the template @@ -112,5 +115,6 @@ def render_template_to_response(path, **kw): :func:`repoze.bfg.renderers.render_to_response` instead. """ package = caller_package() - return renderers._render_to_response(path, None, kw, {}, None, package) - + request = kw.pop('request', None) + renderer = renderers.RendererHelper(path, package=package) + return renderer.render_to_response(kw, None, request=request) diff --git a/repoze/bfg/configuration.py b/repoze/bfg/configuration.py index 89d287f14..22e4ec1d8 100644 --- a/repoze/bfg/configuration.py +++ b/repoze/bfg/configuration.py @@ -45,7 +45,7 @@ from repoze.bfg.interfaces import IException from repoze.bfg import chameleon_text from repoze.bfg import chameleon_zpt from repoze.bfg import renderers -from repoze.bfg.renderers import _render_to_response +from repoze.bfg.renderers import RendererHelper from repoze.bfg.authorization import ACLAuthorizationPolicy from repoze.bfg.compat import all from repoze.bfg.compat import md5 @@ -206,32 +206,6 @@ class Configurator(object): self.registry.registerUtility(factory, IRootFactory) self.registry.registerUtility(factory, IDefaultRootFactory) # b/c - def _renderer_factory_from_name(self, path_or_spec): - if '.' in path_or_spec: - name = os.path.splitext(path_or_spec)[1] - spec = self._make_spec(path_or_spec) - else: - name = path_or_spec - spec = path_or_spec - - factory = self.registry.queryUtility(IRendererFactory, name=name) - return name, spec, factory - - def _renderer_from_name(self, path_or_spec): - if path_or_spec is None: - # check for global default renderer - factory = self.registry.queryUtility(IRendererFactory) - if factory is not None: - return factory(path_or_spec) - return None - - name, spec, factory = self._renderer_factory_from_name(path_or_spec) - if factory is None: - raise ValueError( - 'No factory for renderer named %r when looking up %s' % - (name, spec)) - return factory(spec) - def _set_authentication_policy(self, policy, _info=u''): """ Add a :mod:`repoze.bfg` :term:`authentication policy` to the current configuration.""" @@ -256,12 +230,12 @@ class Configurator(object): attr=None, renderer_name=None, wrapper_viewname=None, viewname=None, accept=None, order=MAX_ORDER, phash=DEFAULT_PHASH): - renderer = self._renderer_from_name(renderer_name) authn_policy = self.registry.queryUtility(IAuthenticationPolicy) authz_policy = self.registry.queryUtility(IAuthorizationPolicy) settings = self.registry.queryUtility(ISettings) logger = self.registry.queryUtility(IDebugLogger) - mapped_view = _map_view(view, attr, renderer, renderer_name) + mapped_view = _map_view(view, attr, renderer_name, self.registry, + self.package) owrapped_view = _owrap_view(mapped_view, viewname, wrapper_viewname) secured_view = _secure_view(owrapped_view, permission, authn_policy, authz_policy) @@ -1819,15 +1793,17 @@ class Configurator(object): and purpose in previous releases).. """ from repoze.bfg.testing import DummyRendererFactory - name, spec, factory = self._renderer_factory_from_name(path) - if factory is None or not isinstance(factory, DummyRendererFactory): - factory = DummyRendererFactory(name, factory) - self.registry.registerUtility(factory, IRendererFactory, name=name) + helper = RendererHelper(path, registry=self.registry) + factory = helper.factory + if not isinstance(factory, DummyRendererFactory): + factory = DummyRendererFactory(helper.renderer_type, helper.factory) + self.registry.registerUtility(factory, IRendererFactory, + name=helper.renderer_type) from repoze.bfg.testing import DummyTemplateRenderer if renderer is None: renderer = DummyTemplateRenderer() - factory.add(spec, renderer) + factory.add(helper.renderer_name, renderer) return renderer testing_add_template = testing_add_renderer @@ -2145,9 +2121,15 @@ def is_response(ob): return True return False -def _map_view(view, attr=None, renderer=None, renderer_name=None): +def _map_view(view, attr=None, renderer_name=None, registry=None, package=None): wrapped_view = view + helper = None + if renderer_name: + helper = RendererHelper(renderer_name, + registry=registry, + package=package) + if inspect.isclass(view): # If the object we've located is a class, turn it into a # function that operates like a Zope view (when it's invoked, @@ -2164,16 +2146,12 @@ def _map_view(view, attr=None, renderer=None, renderer_name=None): response = inst() else: response = getattr(inst, attr)() - if renderer is not None: + if helper is not None: if not is_response(response): system = {'view':inst, 'renderer_name':renderer_name, 'context':context, 'request':request} - response = _render_to_response(renderer_name, - request, - response, - system, - renderer, - None) + response = helper.render_to_response(response, system, + request=request) return response wrapped_view = _bfg_class_requestonly_view else: @@ -2184,16 +2162,12 @@ def _map_view(view, attr=None, renderer=None, renderer_name=None): response = inst() else: response = getattr(inst, attr)() - if renderer is not None: + if helper is not None: if not is_response(response): system = {'view':inst, 'renderer_name':renderer_name, 'context':context, 'request':request} - response = _render_to_response(renderer_name, - request, - response, - system, - renderer, - None) + response = helper.render_to_response(response, system, + request=request) return response wrapped_view = _bfg_class_view @@ -2206,47 +2180,35 @@ def _map_view(view, attr=None, renderer=None, renderer_name=None): else: response = getattr(view, attr)(request) - if renderer is not None: + if helper is not None: if not is_response(response): system = {'view':view, 'renderer_name':renderer_name, 'context':context, 'request':request} - response = _render_to_response(renderer_name, - request, - response, - system, - renderer, - None) + response = helper.render_to_response(response, system, + request=request) return response wrapped_view = _bfg_requestonly_view elif attr: def _bfg_attr_view(context, request): response = getattr(view, attr)(context, request) - if renderer is not None: + if helper is not None: if not is_response(response): system = {'view':view, 'renderer_name':renderer_name, 'context':context, 'request':request} - response = _render_to_response(renderer_name, - request, - response, - system, - renderer, - None) + response = helper.render_to_response(response, system, + request=request) return response wrapped_view = _bfg_attr_view - elif renderer is not None: + elif helper is not None: def _rendered_view(context, request): response = view(context, request) if not is_response(response): system = {'view':view, 'renderer_name':renderer_name, - 'context':context, 'request':request} - response = _render_to_response(renderer_name, - request, - response, - system, - renderer, - None) + 'context':context, 'request':request} + response = helper.render_to_response(response, system, + request=request) return response wrapped_view = _rendered_view diff --git a/repoze/bfg/renderers.py b/repoze/bfg/renderers.py index 645284216..895debe2c 100644 --- a/repoze/bfg/renderers.py +++ b/repoze/bfg/renderers.py @@ -6,6 +6,7 @@ from webob import Response from zope.deprecation import deprecated from repoze.bfg.interfaces import IRendererGlobalsFactory +from repoze.bfg.interfaces import IRendererFactory from repoze.bfg.interfaces import IResponseFactory from repoze.bfg.interfaces import ITemplateRenderer @@ -13,77 +14,116 @@ from repoze.bfg.compat import json from repoze.bfg.path import caller_package from repoze.bfg.settings import get_settings from repoze.bfg.threadlocal import get_current_registry +from repoze.bfg.resource import resolve_resource_spec +from repoze.bfg.decorator import reify # API -def render(_renderer_name, **values): +def render(renderer_name, value, request=None, package=None): """ Using the renderer specified as ``renderer_name`` (a template - or a static renderer) render the set of values present in - ``**values``. Return the result of the renderer's ``__call__`` + or a static renderer) render the value (or set of values) present + in ``value``. Return the result of the renderer's ``__call__`` method (usually a string or Unicode). If the renderer name refers to a file on disk (such as when the renderer is a template), it's usually best to supply the name as a - :term:`resource specification`. You may supply a relative - filename as renderer name; it will be converted to a resource - specification by combining the package name of the *caller* of - this function with the relative filename. - - The ``values`` provided will be supplied as top-level names to the - renderer. These will be augmented by a basic set of top-level - system names, such as ``request``, ``context``, and - ``renderer_name` unless any of these names is already provided - within ``*values``. If :term:`renderer globals` have been + :term:`resource specification`. + + You may supply a relative resource spec as ``renderer_name``. If + the ``package`` argument is supplied, a relative renderer name + will be converted to an absolute resource specification by + combining the package supplied as ``package`` with the relative + resource specification supplied as ``renderer_name``. If you do + not supply a ``package`` (or ``package`` is ``None``) the package + name of the *caller* of this function will be used as the package. + + The ``value`` provided will be supplied as the input to the + renderer. Usually, for template renderings, this should be a + dictionary. For other renderers, this will need to be whatever + sort of value the renderer expects. + + The 'system' values supplied to the renderer will include a basic + set of top-level system names, such as ``request``, ``context``, + and ``renderer_name`. If :term:`renderer globals` have been specified, these will also be used to agument the value. - Supply a ``request`` parameter containing the current - :mod:`repoze.bfg` request as part of ``**values`` in order to - provide the renderer with the most correct 'system' values - (``request`` and ``context`` in particular). + Supply a ``request`` parameter in order to provide the renderer + with the most correct 'system' values (``request`` and ``context`` + in particular). .. note:: This API is new in :mod:`repoze.bfg` 1.3. """ - package = caller_package() - request = values.pop('request', None) - return _render(_renderer_name, request, values, None, None, package) + try: + registry = request.registry + except AttributeError: + registry = None + if package is None: + package = caller_package() + renderer = RendererHelper(renderer_name, package=package, registry=registry) + return renderer.render(value, None, request=request) -def render_to_response(_renderer_name, **values): +def render_to_response(renderer_name, value, request=None, package=None): """ Using the renderer specified as ``renderer_name`` (a template - or a static renderer) render the set of values present in - ``**values``. Return a :term:`Response` object wrapping the result - of of the renderer's ``__call__`` method. + or a static renderer) render the value (or set of values) using + the result of the renderer's ``__call__`` method (usually a string + or Unicode) as the response body. If the renderer name refers to a file on disk (such as when the renderer is a template), it's usually best to supply the name as a - :term:`resource specification`. You may supply a relative - filename as renderer name; it will be converted to a resource - specification by combining the package name of the *caller* of - this function with the relative filename. - - The ``values`` provided will be supplied as top-level names to the - renderer. These will be augmented by a basic set of top-level - system names, such as ``request``, ``context``, and - ``renderer_name`` unless any of these names is already provided - within ``*values``. If :term:`renderer globals` have been + :term:`resource specification`. + + You may supply a relative resource spec as ``renderer_name``. If + the ``package`` argument is supplied, a relative renderer name + will be converted to an absolute resource specification by + combining the package supplied as ``package`` with the relative + resource specification supplied as ``renderer_name``. If you do + not supply a ``package`` (or ``package`` is ``None``) the package + name of the *caller* of this function will be used as the package. + + The ``value`` provided will be supplied as the input to the + renderer. Usually, for template renderings, this should be a + dictionary. For other renderers, this will need to be whatever + sort of value the renderer expects. + + The 'system' values supplied to the renderer will include a basic + set of top-level system names, such as ``request``, ``context``, + and ``renderer_name`. If :term:`renderer globals` have been specified, these will also be used to agument the value. - Supply a ``request`` parameter containing the current - :mod:`repoze.bfg` request as part of ``**values`` in order to - provide the renderer with the most correct 'system' values - (``request`` and ``context`` in particular). + Supply a ``request`` parameter in order to provide the renderer + with the most correct 'system' values (``request`` and ``context`` + in particular). .. note:: This API is new in :mod:`repoze.bfg` 1.3. + + """ + try: + registry = request.registry + except AttributeError: + registry = None + if package is None: + package = caller_package() + renderer = RendererHelper(renderer_name, package=package, registry=registry) + return renderer.render_to_response(value, None, request=request) + +def get_renderer(renderer_name, package=None): + """ Return the renderer object for the renderer named as + ``renderer_name``. + + You may supply a relative resource spec as ``renderer_name``. If + the ``package`` argument is supplied, a relative renderer name + will be converted to an absolute resource specification by + combining the package supplied as ``package`` with the relative + resource specification supplied as ``renderer_name``. If you do + not supply a ``package`` (or ``package`` is ``None``) the package + name of the *caller* of this function will be used as the package. """ - package = caller_package() - request = values.pop('request', None) - return _render_to_response(_renderer_name, request, values, None, None, - package) + if package is None: + package = caller_package() + renderer = RendererHelper(renderer_name, package=package) + return renderer.get_renderer() -def get_renderer(spec): - """ Return the renderer object for the renderer named as ``spec`` """ - package = caller_package() - return renderer_from_name(spec, package) # concrete renderer factory implementations (also API) @@ -146,45 +186,7 @@ def _reload_resources(): return settings and settings.get('reload_resources') def renderer_from_name(path, package=None): - from repoze.bfg.configuration import Configurator - reg = get_current_registry() - config = Configurator(reg, package=package) - return config._renderer_from_name(path) - -def _render(renderer_name, request, values, system_values, renderer, package): - try: - registry = request.registry - except AttributeError: - registry = get_current_registry() - - if renderer is None: - from repoze.bfg.configuration import Configurator - config = Configurator(registry, package=package) - renderer = config._renderer_from_name(renderer_name) - - if system_values is None: - system_values = { - 'view':None, - 'renderer_name':renderer_name, - 'context':getattr(request, 'context', None), - 'request':request, - } - - globals_factory = registry.queryUtility(IRendererGlobalsFactory) - - if globals_factory is not None: - renderer_globals = globals_factory(system_values) - if renderer_globals: - system_values.update(renderer_globals) - - result = renderer(values, system_values) - return result - -def _render_to_response(renderer_name, request, values, system_values, - renderer, package): - result = _render(renderer_name, request, values, system_values, renderer, - package) - return _make_response(request, result) + return RendererHelper(path, package=package).get_renderer() def rendered_response(renderer, result, view, context, request, renderer_name): # XXX: deprecated, left here only to not break old code; use @@ -196,8 +198,9 @@ def rendered_response(renderer, result, view, context, request, renderer_name): system = {'view':view, 'renderer_name':renderer_name, 'context':context, 'request':request} - return _render_to_response(renderer_name, request, result, system, renderer, - None) + helper = RendererHelper(renderer_name) + helper.renderer = renderer + return helper.render_to_response(result, system, request=request) deprecated('rendered_response', "('repoze.bfg.renderers.rendered_response' is not a public API; it is " @@ -205,35 +208,97 @@ deprecated('rendered_response', "use repoze.bfg.renderers.render_to_response instead')", ) -def _make_response(request, result): - try: - registry = request.registry - except AttributeError: - registry = get_current_registry() - - response_factory = registry.queryUtility(IResponseFactory, - default=Response) - - response = response_factory(result) - - if request is not None: - attrs = request.__dict__ - content_type = attrs.get('response_content_type', None) - if content_type is not None: - response.content_type = content_type - headerlist = attrs.get('response_headerlist', None) - if headerlist is not None: - for k, v in headerlist: - response.headers.add(k, v) - status = attrs.get('response_status', None) - if status is not None: - response.status = status - charset = attrs.get('response_charset', None) - if charset is not None: - response.charset = charset - cache_for = attrs.get('response_cache_for', None) - if cache_for is not None: - response.cache_expires = cache_for - - return response +class RendererHelper(object): + def __init__(self, renderer_name, registry=None, package=None): + if registry is None: + registry = get_current_registry() + self.registry = registry + self.package = package + if renderer_name is None: + factory = registry.queryUtility(IRendererFactory) + renderer_type = None + else: + if '.' in renderer_name: + renderer_type = os.path.splitext(renderer_name)[1] + renderer_name = self.resolve_spec(renderer_name) + else: + renderer_type = renderer_name + renderer_name = renderer_name + factory = registry.queryUtility(IRendererFactory, + name=renderer_type) + self.renderer_name = renderer_name + self.renderer_type = renderer_type + self.factory = factory + + @reify + def renderer(self): + if self.factory is None: + raise ValueError('No such renderer factory %s' % self.renderer_type) + return self.factory(self.renderer_name) + + def resolve_spec(self, path_or_spec): + if path_or_spec is None: + return path_or_spec + + package, filename = resolve_resource_spec(path_or_spec, + self.package) + if package is None: + return filename # absolute filename + return '%s:%s' % (package, filename) + + def get_renderer(self): + return self.renderer + + def render(self, value, system_values, request=None): + renderer = self.renderer + if system_values is None: + system_values = { + 'view':None, + 'renderer_name':self.renderer_name, + 'context':getattr(request, 'context', None), + 'request':request, + } + + registry = self.registry + globals_factory = registry.queryUtility(IRendererGlobalsFactory) + + if globals_factory is not None: + renderer_globals = globals_factory(system_values) + if renderer_globals: + system_values.update(renderer_globals) + + result = renderer(value, system_values) + return result + + def render_to_response(self, value, system_values, request=None): + result = self.render(value, system_values, request=request) + return self._make_response(result, request) + + def _make_response(self, result, request): + registry = self.registry + response_factory = registry.queryUtility(IResponseFactory, + default=Response) + + response = response_factory(result) + + if request is not None: + attrs = request.__dict__ + content_type = attrs.get('response_content_type', None) + if content_type is not None: + response.content_type = content_type + headerlist = attrs.get('response_headerlist', None) + if headerlist is not None: + for k, v in headerlist: + response.headers.add(k, v) + status = attrs.get('response_status', None) + if status is not None: + response.status = status + charset = attrs.get('response_charset', None) + if charset is not None: + response.charset = charset + cache_for = attrs.get('response_cache_for', None) + if cache_for is not None: + response.cache_expires = cache_for + + return response diff --git a/repoze/bfg/resource.py b/repoze/bfg/resource.py index 4d8cff197..da49f16ec 100644 --- a/repoze/bfg/resource.py +++ b/repoze/bfg/resource.py @@ -174,6 +174,8 @@ class FileOverride: return self.package, self.prefix def resolve_resource_spec(spec, pname='__main__'): + if pname and not isinstance(pname, basestring): + pname = pname.__name__ # as package if os.path.isabs(spec): return None, spec filename = spec diff --git a/repoze/bfg/testing.py b/repoze/bfg/testing.py index 0d79b559c..d5ae7bd56 100644 --- a/repoze/bfg/testing.py +++ b/repoze/bfg/testing.py @@ -767,7 +767,7 @@ def cleanUp(*arg, **kw): class DummyRendererFactory(object): """ Registered by - ``repoze.bfg.configuration.Configurator.testing_add_template`` as + ``repoze.bfg.configuration.Configurator.testing_add_renderer`` as a dummy renderer factory. The indecision about what to use as a key (a spec vs. a relative name) is caused by test suites in the wild believing they can register either. The ``factory`` argument diff --git a/repoze/bfg/tests/test_configuration.py b/repoze/bfg/tests/test_configuration.py index 58a4a2eda..159429a06 100644 --- a/repoze/bfg/tests/test_configuration.py +++ b/repoze/bfg/tests/test_configuration.py @@ -1989,14 +1989,6 @@ class ConfiguratorTests(unittest.TestCase): self.assertEqual(config.registry.getUtility(ITranslationDirectories), [locale]) - def test__renderer_from_name_default_renderer(self): - from repoze.bfg.interfaces import IRendererFactory - config = self._makeOne() - factory = lambda *arg: 'OK' - config.registry.registerUtility(factory, IRendererFactory) - result = config._renderer_from_name(None) - self.assertEqual(result, 'OK') - def test_derive_view_function(self): def view(request): return 'OK' @@ -2571,7 +2563,8 @@ class ConfiguratorTests(unittest.TestCase): # must provide request to pass in registry (this is a functest) request = DummyRequest() request.registry = config.registry - render_to_response('templates/foo.pt', foo=1, bar=2, request=request) + render_to_response( + 'templates/foo.pt', {'foo':1, 'bar':2}, request=request) renderer.assert_(foo=1) renderer.assert_(bar=2) renderer.assert_(request=request) @@ -2589,7 +2582,7 @@ class ConfiguratorTests(unittest.TestCase): request.registry = config.registry try: render_to_response( - 'templates/foo.pt', foo=1, bar=2, request=request) + 'templates/foo.pt', {'foo':1, 'bar':2}, request=request) except E: pass else: # pragma: no cover @@ -2604,7 +2597,8 @@ class ConfiguratorTests(unittest.TestCase): # must provide request to pass in registry (this is a functest) request = DummyRequest() request.registry = config.registry - render_to_response('templates/foo.pt', foo=1, bar=2, request=request) + render_to_response('templates/foo.pt', dict(foo=1, bar=2), + request=request) renderer.assert_(foo=1) renderer.assert_(bar=2) renderer.assert_(request=request) @@ -2613,22 +2607,25 @@ class Test__map_view(unittest.TestCase): def setUp(self): from repoze.bfg.registry import Registry self.registry = Registry() + testing.setUp(registry=self.registry) def tearDown(self): del self.registry + testing.tearDown() - def _registerRenderer(self, name='.txt'): + def _registerRenderer(self, typ='.txt'): from repoze.bfg.interfaces import IRendererFactory from repoze.bfg.interfaces import ITemplateRenderer from zope.interface import implements class Renderer: implements(ITemplateRenderer) + spec = 'abc' + typ def __init__(self, path): self.__class__.path = path def __call__(self, *arg): return 'Hello!' - self.registry.registerUtility(Renderer, IRendererFactory, name=name) - return Renderer(name) + self.registry.registerUtility(Renderer, IRendererFactory, name=typ) + return Renderer def _makeRequest(self): request = DummyRequest() @@ -2656,7 +2653,8 @@ class Test__map_view(unittest.TestCase): def test__map_view_as_function_with_attr_and_renderer(self): renderer = self._registerRenderer() view = lambda *arg: 'OK' - result = self._callFUT(view, attr='__name__', renderer=renderer) + result = self._callFUT(view, attr='__name__', + renderer_name=renderer.spec) self.failIf(result is view) self.assertRaises(TypeError, result, None, None) @@ -2714,7 +2712,7 @@ class Test__map_view(unittest.TestCase): pass def index(self): return {'a':'1'} - result = self._callFUT(view, attr='index', renderer = renderer) + result = self._callFUT(view, attr='index', renderer_name=renderer.spec) self.failIf(result is view) self.assertEqual(view.__module__, result.__module__) self.assertEqual(view.__doc__, result.__doc__) @@ -2755,7 +2753,7 @@ class Test__map_view(unittest.TestCase): pass def index(self): return {'a':'1'} - result = self._callFUT(view, attr='index', renderer = renderer) + result = self._callFUT(view, attr='index', renderer_name=renderer.spec) self.failIf(result is view) self.assertEqual(view.__module__, result.__module__) self.assertEqual(view.__doc__, result.__doc__) @@ -2796,7 +2794,7 @@ class Test__map_view(unittest.TestCase): pass def index(self): return {'a':'1'} - result = self._callFUT(view, attr='index', renderer = renderer) + result = self._callFUT(view, attr='index', renderer_name=renderer.spec) self.failIf(result is view) self.assertEqual(view.__module__, result.__module__) self.assertEqual(view.__doc__, result.__doc__) @@ -2837,7 +2835,7 @@ class Test__map_view(unittest.TestCase): pass def index(self): return {'a':'1'} - result = self._callFUT(view, attr='index', renderer = renderer) + result = self._callFUT(view, attr='index', renderer_name=renderer.spec) self.failIf(result is view) self.assertEqual(view.__module__, result.__module__) self.assertEqual(view.__doc__, result.__doc__) @@ -2869,7 +2867,7 @@ class Test__map_view(unittest.TestCase): def index(self, context, request): return {'a':'1'} view = View() - result = self._callFUT(view, attr='index', renderer=renderer) + result = self._callFUT(view, attr='index', renderer_name=renderer.spec) self.failIf(result is view) request = self._makeRequest() self.assertEqual(result(None, request).body, 'Hello!') @@ -2904,7 +2902,7 @@ class Test__map_view(unittest.TestCase): def index(self, request): return {'a':'1'} view = View() - result = self._callFUT(view, attr='index', renderer = renderer) + result = self._callFUT(view, attr='index', renderer_name=renderer.spec) self.failIf(result is view) self.assertEqual(view.__module__, result.__module__) self.assertEqual(view.__doc__, result.__doc__) @@ -2916,12 +2914,37 @@ class Test__map_view(unittest.TestCase): renderer = self._registerRenderer() def view(context, request): return {'a':'1'} - result = self._callFUT(view, renderer=renderer) + result = self._callFUT(view, renderer_name=renderer.spec) + self.failIf(result is view) + self.assertEqual(view.__module__, result.__module__) + self.assertEqual(view.__doc__, result.__doc__) + request = self._makeRequest() + self.assertEqual(result(None, request).body, 'Hello!') + + def test__map_view_with_registry(self): + renderer = self._registerRenderer() + def view(context, request): + return {'a':'1'} + result = self._callFUT(view, renderer_name=renderer.spec, + registry=self.registry) + self.failIf(result is view) + self.assertEqual(view.__module__, result.__module__) + self.assertEqual(view.__doc__, result.__doc__) + request = self._makeRequest() + self.assertEqual(result(None, request).body, 'Hello!') + + def test__map_view_with_package(self): + renderer = self._registerRenderer() + def view(context, request): + return {'a':'1'} + result = self._callFUT(view, renderer_name=renderer.spec, + package='repoze.bfg') self.failIf(result is view) self.assertEqual(view.__module__, result.__module__) self.assertEqual(view.__doc__, result.__doc__) request = self._makeRequest() self.assertEqual(result(None, request).body, 'Hello!') + self.assertEqual(renderer.path, 'repoze.bfg:abc.txt') class Test_decorate_view(unittest.TestCase): def _callFUT(self, wrapped, original): diff --git a/repoze/bfg/tests/test_renderers.py b/repoze/bfg/tests/test_renderers.py index 8a8a578eb..264b4a547 100644 --- a/repoze/bfg/tests/test_renderers.py +++ b/repoze/bfg/tests/test_renderers.py @@ -243,30 +243,106 @@ class Test_rendered_response(unittest.TestCase): result = self._callFUT(renderer, response) self.assertEqual(result.body, 'Hello!') -class Test__make_response(unittest.TestCase): + +class TestRendererHelper(unittest.TestCase): def setUp(self): - self.config = testing.setUp() + self.config = cleanUp() def tearDown(self): - testing.tearDown() + cleanUp() + + def _makeOne(self, *arg, **kw): + from repoze.bfg.renderers import RendererHelper + return RendererHelper(*arg, **kw) + + def _registerRendererFactory(self): + from repoze.bfg.interfaces import IRendererFactory + def renderer(*arg): + def respond(*arg): + return arg + return respond + self.config.registry.registerUtility(renderer, IRendererFactory, + name='.foo') + return renderer - def _callFUT(self, request, result): - from repoze.bfg.renderers import _make_response - return _make_response(request, result) + def test_resolve_spec_path_is_None(self): + helper = self._makeOne('loo.foo') + result = helper.resolve_spec(None) + self.assertEqual(result, None) - def test_with_content_type(self): + def test_resolve_spec_package_is_None(self): + helper = self._makeOne('loo.foo') + result = helper.resolve_spec('/foo/bar') + self.assertEqual(result, '/foo/bar') + + def test_resolve_spec_absolute(self): + helper = self._makeOne('loo.foo') + result = helper.resolve_spec('repoze.bfg:flub') + self.assertEqual(result, 'repoze.bfg:flub') + + def test_resolve_spec_relative(self): + helper = self._makeOne('loo.foo', package='repoze.bfg') + result = helper.resolve_spec('flub') + self.assertEqual(result, 'repoze.bfg:flub') + + def test_render_to_response(self): + self._registerRendererFactory() + request = Dummy() + helper = self._makeOne('loo.foo') + response = helper.render_to_response('values', 'system_values', + request=request) + self.assertEqual(response.body, ('values', 'system_values')) + + def test_render_explicit_registry(self): + factory = self._registerRendererFactory() + class DummyRegistry(object): + def __init__(self): + self.responses = [factory, lambda *arg: {}] + def queryUtility(self, iface, name=None): + self.queried = True + return self.responses.pop(0) + reg = DummyRegistry() + helper = self._makeOne('loo.foo', registry=reg) + result = helper.render('value', {}) + self.assertEqual(result, ('value', {})) + self.failUnless(reg.queried) + + def test_render_system_values_is_None(self): + self._registerRendererFactory() + request = Dummy() + context = Dummy() + request.context = context + helper = self._makeOne('loo.foo') + result = helper.render('values', None, request=request) + system = {'request':request, 'context':context, + 'renderer_name':'loo.foo', 'view':None} + self.assertEqual(result, ('values', system)) + + def test_render_renderer_globals_factory_active(self): + self._registerRendererFactory() + from repoze.bfg.interfaces import IRendererGlobalsFactory + def rg(system): + return {'a':1} + self.config.registry.registerUtility(rg, IRendererGlobalsFactory) + helper = self._makeOne('loo.foo') + result = helper.render('values', None) + self.assertEqual(result[1]['a'], 1) + + def test__make_response_with_content_type(self): request = testing.DummyRequest() attrs = {'response_content_type':'text/nonsense'} request.__dict__.update(attrs) - response = self._callFUT(request, 'abc') + helper = self._makeOne('loo.foo') + response = helper._make_response('abc', request) self.assertEqual(response.content_type, 'text/nonsense') self.assertEqual(response.body, 'abc') - def test_with_headerlist(self): + def test__make_response_with_headerlist(self): request = testing.DummyRequest() attrs = {'response_headerlist':[('a', '1'), ('b', '2')]} request.__dict__.update(attrs) - response = self._callFUT(request, 'abc') + helper = self._makeOne('loo.foo') + response = helper._make_response('abc', request) self.assertEqual(response.headerlist, [('Content-Type', 'text/html; charset=UTF-8'), ('Content-Length', '3'), @@ -274,26 +350,29 @@ class Test__make_response(unittest.TestCase): ('b', '2')]) self.assertEqual(response.body, 'abc') - def test_with_status(self): + def test__make_response_with_status(self): request = testing.DummyRequest() attrs = {'response_status':'406 You Lose'} request.__dict__.update(attrs) - response = self._callFUT(request, 'abc') + helper = self._makeOne('loo.foo') + response = helper._make_response('abc', request) self.assertEqual(response.status, '406 You Lose') self.assertEqual(response.body, 'abc') - def test_with_charset(self): + def test__make_response_with_charset(self): request = testing.DummyRequest() attrs = {'response_charset':'UTF-16'} request.__dict__.update(attrs) - response = self._callFUT(request, 'abc') + helper = self._makeOne('loo.foo') + response = helper._make_response('abc', request) self.assertEqual(response.charset, 'UTF-16') - def test_with_cache_for(self): + def test__make_response_with_cache_for(self): request = testing.DummyRequest() attrs = {'response_cache_for':100} request.__dict__.update(attrs) - response = self._callFUT(request, 'abc') + helper = self._makeOne('loo.foo') + response = helper._make_response('abc', request) self.assertEqual(response.cache_control.max_age, 100) def test_with_alternate_response_factory(self): @@ -303,111 +382,22 @@ class Test__make_response(unittest.TestCase): self.result = result self.config.registry.registerUtility(ResponseFactory, IResponseFactory) request = testing.DummyRequest() - response = self._callFUT(request, 'abc') + helper = self._makeOne('loo.foo') + response = helper._make_response('abc', request) self.assertEqual(response.__class__, ResponseFactory) self.assertEqual(response.result, 'abc') - def test_with_real_request(self): + def test__make_response_with_real_request(self): # functional from repoze.bfg.request import Request request = Request({}) attrs = {'response_status':'406 You Lose'} request.__dict__.update(attrs) - response = self._callFUT(request, 'abc') + helper = self._makeOne('loo.foo') + response = helper._make_response('abc', request) self.assertEqual(response.status, '406 You Lose') self.assertEqual(response.body, 'abc') -class Test__render(unittest.TestCase): - def setUp(self): - self.config = cleanUp() - - def tearDown(self): - cleanUp() - - def _callFUT(self, renderer_name, request, values, system_values, renderer, - package): - from repoze.bfg.renderers import _render - return _render(renderer_name, request, values, system_values, renderer, - package) - - def test_explicit_renderer(self): - def renderer(*arg): - return arg - result = self._callFUT( - 'name', 'request', 'values', 'system_values', renderer, None) - self.assertEqual(result, ('values', 'system_values')) - - def test_request_has_registry(self): - request = Dummy() - class DummyRegistry(object): - def queryUtility(self, iface): - self.queried = True - return None - reg = DummyRegistry() - request.registry = reg - def renderer(*arg): - return arg - result = self._callFUT( - 'name', request, 'values', 'system_values', renderer, None) - self.assertEqual(result, ('values', 'system_values')) - self.failUnless(reg.queried) - - def test_renderer_is_None(self): - from repoze.bfg.interfaces import IRendererFactory - def renderer(values, system): - return rf - def rf(spec): - return renderer - self.config.registry.registerUtility(rf, IRendererFactory, name='name') - result = self._callFUT( - 'name', 'request', 'values', 'system_values', None, None) - self.assertEqual(result, rf) - - def test_system_values_is_None(self): - def renderer(*arg): - return arg - request = Dummy() - context = Dummy() - request.context = context - result = self._callFUT( - 'name', request, 'values', None, renderer, None) - system = {'request':request, 'context':context, - 'renderer_name':'name', 'view':None} - self.assertEqual(result, ('values', system)) - - def test_renderer_globals_factory_active(self): - from repoze.bfg.interfaces import IRendererGlobalsFactory - def rg(system): - return {'a':1} - self.config.registry.registerUtility(rg, IRendererGlobalsFactory) - def renderer(*arg): - return arg - result = self._callFUT( - 'name', 'request', 'values', {'a':2}, renderer, None) - self.assertEqual(result, ('values', {'a':1})) - -class Test__render_to_response(unittest.TestCase): - def setUp(self): - self.config = cleanUp() - - def tearDown(self): - cleanUp() - - def _callFUT(self, renderer_name, request, values, system_values, renderer, - package): - from repoze.bfg.renderers import _render_to_response - return _render_to_response( - renderer_name, request, values, system_values, renderer, - package) - - def test_it(self): - def renderer(*arg): - return 'hello' - request = Dummy() - result = self._callFUT( - 'name', request, 'values', 'system_values', renderer, None) - self.assertEqual(result.body, 'hello') - class Test_render(unittest.TestCase): def setUp(self): self.config = testing.setUp() @@ -415,15 +405,15 @@ class Test_render(unittest.TestCase): def tearDown(self): testing.tearDown() - def _callFUT(self, renderer_name, **kw): + def _callFUT(self, renderer_name, value, request=None, package=None): from repoze.bfg.renderers import render - return render(renderer_name, **kw) + return render(renderer_name, value, request=request, package=package) def test_it_no_request(self): renderer = self.config.testing_add_renderer( 'repoze.bfg.tests:abc/def.pt') renderer.string_response = 'abc' - result = self._callFUT('abc/def.pt', a=1) + result = self._callFUT('abc/def.pt', dict(a=1)) self.assertEqual(result, 'abc') renderer.assert_(a=1) renderer.assert_(request=None) @@ -434,7 +424,7 @@ class Test_render(unittest.TestCase): renderer.string_response = 'abc' request = testing.DummyRequest() result = self._callFUT('abc/def.pt', - a=1, request=request) + dict(a=1), request=request) self.assertEqual(result, 'abc') renderer.assert_(a=1) renderer.assert_(request=request) @@ -446,15 +436,16 @@ class Test_render_to_response(unittest.TestCase): def tearDown(self): testing.tearDown() - def _callFUT(self, renderer_name, **kw): + def _callFUT(self, renderer_name, value, request=None, package=None): from repoze.bfg.renderers import render_to_response - return render_to_response(renderer_name, **kw) + return render_to_response(renderer_name, value, request=request, + package=package) def test_it_no_request(self): renderer = self.config.testing_add_renderer( 'repoze.bfg.tests:abc/def.pt') renderer.string_response = 'abc' - response = self._callFUT('abc/def.pt', a=1) + response = self._callFUT('abc/def.pt', dict(a=1)) self.assertEqual(response.body, 'abc') renderer.assert_(a=1) renderer.assert_(request=None) @@ -465,7 +456,7 @@ class Test_render_to_response(unittest.TestCase): renderer.string_response = 'abc' request = testing.DummyRequest() response = self._callFUT('abc/def.pt', - a=1, request=request) + dict(a=1), request=request) self.assertEqual(response.body, 'abc') renderer.assert_(a=1) renderer.assert_(request=request) diff --git a/repoze/bfg/tests/test_resource.py b/repoze/bfg/tests/test_resource.py index 39f883ba1..191d72c8b 100644 --- a/repoze/bfg/tests/test_resource.py +++ b/repoze/bfg/tests/test_resource.py @@ -373,7 +373,15 @@ class Test_resolve_resource_spec(unittest.TestCase): package_name, filename = self._callFUT(path, pkg) self.assertEqual(package_name, None) self.assertEqual(filename, 'test_resource.py') - + + def test_package_name_is_package_object(self): + import repoze.bfg.tests + pkg = repoze.bfg.tests + path = 'test_resource.py' + package_name, filename = self._callFUT(path, pkg) + self.assertEqual(package_name, 'repoze.bfg.tests') + self.assertEqual(filename, 'test_resource.py') + class TestFileOverride(unittest.TestCase): def _getTargetClass(self): diff --git a/repoze/bfg/tests/test_testing.py b/repoze/bfg/tests/test_testing.py index fc3bd7c9e..b24843e77 100644 --- a/repoze/bfg/tests/test_testing.py +++ b/repoze/bfg/tests/test_testing.py @@ -67,7 +67,7 @@ class Test_registerTemplateRenderer(TestBase): from repoze.bfg.testing import DummyTemplateRenderer self.failUnless(isinstance(renderer, DummyTemplateRenderer)) from repoze.bfg.renderers import render_to_response - render_to_response('templates/foo', foo=1, bar=2) + render_to_response('templates/foo', dict(foo=1, bar=2)) renderer.assert_(foo=1) renderer.assert_(bar=2) @@ -77,7 +77,7 @@ class Test_registerTemplateRenderer(TestBase): self.assertEqual(kw, {'foo':1, 'bar':2}) renderer = testing.registerTemplateRenderer('templates/foo', renderer) from repoze.bfg.renderers import render_to_response - render_to_response('templates/foo', foo=1, bar=2) + render_to_response('templates/foo', dict(foo=1, bar=2)) class Test_registerEventListener(TestBase): def test_registerEventListener_single(self): |
