summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES.txt112
-rw-r--r--TODO.txt56
-rw-r--r--docs/api.rst2
-rw-r--r--docs/api/chameleon_text.rst31
-rw-r--r--docs/api/chameleon_zpt.rst28
-rw-r--r--docs/api/config.rst2
-rw-r--r--docs/api/settings.rst2
-rw-r--r--docs/changes.rst2
-rw-r--r--docs/index.rst1
-rw-r--r--docs/latexindex.rst2
-rw-r--r--docs/narr/advconfig.rst2
-rw-r--r--docs/narr/templates.rst30
-rw-r--r--docs/narr/testing.rst2
-rw-r--r--docs/narr/upgrading.rst232
-rw-r--r--docs/tutorials/modwsgi/index.rst22
-rw-r--r--docs/tutorials/wiki/src/authorization/tutorial/views.py10
-rw-r--r--docs/tutorials/wiki/src/tests/tutorial/views.py10
-rw-r--r--docs/tutorials/wiki/src/views/tutorial/views.py10
-rw-r--r--docs/tutorials/wiki2/src/authorization/tutorial/views.py16
-rw-r--r--docs/tutorials/wiki2/src/tests/tutorial/views.py16
-rw-r--r--docs/tutorials/wiki2/src/views/tutorial/views.py16
-rw-r--r--pyramid/chameleon_text.py94
-rw-r--r--pyramid/chameleon_zpt.py91
-rw-r--r--pyramid/config/factories.py21
-rw-r--r--pyramid/configuration.py60
-rw-r--r--pyramid/paster.py10
-rw-r--r--pyramid/request.py9
-rw-r--r--pyramid/router.py16
-rw-r--r--pyramid/scripting.py7
-rw-r--r--pyramid/settings.py26
-rw-r--r--pyramid/testing.py376
-rw-r--r--pyramid/tests/fixtures/withmacro.pt3
-rw-r--r--pyramid/tests/test_chameleon_text.py112
-rw-r--r--pyramid/tests/test_chameleon_zpt.py125
-rw-r--r--pyramid/tests/test_config/test_factories.py67
-rw-r--r--pyramid/tests/test_config/test_settings.py9
-rw-r--r--pyramid/tests/test_configuration.py31
-rw-r--r--pyramid/tests/test_path.py6
-rw-r--r--pyramid/tests/test_renderers.py14
-rw-r--r--pyramid/tests/test_request.py12
-rw-r--r--pyramid/tests/test_router.py36
-rw-r--r--pyramid/tests/test_scripting.py81
-rw-r--r--pyramid/tests/test_settings.py26
-rw-r--r--pyramid/tests/test_testing.py289
-rw-r--r--pyramid/tests/test_traversal.py172
-rw-r--r--pyramid/tests/test_util.py14
-rw-r--r--pyramid/traversal.py32
-rw-r--r--pyramid/util.py7
-rw-r--r--setup.py2
-rw-r--r--tox.ini33
50 files changed, 791 insertions, 1594 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index bb726738c..47f51575c 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,6 +1,7 @@
Next release
============
+
Bug Fixes
---------
@@ -86,7 +87,7 @@ Features
HEAD is a variant of GET that omits the body, and WebOb has special support
to return an empty body when a HEAD is used.
-- ``config.set_request_method`` has been introduced to support extending
+- ``config.add_request_method`` has been introduced to support extending
request objects with arbitrary callables. This method expands on the
previous ``config.set_request_property`` by supporting methods as well as
properties. This method now causes less code to be executed at
@@ -143,11 +144,118 @@ Features
to influence how the sessions are marshalled (by default this is done
with HMAC+pickle).
+- ``pyramid.testing.DummyRequest`` now supports methods supplied by the
+ ``pyramid.util.InstancePropertyMixin`` class such as ``set_property``.
+
+- Request properties and methods added via ``config.set_request_property`` or
+ ``config.add_request_method`` are now available to tweens.
+
+- Request properties and methods added via ``config.set_request_property`` or
+ ``config.add_request_method`` are now available to tweens.
+
+- Request properties and methods added via ``config.set_request_property`` or
+ ``config.add_request_method`` are now available in the request object
+ returned from ``pyramid.paster.bootstrap``.
+
+- ``request.context`` of environment request during ``bootstrap`` is now the
+ root object if a context isn't already set on a provided request.
+
Deprecations
------------
- The ``pyramid.config.Configurator.set_request_property`` has been
documentation-deprecated. The method remains usable but the more
- featureful ``pyramid.config.Configurator.set_request_method`` should be
+ featureful ``pyramid.config.Configurator.add_request_method`` should be
used in its place (it has all of the same capabilities but can also extend
the request object with methods).
+
+Backwards Incompatibilities
+---------------------------
+
+- The Pyramid router no longer adds the values ``bfg.routes.route`` or
+ ``bfg.routes.matchdict`` to the request's WSGI environment dictionary.
+ These values were docs-deprecated in ``repoze.bfg`` 1.0 (effectively seven
+ minor releases ago). If your code depended on these values, use
+ request.matched_route and request.matchdict instead.
+
+- It is no longer possible to pass an environ dictionary directly to
+ ``pyramid.traversal.ResourceTreeTraverser.__call__`` (aka
+ ``ModelGraphTraverser.__call__``). Instead, you must pass a request
+ object. Passing an environment instead of a request has generated a
+ deprecation warning since Pyramid 1.1.
+
+- Pyramid will no longer work properly if you use the
+ ``webob.request.LegacyRequest`` as a request factory. Instances of the
+ LegacyRequest class have a ``request.path_info`` which return a string.
+ This Pyramid release assumes that ``request.path_info`` will
+ unconditionally be Unicode.
+
+- The functions from ``pyramid.chameleon_zpt`` and ``pyramid.chameleon_text``
+ named ``get_renderer``, ``get_template``, ``render_template``, and
+ ``render_template_to_response`` have been removed. These have issued a
+ deprecation warning upon import since Pyramid 1.0. Use
+ ``pyramid.renderers.get_renderer()``,
+ ``pyramid.renderers.get_renderer().implementation()``,
+ ``pyramid.renderers.render()`` or ``pyramid.renderers.render_to_response``
+ respectively instead of these functions.
+
+- The ``pyramid.configuration`` module was removed. It had been deprecated
+ since Pyramid 1.0 and printed a deprecation warning upon its use. Use
+ ``pyramid.config`` instead.
+
+- The ``pyramid.paster.PyramidTemplate`` API was removed. It had been
+ deprecated since Pyramid 1.1 and issued a warning on import. If your code
+ depended on this, adjust your code to import
+ ``pyramid.scaffolds.PyramidTemplate`` instead.
+
+- The ``pyramid.settings.get_settings()`` API was removed. It had been
+ printing a deprecation warning since Pyramid 1.0. If your code depended on
+ this API, use ``pyramid.threadlocal.get_current_registry().settings``
+ instead or use the ``settings`` attribute of the registry available from
+ the request (``request.registry.settings``).
+
+- These APIs from the ``pyramid.testing`` module were removed. They have
+ been printing deprecation warnings since Pyramid 1.0:
+
+ * ``registerDummySecurityPolicy``, use
+ ``pyramid.config.Configurator.testing_securitypolicy`` instead.
+
+ * ``registerResources`` (aka ``registerModels``, use
+ ``pyramid.config.Configurator.testing_resources`` instead.
+
+ * ``registerEventListener``, use
+ ``pyramid.config.Configurator.testing_add_subscriber`` instead.
+
+ * ``registerTemplateRenderer`` (aka `registerDummyRenderer``), use
+ ``pyramid.config.Configurator.testing_add_template`` instead.
+
+ * ``registerView``, use ``pyramid.config.Configurator.add_view`` instead.
+
+ * ``registerUtility``, use
+ ``pyramid.config.Configurator.registry.registerUtility`` instead.
+
+ * ``registerAdapter``, use
+ ``pyramid.config.Configurator.registry.registerAdapter`` instead.
+
+ * ``registerSubscriber``, use
+ ``pyramid.config.Configurator.add_subscriber`` instead.
+
+ * ``registerRoute``, use
+ ``pyramid.config.Configurator.add_route`` instead.
+
+ * ``registerSettings``, use
+ ``pyramid.config.Configurator.add_settings`` instead.
+
+Documentation
+-------------
+
+- Added an "Upgrading Pyramid" chapter to the narrative documentation. It
+ describes how to cope with deprecations and removals of Pyramid APIs.
+
+Dependencies
+------------
+
+- Pyramid now requires WebOb 1.2b3+ (the prior Pyramid release only relied on
+ 1.2dev+). This is to ensure that we obtain a version of WebOb that returns
+ ``request.path_info`` as text.
+
diff --git a/TODO.txt b/TODO.txt
index d1209f325..a13433f54 100644
--- a/TODO.txt
+++ b/TODO.txt
@@ -95,21 +95,49 @@ Nice-to-Have
- Update App engine chapter with less creaky directions.
+- Idea from Zart:
+
+ diff --git a/pyramid/paster.py b/pyramid/paster.py
+ index b0e4d79..b3bd82a 100644
+ --- a/pyramid/paster.py
+ +++ b/pyramid/paster.py
+ @@ -8,6 +8,7 @@ from paste.deploy import (
+ from pyramid.compat import configparser
+ from logging.config import fileConfig
+ from pyramid.scripting import prepare
+ +from pyramid.config import Configurator
+
+ def get_app(config_uri, name=None, loadapp=loadapp):
+ """ Return the WSGI application named ``name`` in the PasteDeploy
+ @@ -111,3 +112,10 @@ def bootstrap(config_uri, request=None):
+ env['app'] = app
+ return env
+
+ +def make_pyramid_app(global_conf, app=None, **settings):
+ + """Return pyramid application configured with provided settings"""
+ + config = Configurator(package='pyramid', settings=settings)
+ + if app:
+ + config.include(app)
+ + app = config.make_wsgi_app()
+ + return app
+ diff --git a/setup.py b/setup.py
+ index 03ebb42..91e0e21 100644
+ --- a/setup.py
+ +++ b/setup.py
+ @@ -118,6 +118,8 @@ setup(name='pyramid',
+ [paste.server_runner]
+ wsgiref = pyramid.scripts.pserve:wsgiref_server_runner
+ cherrypy = pyramid.scripts.pserve:cherrypy_server_runner
+ + [paster.app_factory]
+ + main = pyramid.paster:make_pyramid_app
+ """
+ )
+
+
Future
------
-- 1.4: Kill off ``bfg.routes`` envvars in router.
-
-- 1.4: Remove ``chameleon_text`` / ``chameleon_zpt`` deprecated functions
- (render_*)
-
-- 1.4: Remove ``pyramid.configuration`` (deprecated).
-
-- 1.4: Remove ``pyramid.paster.PyramidTemplate`` (deprecated).
-
-- 1.4: Remove ``pyramid.settings.get_settings`` (deprecated).
-
-- 1.5: Remove all deprecated ``pyramid.testing`` functions.
+- 1.5: remove ``pyramid.view.static`` and ``pyramid.view.is_response``.
- 1.5: turn ``pyramid.settings.Settings`` into a function that returns the
original dict (after ``__getattr__`` deprecation period, it was deprecated
@@ -117,8 +145,8 @@ Future
- 1.5: Remove ``pyramid.requests.DeprecatedRequestMethodsMixin``.
-- 1.6: Maybe? deprecate set_request_property in favor of pointing people at
- set_request_method.
+- 1.5: Maybe? deprecate set_request_property in favor of pointing people at
+ add_request_method, schedule removal for 1.8?
- 1.6: Remove IContextURL and TraversalContextURL.
diff --git a/docs/api.rst b/docs/api.rst
index d510c0d27..e33fd6a74 100644
--- a/docs/api.rst
+++ b/docs/api.rst
@@ -10,8 +10,6 @@ documentation is organized alphabetically by module name.
api/authorization
api/authentication
- api/chameleon_text
- api/chameleon_zpt
api/compat
api/config
api/events
diff --git a/docs/api/chameleon_text.rst b/docs/api/chameleon_text.rst
deleted file mode 100644
index 494f5b464..000000000
--- a/docs/api/chameleon_text.rst
+++ /dev/null
@@ -1,31 +0,0 @@
-.. _chameleon_text_module:
-
-:mod:`pyramid.chameleon_text`
-----------------------------------
-
-.. automodule:: pyramid.chameleon_text
-
- .. autofunction:: get_template
-
- .. autofunction:: render_template
-
- .. autofunction:: render_template_to_response
-
-These APIs will will work against template files which contain simple
-``${Genshi}`` - style replacement markers.
-
-The API of :mod:`pyramid.chameleon_text` is identical to that of
-:mod:`pyramid.chameleon_zpt`; only its import location is
-different. If you need to import an API functions from this module as
-well as the :mod:`pyramid.chameleon_zpt` module within the same
-view file, use the ``as`` feature of the Python import statement,
-e.g.:
-
-.. code-block:: python
- :linenos:
-
- from pyramid.chameleon_zpt import render_template as zpt_render
- from pyramid.chameleon_text import render_template as text_render
-
-
-
diff --git a/docs/api/chameleon_zpt.rst b/docs/api/chameleon_zpt.rst
deleted file mode 100644
index df9a36a56..000000000
--- a/docs/api/chameleon_zpt.rst
+++ /dev/null
@@ -1,28 +0,0 @@
-.. _chameleon_zpt_module:
-
-:mod:`pyramid.chameleon_zpt`
--------------------------------
-
-.. automodule:: pyramid.chameleon_zpt
-
- .. autofunction:: get_template
-
- .. autofunction:: render_template
-
- .. autofunction:: render_template_to_response
-
-These APIs will work against files which supply template text which
-matches the :term:`ZPT` specification.
-
-The API of :mod:`pyramid.chameleon_zpt` is identical to that of
-:mod:`pyramid.chameleon_text`; only its import location is
-different. If you need to import an API functions from this module as
-well as the :mod:`pyramid.chameleon_text` module within the same
-view file, use the ``as`` feature of the Python import statement,
-e.g.:
-
-.. code-block:: python
- :linenos:
-
- from pyramid.chameleon_zpt import render_template as zpt_render
- from pyramid.chameleon_text import render_template as text_render
diff --git a/docs/api/config.rst b/docs/api/config.rst
index 028a55d4b..5d2bce23e 100644
--- a/docs/api/config.rst
+++ b/docs/api/config.rst
@@ -40,7 +40,7 @@
:methodcategory:`Extending the Request Object`
- .. automethod:: set_request_method
+ .. automethod:: add_request_method
.. automethod:: set_request_property
:methodcategory:`Using I18N`
diff --git a/docs/api/settings.rst b/docs/api/settings.rst
index 6b12c038c..cd802e138 100644
--- a/docs/api/settings.rst
+++ b/docs/api/settings.rst
@@ -5,8 +5,6 @@
.. automodule:: pyramid.settings
- .. autofunction:: get_settings
-
.. autofunction:: asbool
.. autofunction:: aslist
diff --git a/docs/changes.rst b/docs/changes.rst
index 6294123ed..fdeaf1e99 100644
--- a/docs/changes.rst
+++ b/docs/changes.rst
@@ -1,3 +1,5 @@
+.. _changelog:
+
:app:`Pyramid` Change History
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/docs/index.rst b/docs/index.rst
index c84314274..321fe1fed 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -88,6 +88,7 @@ Narrative documentation in chapter form explaining how to use
narr/advconfig
narr/extconfig
narr/scaffolding
+ narr/upgrading
narr/threadlocals
narr/zca
diff --git a/docs/latexindex.rst b/docs/latexindex.rst
index 99ec2f54d..604e6e7c6 100644
--- a/docs/latexindex.rst
+++ b/docs/latexindex.rst
@@ -85,8 +85,6 @@ API Reference
api/authorization
api/authentication
- api/chameleon_text
- api/chameleon_zpt
api/config
api/events
api/exceptions
diff --git a/docs/narr/advconfig.rst b/docs/narr/advconfig.rst
index b1ea652d6..165cf7474 100644
--- a/docs/narr/advconfig.rst
+++ b/docs/narr/advconfig.rst
@@ -294,9 +294,9 @@ These are the methods of the configurator which provide conflict detection:
:meth:`~pyramid.config.Configurator.add_view`,
:meth:`~pyramid.config.Configurator.add_route`,
:meth:`~pyramid.config.Configurator.add_renderer`,
+:meth:`~pyramid.config.Configurator.add_request_method`,
:meth:`~pyramid.config.Configurator.set_request_factory`,
:meth:`~pyramid.config.Configurator.set_session_factory`,
-:meth:`~pyramid.config.Configurator.set_request_method`,
:meth:`~pyramid.config.Configurator.set_request_property`,
:meth:`~pyramid.config.Configurator.set_root_factory`,
:meth:`~pyramid.config.Configurator.set_view_mapper`,
diff --git a/docs/narr/templates.rst b/docs/narr/templates.rst
index 5930bb379..ba72ebfbf 100644
--- a/docs/narr/templates.rst
+++ b/docs/narr/templates.rst
@@ -46,20 +46,6 @@ within the body of a view callable like so:
{'foo':1, 'bar':2},
request=request)
-.. warning::
-
- Earlier iterations of this documentation
- (pre-version-1.3) encouraged the application developer to use
- ZPT-specific APIs such as
- :func:`pyramid.chameleon_zpt.render_template_to_response` and
- :func:`pyramid.chameleon_zpt.render_template` to render templates
- directly. This style of rendering still works, but at least for
- purposes of this documentation, those functions are deprecated.
- Application developers are encouraged instead to use the functions
- available in the :mod:`pyramid.renderers` module to perform
- rendering tasks. This set of functions works to render templates
- for all renderer extensions registered with :app:`Pyramid`.
-
The ``sample_view`` :term:`view callable` function above returns a
:term:`response` object which contains the body of the
``templates/foo.pt`` template. In this case, the ``templates``
@@ -79,12 +65,12 @@ prefix on Windows.
.. warning::
Only :term:`Chameleon` templates support defining a renderer for a
- template relative to the location of the module where the view
- callable is defined. Mako templates, and other templating system
- bindings work differently. In particular, Mako templates use a
- "lookup path" as defined by the ``mako.directories`` configuration
- file instead of treating relative paths as relative to the current
- view module. See :ref:`mako_templates`.
+ template relative to the location of the module where the view callable is
+ defined. Mako templates, and other templating system bindings work
+ differently. In particular, Mako templates use a "lookup path" as defined
+ by the ``mako.directories`` configuration file instead of treating
+ relative paths as relative to the current view module. See
+ :ref:`mako_templates`.
The path can alternately be a :term:`asset specification` in the form
``some.dotted.package_name:relative/path``. This makes it possible to
@@ -600,10 +586,6 @@ When the template is rendered, it will show:
Hello, world!
-If you'd rather use templates directly within a view callable (without
-the indirection of using a renderer), see :ref:`chameleon_text_module`
-for the API description.
-
See also :ref:`built_in_renderers` for more general information about
renderers, including Chameleon text renderers.
diff --git a/docs/narr/testing.rst b/docs/narr/testing.rst
index 5ce2c8a66..50e9d5604 100644
--- a/docs/narr/testing.rst
+++ b/docs/narr/testing.rst
@@ -52,7 +52,7 @@ The suggested mechanism for unit and integration testing of a :app:`Pyramid`
application is the Python :mod:`unittest` module. Although this module is
named :mod:`unittest`, it is actually capable of driving both unit and
integration tests. A good :mod:`unittest` tutorial is available within `Dive
-Into Python <http://diveintopython.nfshost.com/unit_testing/index.html>`_ by Mark
+Into Python <http://www.diveintopython.net/unit_testing/index.html>`_ by Mark
Pilgrim.
:app:`Pyramid` provides a number of facilities that make unit, integration,
diff --git a/docs/narr/upgrading.rst b/docs/narr/upgrading.rst
new file mode 100644
index 000000000..92f125c0a
--- /dev/null
+++ b/docs/narr/upgrading.rst
@@ -0,0 +1,232 @@
+Upgrading Pyramid
+=================
+
+When a new version of Pyramid is released, it will sometimes deprecate a
+feature or remove a feature that was deprecated in an older release. When
+features are removed from Pyramid, applications that depend on those features
+will begin to break. This chapter explains how to ensure your Pyramid
+applications keep working when you upgrade the Pyramid version you're using.
+
+.. sidebar:: About Release Numbering
+
+ Conventionally, application version numbering in Python is described as
+ ``major.minor.micro``. If your Pyramid version is "1.2.3", it means
+ you're running a version of Pyramid with the major version "1", the minor
+ version "2" and the micro version "3". A "major" release is one that
+ increments the first-dot number; 2.X.X might follow 1.X.X. A "minor"
+ release is one that increments the second-dot number; 1.3.X might follow
+ 1.2.X. A "micro" release is one that increments the third-dot number;
+ 1.2.3 might follow 1.2.2. In general, micro releases are "bugfix-only",
+ and contain no new features, minor releases contain new features but are
+ largely backwards compatible with older versions, and a major release
+ indicates a large set of backwards incompatibilities.
+
+The Pyramid core team is conservative when it comes to removing features. We
+don't remove features unnecessarily, but we're human, and we make mistakes
+which cause some features to be evolutionary dead ends. Though we are
+willing to support dead-end features for some amount of time, some eventually
+have to be removed when the cost of supporting them outweighs the benefit of
+keeping them around, because each feature in Pyramid represents a certain
+documentation and maintenance burden.
+
+Deprecation and Removal Policy
+------------------------------
+
+When a feature is scheduled for removal from Pyramid or any of its official
+add-ons, the core development team takes these steps:
+
+- Using the feature will begin to generate a `DeprecationWarning`, indicating
+ the version in which the feature became deprecated.
+
+- A note is added to the documentation indicating that the feature is
+ deprecated.
+
+- A note is added to the :ref:`changelog` about the deprecation.
+
+When a deprecated feature is eventually removed:
+
+- The feature is removed.
+
+- A note is added to the :ref:`changelog` about the removal.
+
+Features are never removed in *micro* releases. They are only removed in
+minor and major releases. Deprecated features are kept around for at least
+*three* minor releases from the time the feature became deprecated.
+Therefore, if a feature is added in Pyramid 1.0, but it's deprecated in
+Pyramid 1.1, it will be kept around through all 1.1.X releases, all 1.2.X
+releases and all 1.3.X releases. It will finally be removed in the first
+1.4.X release.
+
+Sometimes features are "docs-deprecated" instead of formally deprecated.
+This means that the feature will be kept around indefinitely, but it will be
+removed from the documentation or a note will be added to the documentation
+telling folks to use some other newer feature. This happens when the cost of
+keeping an old feature around is very minimal and the support and
+documentation burden is very low. For example, we might rename a function
+that is an API without changing the arguments it accepts. In this case,
+we'll often rename the function, and change the docs to point at the new
+function name, but leave around a backwards compatibility alias to the old
+function name so older code doesn't break.
+
+"Docs deprecated" features tend to work "forever", meaning that they won't be
+removed, and they'll never generate a deprecation warning. However, such
+changes are noted in the :ref:`changelog`, so it's possible to know that you
+should change older spellings to newer ones to ensure that people reading
+your code can find the APIs you're using in the Pyramid docs.
+
+Consulting the Change History
+-----------------------------
+
+Your first line of defense against application failures caused by upgrading
+to a newer Pyramid release is always to read the :ref:`changelog`. to find
+the deprecations and removals for each release between the release you're
+currently running and the one you wish to upgrade to. The change history
+notes every deprecation within a ``Deprecation`` section and every removal
+within a ``Backwards Incompatibilies`` section for each release.
+
+The change history often contains instructions for changing your code to
+avoid deprecation warnings and how to change docs-deprecated spellings to
+newer ones. You can follow along with each deprecation explanation in the
+change history, simply doing a grep or other code search to your application,
+using the change log examples to remediate each potential problem.
+
+.. _testing_under_new_release:
+
+Testing Your Application Under a New Pyramid Release
+----------------------------------------------------
+
+Once you've upgraded your application to a new Pyramid release and you've
+remediated as much as possible by using the change history notes, you'll want
+to run your application's tests (see :ref:`running_tests`) in such a way that
+you can see DeprecationWarnings printed to the console when the tests run.
+
+.. code-block:: bash
+
+ $ python -Wd setup.py test -q
+
+The ``-Wd`` argument is an argument that tells Python to print deprecation
+warnings to the console. Note that the ``-Wd`` flag is only required for
+Python 2.7 and better: Python versions 2.6 and older print deprecation
+warnings to the console by default. See `the Python -W flag documentation
+<http://docs.python.org/using/cmdline.html#cmdoption-W>`_ for more
+information.
+
+As your tests run, deprecation warnings will be printed to the console
+explaining the deprecation and providing instructions about how to prevent
+the deprecation warning from being issued. For example:
+
+.. code-block:: text
+
+ $ python -Wd setup.py test -q
+ # .. elided ...
+ running build_ext
+ /home/chrism/projects/pyramid/env27/myproj/myproj/views.py:3:
+ DeprecationWarning: static: The "pyramid.view.static" class is deprecated
+ as of Pyramid 1.1; use the "pyramid.static.static_view" class instead with
+ the "use_subpath" argument set to True.
+ from pyramid.view import static
+ .
+ ----------------------------------------------------------------------
+ Ran 1 test in 0.014s
+
+ OK
+
+In the above case, it's line #3 in the ``myproj.views`` module (``from
+pyramid.view import static``) that is causing the problem:
+
+.. code-block:: python
+ :linenos:
+
+ from pyramid.view import view_config
+
+ from pyramid.view import static
+ myview = static('static', 'static')
+
+The deprecation warning tells me how to fix it, so I can change the code to
+do things the newer way:
+
+.. code-block:: python
+ :linenos:
+
+ from pyramid.view. import view_config
+
+ from pyramid.static import static_view
+ myview = static_view('static', 'static', use_subpath=True)
+
+When I run the tests again, the deprecation warning is no longer printed to
+my console:
+
+.. code-block:: text
+
+ $ python -Wd setup.py test -q
+ # .. elided ...
+ running build_ext
+ .
+ ----------------------------------------------------------------------
+ Ran 1 test in 0.014s
+
+ OK
+
+
+My Application Doesn't Have Any Tests or Has Few Tests
+------------------------------------------------------
+
+If your application has no tests, or has only moderate test coverage, running
+tests won't tell you very much, because the Pyramid codepaths that generate
+deprecation warnings won't be executed.
+
+In this circumstance, you can start your application interactively under a
+server run with the ``PYTHONWARNINGS`` environment variable set to
+``default``. On UNIX, you can do that via:
+
+.. code-block:: bash
+
+ $ PYTHONWARNINGS=default bin/pserve development.ini
+
+On Windows, you need to issue two commands:
+
+.. code-block:: bash
+
+ C:\> set PYTHONWARNINGS=default
+ C:\> Scripts/pserve.exe development.ini
+
+At this point, it's ensured that deprecation warnings will be printed to the
+console whenever a codepath is hit that generates one. You can then click
+around in your application interactively to try to generate them, and
+remediate as explained in :ref:`testing_under_new_release`.
+
+See `the PYTHONWARNINGS environment variable documentation
+<http://docs.python.org/using/cmdline.html#envvar-PYTHONWARNINGS>`_ or `the
+Python -W flag documentation
+<http://docs.python.org/using/cmdline.html#cmdoption-W>`_ for more
+information.
+
+Upgrading to the Very Latest Pyramid Release
+--------------------------------------------
+
+When you upgrade your application to the very most recent Pyramid release,
+it's advisable to upgrade step-wise through each most recent minor release,
+beginning with the one that you know your application currently runs under,
+and ending on the most recent release. For example, if your application is
+running in production on Pyramid 1.2.1, and the most recent Pyramid 1.3
+release is Pyramid 1.3.3, and the most recent Pyramid release is 1.4.4, it's
+advisable to do this:
+
+- Upgrade your environment to the most recent 1.2 release. For example, the
+ most recent 1.2 release might be 1.2.3, so upgrade to it. Then run your
+ application's tests under 1.2.3 as described in
+ :ref:`testing_under_new_release`. Note any deprecation warnings and
+ remediate.
+
+- Upgrade to the most recent 1.3 release, 1.3.3. Run your application's
+ tests, note any deprecation warnings and remediate.
+
+- Upgrade to 1.4.4. Run your application's tests, note any deprecation
+ warnings and remediate.
+
+If you skip testing your application under each minor release (for example if
+you upgrade directly from 1.2.1 to 1.4.4), you might miss a deprecation
+warning and waste more time trying to figure out an error caused by a feature
+removal than it would take to upgrade stepwise through each minor release.
+
+
diff --git a/docs/tutorials/modwsgi/index.rst b/docs/tutorials/modwsgi/index.rst
index d11167344..a22f12610 100644
--- a/docs/tutorials/modwsgi/index.rst
+++ b/docs/tutorials/modwsgi/index.rst
@@ -7,12 +7,11 @@ Running a :app:`Pyramid` Application under ``mod_wsgi``
It allows :term:`WSGI` programs to be served using the Apache web
server.
-This guide will outline broad steps that can be used to get a
-:app:`Pyramid` application running under Apache via ``mod_wsgi``.
-This particular tutorial was developed under Apple's Mac OS X platform
-(Snow Leopard, on a 32-bit Mac), but the instructions should be
-largely the same for all systems, delta specific path information for
-commands and files.
+This guide will outline broad steps that can be used to get a :app:`Pyramid`
+application running under Apache via ``mod_wsgi``. This particular tutorial
+was developed under Apple's Mac OS X platform (Snow Leopard, on a 32-bit
+Mac), but the instructions should be largely the same for all systems, delta
+specific path information for commands and files.
.. note:: Unfortunately these instructions almost certainly won't work for
deploying a :app:`Pyramid` application on a Windows system using
@@ -90,12 +89,11 @@ commands and files.
`logging` module to allow logging within your application.
See :ref:`logging_config`.
-#. Make the ``pyramid.wsgi`` script executable.
-
- .. code-block:: text
-
- $ cd ~/modwsgi/env
- $ chmod 755 pyramid.wsgi
+ There is no need to make the ``pyramid.wsgi`` script executable.
+ However, you'll need to make sure that *two* users have access to change
+ into the ``~/modwsgi/env`` directory: your current user (mine is
+ ``chrism`` and the user that Apache will run as often named ``apache`` or
+ ``httpd``). Make sure both of these users can "cd" into that directory.
#. Edit your Apache configuration and add some stuff. I happened to
create a file named ``/etc/apache2/other/modwsgi.conf`` on my own
diff --git a/docs/tutorials/wiki/src/authorization/tutorial/views.py b/docs/tutorials/wiki/src/authorization/tutorial/views.py
index 21f12b31d..50485d279 100644
--- a/docs/tutorials/wiki/src/authorization/tutorial/views.py
+++ b/docs/tutorials/wiki/src/authorization/tutorial/views.py
@@ -51,17 +51,17 @@ def view_page(context, request):
renderer='templates/edit.pt',
permission='edit')
def add_page(context, request):
- name = request.subpath[0]
+ pagename = request.subpath[0]
if 'form.submitted' in request.params:
body = request.params['body']
page = Page(body)
- page.__name__ = name
+ page.__name__ = pagename
page.__parent__ = context
- context[name] = page
+ context[pagename] = page
return HTTPFound(location = request.resource_url(page))
- save_url = request.resource_url(context, 'add_page', name)
+ save_url = request.resource_url(context, 'add_page', pagename)
page = Page('')
- page.__name__ = name
+ page.__name__ = pagename
page.__parent__ = context
return dict(page = page, save_url = save_url,
diff --git a/docs/tutorials/wiki/src/tests/tutorial/views.py b/docs/tutorials/wiki/src/tests/tutorial/views.py
index 21f12b31d..50485d279 100644
--- a/docs/tutorials/wiki/src/tests/tutorial/views.py
+++ b/docs/tutorials/wiki/src/tests/tutorial/views.py
@@ -51,17 +51,17 @@ def view_page(context, request):
renderer='templates/edit.pt',
permission='edit')
def add_page(context, request):
- name = request.subpath[0]
+ pagename = request.subpath[0]
if 'form.submitted' in request.params:
body = request.params['body']
page = Page(body)
- page.__name__ = name
+ page.__name__ = pagename
page.__parent__ = context
- context[name] = page
+ context[pagename] = page
return HTTPFound(location = request.resource_url(page))
- save_url = request.resource_url(context, 'add_page', name)
+ save_url = request.resource_url(context, 'add_page', pagename)
page = Page('')
- page.__name__ = name
+ page.__name__ = pagename
page.__parent__ = context
return dict(page = page, save_url = save_url,
diff --git a/docs/tutorials/wiki/src/views/tutorial/views.py b/docs/tutorials/wiki/src/views/tutorial/views.py
index 016f5b6bb..b0c15297f 100644
--- a/docs/tutorials/wiki/src/views/tutorial/views.py
+++ b/docs/tutorials/wiki/src/views/tutorial/views.py
@@ -35,17 +35,17 @@ def view_page(context, request):
@view_config(name='add_page', context='.models.Wiki',
renderer='templates/edit.pt')
def add_page(context, request):
- name = request.subpath[0]
+ pagename = request.subpath[0]
if 'form.submitted' in request.params:
body = request.params['body']
page = Page(body)
- page.__name__ = name
+ page.__name__ = pagename
page.__parent__ = context
- context[name] = page
+ context[pagename] = page
return HTTPFound(location = request.resource_url(page))
- save_url = request.resource_url(context, 'add_page', name)
+ save_url = request.resource_url(context, 'add_page', pagename)
page = Page('')
- page.__name__ = name
+ page.__name__ = pagename
page.__parent__ = context
return dict(page = page, save_url = save_url)
diff --git a/docs/tutorials/wiki2/src/authorization/tutorial/views.py b/docs/tutorials/wiki2/src/authorization/tutorial/views.py
index c7670b049..0d085b0e2 100644
--- a/docs/tutorials/wiki2/src/authorization/tutorial/views.py
+++ b/docs/tutorials/wiki2/src/authorization/tutorial/views.py
@@ -60,14 +60,14 @@ def view_page(request):
@view_config(route_name='add_page', renderer='templates/edit.pt',
permission='edit')
def add_page(request):
- name = request.matchdict['pagename']
+ pagename = request.matchdict['pagename']
if 'form.submitted' in request.params:
body = request.params['body']
- page = Page(name, body)
+ page = Page(pagename, body)
DBSession.add(page)
return HTTPFound(location = request.route_url('view_page',
- pagename=name))
- save_url = request.route_url('add_page', pagename=name)
+ pagename=pagename))
+ save_url = request.route_url('add_page', pagename=pagename)
page = Page('', '')
return dict(page=page, save_url=save_url,
logged_in=authenticated_userid(request))
@@ -75,16 +75,16 @@ def add_page(request):
@view_config(route_name='edit_page', renderer='templates/edit.pt',
permission='edit')
def edit_page(request):
- name = request.matchdict['pagename']
- page = DBSession.query(Page).filter_by(name=name).one()
+ pagename = request.matchdict['pagename']
+ page = DBSession.query(Page).filter_by(name=pagename).one()
if 'form.submitted' in request.params:
page.data = request.params['body']
DBSession.add(page)
return HTTPFound(location = request.route_url('view_page',
- pagename=name))
+ pagename=pagename))
return dict(
page=page,
- save_url = request.route_url('edit_page', pagename=name),
+ save_url = request.route_url('edit_page', pagename=pagename),
logged_in=authenticated_userid(request),
)
diff --git a/docs/tutorials/wiki2/src/tests/tutorial/views.py b/docs/tutorials/wiki2/src/tests/tutorial/views.py
index f2a33af1e..42ac0eb7f 100644
--- a/docs/tutorials/wiki2/src/tests/tutorial/views.py
+++ b/docs/tutorials/wiki2/src/tests/tutorial/views.py
@@ -61,15 +61,15 @@ def view_page(request):
@view_config(route_name='add_page', renderer='templates/edit.pt',
permission='edit')
def add_page(request):
- name = request.matchdict['pagename']
+ pagename = request.matchdict['pagename']
if 'form.submitted' in request.params:
session = DBSession()
body = request.params['body']
- page = Page(name, body)
+ page = Page(pagename, body)
session.add(page)
return HTTPFound(location = request.route_url('view_page',
- pagename=name))
- save_url = request.route_url('add_page', pagename=name)
+ pagename=pagename))
+ save_url = request.route_url('add_page', pagename=pagename)
page = Page('', '')
return dict(page=page, save_url=save_url,
logged_in=authenticated_userid(request))
@@ -77,17 +77,17 @@ def add_page(request):
@view_config(route_name='edit_page', renderer='templates/edit.pt',
permission='edit')
def edit_page(request):
- name = request.matchdict['pagename']
+ pagename = request.matchdict['pagename']
session = DBSession()
- page = session.query(Page).filter_by(name=name).one()
+ page = session.query(Page).filter_by(name=pagename).one()
if 'form.submitted' in request.params:
page.data = request.params['body']
session.add(page)
return HTTPFound(location = request.route_url('view_page',
- pagename=name))
+ pagename=pagename))
return dict(
page=page,
- save_url = request.route_url('edit_page', pagename=name),
+ save_url = request.route_url('edit_page', pagename=pagename),
logged_in=authenticated_userid(request),
)
diff --git a/docs/tutorials/wiki2/src/views/tutorial/views.py b/docs/tutorials/wiki2/src/views/tutorial/views.py
index c2a94a96b..5a9c75a61 100644
--- a/docs/tutorials/wiki2/src/views/tutorial/views.py
+++ b/docs/tutorials/wiki2/src/views/tutorial/views.py
@@ -44,27 +44,27 @@ def view_page(request):
@view_config(route_name='add_page', renderer='templates/edit.pt')
def add_page(request):
- name = request.matchdict['pagename']
+ pagename = request.matchdict['pagename']
if 'form.submitted' in request.params:
body = request.params['body']
- page = Page(name, body)
+ page = Page(pagename, body)
DBSession.add(page)
return HTTPFound(location = request.route_url('view_page',
- pagename=name))
- save_url = request.route_url('add_page', pagename=name)
+ pagename=pagename))
+ save_url = request.route_url('add_page', pagename=pagename)
page = Page('', '')
return dict(page=page, save_url=save_url)
@view_config(route_name='edit_page', renderer='templates/edit.pt')
def edit_page(request):
- name = request.matchdict['pagename']
- page = DBSession.query(Page).filter_by(name=name).one()
+ pagename = request.matchdict['pagename']
+ page = DBSession.query(Page).filter_by(name=pagename).one()
if 'form.submitted' in request.params:
page.data = request.params['body']
DBSession.add(page)
return HTTPFound(location = request.route_url('view_page',
- pagename=name))
+ pagename=pagename))
return dict(
page=page,
- save_url = request.route_url('edit_page', pagename=name),
+ save_url = request.route_url('edit_page', pagename=pagename),
)
diff --git a/pyramid/chameleon_text.py b/pyramid/chameleon_text.py
index 20f614857..3484b7973 100644
--- a/pyramid/chameleon_text.py
+++ b/pyramid/chameleon_text.py
@@ -1,6 +1,5 @@
import sys
-from zope.deprecation import deprecated
from zope.interface import implementer
from pyramid.compat import reraise
@@ -20,7 +19,6 @@ from pyramid.interfaces import ITemplateRenderer
from pyramid.decorator import reify
from pyramid import renderers
-from pyramid.path import caller_package
def renderer_factory(info):
return renderers.template_renderer_factory(info, TextTemplateRenderer)
@@ -30,6 +28,8 @@ class TextTemplateRenderer(object):
def __init__(self, path, lookup, macro=None):
self.path = path
self.lookup = lookup
+ # text template renderers have no macros, so we ignore the
+ # macro arg
@reify # avoid looking up reload_templates before manager pushed
def template(self):
@@ -52,93 +52,3 @@ class TextTemplateRenderer(object):
result = self.template(**system)
return result
-def get_renderer(path):
- """ Return a callable object which can be used to render a
- :term:`Chameleon` text template using the template implied by the
- ``path`` argument. The ``path`` argument may be a
- package-relative path, an absolute path, or a :term:`asset
- specification`.
-
- .. warning::
-
- This API is deprecated in :app:`Pyramid` 1.0. Use
- :func:`pyramid.renderers.get_renderer` instead.
- """
- package = caller_package()
- factory = renderers.RendererHelper(path, package=package)
- return factory.get_renderer()
-
-deprecated(
- 'get_renderer',
- '(pyramid.chameleon_text.get_renderer is deprecated '
- 'as of Pyramid 1.0; instead use pyramid.renderers.get_renderer)')
-
-def get_template(path):
- """ Return the underyling object representing a :term:`Chameleon`
- text template using the template implied by the ``path`` argument.
- The ``path`` argument may be a package-relative path, an absolute
- path, or a :term:`asset specification`.
-
- .. warning::
-
- This API is deprecated in :app:`Pyramid` 1.0. Use
- the ``implementation()`` method of a template renderer retrieved via
- :func:`pyramid.renderers.get_renderer` instead.
- """
- package = caller_package()
- factory = renderers.RendererHelper(path, package=package)
- return factory.get_renderer().implementation()
-
-deprecated(
- 'get_template',
- '(pyramid.chameleon_text.get_template is deprecated '
- 'as of Pyramid 1.0; instead use '
- 'pyramid.renderers.get_renderer().implementation())')
-
-def render_template(path, **kw):
- """ Render a :term:`Chameleon` text template using the template
- implied by the ``path`` argument. The ``path`` argument may be a
- package-relative path, an absolute path, or a :term:`asset
- specification`. The arguments in ``*kw`` are passed as top-level
- names to the template, and so may be used within the template
- itself. Returns a string.
-
- .. warning::
-
- This API is deprecated in :app:`Pyramid` 1.0. Use
- :func:`pyramid.renderers.render` instead.
- """
- package = caller_package()
- request = kw.pop('request', None)
- renderer = renderers.RendererHelper(path, package=package)
- return renderer.render(kw, None, request=request)
-
-deprecated(
- 'render_template',
- '(pyramid.chameleon_text.render_template is deprecated '
- 'as of Pyramid 1.0; instead use pyramid.renderers.render)')
-
-def render_template_to_response(path, **kw):
- """ Render a :term:`Chameleon` text template using the template
- implied by the ``path`` argument. The ``path`` argument may be a
- package-relative path, an absolute path, or a :term:`asset
- specification`. The arguments in ``*kw`` are passed as top-level
- names to the template, and so may be used within the template
- itself. Returns a :term:`Response` object with the body as the
- template result.
-
- .. warning::
-
- This API is deprecated in :app:`Pyramid` 1.0. Use
- :func:`pyramid.renderers.render_to_response` instead.
- """
- package = caller_package()
- request = kw.pop('request', None)
- renderer = renderers.RendererHelper(path, package=package)
- return renderer.render_to_response(kw, None, request=request)
-
-deprecated(
- 'render_template_to_response',
- '(pyramid.chameleon_text.render_template_to_response is deprecated '
- 'as of Pyramid 1.0; instead use pyramid.renderers.render_to_response)')
-
diff --git a/pyramid/chameleon_zpt.py b/pyramid/chameleon_zpt.py
index 9f9e09850..d9f4337fa 100644
--- a/pyramid/chameleon_zpt.py
+++ b/pyramid/chameleon_zpt.py
@@ -1,6 +1,5 @@
import sys
-from zope.deprecation import deprecated
from zope.interface import implementer
from pyramid.compat import reraise
@@ -18,7 +17,6 @@ except ImportError: # pragma: no cover
from pyramid.interfaces import ITemplateRenderer
from pyramid.decorator import reify
-from pyramid.path import caller_package
from pyramid import renderers
def renderer_factory(info):
@@ -58,92 +56,3 @@ class ZPTTemplateRenderer(object):
result = self.template(**system)
return result
-def get_renderer(path):
- """ Return a callable object which can be used to render a
- :term:`Chameleon` ZPT template using the template implied by the
- ``path`` argument. The ``path`` argument may be a
- package-relative path, an absolute path, or a :term:`asset
- specification`.
-
- .. warning::
-
- This API is deprecated in :app:`Pyramid` 1.0. Use
- :func:`pyramid.renderers.get_renderer` instead.
- """
- package = caller_package()
- factory = renderers.RendererHelper(name=path, package=package)
- return factory.get_renderer()
-
-deprecated(
- 'get_renderer',
- '(pyramid.chameleon_zpt.get_renderer is deprecated '
- 'as of Pyramid 1.0; instead use pyramid.renderers.get_renderer)')
-
-def get_template(path):
- """ Return the underyling object representing a :term:`Chameleon`
- ZPT template using the template implied by the ``path`` argument.
- The ``path`` argument may be a package-relative path, an absolute
- path, or a :term:`asset specification`.
-
- .. warning::
-
- This API is deprecated in :app:`Pyramid` 1.0. Use
- the ``implementation()`` method of a template renderer retrieved via
- :func:`pyramid.renderers.get_renderer` instead.
- """
- package = caller_package()
- factory = renderers.RendererHelper(name=path, package=package)
- return factory.get_renderer().implementation()
-
-deprecated(
- 'get_template',
- '(pyramid.chameleon_zpt.get_template is deprecated '
- 'as of Pyramid 1.0; instead use '
- 'pyramid.renderers.get_renderer().implementation())')
-
-def render_template(path, **kw):
- """ Render a :term:`Chameleon` ZPT template using the template
- implied by the ``path`` argument. The ``path`` argument may be a
- package-relative path, an absolute path, or a :term:`asset
- specification`. The arguments in ``*kw`` are passed as top-level
- names to the template, and so may be used within the template
- itself. Returns a string.
-
- .. warning::
-
- This API is deprecated in :app:`Pyramid` 1.0. Use
- :func:`pyramid.renderers.render` instead.
- """
- package = caller_package()
- request = kw.pop('request', None)
- renderer = renderers.RendererHelper(name=path, package=package)
- return renderer.render(kw, None, request=request)
-
-deprecated(
- 'render_template',
- '(pyramid.chameleon_zpt.render_template is deprecated as of Pyramid 1.0; '
- 'instead use pyramid.renderers.render)')
-
-def render_template_to_response(path, **kw):
- """ Render a :term:`Chameleon` ZPT template using the template
- implied by the ``path`` argument. The ``path`` argument may be a
- package-relative path, an absolute path, or a :term:`asset
- specification`. The arguments in ``*kw`` are passed as top-level
- names to the template, and so may be used within the template
- itself. Returns a :term:`Response` object with the body as the
- template result.
-
- .. warning::
-
- This API is deprecated in :app:`Pyramid` 1.0. Use
- :func:`pyramid.renderers.render_to_response` instead.
- """
- package = caller_package()
- request = kw.pop('request', None)
- renderer = renderers.RendererHelper(name=path, package=package)
- return renderer.render_to_response(kw, None, request=request)
-
-deprecated(
- 'render_template_to_response',
- '(pyramid.chameleon_zpt.render_template_to_response is deprecated; as of '
- 'Pyramid 1.0, instead use pyramid.renderers.render_to_response)')
diff --git a/pyramid/config/factories.py b/pyramid/config/factories.py
index e8043ed28..e46519bf5 100644
--- a/pyramid/config/factories.py
+++ b/pyramid/config/factories.py
@@ -76,9 +76,9 @@ class FactoriesConfiguratorMixin(object):
:class:`pyramid.request.Request` class (particularly
``__call__``, and ``blank``).
- See :meth:`pyramid.config.Configurator.set_request_property`
+ See :meth:`pyramid.config.Configurator.add_request_method`
for a less intrusive way to extend the request objects with
- custom properties.
+ custom methods and properties.
.. note::
@@ -96,7 +96,7 @@ class FactoriesConfiguratorMixin(object):
self.action(IRequestFactory, register, introspectables=(intr,))
@action_method
- def set_request_method(self,
+ def add_request_method(self,
callable=None,
name=None,
property=False,
@@ -153,8 +153,6 @@ class FactoriesConfiguratorMixin(object):
if exts is None:
exts = _RequestExtensions()
self.registry.registerUtility(exts, IRequestExtensions)
- self.registry.registerHandler(_set_request_extensions,
- (INewRequest,))
plist = exts.descriptors if property else exts.methods
plist[name] = callable
@@ -186,13 +184,13 @@ class FactoriesConfiguratorMixin(object):
.. warning::
- This method has been deprecated as of Pyramid 1.4.
- :meth:`pyramid.config.Configurator.set_request_method` should be
+ This method has been docs-deprecated as of Pyramid 1.4.
+ :meth:`pyramid.config.Configurator.add_request_method` should be
used instead.
.. versionadded:: 1.3
"""
- self.set_request_method(
+ self.add_request_method(
callable, name=name, property=not reify, reify=reify)
@implementer(IRequestExtensions)
@@ -201,10 +199,3 @@ class _RequestExtensions(object):
self.descriptors = {}
self.methods = {}
-def _set_request_extensions(event):
- request = event.request
- exts = request.registry.queryUtility(IRequestExtensions)
- for name, fn in iteritems_(exts.methods):
- method = fn.__get__(request, request.__class__)
- setattr(request, name, method)
- request._set_properties(exts.descriptors)
diff --git a/pyramid/configuration.py b/pyramid/configuration.py
deleted file mode 100644
index 802c10d1f..000000000
--- a/pyramid/configuration.py
+++ /dev/null
@@ -1,60 +0,0 @@
-from pyramid.config import Configurator as BaseConfigurator
-from pyramid.exceptions import ConfigurationError # API
-from pyramid.config import DEFAULT_RENDERERS
-from pyramid.path import caller_package
-
-from zope.deprecation import deprecated
-
-ConfigurationError = ConfigurationError # pyflakes
-
-deprecated(
- 'ConfigurationError',
- 'pyramid.configuration.ConfigurationError is deprecated as of '
- 'Pyramid 1.0. Use ``pyramid.config.ConfigurationError`` instead.')
-
-class Configurator(BaseConfigurator):
- def __init__(self,
- registry=None,
- package=None,
- settings=None,
- root_factory=None,
- authentication_policy=None,
- authorization_policy=None,
- renderers=DEFAULT_RENDERERS,
- debug_logger=None,
- locale_negotiator=None,
- request_factory=None,
- renderer_globals_factory=None,
- default_permission=None,
- session_factory=None,
- autocommit=True,
- route_prefix=None,
- introspection=True,
- ):
- if package is None:
- package = caller_package()
- BaseConfigurator.__init__(
- self,
- registry=registry,
- package=package,
- settings=settings,
- root_factory=root_factory,
- authentication_policy=authentication_policy,
- authorization_policy=authorization_policy,
- renderers=renderers,
- debug_logger=debug_logger,
- locale_negotiator=locale_negotiator,
- request_factory=request_factory,
- renderer_globals_factory=renderer_globals_factory,
- default_permission=default_permission,
- session_factory=session_factory,
- autocommit=autocommit,
- route_prefix=route_prefix,
- introspection=introspection,
- )
-
-deprecated(
- 'Configurator',
- 'pyramid.configuration.Configurator is deprecated as of Pyramid 1.0. Use'
- '``pyramid.config.Configurator`` with ``autocommit=True`` instead.')
-
diff --git a/pyramid/paster.py b/pyramid/paster.py
index 5102e7b9b..b0e4d7933 100644
--- a/pyramid/paster.py
+++ b/pyramid/paster.py
@@ -1,7 +1,5 @@
import os
-import zope.deprecation
-
from paste.deploy import (
loadapp,
appconfig,
@@ -10,14 +8,6 @@ from paste.deploy import (
from pyramid.compat import configparser
from logging.config import fileConfig
from pyramid.scripting import prepare
-from pyramid.scaffolds import PyramidTemplate # bw compat
-
-PyramidTemplate = PyramidTemplate # pyflakes
-
-zope.deprecation.deprecated(
- 'PyramidTemplate', ('pyramid.paster.PyramidTemplate was moved to '
- 'pyramid.scaffolds.PyramidTemplate in Pyramid 1.1'),
-)
def get_app(config_uri, name=None, loadapp=loadapp):
""" Return the WSGI application named ``name`` in the PasteDeploy
diff --git a/pyramid/request.py b/pyramid/request.py
index 37fac6a46..af3310829 100644
--- a/pyramid/request.py
+++ b/pyramid/request.py
@@ -454,13 +454,4 @@ def call_app_with_subpath_as_path_info(request, app):
new_request.environ['SCRIPT_NAME'] = new_script_name
new_request.environ['PATH_INFO'] = new_path_info
- # In case downstream WSGI app is a Pyramid app, hack around existence of
- # these envars until we can safely remove them (see router.py); in any
- # case, even if these get removed, it might be better to not copy the
- # existing environ but to create a new one instead.
- if 'bfg.routes.route' in new_request.environ:
- del new_request.environ['bfg.routes.route']
- if 'bfg.routes.matchdict' in new_request.environ:
- del new_request.environ['bfg.routes.matchdict']
-
return new_request.get_response(app)
diff --git a/pyramid/router.py b/pyramid/router.py
index 0c115a1ac..0cbe00f3a 100644
--- a/pyramid/router.py
+++ b/pyramid/router.py
@@ -6,6 +6,7 @@ from zope.interface import (
from pyramid.interfaces import (
IDebugLogger,
IRequest,
+ IRequestExtensions,
IRootFactory,
IRouteRequest,
IRouter,
@@ -48,6 +49,7 @@ class Router(object):
self.root_factory = q(IRootFactory, default=DefaultRootFactory)
self.routes_mapper = q(IRoutesMapper)
self.request_factory = q(IRequestFactory, default=Request)
+ self.request_extensions = q(IRequestExtensions)
tweens = q(ITweens)
if tweens is None:
tweens = excview_tween_factory
@@ -84,13 +86,6 @@ class Router(object):
request.url)
logger and logger.debug(msg)
else:
- # TODO: kill off bfg.routes.* environ keys
- # when traverser requires request arg, and
- # cant cope with environ anymore (they are
- # docs-deprecated as of BFG 1.3)
- environ = request.environ
- environ['bfg.routes.route'] = route
- environ['bfg.routes.matchdict'] = match
attrs['matchdict'] = match
attrs['matched_route'] = route
@@ -105,7 +100,8 @@ class Router(object):
request.url,
route.name,
request.path_info,
- route.pattern, match,
+ route.pattern,
+ match,
', '.join([p.__text__ for p in route.predicates]))
)
logger and logger.debug(msg)
@@ -184,6 +180,9 @@ class Router(object):
try:
try:
+ extensions = self.request_extensions
+ if extensions is not None:
+ request._set_extensions(extensions)
response = self.handle_request(request)
has_listeners and notify(NewResponse(request, response))
@@ -198,4 +197,3 @@ class Router(object):
finally:
manager.pop()
-
diff --git a/pyramid/scripting.py b/pyramid/scripting.py
index f1dc24637..00177986f 100644
--- a/pyramid/scripting.py
+++ b/pyramid/scripting.py
@@ -3,6 +3,7 @@ from pyramid.exceptions import ConfigurationError
from pyramid.request import Request
from pyramid.interfaces import (
+ IRequestExtensions,
IRequestFactory,
IRootFactory,
)
@@ -70,14 +71,18 @@ def prepare(request=None, registry=None):
'before trying to activate it.')
if request is None:
request = _make_request('/', registry)
- request.registry = registry
threadlocals = {'registry':registry, 'request':request}
threadlocal_manager.push(threadlocals)
+ extensions = registry.queryUtility(IRequestExtensions)
+ if extensions is not None:
+ request._set_extensions(extensions)
def closer():
threadlocal_manager.pop()
root_factory = registry.queryUtility(IRootFactory,
default=DefaultRootFactory)
root = root_factory(request)
+ if getattr(request, 'context', None) is None:
+ request.context = root
return {'root':root, 'closer':closer, 'registry':registry,
'request':request, 'root_factory':root_factory}
diff --git a/pyramid/settings.py b/pyramid/settings.py
index 86304307e..e2cb3cb3c 100644
--- a/pyramid/settings.py
+++ b/pyramid/settings.py
@@ -1,31 +1,5 @@
-from zope.deprecation import deprecated
-
-from pyramid.threadlocal import get_current_registry
from pyramid.compat import string_types
-def get_settings():
- """
- Return a :term:`deployment settings` object for the current application.
- The object is a dictionary-like object that contains key/value pairs
- based on the dictionary passed as the ``settings`` argument to the
- :class:`pyramid.config.Configurator` constructor or the
- :func:`pyramid.router.make_app` API.
-
- .. warning:: This method is deprecated as of Pyramid 1.0. Use
- ``pyramid.threadlocal.get_current_registry().settings`` instead or use
- the ``settings`` attribute of the registry available from the request
- (``request.registry.settings``).
- """
- reg = get_current_registry()
- return reg.settings
-
-deprecated(
- 'get_settings',
- '(pyramid.settings.get_settings is deprecated as of Pyramid 1.0. Use'
- '``pyramid.threadlocal.get_current_registry().settings`` instead or use '
- 'the ``settings`` attribute of the registry available from the request '
- '(``request.registry.settings``)).')
-
truthy = frozenset(('t', 'true', 'y', 'yes', 'on', '1'))
def asbool(s):
diff --git a/pyramid/testing.py b/pyramid/testing.py
index 89eec84b0..750effb83 100644
--- a/pyramid/testing.py
+++ b/pyramid/testing.py
@@ -1,20 +1,14 @@
import copy
import os
-from zope.deprecation import deprecated
-
from zope.interface import (
implementer,
- Interface,
alsoProvides,
)
from pyramid.interfaces import (
IRequest,
IResponseFactory,
- ISecuredView,
- IView,
- IViewClassifier,
ISession,
)
@@ -26,14 +20,12 @@ from pyramid.compat import (
from pyramid.config import Configurator
from pyramid.decorator import reify
-from pyramid.httpexceptions import HTTPForbidden
from pyramid.response import Response
from pyramid.registry import Registry
from pyramid.security import (
Authenticated,
Everyone,
- has_permission,
)
from pyramid.threadlocal import (
@@ -47,374 +39,10 @@ from pyramid.request import (
)
from pyramid.url import URLMethodsMixin
+from pyramid.util import InstancePropertyMixin
_marker = object()
-def registerDummySecurityPolicy(userid=None, groupids=(), permissive=True):
- """ Registers a pair of faux :app:`Pyramid` security policies:
- a :term:`authentication policy` and a :term:`authorization
- policy`.
-
- The behavior of the registered :term:`authorization policy`
- depends on the ``permissive`` argument. If ``permissive`` is
- true, a permissive :term:`authorization policy` is registered;
- this policy allows all access. If ``permissive`` is false, a
- nonpermissive :term:`authorization policy` is registered; this
- policy denies all access.
-
- The behavior of the registered :term:`authentication policy`
- depends on the values provided for the ``userid`` and ``groupids``
- argument. The authentication policy will return the userid
- identifier implied by the ``userid`` argument and the group ids
- implied by the ``groupids`` argument when the
- :func:`pyramid.security.authenticated_userid` or
- :func:`pyramid.security.effective_principals` APIs are used.
-
- This function is most useful when testing code that uses the APIs named
- :func:`pyramid.security.has_permission`,
- :func:`pyramid.security.authenticated_userid`,
- :func:`pyramid.security.unauthenticated_userid`,
- :func:`pyramid.security.effective_principals`, and
- :func:`pyramid.security.principals_allowed_by_permission`.
-
- .. warning:: This API is deprecated as of :app:`Pyramid` 1.0.
- Instead use the
- :meth:`pyramid.config.Configurator.testing_securitypolicy`
- method in your unit and integration tests.
- """
- registry = get_current_registry()
- config = Configurator(registry=registry)
- result = config.testing_securitypolicy(userid=userid, groupids=groupids,
- permissive=permissive)
- config.commit()
- return result
-
-deprecated('registerDummySecurityPolicy',
- 'The testing.registerDummySecurityPolicy API is deprecated as of '
- 'Pyramid 1.0. Instead use the '
- 'pyramid.config.Configurator.testing_securitypolicy '
- 'method in your unit and integration tests.')
-
-def registerResources(resources):
- """ Registers a dictionary of :term:`resource` objects that can be
- resolved via the :func:`pyramid.traversal.find_resource` API.
-
- The :func:`pyramid.traversal.find_resource` API is called with a
- path as one of its arguments. If the dictionary you register when
- calling this method contains that path as a string key
- (e.g. ``/foo/bar`` or ``foo/bar``), the corresponding value will
- be returned to ``find_resource`` (and thus to your code) when
- :func:`pyramid.traversal.find_resource` is called with an
- equivalent path string or tuple.
-
- .. warning:: This API is deprecated as of :app:`Pyramid` 1.0.
- Instead use the
- :meth:`pyramid.config.Configurator.testing_resources`
- method in your unit and integration tests.
-
- .. note:: For ancient backward compatibility purposes, this API can also
- be accessed as :func:`pyramid.testing.registerModels`.
- """
- registry = get_current_registry()
- config = Configurator(registry=registry)
- result = config.testing_resources(resources)
- config.commit()
- return result
-
-deprecated('registerResources',
- 'The testing.registerResources API is deprecated as of '
- 'Pyramid 1.0. Instead use the '
- 'pyramid.config.Configurator.testing_resources '
- 'method in your unit and integration tests.')
-
-registerModels = registerResources
-
-deprecated('registerModels',
- 'The testing.registerModels API is deprecated as of '
- 'Pyramid 1.0. Instead use the '
- 'pyramid.config.Configurator.testing_resources '
- 'method in your unit and integration tests.')
-
-def registerEventListener(event_iface=None):
- """ Registers an :term:`event` listener (aka :term:`subscriber`)
- listening for events of the type ``event_iface``. This method
- returns a list object which is appended to by the subscriber
- whenever an event is captured.
-
- When an event is dispatched that matches ``event_iface``, that
- event will be appended to the list. You can then compare the
- values in the list to expected event notifications. This method
- is useful when testing code that wants to call
- :meth:`pyramid.registry.Registry.notify`.
-
- The default value of ``event_iface`` (``None``) implies a
- subscriber registered for *any* kind of event.
-
- .. warning:: This API is deprecated as of :app:`Pyramid` 1.0.
- Instead use the
- :meth:`pyramid.config.Configurator.testing_add_subscriber`
- method in your unit and integration tests.
- """
- registry = get_current_registry()
- config = Configurator(registry=registry)
- result = config.testing_add_subscriber(event_iface)
- config.commit()
- return result
-
-deprecated('registerEventListener',
- 'The testing.registerEventListener API is deprecated as of '
- 'Pyramid 1.0. Instead use the '
- 'pyramid.config.Configurator.testing_add_subscriber '
- 'method in your unit and integration tests.')
-
-def registerTemplateRenderer(path, renderer=None):
- """ Register a template renderer at ``path`` (usually a relative
- filename ala ``templates/foo.pt``) and return the renderer object.
- If the ``renderer`` argument is None, a 'dummy' renderer will be
- used. This function is useful when testing code that calls the
- :func:`pyramid.renderers.render` function or
- :func:`pyramid.renderers.render_to_response` function or any
- other ``render_*`` or ``get_*`` API of the
- :mod:`pyramid.renderers` module.
-
- .. warning:: This API is deprecated as of :app:`Pyramid` 1.0.
- Instead use the
- :meth:`pyramid.config.Configurator.testing_add_renderer`
- method in your unit and integration tests.
-
- """
- registry = get_current_registry()
- config = Configurator(registry=registry)
- result = config.testing_add_template(path, renderer)
- config.commit()
- return result
-
-deprecated('registerTemplateRenderer',
- 'The testing.registerTemplateRenderer API is deprecated as of '
- 'Pyramid 1.0. Instead use the '
- 'pyramid.config.Configurator.testing_add_renderer '
- 'method in your unit and integration tests.')
-
-# registerDummyRenderer is a deprecated alias that should never be removed
-# (too much usage in the wild)
-registerDummyRenderer = registerTemplateRenderer
-
-deprecated('registerDummyRenderer',
- 'The testing.registerDummyRenderer API is deprecated as of '
- 'Pyramid 1.0. Instead use the '
- 'pyramid.config.Configurator.testing_add_renderer '
- 'method in your unit and integration tests.')
-
-def registerView(name, result='', view=None, for_=(Interface, Interface),
- permission=None):
- """ Registers a :app:`Pyramid` :term:`view callable` under the
- name implied by the ``name`` argument. The view will return a
- :term:`WebOb` :term:`Response` object with the value implied by
- the ``result`` argument as its ``body`` attribute. To gain more
- control, if you pass in a non-``None`` ``view`` argument, this
- value will be used as a view callable instead of an automatically
- generated view callable (and ``result`` is not used).
-
- To protect the view using a :term:`permission`, pass in a
- non-``None`` value as ``permission``. This permission will be
- checked by any active :term:`authorization policy` when view
- execution is attempted.
-
- This function is useful when testing code which calls
- :func:`pyramid.view.render_view_to_response`.
-
- .. warning:: This API is deprecated as of :app:`Pyramid` 1.0.
- Instead use the
- :meth:`pyramid.config.Configurator.add_view`
- method in your unit and integration tests.
- """
- for_ = (IViewClassifier, ) + for_
- if view is None:
- def view(context, request):
- return Response(result)
- if permission is None:
- return registerAdapter(view, for_, IView, name)
- else:
- def _secure(context, request):
- if not has_permission(permission, context, request):
- raise HTTPForbidden('no permission')
- else:
- return view(context, request)
- _secure.__call_permissive__ = view
- def permitted(context, request):
- return has_permission(permission, context, request)
- _secure.__permitted__ = permitted
- return registerAdapter(_secure, for_, ISecuredView, name)
-
-deprecated('registerView',
- 'The registerView API is deprecated as of '
- 'Pyramid 1.0. Instead use the '
- 'pyramid.config.Configurator.add_view '
- 'method in your unit and integration tests.')
-
-def registerUtility(impl, iface=Interface, name=''):
- """ Register a ZCA utility component.
-
- The ``impl`` argument specifies the implementation of the utility.
- The ``iface`` argument specifies the :term:`interface` which will
- be later required to look up the utility
- (:class:`zope.interface.Interface`, by default). The ``name``
- argument implies the utility name; it is the empty string by
- default.
-
- See `The ZCA book <http://www.muthukadan.net/docs/zca.html>`_ for
- more information about ZCA utilities.
-
- .. warning:: This API is deprecated as of :app:`Pyramid` 1.0.
- Instead use the :meth:`pyramid.Registry.registerUtility`
- method. The ``registry`` attribute of a :term:`Configurator`
- in your unit and integration tests is an instance of the
- :class:`pyramid.Registry` class.
- """
- reg = get_current_registry()
- reg.registerUtility(impl, iface, name=name)
- return impl
-
-deprecated('registerUtility',
- 'The registerUtility API is deprecated as of '
- 'Pyramid 1.0. Instead use the '
- 'pyramid.registry.registerUtility method (via '
- 'e.g. "config.registry.registerUtility(..)" '
- 'method in your unit and integration tests.')
-
-def registerAdapter(impl, for_=Interface, provides=Interface, name=''):
- """ Register a ZCA adapter component.
-
- The ``impl`` argument specifies the implementation of the
- component (often a class). The ``for_`` argument implies the
- ``for`` interface type used for this registration; it is
- :class:`zope.interface.Interface` by default. If ``for`` is not a
- tuple or list, it will be converted to a one-tuple before being
- passed to underlying :meth:`pyramid.registry.registerAdapter`
- API.
-
- The ``provides`` argument specifies the ZCA 'provides' interface,
- :class:`zope.interface.Interface` by default.
-
- The ``name`` argument is the empty string by default; it implies
- the name under which the adapter is registered.
-
- See `The ZCA book <http://www.muthukadan.net/docs/zca.html>`_ for
- more information about ZCA adapters.
-
- .. warning:: This API is deprecated as of :app:`Pyramid` 1.0.
- Instead use the :meth:`pyramid.Registry.registerAdapter`
- method. The ``registry`` attribute of a :term:`Configurator`
- in your unit and integration tests is an instance of the
- :class:`pyramid.Registry` class.
- """
- reg = get_current_registry()
- if not isinstance(for_, (tuple, list)):
- for_ = (for_,)
- reg.registerAdapter(impl, for_, provides, name=name)
- return impl
-
-deprecated('registerAdapter',
- 'The registerAdapter API is deprecated as of '
- 'Pyramid 1.0. Instead use the '
- 'pyramid.registry.registerAdapter method (via '
- 'e.g. "config.registry.registerAdapter(..)" '
- 'method in your unit and integration tests.')
-
-def registerSubscriber(subscriber, iface=Interface):
- """ Register a ZCA subscriber component.
-
- The ``subscriber`` argument specifies the implementation of the
- subscriber component (often a function).
-
- The ``iface`` argument is the interface type for which the
- subscriber will be registered (:class:`zope.interface.Interface`
- by default). If ``iface`` is not a tuple or list, it will be
- converted to a one-tuple before being passed to the underlying ZCA
- :meth:`pyramid.registry.registerHandler` method.
-
- See `The ZCA book <http://www.muthukadan.net/docs/zca.html>`_ for
- more information about ZCA subscribers.
-
- .. warning:: This API is deprecated as of :app:`Pyramid` 1.0.
- Instead use the
- :meth:`pyramid.config.Configurator.add_subscriber`
- method in your unit and integration tests.
- """
- registry = get_current_registry()
- config = Configurator(registry)
- result = config.add_subscriber(subscriber, iface=iface)
- config.commit()
- return result
-
-deprecated('registerSubscriber',
- 'The testing.registerSubscriber API is deprecated as of '
- 'Pyramid 1.0. Instead use the '
- 'pyramid.config.Configurator.add_subscriber '
- 'method in your unit and integration tests.')
-
-def registerRoute(pattern, name, factory=None):
- """ Register a new :term:`route` using a pattern
- (e.g. ``:pagename``), a name (e.g. ``home``), and an optional root
- factory.
-
- The ``pattern`` argument implies the route pattern. The ``name``
- argument implies the route name. The ``factory`` argument implies
- a :term:`root factory` associated with the route.
-
- This API is useful for testing code that calls
- e.g. :func:`pyramid.url.route_url`.
-
- .. warning:: This API is deprecated as of :app:`Pyramid` 1.0.
- Instead use the
- :meth:`pyramid.config.Configurator.add_route`
- method in your unit and integration tests.
- """
- reg = get_current_registry()
- config = Configurator(registry=reg)
- config.setup_registry()
- result = config.add_route(name, pattern, factory=factory)
- config.commit()
- return result
-
-deprecated('registerRoute',
- 'The testing.registerRoute API is deprecated as of '
- 'Pyramid 1.0. Instead use the '
- 'pyramid.config.Configurator.add_route '
- 'method in your unit and integration tests.')
-
-def registerSettings(dictarg=None, **kw):
- """Register one or more 'setting' key/value pairs. A setting is
- a single key/value pair in the dictionary-ish object returned from
- the API :attr:`pyramid.registry.Registry.settings`.
-
- You may pass a dictionary::
-
- registerSettings({'external_uri':'http://example.com'})
-
- Or a set of key/value pairs::
-
- registerSettings(external_uri='http://example.com')
-
- Use of this function is required when you need to test code that calls
- the :attr:`pyramid.registry.Registry.settings` API and which uses return
- values from that API.
-
- .. warning:: This API is deprecated as of :app:`Pyramid` 1.0.
- Instead use the
- :meth:`pyramid.config.Configurator.add_settings`
- method in your unit and integration tests.
- """
- registry = get_current_registry()
- config = Configurator(registry=registry)
- config.add_settings(dictarg, **kw)
-
-deprecated('registerSettings',
- 'The testing.registerSettings API is deprecated as of '
- 'Pyramid 1.0. Instead use the '
- 'pyramid.config.Configurator.add_settings '
- 'method in your unit and integration tests.')
-
class DummyRootFactory(object):
__parent__ = None
__name__ = None
@@ -646,7 +274,7 @@ class DummySession(dict):
@implementer(IRequest)
class DummyRequest(DeprecatedRequestMethodsMixin, URLMethodsMixin,
- CallbackMethodsMixin):
+ CallbackMethodsMixin, InstancePropertyMixin):
""" A DummyRequest object (incompletely) imitates a :term:`request` object.
The ``params``, ``environ``, ``headers``, ``path``, and
diff --git a/pyramid/tests/fixtures/withmacro.pt b/pyramid/tests/fixtures/withmacro.pt
index bb80475c0..8bca01e4d 100644
--- a/pyramid/tests/fixtures/withmacro.pt
+++ b/pyramid/tests/fixtures/withmacro.pt
@@ -1,3 +1,6 @@
+<html>
<metal:m define-macro="foo">
Hello!
</metal:m>
+</html>
+
diff --git a/pyramid/tests/test_chameleon_text.py b/pyramid/tests/test_chameleon_text.py
index 8d23c8753..297e96554 100644
--- a/pyramid/tests/test_chameleon_text.py
+++ b/pyramid/tests/test_chameleon_text.py
@@ -1,28 +1,33 @@
+import sys
import unittest
from pyramid.compat import binary_type
from pyramid.testing import skip_on
from pyramid import testing
-class Base:
+class Base(object):
def setUp(self):
self.config = testing.setUp()
- from zope.deprecation import __show__
- __show__.off()
def tearDown(self):
testing.tearDown()
- from zope.deprecation import __show__
- __show__.on()
def _getTemplatePath(self, name):
import os
here = os.path.abspath(os.path.dirname(__file__))
return os.path.join(here, 'fixtures', name)
- def _registerUtility(self, utility, iface, name=''):
- reg = self.config.registry
- reg.registerUtility(utility, iface, name=name)
+class Test_renderer_factory(Base, unittest.TestCase):
+ def _callFUT(self, info):
+ from pyramid.chameleon_text import renderer_factory
+ return renderer_factory(info)
+
+ def test_it(self):
+ # this test is way too functional
+ from pyramid.chameleon_text import TextTemplateRenderer
+ info = DummyInfo()
+ result = self._callFUT(info)
+ self.assertEqual(result.__class__, TextTemplateRenderer)
class TextTemplateRendererTests(Base, unittest.TestCase):
def _getTargetClass(self):
@@ -127,83 +132,24 @@ class TextTemplateRendererTests(Base, unittest.TestCase):
self.assertTrue(isinstance(result, binary_type))
self.assertEqual(result, b'Hello.\n')
-class RenderTemplateTests(Base, unittest.TestCase):
- def _callFUT(self, name, **kw):
- from pyramid.chameleon_text import render_template
- return render_template(name, **kw)
-
- @skip_on('java')
- def test_it(self):
- minimal = self._getTemplatePath('minimal.txt')
- result = self._callFUT(minimal)
- self.assertTrue(isinstance(result, binary_type))
- self.assertEqual(result, b'Hello.\n')
-
-class RenderTemplateToResponseTests(Base, unittest.TestCase):
- def _callFUT(self, name, **kw):
- from pyramid.chameleon_text import render_template_to_response
- return render_template_to_response(name, **kw)
-
- @skip_on('java')
- def test_minimal(self):
- minimal = self._getTemplatePath('minimal.txt')
- result = self._callFUT(minimal)
- from webob import Response
- self.assertTrue(isinstance(result, Response))
- self.assertEqual(result.app_iter, [b'Hello.\n'])
- self.assertEqual(result.status, '200 OK')
- self.assertEqual(len(result.headerlist), 2)
-
- @skip_on('java')
- def test_iresponsefactory_override(self):
- from webob import Response
- class Response2(Response):
- pass
- from pyramid.interfaces import IResponseFactory
- self._registerUtility(Response2, IResponseFactory)
- minimal = self._getTemplatePath('minimal.txt')
- result = self._callFUT(minimal)
- self.assertTrue(isinstance(result, Response2))
-
-class GetRendererTests(Base, unittest.TestCase):
- def _callFUT(self, name):
- from pyramid.chameleon_text import get_renderer
- return get_renderer(name)
-
- @skip_on('java')
- def test_it(self):
- from pyramid.interfaces import IRendererFactory
- class Dummy:
- template = object()
- def implementation(self): pass
- renderer = Dummy()
- def rf(spec):
- return renderer
- self._registerUtility(rf, IRendererFactory, name='foo')
- result = self._callFUT('foo')
- self.assertTrue(result is renderer)
-
-class GetTemplateTests(Base, unittest.TestCase):
- def _callFUT(self, name):
- from pyramid.chameleon_text import get_template
- return get_template(name)
-
- @skip_on('java')
- def test_it(self):
- from pyramid.interfaces import IRendererFactory
- class Dummy:
- template = object()
- def implementation(self):
- return self.template
- renderer = Dummy()
- def rf(spec):
- return renderer
- self._registerUtility(rf, IRendererFactory, name='foo')
- result = self._callFUT('foo')
- self.assertTrue(result is renderer.template)
-
class DummyLookup(object):
auto_reload=True
debug = True
def translate(self, msg): pass
+
+class DummyRegistry(object):
+ def queryUtility(self, iface, name):
+ self.queried = iface, name
+ return None
+
+ def registerUtility(self, impl, iface, name):
+ self.registered = impl, iface, name
+
+class DummyInfo(object):
+ def __init__(self):
+ self.registry = DummyRegistry()
+ self.type = '.pt'
+ self.name = 'fixtures/minimal.pt'
+ self.package = sys.modules[__name__]
+ self.settings = {}
diff --git a/pyramid/tests/test_chameleon_zpt.py b/pyramid/tests/test_chameleon_zpt.py
index e7a1499e6..5d197dac4 100644
--- a/pyramid/tests/test_chameleon_zpt.py
+++ b/pyramid/tests/test_chameleon_zpt.py
@@ -1,3 +1,4 @@
+import sys
import unittest
from pyramid.testing import skip_on
@@ -7,24 +8,27 @@ from pyramid.compat import text_type
class Base(object):
def setUp(self):
self.config = testing.setUp()
- from zope.deprecation import __show__
- __show__.off()
def tearDown(self):
testing.tearDown()
- from zope.deprecation import __show__
- __show__.on()
def _getTemplatePath(self, name):
import os
here = os.path.abspath(os.path.dirname(__file__))
return os.path.join(here, 'fixtures', name)
- def _registerUtility(self, utility, iface, name=''):
- reg = self.config.registry
- reg.registerUtility(utility, iface, name=name)
- return reg
-
+class Test_renderer_factory(Base, unittest.TestCase):
+ def _callFUT(self, info):
+ from pyramid.chameleon_zpt import renderer_factory
+ return renderer_factory(info)
+
+ def test_it(self):
+ # this test is way too functional
+ from pyramid.chameleon_zpt import ZPTTemplateRenderer
+ info = DummyInfo()
+ result = self._callFUT(info)
+ self.assertEqual(result.__class__, ZPTTemplateRenderer)
+
class ZPTTemplateRendererTests(Base, unittest.TestCase):
def _getTargetClass(self):
from pyramid.chameleon_zpt import ZPTTemplateRenderer
@@ -130,86 +134,35 @@ class ZPTTemplateRendererTests(Base, unittest.TestCase):
self.assertTrue(isinstance(result, text_type))
self.assertEqual(result.rstrip('\n'),
'<div xmlns="http://www.w3.org/1999/xhtml">\n</div>')
-
-
-class RenderTemplateTests(Base, unittest.TestCase):
- def _callFUT(self, name, **kw):
- from pyramid.chameleon_zpt import render_template
- return render_template(name, **kw)
-
- @skip_on('java')
- def test_it(self):
- minimal = self._getTemplatePath('minimal.pt')
- result = self._callFUT(minimal)
- self.assertTrue(isinstance(result, text_type))
- self.assertEqual(result.rstrip('\n'),
- '<div xmlns="http://www.w3.org/1999/xhtml">\n</div>')
-
-class RenderTemplateToResponseTests(Base, unittest.TestCase):
- def _callFUT(self, name, **kw):
- from pyramid.chameleon_zpt import render_template_to_response
- return render_template_to_response(name, **kw)
-
- @skip_on('java')
- def test_it(self):
- minimal = self._getTemplatePath('minimal.pt')
- result = self._callFUT(minimal)
- from webob import Response
- self.assertTrue(isinstance(result, Response))
- self.assertEqual(result.app_iter[0].rstrip(b'\n'),
- b'<div xmlns="http://www.w3.org/1999/xhtml">\n</div>')
- self.assertEqual(result.status, '200 OK')
- self.assertEqual(len(result.headerlist), 2)
-
- @skip_on('java')
- def test_iresponsefactory_override(self):
- from webob import Response
- class Response2(Response):
- pass
- from pyramid.interfaces import IResponseFactory
- self._registerUtility(Response2, IResponseFactory)
- minimal = self._getTemplatePath('minimal.pt')
- result = self._callFUT(minimal)
- self.assertTrue(isinstance(result, Response2))
-
-class GetRendererTests(Base, unittest.TestCase):
- def _callFUT(self, name):
- from pyramid.chameleon_zpt import get_renderer
- return get_renderer(name)
-
- @skip_on('java')
- def test_it(self):
- from pyramid.interfaces import IRendererFactory
- class Dummy:
- template = object()
- def implementation(self): pass
- renderer = Dummy()
- def rf(spec):
- return renderer
- self._registerUtility(rf, IRendererFactory, name='foo')
- result = self._callFUT('foo')
- self.assertTrue(result is renderer)
-
-class GetTemplateTests(Base, unittest.TestCase):
- def _callFUT(self, name):
- from pyramid.chameleon_zpt import get_template
- return get_template(name)
- @skip_on('java')
- def test_it(self):
- from pyramid.interfaces import IRendererFactory
- class Dummy:
- template = object()
- def implementation(self):
- return self.template
- renderer = Dummy()
- def rf(spec):
- return renderer
- self._registerUtility(rf, IRendererFactory, name='foo')
- result = self._callFUT('foo')
- self.assertTrue(result is renderer.template)
+ def test_macro_supplied(self):
+ minimal = self._getTemplatePath('withmacro.pt')
+ lookup = DummyLookup()
+ instance = self._makeOne(minimal, lookup, macro='foo')
+ result = instance.implementation()()
+ self.assertEqual(result, '\n Hello!\n')
+
+
+
class DummyLookup(object):
auto_reload=True
debug = True
def translate(self, msg): pass
+
+class DummyRegistry(object):
+ def queryUtility(self, iface, name):
+ self.queried = iface, name
+ return None
+
+ def registerUtility(self, impl, iface, name):
+ self.registered = impl, iface, name
+
+class DummyInfo(object):
+ def __init__(self):
+ self.registry = DummyRegistry()
+ self.type = '.pt'
+ self.name = 'fixtures/minimal.pt'
+ self.package = sys.modules[__name__]
+ self.settings = {}
+
diff --git a/pyramid/tests/test_config/test_factories.py b/pyramid/tests/test_config/test_factories.py
index 38e80416f..e89fc077e 100644
--- a/pyramid/tests/test_config/test_factories.py
+++ b/pyramid/tests/test_config/test_factories.py
@@ -112,49 +112,19 @@ class TestFactoriesMixin(unittest.TestCase):
config.set_request_property(bar, name='bar')
self.assertRaises(ConfigurationConflictError, config.commit)
- def test_set_request_property_subscriber(self):
- from zope.interface import implementer
- from pyramid.interfaces import INewRequest
- config = self._makeOne()
- def foo(r): pass
- config.set_request_property(foo, name='foo')
- config.set_request_property(foo, name='bar', reify=True)
- config.commit()
- @implementer(INewRequest)
- class Event(object):
- request = DummyRequest(config.registry)
- event = Event()
- config.registry.notify(event)
- exts = list(sorted(event.request.extensions))
- self.assertEqual('bar', exts[0])
- self.assertEqual('foo', exts[1])
-
- def test_set_request_method_subscriber(self):
- from zope.interface import implementer
- from pyramid.interfaces import INewRequest
- config = self._makeOne(autocommit=True)
- def foo(r): return 'bar'
- config.set_request_method(foo, name='foo')
- @implementer(INewRequest)
- class Event(object):
- request = DummyRequest(config.registry)
- event = Event()
- config.registry.notify(event)
- self.assertEqual('bar', event.request.foo())
-
- def test_set_request_method_with_callable(self):
+ def test_add_request_method_with_callable(self):
from pyramid.interfaces import IRequestExtensions
config = self._makeOne(autocommit=True)
callable = lambda x: None
- config.set_request_method(callable, name='foo')
+ config.add_request_method(callable, name='foo')
exts = config.registry.getUtility(IRequestExtensions)
self.assertTrue('foo' in exts.methods)
- def test_set_request_method_with_unnamed_callable(self):
+ def test_add_request_method_with_unnamed_callable(self):
from pyramid.interfaces import IRequestExtensions
config = self._makeOne(autocommit=True)
def foo(self): pass
- config.set_request_method(foo)
+ config.add_request_method(foo)
exts = config.registry.getUtility(IRequestExtensions)
self.assertTrue('foo' in exts.methods)
@@ -163,38 +133,27 @@ class TestFactoriesMixin(unittest.TestCase):
config = self._makeOne()
def foo(self): pass
def bar(self): pass
- config.set_request_method(foo, name='bar')
- config.set_request_method(bar, name='bar')
+ config.add_request_method(foo, name='bar')
+ config.add_request_method(bar, name='bar')
self.assertRaises(ConfigurationConflictError, config.commit)
- def test_set_request_method_with_None_callable(self):
+ def test_add_request_method_with_None_callable(self):
from pyramid.interfaces import IRequestExtensions
config = self._makeOne(autocommit=True)
- config.set_request_method(name='foo')
+ config.add_request_method(name='foo')
exts = config.registry.queryUtility(IRequestExtensions)
self.assertTrue(exts is None)
- def test_set_request_method_with_None_callable_conflict(self):
+ def test_add_request_method_with_None_callable_conflict(self):
from pyramid.exceptions import ConfigurationConflictError
config = self._makeOne()
def bar(self): pass
- config.set_request_method(name='foo')
- config.set_request_method(bar, name='foo')
+ config.add_request_method(name='foo')
+ config.add_request_method(bar, name='foo')
self.assertRaises(ConfigurationConflictError, config.commit)
- def test_set_request_method_with_None_callable_and_no_name(self):
+ def test_add_request_method_with_None_callable_and_no_name(self):
config = self._makeOne(autocommit=True)
- self.assertRaises(AttributeError, config.set_request_method)
-
-
-class DummyRequest(object):
- extensions = None
-
- def __init__(self, registry):
- self.registry = registry
+ self.assertRaises(AttributeError, config.add_request_method)
- def _set_properties(self, properties):
- if self.extensions is None:
- self.extensions = []
- self.extensions.extend(properties)
diff --git a/pyramid/tests/test_config/test_settings.py b/pyramid/tests/test_config/test_settings.py
index 0f5239915..c74f96375 100644
--- a/pyramid/tests/test_config/test_settings.py
+++ b/pyramid/tests/test_config/test_settings.py
@@ -47,6 +47,15 @@ class TestSettingsConfiguratorMixin(unittest.TestCase):
settings = reg.getUtility(ISettings)
self.assertEqual(settings['a'], 1)
+ def test_add_settings_settings_None(self):
+ from pyramid.registry import Registry
+ from pyramid.interfaces import ISettings
+ reg = Registry()
+ config = self._makeOne(reg)
+ config.add_settings(None, a=1)
+ settings = reg.getUtility(ISettings)
+ self.assertEqual(settings['a'], 1)
+
class TestSettings(unittest.TestCase):
def _getTargetClass(self):
diff --git a/pyramid/tests/test_configuration.py b/pyramid/tests/test_configuration.py
deleted file mode 100644
index 0a98bcb5c..000000000
--- a/pyramid/tests/test_configuration.py
+++ /dev/null
@@ -1,31 +0,0 @@
-import unittest
-
-class ConfiguratorTests(unittest.TestCase):
- def setUp(self):
- from zope.deprecation import __show__
- __show__.off()
-
- def tearDown(self):
- from zope.deprecation import __show__
- __show__.on()
-
- def _makeOne(self, *arg, **kw):
- from pyramid.configuration import Configurator
- return Configurator(*arg, **kw)
-
- def test_autocommit_true(self):
- config = self._makeOne()
- self.assertEqual(config.autocommit, True)
-
- def test_package_is_not_None(self):
- import pyramid
- config = self._makeOne(package='pyramid')
- self.assertEqual(config.package, pyramid)
-
- def test_with_package(self):
- import pyramid
- config = self._makeOne()
- newconfig = config.with_package('pyramid')
- self.assertEqual(newconfig.package, pyramid)
-
-
diff --git a/pyramid/tests/test_path.py b/pyramid/tests/test_path.py
index ccc56fb0d..a07ebeffa 100644
--- a/pyramid/tests/test_path.py
+++ b/pyramid/tests/test_path.py
@@ -138,9 +138,9 @@ class TestPackageOf(unittest.TestCase):
self.assertEqual(result, tests)
def test_it_module(self):
- import pyramid.tests.test_configuration
+ import pyramid.tests.test_path
from pyramid import tests
- package = DummyPackageOrModule(pyramid.tests.test_configuration)
+ package = DummyPackageOrModule(pyramid.tests.test_path)
result = self._callFUT(package)
self.assertEqual(result, tests)
@@ -395,7 +395,7 @@ class TestDottedNameResolver(unittest.TestCase):
self.assertEqual(result, self.__class__)
def test__zope_dottedname_style_resolve_relative_leading_dots(self):
- import pyramid.tests.test_configuration
+ import pyramid.tests.test_path
typ = self._makeOne()
result = typ._zope_dottedname_style(
'..tests.test_path.TestDottedNameResolver', pyramid.tests)
diff --git a/pyramid/tests/test_renderers.py b/pyramid/tests/test_renderers.py
index cc3d73fb7..af9188abc 100644
--- a/pyramid/tests/test_renderers.py
+++ b/pyramid/tests/test_renderers.py
@@ -533,6 +533,7 @@ class TestRendererHelper(unittest.TestCase):
def renderer(*arg):
def respond(*arg):
return arg
+ renderer.respond = respond
return respond
self.config.registry.registerUtility(renderer, IRendererFactory,
name='.foo')
@@ -554,6 +555,11 @@ class TestRendererHelper(unittest.TestCase):
self.assertEqual(response.body[0], 'values')
self.assertEqual(response.body[1], {})
+ def test_get_renderer(self):
+ factory = self._registerRendererFactory()
+ helper = self._makeOne('loo.foo')
+ self.assertEqual(helper.get_renderer(), factory.respond)
+
def test_render_view(self):
self._registerRendererFactory()
self._registerResponseFactory()
@@ -652,6 +658,14 @@ class TestRendererHelper(unittest.TestCase):
response = helper._make_response(la.encode('utf-8'), request)
self.assertEqual(response.body, la.encode('utf-8'))
+ def test__make_response_result_is_None(self):
+ from pyramid.response import Response
+ request = testing.DummyRequest()
+ request.response = Response()
+ helper = self._makeOne('loo.foo')
+ response = helper._make_response(None, request)
+ self.assertEqual(response.body, b'')
+
def test__make_response_with_content_type(self):
from pyramid.response import Response
request = testing.DummyRequest()
diff --git a/pyramid/tests/test_request.py b/pyramid/tests/test_request.py
index a95d614f9..86cfd8b09 100644
--- a/pyramid/tests/test_request.py
+++ b/pyramid/tests/test_request.py
@@ -549,18 +549,6 @@ class Test_call_app_with_subpath_as_path_info(unittest.TestCase):
self.assertEqual(request.environ['SCRIPT_NAME'], '/' + encoded)
self.assertEqual(request.environ['PATH_INFO'], '/' + encoded)
- def test_it_removes_bfg_routes_info(self):
- request = DummyRequest({})
- request.environ['bfg.routes.route'] = True
- request.environ['bfg.routes.matchdict'] = True
- response = self._callFUT(request, 'app')
- self.assertTrue(request.copied)
- self.assertEqual(response, 'app')
- self.assertEqual(request.environ['SCRIPT_NAME'], '')
- self.assertEqual(request.environ['PATH_INFO'], '/')
- self.assertFalse('bfg.routes.route' in request.environ)
- self.assertFalse('bfg.routes.matchdict' in request.environ)
-
class DummyRequest:
def __init__(self, environ=None):
if environ is None:
diff --git a/pyramid/tests/test_router.py b/pyramid/tests/test_router.py
index eb9b7285d..778b27473 100644
--- a/pyramid/tests/test_router.py
+++ b/pyramid/tests/test_router.py
@@ -312,6 +312,38 @@ class TestRouter(unittest.TestCase):
self.assertEqual(app_iter, [b'abc'])
self.assertEqual(start_response.status, '200 OK')
+ def test_call_with_request_extensions(self):
+ from pyramid.interfaces import IViewClassifier
+ from pyramid.interfaces import IRequestExtensions
+ from pyramid.interfaces import IRequest
+ from pyramid.request import Request
+ context = DummyContext()
+ self._registerTraverserFactory(context)
+ class Extensions(object):
+ def __init__(self):
+ self.methods = {}
+ self.descriptors = {}
+ extensions = Extensions()
+ L = []
+ request = Request.blank('/')
+ request.request_iface = IRequest
+ request.registry = self.registry
+ request._set_extensions = lambda *x: L.extend(x)
+ def request_factory(environ):
+ return request
+ self.registry.registerUtility(extensions, IRequestExtensions)
+ environ = self._makeEnviron()
+ response = DummyResponse()
+ response.app_iter = ['Hello world']
+ view = DummyView(response)
+ self._registerView(self.config.derive_view(view), '',
+ IViewClassifier, None, None)
+ router = self._makeOne()
+ router.request_factory = request_factory
+ start_response = DummyStartResponse()
+ router(environ, start_response)
+ self.assertEqual(L, [extensions])
+
def test_call_view_registered_nonspecific_default_path(self):
from pyramid.interfaces import IViewClassifier
context = DummyContext()
@@ -646,8 +678,6 @@ class TestRouter(unittest.TestCase):
self.assertEqual(request.context, context)
self.assertEqual(request.root, root)
matchdict = {'action':'action1', 'article':'article1'}
- self.assertEqual(environ['bfg.routes.matchdict'], matchdict)
- self.assertEqual(environ['bfg.routes.route'].name, 'foo')
self.assertEqual(request.matchdict, matchdict)
self.assertEqual(request.matched_route.name, 'foo')
self.assertEqual(len(logger.messages), 1)
@@ -712,8 +742,6 @@ class TestRouter(unittest.TestCase):
self.assertEqual(request.context, context)
self.assertEqual(request.root, root)
matchdict = {'action':'action1', 'article':'article1'}
- self.assertEqual(environ['bfg.routes.matchdict'], matchdict)
- self.assertEqual(environ['bfg.routes.route'].name, 'foo')
self.assertEqual(request.matchdict, matchdict)
self.assertEqual(request.matched_route.name, 'foo')
self.assertTrue(IFoo.providedBy(request))
diff --git a/pyramid/tests/test_scripting.py b/pyramid/tests/test_scripting.py
index a99ae53fe..1ccc7af3b 100644
--- a/pyramid/tests/test_scripting.py
+++ b/pyramid/tests/test_scripting.py
@@ -5,31 +5,37 @@ class Test_get_root(unittest.TestCase):
from pyramid.scripting import get_root
return get_root(app, request)
+ def _makeRegistry(self):
+ return DummyRegistry([DummyFactory])
+
def test_it_norequest(self):
- app = DummyApp(registry=dummy_registry)
+ registry = self._makeRegistry()
+ app = DummyApp(registry=registry)
root, closer = self._callFUT(app)
self.assertEqual(len(app.threadlocal_manager.pushed), 1)
pushed = app.threadlocal_manager.pushed[0]
- self.assertEqual(pushed['registry'], dummy_registry)
+ self.assertEqual(pushed['registry'], registry)
self.assertEqual(pushed['request'].registry, app.registry)
self.assertEqual(len(app.threadlocal_manager.popped), 0)
closer()
self.assertEqual(len(app.threadlocal_manager.popped), 1)
def test_it_withrequest(self):
- app = DummyApp(registry=dummy_registry)
+ registry = self._makeRegistry()
+ app = DummyApp(registry=registry)
request = DummyRequest({})
root, closer = self._callFUT(app, request)
self.assertEqual(len(app.threadlocal_manager.pushed), 1)
pushed = app.threadlocal_manager.pushed[0]
- self.assertEqual(pushed['registry'], dummy_registry)
+ self.assertEqual(pushed['registry'], registry)
self.assertEqual(pushed['request'], request)
self.assertEqual(len(app.threadlocal_manager.popped), 0)
closer()
self.assertEqual(len(app.threadlocal_manager.popped), 1)
def test_it_requestfactory_overridden(self):
- app = DummyApp(registry=dummy_registry)
+ registry = self._makeRegistry()
+ app = DummyApp(registry=registry)
root, closer = self._callFUT(app)
self.assertEqual(len(app.threadlocal_manager.pushed), 1)
pushed = app.threadlocal_manager.pushed[0]
@@ -40,8 +46,10 @@ class Test_prepare(unittest.TestCase):
from pyramid.scripting import prepare
return prepare(request, registry)
- def _makeRegistry(self):
- return DummyRegistry(DummyFactory)
+ def _makeRegistry(self, L=None):
+ if L is None:
+ L = [None, DummyFactory]
+ return DummyRegistry(L)
def setUp(self):
from pyramid.threadlocal import manager
@@ -53,21 +61,22 @@ class Test_prepare(unittest.TestCase):
self.assertRaises(ConfigurationError, self._callFUT)
def test_it_norequest(self):
- registry = self._makeRegistry()
+ registry = self._makeRegistry([DummyFactory, None, DummyFactory])
info = self._callFUT(registry=registry)
- root, closer = info['root'], info['closer']
+ root, closer, request = info['root'], info['closer'], info['request']
pushed = self.manager.get()
self.assertEqual(pushed['registry'], registry)
self.assertEqual(pushed['request'].registry, registry)
self.assertEqual(root.a, (pushed['request'],))
closer()
self.assertEqual(self.default, self.manager.get())
+ self.assertEqual(request.context, root)
def test_it_withrequest(self):
request = DummyRequest({})
registry = request.registry = self._makeRegistry()
info = self._callFUT(request=request)
- root, closer = info['root'], info['closer']
+ root, closer, request = info['root'], info['closer'], info['request']
pushed = self.manager.get()
self.assertEqual(pushed['request'], request)
self.assertEqual(pushed['registry'], registry)
@@ -75,12 +84,13 @@ class Test_prepare(unittest.TestCase):
self.assertEqual(root.a, (request,))
closer()
self.assertEqual(self.default, self.manager.get())
+ self.assertEqual(request.context, root)
def test_it_with_request_and_registry(self):
request = DummyRequest({})
registry = request.registry = self._makeRegistry()
info = self._callFUT(request=request, registry=registry)
- root, closer = info['root'], info['closer']
+ root, closer, root = info['root'], info['closer'], info['root']
pushed = self.manager.get()
self.assertEqual(pushed['request'], request)
self.assertEqual(pushed['registry'], registry)
@@ -88,21 +98,44 @@ class Test_prepare(unittest.TestCase):
self.assertEqual(root.a, (request,))
closer()
self.assertEqual(self.default, self.manager.get())
+ self.assertEqual(request.context, root)
+
+ def test_it_with_request_context_already_set(self):
+ request = DummyRequest({})
+ context = Dummy()
+ request.context = context
+ registry = request.registry = self._makeRegistry()
+ info = self._callFUT(request=request, registry=registry)
+ root, closer, root = info['root'], info['closer'], info['root']
+ closer()
+ self.assertEqual(request.context, context)
+
+ def test_it_with_extensions(self):
+ exts = Dummy()
+ request = DummyRequest({})
+ registry = request.registry = self._makeRegistry([exts, DummyFactory])
+ info = self._callFUT(request=request, registry=registry)
+ self.assertEqual(request.extensions, exts)
+ root, closer = info['root'], info['closer']
+ closer()
class Test__make_request(unittest.TestCase):
def _callFUT(self, path='/', registry=None):
from pyramid.scripting import _make_request
return _make_request(path, registry)
+ def _makeRegistry(self):
+ return DummyRegistry([DummyFactory])
+
def test_it_with_registry(self):
- request = self._callFUT('/', dummy_registry)
+ registry = self._makeRegistry()
+ request = self._callFUT('/', registry)
self.assertEqual(request.environ['path'], '/')
- self.assertEqual(request.registry, dummy_registry)
+ self.assertEqual(request.registry, registry)
def test_it_with_no_registry(self):
from pyramid.config import global_registries
- # keep registry local so that global_registries is cleared after
- registry = DummyRegistry(DummyFactory)
+ registry = self._makeRegistry()
global_registries.add(registry)
try:
request = self._callFUT('/hello')
@@ -127,13 +160,13 @@ class DummyFactory(object):
self.kw = kw
class DummyRegistry(object):
- def __init__(self, factory=None):
- self.factory = factory
+ def __init__(self, utilities):
+ self.utilities = utilities
- def queryUtility(self, iface, default=None):
- return self.factory or default
-
-dummy_registry = DummyRegistry(DummyFactory)
+ def queryUtility(self, iface, default=None): # pragma: no cover
+ if self.utilities:
+ return self.utilities.pop(0)
+ return default
class DummyApp:
def __init__(self, registry=None):
@@ -156,6 +189,10 @@ class DummyThreadLocalManager:
self.popped.append(True)
class DummyRequest:
+ matchdict = None
+ matched_route = None
def __init__(self, environ):
self.environ = environ
-
+
+ def _set_extensions(self, exts):
+ self.extensions = exts
diff --git a/pyramid/tests/test_settings.py b/pyramid/tests/test_settings.py
index 2ef15f62a..a586cb6fd 100644
--- a/pyramid/tests/test_settings.py
+++ b/pyramid/tests/test_settings.py
@@ -1,30 +1,4 @@
import unittest
-from pyramid import testing
-
-class TestGetSettings(unittest.TestCase):
- def setUp(self):
- from pyramid.registry import Registry
- registry = Registry('testing')
- self.config = testing.setUp(registry=registry)
- from zope.deprecation import __show__
- __show__.off()
-
- def tearDown(self):
- self.config.end()
- from zope.deprecation import __show__
- __show__.on()
-
- def _callFUT(self):
- from pyramid.settings import get_settings
- return get_settings()
-
- def test_it_nosettings(self):
- self.assertEqual(self._callFUT()['reload_templates'], False)
-
- def test_it_withsettings(self):
- settings = {'a':1}
- self.config.registry.settings = settings
- self.assertEqual(self._callFUT(), settings)
class Test_asbool(unittest.TestCase):
def _callFUT(self, s):
diff --git a/pyramid/tests/test_testing.py b/pyramid/tests/test_testing.py
index a9e50442f..339a39cd8 100644
--- a/pyramid/tests/test_testing.py
+++ b/pyramid/tests/test_testing.py
@@ -1,285 +1,4 @@
import unittest
-from pyramid.compat import text_
-
-class TestBase(unittest.TestCase):
- def setUp(self):
- from pyramid.threadlocal import manager
- from pyramid.registry import Registry
- manager.clear()
- registry = Registry('testing')
- self.registry = registry
- manager.push({'registry':registry, 'request':None})
- from zope.deprecation import __show__
- __show__.off()
-
- def tearDown(self):
- from pyramid.threadlocal import manager
- manager.clear()
- from zope.deprecation import __show__
- __show__.on()
-
-class Test_registerDummySecurityPolicy(TestBase):
- def test_registerDummySecurityPolicy(self):
- from pyramid import testing
- testing.registerDummySecurityPolicy('user', ('group1', 'group2'),
- permissive=False)
- from pyramid.interfaces import IAuthenticationPolicy
- from pyramid.interfaces import IAuthorizationPolicy
- ut = self.registry.getUtility(IAuthenticationPolicy)
- from pyramid.testing import DummySecurityPolicy
- self.assertTrue(isinstance(ut, DummySecurityPolicy))
- ut = self.registry.getUtility(IAuthorizationPolicy)
- self.assertEqual(ut.userid, 'user')
- self.assertEqual(ut.groupids, ('group1', 'group2'))
- self.assertEqual(ut.permissive, False)
-
-class Test_registerResources(TestBase):
- def test_it(self):
- class Dummy:
- pass
- ob1 = Dummy()
- ob2 = Dummy()
- resources = {'/ob1':ob1, '/ob2':ob2}
- from pyramid import testing
- testing.registerResources(resources)
- from pyramid.interfaces import ITraverser
- adapter = self.registry.getAdapter(None, ITraverser)
- result = adapter(DummyRequest({'PATH_INFO':'/ob1'}))
- self.assertEqual(result['context'], ob1)
- self.assertEqual(result['view_name'], '')
- self.assertEqual(result['subpath'], ())
- self.assertEqual(result['traversed'], (text_('ob1'),))
- self.assertEqual(result['virtual_root'], ob1)
- self.assertEqual(result['virtual_root_path'], ())
- result = adapter(DummyRequest({'PATH_INFO':'/ob2'}))
- self.assertEqual(result['context'], ob2)
- self.assertEqual(result['view_name'], '')
- self.assertEqual(result['subpath'], ())
- self.assertEqual(result['traversed'], (text_('ob2'),))
- self.assertEqual(result['virtual_root'], ob2)
- self.assertEqual(result['virtual_root_path'], ())
- self.assertRaises(KeyError, adapter, DummyRequest({'PATH_INFO':'/ob3'}))
- from pyramid.traversal import find_resource
- self.assertEqual(find_resource(None, '/ob1'), ob1)
-
-class Test_registerTemplateRenderer(TestBase):
- def test_registerTemplateRenderer(self):
- from pyramid import testing
- renderer = testing.registerTemplateRenderer('templates/foo')
- from pyramid.testing import DummyTemplateRenderer
- self.assertTrue(isinstance(renderer, DummyTemplateRenderer))
- from pyramid.renderers import render_to_response
- render_to_response('templates/foo', dict(foo=1, bar=2))
- renderer.assert_(foo=1)
- renderer.assert_(bar=2)
-
- def test_registerTemplateRenderer_explicitrenderer(self):
- from pyramid import testing
- def renderer(kw, system):
- self.assertEqual(kw, {'foo':1, 'bar':2})
- renderer = testing.registerTemplateRenderer('templates/foo', renderer)
- from pyramid.renderers import render_to_response
- render_to_response('templates/foo', dict(foo=1, bar=2))
-
-class Test_registerEventListener(TestBase):
- def test_registerEventListener_single(self):
- from pyramid import testing
- L = testing.registerEventListener(IDummy)
- event = DummyEvent()
- self.registry.notify(event)
- self.assertEqual(len(L), 1)
- self.assertEqual(L[0], event)
- self.registry.notify(object())
- self.assertEqual(len(L), 1)
-
- def test_registerEventListener_multiple(self):
- from pyramid import testing
- L = testing.registerEventListener((Interface, IDummy))
- event = DummyEvent()
- event.object = 'foo'
- # the below is the equivalent of z.c.event.objectEventNotify(event)
- self.registry.subscribers((event.object, event), None)
- self.assertEqual(len(L), 2)
- self.assertEqual(L[0], 'foo')
- self.assertEqual(L[1], event)
-
- def test_registerEventListener_defaults(self):
- from pyramid import testing
- L = testing.registerEventListener()
- event = object()
- self.registry.notify(event)
- self.assertEqual(L[-1], event)
- event2 = object()
- self.registry.notify(event2)
- self.assertEqual(L[-1], event2)
-
-class Test_registerView(TestBase):
- def test_registerView_defaults(self):
- from pyramid import testing
- view = testing.registerView('moo.html')
- import types
- self.assertTrue(isinstance(view, types.FunctionType))
- from pyramid.view import render_view_to_response
- request = DummyRequest()
- request.registry = self.registry
- response = render_view_to_response(None, request, 'moo.html')
- self.assertEqual(view(None, None).body, response.body)
-
- def test_registerView_withresult(self):
- from pyramid import testing
- view = testing.registerView('moo.html', 'yo')
- import types
- self.assertTrue(isinstance(view, types.FunctionType))
- from pyramid.view import render_view_to_response
- request = DummyRequest()
- request.registry = self.registry
- response = render_view_to_response(None, request, 'moo.html')
- self.assertEqual(response.body, b'yo')
-
- def test_registerView_custom(self):
- from pyramid import testing
- def view(context, request):
- from webob import Response
- return Response('123')
- view = testing.registerView('moo.html', view=view)
- import types
- self.assertTrue(isinstance(view, types.FunctionType))
- from pyramid.view import render_view_to_response
- request = DummyRequest()
- request.registry = self.registry
- response = render_view_to_response(None, request, 'moo.html')
- self.assertEqual(response.body, b'123')
-
- def test_registerView_with_permission_denying(self):
- from pyramid import testing
- from pyramid.httpexceptions import HTTPForbidden
- def view(context, request):
- """ """
- view = testing.registerView('moo.html', view=view, permission='bar')
- testing.registerDummySecurityPolicy(permissive=False)
- import types
- self.assertTrue(isinstance(view, types.FunctionType))
- from pyramid.view import render_view_to_response
- request = DummyRequest()
- request.registry = self.registry
- self.assertRaises(HTTPForbidden, render_view_to_response,
- None, request, 'moo.html')
-
- def test_registerView_with_permission_denying2(self):
- from pyramid import testing
- from pyramid.security import view_execution_permitted
- def view(context, request):
- """ """
- view = testing.registerView('moo.html', view=view, permission='bar')
- testing.registerDummySecurityPolicy(permissive=False)
- import types
- self.assertTrue(isinstance(view, types.FunctionType))
- result = view_execution_permitted(None, None, 'moo.html')
- self.assertEqual(result, False)
-
- def test_registerView_with_permission_allowing(self):
- from pyramid import testing
- def view(context, request):
- from webob import Response
- return Response('123')
- view = testing.registerView('moo.html', view=view, permission='bar')
- testing.registerDummySecurityPolicy(permissive=True)
- import types
- self.assertTrue(isinstance(view, types.FunctionType))
- from pyramid.view import render_view_to_response
- request = DummyRequest()
- request.registry = self.registry
- result = render_view_to_response(None, request, 'moo.html')
- self.assertEqual(result.app_iter, [b'123'])
-
-
-class Test_registerAdapter(TestBase):
- def test_registerAdapter(self):
- from zope.interface import Interface
- class provides(Interface):
- pass
- class Provider:
- pass
- class for_(Interface):
- pass
- from pyramid import testing
- testing.registerAdapter(Provider, (for_, for_), provides, name='foo')
- adapter = self.registry.adapters.lookup(
- (for_, for_), provides, name='foo')
- self.assertEqual(adapter, Provider)
-
- def test_registerAdapter_notlist(self):
- from zope.interface import Interface
- class provides(Interface):
- pass
- class Provider:
- pass
- class for_(Interface):
- pass
- from pyramid import testing
- testing.registerAdapter(Provider, for_, provides, name='foo')
- adapter = self.registry.adapters.lookup(
- (for_,), provides, name='foo')
- self.assertEqual(adapter, Provider)
-
-class Test_registerUtility(TestBase):
- def test_registerUtility(self):
- from zope.interface import implementer
- from zope.interface import Interface
- class iface(Interface):
- pass
- @implementer(iface)
- class impl:
- def __call__(self):
- return 'foo'
- utility = impl()
- from pyramid import testing
- testing.registerUtility(utility, iface, name='mudge')
- self.assertEqual(self.registry.getUtility(iface, name='mudge')(), 'foo')
-
-class Test_registerSubscriber(TestBase):
- def test_it(self):
- from pyramid import testing
- L = []
- def subscriber(event):
- L.append(event)
- testing.registerSubscriber(subscriber, iface=IDummy)
- event = DummyEvent()
- self.registry.notify(event)
- self.assertEqual(len(L), 1)
- self.assertEqual(L[0], event)
- self.registry.notify(object())
- self.assertEqual(len(L), 1)
-
-class Test_registerRoute(TestBase):
- def test_registerRoute(self):
- from pyramid.config import Configurator
- from pyramid.request import Request
- from pyramid.interfaces import IRoutesMapper
- from pyramid.testing import registerRoute
- registerRoute(':pagename', 'home', DummyFactory)
- mapper = self.registry.getUtility(IRoutesMapper)
- self.assertEqual(len(mapper.routelist), 1)
- request = Request.blank('/')
- request.registry = self.registry
- config = Configurator(registry=self.registry)
- config.setup_registry()
- self.assertEqual(request.route_url('home', pagename='abc'),
- 'http://localhost/abc')
-
-class Test_registerSettings(TestBase):
- def test_registerSettings(self):
- from pyramid.interfaces import ISettings
- from pyramid.testing import registerSettings
- registerSettings({'a':1, 'b':2})
- settings = self.registry.getUtility(ISettings)
- self.assertEqual(settings['a'], 1)
- self.assertEqual(settings['b'], 2)
- registerSettings(b=3, c=4)
- settings = self.registry.getUtility(ISettings)
- self.assertEqual(settings['a'], 1)
- self.assertEqual(settings['b'], 3)
- self.assertEqual(settings['c'], 4)
class TestDummyRootFactory(unittest.TestCase):
def _makeOne(self, environ):
@@ -913,14 +632,6 @@ class IDummy(Interface):
class DummyEvent:
pass
-
-class DummyRequest:
- application_url = 'http://example.com'
- def __init__(self, environ=None):
- if environ is None:
- environ = {}
- self.environ = environ
-
class DummyFactory:
def __init__(self, environ):
""" """
diff --git a/pyramid/tests/test_traversal.py b/pyramid/tests/test_traversal.py
index 8e0bb2494..2e45ae1a9 100644
--- a/pyramid/tests/test_traversal.py
+++ b/pyramid/tests/test_traversal.py
@@ -128,10 +128,23 @@ class ResourceTreeTraverserTests(unittest.TestCase):
context = DummyContext()
verifyObject(ITraverser, self._makeOne(context))
- def test_call_with_no_pathinfo(self):
+ def test_call_with_empty_pathinfo(self):
policy = self._makeOne(None)
environ = self._getEnviron()
- request = DummyRequest(environ)
+ request = DummyRequest(environ, path_info='')
+ result = policy(request)
+ self.assertEqual(result['context'], None)
+ self.assertEqual(result['view_name'], '')
+ self.assertEqual(result['subpath'], ())
+ self.assertEqual(result['traversed'], ())
+ self.assertEqual(result['root'], policy.root)
+ self.assertEqual(result['virtual_root'], policy.root)
+ self.assertEqual(result['virtual_root_path'], ())
+
+ def test_call_with_pathinfo_KeyError(self):
+ policy = self._makeOne(None)
+ environ = self._getEnviron()
+ request = DummyRequest(environ, toraise=KeyError)
result = policy(request)
self.assertEqual(result['context'], None)
self.assertEqual(result['view_name'], '')
@@ -142,31 +155,25 @@ class ResourceTreeTraverserTests(unittest.TestCase):
self.assertEqual(result['virtual_root_path'], ())
def test_call_with_pathinfo_highorder(self):
- foo = DummyContext(None, text_(b'Qu\xc3\xa9bec', 'utf-8'))
+ path = text_(b'/Qu\xc3\xa9bec', 'utf-8')
+ foo = DummyContext(None, path)
root = DummyContext(foo, 'root')
policy = self._makeOne(root)
- if PY3: # pragma: no cover
- path_info = b'/Qu\xc3\xa9bec'.decode('latin-1')
- else:
- path_info = b'/Qu\xc3\xa9bec'
- environ = self._getEnviron(PATH_INFO=path_info)
- request = DummyRequest(environ)
+ environ = self._getEnviron()
+ request = DummyRequest(environ, path_info=path)
result = policy(request)
self.assertEqual(result['context'], foo)
self.assertEqual(result['view_name'], '')
self.assertEqual(result['subpath'], ())
- self.assertEqual(
- result['traversed'],
- (text_(b'Qu\xc3\xa9bec', 'utf-8'),)
- )
+ self.assertEqual(result['traversed'], (path[1:],))
self.assertEqual(result['root'], policy.root)
self.assertEqual(result['virtual_root'], policy.root)
self.assertEqual(result['virtual_root_path'], ())
def test_call_pathel_with_no_getitem(self):
policy = self._makeOne(None)
- environ = self._getEnviron(PATH_INFO='/foo/bar')
- request = DummyRequest(environ)
+ environ = self._getEnviron()
+ request = DummyRequest(environ, path_info=text_('/foo/bar'))
result = policy(request)
self.assertEqual(result['context'], None)
self.assertEqual(result['view_name'], 'foo')
@@ -179,8 +186,8 @@ class ResourceTreeTraverserTests(unittest.TestCase):
def test_call_withconn_getitem_emptypath_nosubpath(self):
root = DummyContext()
policy = self._makeOne(root)
- environ = self._getEnviron(PATH_INFO='')
- request = DummyRequest(environ)
+ environ = self._getEnviron()
+ request = DummyRequest(environ, path_info=text_(''))
result = policy(request)
self.assertEqual(result['context'], root)
self.assertEqual(result['view_name'], '')
@@ -194,8 +201,8 @@ class ResourceTreeTraverserTests(unittest.TestCase):
foo = DummyContext()
root = DummyContext(foo)
policy = self._makeOne(root)
- environ = self._getEnviron(PATH_INFO='/foo/bar')
- request = DummyRequest(environ)
+ environ = self._getEnviron()
+ request = DummyRequest(environ, path_info=text_('/foo/bar'))
result = policy(request)
self.assertEqual(result['context'], foo)
self.assertEqual(result['view_name'], 'bar')
@@ -209,8 +216,8 @@ class ResourceTreeTraverserTests(unittest.TestCase):
foo = DummyContext()
root = DummyContext(foo)
policy = self._makeOne(root)
- environ = self._getEnviron(PATH_INFO='/foo/bar/baz/buz')
- request = DummyRequest(environ)
+ environ = self._getEnviron()
+ request = DummyRequest(environ, path_info=text_('/foo/bar/baz/buz'))
result = policy(request)
self.assertEqual(result['context'], foo)
self.assertEqual(result['view_name'], 'bar')
@@ -224,8 +231,8 @@ class ResourceTreeTraverserTests(unittest.TestCase):
foo = DummyContext()
root = DummyContext(foo)
policy = self._makeOne(root)
- environ = self._getEnviron(PATH_INFO='/@@foo')
- request = DummyRequest(environ)
+ environ = self._getEnviron()
+ request = DummyRequest(environ, path_info=text_('/@@foo'))
result = policy(request)
self.assertEqual(result['context'], root)
self.assertEqual(result['view_name'], 'foo')
@@ -236,14 +243,13 @@ class ResourceTreeTraverserTests(unittest.TestCase):
self.assertEqual(result['virtual_root_path'], ())
def test_call_with_vh_root(self):
- environ = self._getEnviron(PATH_INFO='/baz',
- HTTP_X_VHM_ROOT='/foo/bar')
+ environ = self._getEnviron(HTTP_X_VHM_ROOT='/foo/bar')
baz = DummyContext(None, 'baz')
bar = DummyContext(baz, 'bar')
foo = DummyContext(bar, 'foo')
root = DummyContext(foo, 'root')
policy = self._makeOne(root)
- request = DummyRequest(environ)
+ request = DummyRequest(environ, path_info=text_('/baz'))
result = policy(request)
self.assertEqual(result['context'], baz)
self.assertEqual(result['view_name'], '')
@@ -256,14 +262,13 @@ class ResourceTreeTraverserTests(unittest.TestCase):
(text_('foo'), text_('bar')))
def test_call_with_vh_root2(self):
- environ = self._getEnviron(PATH_INFO='/bar/baz',
- HTTP_X_VHM_ROOT='/foo')
+ environ = self._getEnviron(HTTP_X_VHM_ROOT='/foo')
baz = DummyContext(None, 'baz')
bar = DummyContext(baz, 'bar')
foo = DummyContext(bar, 'foo')
root = DummyContext(foo, 'root')
policy = self._makeOne(root)
- request = DummyRequest(environ)
+ request = DummyRequest(environ, path_info=text_('/bar/baz'))
result = policy(request)
self.assertEqual(result['context'], baz)
self.assertEqual(result['view_name'], '')
@@ -275,14 +280,13 @@ class ResourceTreeTraverserTests(unittest.TestCase):
self.assertEqual(result['virtual_root_path'], (text_('foo'),))
def test_call_with_vh_root3(self):
- environ = self._getEnviron(PATH_INFO='/foo/bar/baz',
- HTTP_X_VHM_ROOT='/')
+ environ = self._getEnviron(HTTP_X_VHM_ROOT='/')
baz = DummyContext()
bar = DummyContext(baz)
foo = DummyContext(bar)
root = DummyContext(foo)
policy = self._makeOne(root)
- request = DummyRequest(environ)
+ request = DummyRequest(environ, path_info=text_('/foo/bar/baz'))
result = policy(request)
self.assertEqual(result['context'], baz)
self.assertEqual(result['view_name'], '')
@@ -294,14 +298,13 @@ class ResourceTreeTraverserTests(unittest.TestCase):
self.assertEqual(result['virtual_root_path'], ())
def test_call_with_vh_root4(self):
- environ = self._getEnviron(PATH_INFO='/',
- HTTP_X_VHM_ROOT='/foo/bar/baz')
+ environ = self._getEnviron(HTTP_X_VHM_ROOT='/foo/bar/baz')
baz = DummyContext(None, 'baz')
bar = DummyContext(baz, 'bar')
foo = DummyContext(bar, 'foo')
root = DummyContext(foo, 'root')
policy = self._makeOne(root)
- request = DummyRequest(environ)
+ request = DummyRequest(environ, path_info=text_('/'))
result = policy(request)
self.assertEqual(result['context'], baz)
self.assertEqual(result['view_name'], '')
@@ -315,9 +318,8 @@ class ResourceTreeTraverserTests(unittest.TestCase):
def test_call_with_vh_root_path_root(self):
policy = self._makeOne(None)
- environ = self._getEnviron(HTTP_X_VHM_ROOT='/',
- PATH_INFO='/')
- request = DummyRequest(environ)
+ environ = self._getEnviron(HTTP_X_VHM_ROOT='/')
+ request = DummyRequest(environ, path_info=text_('/'))
result = policy(request)
self.assertEqual(result['context'], None)
self.assertEqual(result['view_name'], '')
@@ -328,57 +330,48 @@ class ResourceTreeTraverserTests(unittest.TestCase):
self.assertEqual(result['virtual_root_path'], ())
def test_call_with_vh_root_highorder(self):
+ path = text_(b'Qu\xc3\xa9bec', 'utf-8')
bar = DummyContext(None, 'bar')
- foo = DummyContext(bar, text_(b'Qu\xc3\xa9bec', 'utf-8'))
+ foo = DummyContext(bar, path)
root = DummyContext(foo, 'root')
policy = self._makeOne(root)
if PY3: # pragma: no cover
vhm_root = b'/Qu\xc3\xa9bec'.decode('latin-1')
else:
vhm_root = b'/Qu\xc3\xa9bec'
- environ = self._getEnviron(HTTP_X_VHM_ROOT=vhm_root,
- PATH_INFO='/bar')
- request = DummyRequest(environ)
+ environ = self._getEnviron(HTTP_X_VHM_ROOT=vhm_root)
+ request = DummyRequest(environ, path_info=text_('/bar'))
result = policy(request)
self.assertEqual(result['context'], bar)
self.assertEqual(result['view_name'], '')
self.assertEqual(result['subpath'], ())
self.assertEqual(
result['traversed'],
- (text_(b'Qu\xc3\xa9bec', 'utf-8'), text_('bar'))
+ (path, text_('bar'))
)
self.assertEqual(result['root'], policy.root)
self.assertEqual(result['virtual_root'], foo)
self.assertEqual(
result['virtual_root_path'],
- (text_(b'Qu\xc3\xa9bec', 'utf-8'),)
+ (path,)
)
- def test_non_utf8_path_segment_unicode_path_segments_fails(self):
- from pyramid.exceptions import URLDecodeError
- foo = DummyContext()
- root = DummyContext(foo)
- policy = self._makeOne(root)
- segment = native_(text_(b'LaPe\xc3\xb1a', 'utf-8'), 'utf-16')
- environ = self._getEnviron(PATH_INFO='/%s' % segment)
- request = DummyRequest(environ)
- self.assertRaises(URLDecodeError, policy, request)
-
- def test_non_utf8_path_segment_settings_unicode_path_segments_fails(self):
+ def test_path_info_raises_unicodedecodeerror(self):
from pyramid.exceptions import URLDecodeError
foo = DummyContext()
root = DummyContext(foo)
policy = self._makeOne(root)
- segment = native_(text_(b'LaPe\xc3\xb1a', 'utf-8'), 'utf-16')
- environ = self._getEnviron(PATH_INFO='/%s' % segment)
- request = DummyRequest(environ)
+ environ = self._getEnviron()
+ toraise = UnicodeDecodeError('ascii', b'a', 2, 3, '5')
+ request = DummyRequest(environ, toraise=toraise)
+ request.matchdict = None
self.assertRaises(URLDecodeError, policy, request)
def test_withroute_nothingfancy(self):
resource = DummyContext()
traverser = self._makeOne(resource)
- environ = {'bfg.routes.matchdict': {}}
- request = DummyRequest(environ)
+ request = DummyRequest({})
+ request.matchdict = {}
result = traverser(request)
self.assertEqual(result['context'], resource)
self.assertEqual(result['view_name'], '')
@@ -391,8 +384,9 @@ class ResourceTreeTraverserTests(unittest.TestCase):
def test_withroute_with_subpath_string(self):
resource = DummyContext()
traverser = self._makeOne(resource)
- environ = {'bfg.routes.matchdict': {'subpath':'/a/b/c'}}
- request = DummyRequest(environ)
+ matchdict = {'subpath':'/a/b/c'}
+ request = DummyRequest({})
+ request.matchdict = matchdict
result = traverser(request)
self.assertEqual(result['context'], resource)
self.assertEqual(result['view_name'], '')
@@ -405,8 +399,9 @@ class ResourceTreeTraverserTests(unittest.TestCase):
def test_withroute_with_subpath_tuple(self):
resource = DummyContext()
traverser = self._makeOne(resource)
- environ = {'bfg.routes.matchdict': {'subpath':('a', 'b', 'c')}}
- request = DummyRequest(environ)
+ matchdict = {'subpath':('a', 'b', 'c')}
+ request = DummyRequest({})
+ request.matchdict = matchdict
result = traverser(request)
self.assertEqual(result['context'], resource)
self.assertEqual(result['view_name'], '')
@@ -419,8 +414,9 @@ class ResourceTreeTraverserTests(unittest.TestCase):
def test_withroute_and_traverse_string(self):
resource = DummyContext()
traverser = self._makeOne(resource)
- environ = {'bfg.routes.matchdict': {'traverse':'foo/bar'}}
- request = DummyRequest(environ)
+ matchdict = {'traverse':text_('foo/bar')}
+ request = DummyRequest({})
+ request.matchdict = matchdict
result = traverser(request)
self.assertEqual(result['context'], resource)
self.assertEqual(result['view_name'], 'foo')
@@ -433,8 +429,9 @@ class ResourceTreeTraverserTests(unittest.TestCase):
def test_withroute_and_traverse_tuple(self):
resource = DummyContext()
traverser = self._makeOne(resource)
- environ = {'bfg.routes.matchdict': {'traverse':('foo', 'bar')}}
- request = DummyRequest(environ)
+ matchdict = {'traverse':('foo', 'bar')}
+ request = DummyRequest({})
+ request.matchdict = matchdict
result = traverser(request)
self.assertEqual(result['context'], resource)
self.assertEqual(result['view_name'], 'foo')
@@ -447,8 +444,9 @@ class ResourceTreeTraverserTests(unittest.TestCase):
def test_withroute_and_traverse_empty(self):
resource = DummyContext()
traverser = self._makeOne(resource)
- environ = {'bfg.routes.matchdict': {'traverse':''}}
- request = DummyRequest(environ)
+ matchdict = {'traverse':''}
+ request = DummyRequest({})
+ request.matchdict = matchdict
result = traverser(request)
self.assertEqual(result['context'], resource)
self.assertEqual(result['view_name'], '')
@@ -458,21 +456,6 @@ class ResourceTreeTraverserTests(unittest.TestCase):
self.assertEqual(result['virtual_root'], resource)
self.assertEqual(result['virtual_root_path'], ())
- def test_call_with_environ(self):
- with warnings.catch_warnings(record=True) as w:
- warnings.filterwarnings('always')
- policy = self._makeOne(None)
- environ = self._getEnviron()
- result = policy(environ)
- self.assertEqual(result['context'], None)
- self.assertEqual(result['view_name'], '')
- self.assertEqual(result['subpath'], ())
- self.assertEqual(result['traversed'], ())
- self.assertEqual(result['root'], policy.root)
- self.assertEqual(result['virtual_root'], policy.root)
- self.assertEqual(result['virtual_root_path'], ())
- self.assertEqual(len(w), 1)
-
class FindInterfaceTests(unittest.TestCase):
def _callFUT(self, context, iface):
from pyramid.traversal import find_interface
@@ -1310,11 +1293,28 @@ class DummyContext(object):
return '<DummyContext with name %s at id %s>'%(self.__name__, id(self))
class DummyRequest:
+
application_url = 'http://example.com:5432' # app_url never ends with slash
- def __init__(self, environ=None):
+ matchdict = None
+ matched_route = None
+
+ def __init__(self, environ=None, path_info=text_('/'), toraise=None):
if environ is None:
environ = {}
self.environ = environ
+ self._set_path_info(path_info)
+ self.toraise = toraise
+
+ def _get_path_info(self):
+ if self.toraise:
+ raise self.toraise
+ return self._path_info
+
+ def _set_path_info(self, v):
+ self._path_info = v
+
+ path_info = property(_get_path_info, _set_path_info)
+
class DummyContextURL:
def __init__(self, context, request):
diff --git a/pyramid/tests/test_util.py b/pyramid/tests/test_util.py
index e83ad5922..3d85e18f5 100644
--- a/pyramid/tests/test_util.py
+++ b/pyramid/tests/test_util.py
@@ -132,6 +132,20 @@ class Test_InstancePropertyMixin(unittest.TestCase):
self.assertEqual(1, foo.x)
self.assertEqual(2, foo.y)
+ def test__set_extensions(self):
+ inst = self._makeOne()
+ def foo(self, result):
+ return result
+ n, bar = inst._make_property(lambda _: 'bar', name='bar')
+ class Extensions(object):
+ def __init__(self):
+ self.methods = {'foo':foo}
+ self.descriptors = {'bar':bar}
+ extensions = Extensions()
+ inst._set_extensions(extensions)
+ self.assertEqual(inst.bar, 'bar')
+ self.assertEqual(inst.foo('abc'), 'abc')
+
class Test_WeakOrderedSet(unittest.TestCase):
def _makeOne(self):
from pyramid.config import WeakOrderedSet
diff --git a/pyramid/traversal.py b/pyramid/traversal.py
index b514d4c16..6832ce69a 100644
--- a/pyramid/traversal.py
+++ b/pyramid/traversal.py
@@ -614,6 +614,7 @@ else:
_segment_cache[(segment, safe)] = result
return result
+slash = text_('/')
@implementer(ITraverser)
class ResourceTreeTraverser(object):
@@ -629,27 +630,17 @@ class ResourceTreeTraverser(object):
self.root = root
def __call__(self, request):
- try:
- environ = request.environ
- except AttributeError:
- # In BFG 1.0 and before, this API expected an environ
- # rather than a request; some bit of code may still be
- # passing us an environ. If so, deal.
- environ = request
- depwarn = ('Passing an environ dictionary directly to a traverser '
- 'is deprecated in Pyramid 1.1. Pass a request object '
- 'instead.')
- warnings.warn(depwarn, DeprecationWarning, 2)
-
- if 'bfg.routes.matchdict' in environ:
- matchdict = environ['bfg.routes.matchdict']
-
- path = matchdict.get('traverse', '/') or '/'
+ environ = request.environ
+ matchdict = request.matchdict
+
+ if matchdict is not None:
+
+ path = matchdict.get('traverse', slash) or slash
if is_nonstr_iter(path):
# this is a *traverse stararg (not a {traverse})
# routing has already decoded these elements, so we just
# need to join them
- path = '/'.join(path) or '/'
+ path = slash.join(path) or slash
subpath = matchdict.get('subpath', ())
if not is_nonstr_iter(subpath):
@@ -663,9 +654,10 @@ class ResourceTreeTraverser(object):
subpath = ()
try:
# empty if mounted under a path in mod_wsgi, for example
- path = decode_path_info(environ['PATH_INFO'] or '/')
+ path = request.path_info or slash
except KeyError:
- path = '/'
+ # if environ['PATH_INFO'] is just not there
+ path = slash
except UnicodeDecodeError as e:
raise URLDecodeError(e.encoding, e.object, e.start, e.end,
e.reason)
@@ -684,7 +676,7 @@ class ResourceTreeTraverser(object):
root = self.root
ob = vroot = root
- if vpath == '/': # invariant: vpath must not be empty
+ if vpath == slash: # invariant: vpath must not be empty
# prevent a call to traversal_path if we know it's going
# to return the empty tuple
vpath_tuple = ()
diff --git a/pyramid/util.py b/pyramid/util.py
index dabd84695..6190e8156 100644
--- a/pyramid/util.py
+++ b/pyramid/util.py
@@ -2,6 +2,7 @@ import inspect
import weakref
from pyramid.compat import (
+ iteritems_,
integer_types,
string_types,
text_,
@@ -74,6 +75,12 @@ class InstancePropertyMixin(object):
cls = type(parent.__name__, (parent, object), attrs)
self.__class__ = cls
+ def _set_extensions(self, extensions):
+ for name, fn in iteritems_(extensions.methods):
+ method = fn.__get__(self, self.__class__)
+ setattr(self, name, method)
+ self._set_properties(extensions.descriptors)
+
def set_property(self, callable, name=None, reify=False):
""" Add a callable or a property descriptor to the instance.
diff --git a/setup.py b/setup.py
index cbc1075bd..03ebb4293 100644
--- a/setup.py
+++ b/setup.py
@@ -39,7 +39,7 @@ install_requires=[
'setuptools',
'Chameleon >= 1.2.3',
'Mako >= 0.3.6', # strict_undefined
- 'WebOb >= 1.2dev', # response.text / py3 compat
+ 'WebOb >= 1.2b3', # request.path_info is unicode
'repoze.lru >= 0.4', # py3 compat
'zope.interface >= 3.8.0', # has zope.interface.registry
'zope.deprecation >= 3.5.0', # py3 compat
diff --git a/tox.ini b/tox.ini
index 85bd41bda..b50e56544 100644
--- a/tox.ini
+++ b/tox.ini
@@ -4,45 +4,16 @@ envlist =
[testenv]
commands =
+ python setup.py dev
python setup.py test -q
-deps =
- zope.component
- Sphinx
- repoze.sphinx.autointerface
- WebTest
- virtualenv
- venusian
-
-[testenv:py32]
-commands =
- python setup.py test -q
-deps =
- WebTest
- virtualenv
- venusian
-
-[testenv:py33]
-commands =
- python setup.py test -q
-deps =
- WebTest
- virtualenv
- venusian
[testenv:cover]
basepython =
python2.6
commands =
+ python setup.py dev
python setup.py nosetests --with-xunit --with-xcoverage
deps =
- zope.component
- Sphinx
- WebTest
- repoze.sphinx.autointerface
- virtualenv
- venusian
- nose
- coverage
nosexcover
# we separate coverage into its own testenv because a) "last run wins" wrt