Enable 11 more categories in Ruff

* flake8-builtins ('A')
* flake8-blind-except ('BLE')
* flake8-copyright ('CPY')
* eradicate ('ERA')
* flake8-boolean-trap ('FBT')
* flake8-fixme ('FIX')
* flake8-implicit-str-concat ('ISC')
* pep8-naming ('N')
* flake8-use-pathlib ('PTH')
* flake8-self ('SLF')
* tryceratops ('TRY')
This commit is contained in:
Adam Turner committed 2025-01-14 14:43:02 +00:00
1 parent 3521cb60cf
commit c66d3e85d1
45 files changed
+154 -106

No files matched your search

+66 -19
View File
@@ -16,6 +16,10 @@ quote-style = "single"
[lint]
preview = true
ignore = [
# flake8-builtins
"A001", # Variable `{name}` is shadowing a Python builtin
"A002", # Function argument `{name}` is shadowing a Python builtin
"A005", # Module `{name}` is shadowing a Python builtin module
# flake8-annotations
"ANN401", # Dynamically typed expressions (typing.Any) are disallowed in `{name}`
# flake8-unused-arguments ('ARG')
@@ -23,23 +27,44 @@ ignore = [
"ARG002", # Unused method argument: `{name}`
"ARG003", # Unused class method argument: `{name}`
"ARG005", # Unused lambda argument: `{name}`
# flake8-commas ('COM')
# flake8-blind-except
"BLE001", # Do not catch blind exception: `{name}`
# flake8-commas
"COM812", # Trailing comma missing
# flake8-copyright
"CPY001", # Missing copyright notice at top of file
# pycodestyle
"E741", # Ambiguous variable name: `{name}`
# eradicate
"ERA001", # Found commented-out code
# pyflakes
"F841", # Local variable `{name}` is assigned to but never used
# flake8-boolean-trap
"FBT001", # Boolean-typed positional argument in function definition
"FBT002", # Boolean default positional argument in function definition
"FBT003", # Boolean positional value in function call
# flake8-fixme
"FIX001", # Line contains FIXME, consider resolving the issue
"FIX002", # Line contains TODO, consider resolving the issue
"FIX003", # Line contains XXX, consider resolving the issue
"FIX004", # Line contains HACK, consider resolving the issue
# refurb
"FURB101", # `open` and `read` should be replaced by `Path(...).read_text(...)`
"FURB103", # `open` and `write` should be replaced by `Path(...).write_text(...)`
# flake8-implicit-str-concat
# pep8-naming
"N801", # Class name `{name}` should use CapWords convention
"N802", # Function name `{name}` should be lowercase
"N803", # Argument name `{name}` should be lowercase
"N806", # Variable `{name}` in function should be lowercase
"N818", # Exception name `{name}` should be named with an Error suffix
# perflint
"PERF203", # `try`-`except` within a loop incurs performance overhead
# flake8-pie ('PIE')
# flake8-pie
"PIE790", # Unnecessary `pass` statement
# pylint ('PLC')
# pylint
"PLC0415", # `import` should be at the top-level of a file
"PLC2701", # Private name import `{name}` from external module `{module}`
# pylint ('PLR')
"PLR0904", # Too many public methods ({methods} > {max_methods})
"PLR0911", # Too many return statements ({returns} > {max_returns})
"PLR0912", # Too many branches ({branches} > {max_branches})
@@ -53,8 +78,16 @@ ignore = [
"PLR5501", # Use `elif` instead of `else` then `if`, to reduce indentation
"PLR6104", # Use `{operator}` to perform an augmented assignment directly
"PLR6301", # Method `{method_name}` could be a function, class method, or static method
# pylint ('PLW')
"PLW2901", # Outer {outer_kind} variable `{name}` overwritten by inner {inner_kind} target
# flake8-use-pathlib
"PTH100", # `os.path.abspath()` should be replaced by `Path.resolve()`
"PTH110", # `os.path.exists()` should be replaced by `Path.exists()`
"PTH113", # `os.path.isfile()` should be replaced by `Path.is_file()`
"PTH118", # `os.{module}.join()` should be replaced by `Path` with `/` operator
"PTH119", # `os.path.basename()` should be replaced by `Path.name`
"PTH120", # `os.path.dirname()` should be replaced by `Path.parent`
"PTH122", # `os.path.splitext()` should be replaced by `Path.suffix`, `Path.stem`, and `Path.parent`
"PTH123", # `open()` should be replaced by `Path.open()`
# flake8-pyi ('PYI')
"PYI025", # Use `from collections.abc import Set as AbstractSet` to avoid confusion with the `set` builtin
# flake8-bandit ('S')
@@ -66,11 +99,16 @@ ignore = [
# flake8-simplify
"SIM102", # Use a single `if` statement instead of nested `if` statements
"SIM108", # Use ternary operator `{contents}` instead of `if`-`else`-block
# flake8-self
"SLF001", # Private member accessed: `{access}`
# flake8-todos ('TD')
"TD001", # Invalid TODO tag: `{tag}`
"TD002", # Missing author in TODO; try: `# TODO(<author_name>): ...` or `# TODO @<author_name>: ...`
"TD003", # Missing issue link on the line following this TODO
"TD004", # Missing colon in TODO
# tryceratops
"TRY002", # Create your own exception
"TRY300", # Consider moving this statement to an `else` block
# pyupgrade
"UP031", # Use format specifiers instead of percent format
"UP032", # Use f-string instead of `format` call
@@ -88,7 +126,7 @@ external = [ # Whitelist for RUF100 unknown code warnings
]
select = [
# flake8-builtins ('A')
# NOT YET USED
"A",
# airflow ('AIR')
# Airflow is not used in Sphinx
# flake8-annotations ('ANN')
@@ -100,7 +138,7 @@ select = [
# flake8-bugbear ('B')
"B",
# flake8-blind-except ('BLE')
# NOT YET USED
"BLE",
# flake8-comprehensions ('C4')
"C4",
# mccabe ('C90')
@@ -108,7 +146,7 @@ select = [
# flake8-commas ('COM')
"COM", # Trailing comma prohibited
# flake8-copyright ('CPY')
# NOT YET USED
"CPY",
# pydocstyle ('D')
# "D100", # Missing docstring in public module
# "D101", # Missing docstring in public class
@@ -164,7 +202,7 @@ select = [
# flake8-errmsg ('EM')
"EM",
# eradicate ('ERA')
# NOT YET USED
"ERA",
# flake8-executable ('EXE')
"EXE",
# pyflakes ('F')
@@ -174,9 +212,9 @@ select = [
# flake8-fastapi ('FAST')
# FastAPI is not used in Sphinx
# flake8-boolean-trap ('FBT')
# NOT YET USED
"FBT",
# flake8-fixme ('FIX')
# NOT YET USED
"FIX",
# flynt ('FLY')
"FLY",
# refurb ('FURB')
@@ -186,17 +224,17 @@ select = [
# isort ('I')
"I",
# flake8-import-conventions ('ICN')
"ICN", # flake8-import-conventions
"ICN",
# flake8-no-pep420 ('INP')
"INP",
# flake8-gettext ('INT')
"INT",
# flake8-implicit-str-concat ('ISC')
# NOT YET USED
"ISC",
# flake8-logging ('LOG')
"LOG",
# pep8-naming ('N')
# NOT YET USED
"N",
# numpy-specific rules ('NPY')
# Numpy is not used in Sphinx
# pandas-vet ('PD')
@@ -212,9 +250,9 @@ select = [
# flake8-pytest-style ('PT')
"PT",
# flake8-use-pathlib ('PTH')
# NOT YET USED
"PTH",
# flake8-pyi ('PYI')
"PYI",
# Stub files are not used in Sphinx
# flake8-quotes ('Q')
"Q",
# flake8-return ('RET')
@@ -235,7 +273,7 @@ select = [
# flake8-simplify ('SIM')
"SIM", # flake8-simplify
# flake8-self ('SLF')
# NOT YET USED
"SLF",
# flake8-slots ('SLOT')
"SLOT",
# flake8-debugger ('T10')
@@ -251,7 +289,7 @@ select = [
# flake8-trio ('TRIO')
# Trio is not used in Sphinx
# tryceratops ('TRY')
# NOT YET USED
"TRY",
# pyupgrade ('UP')
"UP",
# pycodestyle ('W')
@@ -299,7 +337,10 @@ logger-objects = [
# whitelist ``print`` for stdout messages
"sphinx/cmd/build.py" = ["T201"]
"sphinx/cmd/make_mode.py" = ["T201"]
"sphinx/cmd/quickstart.py" = ["T201"]
"sphinx/cmd/quickstart.py" = [
"PTH",
"T201",
]
"sphinx/environment/collectors/toctree.py" = ["B026"]
"sphinx/environment/adapters/toctree.py" = ["B026"]
@@ -315,9 +356,15 @@ logger-objects = [
# whitelist ``print`` for stdout messages
"sphinx/testing/fixtures.py" = ["T201"]
# whitelist ``os.path`` for deprecated ``sphinx.testing.path``
"sphinx/testing/path.py" = ["PTH"]
# whitelist ``token`` in date format parsing
"sphinx/util/i18n.py" = ["S105"]
# whitelist ``os.path`` for ``sphinx.util.osutil``
"sphinx/util/osutil.py" = ["PTH"]
# whitelist ``token`` in literal parsing
"sphinx/writers/html5.py" = ["S105"]
+2 -2
View File
@@ -6,7 +6,6 @@ Gracefully adapted from the TextPress system by Armin.
from __future__ import annotations
import contextlib
import os
import pickle
import sys
from collections import deque
@@ -36,6 +35,7 @@ from sphinx.util.osutil import ensuredir, relpath
from sphinx.util.tags import Tags
if TYPE_CHECKING:
import os
from collections.abc import Callable, Collection, Iterable, Sequence, Set
from pathlib import Path
from typing import IO, Any, Final, Literal
@@ -424,7 +424,7 @@ class Sphinx:
# delete the saved env to force a fresh build next time
envfile = self.doctreedir / ENV_PICKLE_FILENAME
if envfile.is_file():
os.unlink(envfile)
envfile.unlink()
self.events.emit('build-finished', err)
raise
+4 -4
View File
@@ -2,9 +2,9 @@
from __future__ import annotations
import codecs
import operator
import time
from codecs import open
from collections import defaultdict
from os import getenv, path, walk
from pathlib import Path
@@ -216,7 +216,7 @@ def should_write(filepath: str, new_content: str) -> bool:
if not path.exists(filepath):
return True
try:
with open(filepath, encoding='utf-8') as oldpot:
with codecs.open(filepath, encoding='utf-8') as oldpot:
old_content = oldpot.read()
old_header_index = old_content.index('"POT-Creation-Date:')
new_header_index = new_content.index('"POT-Creation-Date:')
@@ -277,7 +277,7 @@ class MessageCatalogBuilder(I18nBuilder):
files, __('reading templates... '), 'purple', len(files), self.app.verbosity
):
try:
with open(template, encoding='utf-8') as f:
with codecs.open(template, encoding='utf-8') as f:
context = f.read()
for line, _meth, msg in extract_translations(context):
origin = MsgOrigin(source=template, line=line)
@@ -328,7 +328,7 @@ class MessageCatalogBuilder(I18nBuilder):
pofn = path.join(self.outdir, textdomain + '.pot')
if should_write(pofn, content):
with open(pofn, 'w', encoding='utf-8') as pofile:
with codecs.open(pofn, 'w', encoding='utf-8') as pofile:
pofile.write(content)
+1 -1
View File
@@ -1274,7 +1274,7 @@ class StandaloneHTMLBuilder(Builder):
else:
with open(search_index_tmp, 'wb') as fb:
self.indexer.dump(fb, self.indexer_format)
os.replace(search_index_tmp, search_index_path)
Path(search_index_tmp).replace(search_index_path)
def convert_html_css_files(app: Sphinx, config: Config) -> None:
+3 -2
View File
@@ -5,6 +5,7 @@ from __future__ import annotations
import os
import os.path
import warnings
from pathlib import Path
from typing import TYPE_CHECKING
from docutils.frontend import OptionParser
@@ -446,8 +447,8 @@ class LaTeXBuilder(Builder):
'xindy_cyrillic': xindy_cyrillic,
}
staticdirname = os.path.join(package_dir, 'texinputs')
for filename in os.listdir(staticdirname):
if not filename.startswith('.'):
for filename in Path(staticdirname).iterdir():
if not filename.name.startswith('.'):
copy_asset_file(
os.path.join(staticdirname, filename),
self.outdir,
+6 -1
View File
@@ -16,7 +16,12 @@ from typing import TYPE_CHECKING, NamedTuple, cast
from urllib.parse import quote, unquote, urlparse, urlsplit, urlunparse
from docutils import nodes
from requests.exceptions import ConnectionError, HTTPError, SSLError, TooManyRedirects
from requests.exceptions import (
ConnectionError, # NoQA: A004
HTTPError,
SSLError,
TooManyRedirects,
)
from requests.exceptions import Timeout as RequestTimeout
from sphinx.builders.dummy import DummyBuilder
+1 -1
View File
@@ -15,7 +15,7 @@ try:
import readline
if TYPE_CHECKING and sys.platform == 'win32': # always false, for type checking
raise ImportError
raise ImportError # NoQA: TRY301
READLINE_AVAILABLE = True
if readline.__doc__ and 'libedit' in readline.__doc__:
readline.parse_and_bind('bind ^I rl_complete')
+1 -1
View File
@@ -388,7 +388,7 @@ class Config:
# given falsy string from a command line option
return value not in {'0', ''}
if isinstance(default, dict):
raise ValueError(
raise ValueError( # NoQA: TRY004
__(
'cannot override dictionary config setting %r, '
'ignoring (use %r to set individual elements)'
+1 -1
View File
@@ -86,7 +86,7 @@ def container_wrapper(
node = parsed[0]
if isinstance(node, nodes.system_message):
msg = __('Invalid caption: %s') % node.astext()
raise ValueError(msg)
raise ValueError(msg) # NoQA: TRY004
if isinstance(node, nodes.Element):
caption_node = nodes.caption(node.rawsource, '', *node.children)
caption_node.source = literal_node.source
+1 -1
View File
@@ -2052,7 +2052,7 @@ class DefinitionParser(BaseParser):
if object_type == 'member' and len(templates) == 0:
return ASTTemplateDeclarationPrefix(None)
else:
raise e
raise
if object_type == 'concept' and params.requiresClause is not None:
self.fail('requires-clause not allowed for concept')
else:
+1 -1
View File
@@ -562,7 +562,7 @@ def _pseudo_parse_arglist(
stack.pop()
ends_close -= 1
if len(stack) != 1:
raise IndexError
raise IndexError # NoQA: TRY301
except IndexError:
# if there are too few or too many elements on the stack, just give up
# and treat the whole argument list as one argument, discarding the
+1 -1
View File
@@ -515,7 +515,7 @@ def _toctree_copy(
copy.append(sub_node_copy)
else:
msg = f'Unexpected node type {subnode.__class__.__name__!r}!'
raise ValueError(msg)
raise ValueError(msg) # NoQA: TRY004
return copy
+1 -1
View File
@@ -112,7 +112,7 @@ class ImageCollector(EnvironmentCollector):
node: Node,
) -> None:
globbed: dict[str, list[str]] = {}
for filename in glob(imgpath):
for filename in glob(imgpath): # NoQA: PTH207
new_imgpath = _relative_path(Path(filename), srcdir)
try:
mimetype = guess_mimetype(filename)
+6 -4
View File
@@ -15,7 +15,7 @@ from sphinx.util.template import ReSTRenderer
if TYPE_CHECKING:
import re
from collections.abc import Iterator, Sequence
from collections.abc import Iterable, Iterator, Sequence
from sphinx.ext.apidoc._shared import ApidocOptions
@@ -50,13 +50,15 @@ def module_join(*modnames: str | None) -> str:
return '.'.join(filter(None, modnames))
def is_packagedir(dirname: str | None = None, files: list[str] | None = None) -> bool:
def is_packagedir(
dirname: str | None = None, files: Iterable[str | Path] | None = None
) -> bool:
"""Check given *files* contains __init__ file."""
if files is None and dirname is None:
return False
if files is None:
files = os.listdir(dirname)
files = Path(dirname or '.').iterdir()
return any(f for f in files if is_initpy(f))
@@ -208,7 +210,7 @@ def is_skipped_package(
if not Path(dirname).is_dir():
return False
files = glob.glob(str(Path(dirname, '*.py')))
files = glob.glob(str(Path(dirname, '*.py'))) # NoQA: PTH207
regular_package = any(f for f in files if is_initpy(f))
if not regular_package and not opts.implicit_namespaces:
# *dirname* is not both a regular package and an implicit namespace package
+1 -1
View File
@@ -157,7 +157,7 @@ class AutodocDirective(SphinxDirective):
)
except (KeyError, ValueError, TypeError) as exc:
# an option is either unknown or has a wrong type
logger.error(
logger.error( # NoQA: TRY400
'An option to %s is either unknown or has an invalid value: %s',
self.name,
exc,
+1 -1
View File
@@ -131,7 +131,7 @@ class AutosummaryRenderer:
def __init__(self, app: Sphinx) -> None:
if isinstance(app, Builder):
msg = 'Expected a Sphinx application object!'
raise ValueError(msg)
raise TypeError(msg)
system_templates_path = [
os.path.join(package_dir, 'ext', 'autosummary', 'templates')
+1 -1
View File
@@ -179,7 +179,7 @@ class CoverageBuilder(Builder):
self.c_sourcefiles: list[str] = []
for pattern in self.config.coverage_c_path:
pattern = os.path.join(self.srcdir, pattern)
self.c_sourcefiles.extend(glob.glob(pattern))
self.c_sourcefiles.extend(glob.glob(pattern)) # NoQA: PTH207
self.c_regexes: list[tuple[str, re.Pattern[str]]] = []
for name, exp in self.config.coverage_c_regexes.items():
+2 -5
View File
@@ -2,8 +2,6 @@
from __future__ import annotations
import contextlib
import os
import urllib.parse
from typing import TYPE_CHECKING
@@ -39,7 +37,7 @@ def create_nojekyll_and_cname(app: Sphinx, env: BuildEnvironment) -> None:
return
app.builder.outdir.joinpath('.nojekyll').touch()
cname_path = os.path.join(app.builder.outdir, 'CNAME')
cname_path = app.builder.outdir / 'CNAME'
domain = _get_domain_from_url(app.config.html_baseurl)
# Filter out GitHub Pages domains, as they do not require CNAME files.
@@ -49,8 +47,7 @@ def create_nojekyll_and_cname(app: Sphinx, env: BuildEnvironment) -> None:
# auto-generated by the GitHub UI doesn't have one.
f.write(domain)
else:
with contextlib.suppress(FileNotFoundError):
os.unlink(cname_path)
cname_path.unlink(missing_ok=True)
def setup(app: Sphinx) -> ExtensionMetadata:
+5 -5
View File
@@ -366,12 +366,12 @@ def render_dot_html(
filename: str | None = None,
) -> tuple[str, str]:
format = self.builder.config.graphviz_output_format
if format not in {'png', 'svg'}:
logger.warning(
__("graphviz_output_format must be either 'png' or 'svg', but is %r"),
format,
)
try:
if format not in {'png', 'svg'}:
raise GraphvizError(
__("graphviz_output_format must be one of 'png', 'svg', but is %r")
% format
)
fname, outfn = render_dot(self, code, options, format, prefix, filename)
except GraphvizError as exc:
logger.warning(__('dot code %r: %s'), code, exc)
+1 -1
View File
@@ -32,7 +32,7 @@ def inspect_main(argv: list[str], /) -> int:
target_uri='',
inv_location=filename,
config=config,
srcdir=Path(''),
srcdir=Path(),
)
for key in sorted(inv_data or {}):
print(key)
+1 -1
View File
@@ -81,7 +81,7 @@ def validate_intersphinx_mapping(app: Sphinx, config: Config) -> None:
'Invalid value `%r` in intersphinx_mapping[%r]. '
'Values must be a (target URI, inventory locations) pair.'
)
LOGGER.error(msg, value, name)
LOGGER.error(msg, value, name) # NoQA: TRY400
del config.intersphinx_mapping[name]
continue
+1 -1
View File
@@ -76,7 +76,7 @@ class Todo(BaseAdmonition, SphinxDirective):
self.state.document.note_explicit_target(todo)
return [todo]
else:
raise RuntimeError # never reached here
raise TypeError # never reached here
class TodoDomain(Domain):
+2 -1
View File
@@ -4,6 +4,7 @@ from __future__ import annotations
import os
import os.path
from pathlib import Path
from pprint import pformat
from typing import TYPE_CHECKING
@@ -226,7 +227,7 @@ class BuiltinTemplateLoader(TemplateBridge, BaseLoader):
def _newest_template_mtime_name(self) -> tuple[float, str]:
return max(
(os.stat(os.path.join(root, sfile)).st_mtime_ns / 10**9, sfile)
(Path(root, sfile).stat().st_mtime_ns / 10**9, sfile)
for dirname in self.pathchain
for root, _dirs, files in os.walk(dirname)
for sfile in files
+3 -5
View File
@@ -4,8 +4,6 @@ from __future__ import annotations
__all__ = ('SphinxTestApp', 'SphinxTestAppWrapperForSkipBuilding')
import contextlib
import os
import sys
from io import StringIO
from types import MappingProxyType
@@ -21,6 +19,7 @@ from sphinx.util.console import strip_colors
from sphinx.util.docutils import additional_nodes
if TYPE_CHECKING:
import os
from collections.abc import Mapping, Sequence
from pathlib import Path
from typing import Any
@@ -224,8 +223,7 @@ class SphinxTestApp(sphinx.application.Sphinx):
def cleanup(self, doctrees: bool = False) -> None:
sys.path[:] = self._saved_path
_clean_up_global_state()
with contextlib.suppress(FileNotFoundError):
os.remove(self.docutils_conf_path)
self.docutils_conf_path.unlink(missing_ok=True)
def __repr__(self) -> str:
return f'<{self.__class__.__name__} buildername={self._builder_name!r}>'
@@ -247,7 +245,7 @@ class SphinxTestAppWrapperForSkipBuilding(SphinxTestApp):
def build(
self, force_all: bool = False, filenames: list[str] | None = None
) -> None:
if not os.listdir(self.outdir):
if not list(self.outdir.iterdir()):
# if listdir is empty, do build.
super().build(force_all, filenames)
# otherwise, we can use built cache
+1 -1
View File
@@ -115,7 +115,7 @@ class ImageDownloader(BaseImageConverter):
# append a suffix if URI does not contain suffix
ext = get_image_extension(mimetype) or ''
with_ext = path.with_name(path.name + ext)
os.replace(path, with_ext)
path.replace(with_ext)
self.env.original_image_uri.pop(str_path)
self.env.original_image_uri[_StrPath(with_ext)] = node['uri']
path = with_ext
+1 -1
View File
@@ -77,7 +77,7 @@ def __getattr__(name: str) -> Any:
return obj
if name == 'ExtensionError':
from sphinx.errors import ExtensionError as obj
from sphinx.errors import ExtensionError as obj # NoQA: N813
canonical_name = f'{obj.__module__}.{obj.__qualname__}'
_deprecation_warning(__name__, name, canonical_name, remove=(9, 0))
+3 -3
View File
@@ -11,17 +11,17 @@ def parse_line_num_spec(spec: str, total: int) -> list[int]:
try:
begend = part.strip().split('-')
if begend == ['', '']:
raise ValueError
raise ValueError # NoQA: TRY301
if len(begend) == 1:
items.append(int(begend[0]) - 1)
elif len(begend) == 2:
start = int(begend[0] or 1) # left half open (cf. -10)
end = int(begend[1] or max(start, total)) # right half open (cf. 10-)
if start > end: # invalid range (cf. 10-1)
raise ValueError
raise ValueError # NoQA: TRY301
items.extend(range(start - 1, end))
else:
raise ValueError
raise ValueError # NoQA: TRY301
except ValueError as exc:
msg = f'invalid line number spec: {spec!r}'
raise ValueError(msg) from exc
+1 -1
View File
@@ -112,4 +112,4 @@ class Tags:
return node.name in self._tags
else:
msg = 'invalid node, check parsing'
raise ValueError(msg)
raise TypeError(msg)
@@ -1,3 +1,4 @@
# NoQA: N999
from __future__ import annotations
from gettext import NullTranslations # NoQA: TC003
@@ -42,13 +42,13 @@ class Baz:
class Qux:
@deco1
def __new__(self, name=None, age=None):
def __new__(cls, name=None, age=None):
pass
class _Metaclass(type):
@deco1
def __call__(self, name=None, age=None):
def __call__(cls, name=None, age=None):
pass
@@ -57,12 +57,12 @@ class Bar:
"""docstring"""
@overload
def __init__(cls, x: int, y: int) -> None: ...
def __init__(self, x: int, y: int) -> None: ...
@overload
def __init__(cls, x: str, y: str) -> None: ...
def __init__(self, x: str, y: str) -> None: ...
def __init__(cls, x, y):
def __init__(self, x, y):
pass
@@ -7,7 +7,7 @@ class Foo:
@classmethod
@property
def prop2(self) -> int:
def prop2(cls) -> int:
"""docstring"""
@property
@@ -17,6 +17,6 @@ class Foo:
@classmethod
@property
def prop2_with_type_comment(self):
def prop2_with_type_comment(cls):
# type: () -> int
"""docstring"""
@@ -6,7 +6,7 @@ module with trailing underscores everywhere
class class_:
"""Class"""
def method_(_arg):
def method_(_arg): # NoQA: N805
"""Method"""
pass
@@ -2,7 +2,7 @@
submodule
"""
raise RuntimeError('This module should not get imported') # NoQA: EM101
raise RuntimeError('This module should not get imported') # NoQA: EM101,TRY003
def decorator(f):
+1 -1
View File
@@ -71,7 +71,7 @@ def test_build_all(requests_head, make_app, nonascii_srcdir, buildername):
def test_root_doc_not_found(tmp_path, make_app):
(tmp_path / 'conf.py').touch()
assert os.listdir(tmp_path) == ['conf.py']
assert [p.name for p in tmp_path.iterdir()] == ['conf.py']
app = make_app('dummy', srcdir=tmp_path)
with pytest.raises(SphinxError):
@@ -2,7 +2,6 @@
from __future__ import annotations
import os
import re
import pytest
@@ -309,7 +308,7 @@ def test_numfig_without_numbered_toctree(
index = re.sub(':numbered:.*', '', index)
(app.srcdir / 'index.rst').write_text(index, encoding='utf8')
if not os.listdir(app.outdir):
if not list(app.outdir.iterdir()):
app.build()
check_xpath(cached_etree_parse(app.outdir / fname), fname, path, check, be_found)
+1 -4
View File
@@ -2141,10 +2141,7 @@ def test_latex_code_role(app):
r'\PYG{k}{pass}'
)
assert (
r'Inline \sphinxcode{\sphinxupquote{%'
+ '\n'
+ common_content
+ '%\n}} code block'
'Inline \\sphinxcode{\\sphinxupquote{%\n' + common_content + '%\n}} code block'
) in content
assert (
r'\begin{sphinxVerbatim}[commandchars=\\\{\}]'
+1 -1
View File
@@ -260,7 +260,7 @@ def test_format_signature(app):
def foo1(self, b, *c):
pass
def foo2(b, *c):
def foo2(b, *c): # NoQA: N805
pass
def foo3(self, d='\n'):
+2 -2
View File
@@ -33,12 +33,12 @@ def _private_undoc():
pass
def __special_doc__():
def __special_doc__(): # NoQA: N807
"""module.__special_doc__.DOCSTRING"""
pass
def __special_undoc__():
def __special_undoc__(): # NoQA: N807
pass
+3 -2
View File
@@ -24,6 +24,7 @@ from sphinx.util.nodes import NodeMatcher
if TYPE_CHECKING:
from io import StringIO
from pathlib import Path
_CATALOG_LOCALE = 'xx'
@@ -47,9 +48,9 @@ def write_mo(pathname, po):
return mofile.write_mo(f, po)
def _set_mtime_ns(target: str | os.PathLike[str], value: int) -> int:
def _set_mtime_ns(target: Path, value: int) -> int:
os.utime(target, ns=(value, value))
return os.stat(target).st_mtime_ns
return target.stat().st_mtime_ns
def _get_bom_intl_path(app):
+2 -2
View File
@@ -85,7 +85,7 @@ def test_progress_message(app):
# skipping case
with progress_message('testing'):
raise SkipProgressMessage('Reason: %s', 'error') # NoQA: EM101
raise SkipProgressMessage('Reason: %s', 'error') # NoQA: EM101,TRY003
output = strip_colors(app.status.getvalue())
assert 'testing... skipped\nReason: error\n' in output
@@ -93,7 +93,7 @@ def test_progress_message(app):
# error case
try:
with progress_message('testing'):
raise RuntimeError
raise RuntimeError # NoQA: TRY301
except Exception:
pass
+8 -8
View File
@@ -40,32 +40,32 @@ def test_register_node():
assert not hasattr(nodes.SparseNodeVisitor, 'depart_custom_node')
def test_SphinxFileOutput(tmpdir):
def test_SphinxFileOutput(tmp_path):
content = 'Hello Sphinx World'
# write test.txt at first
filename = str(tmpdir / 'test.txt')
output = SphinxFileOutput(destination_path=filename)
filename = tmp_path / 'test.txt'
output = SphinxFileOutput(destination_path=str(filename))
output.write(content)
os.utime(filename, ns=(0, 0))
# overwrite it again
output.write(content)
assert os.stat(filename).st_mtime_ns != 0 # updated
assert filename.stat().st_mtime_ns != 0 # updated
# write test2.txt at first
filename = str(tmpdir / 'test2.txt')
output = SphinxFileOutput(destination_path=filename, overwrite_if_changed=True)
filename = tmp_path / 'test2.txt'
output = SphinxFileOutput(destination_path=str(filename), overwrite_if_changed=True)
output.write(content)
os.utime(filename, ns=(0, 0))
# overwrite it again
output.write(content)
assert os.stat(filename).st_mtime_ns == 0 # not updated
assert filename.stat().st_mtime_ns == 0 # not updated
# overwrite it again (content changed)
output.write(content + '; content change')
assert os.stat(filename).st_mtime_ns != 0 # updated
assert filename.stat().st_mtime_ns != 0 # updated
@pytest.mark.sphinx('html', testroot='root')
+2 -2
View File
@@ -39,7 +39,7 @@ def test_catalog_outdated(tmp_path):
mo_file.write_text('#', encoding='utf8')
assert not cat.is_outdated() # if mo is exist and newer than po
new_mtime = os.stat(mo_file).st_mtime_ns - 10_000_000_000
new_mtime = mo_file.stat().st_mtime_ns - 10_000_000_000
os.utime(mo_file, ns=(new_mtime, new_mtime)) # to be outdated
assert cat.is_outdated() # if mo is exist and older than po
@@ -98,7 +98,7 @@ def test_format_date():
def test_format_date_timezone():
dt = datetime.datetime(2016, 8, 7, 5, 11, 17, 0, tzinfo=datetime.UTC)
if time.localtime(dt.timestamp()).tm_gmtoff == 0:
raise pytest.skip('Local time zone is GMT') # NoQA: EM101
raise pytest.skip('Local time zone is GMT') # NoQA: EM101,TRY003
fmt = '%Y-%m-%d %H:%M:%S'
+2 -2
View File
@@ -942,7 +942,7 @@ def test_unpartial():
def test_getdoc_inherited_classmethod():
class Foo:
@classmethod
def meth(self):
def meth(cls):
"""
Docstring
indented text
@@ -950,7 +950,7 @@ def test_getdoc_inherited_classmethod():
class Bar(Foo):
@classmethod
def meth(self):
def meth(cls):
# inherited classmethod
pass
+2 -3
View File
@@ -2,7 +2,6 @@
from __future__ import annotations
import os
from typing import TYPE_CHECKING
import pytest
@@ -94,10 +93,10 @@ def test_ambiguous_definition_warning(app):
def _write_appconfig(dir: Path, language: str, prefix: str | None = None) -> Path:
prefix = prefix or language
os.makedirs(dir / prefix, exist_ok=True)
(dir / prefix).mkdir(parents=True, exist_ok=True)
(dir / prefix / 'conf.py').write_text(f'language = "{language}"', encoding='utf8')
(dir / prefix / 'index.rst').write_text('index.rst', encoding='utf8')
assert sorted(os.listdir(dir / prefix)) == ['conf.py', 'index.rst']
assert sorted(p.name for p in (dir / prefix).iterdir()) == ['conf.py', 'index.rst']
assert (dir / prefix / 'index.rst').exists()
return dir / prefix