def register(self, kind, handler): """Register a handler for a given type, class, interface, or abstract base class. View registration should happen within the `start` callback of an extension. For example, to register the previous `json` view example: class JSONExtension: def start(self, context): context.view.register(tuple, json) The approach of explicitly referencing a view handler isn't very easy to override without also replacing the extension originally adding it, however there is another approach. Using named handlers registered as discrete plugins (via the `entry_point` argument in `setup.py`) allows the extension to easily ask "what's my handler?" class JSONExtension: def start(self, context): context.view.register( tuple, context.view.json ) Otherwise unknown attributes of the view registry will attempt to look up a handler plugin by that name. """ if __debug__: # In production this logging is completely skipped, regardless of logging level. if py3 and not pypy: # Where possible, we shorten things to just the cannonical name. log.debug("Registering view handler.", extra=dict(type=name(kind), handler=name(handler))) else: # Canonical name lookup is not entirely reliable on some combinations. log.debug("Registering view handler.", extra=dict(type=repr(kind), handler=repr(handler))) # Add the handler to the pool of candidates. This adds to a list instead of replacing the "dictionary item". self._map.add(kind, handler) return handler
def safe_name(thing): """Attempt to resolve the canonical name for an object, falling back on the `repr()` if unable to do so.""" try: return name(thing) except: return repr(thing)
def test__resolve__of_a_module_level_decorated_decorated_method(self): assert name(helper.Example.decorated_deep) == 'test.helper:Example.decorated_deep'
def test__resolve__of_a_nested_class_shallow(self): assert name(helper.Example.Pandora) == 'test.helper:Example.Pandora'
def test__resolve__of_a_module_level_decorated_decorated_function(self): assert name(helper.decorated_deep) == 'test.helper:decorated_deep'
def test__resolve__of_a_module_level_instance_staticmethod(self): assert name(helper.instance.staticmethod) == 'test.helper:Example.staticmethod'
def test__resolve__of_a_nested_class_deep_method(self): assert name(helper.Example.Pandora.Box.nested) == 'test.helper:Example.Pandora.Box.nested'
def test__resolve__of_a_module_level_function(self): assert name(helper.bare) == 'test.helper:bare'
def test__resolve__of_a_module_level_class_method(self): assert name(helper.Example.instance) == 'test.helper:Example.instance'
def test__resolve__of_a_module_level_class(self): assert name(helper.Example) == 'test.helper:Example'
def test__resolve__of_a_closure(self): def closure(): pass assert name(closure) == 'test.test_canonical:TestResolver.test__resolve__of_a_closure.<locals>.closure'