Skip to content

Commit 0290e5b

Browse files
committed
ci: add static type checking through ty
1 parent 7c0a412 commit 0290e5b

3 files changed

Lines changed: 33 additions & 2 deletions

File tree

.github/workflows/lint.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ jobs:
3333
- name: Install dependencies
3434
run: |
3535
python -m pip install --upgrade pip
36-
python -m pip install ruff
36+
python -m pip install ruff ty
3737
3838
- name: Lint with Ruff on a basic set of rules
3939
run: |
@@ -42,3 +42,7 @@ jobs:
4242
- name: Lint with Ruff on an extended ruleset but always return success
4343
run: |
4444
ruff check libdestruct --output-format=github --exit-zero
45+
46+
- name: Type check with ty
47+
run: |
48+
ty check --output-format=github

libdestruct/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
#
66

77
try: # pragma: no cover
8-
from rich.traceback import install
8+
from rich.traceback import install # ty: ignore[unresolved-import]
99

1010
install()
1111
except ImportError: # pragma: no cover

pyproject.toml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,38 @@ dependencies = ["typing_extensions", "pycparser"]
3434
[project.optional-dependencies]
3535
dev = [
3636
"rich",
37+
"ty",
3738
]
3839

3940
[tool.setuptools.packages.find]
4041
include = ["libdestruct*"]
4142

43+
[tool.ty.src]
44+
exclude = ["test/", "build/"]
45+
46+
[tool.ty.rules]
47+
# -- Dynamic metaclass/descriptor inflation pattern --
48+
# The type registry, struct metaclass, and descriptor protocol resolve attributes
49+
# at runtime in ways that ty cannot yet follow (_type_impl, _member_offsets, etc).
50+
unresolved-attribute = "ignore"
51+
52+
# -- Rules that caught real bugs --
53+
# Keep as warn until annotations are improved, then promote to error.
54+
invalid-return-type = "warn" # union.diff() returns dict, ptr.__getitem__ returns bytes
55+
invalid-argument-type = "warn" # union.__init__ passes None as Resolver
56+
invalid-type-form = "warn" # lowercase `callable`, `iter` as type, `...` as annotation
57+
missing-argument = "warn" # wrong _backing_type: type[obj] (should be obj) in enum/flags
58+
too-many-positional-arguments = "warn" # array.__setitem__ calls set() with wrong arity
59+
60+
# -- Intentional design patterns --
61+
invalid-method-override = "warn" # deliberate param narrowing in _set/set overrides (LSP)
62+
invalid-assignment = "warn" # _backing_type instance vs type confusion; descriptor __set__
63+
unsupported-operator = "warn" # obj.get() returns `object`, operators on result untypeable
64+
call-non-callable = "warn" # dynamic inflater dispatch: resolved_type(resolver)
65+
not-subscriptable = "warn" # object.__setattr__ hides dict types from checker
66+
no-matching-overload = "warn" # untyped dict in struct_parser
67+
invalid-yield = "warn" # yield from dynamic __getitem__ typed as object
68+
4269
[tool.ruff]
4370
line-length = 120
4471
indent-width = 4

0 commit comments

Comments
 (0)