Skip to content

Commit d2dbac5

Browse files
1329 enable reportunannotatedclassattribute in basedpyright (#1448)
* Enable `reportUnannotatedClassAttribute` in basedpyright * Update `CONTRIBUTING.md` to reflect new style
1 parent b4d168e commit d2dbac5

17 files changed

Lines changed: 35 additions & 59 deletions

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ Tool implementations are defined in classes in the `usethis._tool.impl` module.
142142
- Start by implementing its `name` property method, then work through the other methods. Most method have default implementations, but even in those cases you will need to consider them individually and determine an appropriate implementation. For example, methods which specify the tool's dependencies default to empty dependencies, but you shouldn't rely on this.
143143
- Mark all methods in your `ToolSpec` subclass with the `@typing.final` decorator. This prevents the methods from being accidentally overridden in the `Tool` subclass.
144144
- Then, define a subclass of the `ToolSpec` subclass you just created, which also subclasses `usethis._tool.base.Tool`, e.g. for a tool named Xyz, define a class `XyzTool(XyzToolSpec, Tool)`. The only method this usually requires a non-default implementation for is `config_spec` to specify which configuration sections should be set up for the tool (and which sections the tool manages). However, you may find it helpful to provide custom implementations for other methods as well, e.g. `print_how_to_use`.
145-
- Mark all methods in your `Tool` subclass with `@final` as well, to prevent further subclassing from overriding them.
145+
- Mark your `Tool` subclass with `@final` as well, to prevent further subclassing.
146146

147147
#### Register your `Tool` subclass
148148

pyproject.toml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,6 @@ reportImplicitStringConcatenation = false
216216
reportMissingParameterType = false
217217
reportMissingTypeArgument = false
218218
reportPrivateUsage = false
219-
reportUnannotatedClassAttribute = false
220219
reportUnknownArgumentType = false
221220
reportUnknownMemberType = false
222221
reportUnknownVariableType = false
@@ -225,11 +224,22 @@ reportUnusedCallResult = false
225224

226225
[[tool.basedpyright.executionEnvironments]]
227226
root = "tests"
227+
reportUnannotatedClassAttribute = false
228228
reportUnknownLambdaType = false
229229
reportUnknownParameterType = false
230230
reportUnreachable = false
231231
reportUnusedFunction = false
232232
reportUnusedParameter = false
233233

234+
[[tool.basedpyright.executionEnvironments]]
235+
# Particularly interested in avoiding the auto-generated schema script
236+
root = "src/usethis/_integrations/ci/bitbucket"
237+
reportUnannotatedClassAttribute = false
238+
239+
[[tool.basedpyright.executionEnvironments]]
240+
# Particularly interested in avoiding the auto-generated schema script
241+
root = "src/usethis/_integrations/pre_commit"
242+
reportUnannotatedClassAttribute = false
243+
234244
[tool.sync-with-uv.repo-to-package]
235245
"https://github.com/astral-sh/uv-pre-commit" = "uv"

src/usethis/_core/docstyle.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,5 @@ def use_docstyle(style: DocStyleEnum) -> None:
1515

1616
RuffTool().set_docstyle(style.value)
1717

18-
if not RuffTool()._are_pydocstyle_rules_selected():
18+
if not RuffTool().are_pydocstyle_rules_selected():
1919
RuffTool().select_rules(["D2", "D3", "D4"])

src/usethis/_io.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ class UsethisFileManager(Generic[DocumentT], metaclass=ABCMeta):
4040
# https://github.com/python/mypy/issues/5144
4141
# The Any in this expression should be identified with DocumentT
4242
_content_by_path: ClassVar[dict[Path, Any | None]] = {}
43+
path: Path
4344

4445
@property
4546
@abstractmethod

src/usethis/_tool/impl/base/codespell.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from usethis._tool.impl.spec.codespell import CodespellToolSpec
88

99

10+
@final
1011
class CodespellTool(CodespellToolSpec, Tool):
11-
@final
1212
def print_how_to_use(self) -> None:
1313
how_print(f"Run '{self.how_to_use_cmd()}' to run the {self.name} spellchecker.")

src/usethis/_tool/impl/base/coverage_py.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,14 @@
1515
from usethis._types.deps import Dependency
1616

1717

18+
@final
1819
class CoveragePyTool(CoveragePyToolSpec, Tool):
19-
@final
2020
def test_deps(self, *, unconditional: bool = False) -> list[Dependency]:
2121
deps = [Dependency(name="coverage", extras=frozenset({"toml"}))]
2222
if unconditional or is_likely_used(PytestToolSpec()):
2323
deps += [Dependency(name="pytest-cov")]
2424
return deps
2525

26-
@final
2726
def print_how_to_use(self) -> None:
2827
backend = get_backend()
2928

src/usethis/_tool/impl/base/deptry.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,14 @@
1616
from usethis._io import KeyValueFileManager
1717

1818

19+
@final
1920
class DeptryTool(DeptryToolSpec, Tool):
20-
@final
2121
def select_rules(self, rules: Sequence[Rule]) -> bool:
2222
"""Does nothing for deptry - all rules are automatically enabled by default."""
2323
if rules:
2424
info_print(f"All {self.name} rules are always implicitly selected.")
2525
return False
2626

27-
@final
2827
def selected_rules(self) -> list[Rule]:
2928
"""No notion of selection for deptry.
3029
@@ -33,12 +32,10 @@ def selected_rules(self) -> list[Rule]:
3332
"""
3433
return []
3534

36-
@final
3735
def deselect_rules(self, rules: Sequence[Rule]) -> bool:
3836
"""Does nothing for deptry - all rules are automatically enabled by default."""
3937
return False
4038

41-
@final
4239
def ignored_rules(self) -> list[Rule]:
4340
(file_manager,) = self.get_active_config_file_managers()
4441
keys = self._get_ignore_keys(file_manager)
@@ -49,7 +46,6 @@ def ignored_rules(self) -> list[Rule]:
4946

5047
return rules
5148

52-
@final
5349
def _get_ignore_keys(self, file_manager: KeyValueFileManager[object]) -> list[str]:
5450
"""Get the keys for the ignored rules in the given file manager."""
5551
if isinstance(file_manager, PyprojectTOMLManager):

src/usethis/_tool/impl/base/import_linter.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,15 @@
1212
from usethis._tool.rule import Rule
1313

1414

15+
@final
1516
class ImportLinterTool(ImportLinterToolSpec, Tool):
16-
@final
1717
def is_used(self) -> bool:
1818
"""Check if the Import Linter tool is used in the project."""
1919
# We suppress the warning about assumptions regarding the package name.
2020
# See _importlinter_warn_no_packages_found
2121
with usethis_config.set(quiet=True):
2222
return super().is_used()
2323

24-
@final
2524
def print_how_to_use(self) -> None:
2625
if not _is_inp_rule_selected():
2726
# If Ruff is used, we enable the INP rules instead.

src/usethis/_tool/impl/base/mkdocs.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
from usethis._types.backend import BackendEnum
1313

1414

15+
@final
1516
class MkDocsTool(MkDocsToolSpec, Tool):
16-
@final
1717
def print_how_to_use(self) -> None:
1818
backend = get_backend()
1919
if backend is BackendEnum.uv and is_uv_used():

src/usethis/_tool/impl/base/pre_commit.py

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,14 @@
1919
from usethis._python.version import PythonVersion
2020

2121

22+
@final
2223
class PreCommitTool(PreCommitToolSpec, Tool):
23-
@final
2424
def is_used(self) -> bool:
2525
return is_pre_commit_used()
2626

27-
@final
2827
def print_how_to_use(self) -> None:
2928
how_print(f"Run '{self.how_to_use_cmd()}' to run the hooks manually.")
3029

31-
@final
3230
def get_bitbucket_steps(
3331
self,
3432
*,
@@ -66,7 +64,6 @@ def get_bitbucket_steps(
6664
else:
6765
assert_never(backend)
6866

69-
@final
7067
def update_bitbucket_steps(self, *, matrix_python: bool = True) -> None:
7168
"""Add Bitbucket steps associated with pre-commit, and remove outdated ones.
7269
@@ -78,10 +75,8 @@ def update_bitbucket_steps(self, *, matrix_python: bool = True) -> None:
7875
"""
7976
self._unconditional_update_bitbucket_steps(matrix_python=matrix_python)
8077

81-
@final
8278
def migrate_config_to_pre_commit(self) -> None:
8379
pass
8480

85-
@final
8681
def migrate_config_from_pre_commit(self) -> None:
8782
pass

0 commit comments

Comments
 (0)