Chris McDonough
2012-09-14 a9f5e705bb331098946eef774857511a02e4f498
Merge branch 'master' of github.com:Pylons/pyramid
4 files deleted
1 files added
45 files modified
2381 ■■■■■ changed files
CHANGES.txt 112 ●●●●● patch | view | raw | blame | history
TODO.txt 56 ●●●● patch | view | raw | blame | history
docs/api.rst 2 ●●●●● patch | view | raw | blame | history
docs/api/chameleon_text.rst 31 ●●●●● patch | view | raw | blame | history
docs/api/chameleon_zpt.rst 28 ●●●●● patch | view | raw | blame | history
docs/api/config.rst 2 ●●● patch | view | raw | blame | history
docs/api/settings.rst 2 ●●●●● patch | view | raw | blame | history
docs/changes.rst 2 ●●●●● patch | view | raw | blame | history
docs/index.rst 1 ●●●● patch | view | raw | blame | history
docs/latexindex.rst 2 ●●●●● patch | view | raw | blame | history
docs/narr/advconfig.rst 2 ●●● patch | view | raw | blame | history
docs/narr/templates.rst 30 ●●●● patch | view | raw | blame | history
docs/narr/testing.rst 2 ●●● patch | view | raw | blame | history
docs/narr/upgrading.rst 232 ●●●●● patch | view | raw | blame | history
docs/tutorials/modwsgi/index.rst 22 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/authorization/tutorial/views.py 10 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/tests/tutorial/views.py 10 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/views/tutorial/views.py 10 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/authorization/tutorial/views.py 16 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/tests/tutorial/views.py 16 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/views/tutorial/views.py 16 ●●●● patch | view | raw | blame | history
pyramid/chameleon_text.py 94 ●●●●● patch | view | raw | blame | history
pyramid/chameleon_zpt.py 91 ●●●●● patch | view | raw | blame | history
pyramid/config/factories.py 21 ●●●● patch | view | raw | blame | history
pyramid/configuration.py 60 ●●●●● patch | view | raw | blame | history
pyramid/paster.py 10 ●●●●● patch | view | raw | blame | history
pyramid/request.py 9 ●●●●● patch | view | raw | blame | history
pyramid/router.py 16 ●●●●● patch | view | raw | blame | history
pyramid/scripting.py 7 ●●●● patch | view | raw | blame | history
pyramid/settings.py 26 ●●●●● patch | view | raw | blame | history
pyramid/testing.py 376 ●●●●● patch | view | raw | blame | history
pyramid/tests/fixtures/withmacro.pt 3 ●●●●● patch | view | raw | blame | history
pyramid/tests/test_chameleon_text.py 112 ●●●● patch | view | raw | blame | history
pyramid/tests/test_chameleon_zpt.py 125 ●●●●● patch | view | raw | blame | history
pyramid/tests/test_config/test_factories.py 67 ●●●● patch | view | raw | blame | history
pyramid/tests/test_config/test_settings.py 9 ●●●●● patch | view | raw | blame | history
pyramid/tests/test_configuration.py 31 ●●●●● patch | view | raw | blame | history
pyramid/tests/test_path.py 6 ●●●● patch | view | raw | blame | history
pyramid/tests/test_renderers.py 14 ●●●●● patch | view | raw | blame | history
pyramid/tests/test_request.py 12 ●●●●● patch | view | raw | blame | history
pyramid/tests/test_router.py 36 ●●●● patch | view | raw | blame | history
pyramid/tests/test_scripting.py 81 ●●●● patch | view | raw | blame | history
pyramid/tests/test_settings.py 26 ●●●●● patch | view | raw | blame | history
pyramid/tests/test_testing.py 289 ●●●●● patch | view | raw | blame | history
pyramid/tests/test_traversal.py 172 ●●●● patch | view | raw | blame | history
pyramid/tests/test_util.py 14 ●●●●● patch | view | raw | blame | history
pyramid/traversal.py 28 ●●●●● patch | view | raw | blame | history
pyramid/util.py 7 ●●●●● patch | view | raw | blame | history
setup.py 2 ●●● patch | view | raw | blame | history
tox.ini 33 ●●●●● patch | view | raw | blame | history
CHANGES.txt
@@ -1,6 +1,7 @@
Next release
============
Bug Fixes
---------
@@ -86,7 +87,7 @@
  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 @@
  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.
TODO.txt
@@ -95,21 +95,49 @@
- 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 @@
- 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.
docs/api.rst
@@ -10,8 +10,6 @@
   api/authorization
   api/authentication
   api/chameleon_text
   api/chameleon_zpt
   api/compat
   api/config
   api/events
docs/api/chameleon_text.rst
File was deleted
docs/api/chameleon_zpt.rst
File was deleted
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`
docs/api/settings.rst
@@ -5,8 +5,6 @@
.. automodule:: pyramid.settings
  .. autofunction:: get_settings
  .. autofunction:: asbool
  .. autofunction:: aslist
docs/changes.rst
@@ -1,3 +1,5 @@
.. _changelog:
:app:`Pyramid` Change History
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
docs/index.rst
@@ -88,6 +88,7 @@
   narr/advconfig
   narr/extconfig
   narr/scaffolding
   narr/upgrading
   narr/threadlocals
   narr/zca
docs/latexindex.rst
@@ -85,8 +85,6 @@
   api/authorization
   api/authentication
   api/chameleon_text
   api/chameleon_zpt
   api/config
   api/events
   api/exceptions
docs/narr/advconfig.rst
@@ -294,9 +294,9 @@
: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`,
docs/narr/templates.rst
@@ -46,20 +46,6 @@
                                 {'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 @@
.. 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
@@ -599,10 +585,6 @@
.. code-block:: text
   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.
docs/narr/testing.rst
@@ -52,7 +52,7 @@
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,
docs/narr/upgrading.rst
New file
@@ -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.
docs/tutorials/modwsgi/index.rst
@@ -7,12 +7,11 @@
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 @@
    `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
docs/tutorials/wiki/src/authorization/tutorial/views.py
@@ -51,17 +51,17 @@
             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,
docs/tutorials/wiki/src/tests/tutorial/views.py
@@ -51,17 +51,17 @@
             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,
docs/tutorials/wiki/src/views/tutorial/views.py
@@ -35,17 +35,17 @@
@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)
docs/tutorials/wiki2/src/authorization/tutorial/views.py
@@ -60,14 +60,14 @@
@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 @@
@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),
        )
docs/tutorials/wiki2/src/tests/tutorial/views.py
@@ -61,15 +61,15 @@
@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 @@
@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),
        )
docs/tutorials/wiki2/src/views/tutorial/views.py
@@ -44,27 +44,27 @@
@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),
        )
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.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 @@
    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):
@@ -51,94 +51,4 @@
            raise ValueError('renderer was passed non-dictionary as value')
        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)')
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 @@
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 @@
        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)')
pyramid/config/factories.py
@@ -76,9 +76,9 @@
        :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 @@
        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 @@
            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 @@
        .. 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 @@
        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)
pyramid/configuration.py
File was deleted
pyramid/paster.py
@@ -1,7 +1,5 @@
import os
import zope.deprecation
from paste.deploy import (
    loadapp,
    appconfig,
@@ -10,14 +8,6 @@
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
pyramid/request.py
@@ -454,13 +454,4 @@
    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)
pyramid/router.py
@@ -6,6 +6,7 @@
from pyramid.interfaces import (
    IDebugLogger,
    IRequest,
    IRequestExtensions,
    IRootFactory,
    IRouteRequest,
    IRouter,
@@ -48,6 +49,7 @@
        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 @@
                           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 @@
                            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 @@
        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 @@
        finally:
            manager.pop()
pyramid/scripting.py
@@ -3,6 +3,7 @@
from pyramid.request import Request
from pyramid.interfaces import (
    IRequestExtensions,
    IRequestFactory,
    IRootFactory,
    )
@@ -70,14 +71,18 @@
                                 '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}
pyramid/settings.py
@@ -1,30 +1,4 @@
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'))
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.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,373 +39,9 @@
    )
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
@@ -646,7 +274,7 @@
        
@implementer(IRequest)
class DummyRequest(DeprecatedRequestMethodsMixin, URLMethodsMixin,
                   CallbackMethodsMixin):
                   CallbackMethodsMixin, InstancePropertyMixin):
    """ A DummyRequest object (incompletely) imitates a :term:`request` object.
    The ``params``, ``environ``, ``headers``, ``path``, and
pyramid/tests/fixtures/withmacro.pt
@@ -1,3 +1,6 @@
<html>
<metal:m define-macro="foo">
  Hello!
</metal:m>
</html>
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 @@
        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 = {}
    
pyramid/tests/test_chameleon_zpt.py
@@ -1,3 +1,4 @@
import sys
import unittest
from pyramid.testing import skip_on
@@ -7,24 +8,27 @@
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 @@
        self.assertTrue(isinstance(result, text_type))
        self.assertEqual(result.rstrip('\n'),
                     '<div xmlns="http://www.w3.org/1999/xhtml">\n</div>')
    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 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)
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 = {}
pyramid/tests/test_config/test_factories.py
@@ -112,49 +112,19 @@
        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 @@
        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)
        self.assertRaises(AttributeError, config.add_request_method)
class DummyRequest(object):
    extensions = None
    def __init__(self, registry):
        self.registry = registry
    def _set_properties(self, properties):
        if self.extensions is None:
            self.extensions = []
        self.extensions.extend(properties)
pyramid/tests/test_config/test_settings.py
@@ -47,6 +47,15 @@
        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):
pyramid/tests/test_configuration.py
File was deleted
pyramid/tests/test_path.py
@@ -138,9 +138,9 @@
        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 @@
        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)
pyramid/tests/test_renderers.py
@@ -533,6 +533,7 @@
        def renderer(*arg):
            def respond(*arg):
                return arg
            renderer.respond = respond
            return respond
        self.config.registry.registerUtility(renderer, IRendererFactory,
                                             name='.foo')
@@ -553,6 +554,11 @@
                                             request=request)
        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()
@@ -652,6 +658,14 @@
        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()
pyramid/tests/test_request.py
@@ -549,18 +549,6 @@
        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:
pyramid/tests/test_router.py
@@ -312,6 +312,38 @@
        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 @@
        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 @@
        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))
pyramid/tests/test_scripting.py
@@ -5,31 +5,37 @@
        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 @@
        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 @@
        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 @@
        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 @@
        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 @@
        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 @@
        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
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):
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 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):
        """ """
pyramid/tests/test_traversal.py
@@ -128,10 +128,23 @@
        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 @@
        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 @@
    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 @@
        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 @@
        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 @@
        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 @@
        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 @@
                         (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 @@
        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 @@
        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 @@
    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 @@
        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):
    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)
        self.assertRaises(URLDecodeError, policy, request)
    def test_non_utf8_path_segment_settings_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)
        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 @@
    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 @@
    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 @@
    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 @@
    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 @@
    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'], '')
@@ -457,21 +455,6 @@
        self.assertEqual(result['root'], resource)
        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):
@@ -1310,11 +1293,28 @@
        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):
pyramid/tests/test_util.py
@@ -132,6 +132,20 @@
        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
pyramid/traversal.py
@@ -614,6 +614,7 @@
            _segment_cache[(segment, safe)] = result
            return result
    
slash = text_('/')
@implementer(ITraverser)
class ResourceTreeTraverser(object):
@@ -629,27 +630,17 @@
        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)
        environ = request.environ
        matchdict = request.matchdict
        if 'bfg.routes.matchdict' in environ:
            matchdict = environ['bfg.routes.matchdict']
        if matchdict is not None:
            path = matchdict.get('traverse', '/') or '/'
            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 @@
            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 @@
        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 = ()
pyramid/util.py
@@ -2,6 +2,7 @@
import weakref
from pyramid.compat import (
    iteritems_,
    integer_types,
    string_types,
    text_,
@@ -74,6 +75,12 @@
        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.
setup.py
@@ -39,7 +39,7 @@
    '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
tox.ini
@@ -4,45 +4,16 @@
[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