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

Upgrading to 3.4.2 breaks autodoc for Flask projects when importing "flask.request" #8655

Closed
exhuma opened this issue Jan 5, 2021 · 1 comment

Comments

@exhuma
Copy link

exhuma commented Jan 5, 2021

Description

All our CI pipelines failed on "Flask" based projects this morning. Downgrading to Sphinx 3.4.1 works. The error was introduced in 3.4.2

The issue originates from the "request" import.

How to Reproduce

File Structure

.
├── doc
│   ├── conf.py
│   └── index.rst
├── myapp
│   ├── app.py
│   └── __init__.py
└── setup.py

File contents

# file: setup.py
from distutils.core import setup
setup(name="myapp", packages=["myapp"])

# file: myapp/app.py
from flask import Flask
from flask import request   # <------- This line triggers the exception!
app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello, World!'

# file: doc/conf.py
extensions = [
    'sphinx.ext.autodoc',
]

templates_path = ['_templates']
source_suffix = {'.rst': 'restructuredtext'}
master_doc = 'index'
project = 'hello'

.. file: doc/index.rst

.. automodule:: myapp.app
   :members:
   :undoc-members:
   :show-inheritance:

# requirements.txt
alabaster==0.7.12
Babel==2.9.0
certifi==2020.12.5
chardet==4.0.0
click==7.1.2
docutils==0.16
Flask==1.1.2
idna==2.10
imagesize==1.2.0
itsdangerous==1.1.0
Jinja2==2.11.2
MarkupSafe==1.1.1
myapp==0.0.0
packaging==20.8
pkg-resources==0.0.0
Pygments==2.7.3
pyparsing==2.4.7
pytz==2020.5
requests==2.25.1
snowballstemmer==2.0.0
Sphinx==3.4.2
sphinxcontrib-applehelp==1.0.2
sphinxcontrib-devhelp==1.0.2
sphinxcontrib-htmlhelp==1.0.3
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==1.0.3
sphinxcontrib-serializinghtml==1.1.4
urllib3==1.26.2
Werkzeug==1.0.1

Build Command

$ # Create the files and structure above, then:
$ python3 -m venv env
$ ./env/bin/pip install -r requirements.txt
$ (cd doc && ../env/bin/sphinx-build -b html -T . output)

Expected Behaviour

Successful build

Observed Behaviour

Traceback:

Running Sphinx v3.4.2
building [mo]: targets for 0 po files that are out of date
building [html]: targets for 1 source files that are out of date
updating environment: [new config] 1 added, 0 changed, 0 removed
reading sources... [100%] index
Traceback (most recent call last):
  File "/home/users/malbert/tmp/sphinx-bug/env/lib/python3.6/site-packages/sphinx/cmd/build.py", line 280, in build_main
    app.build(args.force_all, filenames)
  File "/home/users/malbert/tmp/sphinx-bug/env/lib/python3.6/site-packages/sphinx/application.py", line 352, in build
    self.builder.build_update()
  File "/home/users/malbert/tmp/sphinx-bug/env/lib/python3.6/site-packages/sphinx/builders/__init__.py", line 298, in build_update
    len(to_build))
  File "/home/users/malbert/tmp/sphinx-bug/env/lib/python3.6/site-packages/sphinx/builders/__init__.py", line 310, in build
    updated_docnames = set(self.read())
  File "/home/users/malbert/tmp/sphinx-bug/env/lib/python3.6/site-packages/sphinx/builders/__init__.py", line 417, in read
    self._read_serial(docnames)
  File "/home/users/malbert/tmp/sphinx-bug/env/lib/python3.6/site-packages/sphinx/builders/__init__.py", line 438, in _read_serial
    self.read_doc(docname)
  File "/home/users/malbert/tmp/sphinx-bug/env/lib/python3.6/site-packages/sphinx/builders/__init__.py", line 478, in read_doc
    doctree = read_doc(self.app, self.env, self.env.doc2path(docname))
  File "/home/users/malbert/tmp/sphinx-bug/env/lib/python3.6/site-packages/sphinx/io.py", line 221, in read_doc
    pub.publish()
  File "/home/users/malbert/tmp/sphinx-bug/env/lib/python3.6/site-packages/docutils/core.py", line 218, in publish
    self.settings)
  File "/home/users/malbert/tmp/sphinx-bug/env/lib/python3.6/site-packages/sphinx/io.py", line 126, in read
    self.parse()
  File "/home/users/malbert/tmp/sphinx-bug/env/lib/python3.6/site-packages/docutils/readers/__init__.py", line 77, in parse
    self.parser.parse(self.input, document)
  File "/home/users/malbert/tmp/sphinx-bug/env/lib/python3.6/site-packages/sphinx/parsers.py", line 104, in parse
    self.statemachine.run(inputlines, document, inliner=self.inliner)
  File "/home/users/malbert/tmp/sphinx-bug/env/lib/python3.6/site-packages/docutils/parsers/rst/states.py", line 171, in run
    input_source=document['source'])
  File "/home/users/malbert/tmp/sphinx-bug/env/lib/python3.6/site-packages/docutils/statemachine.py", line 242, in run
    context, state, transitions)
  File "/home/users/malbert/tmp/sphinx-bug/env/lib/python3.6/site-packages/docutils/statemachine.py", line 459, in check_line
    return method(match, context, next_state)
  File "/home/users/malbert/tmp/sphinx-bug/env/lib/python3.6/site-packages/docutils/parsers/rst/states.py", line 2342, in explicit_markup
    nodelist, blank_finish = self.explicit_construct(match)
  File "/home/users/malbert/tmp/sphinx-bug/env/lib/python3.6/site-packages/docutils/parsers/rst/states.py", line 2354, in explicit_construct
    return method(self, expmatch)
  File "/home/users/malbert/tmp/sphinx-bug/env/lib/python3.6/site-packages/docutils/parsers/rst/states.py", line 2097, in directive
    directive_class, match, type_name, option_presets)
  File "/home/users/malbert/tmp/sphinx-bug/env/lib/python3.6/site-packages/docutils/parsers/rst/states.py", line 2146, in run_directive
    result = directive_instance.run()
  File "/home/users/malbert/tmp/sphinx-bug/env/lib/python3.6/site-packages/sphinx/ext/autodoc/directive.py", line 146, in run
    documenter.generate(more_content=self.content)
  File "/home/users/malbert/tmp/sphinx-bug/env/lib/python3.6/site-packages/sphinx/ext/autodoc/__init__.py", line 959, in generate
    self.document_members(all_members)
  File "/home/users/malbert/tmp/sphinx-bug/env/lib/python3.6/site-packages/sphinx/ext/autodoc/__init__.py", line 821, in document_members
    for (mname, member, isattr) in self.filter_members(members, want_all):
  File "/home/users/malbert/tmp/sphinx-bug/env/lib/python3.6/site-packages/sphinx/ext/autodoc/__init__.py", line 734, in filter_members
    if ismock(member):
  File "/home/users/malbert/tmp/sphinx-bug/env/lib/python3.6/site-packages/sphinx/ext/autodoc/mock.py", line 156, in ismock
    if not hasattr(subject, '__sphinx_mock__'):
  File "/home/users/malbert/tmp/sphinx-bug/env/lib/python3.6/site-packages/werkzeug/local.py", line 347, in __getattr__
    return getattr(self._get_current_object(), name)
  File "/home/users/malbert/tmp/sphinx-bug/env/lib/python3.6/site-packages/werkzeug/local.py", line 306, in _get_current_object
    return self.__local()
  File "/home/users/malbert/tmp/sphinx-bug/env/lib/python3.6/site-packages/flask/globals.py", line 38, in _lookup_req_object
    raise RuntimeError(_request_ctx_err_msg)
RuntimeError: Working outside of request context.

This typically means that you attempted to use functionality that needed
an active HTTP request.  Consult the documentation on testing for
information about how to avoid this problem.

Exception occurred:
  File "/home/users/malbert/tmp/sphinx-bug/env/lib/python3.6/site-packages/flask/globals.py", line 38, in _lookup_req_object
    raise RuntimeError(_request_ctx_err_msg)
RuntimeError: Working outside of request context.

This typically means that you attempted to use functionality that needed
an active HTTP request.  Consult the documentation on testing for
information about how to avoid this problem.
The full traceback has been saved in /tmp/sphinx-err-jzo0zc61.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!

Environment info

  • OS: Ubuntu 18.04
  • Python version: 3.6.9
  • Sphinx version: 3.4.2
  • Sphinx extensions: autodoc
@tk0miya
Copy link
Member

tk0miya commented Jan 5, 2021

Sorry for the inconvenience. I don't know hasattr causes an error... Okay, I'll fix it ASAP.

tk0miya added a commit to tk0miya/sphinx that referenced this issue Jan 5, 2021
… on hasattr()

autodoc crashes when the target object raises an exception on
`hasattr()`.  The `hasattr()` function internally calls the
`obj.__getattr__()` or `obj.__getattribute__()` of the target object.
Hence the reaction can be changed on the target object.

Is starts to use `safe_getattr()` to check the object is mocked or not
and to prevent the unexpected errors.
tk0miya added a commit to tk0miya/sphinx that referenced this issue Jan 5, 2021
… on hasattr()

autodoc crashes when the target object raises an exception on
`hasattr()`.  The `hasattr()` function internally calls the
`obj.__getattr__()` or `obj.__getattribute__()` of the target object.
Hence the reaction can be changed on the target object.

This starts to use `safe_getattr()` to check the object is mocked or not
and to prevent the unexpected errors.
tk0miya added a commit to tk0miya/sphinx that referenced this issue Jan 5, 2021
… on hasattr()

autodoc crashes when the target object raises an exception on
`hasattr()`.  The `hasattr()` function internally calls the
`obj.__getattr__()` or `obj.__getattribute__()` of the target object.
Hence the reaction can be changed on the target object.

This starts to use `safe_getattr()` to check the object is mocked or not
and to prevent an unexpected error.
u8sand added a commit to MaayanLab/appyter that referenced this issue Jan 5, 2021
tk0miya added a commit that referenced this issue Jan 6, 2021
Fix #8655: autodoc: Crashes when object raises an exception on hasattr()
@tk0miya tk0miya closed this as completed Jan 6, 2021
GraemeWatt added a commit to HEPData/hepdata that referenced this issue Jan 6, 2021
* The Read the Docs build with Sphinx v3.4.2 fails.
* See sphinx-doc/sphinx#8655 (already closed).
openstack-mirroring pushed a commit to openstack/requirements that referenced this issue Jan 7, 2021
Using sphinx version 3.4.2 with Flask and documentation builds results
in an error:

  Exception occurred:
    File "/opt/stack/keystone/.tox/docs/lib/python3.8/site-packages/flask/globals.py", line 38, in _lookup_req_object
      raise RuntimeError(_request_ctx_err_msg)
  RuntimeError: Working outside of request context.

This issue has occured a few times with sphinx in the past and has been
reported upstream [0][1].

This commit blacklists sphinx 3.4.2 until we get a newer release with a fix.

[0] sphinx-doc/sphinx#8655
[1] sphinx-doc/sphinx#2796

Partial-Bug: 1910419

Change-Id: Ie80e45571efafe73a553ddd89c5be90fe97bea4d
openstack-mirroring pushed a commit to openstack/openstack that referenced this issue Jan 7, 2021
* Update requirements from branch 'master'
  to 8b7a53cac1cc1fdcd4ab94aad9a7b7d24362fdc3
  - Blacklist sphinx 3.4.2 because of Flask regressions
    
    Using sphinx version 3.4.2 with Flask and documentation builds results
    in an error:
    
      Exception occurred:
        File "/opt/stack/keystone/.tox/docs/lib/python3.8/site-packages/flask/globals.py", line 38, in _lookup_req_object
          raise RuntimeError(_request_ctx_err_msg)
      RuntimeError: Working outside of request context.
    
    This issue has occured a few times with sphinx in the past and has been
    reported upstream [0][1].
    
    This commit blacklists sphinx 3.4.2 until we get a newer release with a fix.
    
    [0] sphinx-doc/sphinx#8655
    [1] sphinx-doc/sphinx#2796
    
    Partial-Bug: 1910419
    
    Change-Id: Ie80e45571efafe73a553ddd89c5be90fe97bea4d
@tk0miya tk0miya mentioned this issue Jan 24, 2021
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jul 15, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants