-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathpyproject.toml
448 lines (400 loc) · 15.1 KB
/
pyproject.toml
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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
# SPDX-FileCopyrightText: Copyright 2020-2025, Contributors to Tyrannosaurus
# SPDX-PackageHomePage: https://github.com/dmyersturnbull/tyrannosaurus
# SPDX-License-Identifier: Apache-2.0
#
#########################################################################################
# [build-system]
#########################################################################################
[build-system]
build-backend = "hatchling.build"
requires = ["hatchling~=1.26"]
#
#########################################################################################
# [project]
#########################################################################################
[project]
name = "cicd"
version = "0.0.1-alpha0"
requires-python = "~=3.13"
# 'readme' |--> 'description' in importlib.metadata
readme = { file = "README.md", content-type = "text/markdown" }
# 'description' |--> 'summary' in importlib.metadata
description = "Sandbox for Tyrannosaurus"
maintainers = [
{ name = "Douglas Myers-Turnbull", email = " [email protected]" },
]
authors = [
{ name = "Douglas Myers-Turnbull", email = " [email protected]" },
]
keywords = ["python", "ci", "cd"]
# The Python Packaging Authority has contradictory recommendations for specifying the license:
# - If the license is well-known, add a Trove classifier and omit `project.license`.
# - If you do that, tools like pip won't know what the license is.
# - PEP 639, which is actively developed but not targeted for a release,
# deprecates the Trove classifiers in favor of `project.license` as an SPDX expression:
# license = "Apache-2.0"
# license-files = ["LICENSE.txt", "3rd-party-notices/**/*.txt"]
# The former maps to the core metadata `License-Expression`, now a string.
# Unfortunately, following that now breaks everything.
# note: PyPI is required to error if License-Expression and a Trove license classifier are present.
# see: https://peps.python.org/pep-0639/#deprecate-license-classifiers
# see: https://discuss.python.org/t/pep-639-round-3-improving-license-clarity-with-better-package-metadata/53020
# see: https://github.com/python/peps/pull/3866
# which maps to License-Expression
license = { text = "Apache-2.0" }
classifiers = [
"Development Status :: 2 - Pre-Alpha",
"Environment :: Console",
"Intended Audience :: Developers",
"Natural Language :: English",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3 :: Only",
"Topic :: Software Development :: Build Tools",
"Topic :: Software Development :: Code Generators",
"Typing :: Typed",
]
dependencies = [
"loguru>=0.7.2",
"platformdirs>=4.3.2",
"typer-slim>=0.15",
# /usr/share/zoneinfo uses IANA zones; Windows does not
"tzdata>=2024.2; platform_system == 'Windows'",
]
[project.optional-dependencies]
cli = [
"rich>=13.9.1",
"typer-slim[standard]>=0.12.5",
]
#
#=================================== scripts =================================#
#
[project.scripts]
# :tyranno: ${project.name} = "${project.name}.__main__:cli"
tyranno = "cicd.__main__:cli"
#
#==================================== URIs ===================================#
#
[project.urls]
# :tyranno: "https://github.com/${.frag}"
Homepage = "https://github.com/dmyersturnbull/cicd"
# :tyranno: "https://github.com/${.frag}"
Source = "https://github.com/dmyersturnbull/cicd"
# :tyranno: Documentation = https://${.vendor}.github.io/${project.name}
Documentation = "https://dmyersturnbull.github.io/cicd"
# :tyranno: "Issue Tracker" = ${.home}/issues
Tracker = "https://github.com/dmyersturnbull/cicd/issues"
# :tyranno: Download = "https://pypi.org/project/${project.name}"
Download = "https://pypi.org/project/cicd/"
# :tyranno: "Release Notes" = "https://github.com/${.frag}/releases"
"Release Notes" = "https://github.com/dmyersturnbull/cicd/releases"
# :tyranno: #Sponsor = "https://${.vendor}.github.io/${project.name}/placeholder#sponsor"
#Sponsor = "https://${.vendor}.github.io/${project.name}/placeholder#sponsor"
#########################################################################################
# [dependency-groups]
#########################################################################################
# See https://docs.astral.sh/uv/concepts/projects/dependencies/#dependency-groups
[dependency-groups]
dev = [
"pre-commit>=4.0.1",
"ruff>=0.9",
"mypy>=1.14",
]
test = [
"hypothesis>=6.115",
"pytest>=8.3",
"tzdata>=2024.2; platform_system == 'Windows'",
"coverage[toml]>=7.6.3",
"pytest-cov>=6.0",
]
docs = [
"mkdocs>=1.6",
"mike>=2.1",
"mkdocs-include-markdown-plugin>=7.0",
"mkdocs>=1.6",
"mkdocs-material>=9.5",
"mkdocs-minify-plugin>=0.8",
"mkdocstrings[python]>=0.27",
"mkdocs-literate-nav>=0.6",
]
#
#########################################################################################
# [tool.ruff]
#########################################################################################
[tool.ruff]
#
#=================================== Ruff basics =============================#
line-length = 120 # 120 is hatch's default via 'hatch init'
include = [
"*.py", # Source
"pyproject.toml", # This file (RUF rules only)
"*.ipynb", # Jupyter notebooks
]
#
#=================================== Ruff lint ==============================#
[tool.ruff.lint]
#
# ------------------------- Ruff misc. options ----------------------
preview = true
explicit-preview-rules = true
#
# ---------------------- Ruff selected rule sets --------------------
select = [
"A", # flake8-builtins
#"AIR", # Airflow //DISABLED: enable if using airflow//
"ANN", # flake8-annotations
#"ARG", # flake8-unused-args //DISABLED: correct in overrides//
"ASYNC", # flake8-async
"B", # flake8-bugbear
#"BLE", # flake8-blind-exception (try: * except: only) //DISABLED: covered by E722 (?)//
"C", # flake8-comprehensions
"C4", # flake8-comprehensions
#"C90", # mmcabe //DISABLED: useful but thin-lined and time-intensive//
#"COM", # flake8-commas //DISABLED: handled by formatter//
#"CPY", # flake8-copyright //DISABLED: handle carefully instead; also unmaintained//
"D", # pydocstyle
#"DJ", # flake8-django //DISABLED: enable if using Django//
"DTZ", # flake8-datetimez
#"E", # pycodestyle ERRORs //DISABLED: almost all handled by formatter//
"E502", # redundant backslash
"E71", # == None, != False, not in, not is, etc.
"E72", # bare except
"E73", # lambda assignment
"E74", # easily confused characters in names
"E9", # can't lint -- syntax error, etc.
"EM", # flake8-errmsg
#"ERA", # eradicate (commented-out code) //DISABLED: catches code in comments, etc.//
#"EXE", # flake8-executable //DISABLED: pre-commit shebang rules instead//
"F", # pyflakes
"FA", # flake8-future-annotations
#"FBT", # flake8-boolean-trap //DISABLED: debatable and sometimes unavoidable//
#"FIX", # flake8-fix*me //DISABLED: bans TO*DO, etc. and not configurable//
"FLY", # flynt (https://pypi.org/project/flynt/; updates .format)
"FURB", # refurb (misc., mostly fixable)
#"E", # flake8 errors //DISABLED: handled by formatter or nitpicky//
"G", # flake8-logging-format
#"I", # isort //DISABLED: handled by formatter//
#"ICN", # flake8-import-conventionals //DISABLED: handled by formatter//
"INP", # flake8-no-pep420 (require __init__.py to import)
"INT", # flake8-gettext (i18n)
"ISC", # flake8-implicit-str-concat
"LOG", # flake8-logging
"N", # pep8-naming
#"NPY", # numpy-specific rules //DISABLED: enable if using numpy//
#"PD", # pandas-vet //DISABLED: enable if using pandas//
"PERF", # perflint
"PGH", # pygrep-hooks
"PIE", # flake8-pie (misc. lint rules)
"PL", # pylint
"PT", # flake8-pytest-style
"PTH", # flake8-use-pathlib
#"PYI", # flake8-pyi (rules for stub files) //DISABLED: auto-generate stub files//
#"Q", # flake8-quotes //DISABLED: handled by formatter//
#"RSE", # flake8-raise //DISABLED: handled by formatter//
"RET", # flake8-return (fixable)
"RUF", # Ruff-specific tests
"S", # bandit
"SIM", # flake8-simplify
"SLF", # flake8-self (private access)
"SLOT", # flake8-slots
"T10", # flake8-debugger (bans debugger)
"T20", # flake8-print (bands print and pprint)
"TD", # flake8-to*do (mandates syntax; note: use 'to-do' in prose)
"TCH", # flake8-type-checking
"TID", # flake8-tidy-imports (bans relative imports)
"TRY", # tryceratops (try-except-raise)
"UP", # pyupgrade
#"W", # warnings //DISABLED: most fixed by formatter//
"W60", # E605 invalid escape character
"YTT", # flake8-2020 (incorrect Python vr checks)
"RUF", # Ruff-specific rules
]
#
# ------------------------ Ruff ignored rules ----------------------
ignore = [
"COM812", # contradicts Ruff formatter
"D107", # missing docstring in __init__ (put in class docstring)
"D212", # multi-line docstring start (contradictory)
"E203", # clons with space before (sometimes useful expand)
"E225", # missing whitespace around operator (sometimes useful to condense)
"E501", # line > 79 chars (we use Ruff's formatter)
"INP001", # missing __init__ -- false positives
"ISC001", # contradicts Ruff formatter
"PLR0912", # too many branches
"PLR1711", # return None at end
"PLR0916", # too many boolean expressions
"PLR2044", # line with empty comment
"PLR6301", # 'self' not used -- correct for overrides etc.; and required in
]
#
# ------------------------ Ruff unfixable rules ---------------------
unfixable = [
"F601", # repeated key in dict {}
"F602", # repeated key in dict()
"F811", # unused and redefined
"F841", # unused variable
"PGH004", # blanketed noqa
"PLE2510", # invalid unescaped characters
"RUF100", # unused noqa
"SIM112", # uncapitalized env var
"TD006", # 'to*do' -> 'TO*DO'
"W605", # invalid escape sequence
]
#
# ----------------------- Ruff delegated options --------------------
flake8-bandit.check-typed-exception = true
pydocstyle.convention = "google"
flake8-tidy-imports.ban-relative-imports = "all"
[tool.ruff.lint.pylint]
max-nested-blocks = 3 # default is 5
#
# ------------------------ Ruff per-file ignores --------------------
[tool.ruff.lint.per-file-ignores]
"tests/**/*" = [
"INP001", # missing __init__
"PLR2004", # magic value
"S101", # assert
"TID252", # relative import
"S105", # possible password
"S106",
"S107",
"S108", # harcoded temp file
]
#
#########################################################################################
# [tool.pytest]
#########################################################################################
# A future version of pytest will create [tool.pytest]
[tool.pytest.ini_options]
# show log output from the tests
# in the tests/ code, name the logger {pkg}-TEST to differentiate
log_cli = true
log_cli_level = "INFO"
log_cli_format = "%(asctime)s [%(levelname)8s] %(name)s: %(message)s (%(filename)s:%(lineno)s)"
log_cli_date_format = "%Y-%m-%d %H:%M:%S"
doctest_optionflags = [
"DONT_ACCEPT_TRUE_FOR_1", # 1 is not the same as True
"NORMALIZE_WHITESPACE", # allows us to wrap expected output to 120 lines (ignores newlines)
]
# create markers so we can disable internet (or network-connected), or very slow tests
markers = [
#"integration: marks integration tests (deselect with `-m 'not integration'`)",
"slow: marks tests that take a long time to run (select with `-m slow`)",
"net: marks tests that require internet access (select with `-m net`)",
"ux: marks tests that require manual input such as in-browser (select with `-m ux`)",
]
pythonpath = "./src" # critical!
# coverage stops recursing after it finds one dir without an __init__.py
# so if it finds src/java-app before src/pyapp, it won't find pyapp
# So specify exactly which directories to test
# :tyranno: addopts = """
# :tyranno: --cov=src/${project.name}
addopts = """
--cov=src/cicd \
--cov-report json:.coverage.json \
--cov-report term \
--cov-config=pyproject.toml \
--random-order \
--doctest-modules \
--strict-markers \
-m 'not (slow or net or ux)' \
tests/
"""
#
#########################################################################################
# [tool.coverage]
#########################################################################################
[tool.coverage.run]
data_file = ".coverage.json"
branch = true # quantify % coverage of execution branches
parallel = true # note that pytest-cov overrides this
# :tyranno: source_pkgs = ["${project.name}"]
source_pkgs = ["cicd"]
omit = ["src/**/__main__.py"]
[tool.coverage.paths]
source = ["src/"]
[tool.coverage.report]
fail_under = 50 # 50% coverage required
precision = 1 # n decimal points for coverage %
show_missing = true
exclude_lines = [
"nocov",
"pragma: no cover",
"def __repr__",
"def __str__",
"raise AssertionError",
"raise NotImplementedError",
"if __name__ == \"__main__\":",
"if TYPE_CHECKING:",
"if typing.TYPE_CHECKING:",
]
#
#########################################################################################
# [tool.mypy]
#########################################################################################
[tool.mypy]
files = ["src/**/*.py", "tests/**/*.py"]
# strictness options
disallow_any_generics = true
disallow_subclassing_any = true
disallow_untyped_defs = true
warn_redundant_casts = true
warn_no_return = true
warn_return_any = true
# misc. options
# warn if an unreachable execution branch is found
warn_unreachable = true
# warn if a `# type: ignore` is unnecessary
warn_unused_ignores = true
# no testing 'abc' == 123
strict_equality = true
# formatting output options
pretty = true
show_column_numbers = true
show_error_code_links = true
#
#########################################################################################
# [tool.tyranno]
#########################################################################################
[tool.tyranno]
# Note: All trash globs are automatically excluded from targets.
# So, e.g., .py files in cache dirs are never synced.
target-globs = [
"**/*.yaml",
"**/*.toml",
"**/*.md",
"**/Dockerfile",
"**/*.py",
"**/*.ts",
"**/*.js",
"**/*.css",
"**/*.less",
]
trash-globs = [
"**/*~",
"**/*.bak",
"**/*[.~]t[e]mp",
"**/*.class",
"**/*.py[codi]",
"**/.*_cache",
"**/__pycache__",
"**/cython_debug",
"build/",
".coverage.json",
]
#
#================================ Tyranno data ===============================#
#
# You can add any key-value pairs you want here;
# they're only referenced by 'tyranno' sync comments.
# No keys here have specific meanings.
[tool.tyranno.data]
vendor = "dmyersturnbull"
frag = "${.vendor}/${project.name}"
copyright = "Copyright ${now_utc().year}, Contributors to ${project.name}"
doi = "10.5281/zenodo.4485186" # <<<comment out for new
# This is the version used in CD and some CI
default-python-version = "3.13.1"
# These are the versions to test in CI:
python-versions = ["3.13.1"]