diff options
| author | Chris McDonough <chrism@plope.com> | 2013-02-09 19:15:07 -0500 |
|---|---|---|
| committer | Chris McDonough <chrism@plope.com> | 2013-02-09 19:15:07 -0500 |
| commit | acf115391088770ae434d222179fd22a693bfe46 (patch) | |
| tree | 442d33920cd6d20ccb7ce3cff3344fd851448d0d /CHANGES.txt | |
| parent | 6313e0dd97e22b8c897293cd8d5f2f145637f49f (diff) | |
| parent | 7fe736bf57696aa62c8b0d84e62ad486d0f88f40 (diff) | |
| download | pyramid-acf115391088770ae434d222179fd22a693bfe46.tar.gz pyramid-acf115391088770ae434d222179fd22a693bfe46.tar.bz2 pyramid-acf115391088770ae434d222179fd22a693bfe46.zip | |
Merge branch 'master' of github.com:Pylons/pyramid
Diffstat (limited to 'CHANGES.txt')
| -rw-r--r-- | CHANGES.txt | 221 |
1 files changed, 219 insertions, 2 deletions
diff --git a/CHANGES.txt b/CHANGES.txt index 9f5ce064f..adf448945 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,220 @@ +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 +-------- + +- Small microspeed enhancement which anticipates that a + ``pyramid.response.Response`` object is likely to be returned from a view. + Some code is shortcut if the class of the object returned by a view is this + class. A similar microoptimization was done to + ``pyramid.request.Request.is_response``. + +- Make it possible to use variable arguments on ``p*`` commands (``pserve``, + ``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 +--------- + +- A failure when trying to locate the attribute ``__text__`` on route and view + predicates existed when the ``debug_routematch`` setting was true or when the + ``pviews`` command was used. See https://github.com/Pylons/pyramid/pull/727 + +Documentation +------------- + +- Sync up tutorial source files with the files that are rendered by the + scaffold that each uses. + 1.4a4 (2012-11-14) ================== @@ -115,7 +332,7 @@ Bug Fixes - 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. @@ -319,7 +536,7 @@ Features - 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`` |
