Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Protect sphinx.ext.autodoc.get_sourcename against misbehaving __getattr__ #9644

Merged
merged 1 commit into from
Sep 17, 2021
Merged

Protect sphinx.ext.autodoc.get_sourcename against misbehaving __getattr__ #9644

merged 1 commit into from
Sep 17, 2021

Conversation

xmo-odoo
Copy link
Contributor

Feature or Bugfix

  • Bugfix (minor)

Problem

When a __getattr__ misbehaves on a top-level object, get_sourcename will fail taking down the entire build:

reading sources... [ 50%] index
reading sources... [100%] thing

Traceback (most recent call last):
  File "sphinx/cmd/build.py", line 280, in build_main
    app.build(args.force_all, filenames)
  File "sphinx/application.py", line 343, in build
    self.builder.build_update()
  File "sphinx/builders/__init__.py", line 295, in build_update
    len(to_build))
  File "sphinx/builders/__init__.py", line 307, in build
    updated_docnames = set(self.read())
  File "sphinx/builders/__init__.py", line 414, in read
    self._read_serial(docnames)
  File "sphinx/builders/__init__.py", line 435, in _read_serial
    self.read_doc(docname)
  File "sphinx/builders/__init__.py", line 475, in read_doc
    doctree = read_doc(self.app, self.env, self.env.doc2path(docname))
  File "sphinx/io.py", line 189, in read_doc
    pub.publish()
  File "docutils/core.py", line 218, in publish
    self.settings)
  File "sphinx/io.py", line 109, in read
    self.parse()
  File "docutils/readers/__init__.py", line 78, in parse
    self.parser.parse(self.input, document)
  File "sphinx/parsers.py", line 101, in parse
    self.statemachine.run(inputlines, document, inliner=self.inliner)
  File "docutils/parsers/rst/states.py", line 171, in run
    input_source=document['source'])
  File "docutils/statemachine.py", line 240, in run
    context, state, transitions)
  File "docutils/statemachine.py", line 451, in check_line
    return method(match, context, next_state)
  File "docutils/parsers/rst/states.py", line 2769, in underline
    self.section(title, source, style, lineno - 1, messages)
  File "docutils/parsers/rst/states.py", line 327, in section
    self.new_subsection(title, lineno, messages)
  File "docutils/parsers/rst/states.py", line 395, in new_subsection
    node=section_node, match_titles=True)
  File "docutils/parsers/rst/states.py", line 282, in nested_parse
    node=node, match_titles=match_titles)
  File "docutils/parsers/rst/states.py", line 196, in run
    results = StateMachineWS.run(self, input_lines, input_offset)
  File "docutils/statemachine.py", line 240, in run
    context, state, transitions)
  File "docutils/statemachine.py", line 451, in check_line
    return method(match, context, next_state)
  File "docutils/parsers/rst/states.py", line 2342, in explicit_markup
    nodelist, blank_finish = self.explicit_construct(match)
  File "docutils/parsers/rst/states.py", line 2354, in explicit_construct
    return method(self, expmatch)
  File "docutils/parsers/rst/states.py", line 2097, in directive
    directive_class, match, type_name, option_presets)
  File "docutils/parsers/rst/states.py", line 2146, in run_directive
    result = directive_instance.run()
  File "sphinx/ext/autodoc/directive.py", line 162, in run
    documenter.generate(more_content=self.content)
  File "sphinx/ext/autodoc/__init__.py", line 983, in generate
    self.document_members(all_members)
  File "sphinx/ext/autodoc/__init__.py", line 862, in document_members
    check_module=members_check_module and not isattr)
  File "sphinx/ext/autodoc/__init__.py", line 957, in generate
    sourcename = self.get_sourcename()
  File "sphinx/ext/autodoc/__init__.py", line 589, in get_sourcename
    getattr(self.object, '__qualname__', None)):
  File "werkzeug/local.py", line 348, in __getattr__
    return getattr(self._get_current_object(), name)
  File "werkzeug/local.py", line 307, in _get_current_object
    return self.__local()
  File "werkzeug/local.py", line 137, in _lookup
    raise RuntimeError("object unbound")
RuntimeError: object unbound

Exception occurred:
  File "werkzeug/local.py", line 137, in _lookup
    raise RuntimeError("object unbound")
RuntimeError: object unbound
The full traceback has been saved in /tmp/sphinx-err-6fv3b0or.log, if you want to report the issue to the developers.
Please also report this if it was a user error, so that a better error message can be provided next time.
A bug report can be filed in the tracker at <https://github.com/sphinx-doc/sphinx/issues>. Thanks!
make: *** [Makefile:20: html] Error 2

Here the failure is specifically related to sphinx-autodoc (correctly) trying to document a LocalProxy, which basically do not work when unbound.

Python file:

# src/thing.py
import werkzeug.local

_locals_stack = werkzeug.local.LocalStack()
local = _locals_stack()
"""
    A global proxy that always redirect to the current local object.
"""

Sphinx project generated via apidoc:

$ sphinx-apidoc --ext-autodoc -F -a -o doc src

Generated sphinx file:

-- doc/thing.rst
thing module
============

.. automodule:: thing
   :members:
   :undoc-members:
   :show-inheritance:

Detail

Sphinx already has a safe_getattr, which can handle every possible error. This results in a build warning and the item being undocumented rather than the entire build failing:

reading sources... [100%] thing                                                                                                                                                                                    
WARNING: error while formatting signature for thing.local: Handler <function record_typehints at 0x7f28ba54ff28> for event 'autodoc-process-signature' threw an exception (exception: object unbound)
looking for now-outdated files... none found

Copy link
Member

@tk0miya tk0miya left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM :-)

@tk0miya tk0miya merged commit 62fd91b into sphinx-doc:4.x Sep 17, 2021
tk0miya added a commit that referenced this pull request Sep 17, 2021
@xmo-odoo xmo-odoo deleted the fix-sourcename-broken-getattr branch September 20, 2021 05:47
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Oct 21, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants