Chris McDonough
2011-08-21 4f070b0887e43c6582a06e0e2c318a5c09962340
remove tween aliases as a concept
6 files modified
313 ■■■■ changed files
docs/narr/hooks.rst 33 ●●●● patch | view | raw | blame | history
pyramid/config/tweens.py 103 ●●●●● patch | view | raw | blame | history
pyramid/paster.py 25 ●●●● patch | view | raw | blame | history
pyramid/tests/test_config/test_init.py 27 ●●●● patch | view | raw | blame | history
pyramid/tests/test_config/test_tweens.py 123 ●●●●● patch | view | raw | blame | history
pyramid/tweens.py 2 ●●● patch | view | raw | blame | history
docs/narr/hooks.rst
@@ -930,10 +930,10 @@
Note that you must use a :term:`dotted Python name` as the first argument to
:meth:`pyramid.config.Configurator.add_tween`; this must point at a tween
factory.  You cannot pass the tween factory object itself to the method: it
must be a globally importable object.  In the above example, we assume that a
``timing_tween_factory`` tween factory was defined in a module named
``myapp.tweens``, so the tween factory is importable as
``myapp.tweens.timing_tween_factory``.
must be :term:`dotted Python name` that points to a globally importable
object.  In the above example, we assume that a ``timing_tween_factory``
tween factory was defined in a module named ``myapp.tweens``, so the tween
factory is importable as ``myapp.tweens.timing_tween_factory``.
When you use :meth:`pyramid.config.Configurator.add_tween`, you're
instructing the system to use your tween factory at startup time unless the
@@ -992,9 +992,6 @@
- A :term:`dotted Python name` to a tween factory: a string representing the
  predicted dotted name of a tween factory added in a call to ``add_tween``
  in the same configuration session.
- A "tween alias": a string representing the predicted value of ``alias`` in
  a separate call to ``add_tween`` in the same configuration session
- One of the constants :attr:`pyramid.tweens.MAIN`,
  :attr:`pyramid.tweens.INGRESS`, or :attr:`pyramid.tweens.EXCVIEW`.
@@ -1062,28 +1059,6 @@
'someothertween' tween, the 'someothertween2' tween, and INGRESS. If any of
these is not in the current configuration, this constraint will only organize
itself based on the tweens that are present.
:meth:`~pyramid.config.Configurator.add_tween` also accepts an ``alias``
argument.  If ``alias`` is not ``None``, should be a string.  The string will
represent a value that other callers of ``add_tween`` may pass as an
``under`` and ``over`` argument instead of a dotted name to a tween factory.
For example:
.. code-block:: python
   :linenos:
   import pyramid.tweens
   config.add_tween('myapp.tween_factory1',
                    alias='one'
                    over=pyramid.tweens.MAIN)
   config.add_tween('myapp.tween_factory2',
                    alias='two'
                    over=pyramid.tweens.MAIN,
                    under='one')
Alias names are only useful in relation to ``under`` and ``over`` values.
They cannot be used in explicit tween chain configuration, or anywhere else.
.. _explicit_tween_ordering:
pyramid/config/tweens.py
@@ -9,7 +9,7 @@
from pyramid.config.util import action_method
class TweensConfiguratorMixin(object):
    def add_tween(self, tween_factory, alias=None, under=None, over=None):
    def add_tween(self, tween_factory, under=None, over=None):
        """
        .. note:: This feature is new as of Pyramid 1.2.
@@ -32,11 +32,6 @@
        The ``tween_factory`` argument must be a :term:`dotted Python name`
        to a global object representing the tween factory.
        The ``alias`` argument, if it is not ``None``, should be a string.
        The string will represent a value that other callers of ``add_tween``
        may pass as an ``under`` and ``over`` argument instead of this
        tween's factory name.
        The ``under`` and ``over`` arguments allow the caller of
        ``add_tween`` to provide a hint about where in the tween chain this
        tween factory should be placed when an implicit tween chain is used.
@@ -50,10 +45,6 @@
          representing the dotted name of a tween factory added in a call to
          ``add_tween`` in the same configuration session.
        - A tween alias: a string representing the predicted value of
          ``alias`` in a separate call to ``add_tween`` in the same
          configuration session
        - One of the constants :attr:`pyramid.tweens.MAIN`,
          :attr:`pyramid.tweens.INGRESS`, or :attr:`pyramid.tweens.EXCVIEW`.
@@ -66,23 +57,22 @@
        For example, calling ``add_tween('myapp.tfactory',
        over=pyramid.tweens.MAIN)`` will attempt to place the tween factory
        represented by the dotted name ``myapp.tfactory`` directly 'above' (in
        ``paster ptweens`` order) the main Pyramid request handler.
        represented by the dotted name ``myapp.tfactory`` directly 'above'
        (in ``paster ptweens`` order) the main Pyramid request handler.
        Likewise, calling ``add_tween('myapp.tfactory',
        over=pyramid.tweens.MAIN, under='someothertween')`` will attempt to
        place this tween factory 'above' the main handler but 'below' (a
        fictional) 'someothertween' tween factory (which was presumably added
        via ``add_tween('myapp.tfactory', alias='someothertween')``).
        over=pyramid.tweens.MAIN, under='mypkg.someothertween')`` will
        attempt to place this tween factory 'above' the main handler but
        'below' (a fictional) 'mypkg.someothertween' tween factory.
        If all options for ``under`` (or ``over``) cannot be found in the
        current configuration, it is an error. If some options are specified
        purely for compatibilty with other tweens, just add a fallback of
        MAIN or INGRESS. For example,
        ``under=('someothertween', 'someothertween2', INGRESS)``.
        This constraint will require the tween to be located under both the
        'someothertween' tween, the 'someothertween2' tween, and INGRESS. If
        any of these is not in the current configuration, this constraint will
        only organize itself based on the tweens that are present.
        MAIN or INGRESS. For example, ``under=('mypkg.someothertween',
        'mypkg.someothertween2', INGRESS)``.  This constraint will require
        the tween to be located under both the 'mypkg.someothertween' tween,
        the 'mypkg.someothertween2' tween, and INGRESS. If any of these is
        not in the current configuration, this constraint will only organize
        itself based on the tweens that are present.
        Specifying neither ``over`` nor ``under`` is equivalent to specifying
        ``under=INGRESS``.
@@ -94,19 +84,17 @@
        ordering by using an explicit ``pyramid.tweens`` configuration value
        setting.
        ``alias``, ``under``, and ``over`` arguments are ignored when an
        explicit tween chain is specified using the ``pyramid.tweens``
        configuration value.
        ``under``, and ``over`` arguments are ignored when an explicit tween
        chain is specified using the ``pyramid.tweens`` configuration value.
        For more information, see :ref:`registering_tweens`.
        """
        return self._add_tween(tween_factory, alias=alias, under=under,
                               over=over, explicit=False)
        return self._add_tween(tween_factory, under=under, over=over,
                               explicit=False)
    @action_method
    def _add_tween(self, tween_factory, alias=None, under=None, over=None,
                   explicit=False):
    def _add_tween(self, tween_factory, under=None, over=None, explicit=False):
        if not isinstance(tween_factory, basestring):
            raise ConfigurationError(
@@ -115,6 +103,10 @@
                tween_factory)
        name = tween_factory
        if name in (MAIN, INGRESS):
            raise ConfigurationError('%s is a reserved tween name' % name)
        tween_factory = self.maybe_dotted(tween_factory)
        def is_string_or_iterable(v):
@@ -129,9 +121,6 @@
                    raise ConfigurationError(
                        '"%s" must be a string or iterable, not %s' % (t, p))
        if alias in (MAIN, INGRESS):
            raise ConfigurationError('%s is a reserved tween name' % alias)
        if over is INGRESS or hasattr(over, '__iter__') and INGRESS in over:
            raise ConfigurationError('%s cannot be over INGRESS' % name)
@@ -143,18 +132,13 @@
        if tweens is None:
            tweens = Tweens()
            registry.registerUtility(tweens, ITweens)
            tweens.add_implicit('pyramid.tweens.excview_tween_factory',
                                excview_tween_factory, alias=EXCVIEW,
                                over=MAIN)
            tweens.add_implicit(EXCVIEW, excview_tween_factory, over=MAIN)
        if explicit:
            tweens.add_explicit(name, tween_factory)
        else:
            tweens.add_implicit(name, tween_factory, alias=alias, under=under,
                                over=over)
        self.action(('tween', name, explicit))
        if not explicit and alias is not None:
            self.action(('tween', alias, explicit))
            tweens.add_implicit(name, tween_factory, under=under, over=over)
        self.action(('tween', name, explicit))
class CyclicDependencyError(Exception):
    def __init__(self, cycles):
@@ -179,17 +163,11 @@
        self.req_under = set()
        self.factories = {}
        self.order = []
        self.alias_to_name = {INGRESS:INGRESS, MAIN:MAIN}
        self.name_to_alias = {INGRESS:INGRESS, MAIN:MAIN}
    def add_explicit(self, name, factory):
        self.explicit.append((name, factory))
    def add_implicit(self, name, factory, alias=None, under=None, over=None):
        if alias is None:
            alias = name
        self.alias_to_name[alias] = name
        self.name_to_alias[name] = alias
    def add_implicit(self, name, factory, under=None, over=None):
        self.names.append(name)
        self.factories[name] = factory
        if under is None and over is None:
@@ -197,27 +175,22 @@
        if under is not None:
            if not hasattr(under, '__iter__'):
                under = (under,)
            self.order += [(u, alias) for u in under]
            self.req_under.add(alias)
            self.order += [(u, name) for u in under]
            self.req_under.add(name)
        if over is not None:
            if not hasattr(over, '__iter__'):
                over = (over,)
            self.order += [(alias, o) for o in over]
            self.req_over.add(alias)
            self.order += [(name, o) for o in over]
            self.req_over.add(name)
    def implicit(self):
        order = [(INGRESS, MAIN)]
        roots = []
        graph = {}
        aliases = [INGRESS, MAIN]
        for name in self.names:
            aliases.append(self.name_to_alias[name])
        names = [INGRESS, MAIN]
        names.extend(self.names)
        for a, b in self.order:
            # try to convert both a and b to an alias
            a = self.name_to_alias.get(a, a)
            b = self.name_to_alias.get(b, b)
            order.append((a, b))
        def add_node(node):
@@ -231,12 +204,12 @@
            if tonode in roots:
                roots.remove(tonode)
        for alias in aliases:
            add_node(alias)
        for name in names:
            add_node(name)
        has_over, has_under = set(), set()
        for a, b in order:
            if a in aliases and b in aliases: # deal with missing dependencies
            if a in names and b in names: # deal with missing dependencies
                add_arc(a, b)
                has_over.add(a)
                has_under.add(b)
@@ -252,11 +225,11 @@
                % (', '.join(sorted(self.req_under - has_under)))
            )
        sorted_aliases = []
        sorted_names = []
        while roots:
            root = roots.pop(0)
            sorted_aliases.append(root)
            sorted_names.append(root)
            children = graph[root][1:]
            for child in children:
                arcs = graph[child][0]
@@ -275,8 +248,7 @@
        result = []
        for alias in sorted_aliases:
            name = self.alias_to_name.get(alias, alias)
        for name in sorted_names:
            if name in self.names:
                result.append((name, self.factories[name]))
@@ -290,4 +262,3 @@
        for name, factory in use[::-1]:
            handler = factory(handler, registry)
        return handler
pyramid/paster.py
@@ -606,28 +606,15 @@
    def out(self, msg): # pragma: no cover
        print msg
    def show_implicit(self, tweens):
        implicit = tweens.implicit()
        fmt = '%-10s  %-50s  %-15s'
        self.out(fmt % ('Position', 'Name', 'Alias'))
        self.out(fmt % (
            '-'*len('Position'), '-'*len('Name'), '-'*len('Alias')))
        self.out(fmt % ('-', '-', INGRESS))
        for pos, (name, _) in enumerate(implicit):
            alias = tweens.name_to_alias.get(name, None)
            self.out(fmt % (pos, name, alias))
        self.out(fmt % ('-', '-', MAIN))
    def show_explicit(self, tweens):
        explicit = tweens.explicit
    def show_chain(self, chain):
        fmt = '%-10s  %-65s'
        self.out(fmt % ('Position', 'Name'))
        self.out(fmt % ('-'*len('Position'), '-'*len('Name')))
        self.out(fmt % ('-', INGRESS))
        for pos, (name, _) in enumerate(explicit):
        for pos, (name, _) in enumerate(chain):
            self.out(fmt % (pos, name))
        self.out(fmt % ('-', MAIN))
    def command(self):
        config_uri = self.args[0]
        env = self.bootstrap[0](config_uri)
@@ -641,15 +628,15 @@
                self.out('')
                self.out('Explicit Tween Chain (used)')
                self.out('')
                self.show_explicit(tweens)
                self.show_chain(tweens.explicit)
                self.out('')
                self.out('Implicit Tween Chain (not used)')
                self.out('')
                self.show_implicit(tweens)
                self.show_chain(tweens.implicit())
            else:
                self.out('"pyramid.tweens" config value NOT set '
                         '(implicitly ordered tweens used)')
                self.out('')
                self.out('Implicit Tween Chain')
                self.out('')
                self.show_implicit(tweens)
                self.show_chain(tweens.implicit())
pyramid/tests/test_config/test_init.py
@@ -786,42 +786,23 @@
        config = self._makeOne()
        self.assertRaises(ConfigurationError, config.add_tween, pyramid.tests)
    def test_add_tween_alias_ingress(self):
    def test_add_tween_name_ingress(self):
        from pyramid.exceptions import ConfigurationError
        from pyramid.tweens import INGRESS
        config = self._makeOne()
        self.assertRaises(
            ConfigurationError,
            config.add_tween,
            'pyramid.tests.test_config.dummy_tween_factory',
            alias=INGRESS)
        self.assertRaises(ConfigurationError, config.add_tween, INGRESS)
    def test_add_tween_alias_main(self):
    def test_add_tween_name_main(self):
        from pyramid.exceptions import ConfigurationError
        from pyramid.tweens import MAIN
        config = self._makeOne()
        self.assertRaises(
            ConfigurationError,
            config.add_tween,
            'pyramid.tests.test_config.dummy_tween_factory',
            alias=MAIN)
        self.assertRaises(ConfigurationError, config.add_tween, MAIN)
    def test_add_tweens_conflict(self):
        from zope.configuration.config import ConfigurationConflictError
        config = self._makeOne()
        config.add_tween('pyramid.tests.test_config.dummy_tween_factory')
        config.add_tween('pyramid.tests.test_config.dummy_tween_factory')
        self.assertRaises(ConfigurationConflictError, config.commit)
    def test_add_tweens_conflict_same_alias(self):
        from zope.configuration.config import ConfigurationConflictError
        config = self._makeOne()
        config.add_tween(
            'pyramid.tests.test_config.dummy_tween_factory',
            alias='a')
        config.add_tween(
            'pyramid.tests.test_config.dummy_tween_factory2',
            alias='a')
        self.assertRaises(ConfigurationConflictError, config.commit)
    def test_add_tween_over_ingress(self):
pyramid/tests/test_config/test_tweens.py
@@ -13,22 +13,18 @@
        self.assertEqual(tweens.explicit, [('name',  'factory'),
                                           ('name2', 'factory2')])
    def test_add_implicit_noaliases(self):
    def test_add_implicit(self):
        from pyramid.tweens import INGRESS
        tweens = self._makeOne()
        tweens.add_implicit('name', 'factory')
        self.assertEqual(tweens.names, ['name'])
        self.assertEqual(tweens.factories,
                         {'name':'factory'})
        self.assertEqual(tweens.alias_to_name['name'], 'name')
        self.assertEqual(tweens.name_to_alias['name'], 'name')
        self.assertEqual(tweens.order, [(INGRESS, 'name')])
        tweens.add_implicit('name2', 'factory2')
        self.assertEqual(tweens.names, ['name',  'name2'])
        self.assertEqual(tweens.factories,
                         {'name':'factory', 'name2':'factory2'})
        self.assertEqual(tweens.alias_to_name['name2'], 'name2')
        self.assertEqual(tweens.name_to_alias['name2'], 'name2')
        self.assertEqual(tweens.order,
                         [(INGRESS, 'name'), (INGRESS, 'name2')])
        tweens.add_implicit('name3', 'factory3', over='name2')
@@ -37,41 +33,9 @@
        self.assertEqual(tweens.factories,
                         {'name':'factory', 'name2':'factory2',
                          'name3':'factory3'})
        self.assertEqual(tweens.alias_to_name['name3'], 'name3')
        self.assertEqual(tweens.name_to_alias['name3'], 'name3')
        self.assertEqual(tweens.order,
                         [(INGRESS, 'name'), (INGRESS, 'name2'),
                          ('name3', 'name2')])
    def test_add_implicit_withaliases(self):
        from pyramid.tweens import INGRESS
        tweens = self._makeOne()
        tweens.add_implicit('name1', 'factory', alias='n1')
        self.assertEqual(tweens.names, ['name1'])
        self.assertEqual(tweens.factories,
                         {'name1':'factory'})
        self.assertEqual(tweens.alias_to_name['n1'], 'name1')
        self.assertEqual(tweens.name_to_alias['name1'], 'n1')
        self.assertEqual(tweens.order, [(INGRESS, 'n1')])
        tweens.add_implicit('name2', 'factory2', alias='n2')
        self.assertEqual(tweens.names, ['name1',  'name2'])
        self.assertEqual(tweens.factories,
                         {'name1':'factory', 'name2':'factory2'})
        self.assertEqual(tweens.alias_to_name['n2'], 'name2')
        self.assertEqual(tweens.name_to_alias['name2'], 'n2')
        self.assertEqual(tweens.order,
                         [(INGRESS, 'n1'), (INGRESS, 'n2')])
        tweens.add_implicit('name3', 'factory3', alias='n3', over='name2')
        self.assertEqual(tweens.names,
                         ['name1',  'name2', 'name3'])
        self.assertEqual(tweens.factories,
                         {'name1':'factory', 'name2':'factory2',
                          'name3':'factory3'})
        self.assertEqual(tweens.alias_to_name['n3'], 'name3')
        self.assertEqual(tweens.name_to_alias['name3'], 'n3')
        self.assertEqual(tweens.order,
                         [(INGRESS, 'n1'), (INGRESS, 'n2'),
                          ('n3', 'name2')])
    def test___call___explicit(self):
        tweens = self._makeOne()
@@ -93,21 +57,6 @@
        tweens.alias_to_name = {'name':'name', 'name2':'name2'}
        tweens.name_to_alias = {'name':'name', 'name2':'name2'}
        tweens.req_under = set(['name', 'name2'])
        tweens.order = [(INGRESS, 'name'), (INGRESS, 'name2')]
        tweens.factories = {'name':factory1, 'name2':factory2}
        self.assertEqual(tweens(None, None), '123')
    def test___call___implicit_with_aliasnames_different_than_names(self):
        from pyramid.tweens import INGRESS
        tweens = self._makeOne()
        def factory1(handler, registry):
            return handler
        def factory2(handler, registry):
            return '123'
        tweens.names = ['name', 'name2']
        tweens.alias_to_name = {'foo1':'name', 'foo2':'name2'}
        tweens.name_to_alias = {'name':'foo1', 'name2':'foo2'}
        tweens.req_under = set(['foo1', 'foo2'])
        tweens.order = [(INGRESS, 'name'), (INGRESS, 'name2')]
        tweens.factories = {'name':factory1, 'name2':factory2}
        self.assertEqual(tweens(None, None), '123')
@@ -193,46 +142,6 @@
                             ('txnmgr', 'txnmgr_factory'),
                             ])
    def test_implicit_ordering_withaliases(self):
        from pyramid.tweens import MAIN
        tweens = self._makeOne()
        add = tweens.add_implicit
        add('exceptionview', 'excview_factory', alias='e', over=MAIN)
        add('auth', 'auth_factory', under='b')
        add('retry', 'retry_factory', over='t', under='exceptionview')
        add('browserid', 'browserid_factory', alias='b')
        add('txnmgr', 'txnmgr_factory', alias='t', under='exceptionview')
        add('dbt', 'dbt_factory')
        self.assertEqual(tweens.implicit(),
                         [
                             ('dbt', 'dbt_factory'),
                             ('browserid', 'browserid_factory'),
                             ('auth', 'auth_factory'),
                             ('exceptionview', 'excview_factory'),
                             ('retry', 'retry_factory'),
                             ('txnmgr', 'txnmgr_factory'),
                          ])
    def test_implicit_ordering_withaliases2(self):
        from pyramid.tweens import MAIN
        tweens = self._makeOne()
        add = tweens.add_implicit
        add('exceptionview', 'excview_factory', alias='e', over=MAIN)
        add('auth', 'auth_factory', alias='a', under='b')
        add('retry', 'retry_factory', alias='r', over='t', under='e')
        add('browserid', 'browserid_factory', alias='b')
        add('txnmgr', 'txnmgr_factory', alias='t', under='e')
        add('dbt', 'dbt_factory', alias='d')
        self.assertEqual(tweens.implicit(),
                         [
                             ('dbt', 'dbt_factory'),
                             ('browserid', 'browserid_factory'),
                             ('auth', 'auth_factory'),
                             ('exceptionview', 'excview_factory'),
                             ('retry', 'retry_factory'),
                             ('txnmgr', 'txnmgr_factory'),
                          ])
    def test_implicit_ordering_missing_over_partial(self):
        from pyramid.exceptions import ConfigurationError
        tweens = self._makeOne()
@@ -300,27 +209,13 @@
                             ('retry', 'retry_factory'),
                             ])
    def test_implicit_ordering_missing_partial_with_aliases(self):
        from pyramid.tweens import MAIN
        tweens = self._makeOne()
        add = tweens.add_implicit
        add('exceptionview', 'excview_factory', alias='e', over=MAIN)
        add('retry', 'retry_factory', over=('txnmgr',MAIN), under='e')
        add('browserid', 'browserid_factory')
        self.assertEqual(tweens.implicit(),
                         [
                             ('browserid', 'browserid_factory'),
                             ('exceptionview', 'excview_factory'),
                             ('retry', 'retry_factory'),
                             ])
    def test_implicit_ordering_with_partial_fallbacks(self):
        from pyramid.tweens import MAIN
        tweens = self._makeOne()
        add = tweens.add_implicit
        add('exceptionview', 'excview_factory', alias='e', over=('b', MAIN))
        add('retry', 'retry_factory', under='e')
        add('browserid', 'browserid_factory', over=('txnmgr', 'e'))
        add('exceptionview', 'excview_factory', over=('wontbethere', MAIN))
        add('retry', 'retry_factory', under='exceptionview')
        add('browserid', 'browserid_factory', over=('wont2', 'exceptionview'))
        self.assertEqual(tweens.implicit(),
                         [
                             ('browserid', 'browserid_factory'),
@@ -332,9 +227,9 @@
        from pyramid.tweens import MAIN
        tweens = self._makeOne()
        add = tweens.add_implicit
        add('exceptionview', 'excview_factory', alias='e', over=MAIN)
        add('retry', 'retry_factory', under='e')
        add('browserid', 'browserid_factory', over=('retry', 'e'))
        add('exceptionview', 'excview_factory', over=MAIN)
        add('retry', 'retry_factory', under='exceptionview')
        add('browserid', 'browserid_factory', over=('retry', 'exceptionview'))
        self.assertEqual(tweens.implicit(),
                         [
                             ('browserid', 'browserid_factory'),
@@ -347,8 +242,8 @@
        from pyramid.tweens import MAIN
        tweens = self._makeOne()
        add = tweens.add_implicit
        add('exceptionview', 'excview_factory', alias='e', over=MAIN)
        add('retry', 'retry_factory', under='e')
        add('exceptionview', 'excview_factory', over=MAIN)
        add('retry', 'retry_factory', under='exceptionview')
        add('browserid', 'browserid_factory', over=('txnmgr', 'auth'))
        self.assertRaises(ConfigurationError, tweens.implicit)
pyramid/tweens.py
@@ -45,4 +45,4 @@
MAIN = 'MAIN'
INGRESS = 'INGRESS'
EXCVIEW = 'excview'
EXCVIEW = 'pyramid.tweens.excview_tween_factory'