mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Fix B006 (Do not use mutable data structures for argument defaults)
This commit is contained in:
parent
4791b544dc
commit
1dcc112608
@ -163,7 +163,6 @@ ignore = [
|
||||
"ARG003", # unused class method argument
|
||||
"ARG005", # unused lambda argument
|
||||
# flake8-bugbear
|
||||
"B006", # do not use mutable data structures for argument default
|
||||
"B023", # function definition does not bind loop variable
|
||||
"B026", # keyword argument ... must come after starred arguments
|
||||
"B028", # no explicit `stacklevel` keyword argument found
|
||||
|
@ -9,6 +9,7 @@ import os
|
||||
import pickle
|
||||
import sys
|
||||
from collections import deque
|
||||
from collections.abc import Sequence # NoQA: TCH003
|
||||
from io import StringIO
|
||||
from os import path
|
||||
from pathlib import Path
|
||||
@ -736,7 +737,7 @@ class Sphinx:
|
||||
logger.warning(__('role %r is already registered, it will be overridden'),
|
||||
name, type='app', subtype='add_generic_role')
|
||||
role = roles.GenericRole(name, nodeclass)
|
||||
docutils.register_role(name, role)
|
||||
docutils.register_role(name, role) # type: ignore[arg-type]
|
||||
|
||||
def add_domain(self, domain: type[Domain], override: bool = False) -> None:
|
||||
"""Register a domain.
|
||||
@ -813,7 +814,8 @@ class Sphinx:
|
||||
def add_object_type(self, directivename: str, rolename: str, indextemplate: str = '',
|
||||
parse_node: Callable | None = None,
|
||||
ref_nodeclass: type[TextElement] | None = None,
|
||||
objname: str = '', doc_field_types: list = [], override: bool = False,
|
||||
objname: str = '', doc_field_types: Sequence = (),
|
||||
override: bool = False,
|
||||
) -> None:
|
||||
"""Register a new object type.
|
||||
|
||||
|
@ -52,7 +52,7 @@ from sphinx.writers.html import HTMLWriter
|
||||
from sphinx.writers.html5 import HTML5Translator
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from collections.abc import Iterable, Iterator
|
||||
from collections.abc import Iterable, Iterator, Sequence
|
||||
|
||||
#: the filename for the inventory of objects
|
||||
INVENTORY_FILENAME = 'objects.inv'
|
||||
@ -122,7 +122,7 @@ class BuildInfo:
|
||||
self,
|
||||
config: Config | None = None,
|
||||
tags: Tags | None = None,
|
||||
config_categories: list[str] = [],
|
||||
config_categories: Sequence[str] = (),
|
||||
) -> None:
|
||||
self.config_hash = ''
|
||||
self.tags_hash = ''
|
||||
|
@ -155,8 +155,10 @@ class Config:
|
||||
'option_emphasise_placeholders': (False, 'env', []),
|
||||
}
|
||||
|
||||
def __init__(self, config: dict[str, Any] = {}, overrides: dict[str, Any] = {}) -> None:
|
||||
self.overrides = dict(overrides)
|
||||
def __init__(self, config: dict[str, Any] | None = None,
|
||||
overrides: dict[str, Any] | None = None) -> None:
|
||||
config = config or {}
|
||||
self.overrides = dict(overrides) if overrides is not None else {}
|
||||
self.values = Config.config_values.copy()
|
||||
self._raw_config = config
|
||||
self.setup: Callable | None = config.get('setup', None)
|
||||
@ -310,7 +312,7 @@ class Config:
|
||||
raise ExtensionError(__('Config value %r already present') % name)
|
||||
self.values[name] = (default, rebuild, types)
|
||||
|
||||
def filter(self, rebuild: str | list[str]) -> Iterator[ConfigValue]:
|
||||
def filter(self, rebuild: str | Sequence[str]) -> Iterator[ConfigValue]:
|
||||
if isinstance(rebuild, str):
|
||||
rebuild = [rebuild]
|
||||
return (value for value in self if value.rebuild in rebuild)
|
||||
|
@ -319,7 +319,7 @@ class DefaultRole(SphinxDirective):
|
||||
role, messages = roles.role(role_name, self.state_machine.language,
|
||||
self.lineno, self.state.reporter)
|
||||
if role: # type: ignore[truthy-function]
|
||||
docutils.register_role('', role)
|
||||
docutils.register_role('', role) # type: ignore[arg-type]
|
||||
self.env.temp_data['default_role'] = role_name
|
||||
else:
|
||||
literal_block = nodes.literal_block(self.block_text, self.block_text)
|
||||
|
@ -21,7 +21,7 @@ from sphinx.roles import XRefRole
|
||||
from sphinx.util.typing import RoleFunction
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from collections.abc import Iterable
|
||||
from collections.abc import Iterable, Sequence
|
||||
|
||||
from docutils.parsers.rst import Directive
|
||||
|
||||
@ -264,10 +264,11 @@ class Domain:
|
||||
fullname = f'{self.name}:{name}'
|
||||
|
||||
def role_adapter(typ: str, rawtext: str, text: str, lineno: int,
|
||||
inliner: Inliner, options: dict = {}, content: list[str] = [],
|
||||
inliner: Inliner, options: dict | None = None,
|
||||
content: Sequence[str] = (),
|
||||
) -> tuple[list[Node], list[system_message]]:
|
||||
return self.roles[name](fullname, rawtext, text, lineno,
|
||||
inliner, options, content)
|
||||
inliner, options or {}, content)
|
||||
self._role_cache[name] = role_adapter
|
||||
return role_adapter
|
||||
|
||||
|
@ -628,7 +628,7 @@ def get_import_prefixes_from_env(env: BuildEnvironment) -> list[str | None]:
|
||||
|
||||
|
||||
def import_by_name(
|
||||
name: str, prefixes: list[str | None] = [None],
|
||||
name: str, prefixes: Sequence[str | None] = (None,),
|
||||
) -> tuple[str, Any, Any, str]:
|
||||
"""Import a Python object that has the given *name*, under one of the
|
||||
*prefixes*. The first name that succeeds is used.
|
||||
@ -700,7 +700,7 @@ def _import_by_name(name: str, grouped_exception: bool = True) -> tuple[Any, Any
|
||||
raise ImportError(*exc.args) from exc
|
||||
|
||||
|
||||
def import_ivar_by_name(name: str, prefixes: list[str | None] = [None],
|
||||
def import_ivar_by_name(name: str, prefixes: Sequence[str | None] = (None,),
|
||||
grouped_exception: bool = True) -> tuple[str, Any, Any, str]:
|
||||
"""Import an instance variable that has the given *name*, under one of the
|
||||
*prefixes*. The first name that succeeds is used.
|
||||
|
@ -20,7 +20,7 @@ Both, the url string and the caption string must escape ``%`` as ``%%``.
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
from typing import Any
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from docutils import nodes, utils
|
||||
from docutils.nodes import Node, system_message
|
||||
@ -34,6 +34,9 @@ from sphinx.util import logging, rst
|
||||
from sphinx.util.nodes import split_explicit_title
|
||||
from sphinx.util.typing import RoleFunction
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from collections.abc import Sequence
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@ -91,7 +94,7 @@ def make_link_role(name: str, base_url: str, caption: str) -> RoleFunction:
|
||||
# Remark: It is an implementation detail that we use Pythons %-formatting.
|
||||
# So far we only expose ``%s`` and require quoting of ``%`` using ``%%``.
|
||||
def role(typ: str, rawtext: str, text: str, lineno: int,
|
||||
inliner: Inliner, options: dict = {}, content: list[str] = [],
|
||||
inliner: Inliner, options: dict | None = None, content: Sequence[str] = (),
|
||||
) -> tuple[list[Node], list[system_message]]:
|
||||
text = utils.unescape(text)
|
||||
has_explicit_title, title, part = split_explicit_title(text)
|
||||
|
@ -34,7 +34,7 @@ import builtins
|
||||
import hashlib
|
||||
import inspect
|
||||
import re
|
||||
from collections.abc import Iterable
|
||||
from collections.abc import Iterable, Sequence
|
||||
from importlib import import_module
|
||||
from typing import Any, cast
|
||||
|
||||
@ -140,7 +140,7 @@ class InheritanceGraph:
|
||||
"""
|
||||
def __init__(self, class_names: list[str], currmodule: str, show_builtins: bool = False,
|
||||
private_bases: bool = False, parts: int = 0,
|
||||
aliases: dict[str, str] | None = None, top_classes: list[Any] = [],
|
||||
aliases: dict[str, str] | None = None, top_classes: Sequence[Any] = (),
|
||||
) -> None:
|
||||
"""*class_names* is a list of child classes to show bases from.
|
||||
|
||||
@ -163,7 +163,7 @@ class InheritanceGraph:
|
||||
return classes
|
||||
|
||||
def _class_info(self, classes: list[Any], show_builtins: bool, private_bases: bool,
|
||||
parts: int, aliases: dict[str, str] | None, top_classes: list[Any],
|
||||
parts: int, aliases: dict[str, str] | None, top_classes: Sequence[Any],
|
||||
) -> list[tuple[str, str, list[str], str]]:
|
||||
"""Return name and bases for all classes that are ancestors of
|
||||
*classes*.
|
||||
@ -273,9 +273,11 @@ class InheritanceGraph:
|
||||
def _format_graph_attrs(self, attrs: dict[str, Any]) -> str:
|
||||
return ''.join(['%s=%s;\n' % x for x in sorted(attrs.items())])
|
||||
|
||||
def generate_dot(self, name: str, urls: dict[str, str] = {},
|
||||
def generate_dot(self, name: str, urls: dict[str, str] | None = None,
|
||||
env: BuildEnvironment | None = None,
|
||||
graph_attrs: dict = {}, node_attrs: dict = {}, edge_attrs: dict = {},
|
||||
graph_attrs: dict | None = None,
|
||||
node_attrs: dict | None = None,
|
||||
edge_attrs: dict | None = None,
|
||||
) -> str:
|
||||
"""Generate a graphviz dot graph from the classes that were passed in
|
||||
to __init__.
|
||||
@ -287,12 +289,17 @@ class InheritanceGraph:
|
||||
*graph_attrs*, *node_attrs*, *edge_attrs* are dictionaries containing
|
||||
key/value pairs to pass on as graphviz properties.
|
||||
"""
|
||||
if urls is None:
|
||||
urls = {}
|
||||
g_attrs = self.default_graph_attrs.copy()
|
||||
n_attrs = self.default_node_attrs.copy()
|
||||
e_attrs = self.default_edge_attrs.copy()
|
||||
g_attrs.update(graph_attrs)
|
||||
n_attrs.update(node_attrs)
|
||||
e_attrs.update(edge_attrs)
|
||||
if graph_attrs is not None:
|
||||
g_attrs.update(graph_attrs)
|
||||
if node_attrs is not None:
|
||||
n_attrs.update(node_attrs)
|
||||
if edge_attrs is not None:
|
||||
e_attrs.update(edge_attrs)
|
||||
if env:
|
||||
g_attrs.update(env.config.inheritance_graph_attrs)
|
||||
n_attrs.update(env.config.inheritance_node_attrs)
|
||||
|
@ -69,17 +69,13 @@ class Deque(collections.deque):
|
||||
raise StopIteration
|
||||
|
||||
|
||||
def _convert_type_spec(_type: str, translations: dict[str, str] = {}) -> str:
|
||||
def _convert_type_spec(_type: str, translations: dict[str, str] | None = None) -> str:
|
||||
"""Convert type specification to reference in reST."""
|
||||
if _type in translations:
|
||||
if translations is not None and _type in translations:
|
||||
return translations[_type]
|
||||
else:
|
||||
if _type == 'None':
|
||||
return ':obj:`None`'
|
||||
else:
|
||||
return ':class:`%s`' % _type
|
||||
|
||||
return _type
|
||||
if _type == 'None':
|
||||
return ':py:obj:`None`'
|
||||
return f':py:class:`{_type}`'
|
||||
|
||||
|
||||
class GoogleDocstring:
|
||||
@ -1023,8 +1019,11 @@ def _token_type(token: str, location: str | None = None) -> str:
|
||||
|
||||
|
||||
def _convert_numpy_type_spec(
|
||||
_type: str, location: str | None = None, translations: dict = {},
|
||||
_type: str, location: str | None = None, translations: dict | None = None,
|
||||
) -> str:
|
||||
if translations is None:
|
||||
translations = {}
|
||||
|
||||
def convert_obj(obj, translations, default_translation):
|
||||
translation = translations.get(obj, obj)
|
||||
|
||||
|
@ -36,7 +36,7 @@ from sphinx.util.logging import prefixed_warnings
|
||||
from sphinx.util.typing import RoleFunction, TitleGetter
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from collections.abc import Iterator
|
||||
from collections.abc import Iterator, Sequence
|
||||
|
||||
from sphinx.application import Sphinx
|
||||
from sphinx.ext.autodoc import Documenter
|
||||
@ -224,7 +224,7 @@ class SphinxComponentRegistry:
|
||||
parse_node: Callable | None = None,
|
||||
ref_nodeclass: type[TextElement] | None = None,
|
||||
objname: str = '',
|
||||
doc_field_types: list = [],
|
||||
doc_field_types: Sequence = (),
|
||||
override: bool = False,
|
||||
) -> None:
|
||||
logger.debug('[app] adding object type: %r',
|
||||
|
@ -18,6 +18,8 @@ from sphinx.util.docutils import ReferenceRole, SphinxRole
|
||||
from sphinx.util.typing import RoleFunction
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from collections.abc import Sequence
|
||||
|
||||
from sphinx.application import Sphinx
|
||||
from sphinx.environment import BuildEnvironment
|
||||
|
||||
@ -365,8 +367,10 @@ class Abbreviation(SphinxRole):
|
||||
# TODO: Change to use `SphinxRole` once SphinxRole is fixed to support options.
|
||||
def code_role(name: str, rawtext: str, text: str, lineno: int,
|
||||
inliner: docutils.parsers.rst.states.Inliner,
|
||||
options: dict = {}, content: list[str] = [],
|
||||
options: dict | None = None, content: Sequence[str] = (),
|
||||
) -> tuple[list[Node], list[system_message]]:
|
||||
if options is None:
|
||||
options = {}
|
||||
options = options.copy()
|
||||
docutils.parsers.rst.roles.set_classes(options)
|
||||
language = options.get('language', '')
|
||||
|
@ -107,8 +107,11 @@ class Theme:
|
||||
'searched theme configs') % (section, name)) from exc
|
||||
return default
|
||||
|
||||
def get_options(self, overrides: dict[str, Any] = {}) -> dict[str, Any]:
|
||||
def get_options(self, overrides: dict[str, Any] | None = None) -> dict[str, Any]:
|
||||
"""Return a dictionary of theme options and their values."""
|
||||
if overrides is None:
|
||||
overrides = {}
|
||||
|
||||
if self.base:
|
||||
options = self.base.get_options()
|
||||
else:
|
||||
|
@ -4,6 +4,7 @@ from __future__ import annotations
|
||||
|
||||
import os
|
||||
import re
|
||||
from collections.abc import Sequence # NoQA: TCH003
|
||||
from contextlib import contextmanager
|
||||
from copy import copy
|
||||
from os import path
|
||||
@ -276,7 +277,8 @@ class CustomReSTDispatcher:
|
||||
def role(
|
||||
self, role_name: str, language_module: ModuleType, lineno: int, reporter: Reporter,
|
||||
) -> tuple[RoleFunction, list[system_message]]:
|
||||
return self.role_func(role_name, language_module, lineno, reporter)
|
||||
return self.role_func(role_name, language_module, # type: ignore[return-value]
|
||||
lineno, reporter)
|
||||
|
||||
|
||||
class ElementLookupError(Exception):
|
||||
@ -448,24 +450,24 @@ class SphinxRole:
|
||||
.. note:: The subclasses of this class might not work with docutils.
|
||||
This class is strongly coupled with Sphinx.
|
||||
"""
|
||||
name: str #: The role name actually used in the document.
|
||||
rawtext: str #: A string containing the entire interpreted text input.
|
||||
text: str #: The interpreted text content.
|
||||
lineno: int #: The line number where the interpreted text begins.
|
||||
inliner: Inliner #: The ``docutils.parsers.rst.states.Inliner`` object.
|
||||
options: dict #: A dictionary of directive options for customization
|
||||
#: (from the "role" directive).
|
||||
content: list[str] #: A list of strings, the directive content for customization
|
||||
#: (from the "role" directive).
|
||||
name: str #: The role name actually used in the document.
|
||||
rawtext: str #: A string containing the entire interpreted text input.
|
||||
text: str #: The interpreted text content.
|
||||
lineno: int #: The line number where the interpreted text begins.
|
||||
inliner: Inliner #: The ``docutils.parsers.rst.states.Inliner`` object.
|
||||
options: dict #: A dictionary of directive options for customization
|
||||
#: (from the "role" directive).
|
||||
content: Sequence[str] #: A list of strings, the directive content for customization
|
||||
#: (from the "role" directive).
|
||||
|
||||
def __call__(self, name: str, rawtext: str, text: str, lineno: int,
|
||||
inliner: Inliner, options: dict = {}, content: list[str] = [],
|
||||
inliner: Inliner, options: dict | None = None, content: Sequence[str] = (),
|
||||
) -> tuple[list[Node], list[system_message]]:
|
||||
self.rawtext = rawtext
|
||||
self.text = unescape(text)
|
||||
self.lineno = lineno
|
||||
self.inliner = inliner
|
||||
self.options = options
|
||||
self.options = options if options is not None else {}
|
||||
self.content = content
|
||||
|
||||
# guess role type
|
||||
@ -522,8 +524,11 @@ class ReferenceRole(SphinxRole):
|
||||
explicit_title_re = re.compile(r'^(.+?)\s*(?<!\x00)<(.*?)>$', re.DOTALL)
|
||||
|
||||
def __call__(self, name: str, rawtext: str, text: str, lineno: int,
|
||||
inliner: Inliner, options: dict = {}, content: list[str] = [],
|
||||
inliner: Inliner, options: dict | None = None, content: Sequence[str] = (),
|
||||
) -> tuple[list[Node], list[system_message]]:
|
||||
if options is None:
|
||||
options = {}
|
||||
|
||||
# if the first character is a bang, don't cross-reference at all
|
||||
self.disabled = text.startswith('!')
|
||||
|
||||
|
@ -537,12 +537,14 @@ def _should_unwrap(subject: Callable) -> bool:
|
||||
return False
|
||||
|
||||
|
||||
def signature(subject: Callable, bound_method: bool = False, type_aliases: dict = {},
|
||||
def signature(subject: Callable, bound_method: bool = False, type_aliases: dict | None = None,
|
||||
) -> inspect.Signature:
|
||||
"""Return a Signature object for the given *subject*.
|
||||
|
||||
:param bound_method: Specify *subject* is a bound method or not
|
||||
"""
|
||||
if type_aliases is None:
|
||||
type_aliases = {}
|
||||
|
||||
try:
|
||||
if _should_unwrap(subject):
|
||||
|
@ -64,7 +64,7 @@ def default_role(docname: str, name: str) -> Generator[None, None, None]:
|
||||
dummy_reporter = Reporter('', 4, 4)
|
||||
role_fn, _ = roles.role(name, english, 0, dummy_reporter)
|
||||
if role_fn: # type: ignore[truthy-function]
|
||||
docutils.register_role('', role_fn)
|
||||
docutils.register_role('', role_fn) # type: ignore[arg-type]
|
||||
else:
|
||||
logger.warning(__('default role %s not found'), name, location=docname)
|
||||
|
||||
|
@ -4,6 +4,7 @@ from __future__ import annotations
|
||||
|
||||
import sys
|
||||
import typing
|
||||
from collections.abc import Sequence
|
||||
from struct import Struct
|
||||
from types import TracebackType
|
||||
from typing import Any, Callable, ForwardRef, TypeVar, Union
|
||||
@ -41,7 +42,7 @@ NoneType = type(None)
|
||||
PathMatcher = Callable[[str], bool]
|
||||
|
||||
# common role functions
|
||||
RoleFunction = Callable[[str, str, str, int, Inliner, dict[str, Any], list[str]],
|
||||
RoleFunction = Callable[[str, str, str, int, Inliner, dict[str, Any], Sequence[str]],
|
||||
tuple[list[nodes.Node], list[nodes.system_message]]]
|
||||
|
||||
# A option spec for directive
|
||||
|
@ -5,7 +5,7 @@ import math
|
||||
import os
|
||||
import re
|
||||
import textwrap
|
||||
from collections.abc import Generator, Iterable
|
||||
from collections.abc import Generator, Iterable, Sequence
|
||||
from itertools import chain, groupby
|
||||
from typing import TYPE_CHECKING, Any, cast
|
||||
|
||||
@ -416,7 +416,7 @@ class TextTranslator(SphinxTranslator):
|
||||
self.stateindent.append(indent)
|
||||
|
||||
def end_state(
|
||||
self, wrap: bool = True, end: list[str] | None = [''], first: str | None = None,
|
||||
self, wrap: bool = True, end: Sequence[str] | None = ('',), first: str | None = None,
|
||||
) -> None:
|
||||
content = self.states.pop()
|
||||
maxindent = sum(self.stateindent)
|
||||
|
@ -1222,7 +1222,7 @@ Do as you please
|
||||
expected = """\
|
||||
Do as you please
|
||||
|
||||
:Yields: :class:`str` -- Extended
|
||||
:Yields: :py:class:`str` -- Extended
|
||||
"""
|
||||
assert expected == actual
|
||||
|
||||
|
@ -39,7 +39,7 @@ def f6(x: int, *args, y: str, z: str) -> None:
|
||||
pass
|
||||
|
||||
|
||||
def f7(x: int = None, y: dict = {}) -> None:
|
||||
def f7(x: int = None, y: dict = {}) -> None: # NoQA: B006
|
||||
pass
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user