-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpyproject.toml
More file actions
158 lines (144 loc) · 6.11 KB
/
Copy pathpyproject.toml
File metadata and controls
158 lines (144 loc) · 6.11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
[build-system]
requires = ["setuptools>=77"]
build-backend = "setuptools.build_meta"
[project]
name = "snesdsp"
description = "A model of the SNES DSP-2 coprocessor, with its commands proved rather than sampled."
readme = "README.md"
license = "MIT"
license-files = ["LICENSE"]
requires-python = ">=3.12"
dynamic = ["version"]
keywords = ["dsp1", "dsp2", "dsp3", "dsp4", "upd77c25", "snes", "emulator", "coprocessor"]
classifiers = [
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
"Topic :: System :: Emulators",
]
[project.urls]
Homepage = "https://github.com/gufranco/snes-dsp-python"
Source = "https://github.com/gufranco/snes-dsp-python"
Issues = "https://github.com/gufranco/snes-dsp-python/issues"
[project.scripts]
snesdsp-doctor = "snesdsp.doctor:main"
[tool.setuptools]
packages = ["snesdsp"]
[tool.setuptools.dynamic]
version = { attr = "snesdsp.version.VERSION" }
[tool.setuptools.package-data]
snesdsp = ["artifacts.manifest.json"]
[tool.setuptools.exclude-package-data]
snesdsp = ["*.test.py"]
[tool.ruff]
target-version = "py312"
line-length = 100
# The processor is another project checked out beside this one, named after
# itself so anybody browsing the repository can see what this is built on. It
# carries its own gate at its own version, and this repository's lint passing or
# failing should never depend on a commit made in a different repository.
extend-exclude = ["nec-upd7725-96050-python"]
[tool.ruff.lint]
select = ["E", "F", "W", "I", "UP", "B", "SIM", "RUF", "PL", "BLE", "C4", "N", "A", "T20", "PTH"]
ignore = [
"PLR0913",
"PLR2004",
"PLR0912",
"PLR0915",
"PLR0911",
"PLC0415",
"PLR0917",
"E501",
# N818 wants every exception to end in Error. The control flow signals here are
# named the way CPython names its own: StopIteration, SystemExit and
# GeneratorExit carry no suffix either. The exceptions that report a genuine
# failure do end in Error.
"N818",
]
[tool.ruff.lint.per-file-ignores]
# The environment checks are the same shape and exist for the same reason: they
# report what a machine is, so a check that throws has to become a line in the
# report rather than end the run, and its output is the product.
"snesdsp/environment.py" = ["BLE001", "T201"]
# A test file sits beside the module it covers and is named after it, so its
# module name carries a dot that N999 rejects. The layout is deliberate: a
# module and its tests are read together.
"*.test.py" = ["PLR2004", "N999"]
# These are command line tools. Printing is their output, not a stray debug
# statement left behind, and routing it through a logger would put a level and
# a timestamp in front of a report meant to be read by a person.
"conformance/*.py" = ["T201"]
# The doctor exists so that nothing fails silently, which means it has to survive
# whatever a check throws at it and report that rather than propagate it. A
# narrower catch here would let an unforeseen failure escape as a traceback and
# take the rest of the report with it, which is the one outcome it must avoid.
# It prints for the same reason every tool here does: its output is the product.
"snesdsp/doctor.py" = ["BLE001", "T201"]
[tool.coverage.run]
source = ["snesdsp", "conformance"]
branch = true
# Finding cartridges is measured out of the gate on purpose. It depends on files
# nobody may distribute, so a machine that has them runs one set of paths and a
# machine that does not runs the other. No single build can exercise both, and a
# gate that demands the impossible gets switched off rather than met. What it
# does instead is report every check it could not run as skipped, out loud.
omit = []
[tool.coverage.report]
fail_under = 100
show_missing = true
exclude_also = [
# A protocol body is a contract, never code: the type checker reads it and the
# runtime never runs it, because the class exists to be satisfied rather than
# instantiated. Demanding coverage of the ellipses would mean calling methods
# that deliberately do nothing.
'class .*\(.*Protocol.*\):',
# The command line guard hands argv to a function that is itself tested, so
# there is nothing behind it left to exercise. Importing the module to cover
# the guard would run the tool rather than test it.
'if __name__ == "__main__":',
# The doctor puts its own repository on the import path so that it still runs
# when the package will not import, which is the case it exists for. A suite
# that imports the doctor has already put it there, so the branch the guard
# takes when running as a file is one no test can be in.
'if str\(ROOT\) not in sys\.path:',
# A type checking block never runs, by definition. Python 3.14 drops it before
# coverage can see it and earlier versions do not, so leaving it in would make
# the gate mean one thing on the newest runtime and another on the oldest
# supported one, which is worse than either.
'if TYPE_CHECKING:',
# A protocol method has no body to run, whether the ellipsis sits on its own
# line or after the signature. The same version split applies.
'^\s*\.\.\.$',
': \.\.\.$',
]
[tool.mypy]
# Every flag mypy has, plus the ones strict does not turn on. A model of a
# processor is arithmetic on masked integers from end to end, and the errors that
# matter most here are the ones where a width, a sign or a None slips through a
# boundary. A checker that sees the whole register file is the cheapest place to
# catch those.
strict = true
python_version = "3.12"
warn_unreachable = true
warn_no_return = true
strict_equality = true
extra_checks = true
enable_error_code = [
"explicit-override",
"ignore-without-code",
"possibly-undefined",
"redundant-expr",
"truthy-bool",
"truthy-iterable",
"unused-awaitable",
]
files = ["snesdsp", "conformance"]
[[tool.mypy.overrides]]
# The submodules are checked in their own repositories, against their own gate.
# Following imports into them here would report the state of somebody else's
# project, and a finding nobody in this one can act on.
module = ["upd7725.*", "mapper.*", "snesdriver.*"]
follow_imports = "skip"
ignore_missing_imports = true