summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris McDonough <chrism@plope.com>2012-02-19 17:55:38 -0500
committerChris McDonough <chrism@plope.com>2012-02-19 17:55:38 -0500
commit4c3cca9d034818d3ab280bd3a1ff890b543bfa81 (patch)
tree42cd6958e035436b2bd5d8ee1f5e844983c86837
parent5baff75c94768628e777ec74fe8f653ef69dd0db (diff)
parent51919e05d9c251f7f80a4736be2b822eafc5d189 (diff)
downloadpyramid-4c3cca9d034818d3ab280bd3a1ff890b543bfa81.tar.gz
pyramid-4c3cca9d034818d3ab280bd3a1ff890b543bfa81.tar.bz2
pyramid-4c3cca9d034818d3ab280bd3a1ff890b543bfa81.zip
Merge branch '1.3-branch'
-rw-r--r--CHANGES.txt20
-rw-r--r--CONTRIBUTORS.txt2
-rw-r--r--TODO.txt28
-rw-r--r--docs/api/config.rst147
-rw-r--r--docs/conf.py2
-rw-r--r--docs/glossary.rst11
-rw-r--r--docs/narr/MyProject/development.ini3
-rw-r--r--docs/narr/advconfig.rst20
-rw-r--r--docs/narr/hooks.rst18
-rw-r--r--docs/narr/introspector.rst22
-rw-r--r--docs/narr/project.rst31
-rw-r--r--docs/tutorials/wiki/src/authorization/development.ini8
-rw-r--r--docs/tutorials/wiki/src/authorization/production.ini6
-rw-r--r--docs/tutorials/wiki/src/basiclayout/development.ini8
-rw-r--r--docs/tutorials/wiki/src/basiclayout/production.ini6
-rw-r--r--docs/tutorials/wiki/src/models/development.ini8
-rw-r--r--docs/tutorials/wiki/src/models/production.ini6
-rw-r--r--docs/tutorials/wiki/src/tests/development.ini8
-rw-r--r--docs/tutorials/wiki/src/tests/production.ini6
-rw-r--r--docs/tutorials/wiki/src/views/development.ini8
-rw-r--r--docs/tutorials/wiki/src/views/production.ini6
-rw-r--r--docs/tutorials/wiki2/src/authorization/development.ini5
-rw-r--r--docs/tutorials/wiki2/src/authorization/production.ini3
-rw-r--r--docs/tutorials/wiki2/src/basiclayout/development.ini5
-rw-r--r--docs/tutorials/wiki2/src/basiclayout/production.ini3
-rw-r--r--docs/tutorials/wiki2/src/models/development.ini5
-rw-r--r--docs/tutorials/wiki2/src/models/production.ini3
-rw-r--r--docs/tutorials/wiki2/src/tests/development.ini5
-rw-r--r--docs/tutorials/wiki2/src/tests/production.ini3
-rw-r--r--docs/tutorials/wiki2/src/views/development.ini5
-rw-r--r--docs/tutorials/wiki2/src/views/production.ini3
-rw-r--r--docs/whatsnew-1.3.rst7
-rw-r--r--pyramid/config/adapters.py134
-rw-r--r--pyramid/config/factories.py143
-rw-r--r--pyramid/interfaces.py11
-rw-r--r--pyramid/mako_templating.py125
-rw-r--r--pyramid/paster.py2
-rw-r--r--pyramid/scaffolds/alchemy/development.ini_tmpl5
-rw-r--r--pyramid/scaffolds/alchemy/production.ini_tmpl3
-rw-r--r--pyramid/scaffolds/starter/+package+/templates/mytemplate.pt_tmpl2
-rw-r--r--pyramid/scaffolds/starter/development.ini_tmpl3
-rw-r--r--pyramid/scaffolds/zodb/+package+/templates/mytemplate.pt2
-rw-r--r--pyramid/scaffolds/zodb/development.ini_tmpl8
-rw-r--r--pyramid/scaffolds/zodb/production.ini_tmpl6
-rw-r--r--pyramid/tests/test_config/test_adapters.py117
-rw-r--r--pyramid/tests/test_config/test_factories.py114
-rw-r--r--pyramid/tests/test_mako_templating.py98
-rw-r--r--pyramid/tests/test_traversal.py135
-rw-r--r--pyramid/tests/test_url.py3
-rw-r--r--pyramid/traversal.py26
-rw-r--r--setup.py2
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
diff --git a/TODO.txt b/TODO.txt
index ab26a87a8..90f5f8547 100644
--- a/TODO.txt
+++ b/TODO.txt
@@ -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):
diff --git a/setup.py b/setup.py
index a6cfa1480..7a5e80c67 100644
--- a/setup.py
+++ b/setup.py
@@ -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,