refactor: Make the app argument for BuildEnvironment required

At present, some attributes of env object are considered as optional
because they have been initialized by None on the constructor.  But
they have always been fullfilled actually.

To be clear the type hints of the env object, this makes the `app`
argument for the BuildEnvironment class required.  It can ensure the
attributes of env object are not optional.
This commit is contained in:
Takeshi KOMIYA 2021-05-17 00:21:08 +09:00
parent b19dc365fe
commit 63fbfb02f1
5 changed files with 29 additions and 5 deletions

View File

@ -12,6 +12,8 @@ Incompatible changes
Deprecated Deprecated
---------- ----------
* The ``app`` argument of ``sphinx.environment.BuildEnvironment`` becomes
required
* ``sphinx.application.Sphinx.html_theme`` * ``sphinx.application.Sphinx.html_theme``
* ``sphinx.util.docstrings.extract_metadata()`` * ``sphinx.util.docstrings.extract_metadata()``

View File

@ -22,6 +22,11 @@ The following is a list of deprecated interfaces.
- (will be) Removed - (will be) Removed
- Alternatives - Alternatives
* - The optional argument ``app`` for ``sphinx.environment.BuildEnvironment``
- 4.1
- 6.0
- The required argument
* - ``sphinx.application.Sphinx.html_theme`` * - ``sphinx.application.Sphinx.html_theme``
- 4.1 - 4.1
- 6.0 - 6.0

View File

@ -300,8 +300,7 @@ class Sphinx:
def _init_env(self, freshenv: bool) -> None: def _init_env(self, freshenv: bool) -> None:
filename = path.join(self.doctreedir, ENV_PICKLE_FILENAME) filename = path.join(self.doctreedir, ENV_PICKLE_FILENAME)
if freshenv or not os.path.exists(filename): if freshenv or not os.path.exists(filename):
self.env = BuildEnvironment() self.env = BuildEnvironment(self)
self.env.setup(self)
self.env.find_files(self.config, self.builder) self.env.find_files(self.config, self.builder)
else: else:
try: try:

View File

@ -10,6 +10,7 @@
import os import os
import pickle import pickle
import warnings
from collections import defaultdict from collections import defaultdict
from copy import copy from copy import copy
from datetime import datetime from datetime import datetime
@ -22,6 +23,7 @@ from docutils.nodes import Node
from sphinx import addnodes from sphinx import addnodes
from sphinx.config import Config from sphinx.config import Config
from sphinx.deprecation import RemovedInSphinx60Warning
from sphinx.domains import Domain from sphinx.domains import Domain
from sphinx.environment.adapters.toctree import TocTree from sphinx.environment.adapters.toctree import TocTree
from sphinx.errors import BuildEnvironmentError, DocumentError, ExtensionError, SphinxError from sphinx.errors import BuildEnvironmentError, DocumentError, ExtensionError, SphinxError
@ -181,6 +183,9 @@ class BuildEnvironment:
# set up environment # set up environment
if app: if app:
self.setup(app) self.setup(app)
else:
warnings.warn("The 'app' argument for BuildEnvironment() becomes required now.",
RemovedInSphinx60Warning, stacklevel=2)
def __getstate__(self) -> Dict: def __getstate__(self) -> Dict:
"""Obtains serializable data for pickling.""" """Obtains serializable data for pickling."""

View File

@ -80,7 +80,9 @@ from sphinx.ext.autodoc.directive import DocumenterBridge, Options
from sphinx.ext.autodoc.importer import import_module from sphinx.ext.autodoc.importer import import_module
from sphinx.ext.autodoc.mock import mock from sphinx.ext.autodoc.mock import mock
from sphinx.locale import __ from sphinx.locale import __
from sphinx.project import Project
from sphinx.pycode import ModuleAnalyzer, PycodeError from sphinx.pycode import ModuleAnalyzer, PycodeError
from sphinx.registry import SphinxComponentRegistry
from sphinx.util import logging, rst from sphinx.util import logging, rst
from sphinx.util.docutils import (NullReporter, SphinxDirective, SphinxRole, new_document, from sphinx.util.docutils import (NullReporter, SphinxDirective, SphinxRole, new_document,
switch_source_input) switch_source_input)
@ -168,13 +170,24 @@ def autosummary_table_visit_html(self: HTMLTranslator, node: autosummary_table)
_app: Sphinx = None _app: Sphinx = None
class FakeApplication:
def __init__(self):
self.doctreedir = None
self.events = None
self.extensions = {}
self.srcdir = None
self.config = Config()
self.project = Project(None, None)
self.registry = SphinxComponentRegistry()
class FakeDirective(DocumenterBridge): class FakeDirective(DocumenterBridge):
def __init__(self) -> None: def __init__(self) -> None:
settings = Struct(tab_width=8) settings = Struct(tab_width=8)
document = Struct(settings=settings) document = Struct(settings=settings)
env = BuildEnvironment() app = FakeApplication()
env.config = Config() app.config.add('autodoc_class_signature', 'mixed', True, None)
env.config.add('autodoc_class_signature', 'mixed', True, None) env = BuildEnvironment(app) # type: ignore
state = Struct(document=document) state = Struct(document=document)
super().__init__(env, None, Options(), 0, state) super().__init__(env, None, Options(), 0, state)