summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris McDonough <chrism@plope.com>2011-11-24 17:37:19 -0500
committerChris McDonough <chrism@plope.com>2011-11-24 17:37:19 -0500
commit5e92f34f019e2e6e06ff4c0b5c019349591f9a43 (patch)
tree355cc85952e1e04c9536c9823d17da15b8efd69f
parent8a32e380d933ba015efe4de0d11f9c5971ef9d06 (diff)
downloadpyramid-5e92f34f019e2e6e06ff4c0b5c019349591f9a43.tar.gz
pyramid-5e92f34f019e2e6e06ff4c0b5c019349591f9a43.tar.bz2
pyramid-5e92f34f019e2e6e06ff4c0b5c019349591f9a43.zip
add type name to iintrospectable constructor; rejigger responsibilities between iintrospectable and iintrospector
-rw-r--r--pyramid/config/__init__.py9
-rw-r--r--pyramid/config/adapters.py12
-rw-r--r--pyramid/config/assets.py4
-rw-r--r--pyramid/config/factories.py19
-rw-r--r--pyramid/config/i18n.py5
-rw-r--r--pyramid/config/introspection.py61
-rw-r--r--pyramid/config/routes.py2
-rw-r--r--pyramid/config/views.py17
-rw-r--r--pyramid/interfaces.py125
9 files changed, 152 insertions, 102 deletions
diff --git a/pyramid/config/__init__.py b/pyramid/config/__init__.py
index d78d46cb8..d7e95b7e9 100644
--- a/pyramid/config/__init__.py
+++ b/pyramid/config/__init__.py
@@ -477,12 +477,14 @@ class Configurator(
autocommit = self.autocommit
action_info = self.action_info
+ introspector = self.introspector
if autocommit:
if callable is not None:
callable(*args, **kw)
for introspectable in introspectables:
- introspectable(self.introspector, action_info)
+ if introspector is not None:
+ introspector.register(introspectable, action_info)
else:
self.action_state.action(
@@ -960,8 +962,9 @@ class ActionState(object):
tb)
finally:
del t, v, tb
- for introspectable in introspectables:
- introspectable(introspector, info)
+ if introspector is not None:
+ for introspectable in introspectables:
+ introspector.register(introspectable, info)
finally:
if clear:
diff --git a/pyramid/config/adapters.py b/pyramid/config/adapters.py
index df6b64fa8..620464ed3 100644
--- a/pyramid/config/adapters.py
+++ b/pyramid/config/adapters.py
@@ -27,7 +27,10 @@ class AdaptersConfiguratorMixin(object):
iface = (iface,)
def register():
self.registry.registerHandler(subscriber, iface)
- intr = self.introspectable('subscriber', id(subscriber), 'subscriber')
+ intr = self.introspectable('subscribers',
+ id(subscriber),
+ repr(subscriber),
+ 'subscriber')
intr['subscriber'] = subscriber
intr['interfaces'] = iface
self.action(None, register, introspectables=(intr,))
@@ -56,8 +59,11 @@ class AdaptersConfiguratorMixin(object):
else:
reg.registerAdapter(adapter, (type_or_iface,), IResponse)
discriminator = (IResponse, type_or_iface)
- intr = self.introspectable('response adapter', discriminator,
- 'response adapter')
+ intr = self.introspectable(
+ 'response adapters',
+ discriminator,
+ repr(adapter),
+ 'response adapter')
intr['adapter'] = adapter
intr['type'] = type_or_iface
self.action(discriminator, register, introspectables=(intr,))
diff --git a/pyramid/config/assets.py b/pyramid/config/assets.py
index b37f11865..7080e5e7c 100644
--- a/pyramid/config/assets.py
+++ b/pyramid/config/assets.py
@@ -237,8 +237,10 @@ class AssetsConfiguratorMixin(object):
override(from_package, path, to_package, override_prefix)
intr = self.introspectable(
- 'asset override',
+ 'asset overrides',
(package, override_package, path, override_prefix),
+ '%s/%s -> %s/%s' % (package, path, override_package,
+ override_prefix),
'asset override',
)
intr['package'] = package
diff --git a/pyramid/config/factories.py b/pyramid/config/factories.py
index c557ff72e..6cc90a80b 100644
--- a/pyramid/config/factories.py
+++ b/pyramid/config/factories.py
@@ -27,17 +27,18 @@ class FactoriesConfiguratorMixin(object):
self.registry.registerUtility(factory, IRootFactory)
self.registry.registerUtility(factory, IDefaultRootFactory) # b/c
- intr = self.introspectable('root factory', None, 'root factory')
+ intr = self.introspectable('root factories', None, repr(factory),
+ 'root factory')
intr['factory'] = factory
self.action(IRootFactory, register, introspectables=(intr,))
_set_root_factory = set_root_factory # bw compat
@action_method
- def set_session_factory(self, session_factory):
+ def set_session_factory(self, factory):
"""
Configure the application with a :term:`session factory`. If this
- method is called, the ``session_factory`` argument must be a session
+ method is called, the ``factory`` argument must be a session
factory callable or a :term:`dotted Python name` to that factory.
.. note::
@@ -46,11 +47,12 @@ class FactoriesConfiguratorMixin(object):
:class:`pyramid.config.Configurator` constructor can be used to
achieve the same purpose.
"""
- session_factory = self.maybe_dotted(session_factory)
+ factory = self.maybe_dotted(factory)
def register():
- self.registry.registerUtility(session_factory, ISessionFactory)
- intr = self.introspectable('session factory', None, 'session factory')
- intr['factory'] = session_factory
+ self.registry.registerUtility(factory, ISessionFactory)
+ intr = self.introspectable('session factory', None, repr(factory),
+ 'session factory')
+ intr['factory'] = factory
self.action(ISessionFactory, register, introspectables=(intr,))
@action_method
@@ -72,7 +74,8 @@ class FactoriesConfiguratorMixin(object):
factory = self.maybe_dotted(factory)
def register():
self.registry.registerUtility(factory, IRequestFactory)
- intr = self.introspectable('request factory', None, 'request factory')
+ intr = self.introspectable('request factory', None, repr(factory),
+ 'request factory')
intr['factory'] = factory
self.action(IRequestFactory, register, introspectables=(intr,))
diff --git a/pyramid/config/i18n.py b/pyramid/config/i18n.py
index 5b60f1d99..b405f3683 100644
--- a/pyramid/config/i18n.py
+++ b/pyramid/config/i18n.py
@@ -38,7 +38,7 @@ class I18NConfiguratorMixin(object):
"""
def register():
self._set_locale_negotiator(negotiator)
- intr = self.introspectable('locale negotiator', None,
+ intr = self.introspectable('locale negotiator', None, repr(negotiator),
'locale negotiator')
intr['negotiator'] = negotiator
self.action(ILocaleNegotiator, register, introspectables=(intr,))
@@ -87,7 +87,8 @@ class I18NConfiguratorMixin(object):
if not os.path.isdir(os.path.realpath(directory)):
raise ConfigurationError('"%s" is not a directory' %
directory)
- intr = self.introspectable('translation directory', directory, spec)
+ intr = self.introspectable('translation directories', directory,
+ spec, 'translation directory')
intr['directory'] = directory
introspectables.append(intr)
directories.append(directory)
diff --git a/pyramid/config/introspection.py b/pyramid/config/introspection.py
index 1d766fb5d..666728fc5 100644
--- a/pyramid/config/introspection.py
+++ b/pyramid/config/introspection.py
@@ -3,32 +3,18 @@ import operator
from zope.interface import implementer
from pyramid.interfaces import (
- IIntrospector,
- IIntrospectable
+ IIntrospectable,
+ IIntrospector
)
@implementer(IIntrospector)
class Introspector(object):
- action_info = None
def __init__(self):
self._refs = {}
self._categories = {}
self._counter = 0
- def add(self, category_name, discriminator):
- category = self._categories.setdefault(category_name, {})
- intr = category.get(discriminator)
- if intr is None:
- intr = Introspectable(category_name, discriminator)
- category[intr.discriminator] = intr
- category[intr.discriminator_hash] = intr
- intr.order = self._counter
- self._counter += 1
- return intr
-
- # for adding custom introspectables (instead of using .add)
-
- def add_intr(self, intr):
+ def add(self, intr):
category = self._categories.setdefault(intr.category_name, {})
category[intr.discriminator] = intr
category[intr.discriminator_hash] = intr
@@ -49,9 +35,12 @@ class Introspector(object):
return [{'introspectable':intr, 'related':self.related(intr)} for
intr in values]
+ def categories(self):
+ return sorted(self._categories.keys())
+
def categorized(self, sort_fn=None):
L = []
- for category_name in sorted(self._categories.keys()):
+ for category_name in self.categories():
L.append((category_name, self.get_category(category_name, sort_fn)))
return L
@@ -73,7 +62,6 @@ class Introspector(object):
category_name, discriminator = pair
intr = self._categories.get(category_name, {}).get(discriminator)
if intr is None:
- import pdb; pdb.set_trace()
raise KeyError((category_name, discriminator))
introspectables.append(intr)
return introspectables
@@ -101,16 +89,30 @@ class Introspector(object):
raise KeyError((category_name, discriminator))
return self._refs.get(intr, [])
+ def register(self, introspectable, action_info=''):
+ introspectable.action_info = action_info
+ self.add(introspectable)
+ for category_name, discriminator in introspectable.relations:
+ self.relate((
+ introspectable.category_name, introspectable.discriminator),
+ (category_name, discriminator))
+
+ for category_name, discriminator in introspectable.unrelations:
+ self.unrelate((
+ introspectable.category_name, introspectable.discriminator),
+ (category_name, discriminator))
+
@implementer(IIntrospectable)
class Introspectable(dict):
- order = 0 # mutated by .add/.add_intr
- action_info = ''
+ order = 0 # mutated by introspector.add/introspector.add_intr
+ action_info = '' # mutated by introspector.register
- def __init__(self, category_name, discriminator, title):
+ def __init__(self, category_name, discriminator, title, type_name):
self.category_name = category_name
self.discriminator = discriminator
self.title = title
+ self.type_name = type_name
self.relations = []
self.unrelations = []
@@ -120,25 +122,10 @@ class Introspectable(dict):
def unrelate(self, category_name, discriminator):
self.unrelations.append((category_name, discriminator))
- def __call__(self, introspector, action_info):
- self.action_info = action_info
- introspector.add_intr(self)
- for category_name, discriminator in self.relations:
- introspector.relate((self.category_name, self.discriminator),
- (category_name, discriminator))
-
- for category_name, discriminator in self.unrelations:
- introspector.unrelate((self.category_name, self.discriminator),
- (category_name, discriminator))
-
@property
def discriminator_hash(self):
return hash(self.discriminator)
- @property
- def related(self, introspector):
- return introspector.related(self)
-
def __hash__(self):
return hash((self.category_name,) + (self.discriminator,))
diff --git a/pyramid/config/routes.py b/pyramid/config/routes.py
index d4e8a94ab..46f69300d 100644
--- a/pyramid/config/routes.py
+++ b/pyramid/config/routes.py
@@ -365,7 +365,7 @@ class RoutesConfiguratorMixin(object):
mapper = self.get_routes_mapper()
- intr = self.introspectable('route', name, name)
+ intr = self.introspectable('routes', name, name, 'route')
intr['name'] = name
intr['pattern'] = pattern
intr['factory'] = factory
diff --git a/pyramid/config/views.py b/pyramid/config/views.py
index df0a64231..f4e7bb1db 100644
--- a/pyramid/config/views.py
+++ b/pyramid/config/views.py
@@ -931,7 +931,8 @@ class ViewsConfiguratorMixin(object):
xhr, accept, header, path_info, match_param]
discriminator.extend(sorted([hash(x) for x in custom_predicates]))
discriminator = tuple(discriminator)
- view_intr = self.introspectable('view', discriminator, 'view')
+ view_intr = self.introspectable('views', discriminator, repr(view),
+ 'view')
view_intr.update(
dict(name=name,
context=context,
@@ -1092,20 +1093,20 @@ class ViewsConfiguratorMixin(object):
IMultiView, name=name)
if route_name:
- view_intr.relate('route', route_name) # see add_route
+ view_intr.relate('routes', route_name) # see add_route
if renderer is not None and renderer.name and '.' in renderer.name:
- tmpl_intr = self.introspectable('template', discriminator,
- renderer.name)
- tmpl_intr.relate('view', discriminator)
+ tmpl_intr = self.introspectable('templates', discriminator,
+ renderer.name, 'template')
+ tmpl_intr.relate('views', discriminator)
tmpl_intr['name'] = renderer.name
tmpl_intr['type'] = renderer.type
tmpl_intr['renderer'] = renderer
introspectables.append(tmpl_intr)
if permission is not None:
- perm_intr = self.introspectable('permission', permission,
- permission)
+ perm_intr = self.introspectable('permissions', permission,
+ permission, 'permission')
perm_intr['value'] = permission
- perm_intr.relate('view', discriminator)
+ perm_intr.relate('views', discriminator)
introspectables.append(perm_intr)
self.action(discriminator, register, introspectables=introspectables)
diff --git a/pyramid/interfaces.py b/pyramid/interfaces.py
index fd66ebca5..81ff6df1e 100644
--- a/pyramid/interfaces.py
+++ b/pyramid/interfaces.py
@@ -858,16 +858,6 @@ class IRendererInfo(Interface):
class IIntrospector(Interface):
- def add(category_name, discriminator):
- """ If the introspectable of category_name with ``discriminator``
- already exists, return it; otherwise create an IIntrospectable object
- and return it"""
-
- def add_intr(intr):
- """ Add the IIntrospectable ``intr`` (use
- instead of :meth:`pyramid.interfaces.IIntrospector.add` when you have
- a custom IIntrospectable). """
-
def get(category_name, discriminator, default=None):
""" Get the IIntrospectable related to the category_name and the
discriminator (or discriminator hash) ``discriminator``. If it does
@@ -884,6 +874,10 @@ class IIntrospector(Interface):
value from it (ala the ``key`` function of Python's ``sorted``
callable)."""
+ def categories():
+ """ Return a sorted sequence of category names known by
+ this introspector """
+
def categorized(sort_fn=None):
""" Get a sequence of tuples in the form ``[(category_name,
[{'introspectable':IIntrospectable, 'related':[sequence of related
@@ -896,8 +890,57 @@ class IIntrospector(Interface):
def remove(category_name, discriminator):
""" Remove the IIntrospectable related to ``category_name`` and
- ``discriminator`` from the introspector. This method will not raise
- an error if the intrpsectable does not exist. """
+ ``discriminator`` from the introspector, and fix up any relations
+ that the introspectable participates in. This method will not raise
+ an error if an introspectable related to the category name and
+ discriminator does not exist."""
+
+ def related(category_name, discriminator):
+ """ Return a sequence of IIntrospectables related to the
+ IIntrospectable associated with (``category_name``,
+ ``discriminator``). Return the empty sequence if no relations for
+ exist."""
+
+ def register(introspectable, action_info=''):
+ """ Register an IIntrospectable with this introspector. This method
+ is invoked during action execution. Adds the introspectable and its
+ relations to the introspector. ``introspectable`` should be an
+ object implementing IIntrospectable. ``action_info`` should be a
+ string representing the call that registered this introspectable
+ (e.g. with line numbers, etc). Pseudocode for an implementation of
+ this method:
+
+ .. code-block:: python
+
+ def register(self, introspectable, action_info=''):
+ i = introspectable
+ i.action_info = action_info
+ self.add(introspectable)
+ for category_name, discriminator in i.relations:
+ self.relate((
+ i.category_name, i.discriminator),
+ (category_name, discriminator))
+
+ for category_name, discriminator in i.unrelations:
+ self.unrelate((
+ i.category_name, i.discriminator),
+ (category_name, discriminator))
+
+ The introspectable you wished to be related to or unrelated from must
+ have already been added via
+ :meth:`pyramid.interfaces.IIntrospector.add` (or by this method,
+ which implies an add) before this method is called; a :exc:`KeyError`
+ will result if this is not true.
+ """
+
+ def add(intr):
+ """ Add the IIntrospectable ``intr`` (use instead of
+ :meth:`pyramid.interfaces.IIntrospector.add` when you have a custom
+ IIntrospectable). Replaces any existing introspectable registered
+ using the same category/discriminator.
+
+ This method is not typically called directly, instead it's called
+ indirectly by :meth:`pyramid.interfaces.IIntrospector.register`"""
def relate(*pairs):
""" Given any number of of ``(category_name, discriminator)`` pairs
@@ -905,7 +948,11 @@ class IIntrospector(Interface):
to each other. The introspectable related to each pair must have
already been added via ``.add`` or ``.add_intr``; a :exc:`KeyError`
will result if this is not true. An error will not be raised if any
- pair has already been associated with another."""
+ pair has already been associated with another.
+
+ This method is not typically called directly, instead it's called
+ indirectly by :meth:`pyramid.interfaces.IIntrospector.register`
+ """
def unrelate(*pairs):
""" Given any number of of ``(category_name, discriminator)`` pairs
@@ -913,13 +960,11 @@ class IIntrospector(Interface):
from each other. The introspectable related to each pair must have
already been added via ``.add`` or ``.add_intr``; a :exc:`KeyError`
will result if this is not true. An error will not be raised if any
- pair is not already related to another."""
+ pair is not already related to another.
- def related(category_name, discriminator):
- """ Return a sequence of IIntrospectables related to the
- IIntrospectable associated with (``category_name``,
- ``discriminator``). Return the empty sequence if no relations for
- exist."""
+ This method is not typically called directly, instead it's called
+ indirectly by :meth:`pyramid.interfaces.IIntrospector.register`
+ """
class IIntrospectable(Interface):
@@ -928,35 +973,37 @@ class IIntrospectable(Interface):
must also implement all the methods of Python's
``collections.MutableMapping`` (the "dictionary interface")."""
- order = Attribute('integer order in which registered with introspector')
+ title = Attribute('Text title describing this introspectable')
+ type_name = Attribute('Text type name describing this introspectable')
+ order = Attribute('integer order in which registered with introspector '
+ '(managed by introspector, usually')
category_name = Attribute('introspection category name')
discriminator = Attribute('introspectable discriminator (within category) '
'(must be hashable)')
discriminator_hash = Attribute('an integer hash of the discriminator')
+ relations = Attribute('A sequence of ``(category_name, discriminator)`` '
+ 'pairs indicating the relations that this '
+ 'introspectable wants to establish when registered '
+ 'with the introspector')
+ unrelations = Attribute('A sequence of ``(category_name, discriminator)`` '
+ 'pairs indicating the relations that this '
+ 'introspectable wants to break when registered '
+ 'with the introspector')
+ action_info = Attribute('A string representing the caller that invoked '
+ 'the creation of this introspectable (usually '
+ 'managed by IIntrospector during registration)')
def relate(category_name, discriminator):
- """ Relate this IIntrospectable with another IIntrospectable (the one
- associated with the ``category_name`` and ``discriminator``). The
- introspectable you wish to relate to must have already been added via
- :meth:`pyramid.interfaces.IIntrospector.add` or
- :meth:`pyramid.interfaces.IIntrospector.add_intr`; a :exc:`KeyError`
- will result if this is not true.
+ """ Indicate an intent to relate this IIntrospectable with another
+ IIntrospectable (the one associated with the ``category_name`` and
+ ``discriminator``) during action execution.
"""
def unrelate(category_name, discriminator):
- """ Break any relationship between this IIntrospectable and another
- IIntrospectable (the one associated with the ``category_name`` and
- ``discriminator``). The introspectable you wish to unrelate from must
- have already been added via
- :meth:`pyramid.interfaces.IIntrospector.add` or
- :meth:`pyramid.interfaces.IIntrospector.add_intr`; a :exc:`KeyError`
- will result if this is not true. """
-
- def related(introspector):
- """ Return a sequence of related IIntrospectables """
-
- def __call__(introspector, action_info):
- """ Register this IIntrospectable with the introspector """
+ """ Indicate an intent to break the relationship between this
+ IIntrospectable with another IIntrospectable (the one associated with
+ the ``category_name`` and ``discriminator``) during action execution.
+ """
# configuration phases: a lower phase number means the actions associated
# with this phase will be executed earlier than those with later phase