diff options
| author | Chris McDonough <chrism@plope.com> | 2012-02-19 17:55:38 -0500 |
|---|---|---|
| committer | Chris McDonough <chrism@plope.com> | 2012-02-19 17:55:38 -0500 |
| commit | 4c3cca9d034818d3ab280bd3a1ff890b543bfa81 (patch) | |
| tree | 42cd6958e035436b2bd5d8ee1f5e844983c86837 | |
| parent | 5baff75c94768628e777ec74fe8f653ef69dd0db (diff) | |
| parent | 51919e05d9c251f7f80a4736be2b822eafc5d189 (diff) | |
| download | pyramid-4c3cca9d034818d3ab280bd3a1ff890b543bfa81.tar.gz pyramid-4c3cca9d034818d3ab280bd3a1ff890b543bfa81.tar.bz2 pyramid-4c3cca9d034818d3ab280bd3a1ff890b543bfa81.zip | |
Merge branch '1.3-branch'
51 files changed, 797 insertions, 563 deletions
diff --git a/CHANGES.txt b/CHANGES.txt index 22f8320f9..1df924b4c 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,5 +1,5 @@ -Next release -============ +1.3a8 (2012-02-19) +================== Features -------- @@ -93,11 +93,27 @@ Documentation - Don't create a ``session`` instance in SQLA Wiki tutorial, use raw ``DBSession`` instead (this is more common in real SQLA apps). +Scaffolding +----------- + +- Put ``pyramid.includes`` targets within ini files in scaffolds on separate + lines in order to be able to tell people to comment out only the + ``pyramid_debugtoolbar`` line when they want to disable the toolbar. + Dependencies ------------ - Depend on ``venusian`` >= 1.0a3 to provide scan ``ignore`` support. +Internal +-------- + +- Create a "MakoRendererFactoryHelper" that provides customizable settings + key prefixes. Allows settings prefixes other than "mako." to be used to + create different factories that don't use the global mako settings. This + will be useful for the debug toolbar, which can currently be sabotaged by + someone using custom mako configuration settings. + 1.3a7 (2012-02-07) ================== diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index 050225b5b..a3c1ab35b 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -160,3 +160,5 @@ Contributors - Klee Dienes, 2011/10/30 - Michael Ryabushin, 2011/12/14 + +- Mike Orr, 2012/02/14 @@ -4,13 +4,12 @@ Pyramid TODOs Nice-to-Have ------------ +- Add docs about upgrading between Pyramid versions (e.g. how to see + deprecation warnings). + - Fix renderers chapter to better document system values passed to template renderers. -- Put includes in development.ini on separate lines and fix project.rst to - tell people to comment out only the debugtoolbar include when they want to - disable. - - Modify view mapper narrative docs to not use pyramid_handlers. - Modify the urldispatch chapter examples to assume a scan rather than @@ -20,23 +19,25 @@ Nice-to-Have - Introspection: - * ``default root factory`` category? + * ``default root factory`` category (prevent folks from needing to searh + "root factories" category)? - * ``default view mapper`` category? + * ``default view mapper`` category (prevent folks from needing to search + "view mappers" category)? * get rid of "tweens" category (can't sort properly?) - * implement ptweens and proutes based on introspection instead of current - state of affairs. - - * introspection hiding for directives? + * Introspection hiding for directives for purposes of omitting toolbar + registrations. Maybe toolbar can just use a null introspector? - Fix deployment recipes in cookbook (discourage proxying without changing server). - Try "with transaction.manager" in an exception view with SQLA (preempt homina homina response about how to write "to the database" from within in - an exception view). + an exception view). Note: tried this and couldn't formulate the right + situation where the database could not be written to within an exception + view (but didn't try exhaustively). - Add narrative docs for wsgiapp and wsgiapp2. @@ -44,7 +45,8 @@ Nice-to-Have - Basic WSGI documentation (pipeline / app / server). -- Change docs about creating a venusian decorator to not use ZCA. +- Change docs about creating a venusian decorator to not use ZCA (use + configurator methods instead). - Try to better explain the relationship between a renderer and a template in the templates chapter and elsewhere. Scan the documentation for reference @@ -113,6 +115,8 @@ Future - 1.5: Remove ``pyramid.requests.DeprecatedRequestMethodsMixin``. +- 1.6: Remove IContextURL and TraversalContextURL. + Probably Bad Ideas ------------------ diff --git a/docs/api/config.rst b/docs/api/config.rst index 3fc2cfc44..b76fed9cb 100644 --- a/docs/api/config.rst +++ b/docs/api/config.rst @@ -1,102 +1,102 @@ .. _configuration_module: +.. role:: methodcategory + :class: methodcategory + :mod:`pyramid.config` --------------------- .. automodule:: pyramid.config - .. autoclass:: Configurator - - .. attribute:: registry - - The :term:`application registry` which holds the configuration - associated with this configurator. +.. autoclass:: Configurator - .. automethod:: begin + :methodcategory:`Controlling Configuration State` - .. automethod:: end + .. automethod:: commit + .. automethod:: begin + .. automethod:: end + .. automethod:: include + .. automethod:: make_wsgi_app() + .. automethod:: scan - .. automethod:: hook_zca + :methodcategory:`Adding Routes and Views` - .. automethod:: unhook_zca + .. automethod:: add_route + .. automethod:: add_static_view(name, path, cache_max_age=3600, permission=NO_PERMISSION_REQUIRED) + .. automethod:: add_view + .. automethod:: set_forbidden_view + .. automethod:: set_notfound_view - .. automethod:: get_settings + :methodcategory:`Adding an Event Subscriber` - .. automethod:: commit + .. automethod:: add_subscriber - .. automethod:: action + :methodcategory:`Using Security` - .. automethod:: include + .. automethod:: set_authentication_policy + .. automethod:: set_authorization_policy + .. automethod:: set_default_permission - .. automethod:: add_directive + :methodcategory:`Setting Request Properties` - .. automethod:: with_package + .. automethod:: set_request_property - .. automethod:: maybe_dotted + :methodcategory:`Using I18N` - .. automethod:: absolute_asset_spec + .. automethod:: add_translation_dirs + .. automethod:: set_locale_negotiator - .. automethod:: setup_registry + :methodcategory:`Overriding Assets` - .. automethod:: add_renderer + .. automethod:: override_asset(to_override, override_with) - .. automethod:: add_response_adapter + :methodcategory:`Setting Renderer Globals` - .. automethod:: add_route + .. automethod:: set_renderer_globals_factory(factory) - .. automethod:: add_static_view(name, path, cache_max_age=3600, permission=NO_PERMISSION_REQUIRED) + :methodcategory:`Getting and Adding Settings` .. automethod:: add_settings + .. automethod:: get_settings - .. automethod:: add_subscriber - - .. automethod:: add_translation_dirs - - .. automethod:: add_view + :methodcategory:`Hooking Pyramid Behavior` + .. automethod:: add_renderer + .. automethod:: add_resource_url_adapter + .. automethod:: add_response_adapter + .. automethod:: add_traverser .. automethod:: add_tween - - .. automethod:: derive_view - - .. automethod:: make_wsgi_app() - - .. automethod:: override_asset(to_override, override_with) - - .. automethod:: scan - - .. automethod:: set_locale_negotiator - - .. automethod:: set_default_permission - - .. automethod:: set_session_factory - .. automethod:: set_request_factory - - .. automethod:: set_request_property - .. automethod:: set_root_factory - + .. automethod:: set_session_factory .. automethod:: set_view_mapper - .. automethod:: set_authentication_policy - - .. automethod:: set_authorization_policy + :methodcategory:`Extension Author APIs` - .. automethod:: testing_securitypolicy + .. automethod:: action + .. automethod:: add_directive + .. automethod:: with_package - .. automethod:: testing_resources + :methodcategory:`Utility Methods` - .. automethod:: testing_add_subscriber + .. automethod:: absolute_asset_spec + .. automethod:: derive_view + .. automethod:: maybe_dotted + .. automethod:: setup_registry - .. automethod:: testing_add_renderer + :methodcategory:`ZCA-Related APIs` - .. automethod:: set_forbidden_view + .. automethod:: hook_zca + .. automethod:: unhook_zca - .. automethod:: set_notfound_view + :methodcategory:`Testing Helper APIs` - .. automethod:: add_traverser + .. automethod:: testing_add_renderer + .. automethod:: testing_add_subscriber + .. automethod:: testing_resources + .. automethod:: testing_securitypolicy - .. automethod:: set_renderer_globals_factory(factory) + :methodcategory:`Attributes` .. attribute:: introspectable @@ -104,7 +104,9 @@ :class:`pyramid.registry.Introspectable` class (used during directives to provide introspection to actions). - This attribute is new as of :app:`Pyramid` 1.3. + .. note:: + + This attribute is new as of :app:`Pyramid` 1.3. .. attribute:: introspector @@ -114,17 +116,24 @@ ``introspector`` argument, this attribute will be that value. Otherwise, it will be an instance of a default introspector type. - This attribute is new as of :app:`Pyramid` 1.3. + .. note:: + + This attribute is new as of :app:`Pyramid` 1.3. + + .. attribute:: registry + + The :term:`application registry` which holds the configuration + associated with this configurator. - .. attribute:: global_registries +.. attribute:: global_registries - The set of registries that have been created for :app:`Pyramid` - applications, one per each call to - :meth:`pyramid.config.Configurator.make_wsgi_app` in the current - process. The object itself supports iteration and has a ``last`` - property containing the last registry loaded. + The set of registries that have been created for :app:`Pyramid` + applications, one per each call to + :meth:`pyramid.config.Configurator.make_wsgi_app` in the current + process. The object itself supports iteration and has a ``last`` property + containing the last registry loaded. - The registries contained in this object are stored as weakrefs, - thus they will only exist for the lifetime of the actual - applications for which they are being used. + The registries contained in this object are stored as weakrefs, thus they + will only exist for the lifetime of the actual applications for which they + are being used. diff --git a/docs/conf.py b/docs/conf.py index 0c56f56e7..3e38226c1 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -80,7 +80,7 @@ copyright = '%s, Agendaless Consulting' % datetime.datetime.now().year # other places throughout the built documents. # # The short X.Y version. -version = '1.3a7' +version = '1.3a8' # The full version, including alpha/beta/rc tags. release = version diff --git a/docs/glossary.rst b/docs/glossary.rst index 8307c0472..60920a73a 100644 --- a/docs/glossary.rst +++ b/docs/glossary.rst @@ -876,12 +876,11 @@ Glossary on the Jinja2 templating system. Akhet - Akhet is a Pyramid-based development environment which provides a - Pylons-esque scaffold which sports support for :term:`view handler` - application development, :term:`SQLAlchemy` support, :term:`Mako` - templating by default, and other Pylons-like features. See - http://docs.pylonsproject.org/projects/akhet/dev/index.html for more - information. + `Akhet <http://docs.pylonsproject.org/projects/akhet/en/latest/>`_ is a + Pyramid library and demo application with a Pylons-like feel. + It's most known for its former application scaffold, which helped + users transition from Pylons and those prefering a more Pylons-like API. + The scaffold has been retired but the demo plays a similar role. Pyramid Cookbook An additional documentation resource for Pyramid which presents topical, diff --git a/docs/narr/MyProject/development.ini b/docs/narr/MyProject/development.ini index 2ccedb27b..3c38e3805 100644 --- a/docs/narr/MyProject/development.ini +++ b/docs/narr/MyProject/development.ini @@ -7,7 +7,8 @@ pyramid.debug_notfound = false pyramid.debug_routematch = false pyramid.debug_templates = true pyramid.default_locale_name = en -pyramid.includes = pyramid_debugtoolbar +pyramid.includes = + pyramid_debugtoolbar [server:main] use = egg:waitress#main diff --git a/docs/narr/advconfig.rst b/docs/narr/advconfig.rst index 5f2175d2a..0060ef65c 100644 --- a/docs/narr/advconfig.rst +++ b/docs/narr/advconfig.rst @@ -122,9 +122,10 @@ configuration or configuration that results from the execution of a Manually Resolving Conflicts ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -There are a number of ways to manually resolve conflicts: the "right" way, by -strategically using :meth:`pyramid.config.Configurator.commit`, or by using -an "autocommitting" configurator. +There are a number of ways to manually resolve conflicts: by changing +registrations to not conflict, by strategically using +:meth:`pyramid.config.Configurator.commit`, or by using an "autocommitting" +configurator. The Right Thing +++++++++++++++ @@ -294,9 +295,18 @@ These are the methods of the configurator which provide conflict detection: :meth:`~pyramid.config.Configurator.add_route`, :meth:`~pyramid.config.Configurator.add_renderer`, :meth:`~pyramid.config.Configurator.set_request_factory`, +:meth:`~pyramid.config.Configurator.set_session_factory`, +:meth:`~pyramid.config.Configurator.set_request_property`, +:meth:`~pyramid.config.Configurator.set_root_factory`, +:meth:`~pyramid.config.Configurator.set_view_mapper`, +:meth:`~pyramid.config.Configurator.set_authentication_policy`, +:meth:`~pyramid.config.Configurator.set_authorization_policy`, :meth:`~pyramid.config.Configurator.set_renderer_globals_factory`, -:meth:`~pyramid.config.Configurator.set_locale_negotiator` and -:meth:`~pyramid.config.Configurator.set_default_permission`. +:meth:`~pyramid.config.Configurator.set_locale_negotiator`, +:meth:`~pyramid.config.Configurator.set_default_permission`, +:meth:`~pyramid.config.Configurator.add_traverser`, +:meth:`~pyramid.config.Configurator.add_resource_url_adapter`, +and :meth:`~pyramid.config.Configurator.add_response_adapter`. :meth:`~pyramid.config.Configurator.add_static_view` also indirectly provides conflict detection, because it's implemented in terms of the diff --git a/docs/narr/hooks.rst b/docs/narr/hooks.rst index 2c4310080..eaccc14a3 100644 --- a/docs/narr/hooks.rst +++ b/docs/narr/hooks.rst @@ -145,10 +145,10 @@ Here's some sample code that implements a minimal forbidden view: Changing the Request Factory ---------------------------- -Whenever :app:`Pyramid` handles a :term:`WSGI` request, it creates a -:term:`request` object based on the WSGI environment it has been passed. By -default, an instance of the :class:`pyramid.request.Request` class is created -to represent the request object. +Whenever :app:`Pyramid` handles a request from a :term:`WSGI` server, it +creates a :term:`request` object based on the WSGI environment it has been +passed. By default, an instance of the :class:`pyramid.request.Request` +class is created to represent the request object. The class (aka "factory") that :app:`Pyramid` uses to create a request object instance can be changed by passing a ``request_factory`` argument to the @@ -236,11 +236,11 @@ Adding Renderer Globals (Deprecated) is documented in :ref:`beforerender_event`. Whenever :app:`Pyramid` handles a request to perform a rendering (after a -view with a ``renderer=`` configuration attribute is invoked, or when any -of the methods beginning with ``render`` within the :mod:`pyramid.renderers` +view with a ``renderer=`` configuration attribute is invoked, or when any of +the methods beginning with ``render`` within the :mod:`pyramid.renderers` module are called), *renderer globals* can be injected into the *system* values sent to the renderer. By default, no renderer globals are injected, -and the "bare" system values (such as ``request``, ``context``, and +and the "bare" system values (such as ``request``, ``context``, ``view``, and ``renderer_name``) are the only values present in the system dictionary passed to every renderer. @@ -447,7 +447,7 @@ that implements the following interface: More than one traversal algorithm can be active at the same time. For instance, if your :term:`root factory` returns more than one type of object -conditionally, you could claim that an alternate traverser adapter is ``for`` +conditionally, you could claim that an alternate traverser adapter is "for" only one particular class or interface. When the root factory returned an object that implemented that class or interface, a custom traverser would be used. Otherwise, the default traverser would be used. For example: @@ -495,7 +495,7 @@ For example: from myapp.traversal import ResourceURLAdapter from myapp.resources import MyRoot - config.add_resource_url_adapter(ResourceURLAdapter, resource_iface=MyRoot) + config.add_resource_url_adapter(ResourceURLAdapter, MyRoot) In the above example, the ``myapp.traversal.ResourceURLAdapter`` class will be used to provide services to :meth:`~pyramid.request.Request.resource_url` diff --git a/docs/narr/introspector.rst b/docs/narr/introspector.rst index 08cc430f6..d465c47d9 100644 --- a/docs/narr/introspector.rst +++ b/docs/narr/introspector.rst @@ -540,10 +540,30 @@ introspectables in categories not described here. The (resolved) interface or class object that represents the return value of a root factory that this traverser will be used for. - ``factory`` + ``adapter`` The (resolved) traverser class. +``resource url adapters`` + + Each introspectable in the ``resource url adapters`` category represents a + call to :meth:`pyramid.config.Configurator.add_resource_url_adapter`; each + will have the following data. + + ``adapter`` + + The (resolved) resource URL adapter class. + + ``resource_iface`` + + The (resolved) interface or class object that represents the resource + interface that this url adapter is registered for. + + ``request_iface`` + + The (resolved) interface or class object that represents the request + interface that this url adapter is registered for. + Introspection in the Toolbar ---------------------------- diff --git a/docs/narr/project.rst b/docs/narr/project.rst index 4566a4fb8..5a519ca30 100644 --- a/docs/narr/project.rst +++ b/docs/narr/project.rst @@ -348,27 +348,48 @@ when you use the ``production.ini`` file instead of the ``development.ini`` ini file to run the application. You can also turn the debug toolbar off by editing ``development.ini`` and -commenting out the line ``pyramid.includes = pyramid_debugtoolbar``. For -example, instead of: +commenting out a line. For example, instead of: .. code-block:: ini :linenos: [app:main] ... - pyramid.includes = pyramid_debugtoolbar + pyramid.includes = + pyramid_debugtoolbar -Put a hash mark in front of the ``pyramid.includes`` line: +Put a hash mark at the beginning of the ``pyramid_debugtoolbar`` line: .. code-block:: ini :linenos: [app:main] ... - #pyramid.includes = pyramid_debugtoolbar + pyramid.includes = + # pyramid_debugtoolbar Then restart the application to see that the toolbar has been turned off. +Note that if you comment out the ``pryamid_debugtoolbar`` line, the ``#`` +*must* be in the first column. If you put the hash mark anywhere except the +first column instead, for example like this: + +.. code-block:: ini + :linenos: + + [app:main] + ... + pyramid.includes = + #pyramid_debugtoolbar + +When you attempt to restart the application with a section like the abvoe +you'll receive an error that ends something like this, and the application +will not start: + +.. code-block:: text + + ImportError: No module named #pyramid_debugtoolbar + .. index:: single: project structure diff --git a/docs/tutorials/wiki/src/authorization/development.ini b/docs/tutorials/wiki/src/authorization/development.ini index 47566515c..74781caed 100644 --- a/docs/tutorials/wiki/src/authorization/development.ini +++ b/docs/tutorials/wiki/src/authorization/development.ini @@ -6,9 +6,11 @@ pyramid.debug_notfound = false pyramid.debug_routematch = false pyramid.debug_templates = true pyramid.default_locale_name = en -pyramid.includes = pyramid_debugtoolbar - pyramid_zodbconn - pyramid_tm +pyramid.includes = + pyramid_debugtoolbar + pyramid_zodbconn + pyramid_tm + tm.attempts = 3 zodbconn.uri = file://%(here)s/Data.fs?connection_cache_size=20000 diff --git a/docs/tutorials/wiki/src/authorization/production.ini b/docs/tutorials/wiki/src/authorization/production.ini index 919efce1e..2da493def 100644 --- a/docs/tutorials/wiki/src/authorization/production.ini +++ b/docs/tutorials/wiki/src/authorization/production.ini @@ -6,8 +6,10 @@ pyramid.debug_notfound = false pyramid.debug_routematch = false pyramid.debug_templates = false pyramid.default_locale_name = en -pyramid.includes = pyramid_tm - pyramid_zodbconn +pyramid.includes = + pyramid_tm + pyramid_zodbconn + tm.attempts = 3 zodbconn.uri = file://%(here)s/Data.fs?connection_cache_size=20000 diff --git a/docs/tutorials/wiki/src/basiclayout/development.ini b/docs/tutorials/wiki/src/basiclayout/development.ini index 3acff7f6d..5a3dba52a 100644 --- a/docs/tutorials/wiki/src/basiclayout/development.ini +++ b/docs/tutorials/wiki/src/basiclayout/development.ini @@ -6,9 +6,11 @@ pyramid.debug_notfound = false pyramid.debug_routematch = false pyramid.debug_templates = true pyramid.default_locale_name = en -pyramid.includes = pyramid_debugtoolbar - pyramid_zodbconn - pyramid_tm +pyramid.includes = + pyramid_debugtoolbar + pyramid_zodbconn + pyramid_tm + tm.attempts = 3 zodbconn.uri = file://%(here)s/Data.fs?connection_cache_size=20000 diff --git a/docs/tutorials/wiki/src/basiclayout/production.ini b/docs/tutorials/wiki/src/basiclayout/production.ini index 919efce1e..2da493def 100644 --- a/docs/tutorials/wiki/src/basiclayout/production.ini +++ b/docs/tutorials/wiki/src/basiclayout/production.ini @@ -6,8 +6,10 @@ pyramid.debug_notfound = false pyramid.debug_routematch = false pyramid.debug_templates = false pyramid.default_locale_name = en -pyramid.includes = pyramid_tm - pyramid_zodbconn +pyramid.includes = + pyramid_tm + pyramid_zodbconn + tm.attempts = 3 zodbconn.uri = file://%(here)s/Data.fs?connection_cache_size=20000 diff --git a/docs/tutorials/wiki/src/models/development.ini b/docs/tutorials/wiki/src/models/development.ini index 47566515c..74781caed 100644 --- a/docs/tutorials/wiki/src/models/development.ini +++ b/docs/tutorials/wiki/src/models/development.ini @@ -6,9 +6,11 @@ pyramid.debug_notfound = false pyramid.debug_routematch = false pyramid.debug_templates = true pyramid.default_locale_name = en -pyramid.includes = pyramid_debugtoolbar - pyramid_zodbconn - pyramid_tm +pyramid.includes = + pyramid_debugtoolbar + pyramid_zodbconn + pyramid_tm + tm.attempts = 3 zodbconn.uri = file://%(here)s/Data.fs?connection_cache_size=20000 diff --git a/docs/tutorials/wiki/src/models/production.ini b/docs/tutorials/wiki/src/models/production.ini index 919efce1e..2da493def 100644 --- a/docs/tutorials/wiki/src/models/production.ini +++ b/docs/tutorials/wiki/src/models/production.ini @@ -6,8 +6,10 @@ pyramid.debug_notfound = false pyramid.debug_routematch = false pyramid.debug_templates = false pyramid.default_locale_name = en -pyramid.includes = pyramid_tm - pyramid_zodbconn +pyramid.includes = + pyramid_tm + pyramid_zodbconn + tm.attempts = 3 zodbconn.uri = file://%(here)s/Data.fs?connection_cache_size=20000 diff --git a/docs/tutorials/wiki/src/tests/development.ini b/docs/tutorials/wiki/src/tests/development.ini index 47566515c..74781caed 100644 --- a/docs/tutorials/wiki/src/tests/development.ini +++ b/docs/tutorials/wiki/src/tests/development.ini @@ -6,9 +6,11 @@ pyramid.debug_notfound = false pyramid.debug_routematch = false pyramid.debug_templates = true pyramid.default_locale_name = en -pyramid.includes = pyramid_debugtoolbar - pyramid_zodbconn - pyramid_tm +pyramid.includes = + pyramid_debugtoolbar + pyramid_zodbconn + pyramid_tm + tm.attempts = 3 zodbconn.uri = file://%(here)s/Data.fs?connection_cache_size=20000 diff --git a/docs/tutorials/wiki/src/tests/production.ini b/docs/tutorials/wiki/src/tests/production.ini index 919efce1e..2da493def 100644 --- a/docs/tutorials/wiki/src/tests/production.ini +++ b/docs/tutorials/wiki/src/tests/production.ini @@ -6,8 +6,10 @@ pyramid.debug_notfound = false pyramid.debug_routematch = false pyramid.debug_templates = false pyramid.default_locale_name = en -pyramid.includes = pyramid_tm - pyramid_zodbconn +pyramid.includes = + pyramid_tm + pyramid_zodbconn + tm.attempts = 3 zodbconn.uri = file://%(here)s/Data.fs?connection_cache_size=20000 diff --git a/docs/tutorials/wiki/src/views/development.ini b/docs/tutorials/wiki/src/views/development.ini index 3acff7f6d..5a3dba52a 100644 --- a/docs/tutorials/wiki/src/views/development.ini +++ b/docs/tutorials/wiki/src/views/development.ini @@ -6,9 +6,11 @@ pyramid.debug_notfound = false pyramid.debug_routematch = false pyramid.debug_templates = true pyramid.default_locale_name = en -pyramid.includes = pyramid_debugtoolbar - pyramid_zodbconn - pyramid_tm +pyramid.includes = + pyramid_debugtoolbar + pyramid_zodbconn + pyramid_tm + tm.attempts = 3 zodbconn.uri = file://%(here)s/Data.fs?connection_cache_size=20000 diff --git a/docs/tutorials/wiki/src/views/production.ini b/docs/tutorials/wiki/src/views/production.ini index 919efce1e..2da493def 100644 --- a/docs/tutorials/wiki/src/views/production.ini +++ b/docs/tutorials/wiki/src/views/production.ini @@ -6,8 +6,10 @@ pyramid.debug_notfound = false pyramid.debug_routematch = false pyramid.debug_templates = false pyramid.default_locale_name = en -pyramid.includes = pyramid_tm - pyramid_zodbconn +pyramid.includes = + pyramid_tm + pyramid_zodbconn + tm.attempts = 3 zodbconn.uri = file://%(here)s/Data.fs?connection_cache_size=20000 diff --git a/docs/tutorials/wiki2/src/authorization/development.ini b/docs/tutorials/wiki2/src/authorization/development.ini index 2bb74454c..06c51fb12 100644 --- a/docs/tutorials/wiki2/src/authorization/development.ini +++ b/docs/tutorials/wiki2/src/authorization/development.ini @@ -7,8 +7,9 @@ pyramid.debug_notfound = false pyramid.debug_routematch = false pyramid.debug_templates = true pyramid.default_locale_name = en -pyramid.includes = pyramid_debugtoolbar - pyramid_tm +pyramid.includes = + pyramid_debugtoolbar + pyramid_tm sqlalchemy.url = sqlite:///%(here)s/tutorial.db diff --git a/docs/tutorials/wiki2/src/authorization/production.ini b/docs/tutorials/wiki2/src/authorization/production.ini index ec6dea135..cefb5c231 100644 --- a/docs/tutorials/wiki2/src/authorization/production.ini +++ b/docs/tutorials/wiki2/src/authorization/production.ini @@ -7,7 +7,8 @@ pyramid.debug_notfound = false pyramid.debug_routematch = false pyramid.debug_templates = false pyramid.default_locale_name = en -pyramid.includes = pyramid_tm +pyramid.includes = + pyramid_tm sqlalchemy.url = sqlite:///%(here)s/tutorial.db diff --git a/docs/tutorials/wiki2/src/basiclayout/development.ini b/docs/tutorials/wiki2/src/basiclayout/development.ini index 2bb74454c..06c51fb12 100644 --- a/docs/tutorials/wiki2/src/basiclayout/development.ini +++ b/docs/tutorials/wiki2/src/basiclayout/development.ini @@ -7,8 +7,9 @@ pyramid.debug_notfound = false pyramid.debug_routematch = false pyramid.debug_templates = true pyramid.default_locale_name = en -pyramid.includes = pyramid_debugtoolbar - pyramid_tm +pyramid.includes = + pyramid_debugtoolbar + pyramid_tm sqlalchemy.url = sqlite:///%(here)s/tutorial.db diff --git a/docs/tutorials/wiki2/src/basiclayout/production.ini b/docs/tutorials/wiki2/src/basiclayout/production.ini index ec6dea135..cefb5c231 100644 --- a/docs/tutorials/wiki2/src/basiclayout/production.ini +++ b/docs/tutorials/wiki2/src/basiclayout/production.ini @@ -7,7 +7,8 @@ pyramid.debug_notfound = false pyramid.debug_routematch = false pyramid.debug_templates = false pyramid.default_locale_name = en -pyramid.includes = pyramid_tm +pyramid.includes = + pyramid_tm sqlalchemy.url = sqlite:///%(here)s/tutorial.db diff --git a/docs/tutorials/wiki2/src/models/development.ini b/docs/tutorials/wiki2/src/models/development.ini index 2bb74454c..06c51fb12 100644 --- a/docs/tutorials/wiki2/src/models/development.ini +++ b/docs/tutorials/wiki2/src/models/development.ini @@ -7,8 +7,9 @@ pyramid.debug_notfound = false pyramid.debug_routematch = false pyramid.debug_templates = true pyramid.default_locale_name = en -pyramid.includes = pyramid_debugtoolbar - pyramid_tm +pyramid.includes = + pyramid_debugtoolbar + pyramid_tm sqlalchemy.url = sqlite:///%(here)s/tutorial.db diff --git a/docs/tutorials/wiki2/src/models/production.ini b/docs/tutorials/wiki2/src/models/production.ini index ec6dea135..cefb5c231 100644 --- a/docs/tutorials/wiki2/src/models/production.ini +++ b/docs/tutorials/wiki2/src/models/production.ini @@ -7,7 +7,8 @@ pyramid.debug_notfound = false pyramid.debug_routematch = false pyramid.debug_templates = false pyramid.default_locale_name = en -pyramid.includes = pyramid_tm +pyramid.includes = + pyramid_tm sqlalchemy.url = sqlite:///%(here)s/tutorial.db diff --git a/docs/tutorials/wiki2/src/tests/development.ini b/docs/tutorials/wiki2/src/tests/development.ini index 2bb74454c..06c51fb12 100644 --- a/docs/tutorials/wiki2/src/tests/development.ini +++ b/docs/tutorials/wiki2/src/tests/development.ini @@ -7,8 +7,9 @@ pyramid.debug_notfound = false pyramid.debug_routematch = false pyramid.debug_templates = true pyramid.default_locale_name = en -pyramid.includes = pyramid_debugtoolbar - pyramid_tm +pyramid.includes = + pyramid_debugtoolbar + pyramid_tm sqlalchemy.url = sqlite:///%(here)s/tutorial.db diff --git a/docs/tutorials/wiki2/src/tests/production.ini b/docs/tutorials/wiki2/src/tests/production.ini index ec6dea135..cefb5c231 100644 --- a/docs/tutorials/wiki2/src/tests/production.ini +++ b/docs/tutorials/wiki2/src/tests/production.ini @@ -7,7 +7,8 @@ pyramid.debug_notfound = false pyramid.debug_routematch = false pyramid.debug_templates = false pyramid.default_locale_name = en -pyramid.includes = pyramid_tm +pyramid.includes = + pyramid_tm sqlalchemy.url = sqlite:///%(here)s/tutorial.db diff --git a/docs/tutorials/wiki2/src/views/development.ini b/docs/tutorials/wiki2/src/views/development.ini index 2bb74454c..06c51fb12 100644 --- a/docs/tutorials/wiki2/src/views/development.ini +++ b/docs/tutorials/wiki2/src/views/development.ini @@ -7,8 +7,9 @@ pyramid.debug_notfound = false pyramid.debug_routematch = false pyramid.debug_templates = true pyramid.default_locale_name = en -pyramid.includes = pyramid_debugtoolbar - pyramid_tm +pyramid.includes = + pyramid_debugtoolbar + pyramid_tm sqlalchemy.url = sqlite:///%(here)s/tutorial.db diff --git a/docs/tutorials/wiki2/src/views/production.ini b/docs/tutorials/wiki2/src/views/production.ini index ec6dea135..cefb5c231 100644 --- a/docs/tutorials/wiki2/src/views/production.ini +++ b/docs/tutorials/wiki2/src/views/production.ini @@ -7,7 +7,8 @@ pyramid.debug_notfound = false pyramid.debug_routematch = false pyramid.debug_templates = false pyramid.default_locale_name = en -pyramid.includes = pyramid_tm +pyramid.includes = + pyramid_tm sqlalchemy.url = sqlite:///%(here)s/tutorial.db diff --git a/docs/whatsnew-1.3.rst b/docs/whatsnew-1.3.rst index acb884d49..d2df88093 100644 --- a/docs/whatsnew-1.3.rst +++ b/docs/whatsnew-1.3.rst @@ -243,11 +243,6 @@ Minor Feature Additions - We allow extra keyword arguments to be passed to the :meth:`pyramid.config.Configurator.action` method. -- New API: :meth:`pyramid.config.Configurator.set_request_property`. Add lazy - property descriptors to a request without changing the request factory. - This method provides conflict detection and is the suggested way to add - properties to a request. - - Responses generated by Pyramid's :class:`pyramid.views.static_view` now use a ``wsgi.file_wrapper`` (see http://www.python.org/dev/peps/pep-0333/#optional-platform-specific-file-handling) @@ -318,7 +313,7 @@ Minor Feature Additions partially. - A new API named :meth:`pyramid.request.Request.resource_path` now exists. - It works like :meth:`pyramid.request.Request.resource_url`` but produces a + It works like :meth:`pyramid.request.Request.resource_url` but produces a relative URL rather than an absolute one. - The :meth:`pyramid.request.Request.route_url` API now accepts these diff --git a/pyramid/config/adapters.py b/pyramid/config/adapters.py index 04571bec3..5f15f2e46 100644 --- a/pyramid/config/adapters.py +++ b/pyramid/config/adapters.py @@ -1,6 +1,10 @@ from zope.interface import Interface -from pyramid.interfaces import IResponse +from pyramid.interfaces import ( + IResponse, + ITraverser, + IResourceURL, + ) from pyramid.config.util import action_method @@ -72,3 +76,131 @@ class AdaptersConfiguratorMixin(object): # cope with WebOb response objects that aren't decorated with IResponse from webob import Response as WebobResponse self.registry.registerSelfAdapter((WebobResponse,), IResponse) + + @action_method + def add_traverser(self, adapter, iface=None): + """ + The superdefault :term:`traversal` algorithm that :app:`Pyramid` uses + is explained in :ref:`traversal_algorithm`. Though it is rarely + necessary, this default algorithm can be swapped out selectively for + a different traversal pattern via configuration. The section + entitled :ref:`changing_the_traverser` details how to create a + traverser class. + + For example, to override the superdefault traverser used by Pyramid, + you might do something like this: + + .. code-block:: python + + from myapp.traversal import MyCustomTraverser + config.add_traverser(MyCustomTraverser) + + This would cause the Pyramid superdefault traverser to never be used; + intead all traversal would be done using your ``MyCustomTraverser`` + class, no matter which object was returned by the :term:`root + factory` of this application. Note that we passed no arguments to + the ``iface`` keyword parameter. The default value of ``iface``, + ``None`` represents that the registered traverser should be used when + no other more specific traverser is available for the object returned + by the root factory. + + However, more than one traversal algorithm can be active at the same + time. The traverser used can depend on the result of the :term:`root + factory`. For instance, if your root factory returns more than one + type of object conditionally, you could claim that an alternate + traverser adapter should be used agsinst one particular class or + interface returned by that root factory. When the root factory + returned an object that implemented that class or interface, a custom + traverser would be used. Otherwise, the default traverser would be + used. The ``iface`` argument represents the class of the object that + the root factory might return or an :term:`interface` that the object + might implement. + + To use a particular traverser only when the root factory returns a + particular class: + + .. code-block:: python + + config.add_traverser(MyCustomTraverser, MyRootClass) + + When more than one traverser is active, the "most specific" traverser + will be used (the one that matches the class or interface of the + value returned by the root factory most closely). + + Note that either ``adapter`` or ``iface`` can be a :term:`dotted + Python name` or a Python object. + + See :ref:`changing_the_traverser` for more information. + """ + iface = self.maybe_dotted(iface) + adapter= self.maybe_dotted(adapter) + def register(iface=iface): + if iface is None: + iface = Interface + self.registry.registerAdapter(adapter, (iface,), ITraverser) + discriminator = ('traverser', iface) + intr = self.introspectable( + 'traversers', + discriminator, + 'traverser for %r' % iface, + 'traverser', + ) + intr['adapter'] = adapter + intr['iface'] = iface + self.action(discriminator, register, introspectables=(intr,)) + + @action_method + def add_resource_url_adapter(self, adapter, resource_iface=None): + """ + When you add a traverser as described in + :ref:`changing_the_traverser`, it's convenient to continue to use the + :meth:`pyramid.request.Request.resource_url` API. However, since the + way traversal is done may have been modified, the URLs that + ``resource_url`` generates by default may be incorrect when resources + are returned by a custom traverser. + + If you've added a traverser, you can change how + :meth:`~pyramid.request.Request.resource_url` generates a URL for a + specific type of resource by calling this method. + + The ``adapter`` argument represents a class that implements the + :class:`~pyramid.interfaces.IResourceURL` interface. The class + constructor should accept two arguments in its constructor (the + resource and the request) and the resulting instance should provide + the attributes detailed in that interface (``virtual_path`` and + ``physical_path``, in particular). + + The ``resource_iface`` argument represents a class or interface that + the resource should possess for this url adapter to be used when + :meth:`pyramid.request.Request.resource_url` looks up a resource url + adapter. If ``resource_iface`` is not passed, or it is passed as + ``None``, the url adapter will be used for every type of resource. + + See :ref:`changing_resource_url` for more information. + + .. note:: + + This API is new in Pyramid 1.3. + """ + adapter = self.maybe_dotted(adapter) + resource_iface = self.maybe_dotted(resource_iface) + def register(resource_iface=resource_iface): + if resource_iface is None: + resource_iface = Interface + self.registry.registerAdapter( + adapter, + (resource_iface, Interface), + IResourceURL, + ) + discriminator = ('resource url adapter', resource_iface) + intr = self.introspectable( + 'resource url adapters', + discriminator, + 'resource url adapter for resource iface %r' % resource_iface, + 'resource url adapter', + ) + intr['adapter'] = adapter + intr['resource_iface'] = resource_iface + self.action(discriminator, register, introspectables=(intr,)) + + diff --git a/pyramid/config/factories.py b/pyramid/config/factories.py index 76f8d86ed..eb4442e98 100644 --- a/pyramid/config/factories.py +++ b/pyramid/config/factories.py @@ -1,5 +1,3 @@ -from zope.interface import Interface - from pyramid.config.util import action_method from pyramid.interfaces import ( @@ -9,8 +7,6 @@ from pyramid.interfaces import ( IRequestProperties, IRootFactory, ISessionFactory, - ITraverser, - IResourceURL, ) from pyramid.traversal import DefaultRootFactory @@ -144,145 +140,6 @@ class FactoriesConfiguratorMixin(object): self.action(('request properties', name), register, introspectables=(intr,)) - @action_method - def add_traverser(self, factory, iface=None): - """ - The superdefault :term:`traversal` algorithm that :app:`Pyramid` uses - is explained in :ref:`traversal_algorithm`. Though it is rarely - necessary, this default algorithm can be swapped out selectively for - a different traversal pattern via configuration. The section - entitled :ref:`changing_the_traverser` details how to create a - traverser class. - - For example, to override the superdefault traverser used by Pyramid, - you might do something like this: - - .. code-block:: python - - from myapp.traversal import MyCustomTraverser - config.add_traverser(MyCustomTraverser) - - This would cause the Pyramid superdefault traverser to never be used; - intead all traversal would be done using your ``MyCustomTraverser`` - class, no matter which object was returned by the :term:`root - factory` of this application. Note that we passed no arguments to - the ``iface`` keyword parameter. The default value of ``iface``, - ``None`` represents that the registered traverser should be used when - no other more specific traverser is available for the object returned - by the root factory. - - However, more than one traversal algorithm can be active at the same - time. The traverser used can depend on the result of the :term:`root - factory`. For instance, if your root factory returns more than one - type of object conditionally, you could claim that an alternate - traverser adapter should be used agsinst one particular class or - interface returned by that root factory. When the root factory - returned an object that implemented that class or interface, a custom - traverser would be used. Otherwise, the default traverser would be - used. The ``iface`` argument represents the class of the object that - the root factory might return or an :term:`interface` that the object - might implement. - - To use a particular traverser only when the root factory returns a - particular class: - - .. code-block:: python - - config.add_traverser(MyCustomTraverser, MyRootClass) - - When more than one traverser is active, the "most specific" traverser - will be used (the one that matches the class or interface of the - value returned by the root factory most closely). - - Note that either ``factory`` or ``iface`` can be a :term:`dotted - Python name` or a Python object. - - See :ref:`changing_the_traverser` for more information. - """ - iface = self.maybe_dotted(iface) - factory = self.maybe_dotted(factory) - def register(iface=iface): - if iface is None: - iface = Interface - self.registry.registerAdapter(factory, (iface,), ITraverser) - discriminator = ('traverser', iface) - intr = self.introspectable( - 'traversers', - discriminator, - 'traverser for %r' % iface, - 'traverser', - ) - intr['factory'] = factory - intr['iface'] = iface - self.action(discriminator, register, introspectables=(intr,)) - - @action_method - def add_resource_url_adapter(self, factory, resource_iface=None, - request_iface=None): - """ - When you add a traverser as described in - :ref:`changing_the_traverser`, it's convenient to continue to use the - :meth:`pyramid.request.Request.resource_url` API. However, since the - way traversal is done may have been modified, the URLs that - ``resource_url`` generates by default may be incorrect when resources - are returned by a custom traverser. - - If you've added a traverser, you can change how - :meth:`~pyramid.request.Request.resource_url` generates a URL for a - specific type of resource by calling this method. - - The ``factory`` argument represents a class that implements the - :class:`~pyramid.interfaces.IResourceURL` interface. The class - constructor should accept two arguments in its constructor (the - resource and the request) and the resulting instance should provide - the attributes detailed in that interface (``virtual_path`` and - ``physical_path``, in particular). - - The ``resource_iface`` argument represents a class or interface that - the resource should possess for this url adapter to be used when - :meth:`pyramid.request.Request.resource_url` looks up a resource url - adapter. If ``resource_iface`` is not passed, or it is passed as - ``None``, the adapter will be used for every type of resource. - - The ``request_iface`` argument represents a class or interface that - the request should possess for this url adapter to be used when - :meth:`pyramid.request.Request.resource_url` looks up a resource url - adapter. If ``request_iface`` is not epassed, or it is passed as - ``None``, the adapter will be used for every type of request. - - See :ref:`changing_resource_url` for more information. - - .. note:: - - This API is new in Pyramid 1.3. - """ - factory = self.maybe_dotted(factory) - resource_iface = self.maybe_dotted(resource_iface) - request_iface = self.maybe_dotted(request_iface) - def register(resource_iface=resource_iface, - request_iface=request_iface): - if resource_iface is None: - resource_iface = Interface - if request_iface is None: - request_iface = Interface - self.registry.registerAdapter( - factory, - (resource_iface, request_iface), - IResourceURL, - ) - discriminator = ('resource url adapter', resource_iface, request_iface) - intr = self.introspectable( - 'resource url adapters', - discriminator, - 'resource url adapter for resource iface %r, request_iface %r' % ( - resource_iface, request_iface), - 'resource url adapter', - ) - intr['factory'] = factory - intr['resource_iface'] = resource_iface - intr['request_iface'] = request_iface - self.action(discriminator, register, introspectables=(intr,)) - def _set_request_properties(event): request = event.request plist = request.registry.queryUtility(IRequestProperties) diff --git a/pyramid/interfaces.py b/pyramid/interfaces.py index 5b9edf31a..5d9d29afa 100644 --- a/pyramid/interfaces.py +++ b/pyramid/interfaces.py @@ -1,3 +1,5 @@ +from zope.deprecation import deprecated + from zope.interface import ( Attribute, Interface, @@ -780,6 +782,15 @@ class IContextURL(IResourceURL): def __call__(): """ Return a URL that points to the context. """ +deprecated( + 'IContextURL', + 'As of Pyramid 1.3 the, "pyramid.interfaces.IContextURL" interface is ' + 'scheduled to be removed. Use the ' + '"pyramid.config.Configurator.add_resource_url_adapter" method to register ' + 'a class that implements "pyramid.interfaces.IResourceURL" instead. ' + 'See the "What\'s new In Pyramid 1.3" document for a further description.' + ) + class IPackageOverrides(Interface): """ Utility for pkg_resources overrides """ diff --git a/pyramid/mako_templating.py b/pyramid/mako_templating.py index 761695220..b2db28ba7 100644 --- a/pyramid/mako_templating.py +++ b/pyramid/mako_templating.py @@ -65,58 +65,79 @@ class PkgResourceTemplateLookup(TemplateLookup): registry_lock = threading.Lock() -def renderer_factory(info): - path = info.name - registry = info.registry - settings = info.settings - lookup = registry.queryUtility(IMakoLookup) - if lookup is None: - reload_templates = settings.get('reload_templates', False) - directories = settings.get('mako.directories', []) - module_directory = settings.get('mako.module_directory', None) - input_encoding = settings.get('mako.input_encoding', 'utf-8') - error_handler = settings.get('mako.error_handler', None) - default_filters = settings.get('mako.default_filters', 'h') - imports = settings.get('mako.imports', None) - strict_undefined = settings.get('mako.strict_undefined', 'false') - preprocessor = settings.get('mako.preprocessor', None) - if not is_nonstr_iter(directories): - directories = list(filter(None, directories.splitlines())) - directories = [ abspath_from_asset_spec(d) for d in directories ] - if module_directory is not None: - module_directory = abspath_from_asset_spec(module_directory) - if error_handler is not None: - dotted = DottedNameResolver(info.package) - error_handler = dotted.maybe_resolve(error_handler) - if default_filters is not None: - if not is_nonstr_iter(default_filters): - default_filters = list(filter( - None, default_filters.splitlines())) - if imports is not None: - if not is_nonstr_iter(imports): - imports = list(filter(None, imports.splitlines())) - strict_undefined = asbool(strict_undefined) - if preprocessor is not None: - dotted = DottedNameResolver(info.package) - preprocessor = dotted.maybe_resolve(preprocessor) - - - lookup = PkgResourceTemplateLookup(directories=directories, - module_directory=module_directory, - input_encoding=input_encoding, - error_handler=error_handler, - default_filters=default_filters, - imports=imports, - filesystem_checks=reload_templates, - strict_undefined=strict_undefined, - preprocessor=preprocessor) - registry_lock.acquire() - try: - registry.registerUtility(lookup, IMakoLookup) - finally: - registry_lock.release() - - return MakoLookupTemplateRenderer(path, lookup) +class MakoRendererFactoryHelper(object): + def __init__(self, settings_prefix=None): + self.settings_prefix = settings_prefix + + def __call__(self, info): + path = info.name + registry = info.registry + settings = info.settings + settings_prefix = self.settings_prefix + + if settings_prefix is None: + settings_prefix = info.type +'.' + + lookup = registry.queryUtility(IMakoLookup, name=settings_prefix) + + def sget(name, default=None): + return settings.get(settings_prefix + name, default) + + if lookup is None: + reload_templates = settings.get('pyramid.reload_templates', None) + if reload_templates is None: + reload_templates = settings.get('reload_templates', False) + reload_templates = asbool(reload_templates) + directories = sget('directories', []) + module_directory = sget('module_directory', None) + input_encoding = sget('input_encoding', 'utf-8') + error_handler = sget('error_handler', None) + default_filters = sget('default_filters', 'h') + imports = sget('imports', None) + strict_undefined = asbool(sget('strict_undefined', False)) + preprocessor = sget('preprocessor', None) + if not is_nonstr_iter(directories): + directories = list(filter(None, directories.splitlines())) + directories = [ abspath_from_asset_spec(d) for d in directories ] + if module_directory is not None: + module_directory = abspath_from_asset_spec(module_directory) + if error_handler is not None: + dotted = DottedNameResolver(info.package) + error_handler = dotted.maybe_resolve(error_handler) + if default_filters is not None: + if not is_nonstr_iter(default_filters): + default_filters = list(filter( + None, default_filters.splitlines())) + if imports is not None: + if not is_nonstr_iter(imports): + imports = list(filter(None, imports.splitlines())) + if preprocessor is not None: + dotted = DottedNameResolver(info.package) + preprocessor = dotted.maybe_resolve(preprocessor) + + + lookup = PkgResourceTemplateLookup( + directories=directories, + module_directory=module_directory, + input_encoding=input_encoding, + error_handler=error_handler, + default_filters=default_filters, + imports=imports, + filesystem_checks=reload_templates, + strict_undefined=strict_undefined, + preprocessor=preprocessor + ) + + registry_lock.acquire() + try: + registry.registerUtility(lookup, IMakoLookup, + name=settings_prefix) + finally: + registry_lock.release() + + return MakoLookupTemplateRenderer(path, lookup) + +renderer_factory = MakoRendererFactoryHelper('mako.') class MakoRenderingException(Exception): def __init__(self, text): diff --git a/pyramid/paster.py b/pyramid/paster.py index cee437ec4..5102e7b9b 100644 --- a/pyramid/paster.py +++ b/pyramid/paster.py @@ -33,7 +33,7 @@ def get_app(config_uri, name=None, loadapp=loadapp): return app def get_appsettings(config_uri, name=None, appconfig=appconfig): - """ Return a dictionary representing the key/value pairs in an ``app` + """ Return a dictionary representing the key/value pairs in an ``app`` section within the file represented by ``config_uri``. If the ``name`` is None, this will attempt to parse the name from diff --git a/pyramid/scaffolds/alchemy/development.ini_tmpl b/pyramid/scaffolds/alchemy/development.ini_tmpl index 1127aa00f..17ef89856 100644 --- a/pyramid/scaffolds/alchemy/development.ini_tmpl +++ b/pyramid/scaffolds/alchemy/development.ini_tmpl @@ -7,8 +7,9 @@ pyramid.debug_notfound = false pyramid.debug_routematch = false pyramid.debug_templates = true pyramid.default_locale_name = en -pyramid.includes = pyramid_debugtoolbar - pyramid_tm +pyramid.includes = + pyramid_debugtoolbar + pyramid_tm sqlalchemy.url = sqlite:///%(here)s/{{project}}.db diff --git a/pyramid/scaffolds/alchemy/production.ini_tmpl b/pyramid/scaffolds/alchemy/production.ini_tmpl index 9c9335d20..7bce40176 100644 --- a/pyramid/scaffolds/alchemy/production.ini_tmpl +++ b/pyramid/scaffolds/alchemy/production.ini_tmpl @@ -7,7 +7,8 @@ pyramid.debug_notfound = false pyramid.debug_routematch = false pyramid.debug_templates = false pyramid.default_locale_name = en -pyramid.includes = pyramid_tm +pyramid.includes = + pyramid_tm sqlalchemy.url = sqlite:///%(here)s/{{project}}.db diff --git a/pyramid/scaffolds/starter/+package+/templates/mytemplate.pt_tmpl b/pyramid/scaffolds/starter/+package+/templates/mytemplate.pt_tmpl index 8d85ed991..743eab026 100644 --- a/pyramid/scaffolds/starter/+package+/templates/mytemplate.pt_tmpl +++ b/pyramid/scaffolds/starter/+package+/templates/mytemplate.pt_tmpl @@ -32,7 +32,7 @@ <div class="bottom"> <div id="left" class="align-right"> <h2>Search documentation</h2> - <form method="get" action="http://docs.pylonsproject.org/projects/pyramid/current/search.html"> + <form method="get" action="http://docs.pylonsproject.org/projects/pyramid/en/1.3-branch/search.html"> <input type="text" id="q" name="q" value="" /> <input type="submit" id="x" value="Go" /> </form> diff --git a/pyramid/scaffolds/starter/development.ini_tmpl b/pyramid/scaffolds/starter/development.ini_tmpl index ee53fcf1c..4510074da 100644 --- a/pyramid/scaffolds/starter/development.ini_tmpl +++ b/pyramid/scaffolds/starter/development.ini_tmpl @@ -7,7 +7,8 @@ pyramid.debug_notfound = false pyramid.debug_routematch = false pyramid.debug_templates = true pyramid.default_locale_name = en -pyramid.includes = pyramid_debugtoolbar +pyramid.includes = + pyramid_debugtoolbar [server:main] use = egg:waitress#main diff --git a/pyramid/scaffolds/zodb/+package+/templates/mytemplate.pt b/pyramid/scaffolds/zodb/+package+/templates/mytemplate.pt index 0bfac946e..d64f18fca 100644 --- a/pyramid/scaffolds/zodb/+package+/templates/mytemplate.pt +++ b/pyramid/scaffolds/zodb/+package+/templates/mytemplate.pt @@ -32,7 +32,7 @@ <div class="bottom"> <div id="left" class="align-right"> <h2>Search documentation</h2> - <form method="get" action="http://docs.pylonsproject.org/projects/pyramid/current/search.html"> + <form method="get" action="http://docs.pylonsproject.org/projects/pyramid/en/1.3-branch/search.html"> <input type="text" id="q" name="q" value="" /> <input type="submit" id="x" value="Go" /> </form> diff --git a/pyramid/scaffolds/zodb/development.ini_tmpl b/pyramid/scaffolds/zodb/development.ini_tmpl index 6cffd5657..f24583cbf 100644 --- a/pyramid/scaffolds/zodb/development.ini_tmpl +++ b/pyramid/scaffolds/zodb/development.ini_tmpl @@ -7,9 +7,11 @@ pyramid.debug_notfound = false pyramid.debug_routematch = false pyramid.debug_templates = true pyramid.default_locale_name = en -pyramid.includes = pyramid_debugtoolbar - pyramid_zodbconn - pyramid_tm +pyramid.includes = + pyramid_debugtoolbar + pyramid_zodbconn + pyramid_tm + tm.attempts = 3 zodbconn.uri = file://%(here)s/Data.fs?connection_cache_size=20000 diff --git a/pyramid/scaffolds/zodb/production.ini_tmpl b/pyramid/scaffolds/zodb/production.ini_tmpl index c0f2fbbf3..b38252d8f 100644 --- a/pyramid/scaffolds/zodb/production.ini_tmpl +++ b/pyramid/scaffolds/zodb/production.ini_tmpl @@ -7,8 +7,10 @@ pyramid.debug_notfound = false pyramid.debug_routematch = false pyramid.debug_templates = false pyramid.default_locale_name = en -pyramid.includes = pyramid_tm - pyramid_zodbconn +pyramid.includes = + pyramid_tm + pyramid_zodbconn + tm.attempts = 3 zodbconn.uri = file://%(here)s/Data.fs?connection_cache_size=20000 diff --git a/pyramid/tests/test_config/test_adapters.py b/pyramid/tests/test_config/test_adapters.py index 84b7119cf..83ea0f05b 100644 --- a/pyramid/tests/test_config/test_adapters.py +++ b/pyramid/tests/test_config/test_adapters.py @@ -112,3 +112,120 @@ class AdaptersConfiguratorMixinTests(unittest.TestCase): result = config.registry.queryAdapter('foo', IResponse) self.assertTrue(result.body, b'foo') + def test_add_traverser_dotted_names(self): + from pyramid.interfaces import ITraverser + config = self._makeOne(autocommit=True) + config.add_traverser( + 'pyramid.tests.test_config.test_adapters.DummyTraverser', + 'pyramid.tests.test_config.test_adapters.DummyIface') + iface = DummyIface() + traverser = config.registry.getAdapter(iface, ITraverser) + self.assertEqual(traverser.__class__, DummyTraverser) + self.assertEqual(traverser.root, iface) + + def test_add_traverser_default_iface_means_Interface(self): + from pyramid.interfaces import ITraverser + config = self._makeOne(autocommit=True) + config.add_traverser(DummyTraverser) + traverser = config.registry.getAdapter(None, ITraverser) + self.assertEqual(traverser.__class__, DummyTraverser) + + def test_add_traverser_nondefault_iface(self): + from pyramid.interfaces import ITraverser + config = self._makeOne(autocommit=True) + config.add_traverser(DummyTraverser, DummyIface) + iface = DummyIface() + traverser = config.registry.getAdapter(iface, ITraverser) + self.assertEqual(traverser.__class__, DummyTraverser) + self.assertEqual(traverser.root, iface) + + def test_add_traverser_introspectables(self): + config = self._makeOne() + config.add_traverser(DummyTraverser, DummyIface) + actions = config.action_state.actions + self.assertEqual(len(actions), 1) + intrs = actions[0]['introspectables'] + self.assertEqual(len(intrs), 1) + intr = intrs[0] + self.assertEqual(intr.type_name, 'traverser') + self.assertEqual(intr.discriminator, ('traverser', DummyIface)) + self.assertEqual(intr.category_name, 'traversers') + self.assertEqual(intr.title, 'traverser for %r' % DummyIface) + self.assertEqual(intr['adapter'], DummyTraverser) + self.assertEqual(intr['iface'], DummyIface) + + def test_add_resource_url_adapter_dotted_names(self): + from pyramid.interfaces import IResourceURL + config = self._makeOne(autocommit=True) + config.add_resource_url_adapter( + 'pyramid.tests.test_config.test_adapters.DummyResourceURL', + 'pyramid.tests.test_config.test_adapters.DummyIface', + ) + iface = DummyIface() + adapter = config.registry.getMultiAdapter((iface, iface), + IResourceURL) + self.assertEqual(adapter.__class__, DummyResourceURL) + self.assertEqual(adapter.resource, iface) + self.assertEqual(adapter.request, iface) + + def test_add_resource_url_default_resource_iface_means_Interface(self): + from pyramid.interfaces import IResourceURL + config = self._makeOne(autocommit=True) + config.add_resource_url_adapter(DummyResourceURL) + iface = DummyIface() + adapter = config.registry.getMultiAdapter((iface, iface), + IResourceURL) + self.assertEqual(adapter.__class__, DummyResourceURL) + self.assertEqual(adapter.resource, iface) + self.assertEqual(adapter.request, iface) + + def test_add_resource_url_nodefault_resource_iface(self): + from zope.interface import Interface + from pyramid.interfaces import IResourceURL + config = self._makeOne(autocommit=True) + config.add_resource_url_adapter(DummyResourceURL, DummyIface) + iface = DummyIface() + adapter = config.registry.getMultiAdapter((iface, iface), + IResourceURL) + self.assertEqual(adapter.__class__, DummyResourceURL) + self.assertEqual(adapter.resource, iface) + self.assertEqual(adapter.request, iface) + bad_result = config.registry.queryMultiAdapter( + (Interface, Interface), + IResourceURL, + ) + self.assertEqual(bad_result, None) + + def test_add_resource_url_adapter_introspectables(self): + config = self._makeOne() + config.add_resource_url_adapter(DummyResourceURL, DummyIface) + actions = config.action_state.actions + self.assertEqual(len(actions), 1) + intrs = actions[0]['introspectables'] + self.assertEqual(len(intrs), 1) + intr = intrs[0] + self.assertEqual(intr.type_name, 'resource url adapter') + self.assertEqual(intr.discriminator, + ('resource url adapter', DummyIface)) + self.assertEqual(intr.category_name, 'resource url adapters') + self.assertEqual( + intr.title, + "resource url adapter for resource iface " + "<class 'pyramid.tests.test_config.test_adapters.DummyIface'>" + ) + self.assertEqual(intr['adapter'], DummyResourceURL) + self.assertEqual(intr['resource_iface'], DummyIface) + +class DummyTraverser(object): + def __init__(self, root): + self.root = root + +class DummyIface(object): + pass + +class DummyResourceURL(object): + def __init__(self, resource, request): + self.resource = resource + self.request = request + + diff --git a/pyramid/tests/test_config/test_factories.py b/pyramid/tests/test_config/test_factories.py index 5f300a73e..0930f9603 100644 --- a/pyramid/tests/test_config/test_factories.py +++ b/pyramid/tests/test_config/test_factories.py @@ -129,108 +129,6 @@ class TestFactoriesMixin(unittest.TestCase): self.assertEqual(callables, [('foo', foo, False), ('bar', foo, True)]) - def test_add_traverser_dotted_names(self): - from pyramid.interfaces import ITraverser - config = self._makeOne(autocommit=True) - config.add_traverser( - 'pyramid.tests.test_config.test_factories.DummyTraverser', - 'pyramid.tests.test_config.test_factories.DummyIface') - iface = DummyIface() - traverser = config.registry.getAdapter(iface, ITraverser) - self.assertEqual(traverser.__class__, DummyTraverser) - self.assertEqual(traverser.root, iface) - - def test_add_traverser_default_iface_means_Interface(self): - from pyramid.interfaces import ITraverser - config = self._makeOne(autocommit=True) - config.add_traverser(DummyTraverser) - traverser = config.registry.getAdapter(None, ITraverser) - self.assertEqual(traverser.__class__, DummyTraverser) - - def test_add_traverser_nondefault_iface(self): - from pyramid.interfaces import ITraverser - config = self._makeOne(autocommit=True) - config.add_traverser(DummyTraverser, DummyIface) - iface = DummyIface() - traverser = config.registry.getAdapter(iface, ITraverser) - self.assertEqual(traverser.__class__, DummyTraverser) - self.assertEqual(traverser.root, iface) - - def test_add_traverser_introspectables(self): - config = self._makeOne() - config.add_traverser(DummyTraverser, DummyIface) - actions = config.action_state.actions - self.assertEqual(len(actions), 1) - intrs = actions[0]['introspectables'] - self.assertEqual(len(intrs), 1) - intr = intrs[0] - self.assertEqual(intr.type_name, 'traverser') - self.assertEqual(intr.discriminator, ('traverser', DummyIface)) - self.assertEqual(intr.category_name, 'traversers') - self.assertEqual(intr.title, 'traverser for %r' % DummyIface) - - def test_add_resource_url_adapter_dotted_names(self): - from pyramid.interfaces import IResourceURL - config = self._makeOne(autocommit=True) - config.add_resource_url_adapter( - 'pyramid.tests.test_config.test_factories.DummyResourceURL', - 'pyramid.tests.test_config.test_factories.DummyIface', - 'pyramid.tests.test_config.test_factories.DummyIface', - ) - iface = DummyIface() - adapter = config.registry.getMultiAdapter((iface, iface), - IResourceURL) - self.assertEqual(adapter.__class__, DummyResourceURL) - self.assertEqual(adapter.resource, iface) - self.assertEqual(adapter.request, iface) - - def test_add_resource_url_default_interfaces_mean_Interface(self): - from pyramid.interfaces import IResourceURL - config = self._makeOne(autocommit=True) - config.add_resource_url_adapter(DummyResourceURL) - iface = DummyIface() - adapter = config.registry.getMultiAdapter((iface, iface), - IResourceURL) - self.assertEqual(adapter.__class__, DummyResourceURL) - self.assertEqual(adapter.resource, iface) - self.assertEqual(adapter.request, iface) - - def test_add_resource_url_nodefault_interfaces(self): - from zope.interface import Interface - from pyramid.interfaces import IResourceURL - config = self._makeOne(autocommit=True) - config.add_resource_url_adapter(DummyResourceURL, DummyIface, - DummyIface) - iface = DummyIface() - adapter = config.registry.getMultiAdapter((iface, iface), - IResourceURL) - self.assertEqual(adapter.__class__, DummyResourceURL) - self.assertEqual(adapter.resource, iface) - self.assertEqual(adapter.request, iface) - bad_result = config.registry.queryMultiAdapter( - (Interface, Interface), - IResourceURL, - ) - self.assertEqual(bad_result, None) - - def test_add_resource_url_adapter_introspectables(self): - config = self._makeOne() - config.add_resource_url_adapter(DummyResourceURL, DummyIface) - actions = config.action_state.actions - self.assertEqual(len(actions), 1) - intrs = actions[0]['introspectables'] - self.assertEqual(len(intrs), 1) - intr = intrs[0] - self.assertEqual(intr.type_name, 'resource url adapter') - self.assertEqual(intr.discriminator, - ('resource url adapter', DummyIface, None)) - self.assertEqual(intr.category_name, 'resource url adapters') - self.assertEqual( - intr.title, - "resource url adapter for resource iface " - "<class 'pyramid.tests.test_config.test_factories.DummyIface'>, " - "request_iface None" - ) class DummyRequest(object): @@ -244,15 +142,3 @@ class DummyRequest(object): self.callables = [] self.callables.append((name, callable, reify)) -class DummyTraverser(object): - def __init__(self, root): - self.root = root - -class DummyIface(object): - pass - -class DummyResourceURL(object): - def __init__(self, resource, request): - self.resource = resource - self.request = request - diff --git a/pyramid/tests/test_mako_templating.py b/pyramid/tests/test_mako_templating.py index 4c444facf..0726c5250 100644 --- a/pyramid/tests/test_mako_templating.py +++ b/pyramid/tests/test_mako_templating.py @@ -21,8 +21,11 @@ class Test_renderer_factory(Base, unittest.TestCase): from pyramid.mako_templating import renderer_factory return renderer_factory(info) - def test_no_directories(self): + def _getLookup(self, name='mako.'): from pyramid.mako_templating import IMakoLookup + return self.config.registry.getUtility(IMakoLookup, name=name) + + def test_no_directories(self): info = DummyRendererInfo({ 'name':'pyramid.tests:fixtures/helloworld.mak', 'package':None, @@ -30,7 +33,7 @@ class Test_renderer_factory(Base, unittest.TestCase): 'settings':{}, }) renderer = self._callFUT(info) - lookup = self.config.registry.getUtility(IMakoLookup) + lookup = self._getLookup() self.assertEqual(lookup.directories, []) self.assertEqual(lookup.filesystem_checks, False) self.assertEqual(renderer.path, @@ -38,7 +41,6 @@ class Test_renderer_factory(Base, unittest.TestCase): self.assertEqual(renderer.lookup, lookup) def test_no_lookup(self): - from pyramid.mako_templating import IMakoLookup settings = {'mako.directories':self.templates_dir} info = DummyRendererInfo({ 'name':'helloworld.mak', @@ -47,14 +49,13 @@ class Test_renderer_factory(Base, unittest.TestCase): 'settings':settings, }) renderer = self._callFUT(info) - lookup = self.config.registry.getUtility(IMakoLookup) + lookup = self._getLookup() self.assertEqual(lookup.directories, [self.templates_dir]) self.assertEqual(lookup.filesystem_checks, False) self.assertEqual(renderer.path, 'helloworld.mak') self.assertEqual(renderer.lookup, lookup) def test_composite_directories_path(self): - from pyramid.mako_templating import IMakoLookup twice = '\n' + self.templates_dir + '\n' + self.templates_dir + '\n' settings = {'mako.directories':twice} info = DummyRendererInfo({ @@ -64,13 +65,12 @@ class Test_renderer_factory(Base, unittest.TestCase): 'settings':settings, }) self._callFUT(info) - lookup = self.config.registry.getUtility(IMakoLookup) + lookup = self._getLookup() self.assertEqual(lookup.directories, [self.templates_dir]*2) def test_directories_list(self): import sys import os.path - from pyramid.mako_templating import IMakoLookup settings = {'mako.directories':['a', 'b']} info = DummyRendererInfo({ 'name':'helloworld.mak', @@ -79,7 +79,7 @@ class Test_renderer_factory(Base, unittest.TestCase): 'settings':settings, }) self._callFUT(info) - lookup = self.config.registry.getUtility(IMakoLookup) + lookup = self._getLookup() module_path = os.path.dirname( sys.modules['__main__'].__file__).rstrip('.') # ./setup.py self.assertEqual(lookup.directories, [ @@ -88,7 +88,6 @@ class Test_renderer_factory(Base, unittest.TestCase): def test_with_module_directory_asset_spec(self): import os - from pyramid.mako_templating import IMakoLookup module_directory = 'pyramid.tests:fixtures' settings = {'mako.directories':self.templates_dir, 'mako.module_directory':module_directory} @@ -99,13 +98,12 @@ class Test_renderer_factory(Base, unittest.TestCase): 'settings':settings, }) self._callFUT(info) - lookup = self.config.registry.getUtility(IMakoLookup) + lookup = self._getLookup() fixtures = os.path.join(os.path.dirname(__file__), 'fixtures') self.assertEqual(lookup.module_directory, fixtures) def test_with_module_directory_asset_abspath(self): import os - from pyramid.mako_templating import IMakoLookup fixtures = os.path.join(os.path.dirname(__file__), 'fixtures') settings = {'mako.directories':self.templates_dir, 'mako.module_directory':fixtures} @@ -116,11 +114,10 @@ class Test_renderer_factory(Base, unittest.TestCase): 'settings':settings, }) self._callFUT(info) - lookup = self.config.registry.getUtility(IMakoLookup) + lookup = self._getLookup() self.assertEqual(lookup.module_directory, fixtures) def test_with_input_encoding(self): - from pyramid.mako_templating import IMakoLookup settings = {'mako.directories':self.templates_dir, 'mako.input_encoding':'utf-16'} info = DummyRendererInfo({ @@ -130,11 +127,10 @@ class Test_renderer_factory(Base, unittest.TestCase): 'settings':settings, }) self._callFUT(info) - lookup = self.config.registry.getUtility(IMakoLookup) + lookup = self._getLookup() self.assertEqual(lookup.template_args['input_encoding'], 'utf-16') def test_with_error_handler(self): - from pyramid.mako_templating import IMakoLookup settings = {'mako.directories':self.templates_dir, 'mako.error_handler':'pyramid.tests'} import pyramid.tests @@ -145,11 +141,10 @@ class Test_renderer_factory(Base, unittest.TestCase): 'settings':settings, }) self._callFUT(info) - lookup = self.config.registry.getUtility(IMakoLookup) + lookup = self._getLookup() self.assertEqual(lookup.template_args['error_handler'], pyramid.tests) def test_with_preprocessor(self): - from pyramid.mako_templating import IMakoLookup settings = {'mako.directories':self.templates_dir, 'mako.preprocessor':'pyramid.tests'} import pyramid.tests @@ -160,11 +155,10 @@ class Test_renderer_factory(Base, unittest.TestCase): 'settings':settings, }) self._callFUT(info) - lookup = self.config.registry.getUtility(IMakoLookup) + lookup = self._getLookup() self.assertEqual(lookup.template_args['preprocessor'], pyramid.tests) def test_with_default_filters(self): - from pyramid.mako_templating import IMakoLookup settings = {'mako.directories':self.templates_dir, 'mako.default_filters':'\nh\ng\n\n'} info = DummyRendererInfo({ @@ -174,11 +168,10 @@ class Test_renderer_factory(Base, unittest.TestCase): 'settings':settings, }) self._callFUT(info) - lookup = self.config.registry.getUtility(IMakoLookup) + lookup = self._getLookup() self.assertEqual(lookup.template_args['default_filters'], ['h', 'g']) def test_with_default_filters_list(self): - from pyramid.mako_templating import IMakoLookup settings = {'mako.directories':self.templates_dir, 'mako.default_filters':['h', 'g']} info = DummyRendererInfo({ @@ -188,11 +181,10 @@ class Test_renderer_factory(Base, unittest.TestCase): 'settings':settings, }) self._callFUT(info) - lookup = self.config.registry.getUtility(IMakoLookup) + lookup = self._getLookup() self.assertEqual(lookup.template_args['default_filters'], ['h', 'g']) def test_with_imports(self): - from pyramid.mako_templating import IMakoLookup settings = {'mako.directories':self.templates_dir, 'mako.imports':'\none\ntwo\n\n'} info = DummyRendererInfo({ @@ -202,11 +194,10 @@ class Test_renderer_factory(Base, unittest.TestCase): 'settings':settings, }) self._callFUT(info) - lookup = self.config.registry.getUtility(IMakoLookup) + lookup = self._getLookup() self.assertEqual(lookup.template_args['imports'], ['one', 'two']) def test_with_imports_list(self): - from pyramid.mako_templating import IMakoLookup settings = {'mako.directories':self.templates_dir, 'mako.imports':['one', 'two']} info = DummyRendererInfo({ @@ -216,11 +207,10 @@ class Test_renderer_factory(Base, unittest.TestCase): 'settings':settings, }) self._callFUT(info) - lookup = self.config.registry.getUtility(IMakoLookup) + lookup = self._getLookup() self.assertEqual(lookup.template_args['imports'], ['one', 'two']) def test_with_strict_undefined_true(self): - from pyramid.mako_templating import IMakoLookup settings = {'mako.directories':self.templates_dir, 'mako.strict_undefined':'true'} info = DummyRendererInfo({ @@ -230,11 +220,10 @@ class Test_renderer_factory(Base, unittest.TestCase): 'settings':settings, }) self._callFUT(info) - lookup = self.config.registry.getUtility(IMakoLookup) + lookup = self._getLookup() self.assertEqual(lookup.template_args['strict_undefined'], True) def test_with_strict_undefined_false(self): - from pyramid.mako_templating import IMakoLookup settings = {'mako.directories':self.templates_dir, 'mako.strict_undefined':'false'} info = DummyRendererInfo({ @@ -244,13 +233,13 @@ class Test_renderer_factory(Base, unittest.TestCase): 'settings':settings, }) self._callFUT(info) - lookup = self.config.registry.getUtility(IMakoLookup) + lookup = self._getLookup() self.assertEqual(lookup.template_args['strict_undefined'], False) def test_with_lookup(self): from pyramid.mako_templating import IMakoLookup lookup = dict() - self.config.registry.registerUtility(lookup, IMakoLookup) + self.config.registry.registerUtility(lookup, IMakoLookup, name='mako.') info = DummyRendererInfo({ 'name':'helloworld.mak', 'package':None, @@ -261,6 +250,53 @@ class Test_renderer_factory(Base, unittest.TestCase): self.assertEqual(renderer.lookup, lookup) self.assertEqual(renderer.path, 'helloworld.mak') +class MakoRendererFactoryHelperTests(Base, unittest.TestCase): + def _getTargetClass(self): + from pyramid.mako_templating import MakoRendererFactoryHelper + return MakoRendererFactoryHelper + + def _makeOne(self, *arg, **kw): + klass = self._getTargetClass() + return klass(*arg, **kw) + + def _getLookup(self, name='mako.'): + from pyramid.mako_templating import IMakoLookup + return self.config.registry.getUtility(IMakoLookup, name=name) + + def test_no_settings_prefix(self): + settings = {'foo.directories':self.templates_dir} + info = DummyRendererInfo({ + 'name':'helloworld.mak', + 'package':None, + 'registry':self.config.registry, + 'settings':settings, + 'type':'foo', + }) + helper = self._makeOne() + renderer = helper(info) + lookup = self._getLookup('foo.') + self.assertEqual(lookup.directories, [self.templates_dir]) + self.assertEqual(lookup.filesystem_checks, False) + self.assertEqual(renderer.path, 'helloworld.mak') + self.assertEqual(renderer.lookup, lookup) + + def test_custom_settings_prefix(self): + settings = {'bar.directories':self.templates_dir} + info = DummyRendererInfo({ + 'name':'helloworld.mak', + 'package':None, + 'registry':self.config.registry, + 'settings':settings, + 'type':'foo', + }) + helper = self._makeOne('bar.') + renderer = helper(info) + lookup = self._getLookup('bar.') + self.assertEqual(lookup.directories, [self.templates_dir]) + self.assertEqual(lookup.filesystem_checks, False) + self.assertEqual(renderer.path, 'helloworld.mak') + self.assertEqual(renderer.lookup, lookup) + class MakoLookupTemplateRendererTests(Base, unittest.TestCase): def _getTargetClass(self): from pyramid.mako_templating import MakoLookupTemplateRenderer diff --git a/pyramid/tests/test_traversal.py b/pyramid/tests/test_traversal.py index 1f9971ca5..8e0bb2494 100644 --- a/pyramid/tests/test_traversal.py +++ b/pyramid/tests/test_traversal.py @@ -1,6 +1,8 @@ import unittest +import warnings from pyramid.testing import cleanUp + from pyramid.compat import ( text_, native_, @@ -9,6 +11,11 @@ from pyramid.compat import ( PY3, ) +with warnings.catch_warnings(record=True) as w: + warnings.filterwarnings('always') + from pyramid.interfaces import IContextURL + assert(len(w) == 1) + class TraversalPathTests(unittest.TestCase): def _callFUT(self, path): from pyramid.traversal import traversal_path @@ -452,9 +459,8 @@ class ResourceTreeTraverserTests(unittest.TestCase): self.assertEqual(result['virtual_root_path'], ()) def test_call_with_environ(self): - import warnings - warnings.filterwarnings('ignore') - try: + with warnings.catch_warnings(record=True) as w: + warnings.filterwarnings('always') policy = self._makeOne(None) environ = self._getEnviron() result = policy(environ) @@ -465,8 +471,7 @@ class ResourceTreeTraverserTests(unittest.TestCase): self.assertEqual(result['root'], policy.root) self.assertEqual(result['virtual_root'], policy.root) self.assertEqual(result['virtual_root_path'], ()) - finally: - warnings.resetwarnings() + self.assertEqual(len(w), 1) class FindInterfaceTests(unittest.TestCase): def _callFUT(self, context, iface): @@ -857,13 +862,13 @@ class QuotePathSegmentTests(unittest.TestCase): result = self._callFUT(s) self.assertEqual(result, 'abc') -class TraversalContextURLTests(unittest.TestCase): +class ResourceURLTests(unittest.TestCase): def _makeOne(self, context, url): return self._getTargetClass()(context, url) def _getTargetClass(self): - from pyramid.traversal import TraversalContextURL - return TraversalContextURL + from pyramid.traversal import ResourceURL + return ResourceURL def _registerTraverser(self, traverser): from pyramid.threadlocal import get_current_registry @@ -873,17 +878,23 @@ class TraversalContextURLTests(unittest.TestCase): reg.registerAdapter(traverser, (Interface,), ITraverser) def test_class_conforms_to_IContextURL(self): + # bw compat from zope.interface.verify import verifyClass - from pyramid.interfaces import IContextURL verifyClass(IContextURL, self._getTargetClass()) def test_instance_conforms_to_IContextURL(self): from zope.interface.verify import verifyObject - from pyramid.interfaces import IContextURL context = DummyContext() request = DummyRequest() verifyObject(IContextURL, self._makeOne(context, request)) + def test_instance_conforms_to_IResourceURL(self): + from pyramid.interfaces import IResourceURL + from zope.interface.verify import verifyObject + context = DummyContext() + request = DummyRequest() + verifyObject(IResourceURL, self._makeOne(context, request)) + def test_call_withlineage(self): baz = DummyContext() bar = DummyContext(baz) @@ -965,39 +976,7 @@ class TraversalContextURLTests(unittest.TestCase): result = context_url() self.assertEqual(result, 'http://example.com:5432/one/two/') - def test_virtual_root_no_virtual_root_path(self): - root = DummyContext() - root.__name__ = None - root.__parent__ = None - one = DummyContext() - one.__name__ = 'one' - one.__parent__ = root - request = DummyRequest() - context_url = self._makeOne(one, request) - self.assertEqual(context_url.virtual_root(), root) - - def test_virtual_root_no_virtual_root_path_with_root_on_request(self): - context = DummyContext() - context.__parent__ = None - request = DummyRequest() - request.root = DummyContext() - context_url = self._makeOne(context, request) - self.assertEqual(context_url.virtual_root(), request.root) - - def test_virtual_root_with_virtual_root_path(self): - from pyramid.interfaces import VH_ROOT_KEY - context = DummyContext() - context.__parent__ = None - traversed_to = DummyContext() - environ = {VH_ROOT_KEY:'/one'} - request = DummyRequest(environ) - traverser = make_traverser({'context':traversed_to, 'view_name':''}) - self._registerTraverser(traverser) - context_url = self._makeOne(context, request) - self.assertEqual(context_url.virtual_root(), traversed_to) - self.assertEqual(context.request.environ['PATH_INFO'], '/one') - - def test_empty_names_not_ignored(self): + def test_call_empty_names_not_ignored(self): bar = DummyContext() empty = DummyContext(bar) root = DummyContext(empty) @@ -1012,7 +991,7 @@ class TraversalContextURLTests(unittest.TestCase): result = context_url() self.assertEqual(result, 'http://example.com:5432//bar/') - def test_local_url_returns_None(self): + def test_call_local_url_returns_None(self): resource = DummyContext() def resource_url(request, info): self.assertEqual(info['virtual_path'], '/') @@ -1024,7 +1003,7 @@ class TraversalContextURLTests(unittest.TestCase): result = context_url() self.assertEqual(result, 'http://example.com:5432/') - def test_local_url_returns_url(self): + def test_call_local_url_returns_url(self): resource = DummyContext() def resource_url(request, info): self.assertEqual(info['virtual_path'], '/') @@ -1036,6 +1015,71 @@ class TraversalContextURLTests(unittest.TestCase): result = context_url() self.assertEqual(result, 'abc') + def test_virtual_root_no_virtual_root_path(self): + root = DummyContext() + root.__name__ = None + root.__parent__ = None + one = DummyContext() + one.__name__ = 'one' + one.__parent__ = root + request = DummyRequest() + context_url = self._makeOne(one, request) + self.assertEqual(context_url.virtual_root(), root) + + def test_virtual_root_no_virtual_root_path_with_root_on_request(self): + context = DummyContext() + context.__parent__ = None + request = DummyRequest() + request.root = DummyContext() + context_url = self._makeOne(context, request) + self.assertEqual(context_url.virtual_root(), request.root) + + def test_virtual_root_with_virtual_root_path(self): + from pyramid.interfaces import VH_ROOT_KEY + context = DummyContext() + context.__parent__ = None + traversed_to = DummyContext() + environ = {VH_ROOT_KEY:'/one'} + request = DummyRequest(environ) + traverser = make_traverser({'context':traversed_to, 'view_name':''}) + self._registerTraverser(traverser) + context_url = self._makeOne(context, request) + self.assertEqual(context_url.virtual_root(), traversed_to) + self.assertEqual(context.request.environ['PATH_INFO'], '/one') + + def test_IResourceURL_attributes_with_vroot(self): + from pyramid.interfaces import VH_ROOT_KEY + root = DummyContext() + root.__parent__ = None + root.__name__ = None + one = DummyContext() + one.__parent__ = root + one.__name__ = 'one' + two = DummyContext() + two.__parent__ = one + two.__name__ = 'two' + environ = {VH_ROOT_KEY:'/one'} + request = DummyRequest(environ) + context_url = self._makeOne(two, request) + self.assertEqual(context_url.physical_path, '/one/two/') + self.assertEqual(context_url.virtual_path, '/two/') + + def test_IResourceURL_attributes_no_vroot(self): + root = DummyContext() + root.__parent__ = None + root.__name__ = None + one = DummyContext() + one.__parent__ = root + one.__name__ = 'one' + two = DummyContext() + two.__parent__ = one + two.__name__ = 'two' + environ = {} + request = DummyRequest(environ) + context_url = self._makeOne(two, request) + self.assertEqual(context_url.physical_path, '/one/two/') + self.assertEqual(context_url.virtual_path, '/one/two/') + class TestVirtualRoot(unittest.TestCase): def setUp(self): cleanUp() @@ -1048,7 +1092,6 @@ class TestVirtualRoot(unittest.TestCase): return virtual_root(resource, request) def test_registered(self): - from pyramid.interfaces import IContextURL from zope.interface import Interface request = _makeRequest() request.registry.registerAdapter(DummyContextURL, (Interface,Interface), diff --git a/pyramid/tests/test_url.py b/pyramid/tests/test_url.py index 3c36363ed..7b05368ce 100644 --- a/pyramid/tests/test_url.py +++ b/pyramid/tests/test_url.py @@ -27,7 +27,8 @@ class TestURLMethodsMixin(unittest.TestCase): return request def _registerContextURL(self, reg): - from pyramid.interfaces import IContextURL + with warnings.catch_warnings(record=True): + from pyramid.interfaces import IContextURL from zope.interface import Interface class DummyContextURL(object): def __init__(self, context, request): diff --git a/pyramid/traversal.py b/pyramid/traversal.py index 9801f8f18..b514d4c16 100644 --- a/pyramid/traversal.py +++ b/pyramid/traversal.py @@ -1,5 +1,7 @@ import warnings +from zope.deprecation import deprecated + from zope.interface import implementer from zope.interface.interfaces import IInterface @@ -7,12 +9,15 @@ from repoze.lru import lru_cache from pyramid.interfaces import ( IResourceURL, - IContextURL, IRequestFactory, ITraverser, VH_ROOT_KEY, ) +with warnings.catch_warnings(): + warnings.filterwarnings('ignore') + from pyramid.interfaces import IContextURL + from pyramid.compat import ( PY3, native_, @@ -751,10 +756,12 @@ class ResourceURL(object): if physical_path.startswith(vroot_path): virtual_path = physical_path[len(vroot_path):] - self.virtual_path = virtual_path - self.physical_path = physical_path + self.virtual_path = virtual_path # IResourceURL attr + self.physical_path = physical_path # IResourceURL attr + + # bw compat for IContextURL methods self.resource = resource - self.context = resource # bw compat alias for IContextURL compat + self.context = resource self.request = request # IContextURL method (deprecated in 1.3) @@ -794,7 +801,16 @@ class ResourceURL(object): app_url = self.request.application_url # never ends in a slash return app_url + self.virtual_path -TraversalContextURL = ResourceURL # bw compat as of 1.3 +TraversalContextURL = ResourceURL # deprecated as of 1.3 + +deprecated( + 'TraversalContextURL', + 'As of Pyramid 1.3 the, "pyramid.traversal.TraversalContextURL" class is ' + 'scheduled to be removed. Use the ' + '"pyramid.config.Configurator.add_resource_url_adapter" method to register ' + 'a class that implements "pyramid.interfaces.IResourceURL" instead. ' + 'See the "What\'s new In Pyramid 1.3" document for a further description.' + ) @lru_cache(1000) def _join_path_tuple(tuple): @@ -56,7 +56,7 @@ if not PY3: ]) setup(name='pyramid', - version='1.3a7', + version='1.3a8', description=('The Pyramid web application development framework, a ' 'Pylons project'), long_description=README + '\n\n' + CHANGES, |
