From 4b51ed4aa9170265d682d120bb900e9fd94a21bc Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 18 Jun 2017 19:21:46 +0900 Subject: [PATCH] Deprecate AutoDirective._special_attrgetters --- CHANGES | 4 +++- sphinx/application.py | 9 ++++----- sphinx/ext/autodoc/__init__.py | 31 ++++++++++++++++++++----------- sphinx/registry.py | 5 +++++ 4 files changed, 32 insertions(+), 17 deletions(-) diff --git a/CHANGES b/CHANGES index c0934c396..ca0f3220a 100644 --- a/CHANGES +++ b/CHANGES @@ -22,7 +22,9 @@ Deprecated * ``format_annotation()`` and ``formatargspec()`` is deprecated. Please use ``sphinx.util.inspect.Signature`` instead. * ``sphinx.ext.autodoc.add_documenter()`` and ``AutoDirective._register`` is now - deprecated. Please use ``app.add_autodocumenter()`` + deprecated. Please use ``app.add_autodocumenter()`` instead. +* ``AutoDirective._special_attrgetters`` is now deprecated. Please use + ``app.add_autodoc_attrgetter()`` instead. Features added -------------- diff --git a/sphinx/application.py b/sphinx/application.py index 3bfea910f..07b8539a9 100644 --- a/sphinx/application.py +++ b/sphinx/application.py @@ -646,11 +646,10 @@ class Sphinx(object): self.add_directive('auto' + cls.objtype, AutoDirective) self.registry.add_documenter(cls.objtype, cls) - def add_autodoc_attrgetter(self, type, getter): - # type: (Any, Callable) -> None - logger.debug('[app] adding autodoc attrgetter: %r', (type, getter)) - from sphinx.ext import autodoc - autodoc.AutoDirective._special_attrgetters[type] = getter + def add_autodoc_attrgetter(self, typ, getter): + # type: (Type, Callable[[Any, unicode, Any], Any]) -> None + logger.debug('[app] adding autodoc attrgetter: %r', (typ, getter)) + self.registy.add_autodoc_attrgetter(typ, getter) def add_search_language(self, cls): # type: (Any) -> None diff --git a/sphinx/ext/autodoc/__init__.py b/sphinx/ext/autodoc/__init__.py index a6afe4f4c..14572e283 100644 --- a/sphinx/ext/autodoc/__init__.py +++ b/sphinx/ext/autodoc/__init__.py @@ -285,14 +285,10 @@ class Documenter(object): option_spec = {'noindex': bool_option} # type: Dict[unicode, Callable] - @staticmethod - def get_attr(obj, name, *defargs): + def get_attr(self, obj, name, *defargs): # type: (Any, unicode, Any) -> Any """getattr() override for types such as Zope interfaces.""" - for typ, func in iteritems(AutoDirective._special_attrgetters): - if isinstance(obj, typ): - return func(obj, name, *defargs) - return safe_getattr(obj, name, *defargs) + return autodoc_attrgetter(self.env.app, obj, name, *defargs) @classmethod def can_document_member(cls, member, membername, isattr, parent): @@ -1496,10 +1492,6 @@ class AutoDirective(Directive): The AutoDirective class is used for all autodoc directives. It dispatches most of the work to one of the Documenters. - The *_special_attrgetters* attribute is used to customize ``getattr()`` - calls that the Documenters make; its entries are of the form ``type: - getattr_function``. - Note: When importing an object, all items along the import chain are accessed using the descendant's *_special_attrgetters*, thus this dictionary should include all necessary functions for accessing @@ -1512,7 +1504,10 @@ class AutoDirective(Directive): ) # type: Dict[unicode, Type[Documenter]] # a registry of type -> getattr function - _special_attrgetters = {} # type: Dict[Type, Callable] + _special_attrgetters = DeprecatedDict( + 'AutoDirective._special_attrgetters has been deprecated. ' + 'Please use app.add_autodoc_attrgetter() instead.' + ) # type: Dict[Type, Callable] # flags that can be given in autodoc_default_flags _default_flags = set([ @@ -1628,6 +1623,20 @@ def get_documenters(app): return classes +def autodoc_attrgetter(app, obj, name, *defargs): + # type: (Sphinx, Any, unicode, Any) -> Any + """Alternative getattr() for types""" + candidates = dict(AutoDirective._special_attrgetters) + if app: + candidates.update(app.registry.autodoc_attrgettrs) + + for typ, func in iteritems(candidates): + if isinstance(obj, typ): + return func(obj, name, *defargs) + + return safe_getattr(obj, name, *defargs) + + def setup(app): # type: (Sphinx) -> Dict[unicode, Any] app.add_autodocumenter(ModuleDocumenter) diff --git a/sphinx/registry.py b/sphinx/registry.py index 38fe9caf3..e48c12f96 100644 --- a/sphinx/registry.py +++ b/sphinx/registry.py @@ -52,6 +52,7 @@ EXTENSION_BLACKLIST = { class SphinxComponentRegistry(object): def __init__(self): + self.autodoc_attrgettrs = {} # type: Dict[Type, Callable[[Any, unicode, Any], Any]] self.builders = {} # type: Dict[unicode, Type[Builder]] self.documenters = {} # type: Dict[unicode, Type[Documenter]] self.domains = {} # type: Dict[unicode, Type[Domain]] @@ -290,6 +291,10 @@ class SphinxComponentRegistry(object): # type: (unicode, Type[Documenter]) -> None self.documenters[objtype] = documenter + def add_autodoc_attrgetter(self, typ, attrgetter): + # type: (Type, Callable[[Any, unicode, Any], Any]) -> None + self.autodoc_attrgettrs[typ] = attrgetter + def load_extension(self, app, extname): # type: (Sphinx, unicode) -> None """Load a Sphinx extension."""