Skip to content

Commit b21f597

Browse files
committed
Enable many new Ruff lint checks
1 parent e1f50b0 commit b21f597

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+263
-297
lines changed

properdocs/__main__.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#!/usr/bin/env python
2-
31
from __future__ import annotations
42

53
import logging
@@ -9,6 +7,7 @@
97
import textwrap
108
import traceback
119
import warnings
10+
from typing import ClassVar
1211

1312
import click
1413

@@ -41,7 +40,7 @@ def _showwarning(message, category, filename, lineno, file=None, line=None):
4140
stack = [frame for frame in traceback.extract_stack() if frame.line][-4:-2]
4241
# Make sure the actual affected file's name is still present (the case of syntax warning):
4342
if not any(frame.filename == filename for frame in stack):
44-
stack = stack[-1:] + [traceback.FrameSummary(filename, lineno, '')]
43+
stack = [*stack[-1:], traceback.FrameSummary(filename, lineno, '')]
4544

4645
tb = ''.join(traceback.format_list(stack))
4746
except Exception:
@@ -64,7 +63,7 @@ def _enable_warnings():
6463

6564

6665
class ColorFormatter(logging.Formatter):
67-
colors = {
66+
colors: ClassVar = {
6867
'CRITICAL': 'red',
6968
'ERROR': 'red',
7069
'WARNING': 'yellow',

properdocs/commands/build.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,7 @@ def _build_template(
8787
output = template.render(context)
8888

8989
# Run `post_template` plugin events.
90-
output = config.plugins.on_post_template(output, template_name=name, config=config)
91-
92-
return output
90+
return config.plugins.on_post_template(output, template_name=name, config=config)
9391

9492

9593
def _build_theme_template(
@@ -321,8 +319,8 @@ def build(config: ProperDocsConfig, *, serve_url: str | None = None, dirty: bool
321319
if excluded:
322320
log.info(
323321
"The following pages are being built only for the preview "
324-
"but will be excluded from `properdocs build` per `draft_docs` config:\n - "
325-
+ "\n - ".join(excluded)
322+
"but will be excluded from `properdocs build` per `draft_docs` config:\n - %s",
323+
"\n - ".join(excluded),
326324
)
327325

328326
# Run `env` plugin events.

properdocs/commands/get_deps.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import io
99
import logging
1010
import os
11+
import pathlib
1112
import urllib.parse
1213
from collections.abc import Collection, Mapping, Sequence
1314
from typing import IO, Any, BinaryIO
@@ -27,7 +28,7 @@
2728
log = logging.getLogger(__name__)
2829

2930

30-
class YamlLoaderWithSuppressions(SafeLoader): # type: ignore
31+
class YamlLoaderWithSuppressions(SafeLoader): # type: ignore # noqa: PGH003
3132
pass
3233

3334

@@ -128,8 +129,7 @@ def get_projects_file(path: str | None = None) -> BinaryIO:
128129
if urllib.parse.urlsplit(path).scheme in ("http", "https"):
129130
content = cache.download_and_cache_url(path, datetime.timedelta(days=1))
130131
else:
131-
with open(path, "rb") as f:
132-
content = f.read()
132+
content = pathlib.Path(path).read_bytes()
133133
return io.BytesIO(content)
134134

135135

properdocs/commands/gh_deploy.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@
44
import os
55
import re
66
import subprocess
7+
from pathlib import Path
78
from typing import TYPE_CHECKING
89

9-
import ghp_import # type: ignore
10+
import ghp_import # type: ignore[import-untyped]
1011
from packaging import version
1112

1213
import properdocs
@@ -43,8 +44,7 @@ def _get_current_sha(repo_path) -> str:
4344
)
4445

4546
stdout, _ = proc.communicate()
46-
sha = stdout.decode('utf-8').strip()
47-
return sha
47+
return stdout.decode('utf-8').strip()
4848

4949

5050
def _get_remote_url(remote_name: str) -> tuple[str, str] | tuple[None, None]:
@@ -78,7 +78,9 @@ def _check_version(branch: str) -> None:
7878

7979
stdout, _ = proc.communicate()
8080
msg = stdout.decode('utf-8').strip()
81-
m = re.search(r'\d+(\.\d+)+((a|b|rc)\d+)?(\.post\d+)?(\.dev\d+)?', msg, re.X | re.I)
81+
m = re.search(
82+
r'\d+(\.\d+)+((a|b|rc)\d+)?(\.post\d+)?(\.dev\d+)?', msg, re.VERBOSE | re.IGNORECASE
83+
)
8284
previousv = version.parse(m.group()) if m else None
8385
currentv = version.parse(properdocs.__version__)
8486
if not previousv:
@@ -145,8 +147,7 @@ def gh_deploy(
145147
# Does this repository have a CNAME set for GitHub Pages?
146148
if os.path.isfile(cname_file):
147149
# This GitHub Pages repository has a CNAME configured.
148-
with open(cname_file) as f:
149-
cname_host = f.read().strip()
150+
cname_host = Path(cname_file).read_text(encoding='utf-8').strip()
150151
log.info(
151152
f'Based on your CNAME file, your documentation should be '
152153
f'available shortly at: http://{cname_host}'
@@ -163,7 +164,6 @@ def gh_deploy(
163164
log.info('Your documentation should be available shortly.')
164165
else:
165166
username, repo = path.split('/', 1)
166-
if repo.endswith('.git'):
167-
repo = repo[: -len('.git')]
167+
repo = repo.removesuffix('.git')
168168
url = f'https://{username}.github.io/{repo}/'
169169
log.info(f"Your documentation should shortly be available at: {url}")

properdocs/commands/new.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import logging
44
import os
5+
import pathlib
56

67
config_text = 'site_name: My Docs\n'
78
index_text = """# Welcome to ProperDocs
@@ -40,14 +41,12 @@ def new(output_dir: str) -> None:
4041
os.mkdir(output_dir)
4142

4243
log.info(f'Writing config file: {config_path}')
43-
with open(config_path, 'w', encoding='utf-8') as f:
44-
f.write(config_text)
44+
pathlib.Path(config_path).write_text(config_text, encoding='utf-8')
4545

4646
if os.path.exists(index_path):
4747
return
4848

4949
log.info(f'Writing initial docs: {index_path}')
5050
if not os.path.exists(docs_dir):
5151
os.mkdir(docs_dir)
52-
with open(index_path, 'w', encoding='utf-8') as f:
53-
f.write(index_text)
52+
pathlib.Path(index_path).write_text(index_text, encoding='utf-8')

properdocs/commands/serve.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import tempfile
88
from collections.abc import Callable
99
from os.path import isdir, isfile, join
10+
from pathlib import Path
1011
from typing import TYPE_CHECKING, BinaryIO
1112
from urllib.parse import urlsplit
1213

@@ -88,8 +89,7 @@ def error_handler(code) -> bytes | None:
8889
if code in (404, 500):
8990
error_page = join(site_dir, f'{code}.html')
9091
if isfile(error_page):
91-
with open(error_page, 'rb') as f:
92-
return f.read()
92+
return Path(error_page).read_bytes()
9393
return None
9494

9595
server.error_handler = error_handler

properdocs/config/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
from properdocs.config.base import Config, load_config
22

3-
__all__ = ['load_config', 'Config']
3+
__all__ = ['Config', 'load_config']

properdocs/config/base.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import warnings
88
from collections import UserDict
99
from collections.abc import Iterator, Mapping, Sequence
10-
from contextlib import contextmanager
10+
from contextlib import contextmanager, suppress
1111
from typing import IO, TYPE_CHECKING, Any, Generic, TypeVar, overload
1212

1313
from properdocs import exceptions, utils
@@ -136,7 +136,7 @@ def __init_subclass__(cls):
136136
"All values are required, or can be wrapped into config_options.Optional"
137137
)
138138

139-
def __new__(cls, *args, **kwargs) -> Config:
139+
def __new__(cls, *args, **kwargs) -> Config: # noqa: PYI034
140140
"""Compatibility: allow referring to `LegacyConfig(...)` constructor as `Config(...)`."""
141141
if cls is Config:
142142
return LegacyConfig(*args, **kwargs)
@@ -314,10 +314,8 @@ def _open_config_file(config_file: str | IO | None) -> Iterator[IO]:
314314
else:
315315
log.debug(f"Loading configuration file: {result_config_file}")
316316
# Ensure file descriptor is at beginning
317-
try:
317+
with suppress(OSError):
318318
result_config_file.seek(0)
319-
except OSError:
320-
pass
321319

322320
try:
323321
yield result_config_file

properdocs/config/config_options.py

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from __future__ import annotations
22

3+
import contextlib
34
import functools
45
import importlib.util
56
import ipaddress
@@ -13,7 +14,7 @@
1314
from collections import Counter, UserString
1415
from collections.abc import Callable, Collection, Iterator, Mapping, MutableMapping
1516
from types import SimpleNamespace
16-
from typing import Any, Generic, NamedTuple, TypeVar, Union, overload
17+
from typing import Any, Generic, NamedTuple, TypeVar, overload
1718
from urllib.parse import quote as urlquote
1819
from urllib.parse import urlsplit, urlunsplit
1920

@@ -93,7 +94,7 @@ def pre_validation(self, config: Config, key_name: str):
9394
def run_validation(self, value: object) -> SomeConfig:
9495
config = self.config_class(config_file_path=self._config_file_path)
9596
try:
96-
config.load_dict(value) # type: ignore
97+
config.load_dict(value) # type: ignore[arg-type]
9798
failed, warnings = config.validate()
9899
except ConfigurationError as e:
99100
raise ValidationError(str(e))
@@ -204,15 +205,13 @@ def run_validation(self, value: object) -> list[T]:
204205
return value
205206

206207
fake_config = LegacyConfig(())
207-
try:
208+
with contextlib.suppress(AttributeError):
208209
fake_config.config_file_path = self._config.config_file_path
209-
except AttributeError:
210-
pass
211210

212211
# Emulate a config-like environment for pre_validation and post_validation.
213212
parent_key_name = getattr(self, '_key_name', '')
214213
fake_keys = [f'{parent_key_name}[{i}]' for i in range(len(value))]
215-
fake_config.data = dict(zip(fake_keys, value))
214+
fake_config.data = dict(zip(fake_keys, value, strict=False))
216215

217216
self.option_type.warnings = self.warnings
218217
for key_name in fake_config:
@@ -259,10 +258,8 @@ def run_validation(self, value: object) -> dict[str, T]:
259258
return value
260259

261260
fake_config = LegacyConfig(())
262-
try:
261+
with contextlib.suppress(AttributeError):
263262
fake_config.config_file_path = self._config.config_file_path
264-
except AttributeError:
265-
pass
266263

267264
# Emulate a config-like environment for pre_validation and post_validation.
268265
fake_config.data = value
@@ -362,7 +359,7 @@ def __init__(self, choices: Collection[T], default: T | None = None, **kwargs) -
362359
def run_validation(self, value: object) -> T:
363360
if value not in self.choices:
364361
raise ValidationError(f"Expected one of: {self.choices} but received: {value!r}")
365-
return value # type: ignore
362+
return value # type: ignore[return-value]
366363

367364

368365
class Deprecated(BaseConfigOption):
@@ -508,7 +505,7 @@ def run_validation(self, value: object) -> str:
508505
raise ValidationError("The URL isn't valid, it should include the http:// (scheme)")
509506

510507

511-
class Optional(Generic[T], BaseConfigOption[Union[T, None]]):
508+
class Optional(Generic[T], BaseConfigOption[T | None]):
512509
"""
513510
Wraps a field and makes a None value possible for it when no value is set.
514511
@@ -539,7 +536,7 @@ def run_validation(self, value: object) -> T | None:
539536
return self.option.validate(value)
540537

541538
def post_validation(self, config: Config, key_name: str):
542-
result = self.option.post_validation(config, key_name) # type: ignore
539+
result = self.option.post_validation(config, key_name) # type: ignore[func-returns-value]
543540
self.warnings = self.option.warnings
544541
return result
545542

@@ -940,7 +937,7 @@ def __fspath__(self):
940937
return self.path
941938

942939

943-
class ExtraScript(BaseConfigOption[Union[ExtraScriptValue, str]]):
940+
class ExtraScript(BaseConfigOption[ExtraScriptValue | str]):
944941
def __init__(self):
945942
super().__init__()
946943
self.option_type = SubConfig[ExtraScriptValue]()

properdocs/contrib/search/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ def get_lunr_supported_lang(self, lang):
3030
lang_part = fallback.get(lang_part, lang_part)
3131
if os.path.isfile(os.path.join(base_path, 'lunr-language', f'lunr.{lang_part}.js')):
3232
return lang_part
33+
return None
3334

3435
def run_validation(self, value: object):
3536
if isinstance(value, str):
@@ -70,7 +71,7 @@ def on_config(self, config: ProperDocsConfig, **kwargs) -> ProperDocsConfig:
7071
path = os.path.join(base_path, 'templates')
7172
config.theme.dirs.append(path)
7273
if 'search/main.js' not in config.extra_javascript:
73-
config.extra_javascript.append('search/main.js') # type: ignore
74+
config.extra_javascript.append('search/main.js')
7475
if self.config.lang is None:
7576
# lang setting undefined. Set default based on theme locale
7677
validate = _PluginConfig.lang.run_validation

0 commit comments

Comments
 (0)