From 15a3c6f561563eb53ff1cc3637fc6afa75da9e89 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Fri, 20 Nov 2009 05:38:38 +0000 Subject: Passable stab at supporting an imperative mode. ZCML directives which accept paths now register absolute paths, while imperative registrations now register resource specifications. --- CHANGES.txt | 6 ++++ repoze/bfg/chameleon_text.py | 4 +-- repoze/bfg/chameleon_zpt.py | 4 +-- repoze/bfg/configuration.py | 56 ++++++++++++++++++++------------ repoze/bfg/path.py | 2 -- repoze/bfg/renderers.py | 34 ++++++++------------ repoze/bfg/resource.py | 13 +++++--- repoze/bfg/router.py | 10 ++++-- repoze/bfg/tests/test_configuration.py | 59 +++++++--------------------------- repoze/bfg/tests/test_renderers.py | 47 +++++---------------------- repoze/bfg/tests/test_resource.py | 31 ++++++++++-------- repoze/bfg/tests/test_router.py | 18 ++++------- repoze/bfg/tests/test_zcml.py | 5 ++- repoze/bfg/view.py | 20 ++++++------ repoze/bfg/zcml.py | 34 ++++++++++++-------- 15 files changed, 153 insertions(+), 190 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 4adab96d4..ccda60d52 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -66,6 +66,12 @@ Internals - The ``repoze.bfg.zcml.Uncacheable`` class has been removed. +- The ``repoze.bfg.resource.resource_spec`` function has been removed. + +- All ZCML directives which deal with attributes which are paths now + use the ``path`` method of the ZCML context to resolve a relative + name to an absolute one (imperative configuration requirement). + Backwards Incompatibilites -------------------------- diff --git a/repoze/bfg/chameleon_text.py b/repoze/bfg/chameleon_text.py index d0d0ac25e..7e3ea17f4 100644 --- a/repoze/bfg/chameleon_text.py +++ b/repoze/bfg/chameleon_text.py @@ -22,8 +22,8 @@ class TextTemplateFile(TemplateFile): super(TextTemplateFile, self).__init__(filename, parser, format, doctype, **kwargs) -def renderer_factory(path, level=4): - return template_renderer_factory(path, TextTemplateRenderer, level=level) +def renderer_factory(path): + return template_renderer_factory(path, TextTemplateRenderer) class TextTemplateRenderer(object): implements(ITemplateRenderer) diff --git a/repoze/bfg/chameleon_zpt.py b/repoze/bfg/chameleon_zpt.py index 723527a03..090321204 100644 --- a/repoze/bfg/chameleon_zpt.py +++ b/repoze/bfg/chameleon_zpt.py @@ -11,8 +11,8 @@ from repoze.bfg.interfaces import ITemplateRenderer from repoze.bfg.renderers import template_renderer_factory from repoze.bfg.settings import get_settings -def renderer_factory(path, level=4): - return template_renderer_factory(path, ZPTTemplateRenderer, level=level) +def renderer_factory(path): + return template_renderer_factory(path, ZPTTemplateRenderer) class ZPTTemplateRenderer(object): implements(ITemplateRenderer) diff --git a/repoze/bfg/configuration.py b/repoze/bfg/configuration.py index 8a78db607..b272bee52 100644 --- a/repoze/bfg/configuration.py +++ b/repoze/bfg/configuration.py @@ -46,9 +46,11 @@ from repoze.bfg.events import WSGIApplicationCreatedEvent from repoze.bfg.exceptions import Forbidden from repoze.bfg.exceptions import NotFound from repoze.bfg.log import make_stream_logger +from repoze.bfg.path import caller_package from repoze.bfg.registry import Registry from repoze.bfg.request import route_request_iface from repoze.bfg.resource import PackageOverrides +from repoze.bfg.resource import resolve_resource_spec from repoze.bfg.settings import Settings from repoze.bfg.static import StaticRootFactory from repoze.bfg.threadlocal import get_current_registry @@ -64,6 +66,7 @@ import martian class Configurator(object): """ A wrapper around the registry that performs configuration tasks """ def __init__(self, registry=None): + self.package = caller_package() if registry is None: registry = self.make_default_registry() self.reg = registry @@ -102,7 +105,7 @@ class Configurator(object): manager.pop() return app - def declarative(self, root_factory, filename='configure.zcml', + def declarative(self, root_factory, spec='configure.zcml', settings=None, debug_logger=None, os=os, lock=threading.Lock()): @@ -113,23 +116,27 @@ class Configurator(object): settings = {} if not 'configure_zcml' in settings: - settings['configure_zcml'] = filename + settings['configure_zcml'] = spec settings = Settings(settings) - filename = settings['configure_zcml'] - - # not os.path.isabs below for windows systems - if (':' in filename) and (not os.path.isabs(filename)): - package, filename = filename.split(':', 1) - __import__(package) - package = sys.modules[package] + spec = settings['configure_zcml'] self.settings(settings) self.debug_logger(debug_logger) self.root_factory(root_factory or DefaultRootFactory) - self.load_zcml(filename, package, lock=lock) + self.load_zcml(spec, lock=lock) + + def make_spec(self, path_or_spec): + package, filename = resolve_resource_spec(path_or_spec, + self.package.__name__) + if package is None: + return filename # absolute filename + return '%s:%s' % (package, filename) + + def split_spec(self, path_or_spec): + return resolve_resource_spec(path_or_spec, self.package.__name__) - def load_zcml(self, filename, package=None, lock=threading.Lock()): + def load_zcml(self, spec, 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 @@ -143,8 +150,13 @@ class Configurator(object): # site manager API directly in a different thread while we hold the # lock. Those registrations will end up in our application's # registry. - if package is None: - package = sys.modules['__main__'] + package_name, filename = self.split_spec(spec) + if package_name is None: # absolute filename + package = None + else: + __import__(package_name) + package = sys.modules[package_name] + lock.acquire() manager.push({'registry':self.reg, 'request':None}) try: @@ -231,14 +243,17 @@ class Configurator(object): self.reg.registerAdapter(multiview, (for_, request_type), IMultiView, name, info=_info) - def renderer_from_name(self, path): - name = os.path.splitext(path)[1] - if not name: - name = path + def renderer_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.reg.queryUtility(IRendererFactory, name=name) if factory is None: raise ValueError('No renderer for renderer name %r' % name) - return factory(path) + return factory(spec) def derive_view(self, original_view, permission=None, predicates=(), attr=None, renderer_name=None, wrapper_viewname=None, @@ -581,9 +596,10 @@ class Configurator(object): self.reg.registerUtility(derived_view, iface, '', info=_info) def static(self, name, path, cache_max_age=3600, _info=u''): - view = static(path, cache_max_age=cache_max_age) + spec = self.make_spec(path) + view = static(spec, cache_max_age=cache_max_age) self.route(name, "%s*subpath" % name, view=view, - view_for=StaticRootFactory, factory=StaticRootFactory(path), + view_for=StaticRootFactory, factory=StaticRootFactory(spec), _info=_info) def settings(self, settings): diff --git a/repoze/bfg/path.py b/repoze/bfg/path.py index 11fbbcb0e..cdc0cd1ea 100644 --- a/repoze/bfg/path.py +++ b/repoze/bfg/path.py @@ -58,5 +58,3 @@ def package_path(package): return prefix - - diff --git a/repoze/bfg/renderers.py b/repoze/bfg/renderers.py index f13d1ccb4..e5ea4f3de 100644 --- a/repoze/bfg/renderers.py +++ b/repoze/bfg/renderers.py @@ -7,8 +7,6 @@ from zope.component import queryUtility from repoze.bfg.interfaces import ITemplateRenderer from repoze.bfg.compat import json -from repoze.bfg.path import caller_package -from repoze.bfg.resource import resource_spec from repoze.bfg.settings import get_settings # concrete renderer factory implementations @@ -27,37 +25,33 @@ def string_renderer_factory(name): # utility functions -def template_renderer_factory(path, impl, level=3): - if os.path.isabs(path): - # 'path' is an absolute filename (not common and largely only - # for backwards compatibility) - if not os.path.exists(path): - raise ValueError('Missing template file: %s' % path) - renderer = queryUtility(ITemplateRenderer, name=path) +def template_renderer_factory(spec, impl): + if os.path.isabs(spec): + # 'spec' is an absolute filename + if not os.path.exists(spec): + raise ValueError('Missing template file: %s' % spec) + renderer = queryUtility(ITemplateRenderer, name=spec) if renderer is None: - renderer = impl(path) + renderer = impl(spec) sm = getSiteManager() - sm.registerUtility(renderer, ITemplateRenderer, name=path) - + sm.registerUtility(renderer, ITemplateRenderer, name=spec) else: - # 'path' is a relative filename or a package:relpath spec - spec = resource_spec(path, caller_package(level=level).__name__) + # spec is a package:relpath resource spec renderer = queryUtility(ITemplateRenderer, name=spec) if renderer is None: # service unit tests by trying the relative path string as # the utility name directly - renderer = queryUtility(ITemplateRenderer, name=path) + renderer = queryUtility(ITemplateRenderer, name=spec) if renderer is None: - pkg, path = spec.split(':', 1) - if not pkg_resources.resource_exists(pkg, path): + package_name, filename = spec.split(':', 1) + if not pkg_resources.resource_exists(package_name, filename): raise ValueError('Missing template resource: %s' % spec) - abspath = pkg_resources.resource_filename(pkg, path) + abspath = pkg_resources.resource_filename(package_name, filename) renderer = impl(abspath) if not _reload_resources(): # cache the template sm = getSiteManager() - sm.registerUtility(renderer, ITemplateRenderer, - name=spec) + sm.registerUtility(renderer, ITemplateRenderer, name=spec) return renderer diff --git a/repoze/bfg/resource.py b/repoze/bfg/resource.py index c597ad712..ca6cee543 100644 --- a/repoze/bfg/resource.py +++ b/repoze/bfg/resource.py @@ -1,4 +1,5 @@ import os +import sys import pkg_resources from zope.component import queryUtility @@ -169,10 +170,12 @@ class FileOverride: if resource_name == self.path: return self.package, self.prefix -def resource_spec(spec, package_name): +def resolve_resource_spec(spec, package_name='__main__'): if os.path.isabs(spec): - return spec + return None, spec + filename = spec if ':' in spec: - return spec - return '%s:%s' % (package_name, spec) - + package_name, filename = spec.split(':', 1) + elif package_name is None: + package_name, filename = None, spec + return package_name, filename diff --git a/repoze/bfg/router.py b/repoze/bfg/router.py index a46232330..16c273012 100644 --- a/repoze/bfg/router.py +++ b/repoze/bfg/router.py @@ -18,6 +18,7 @@ from repoze.bfg.events import NewRequest from repoze.bfg.events import NewResponse from repoze.bfg.exceptions import Forbidden from repoze.bfg.exceptions import NotFound +from repoze.bfg.resource import resolve_resource_spec from repoze.bfg.request import Request from repoze.bfg.threadlocal import manager from repoze.bfg.traversal import DefaultRootFactory @@ -193,8 +194,13 @@ def make_app(root_factory, package=None, filename='configure.zcml', from repoze.bfg.configuration import Configurator # pragma: no cover settings = settings or options config = Configurator() - config.declarative(root_factory, package=package, - filename=filename, settings=settings) + package_name = package and package.__name__ or None + package_name, filename = resolve_resource_spec(filename, package_name) + if package_name is not None: + spec = '%s:%s' % (package_name, filename) + else: + spec = filename + config.declarative(root_factory, spec, settings=settings) app = config.make_wsgi_app() return app diff --git a/repoze/bfg/tests/test_configuration.py b/repoze/bfg/tests/test_configuration.py index 379609cdc..e427823fa 100644 --- a/repoze/bfg/tests/test_configuration.py +++ b/repoze/bfg/tests/test_configuration.py @@ -127,64 +127,28 @@ class ConfiguratorTests(unittest.TestCase): self.assertEqual(len(subscriber), 1) def test_declarative_fixtureapp_default_filename_withpackage(self): - from repoze.bfg.tests import fixtureapp - rootfactory = DummyRootFactory(None) - registry = self._callDeclarative(rootfactory, fixtureapp) - from repoze.bfg.tests.fixtureapp.models import IFixture - self.failUnless(registry.queryUtility(IFixture)) # only in c.zcml - - def test_declarative_fixtureapp_explicit_filename(self): - from repoze.bfg.tests import fixtureapp - rootfactory = DummyRootFactory(None) - registry = self._callDeclarative( - rootfactory, fixtureapp, filename='another.zcml') - from repoze.bfg.tests.fixtureapp.models import IFixture - self.failIf(registry.queryUtility(IFixture)) # only in c.zcml - - def test_declarative_fixtureapp_explicit_filename_in_settings(self): - import os rootfactory = DummyRootFactory(None) - from repoze.bfg.tests import fixtureapp - zcmlfile = os.path.join(os.path.dirname(fixtureapp.__file__), - 'another.zcml') registry = self._callDeclarative( - rootfactory, fixtureapp, filename='configure.zcml', - settings={'configure_zcml':zcmlfile}) + rootfactory, + 'repoze.bfg.tests.fixtureapp:configure.zcml') from repoze.bfg.tests.fixtureapp.models import IFixture - self.failIf(registry.queryUtility(IFixture)) # only in c.zcml + self.failUnless(registry.queryUtility(IFixture)) # only in c.zcml def test_declarative_fixtureapp_explicit_specification_in_settings(self): rootfactory = DummyRootFactory(None) - from repoze.bfg.tests import fixtureapp zcmlfile = 'repoze.bfg.tests.fixtureapp.subpackage:yetanother.zcml' registry = self._callDeclarative( - rootfactory, fixtureapp, filename='configure.zcml', + rootfactory, 'repoze.bfg.tests.fixtureapp:configure.zcml', settings={'configure_zcml':zcmlfile}) from repoze.bfg.tests.fixtureapp.models import IFixture self.failIf(registry.queryUtility(IFixture)) # only in c.zcml - def test_declarative_fixtureapp_filename_hascolon_isabs(self): - rootfactory = DummyRootFactory(None) - from repoze.bfg.tests import fixtureapp - zcmlfile = 'repoze.bfg.tests.fixtureapp.subpackage:yetanother.zcml' - class Dummy: - def isabs(self, name): - return True - os = Dummy() - os.path = Dummy() - self.assertRaises(IOError, self._callDeclarative, - rootfactory, - fixtureapp, - filename='configure.zcml', - settings={'configure_zcml':zcmlfile}, - os=os) - def test_declarative_custom_settings(self): settings = {'mysetting':True} - from repoze.bfg.tests import fixtureapp rootfactory = DummyRootFactory(None) registry = self._callDeclarative( - rootfactory, fixtureapp, settings=settings) + rootfactory, 'repoze.bfg.tests.fixtureapp:configure.zcml', + settings=settings) from repoze.bfg.interfaces import ISettings settings = registry.getUtility(ISettings) self.assertEqual(settings.reload_templates, False) @@ -194,10 +158,10 @@ class ConfiguratorTests(unittest.TestCase): def test_declarative_registrations(self): settings = {'reload_templates':True, 'debug_authorization':True} - from repoze.bfg.tests import fixtureapp rootfactory = DummyRootFactory(None) registry = self._callDeclarative( - rootfactory, fixtureapp, settings=settings) + rootfactory, 'repoze.bfg.tests.fixtureapp:configure.zcml', + settings=settings) from repoze.bfg.interfaces import ISettings from repoze.bfg.interfaces import ILogger from repoze.bfg.interfaces import IRootFactory @@ -216,21 +180,20 @@ class ConfiguratorTests(unittest.TestCase): from repoze.bfg.interfaces import IRoutesMapper settings = {'reload_templates':True, 'debug_authorization':True} - from repoze.bfg.tests import routesapp rootfactory = DummyRootFactory(None) registry = self._callDeclarative( - rootfactory, routesapp, settings=settings) + rootfactory, 'repoze.bfg.tests.routesapp:configure.zcml', + settings=settings) settings = registry.getUtility(ISettings) logger = registry.getUtility(ILogger, name='repoze.bfg.debug') self.assertEqual(registry.getUtility(IRootFactory), rootfactory) self.failUnless(registry.getUtility(IRoutesMapper)) def test_declarative_lock_and_unlock(self): - from repoze.bfg.tests import fixtureapp rootfactory = DummyRootFactory(None) dummylock = DummyLock() registry = self._callDeclarative( - rootfactory, fixtureapp, filename='configure.zcml', + rootfactory, 'repoze.bfg.tests.fixtureapp:configure.zcml', lock=dummylock) self.assertEqual(dummylock.acquired, True) self.assertEqual(dummylock.released, True) diff --git a/repoze/bfg/tests/test_renderers.py b/repoze/bfg/tests/test_renderers.py index a330d19da..d94ffbc1e 100644 --- a/repoze/bfg/tests/test_renderers.py +++ b/repoze/bfg/tests/test_renderers.py @@ -10,9 +10,9 @@ class TestTemplateRendererFactory(unittest.TestCase): def tearDown(self): cleanUp() - def _callFUT(self, path, factory, level=3): + def _callFUT(self, path, factory): from repoze.bfg.renderers import template_renderer_factory - return template_renderer_factory(path, factory, level) + return template_renderer_factory(path, factory) def test_abspath_notfound(self): from repoze.bfg.interfaces import ITemplateRenderer @@ -52,27 +52,11 @@ class TestTemplateRendererFactory(unittest.TestCase): result = self._callFUT('foo:bar/baz', None) self.failUnless(renderer is result) - def test_relpath_notfound(self): - self.assertRaises(ValueError, self._callFUT, 'wont/exist', None) - - def test_relpath_is_package_notfound(self): - from repoze.bfg import tests - module_name = tests.__name__ + def test_spec_notfound(self): self.assertRaises(ValueError, self._callFUT, - '%s:wont/exist' % module_name, None) - - def test_relpath_alreadyregistered(self): - from repoze.bfg.interfaces import ITemplateRenderer - from repoze.bfg import tests - module_name = tests.__name__ - relpath = 'test_renderers.py' - spec = '%s:%s' % (module_name, relpath) - renderer = {} - testing.registerUtility(renderer, ITemplateRenderer, name=spec) - result = self._callFUT('test_renderers.py', None) - self.failUnless(result is renderer) + 'repoze.bfg.tests:wont/exist', None) - def test_relpath_is_package_alreadyregistered(self): + def test_spec_alreadyregistered(self): from repoze.bfg.interfaces import ITemplateRenderer from repoze.bfg import tests module_name = tests.__name__ @@ -83,22 +67,7 @@ class TestTemplateRendererFactory(unittest.TestCase): result = self._callFUT(spec, None) self.failUnless(result is renderer) - def test_relpath_notyetregistered(self): - import os - from repoze.bfg.tests import test_renderers - module_name = test_renderers.__name__ - relpath = 'test_renderers.py' - renderer = {} - factory = DummyFactory(renderer) - result = self._callFUT('test_renderers.py', factory) - self.failUnless(result is renderer) - path = os.path.abspath(__file__) - if path.endswith('pyc'): # pragma: no cover - path = path[:-1] - self.assertEqual(factory.path, path) - self.assertEqual(factory.kw, {}) - - def test_relpath_is_package_notyetregistered(self): + def test_spec_notyetregistered(self): import os from repoze.bfg import tests module_name = tests.__name__ @@ -122,7 +91,7 @@ class TestTemplateRendererFactory(unittest.TestCase): testing.registerUtility(settings, ISettings) renderer = {} factory = DummyFactory(renderer) - result = self._callFUT('test_renderers.py', factory) + result = self._callFUT('repoze.bfg.tests:test_renderers.py', factory) self.failUnless(result is renderer) spec = '%s:%s' % ('repoze.bfg.tests', 'test_renderers.py') self.assertEqual(queryUtility(ITemplateRenderer, name=spec), @@ -136,7 +105,7 @@ class TestTemplateRendererFactory(unittest.TestCase): testing.registerUtility(settings, ISettings) renderer = {} factory = DummyFactory(renderer) - result = self._callFUT('test_renderers.py', factory) + result = self._callFUT('repoze.bfg.tests:test_renderers.py', factory) self.failUnless(result is renderer) spec = '%s:%s' % ('repoze.bfg.tests', 'test_renderers.py') self.assertNotEqual(queryUtility(ITemplateRenderer, name=spec), diff --git a/repoze/bfg/tests/test_resource.py b/repoze/bfg/tests/test_resource.py index efdc15c63..f14d9860d 100644 --- a/repoze/bfg/tests/test_resource.py +++ b/repoze/bfg/tests/test_resource.py @@ -341,27 +341,32 @@ class TestDirectoryOverride(unittest.TestCase): result = o('baz/notfound.pt') self.assertEqual(result, None) -class Test_resource_spec(unittest.TestCase): - def _callFUT(self, path, package): - from repoze.bfg.resource import resource_spec - return resource_spec(path, package) +class Test_resolve_resource_spec(unittest.TestCase): + def _callFUT(self, spec, package_name='__main__'): + from repoze.bfg.resource import resolve_resource_spec + return resolve_resource_spec(spec, package_name) def test_abspath(self): import os here = os.path.dirname(__file__) - path= os.path.abspath(here) - self.assertEqual(self._callFUT(path, 'apackage'), path) + path = os.path.abspath(here) + package_name, filename = self._callFUT(path, 'apackage') + self.assertEqual(filename, path) + self.assertEqual(package_name, None) def test_rel_spec(self): - pkg, path = 'repoze.bfg.tests', 'test_resource.py' - self.assertEqual(self._callFUT(path, pkg), - 'repoze.bfg.tests:test_resource.py') + 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') def test_abs_spec(self): - pkg, path = 'repoze.bfg.tests', 'repoze.bfg.nottests:test_resource.py' - self.assertEqual(self._callFUT(path, pkg), - 'repoze.bfg.nottests:test_resource.py') - + pkg = 'repoze.bfg.tests' + path = 'repoze.bfg.nottests:test_resource.py' + package_name, filename = self._callFUT(path, pkg) + self.assertEqual(package_name, 'repoze.bfg.nottests') + self.assertEqual(filename, 'test_resource.py') class TestFileOverride(unittest.TestCase): def _getTargetClass(self): diff --git a/repoze/bfg/tests/test_router.py b/repoze/bfg/tests/test_router.py index e747a26e6..2fc31419a 100644 --- a/repoze/bfg/tests/test_router.py +++ b/repoze/bfg/tests/test_router.py @@ -529,25 +529,21 @@ class TestMakeApp(unittest.TestCase): def test_it(self): settings = {'a':1} - package = object() rootfactory = object() - app = self._callFUT(rootfactory, package, settings=settings, + app = self._callFUT(rootfactory, settings=settings, Configurator=DummyConfigurator) self.assertEqual(app.root_factory, rootfactory) self.assertEqual(app.settings, settings) - self.assertEqual(app.package, package) - self.assertEqual(app.filename, 'configure.zcml') + self.assertEqual(app.spec, 'configure.zcml') def test_it_options_means_settings(self): settings = {'a':1} - package = object() rootfactory = object() - app = self._callFUT(rootfactory, package, options=settings, + app = self._callFUT(rootfactory, options=settings, Configurator=DummyConfigurator) self.assertEqual(app.root_factory, rootfactory) self.assertEqual(app.settings, settings) - self.assertEqual(app.package, package) - self.assertEqual(app.filename, 'configure.zcml') + self.assertEqual(app.spec, 'configure.zcml') class DummyContext: pass @@ -616,10 +612,8 @@ class DummyConfigurator(object): def make_wsgi_app(self): return self - def declarative(self, root_factory=None, package=None, - filename=None, settings=None): + def declarative(self, root_factory=None, spec=None, settings=None): self.root_factory = root_factory - self.package = package - self.filename = filename + self.spec = spec self.settings = settings diff --git a/repoze/bfg/tests/test_zcml.py b/repoze/bfg/tests/test_zcml.py index 608c69f51..4623ea3b1 100644 --- a/repoze/bfg/tests/test_zcml.py +++ b/repoze/bfg/tests/test_zcml.py @@ -499,7 +499,7 @@ class TestStaticDirective(unittest.TestCase): discriminator = route_action['discriminator'] self.assertEqual(discriminator, ('route', 'name', False, None, None, None, None, None)) - route_action['callable']() + route_action['callable'](*route_action['args']) mapper = sm.getUtility(IRoutesMapper) routes = mapper.get_routes() self.assertEqual(len(routes), 1) @@ -649,6 +649,9 @@ class DummyContext: 'args':args} ) + def path(self, path): + return path + def resolve(self, dottedname): return self.resolved diff --git a/repoze/bfg/view.py b/repoze/bfg/view.py index d94da9570..5096b291e 100644 --- a/repoze/bfg/view.py +++ b/repoze/bfg/view.py @@ -27,7 +27,7 @@ from repoze.bfg.interfaces import IRoutesMapper from repoze.bfg.interfaces import IView from repoze.bfg.path import caller_package -from repoze.bfg.resource import resource_spec +from repoze.bfg.resource import resolve_resource_spec from repoze.bfg.static import PackageURLParser # b/c imports @@ -170,19 +170,19 @@ class static(object): directive will not be able to override the resources it contains. """ - def __init__(self, root_dir, cache_max_age=3600, level=2, - package_name=None): + def __init__(self, root_dir, cache_max_age=3600, package_name=None): # package_name is for bw compat; it is preferred to pass in a # package-relative path as root_dir # (e.g. ``anotherpackage:foo/static``). - if os.path.isabs(root_dir): - self.app = StaticURLParser(root_dir, cache_max_age=cache_max_age) - return caller_package_name = caller_package().__name__ - spec = resource_spec(root_dir, package_name or caller_package_name) - package_name, root_dir = spec.split(':', 1) - self.app = PackageURLParser(package_name, root_dir, - cache_max_age=cache_max_age) + package_name = package_name or caller_package_name + package_name, root_dir = resolve_resource_spec(root_dir, package_name) + if package_name is None: + app = StaticURLParser(root_dir, cache_max_age=cache_max_age) + else: + app = PackageURLParser( + package_name, root_dir, cache_max_age=cache_max_age) + self.app = app def __call__(self, context, request): subpath = '/'.join(request.subpath) diff --git a/repoze/bfg/zcml.py b/repoze/bfg/zcml.py index 1767880bd..f801c62ac 100644 --- a/repoze/bfg/zcml.py +++ b/repoze/bfg/zcml.py @@ -24,12 +24,9 @@ from repoze.bfg.authentication import RepozeWho1AuthenticationPolicy from repoze.bfg.authentication import RemoteUserAuthenticationPolicy from repoze.bfg.authentication import AuthTktAuthenticationPolicy from repoze.bfg.authorization import ACLAuthorizationPolicy -from repoze.bfg.path import package_name from repoze.bfg.request import route_request_iface -from repoze.bfg.resource import resource_spec -from repoze.bfg.static import StaticRootFactory from repoze.bfg.threadlocal import get_current_registry -from repoze.bfg.view import static as static_view +from repoze.bfg.static import StaticRootFactory ###################### directives ########################## @@ -163,8 +160,7 @@ def view( request_type = _context.resolve(request_type) if renderer and '.' in renderer: - zcml_package = package_name(_context.resolve('.')) - renderer = resource_spec(renderer, zcml_package) + renderer = _context.path(renderer) def register(): config = get_configurator(reg) @@ -243,8 +239,7 @@ def route(_context, name, path, view=None, view_for=None, view_permission = view_permission or permission view_renderer = view_renderer or renderer if view_renderer and '.' in view_renderer: - zcml_package = package_name(_context.resolve('.')) - view_renderer = resource_spec(view_renderer, zcml_package) + view_renderer = _context.path(view_renderer) def register(): config = get_configurator(reg) @@ -321,8 +316,7 @@ class SystemViewHandler(object): def __call__(self, _context, view=None, attr=None, renderer=None, wrapper=None): if renderer and '.' in renderer: - renderer = resource_spec( - renderer, package_name(_context.resolve('.'))) + renderer = _context.path(renderer) def register(iface=self.iface): reg = get_current_registry() @@ -483,10 +477,22 @@ class IStaticDirective(Interface): def static(_context, name, path, cache_max_age=3600): """ Handle ``static`` ZCML directives """ - path = resource_spec(path, package_name(_context.resolve('.'))) - view = static_view(path, cache_max_age=cache_max_age) - route(_context, name, "%s*subpath" % name, view=view, - view_for=StaticRootFactory, factory=StaticRootFactory(path)) + abspath = _context.path(path) + reg = get_current_registry() + config = get_configurator(reg) + + _context.action( + discriminator = ('route', name, False, None, None, None, None, None), + callable=config.static, + args = (name, abspath, cache_max_age, _context.info), + ) + + _context.action( + discriminator = ( + 'view', StaticRootFactory, '', None, IView, None, None, None, + name, None, None, None, None, None, + ) + ) class IScanDirective(Interface): package = GlobalObject( -- cgit v1.2.3