Description
Describe the bug
We ran into a problem when type-checking a Sphinx extension we're working on. mypy reports Cannot determine type of 'config'
for app.config
, where app
is the sphinx.application.Sphinx
object passed to the extension.
To Reproduce
Run mypy on the following program:
from typing import Any, Dict
from sphinx.application import Sphinx
def setup(app: Sphinx) -> Dict[str, Any]:
reveal_type(app.config)
return {}
Example output:
$ mypy repro.py
repro.py:5: error: Cannot determine type of 'config'
repro.py:5: note: Revealed type is 'Any'
Found 1 error in 1 file (checked 1 source file)
Expected behavior
The type of app.config
is sphinx.config.Config
and I'd expect mypy to be able to figure this out automatically.
The problem seems to be caused by this fragment in Sphinx.__init__()
:
if self.confdir is None:
self.config = Config({}, confoverrides or {})
else:
self.config = Config.read(self.confdir, confoverrides or {}, self.tags)
The self.confdir
attribute is assigned from the confdir
argument, which is annotated as having type str
. Therefore mypy concludes that self.confdir is None
can never be true and the first assignment to self.config
is unreachable code. But as the first assignment usually determines the type of an attribute, mypy is now confused about the type of self.config
.
You could argue that this is a mypy bug and I will be reporting this issue with mypy as well, if it's not already in their tracker. However, there is still an inconsistency in how Sphinx.__init__()
handles confdir
and how confdir
is annotated, so there is an opportunity to improve Sphinx by either removing the code that handles confdir is None
or changing the argument annotation to confdir: Optional[str]
.
Your project
Original PR in which the problem was encountered.
Environment info
- OS: Linux (openSUSE Tumbleweed)
- Python version: 3.8
- Sphinx version: 3.3.0
- Sphinx extensions: n/a
- Extra tools: mypy 0.790