diff options
| author | Chris McDonough <chrism@plope.com> | 2013-02-09 19:45:23 -0500 |
|---|---|---|
| committer | Chris McDonough <chrism@plope.com> | 2013-02-09 19:45:23 -0500 |
| commit | eb60ad1289f5f7d9ace02b0a28feda70908f9fa0 (patch) | |
| tree | b495b477d46197e5874cbd30bba4035b587b6c84 | |
| parent | acf115391088770ae434d222179fd22a693bfe46 (diff) | |
| parent | 65cf215b75909f3b2624150c432d5355af7384da (diff) | |
| download | pyramid-eb60ad1289f5f7d9ace02b0a28feda70908f9fa0.tar.gz pyramid-eb60ad1289f5f7d9ace02b0a28feda70908f9fa0.tar.bz2 pyramid-eb60ad1289f5f7d9ace02b0a28feda70908f9fa0.zip | |
Merge branch 'master' of github.com:Pylons/pyramid
| -rw-r--r-- | docs/api/exceptions.rst | 2 | ||||
| -rw-r--r-- | docs/api/request.rst | 2 | ||||
| -rw-r--r-- | docs/narr/hooks.rst | 89 | ||||
| -rw-r--r-- | docs/narr/install.rst | 2 | ||||
| -rw-r--r-- | docs/narr/renderers.rst | 3 | ||||
| -rw-r--r-- | docs/tutorials/wiki/definingviews.rst | 37 | ||||
| -rw-r--r-- | pyramid/config/factories.py | 4 | ||||
| -rw-r--r-- | pyramid/exceptions.py | 28 | ||||
| -rw-r--r-- | pyramid/interfaces.py | 8 | ||||
| -rw-r--r-- | pyramid/response.py | 12 |
10 files changed, 158 insertions, 29 deletions
diff --git a/docs/api/exceptions.rst b/docs/api/exceptions.rst index 1dfbf46fd..ab158f18d 100644 --- a/docs/api/exceptions.rst +++ b/docs/api/exceptions.rst @@ -5,6 +5,8 @@ .. automodule:: pyramid.exceptions + .. autoclass:: PredicateMismatch + .. autoclass:: Forbidden .. autoclass:: NotFound diff --git a/docs/api/request.rst b/docs/api/request.rst index 9f1f71b31..7b843f86e 100644 --- a/docs/api/request.rst +++ b/docs/api/request.rst @@ -245,7 +245,7 @@ influence response values from a view that uses a renderer (such as the status code, a header, the content type, etc) you would set these attributes. See :ref:`response_prefixed_attrs` for further discussion. - As of Pyramid 1.1, assignment to ``response_*`` attrs are deprecated. + As of Pyramid 1.1, assignment to ``response_*`` attrs is deprecated. Assigning to one is still supported but will cause a deprecation warning to be emitted, and eventually the feature will be removed. For new code, instead of assigning ``response_*`` attributes to the diff --git a/docs/narr/hooks.rst b/docs/narr/hooks.rst index fc5c0ff23..43bf48289 100644 --- a/docs/narr/hooks.rst +++ b/docs/narr/hooks.rst @@ -257,6 +257,95 @@ already constructed a :term:`configurator` it can also be registered via the config.set_request_factory(MyRequest) .. index:: + single: request method + +.. _adding_request_method: + +Adding Methods or Properties to Request Object +---------------------------------------------- + +.. versionadded:: 1.4. + +Since each Pyramid application can only have one :term:`request` factory, +:ref:`changing the request factory <changing_the_request_factory>` +is not that extensible, especially if you want to build composable features +(e.g., Pyramid add-ons and plugins). + +A lazy property can be registered to the request object via the +:meth:`pyramid.config.Configurator.add_request_method` API. This allows you +to specify a callable that will be available on the request object, but will not +actually execute the function until accessed. + +.. warning:: This will silently override methods and properties from + :term:`request factory` that have the same name. + +.. code-block:: python + :linenos: + + from pyramid.config import Configurator + + def total(request, *args): + return sum(args) + + def prop(request): + print "getting the property" + return "the property" + + config = Configurator() + config.add_request_method(total) + config.add_request_method(prop, reify=True) + +In the above example, ``total`` is added as a method. However, ``prop`` is added +as a property and its result is cached per-request by setting ``reify=True``. +This way, we eliminate the overhead of running the function multiple times. + + >>> request.total(1, 2, 3) + 6 + >>> request.prop + getting the property + the property + >>> request.prop + the property + +To not cache the result of ``request.prop``, set ``property=True`` instead of +``reify=True``. + +Here is an example of passing a class to ``Configurator.add_request_method``: + +.. code-block:: python + :linenos: + + from pyramid.config import Configurator + from pyramid.decorator import reify + + class ExtraStuff(object): + + def __init__(self, request): + self.request = request + + def total(self, *args): + return sum(args) + + # use @property if you don't want to cache the result + @reify + def prop(self): + print "getting the property" + return "the property" + + config = Configurator() + config.add_request_method(ExtraStuff, 'extra', reify=True) + +We attach and cache an object named ``extra`` to the ``request`` object. + + >>> request.extra.total(1, 2, 3) + 6 + >>> request.extra.prop + getting the property + the property + >>> request.extra.prop + the property + +.. index:: single: before render event single: adding renderer globals diff --git a/docs/narr/install.rst b/docs/narr/install.rst index b092f73bc..85dfd5bf4 100644 --- a/docs/narr/install.rst +++ b/docs/narr/install.rst @@ -203,7 +203,7 @@ Installing Distribute On Python 3 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``setuptools`` doesn't work under Python 3. Instead, you can use -``distribute``, which is a fork of setuptools that does work on Python 3. To +``distribute``, which is a fork of setuptools. To install it, first download `distribute_setup.py <http://python-distribute.org/distribute_setup.py>`_ then invoke it using the Python interpreter into which you want to install setuptools. diff --git a/docs/narr/renderers.rst b/docs/narr/renderers.rst index 863932e83..34b9ad00c 100644 --- a/docs/narr/renderers.rst +++ b/docs/narr/renderers.rst @@ -565,9 +565,6 @@ in :ref:`request_module`. For more information on the API of Deprecated Mechanism to Vary Attributes of Rendered Responses ------------------------------------------------------------- -.. deprecated:: 1.1 - The behavior described in this entire section. - In previous releases of Pyramid (1.0 and before), the ``request.response`` attribute did not exist. Instead, Pyramid required users to set special ``response_`` -prefixed attributes of the request to influence response diff --git a/docs/tutorials/wiki/definingviews.rst b/docs/tutorials/wiki/definingviews.rst index efcc7bf21..4dedf4320 100644 --- a/docs/tutorials/wiki/definingviews.rst +++ b/docs/tutorials/wiki/definingviews.rst @@ -71,6 +71,13 @@ and a final view named ``edit_page`` will allow a page to be edited. The ``view_wiki`` view function ------------------------------- +Here is the code for the ``view_wiki`` view function and its decorator, which +will be added to ``views.py``: + +.. literalinclude:: src/views/tutorial/views.py + :lines: 12-14 + :language: python + The ``view_wiki`` function will be configured to respond as the default view callable for a Wiki resource. We'll provide it with a ``@view_config`` decorator which names the class ``tutorial.models.Wiki`` as its context. @@ -84,16 +91,22 @@ The ``view_wiki`` view callable always redirects to the URL of a Page resource named "FrontPage". To do so, it returns an instance of the :class:`pyramid.httpexceptions.HTTPFound` class (instances of which implement the :class:`pyramid.interfaces.IResponse` interface like -:class:`pyramid.response.Response` does). The -:meth:`pyramid.request.Request.resource_url` API. +:class:`pyramid.response.Response` does). :meth:`pyramid.request.Request.resource_url` constructs a URL to the -``FrontPage`` page resource (e.g. ``http://localhost:6543/FrontPage``), and +``FrontPage`` page resource (i.e., ``http://localhost:6543/FrontPage``), and uses it as the "location" of the HTTPFound response, forming an HTTP redirect. The ``view_page`` view function ------------------------------- +Here is the code for the ``view_page`` view function and its decorator, which +will be added to ``views.py``: + +.. literalinclude:: src/views/tutorial/views.py + :lines: 16-33 + :language: python + The ``view_page`` function will be configured to respond as the default view of a Page resource. We'll provide it with a ``@view_config`` decorator which names the class ``tutorial.models.Page`` as its context. This means that @@ -101,7 +114,7 @@ when a Page resource is the context, and no :term:`view name` exists in the request, this view will be used. We inform :app:`Pyramid` this view will use the ``templates/view.pt`` template file as a ``renderer``. -The ``view_page`` function generates the :term:`ReStructuredText` body of a +The ``view_page`` function generates the :term:`reStructuredText` body of a page (stored as the ``data`` attribute of the context passed to the view; the context will be a Page resource) as HTML. Then it substitutes an HTML anchor for each *WikiWord* reference in the rendered HTML using a compiled regular @@ -140,6 +153,13 @@ callable. In the ``view_wiki`` view callable, we unconditionally return a The ``add_page`` view function ------------------------------ +Here is the code for the ``add_page`` view function and its decorator, which +will be added to ``views.py``: + +.. literalinclude:: src/views/tutorial/views.py + :lines: 35-50 + :language: python + The ``add_page`` function will be configured to respond when the context resource is a Wiki and the :term:`view name` is ``add_page``. We'll provide it with a ``@view_config`` decorator which names the string ``add_page`` as @@ -171,7 +191,7 @@ we're trying to add. If the view rendering is *not* a result of a form submission (if the expression ``'form.submitted' in request.params`` is ``False``), the view renders a template. To do so, it generates a "save url" which the template -use as the form post URL during rendering. We're lazy here, so we're trying +uses as the form post URL during rendering. We're lazy here, so we're trying to use the same template (``templates/edit.pt``) for the add view as well as the page edit view. To do so, we create a dummy Page resource object in order to satisfy the edit form's desire to have *some* page object exposed as @@ -187,6 +207,13 @@ the page body, and save it into "our context" (the Wiki) using the The ``edit_page`` view function ------------------------------- +Here is the code for the ``edit_page`` view function and its decorator, which +will be added to ``views.py``: + +.. literalinclude:: src/views/tutorial/views.py + :lines: 52-60 + :language: python + The ``edit_page`` function will be configured to respond when the context is a Page resource and the :term:`view name` is ``edit_page``. We'll provide it with a ``@view_config`` decorator which names the string ``edit_page`` as its diff --git a/pyramid/config/factories.py b/pyramid/config/factories.py index ef7975d92..d30df3b74 100644 --- a/pyramid/config/factories.py +++ b/pyramid/config/factories.py @@ -182,9 +182,7 @@ class FactoriesConfiguratorMixin(object): def set_request_property(self, callable, name=None, reify=False): """ Add a property to the request object. - .. warning:: - - This method has been docs-deprecated as of Pyramid 1.4. + .. deprecated:: 1.4 :meth:`pyramid.config.Configurator.add_request_method` should be used instead. diff --git a/pyramid/exceptions.py b/pyramid/exceptions.py index dab958282..a8fca1d84 100644 --- a/pyramid/exceptions.py +++ b/pyramid/exceptions.py @@ -10,11 +10,29 @@ CR = '\n' class PredicateMismatch(HTTPNotFound): """ - Internal exception (not an API) raised by multiviews when no - view matches. This exception subclasses the ``NotFound`` - exception only one reason: if it reaches the main exception - handler, it should be treated like a ``NotFound`` by any exception - view registrations. + This exception is raised by multiviews when no view matches + all given predicates. + + This exception subclasses the :class:`HTTPNotFound` exception for a + specific reason: if it reaches the main exception handler, it should + be treated as :class:`HTTPNotFound`` by any exception view + registrations. Thus, typically, this exception will not be seen + publicly. + + However, this exception will be raised if the predicates of all + views configured to handle another exception context cannot be + successfully matched. For instance, if a view is configured to + handle a context of ``HTTPForbidden`` and the configured with + additional predicates, then :class:`PredicateMismatch` will be + raised if: + + * An original view callable has raised :class:`HTTPForbidden` (thus + invoking an exception view); and + * The given request fails to match all predicates for said + exception view associated with :class:`HTTPForbidden`. + + The same applies to any type of exception being handled by an + exception view. """ class URLDecodeError(UnicodeDecodeError): diff --git a/pyramid/interfaces.py b/pyramid/interfaces.py index 54bce6fd2..0a5ec9588 100644 --- a/pyramid/interfaces.py +++ b/pyramid/interfaces.py @@ -744,10 +744,8 @@ class IResourceURL(Interface): class IContextURL(IResourceURL): """ An adapter which deals with URLs related to a context. - ..warning:: - - This interface is deprecated as of Pyramid 1.3 with the introduction of - IResourceURL. + .. deprecated:: 1.3 + use IResourceURL instead. """ # this class subclasses IResourceURL because request.resource_url looks # for IResourceURL via queryAdapter. queryAdapter will find a deprecated @@ -792,7 +790,7 @@ deprecated( 'scheduled to be removed. Use the ' '"pyramid.config.Configurator.add_resource_url_adapter" method to register ' 'a class that implements "pyramid.interfaces.IResourceURL" instead. ' - 'See the "What\'s new In Pyramid 1.3" document for a further description.' + 'See the "What\'s new In Pyramid 1.3" document for more details.' ) class IPackageOverrides(Interface): diff --git a/pyramid/response.py b/pyramid/response.py index 1dccb7ae8..0f61af472 100644 --- a/pyramid/response.py +++ b/pyramid/response.py @@ -35,20 +35,20 @@ class FileResponse(Response): ``path`` is a file path on disk. - ``request`` must be a Pyramid :term:`request` object if passed. Note + ``request`` must be a Pyramid :term:`request` object. Note that a request *must* be passed if the response is meant to attempt to use the ``wsgi.file_wrapper`` feature of the web server that you're using to serve your Pyramid application. - ``cache_max_age`` if passed, is the number of seconds that should be used + ``cache_max_age`` is the number of seconds that should be used to HTTP cache this response. - ``content_type``, if passed, is the content_type of the response. + ``content_type`` is the content_type of the response. - ``content_encoding``, if passed is the content_encoding of the response. + ``content_encoding`` is the content_encoding of the response. It's generally safe to leave this set to ``None`` if you're serving a - binary file. This argument will be ignored if you don't also pass - ``content-type``. + binary file. This argument will be ignored if you also leave + ``content-type`` as ``None``. """ def __init__(self, path, request=None, cache_max_age=None, content_type=None, content_encoding=None): |
