| | |
| | | Next release |
| | | next release |
| | | ============ |
| | | |
| | | Features |
| | | -------- |
| | | |
| | | - ``scripts/prequest.py``: add support for submitting ``PUT`` and ``PATCH`` |
| | | requests. See https://github.com/Pylons/pyramid/pull/1033. |
| | | |
| | | - ``ACLAuthorizationPolicy`` supports ``__acl__`` as a callable. This |
| | | removes the ambiguity between the potential ``AttributeError`` that would |
| | | be raised on the ``context`` when the property was not defined and the |
| | | ``AttributeError`` that could be raised from any user-defined code within |
| | | a dynamic property. It is recommended to define a dynamic ACL as a callable |
| | | to avoid this ambiguity. See https://github.com/Pylons/pyramid/issues/735. |
| | | |
| | | - Allow a protocol-relative URL (e.g. ``//example.com/images``) to be passed to |
| | | ``pyramid.config.Configurator.add_static_view``. This allows |
| | | externally-hosted static URLs to be generated based on the current protocol. |
| | | |
| | | - The ``AuthTktAuthenticationPolicy`` now supports IPv6 addresses when using |
| | | the ``include_ip=True`` option. This is possibly incompatible with |
| | | alternative ``auth_tkt`` implementations, as the specification does not |
| | | define how to properly handle IPv6. See |
| | | https://github.com/Pylons/pyramid/issues/831. |
| | | |
| | | - Make it possible to use variable arguments via |
| | | ``pyramid.paster.get_appsettings``. This also allowed the generated |
| | | ``initialize_db`` script from the ``alchemy`` scaffold to grow support |
| | | for options in the form ``a=1 b=2`` so you can fill in |
| | | values in a parameterized ``.ini`` file, e.g. |
| | | ``initialize_myapp_db etc/development.ini a=1 b=2``. |
| | | See https://github.com/Pylons/pyramid/pull/911 |
| | | |
| | | - The ``request.session.check_csrf_token()`` method and the ``check_csrf`` view |
| | | predicate now take into account the value of the HTTP header named |
| | | ``X-CSRF-Token`` (as well as the ``csrf_token`` form parameter, which they |
| | | always did). The header is tried when the form parameter does not exist. |
| | | |
| | | Bug Fixes |
| | | --------- |
| | | |
| | | - Make the ``pyramid.config.assets.PackageOverrides`` object implement the API |
| | | for ``__loader__`` objects specified in PEP 302. Proxies to the |
| | | ``__loader__`` set by the importer, if present; otherwise, raises |
| | | ``NotImplementedError``. This makes Pyramid static view overrides work |
| | | properly under Python 3.3 (previously they would not). See |
| | | https://github.com/Pylons/pyramid/pull/1015 for more information. |
| | | |
| | | - ``mako_templating``: added defensive workaround for non-importability of |
| | | ``mako`` due to upstream ``markupsafe`` dropping Python 3.2 support. Mako |
| | | templating will no longer work under the combination of MarkupSafe 0.17 and |
| | | Python 3.2 (although the combination of MarkupSafe 0.17 and Python 3.3 or any |
| | | supported Python 2 version will work OK). |
| | | |
| | | - View lookup will now search for valid views based on the inheritance |
| | | hierarchy of the context. It tries to find views based on the most |
| | | specific context first, and upon predicate failure, will move up the |
| | | inheritance chain to test views found by the super-type of the context. |
| | | In the past, only the most specific type containing views would be checked |
| | | and if no matching view could be found then a PredicateMismatch would be |
| | | raised. Now predicate mismatches don't hide valid views registered on |
| | | super-types. Here's an example that now works:: |
| | | |
| | | .. code-block:: python |
| | | |
| | | class IResource(Interface): |
| | | |
| | | ... |
| | | |
| | | @view_config(context=IResource) |
| | | def get(context, request): |
| | | |
| | | ... |
| | | |
| | | @view_config(context=IResource, request_method='POST') |
| | | def post(context, request): |
| | | |
| | | ... |
| | | |
| | | @view_config(context=IResource, request_method='DELETE') |
| | | def delete(context, request): |
| | | |
| | | ... |
| | | |
| | | @implementor(IResource) |
| | | class MyResource: |
| | | |
| | | ... |
| | | |
| | | @view_config(context=MyResource, request_method='POST') |
| | | def override_post(context, request): |
| | | |
| | | ... |
| | | |
| | | Previously the override_post view registration would hide the get |
| | | and delete views in the context of MyResource -- leading to a |
| | | predicate mismatch error when trying to use GET or DELETE |
| | | methods. Now the views are found and no predicate mismatch is |
| | | raised. |
| | | See https://github.com/Pylons/pyramid/pull/786 |
| | | |
| | | - Spaces and dots may now be in mako renderer template paths. This was |
| | | broken when support for the new makodef syntax was added in 1.4a1. |
| | | See https://github.com/Pylons/pyramid/issues/950 |
| | | |
| | | - ``pyramid.debug_authorization=true`` will now correctly print out |
| | | ``Allowed`` for views registered with ``NO_PERMISSION_REQUIRED`` instead |
| | | of invoking the ``permits`` method of the authorization policy. |
| | | See https://github.com/Pylons/pyramid/issues/954 |
| | | |
| | | - Pyramid failed to install on some systems due to being packaged with |
| | | some test files containing higher order characters in their names. These |
| | | files have now been removed. See |
| | | https://github.com/Pylons/pyramid/issues/981 |
| | | |
| | | - ``pyramid.testing.DummyResource`` didn't define ``__bool__``, so code under |
| | | Python 3 would use ``__len__`` to find truthiness; this usually caused an |
| | | instance of DummyResource to be "falsy" instead of "truthy". See |
| | | https://github.com/Pylons/pyramid/pull/1032 |
| | | |
| | | 1.4 (2012-12-18) |
| | | ================ |
| | | |
| | | Docs |
| | | ---- |
| | | |
| | | - Fix functional tests in the ZODB tutorial |
| | | |
| | | 1.4b3 (2012-12-10) |
| | | ================== |
| | | |
| | | - Packaging release only, no code changes. 1.4b2 was a brownbag release due to |
| | | missing directories in the tarball. |
| | | |
| | | 1.4b2 (2012-12-10) |
| | | ================== |
| | | |
| | | Docs |
| | | ---- |
| | | |
| | | - Scaffolding is now PEP-8 compliant (at least for a brief shining moment). |
| | | |
| | | - Tutorial improvements. |
| | | |
| | | Backwards Incompatibilities |
| | | --------------------------- |
| | | |
| | | - Modified the ``_depth`` argument to ``pyramid.view.view_config`` to accept |
| | | a value relative to the invocation of ``view_config`` itself. Thus, when it |
| | | was previously expecting a value of ``1`` or greater, to reflect that |
| | | the caller of ``view_config`` is 1 stack frame away from ``venusian.attach``, |
| | | this implementation detail is now hidden. |
| | | |
| | | - Modified the ``_backframes`` argument to ``pyramid.util.action_method`` in a |
| | | similar way to the changes described to ``_depth`` above. This argument |
| | | remains undocumented, but might be used in the wild by some insane person. |
| | | |
| | | 1.4b1 (2012-11-21) |
| | | ================== |
| | | |
| | | Features |
| | | -------- |
| | |
| | | ``pshell``, ``pviews``, etc) in the form ``a=1 b=2`` so you can fill in |
| | | values in parameterized ``.ini`` file, e.g. ``pshell etc/development.ini |
| | | http_port=8080``. See https://github.com/Pylons/pyramid/pull/714 |
| | | |
| | | - A somewhat advanced and obscure feature of Pyramid event handlers is their |
| | | ability to handle "multi-interface" notifications. These notifications have |
| | | traditionally presented multiple objects to the subscriber callable. For |
| | | instance, if an event was sent by code like this:: |
| | | |
| | | registry.notify(event, context) |
| | | |
| | | In the past, in order to catch such an event, you were obligated to write and |
| | | register an event subscriber that mentioned both the event and the context in |
| | | its argument list:: |
| | | |
| | | @subscriber([SomeEvent, SomeContextType]) |
| | | def asubscriber(event, context): |
| | | pass |
| | | |
| | | In many subscriber callables registered this way, it was common for the logic |
| | | in the subscriber callable to completely ignore the second and following |
| | | arguments (e.g. ``context`` in the above example might be ignored), because |
| | | they usually existed as attributes of the event anyway. You could usually |
| | | get the same value by doing ``event.context`` or similar. |
| | | |
| | | The fact that you needed to put an extra argument which you usually ignored |
| | | in the subscriber callable body was only a minor annoyance until we added |
| | | "subscriber predicates", used to narrow the set of circumstances under which |
| | | a subscriber will be executed, in a prior 1.4 alpha release. Once those were |
| | | added, the annoyance was escalated, because subscriber predicates needed to |
| | | accept the same argument list and arity as the subscriber callables that they |
| | | were configured against. So, for example, if you had these two subscriber |
| | | registrations in your code:: |
| | | |
| | | @subscriber([SomeEvent, SomeContextType]) |
| | | def asubscriber(event, context): |
| | | pass |
| | | |
| | | @subscriber(SomeOtherEvent) |
| | | def asubscriber(event): |
| | | pass |
| | | |
| | | And you wanted to use a subscriber predicate:: |
| | | |
| | | @subscriber([SomeEvent, SomeContextType], mypredicate=True) |
| | | def asubscriber1(event, context): |
| | | pass |
| | | |
| | | @subscriber(SomeOtherEvent, mypredicate=True) |
| | | def asubscriber2(event): |
| | | pass |
| | | |
| | | If an existing ``mypredicate`` subscriber predicate had been written in such |
| | | a way that it accepted only one argument in its ``__call__``, you could not |
| | | use it against a subscription which named more than one interface in its |
| | | subscriber interface list. Similarly, if you had written a subscriber |
| | | predicate that accepted two arguments, you couldn't use it against a |
| | | registration that named only a single interface type. |
| | | |
| | | For example, if you created this predicate:: |
| | | |
| | | class MyPredicate(object): |
| | | # portions elided... |
| | | def __call__(self, event): |
| | | return self.val == event.context.foo |
| | | |
| | | It would not work against a multi-interface-registered subscription, so in |
| | | the above example, when you attempted to use it against ``asubscriber1``, it |
| | | would fail at runtime with a TypeError, claiming something was attempting to |
| | | call it with too many arguments. |
| | | |
| | | To hack around this limitation, you were obligated to design the |
| | | ``mypredicate`` predicate to expect to receive in its ``__call__`` either a |
| | | single ``event`` argument (a SomeOtherEvent object) *or* a pair of arguments |
| | | (a SomeEvent object and a SomeContextType object), presumably by doing |
| | | something like this:: |
| | | |
| | | class MyPredicate(object): |
| | | # portions elided... |
| | | def __call__(self, event, context=None): |
| | | return self.val == event.context.foo |
| | | |
| | | This was confusing and bad. |
| | | |
| | | In order to allow people to ignore unused arguments to subscriber callables |
| | | and to normalize the relationship between event subscribers and subscriber |
| | | predicates, we now allow both subscribers and subscriber predicates to accept |
| | | only a single ``event`` argument even if they've been subscribed for |
| | | notifications that involve multiple interfaces. Subscribers and subscriber |
| | | predicates that accept only one argument will receive the first object passed |
| | | to ``notify``; this is typically (but not always) the event object. The |
| | | other objects involved in the subscription lookup will be discarded. You can |
| | | now write an event subscriber that accepts only ``event`` even if it |
| | | subscribes to multiple interfaces:: |
| | | |
| | | @subscriber([SomeEvent, SomeContextType]) |
| | | def asubscriber(event): |
| | | # this will work! |
| | | |
| | | This prevents you from needing to match the subscriber callable parameters to |
| | | the subscription type unnecessarily, especially when you don't make use of |
| | | any argument in your subscribers except for the event object itself. |
| | | |
| | | Note, however, that if the event object is not the first |
| | | object in the call to ``notify``, you'll run into trouble. For example, if |
| | | notify is called with the context argument first:: |
| | | |
| | | registry.notify(context, event) |
| | | |
| | | You won't be able to take advantage of the event-only feature. It will |
| | | "work", but the object received by your event handler won't be the event |
| | | object, it will be the context object, which won't be very useful:: |
| | | |
| | | @subscriber([SomeContextType, SomeEvent]) |
| | | def asubscriber(event): |
| | | # bzzt! you'll be getting the context here as ``event``, and it'll |
| | | # be useless |
| | | |
| | | Existing multiple-argument subscribers continue to work without issue, so you |
| | | should continue use those if your system notifies using multiple interfaces |
| | | and the first interface is not the event interface. For example:: |
| | | |
| | | @subscriber([SomeContextType, SomeEvent]) |
| | | def asubscriber(context, event): |
| | | # this will still work! |
| | | |
| | | The event-only feature makes it possible to use a subscriber predicate that |
| | | accepts only a request argument within both multiple-interface subscriber |
| | | registrations and single-interface subscriber registrations. You needn't |
| | | make slightly different variations of predicates depending on the |
| | | subscription type arguments. Instead, just write all your subscriber |
| | | predicates so they only accept ``event`` in their ``__call__`` and they'll be |
| | | useful across all registrations for subscriptions that use an event as their |
| | | first argument, even ones which accept more than just ``event``. |
| | | |
| | | However, the same caveat applies to predicates as to subscriber callables: if |
| | | you're subscribing to a multi-interface event, and the first interface is not |
| | | the event interface, the predicate won't work properly. In such a case, |
| | | you'll need to match the predicate ``__call__`` argument ordering and |
| | | composition to the ordering of the interfaces. For example, if the |
| | | registration for the subscription uses ``[SomeContext, SomeEvent]``, you'll |
| | | need to reflect that in the ordering of the parameters of the predicate's |
| | | ``__call__`` method:: |
| | | |
| | | def __call__(self, context, event): |
| | | return event.request.path.startswith(self.val) |
| | | |
| | | tl;dr: 1) When using multi-interface subscriptions, always use the event type |
| | | as the first subscription registration argument and 2) When 1 is true, use |
| | | only ``event`` in your subscriber and subscriber predicate parameter lists, |
| | | no matter how many interfaces the subscriber is notified with. This |
| | | combination will result in the maximum amount of reusability of subscriber |
| | | predicates and the least amount of thought on your part. Drink responsibly. |
| | | |
| | | Bug Fixes |
| | | --------- |
| | |
| | | |
| | | - ``pyramid.view.render_view`` was not functioning properly under Python 3.x |
| | | due to a byte/unicode discrepancy. See |
| | | http://github.com/Pylons/pyramid/issues/721 |
| | | https://github.com/Pylons/pyramid/issues/721 |
| | | |
| | | Deprecations |
| | | ------------ |
| | |
| | | |
| | | - When registering a view configuration that named a Chameleon ZPT renderer |
| | | with a macro name in it (e.g. ``renderer='some/template#somemacro.pt``) as |
| | | well as a view configuration without a macro name it it that pointed to the |
| | | well as a view configuration without a macro name in it that pointed to the |
| | | same template (e.g. ``renderer='some/template.pt'``), internal caching could |
| | | confuse the two, and your code might have rendered one instead of the |
| | | other. |
| | |
| | | |
| | | - The static view machinery now raises (rather than returns) ``HTTPNotFound`` |
| | | and ``HTTPMovedPermanently`` exceptions, so these can be caught by the |
| | | NotFound view (and other exception views). |
| | | Not Found View (and other exception views). |
| | | |
| | | - The Mako renderer now supports a def name in an asset spec. When the def |
| | | name is present in the asset spec, the system will render the template def |
| | |
| | | - An ``add_permission`` directive method was added to the Configurator. This |
| | | directive registers a free-standing permission introspectable into the |
| | | Pyramid introspection system. Frameworks built atop Pyramid can thus use |
| | | the the ``permissions`` introspectable category data to build a |
| | | the ``permissions`` introspectable category data to build a |
| | | comprehensive list of permissions supported by a running system. Before |
| | | this method was added, permissions were already registered in this |
| | | introspectable category as a side effect of naming them in an ``add_view`` |