Skip to content

Commit 65d4561

Browse files
committed
merge: Enable more lint rules (#612)
2 parents 7a85ba2 + feb9554 commit 65d4561

71 files changed

Lines changed: 970 additions & 556 deletions

Some content is hidden

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

docs/source/conf.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@
5454
("py:exc", "capellambse.UnsupportedPluginError"),
5555
("py:exc", "capellambse.UnsupportedPluginVersionError"),
5656
("any", "capellambse.aird.GLOBAL_FILTERS"),
57+
# I don't even know what Sphinx is doing at this point
58+
("py:class", "T_co | _obj.ElementList[T_co] | None"),
5759
# Private type hinting helpers
5860
("py:class", "_MapFunction"),
5961
("py:class", "_NotSpecifiedType"),

docs/source/examples/04 Intro to Jinja templating.ipynb

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -604,13 +604,11 @@
604604
}
605605
],
606606
"source": [
607-
"fig_templ = \"\".join(\n",
608-
" (\n",
609-
" '{% extends \"template.html\" %}',\n",
610-
" \"{% block content %}\",\n",
611-
" templ,\n",
612-
" \"{% endblock %}\",\n",
613-
" )\n",
607+
"fig_templ = (\n",
608+
" '{% extends \"template.html\" %}'\n",
609+
" \"{% block content %}\"\n",
610+
" f\"{templ}\"\n",
611+
" \"{% endblock %}\"\n",
614612
")\n",
615613
"final_templ = \"\"\"\n",
616614
"<!DOCTYPE html>\n",

docs/source/examples/05 Introduction to Libraries.ipynb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
"name": "stdout",
2020
"output_type": "stream",
2121
"text": [
22-
"MissingResourceLocationError: 'Library Test'\n"
22+
"capellambse.loader.core.MissingResourceLocationError: 'Library Test'\n"
2323
]
2424
}
2525
],
@@ -32,8 +32,8 @@
3232
"\n",
3333
"try:\n",
3434
" capellambse.MelodyModel(path_to_model)\n",
35-
"except Exception as err:\n",
36-
" print(f\"{type(err).__name__}: {err}\")"
35+
"except Exception as err: # noqa: BLE001\n",
36+
" print(f\"{type(err).__module__}.{type(err).__name__}: {err}\")"
3737
]
3838
},
3939
{

pyproject.toml

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,8 @@ wrap-summaries = 79
226226

227227
[tool.mypy]
228228
check_untyped_defs = true
229+
disallow_incomplete_defs = true
230+
disallow_untyped_defs = true
229231
no_implicit_optional = true
230232
show_error_codes = true
231233
warn_redundant_casts = true
@@ -234,11 +236,6 @@ warn_unused_ignores = true
234236
plugins = ["mypypp.deprecated"]
235237
python_version = "3.10"
236238

237-
[[tool.mypy.overrides]]
238-
module = ["tests.*"]
239-
disallow_incomplete_defs = false
240-
disallow_untyped_defs = false
241-
242239
[[tool.mypy.overrides]]
243240
# Untyped third party libraries
244241
module = [
@@ -269,32 +266,43 @@ line-length = 79
269266
[tool.ruff.lint]
270267
extend-select = [
271268
"ARG", # flake8-unused-arguments
269+
"ASYNC", # flake8-async
272270
"B", # flake8-bugbear
271+
"BLE", # flake8-blind-except
273272
"C4", # flake8-comprehensions
274273
"D", # pydocstyle
275274
"D212", # "Multi-line docstring summary should start at the first line"
276275
"D402", # "First line should not be the function’s 'signature'"
277276
"D417", # "Missing argument descriptions in the docstring"
278277
"DTZ", # flake8-datetimez
278+
"E", # pycodestyle
279279
"ERA", # eradicate
280+
"F", # pyflakes
280281
"FA", # flake8-future-annotations
281282
"FIX", # flake8-fixme
283+
"FLY", # flynt
282284
"FURB", # refurb
283285
"G", # flake8-logging-format
284286
"I", # isort
285287
"ICN", # flake8-import-conventions
286288
"ISC001", # "Implicitly concatenated string literals on one line"
287289
"ISC003", # "Explicitly concatenated string should be implicitly concatenated"
288290
"LOG", # flake8-logging
291+
"PERF", # perflint
292+
"PGH", # pygrep-hooks
289293
"PIE", # flake8-pie
290294
"PL", # pylint
291295
"PT", # flake8-pytest-style
296+
"PYI", # flake8-pyi
292297
"RET", # flake8-return
293298
"RUF", # ruff
294299
"SIM", # flake8-simplify
295-
"TC005", # "Found empty type-checking block"
296-
"T1", # flake8-debugger
300+
"SLOT", # flake8-slots
301+
"T10", # flake8-debugger
302+
"T20", # flake8-print
303+
"TC", # flake8-type-checking
297304
"UP", # pyupgrade
305+
"W", # pycodestyle
298306
"YTT", # flake8-2020
299307
]
300308
ignore = [
@@ -308,6 +316,7 @@ ignore = [
308316
"DTZ001", # `tzinfo=None` passed to `datetime.datetime()`
309317
"DTZ005", # `tz=None` passed to `datetime.datetime.now()`
310318
"E402", # Module level import not at top of file
319+
"E501", # Line too long # auto-formatting
311320
"F403", # `from _ import *` used; unable to detect undefined names
312321
"F405", # `_` may be undefined, or defined from star imports
313322
"PLC0414", # Import alias does not rename original package # used for explicit reexports
@@ -324,6 +333,9 @@ ignore = [
324333
"PLW2901", # `for` loop variable `_` overwritten by assignment target
325334
"RUF005", # Consider iterable unpacking instead of concatenation # false-positives with NamedTuple and overridden __add__ (i.e. Vector2D)
326335
"SIM108", # Use ternary operator instead of `if`-`else`-block
336+
"TC001", # Move first-party import into type-checking block # Sphinx needs all imports at runtime
337+
"TC002", # Move third-party import into type-checking block # Sphinx needs all imports at runtime
338+
"TC003", # Move stdlib import into type-checking block # Sphinx needs all imports at runtime
327339
]
328340

329341
[tool.ruff.lint.extend-per-file-ignores]
@@ -332,13 +344,24 @@ ignore = [
332344
]
333345
"tests/test_*.py" = [
334346
"F811", # Redefinition of unused `_` from line _
347+
"PGH003", # Use specific rule codes when ignoring type issues
335348
"PLR2004", # Magic value used in comparison, consider replacing `_` with a constant variable
336349
]
337350

338-
# Jupyter notebooks
351+
# Jupyter notebooks and CLI scripts
339352
"*.ipynb" = [
340353
"ERA001", # commented-out code # used to showcase alternatives to the executed code
341354
"FIX", # flake8-fixme
355+
"T201", # print used
356+
]
357+
"src/capellambse/_diagram_cache.py" = [
358+
"T201", # print used
359+
]
360+
"src/capellambse/_scripts/*.py" = [
361+
"T201", # print used
362+
]
363+
"scripts/*.py" = [
364+
"T201", # print used
342365
]
343366

344367
[tool.ruff.lint.flake8-bugbear]

scripts/mkchangelog.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ def _main(since: str, until: str) -> None:
9797
custom_changes = f.read().strip()
9898
except FileNotFoundError:
9999
custom_changes = ""
100-
except Exception as err:
100+
except Exception as err: # noqa: BLE001
101101
errtext = f" {type(err).__name__}: {err}"
102102
custom_changes = f"***Cannot read notable-changes.md:*** {errtext}"
103103

src/capellambse/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ def load_model_extensions() -> None:
4848
try:
4949
initfunc = entrypoint.load()
5050
initfunc()
51-
except Exception:
51+
except Exception: # noqa: PERF203
5252
logging.getLogger(__name__).exception(
5353
"Cannot load model extension %r from %r",
5454
entrypoint.name,

src/capellambse/__main__.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,19 @@
1212

1313

1414
class LazyGroup(click.Group):
15-
def list_commands(self, ctx):
16-
cmds: list[str] = []
17-
for i in imr.files(_scripts).iterdir():
18-
if i.name.endswith(".py") and not i.name.startswith("_"):
19-
cmds.append(i.name.removesuffix(".py").replace("_", "-"))
20-
cmds.sort()
15+
def list_commands(self, ctx: click.Context) -> list[str]:
16+
cmds = sorted(
17+
i.name.removesuffix(".py").replace("_", "-")
18+
for i in imr.files(_scripts).iterdir()
19+
if i.name.endswith(".py") and not i.name.startswith("_")
20+
)
2121
return super().list_commands(ctx) + cmds
2222

23-
def get_command(self, ctx, name):
23+
def get_command(
24+
self,
25+
ctx: click.Context,
26+
name: str,
27+
) -> click.Command | None:
2428
with contextlib.suppress(ImportError):
2529
modname = name.replace("-", "_")
2630
cmd = importlib.import_module(
@@ -34,7 +38,7 @@ def get_command(self, ctx, name):
3438

3539

3640
@click.group(cls=LazyGroup, no_args_is_help=True)
37-
def main():
41+
def main() -> None:
3842
pass
3943

4044

src/capellambse/_diagram_cache.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ def export(
103103
*,
104104
format: str,
105105
index: bool,
106-
force: t.Literal["exe", "docker", None],
106+
force: t.Literal["exe", "docker"] | None,
107107
background: bool,
108108
refresh: bool = False,
109109
) -> list[IndexEntry]:
@@ -161,7 +161,7 @@ def export(
161161
def _find_executor(
162162
model: capellambse.MelodyModel,
163163
capella: str,
164-
force: t.Literal["exe", "docker", None],
164+
force: t.Literal["exe", "docker"] | None,
165165
) -> dict[str, str]:
166166
assert model.info.capella_version
167167
capella = capella.replace("{VERSION}", model.info.capella_version)
@@ -385,7 +385,7 @@ def _calculate_svg_viewbox(root: etree._Element) -> ViewBox:
385385
return ViewBox(x_min, y_min, x_max - x_min, y_max - y_min)
386386

387387

388-
def _crop_svg_viewbox(src: pathlib.Path, root: etree._Element):
388+
def _crop_svg_viewbox(src: pathlib.Path, root: etree._Element) -> None:
389389
try:
390390
min_x, min_y, new_width, new_height = _calculate_svg_viewbox(root)
391391
except _NoBoundingBoxFound:
@@ -489,7 +489,7 @@ def _write_index(
489489
body := E.body(E.h1(title), E.p({"class": "small"}, "Created: ", now)),
490490
)
491491

492-
def sortkey(entry: IndexEntry):
492+
def sortkey(entry: IndexEntry) -> tuple[int, str, str]:
493493
try:
494494
vp_index = VIEWPOINT_ORDER.index(entry["viewpoint"])
495495
except ValueError:
@@ -520,7 +520,7 @@ def sortkey(entry: IndexEntry):
520520
class IndexEncoder(json.JSONEncoder):
521521
"""A JSON encoder for the index file."""
522522

523-
def default(self, o):
523+
def default(self, o: object) -> object:
524524
if isinstance(o, m.DiagramType):
525525
return o.name
526526
return super().default(o)

src/capellambse/_scripts/export_diagrams.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ def main(
134134
logger.info("No diagrams found in the model, nothing to export")
135135
raise SystemExit(0)
136136

137+
force: t.Literal["docker", "exe"] | None
137138
if docker:
138139
capella = docker
139140
force = "docker"
@@ -146,7 +147,7 @@ def main(
146147
model_,
147148
format=format,
148149
index=index,
149-
force=force, # type: ignore
150+
force=force,
150151
background=background,
151152
refresh=refresh,
152153
)

src/capellambse/_scripts/repl.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import pathlib
1616
import shutil
1717
import subprocess
18+
import sys
1819
import textwrap
1920
import typing as t
2021

@@ -72,7 +73,7 @@ def _readline_history(histfile: pathlib.Path, /) -> cabc.Iterator[None]:
7273
except ImportError:
7374

7475
@contextlib.contextmanager
75-
def _readline_history(_histfile, /) -> cabc.Iterator[None]:
76+
def _readline_history(_histfile: pathlib.Path, /) -> cabc.Iterator[None]:
7677
yield
7778

7879

@@ -337,7 +338,7 @@ def fzf(
337338
>>> obj = fzf(model.search("ComponentExchange"), "target.parent.name")
338339
"""
339340

340-
def repr(obj):
341+
def repr(obj: object) -> str:
341342
return getattr(obj, "_short_repr_", obj.__repr__)()
342343

343344
binary = shutil.which("fzf")
@@ -363,7 +364,10 @@ def repr(obj):
363364
text=True,
364365
stdout=subprocess.PIPE,
365366
)
366-
except (Exception, KeyboardInterrupt):
367+
except KeyboardInterrupt:
368+
return None
369+
except subprocess.CalledProcessError as err:
370+
print(f"fzf failed with exit code {err.returncode}", file=sys.stderr)
367371
return None
368372
else:
369373
selected = elements[int(proc.stdout.strip().split(" ", 1)[0])]

0 commit comments

Comments
 (0)