From 57a9d679eb78e774c271bf68f6e805dc2b8186c4 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Wed, 30 Nov 2011 13:55:02 -0500 Subject: add tests for introspectable; add more interface docs and expose actioninfo --- docs/api/interfaces.rst | 2 + pyramid/interfaces.py | 27 +++++++----- pyramid/registry.py | 29 ++++++------- pyramid/tests/test_registry.py | 93 +++++++++++++++++++++++++++++++++++++++++- 4 files changed, 125 insertions(+), 26 deletions(-) diff --git a/docs/api/interfaces.rst b/docs/api/interfaces.rst index 64f2773d3..5b190b53b 100644 --- a/docs/api/interfaces.rst +++ b/docs/api/interfaces.rst @@ -74,3 +74,5 @@ Other Interfaces .. autointerface:: IIntrospector :members: + .. autointerface:: IActionInfo + :members: diff --git a/pyramid/interfaces.py b/pyramid/interfaces.py index 6bb0c6738..2576b4e35 100644 --- a/pyramid/interfaces.py +++ b/pyramid/interfaces.py @@ -897,11 +897,10 @@ class IIntrospector(Interface): an error if an introspectable related to the category name and discriminator does not exist.""" - def related(category_name, discriminator): + def related(intr): """ Return a sequence of IIntrospectables related to the - IIntrospectable associated with (``category_name``, - ``discriminator``). Return the empty sequence if no relations for - exist.""" + IIntrospectable ``intr``. Return the empty sequence if no relations + for exist.""" def add(intr): """ Add the IIntrospectable ``intr`` (use instead of @@ -968,14 +967,14 @@ class IIntrospectable(Interface): the ``category_name`` and ``discriminator``) during action execution. """ - def register(introspector, action_info=''): + def register(introspector, action_info): """ Register this IIntrospectable with an introspector. This method is invoked during action execution. Adds the introspectable and its - relations to the introspector. ``introspector`` should be an - object implementing IIntrospector. ``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: + relations to the introspector. ``introspector`` should be an object + implementing IIntrospector. ``action_info`` should be a object + implementing the interface :class:`pyramid.interfaces.IActionInfo` + representing the call that registered this introspectable. + Pseudocode for an implementation of this method: .. code-block:: python @@ -996,6 +995,14 @@ class IIntrospectable(Interface): return hash((self.category_name,) + (self.discriminator,)) """ +class IActionInfo(Interface): + filename = Attribute('filename as a string') + lineno = Attribute('line number in file as an integer') + function = Attribute('a string representing the function or method ' + 'that was executing') + linerepr = Attribute('a string representing the call site ' + 'which caused the action to be executed') + # configuration phases: a lower phase number means the actions associated # with this phase will be executed earlier than those with later phase # numbers. The default phase number is 0, FTR. diff --git a/pyramid/registry.py b/pyramid/registry.py index 813cde715..a6d70bfa8 100644 --- a/pyramid/registry.py +++ b/pyramid/registry.py @@ -170,7 +170,7 @@ class Introspector(object): class Introspectable(dict): order = 0 # mutated by introspector.add - action_info = None # mutated by introspectable.register + action_info = None # mutated by self.register def __init__(self, category_name, discriminator, title, type_name): self.category_name = category_name @@ -185,19 +185,6 @@ class Introspectable(dict): def unrelate(self, category_name, discriminator): self._relations.append((False, category_name, discriminator)) - def register(self, introspector, action_info): - self.action_info = action_info - introspector.add(self) - for relate, category_name, discriminator in self._relations: - if relate: - method = introspector.relate - else: - method = introspector.unrelate - method( - (self.category_name, self.discriminator), - (category_name, discriminator) - ) - @property def discriminator_hash(self): return hash(self.discriminator) @@ -215,4 +202,18 @@ class Introspectable(dict): __bool__ = __nonzero__ # py3 + def register(self, introspector, action_info): + self.action_info = action_info + introspector.add(self) + for relate, category_name, discriminator in self._relations: + if relate: + method = introspector.relate + else: + method = introspector.unrelate + method( + (self.category_name, self.discriminator), + (category_name, discriminator) + ) + + global_registry = Registry('global') diff --git a/pyramid/tests/test_registry.py b/pyramid/tests/test_registry.py index 5b2152d3a..3d68688d1 100644 --- a/pyramid/tests/test_registry.py +++ b/pyramid/tests/test_registry.py @@ -43,9 +43,19 @@ class TestRegistry(unittest.TestCase): self.assertEqual(registry._settings, 'foo') class TestIntrospector(unittest.TestCase): - def _makeOne(self): + def _getTargetClass(slf): from pyramid.registry import Introspector - return Introspector() + return Introspector + + def _makeOne(self): + return self._getTargetClass()() + + def test_conformance(self): + from zope.interface.verify import verifyClass + from zope.interface.verify import verifyObject + from pyramid.interfaces import IIntrospector + verifyClass(IIntrospector, self._getTargetClass()) + verifyObject(IIntrospector, self._makeOne()) def test_add(self): inst = self._makeOne() @@ -240,6 +250,85 @@ class TestIntrospector(unittest.TestCase): del inst._categories['category'] self.assertRaises(KeyError, inst.related, intr) +class TestIntrospectable(unittest.TestCase): + def _getTargetClass(slf): + from pyramid.registry import Introspectable + return Introspectable + + def _makeOne(self, *arg, **kw): + return self._getTargetClass()(*arg, **kw) + + def _makeOnePopulated(self): + return self._makeOne('category', 'discrim', 'title', 'type') + + def test_conformance(self): + from zope.interface.verify import verifyClass + from zope.interface.verify import verifyObject + from pyramid.interfaces import IIntrospectable + verifyClass(IIntrospectable, self._getTargetClass()) + verifyObject(IIntrospectable, self._makeOnePopulated()) + + def test_relate(self): + inst = self._makeOnePopulated() + inst.relate('a', 'b') + self.assertEqual(inst._relations, [(True, 'a', 'b')]) + + def test_unrelate(self): + inst = self._makeOnePopulated() + inst.unrelate('a', 'b') + self.assertEqual(inst._relations, [(False, 'a', 'b')]) + + def test_discriminator_hash(self): + inst = self._makeOnePopulated() + self.assertEqual(inst.discriminator_hash, hash(inst.discriminator)) + + def test___hash__(self): + inst = self._makeOnePopulated() + self.assertEqual(hash(inst), + hash((inst.category_name,) + (inst.discriminator,))) + + def test___repr__(self): + inst = self._makeOnePopulated() + self.assertEqual( + repr(inst), + "") + + def test___nonzero__(self): + inst = self._makeOnePopulated() + self.assertEqual(inst.__nonzero__(), True) + + def test___bool__(self): + inst = self._makeOnePopulated() + self.assertEqual(inst.__bool__(), True) + + def test_register(self): + introspector = DummyIntrospector() + action_info = object() + inst = self._makeOnePopulated() + inst._relations.append((True, 'category1', 'discrim1')) + inst._relations.append((False, 'category2', 'discrim2')) + inst.register(introspector, action_info) + self.assertEqual(inst.action_info, action_info) + self.assertEqual(introspector.intrs, [inst]) + self.assertEqual(introspector.relations, + [(('category', 'discrim'), ('category1', 'discrim1'))]) + self.assertEqual(introspector.unrelations, + [(('category', 'discrim'), ('category2', 'discrim2'))]) + +class DummyIntrospector(object): + def __init__(self): + self.intrs = [] + self.relations = [] + self.unrelations = [] + + def add(self, intr): + self.intrs.append(intr) + + def relate(self, *pairs): + self.relations.append(pairs) + + def unrelate(self, *pairs): + self.unrelations.append(pairs) class DummyModule: __path__ = "foo" -- cgit v1.2.3