diff options
| -rw-r--r-- | docs/api.rst | 1 | ||||
| -rw-r--r-- | docs/api/router.rst | 8 | ||||
| -rw-r--r-- | docs/latexindex.rst | 1 | ||||
| -rw-r--r-- | docs/tutorials/bfg/index.rst | 42 | ||||
| -rw-r--r-- | pyramid/configuration.py | 56 | ||||
| -rw-r--r-- | pyramid/router.py | 5 | ||||
| -rw-r--r-- | pyramid/tests/test_configuration.py | 68 |
7 files changed, 180 insertions, 1 deletions
diff --git a/docs/api.rst b/docs/api.rst index a4d853942..8d93ff450 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -22,6 +22,7 @@ documentation is organized alphabetically by module name. api/paster api/renderers api/request + api/router api/scripting api/security api/settings diff --git a/docs/api/router.rst b/docs/api/router.rst new file mode 100644 index 000000000..e5ffe97ce --- /dev/null +++ b/docs/api/router.rst @@ -0,0 +1,8 @@ +.. _router_module: + +:mod:`pyramid.router` +--------------------- + +.. automodule:: pyramid.router + +.. autofunction:: pyramid.router.make_app(root_factory, package=None, filename='configure.zcml', settings=None) diff --git a/docs/latexindex.rst b/docs/latexindex.rst index 493aa8232..10cca4401 100644 --- a/docs/latexindex.rst +++ b/docs/latexindex.rst @@ -93,6 +93,7 @@ API Reference api/paster api/renderers api/request + api/router api/scripting api/security api/settings diff --git a/docs/tutorials/bfg/index.rst b/docs/tutorials/bfg/index.rst index 4689831fa..efced23fb 100644 --- a/docs/tutorials/bfg/index.rst +++ b/docs/tutorials/bfg/index.rst @@ -96,8 +96,16 @@ Here's how to convert a :mod:`repoze.bfg` application to a converted recursively, except Python files which live in directories which start with a ``.`` (dot). + - Each ZCML file found (recursively) within the path will have the + default ``xmlns`` attribute attached to the ``configure`` tag + changed from ``http://namespaces.repoze.org/bfg`` to + ``http://pylonshq.com/pyramid``. Every ZCML file beneath the + top-level path (files ending with ``.zcml``) will be visited and + converted recursively, except ZCML files which live in + directories which start with a ``.`` (dot). + - ZCML files which contain directives that have attributes which - name ``repoze.bfg`` + name a ``repoze.bfg`` API module or attribute of an API module (e.g. ``context="repoze.bfg.exceptions.NotFound"``) will be converted to :mod:`pyramid` compatible ZCML attributes (e.g. ``context="pyramid.exceptions.NotFound``). Every ZCML file @@ -136,6 +144,38 @@ Here's how to convert a :mod:`repoze.bfg` application to a the documentation of the :mod:`pyramid` add-on package for information. +#. *Only if you use ZCML and add-ons which use ZCML*: The default + ``xmlns`` of the ``configure`` tag in ZCML has changed. The + ``bfg2pyramid`` script effects the default namespace change (it + changes the ``configure`` tag default ``xmlns`` from + ``http://namespaces.repoze.org/bfg`` to + ``http://pylonshq.com/pyramid``). + + This means that uses of add-ons which define ZCML directives in the + ``http://namespaces.repoze.org/bfg`` namespace will begin to "fail" + (they're actually not really failing, but your ZCML assumes that + they will always be used within a ``configure`` tag which names the + ``http://namespaces.repoze.org/bfg`` namespace as its default + ``xmlns``). Symptom: when you attempt to start the application, an + error such as ``ConfigurationError: ('Unknown directive', + u'http://namespaces.repoze.org/bfg', u'workflow')`` is printed to + the console and the application fails to start. In such a case, + either add an ``xmlns="http://namespaces.repoze.org/bfg"`` + attribute to each tag which causes a failure, or define a namespace + alias in the configure tag and prefix each failing tag. For + example, change this "failing" tag instance:: + + <configure xmlns="http://pylonshq.com/pyramid"> + <failingtag attr="foo"/> + </configure> + + To this, which will begin to succeed:: + + <configure xmlns="http://pylonshq.com/pyramid" + xmlns:bfg="http://namespaces.repoze.org/bfg"> + <bfg:failingtag attr="foo"/> + </configure> + #. Retest your application using :mod:`pyramid`. This might be as easy as: diff --git a/pyramid/configuration.py b/pyramid/configuration.py index ecb7cc9da..3589cbede 100644 --- a/pyramid/configuration.py +++ b/pyramid/configuration.py @@ -2452,6 +2452,62 @@ def isexception(o): (inspect.isclass(o) and (issubclass(o, Exception))) ) +# note that ``options`` is a b/w compat alias for ``settings`` and +# ``Configurator`` is a testing dep inj +def make_app(root_factory, package=None, filename='configure.zcml', + settings=None, options=None, Configurator=Configurator): + """ Return a Router object, representing a fully configured + :mod:`pyramid` WSGI application. + + .. warning:: Use of this function is deprecated as of + :mod:`pyramid` 1.0. You should instead use a + :class:`pyramid.configuration.Configurator` instance to + perform startup configuration as shown in + :ref:`configuration_narr`. + + ``root_factory`` must be a callable that accepts a :term:`request` + object and which returns a traversal root object. The traversal + root returned by the root factory is the *default* traversal root; + it can be overridden on a per-view basis. ``root_factory`` may be + ``None``, in which case a 'default default' traversal root is + used. + + ``package`` is a Python :term:`package` or module representing the + application's package. It is optional, defaulting to ``None``. + ``package`` may be ``None``. If ``package`` is ``None``, the + ``filename`` passed or the value in the ``options`` dictionary + named ``configure_zcml`` must be a) absolute pathname to a + :term:`ZCML` file that represents the application's configuration + *or* b) a :term:`resource specification` to a :term:`ZCML` file in + the form ``dotted.package.name:relative/file/path.zcml``. + + ``filename`` is the filesystem path to a ZCML file (optionally + relative to the package path) that should be parsed to create the + application registry. It defaults to ``configure.zcml``. It can + also be a ;term:`resource specification` in the form + ``dotted_package_name:relative/file/path.zcml``. Note that if any + value for ``configure_zcml`` is passed within the ``settings`` + dictionary, the value passed as ``filename`` will be ignored, + replaced with the ``configure_zcml`` value. + + ``settings``, if used, should be a dictionary containing runtime + settings (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}``. Note that the keyword + parameter ``options`` is a backwards compatibility alias for the + ``settings`` keyword parameter. + """ + settings = settings or options or {} + zcml_file = settings.get('configure_zcml', filename) + config = Configurator(package=package, settings=settings, + root_factory=root_factory) + config.hook_zca() + config.begin() + config.load_zcml(zcml_file) + config.end() + return config.make_wsgi_app() + class DottedNameResolver(object): """ This class resolves dotted name references to 'global' Python objects (objects which can be imported) to those objects. diff --git a/pyramid/router.py b/pyramid/router.py index 3ec23c3e4..038bed6d6 100644 --- a/pyramid/router.py +++ b/pyramid/router.py @@ -23,6 +23,11 @@ from pyramid.threadlocal import manager from pyramid.traversal import DefaultRootFactory from pyramid.traversal import ModelGraphTraverser +from pyramid.configuration import make_app # b/c + +make_app # prevent PyFlakes from complaining + + class Router(object): implements(IRouter) diff --git a/pyramid/tests/test_configuration.py b/pyramid/tests/test_configuration.py index f3958c7de..913476a7b 100644 --- a/pyramid/tests/test_configuration.py +++ b/pyramid/tests/test_configuration.py @@ -3927,6 +3927,50 @@ class TestRequestOnly(unittest.TestCase): foo = Foo() self.assertFalse(self._callFUT(foo)) +class TestMakeApp(unittest.TestCase): + def setUp(self): + testing.setUp() + + def tearDown(self): + testing.tearDown() + + def _callFUT(self, *arg, **kw): + from pyramid.configuration import make_app + return make_app(*arg, **kw) + + def test_it(self): + settings = {'a':1} + rootfactory = object() + app = self._callFUT(rootfactory, settings=settings, + Configurator=DummyConfigurator) + self.assertEqual(app.root_factory, rootfactory) + self.assertEqual(app.settings, settings) + self.assertEqual(app.zcml_file, 'configure.zcml') + self.assertEqual(app.zca_hooked, True) + + def test_it_options_means_settings(self): + settings = {'a':1} + rootfactory = object() + app = self._callFUT(rootfactory, options=settings, + Configurator=DummyConfigurator) + self.assertEqual(app.root_factory, rootfactory) + self.assertEqual(app.settings, settings) + self.assertEqual(app.zcml_file, 'configure.zcml') + + def test_it_with_package(self): + package = object() + rootfactory = object() + app = self._callFUT(rootfactory, package=package, + Configurator=DummyConfigurator) + self.assertEqual(app.package, package) + + def test_it_with_custom_configure_zcml(self): + rootfactory = object() + settings = {'configure_zcml':'2.zcml'} + app = self._callFUT(rootfactory, filename='1.zcml', settings=settings, + Configurator=DummyConfigurator) + self.assertEqual(app.zcml_file, '2.zcml') + class TestDottedNameResolver(unittest.TestCase): def _makeOne(self, package=None): from pyramid.configuration import DottedNameResolver @@ -4202,6 +4246,30 @@ class DummySecurityPolicy: def permits(self, context, principals, permission): return self.permitted +class DummyConfigurator(object): + def __init__(self, registry=None, package=None, root_factory=None, + settings=None): + self.root_factory = root_factory + self.package = package + self.settings = settings + + def begin(self, request=None): + self.begun = True + self.request = request + + def end(self): + self.ended = True + + def load_zcml(self, filename): + self.zcml_file = filename + + def make_wsgi_app(self): + return self + + def hook_zca(self): + self.zca_hooked = True + + class DummyAccept(object): def __init__(self, *matches): self.matches = list(matches) |
