btclib-node 2026.8.27__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- btclib_node-2026.8.27/.markdownlint.jsonc +60 -0
- btclib_node-2026.8.27/.pre-commit-config.yaml +469 -0
- btclib_node-2026.8.27/.python-version +22 -0
- btclib_node-2026.8.27/.readthedocs.yaml +58 -0
- btclib_node-2026.8.27/.secrets.baseline +160 -0
- btclib_node-2026.8.27/.taplo.toml +27 -0
- btclib_node-2026.8.27/.yamllint.yaml +76 -0
- btclib_node-2026.8.27/AUTHORS.md +5 -0
- btclib_node-2026.8.27/CHANGELOG.md +4978 -0
- btclib_node-2026.8.27/CLAUDE.md +339 -0
- btclib_node-2026.8.27/CONTRIBUTING.md +392 -0
- btclib_node-2026.8.27/LICENSE +21 -0
- btclib_node-2026.8.27/PKG-INFO +114 -0
- btclib_node-2026.8.27/README.md +81 -0
- btclib_node-2026.8.27/RELEASE_NOTES.md +47 -0
- btclib_node-2026.8.27/RELEASING.md +518 -0
- btclib_node-2026.8.27/REPOSITORY.md +423 -0
- btclib_node-2026.8.27/REVIEWING.md +507 -0
- btclib_node-2026.8.27/SECURITY.md +85 -0
- btclib_node-2026.8.27/docs/source/btclib_node.block_db.rst +9 -0
- btclib_node-2026.8.27/docs/source/btclib_node.chainstate.rst +40 -0
- btclib_node-2026.8.27/docs/source/btclib_node.p2p.messages.rst +19 -0
- btclib_node-2026.8.27/docs/source/btclib_node.p2p.rst +62 -0
- btclib_node-2026.8.27/docs/source/btclib_node.rpc.rst +47 -0
- btclib_node-2026.8.27/docs/source/btclib_node.rst +93 -0
- btclib_node-2026.8.27/docs/source/changelog_link.md +4 -0
- btclib_node-2026.8.27/docs/source/conf.py +296 -0
- btclib_node-2026.8.27/docs/source/contributing_link.md +6 -0
- btclib_node-2026.8.27/docs/source/index.rst +22 -0
- btclib_node-2026.8.27/docs/source/modules.rst +7 -0
- btclib_node-2026.8.27/docs/source/readme_link.md +6 -0
- btclib_node-2026.8.27/docs/source/release_notes_link.md +6 -0
- btclib_node-2026.8.27/docs/source/reviewing_link.md +6 -0
- btclib_node-2026.8.27/docs/source/security_link.md +6 -0
- btclib_node-2026.8.27/pyproject.toml +282 -0
- btclib_node-2026.8.27/pyproject.toml.orig +960 -0
- btclib_node-2026.8.27/scripts/chains/mainnet.py +35 -0
- btclib_node-2026.8.27/scripts/chains/signet.py +30 -0
- btclib_node-2026.8.27/scripts/chains/testnet.py +30 -0
- btclib_node-2026.8.27/scripts/prune.py +27 -0
- btclib_node-2026.8.27/scripts/reset_chainstate.py +37 -0
- btclib_node-2026.8.27/scripts/reset_download.py +46 -0
- btclib_node-2026.8.27/scripts/test_errors.py +59 -0
- btclib_node-2026.8.27/scripts/testnet_test.py +26 -0
- btclib_node-2026.8.27/src/btclib_node/__init__.py +555 -0
- btclib_node-2026.8.27/src/btclib_node/block_db/__init__.py +385 -0
- btclib_node-2026.8.27/src/btclib_node/chains.py +269 -0
- btclib_node-2026.8.27/src/btclib_node/chainstate/__init__.py +59 -0
- btclib_node-2026.8.27/src/btclib_node/chainstate/block_index.py +722 -0
- btclib_node-2026.8.27/src/btclib_node/chainstate/contextual.py +190 -0
- btclib_node-2026.8.27/src/btclib_node/chainstate/filter_index.py +199 -0
- btclib_node-2026.8.27/src/btclib_node/chainstate/utxo_index.py +142 -0
- btclib_node-2026.8.27/src/btclib_node/config.py +147 -0
- btclib_node-2026.8.27/src/btclib_node/constants.py +40 -0
- btclib_node-2026.8.27/src/btclib_node/db.py +190 -0
- btclib_node-2026.8.27/src/btclib_node/download.py +695 -0
- btclib_node-2026.8.27/src/btclib_node/exceptions.py +219 -0
- btclib_node-2026.8.27/src/btclib_node/interpreter.py +164 -0
- btclib_node-2026.8.27/src/btclib_node/log.py +48 -0
- btclib_node-2026.8.27/src/btclib_node/main.py +387 -0
- btclib_node-2026.8.27/src/btclib_node/mempool.py +574 -0
- btclib_node-2026.8.27/src/btclib_node/p2p/__init__.py +15 -0
- btclib_node-2026.8.27/src/btclib_node/p2p/address.py +599 -0
- btclib_node-2026.8.27/src/btclib_node/p2p/callbacks.py +1178 -0
- btclib_node-2026.8.27/src/btclib_node/p2p/connection.py +870 -0
- btclib_node-2026.8.27/src/btclib_node/p2p/filter_size.py +41 -0
- btclib_node-2026.8.27/src/btclib_node/p2p/main.py +242 -0
- btclib_node-2026.8.27/src/btclib_node/p2p/manager.py +833 -0
- btclib_node-2026.8.27/src/btclib_node/p2p/messages/__init__.py +18 -0
- btclib_node-2026.8.27/src/btclib_node/p2p/messages/errors.py +143 -0
- btclib_node-2026.8.27/src/btclib_node/py.typed +0 -0
- btclib_node-2026.8.27/src/btclib_node/rpc/__init__.py +15 -0
- btclib_node-2026.8.27/src/btclib_node/rpc/callbacks.py +837 -0
- btclib_node-2026.8.27/src/btclib_node/rpc/connection.py +382 -0
- btclib_node-2026.8.27/src/btclib_node/rpc/errors.py +166 -0
- btclib_node-2026.8.27/src/btclib_node/rpc/main.py +121 -0
- btclib_node-2026.8.27/src/btclib_node/rpc/manager.py +347 -0
- btclib_node-2026.8.27/tests/README.md +26 -0
- btclib_node-2026.8.27/tests/__init__.py +444 -0
- btclib_node-2026.8.27/tests/_data/README.md +99 -0
- btclib_node-2026.8.27/tests/conftest.py +212 -0
- btclib_node-2026.8.27/tests/functional/__init__.py +12 -0
- btclib_node-2026.8.27/tests/functional/p2p/__init__.py +11 -0
- btclib_node-2026.8.27/tests/functional/p2p/backpressure_test.py +330 -0
- btclib_node-2026.8.27/tests/functional/p2p/block_filters_test.py +335 -0
- btclib_node-2026.8.27/tests/functional/p2p/download_test.py +110 -0
- btclib_node-2026.8.27/tests/functional/p2p/handshake_test.py +96 -0
- btclib_node-2026.8.27/tests/functional/p2p/init_test.py +50 -0
- btclib_node-2026.8.27/tests/functional/p2p/ping_test.py +137 -0
- btclib_node-2026.8.27/tests/functional/p2p/tx_test.py +115 -0
- btclib_node-2026.8.27/tests/functional/rpc/__init__.py +10 -0
- btclib_node-2026.8.27/tests/functional/rpc/chain_test.py +268 -0
- btclib_node-2026.8.27/tests/functional/rpc/connections_test.py +74 -0
- btclib_node-2026.8.27/tests/functional/rpc/errors_test.py +234 -0
- btclib_node-2026.8.27/tests/functional/rpc/init_test.py +129 -0
- btclib_node-2026.8.27/tests/functional/rpc/peers_test.py +199 -0
- btclib_node-2026.8.27/tests/functional/rpc/tx_test.py +246 -0
- btclib_node-2026.8.27/tests/integration/__init__.py +18 -0
- btclib_node-2026.8.27/tests/integration/backpressure_test.py +227 -0
- btclib_node-2026.8.27/tests/integration/bitcoind_test.py +68 -0
- btclib_node-2026.8.27/tests/integration/conftest.py +150 -0
- btclib_node-2026.8.27/tests/integration/reorg_test.py +330 -0
- btclib_node-2026.8.27/tests/interpreters_test.py +178 -0
- btclib_node-2026.8.27/tests/unit/__init__.py +11 -0
- btclib_node-2026.8.27/tests/unit/all_test.py +216 -0
- btclib_node-2026.8.27/tests/unit/block_db_test.py +448 -0
- btclib_node-2026.8.27/tests/unit/chains_test.py +117 -0
- btclib_node-2026.8.27/tests/unit/chainstate/__init__.py +10 -0
- btclib_node-2026.8.27/tests/unit/chainstate/_data/blockfilters.json +13 -0
- btclib_node-2026.8.27/tests/unit/chainstate/_data/testnet_bip158_vectors.json +5 -0
- btclib_node-2026.8.27/tests/unit/chainstate/block_index_test.py +1090 -0
- btclib_node-2026.8.27/tests/unit/chainstate/contextual_test.py +325 -0
- btclib_node-2026.8.27/tests/unit/chainstate/filter_index_test.py +715 -0
- btclib_node-2026.8.27/tests/unit/chainstate/init_test.py +19 -0
- btclib_node-2026.8.27/tests/unit/chainstate/utxo_index_test.py +232 -0
- btclib_node-2026.8.27/tests/unit/config_test.py +84 -0
- btclib_node-2026.8.27/tests/unit/conventions_test.py +183 -0
- btclib_node-2026.8.27/tests/unit/coverage_floor_test.py +227 -0
- btclib_node-2026.8.27/tests/unit/db_test.py +348 -0
- btclib_node-2026.8.27/tests/unit/docs_test.py +209 -0
- btclib_node-2026.8.27/tests/unit/download_test.py +1021 -0
- btclib_node-2026.8.27/tests/unit/harness_test.py +34 -0
- btclib_node-2026.8.27/tests/unit/helpers_test.py +220 -0
- btclib_node-2026.8.27/tests/unit/init_test.py +978 -0
- btclib_node-2026.8.27/tests/unit/interpreter_test.py +354 -0
- btclib_node-2026.8.27/tests/unit/log_test.py +45 -0
- btclib_node-2026.8.27/tests/unit/main_test.py +746 -0
- btclib_node-2026.8.27/tests/unit/mempool_test.py +694 -0
- btclib_node-2026.8.27/tests/unit/p2p/__init__.py +11 -0
- btclib_node-2026.8.27/tests/unit/p2p/address_test.py +1092 -0
- btclib_node-2026.8.27/tests/unit/p2p/callbacks_test.py +2605 -0
- btclib_node-2026.8.27/tests/unit/p2p/connection_test.py +1115 -0
- btclib_node-2026.8.27/tests/unit/p2p/main_test.py +765 -0
- btclib_node-2026.8.27/tests/unit/p2p/manager_test.py +1747 -0
- btclib_node-2026.8.27/tests/unit/p2p/messages/__init__.py +12 -0
- btclib_node-2026.8.27/tests/unit/p2p/messages/errors_test.py +128 -0
- btclib_node-2026.8.27/tests/unit/p2p/messages/init_test.py +401 -0
- btclib_node-2026.8.27/tests/unit/rpc/__init__.py +10 -0
- btclib_node-2026.8.27/tests/unit/rpc/callbacks_test.py +1548 -0
- btclib_node-2026.8.27/tests/unit/rpc/connection_test.py +477 -0
- btclib_node-2026.8.27/tests/unit/rpc/main_test.py +253 -0
- btclib_node-2026.8.27/tests/unit/rpc/manager_test.py +560 -0
- btclib_node-2026.8.27/uv.lock +2131 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
// rules https://github.com/DavidAnson/markdownlint
|
|
3
|
+
|
|
4
|
+
// See https://github.com/DavidAnson/markdownlint-cli2 and
|
|
5
|
+
// https://github.com/DavidAnson/markdownlint/blob/main/schema/.markdownlint.jsonc
|
|
6
|
+
|
|
7
|
+
// To locally disable a single error, e.g. MD013:
|
|
8
|
+
// <!-- markdownlint-disable MD013 -->
|
|
9
|
+
// and after the offending block
|
|
10
|
+
// <!-- markdownlint-enable MD013 -->
|
|
11
|
+
|
|
12
|
+
// This file is the same in btclib, btclib-secp256k1 and
|
|
13
|
+
// bitcoin-core-rpc, deliberately: prose moves between the three, and a
|
|
14
|
+
// paragraph that lints in one has to lint in the others. No rule is
|
|
15
|
+
// disabled here -- what follows only names a style where markdownlint's
|
|
16
|
+
// default is "consistent", which asks each file to agree with itself and
|
|
17
|
+
// therefore lets two files disagree. That is what let an indented block
|
|
18
|
+
// pass in one repository and fail in another.
|
|
19
|
+
//
|
|
20
|
+
// A rule that only one file needs is not here: bitcoin-core-rpc's
|
|
21
|
+
// CHANGELOG.md repeats "### Added" under every release, which is what
|
|
22
|
+
// MD024 exists to catch and what its own `siblings_only` setting is for
|
|
23
|
+
// -- but the other files, in every repository, have no such repeat, and
|
|
24
|
+
// a per-file exception belongs in that file's own
|
|
25
|
+
// `markdownlint-configure-file` comment rather than in a shared config
|
|
26
|
+
// read by files that never trip the rule it relaxes.
|
|
27
|
+
|
|
28
|
+
// MD003/heading-style - ATX, the "## Heading" spelling, everywhere
|
|
29
|
+
"MD003": { "style": "atx" },
|
|
30
|
+
|
|
31
|
+
// MD004/ul-style - a dash, which is what every list here already uses
|
|
32
|
+
"MD004": { "style": "dash" },
|
|
33
|
+
|
|
34
|
+
// MD007/ul-indent - Unordered list indentation
|
|
35
|
+
"MD007": {
|
|
36
|
+
// Spaces for indent
|
|
37
|
+
"indent": 4,
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
// MD029/ol-prefix - every item numbered "1.", the renderer numbering
|
|
41
|
+
// them: inserting a step into a release procedure then touches one line
|
|
42
|
+
// rather than renumbering every line below it
|
|
43
|
+
"MD029": { "style": "one" },
|
|
44
|
+
|
|
45
|
+
// MD035/hr-style - one spelling of the thematic break
|
|
46
|
+
"MD035": { "style": "---" },
|
|
47
|
+
|
|
48
|
+
// MD046/code-block-style - fenced, so a block can say which language it
|
|
49
|
+
// is in and the renderer can highlight it; an indented block cannot
|
|
50
|
+
"MD046": { "style": "fenced" },
|
|
51
|
+
|
|
52
|
+
// MD048/code-fence-style - backticks, tildes being for fencing a block
|
|
53
|
+
// that itself contains backticks, which nothing here does
|
|
54
|
+
"MD048": { "style": "backtick" },
|
|
55
|
+
|
|
56
|
+
// MD049/MD050 - asterisks for both, so that *emphasis* and **strong**
|
|
57
|
+
// are told apart by how many rather than by which character
|
|
58
|
+
"MD049": { "style": "asterisk" },
|
|
59
|
+
"MD050": { "style": "asterisk" },
|
|
60
|
+
}
|
|
@@ -0,0 +1,469 @@
|
|
|
1
|
+
---
|
|
2
|
+
# Skip execution of one or more hooks using the SKIP environment variable:
|
|
3
|
+
# $ SKIP=mypy git commit -m "foo"
|
|
4
|
+
# $ SKIP=mypy,ruff-check pre-commit run --all-files
|
|
5
|
+
#
|
|
6
|
+
# If want to disable all hooks while committing, use the --no-verify/-n option:
|
|
7
|
+
# $ git commit -n -m "foo"
|
|
8
|
+
|
|
9
|
+
# these hooks are the lint gate: the lint workflow will run this very
|
|
10
|
+
# file once btclib-org/.github#9's workflow step lands, so what CI
|
|
11
|
+
# enforces will be exactly what a commit enforces, with no second list
|
|
12
|
+
# of tools and versions to keep in step. What pre-commit.ci provides in
|
|
13
|
+
# the meantime is the periodic pull request bumping the revisions
|
|
14
|
+
# pinned below
|
|
15
|
+
ci:
|
|
16
|
+
# a bot committing to a branch is at odds with a setup where a
|
|
17
|
+
# failing hook is fixed by its author
|
|
18
|
+
autofix_prs: false
|
|
19
|
+
# no autoupdate_branch, as dependabot declares no target-branch: the
|
|
20
|
+
# default is the default branch, which is the only branch a change
|
|
21
|
+
# lands on
|
|
22
|
+
autoupdate_commit_msg: "Update the pinned pre-commit hook revisions"
|
|
23
|
+
autoupdate_schedule: weekly
|
|
24
|
+
# the hook pre-commit.ci cannot run: it shells out to uv, which is not
|
|
25
|
+
# installed there. Not a gap in the gate, and only because
|
|
26
|
+
# .github/workflows/lint.yml now exists to run this very file with the
|
|
27
|
+
# same command a developer runs -- before it, a skipped hook here was a
|
|
28
|
+
# hook nothing ran at all, this repository having had no workflow but
|
|
29
|
+
# the review one (issue #33). What pre-commit.ci is kept for is the
|
|
30
|
+
# pull request above, bumping the revisions pinned below, and a local
|
|
31
|
+
# hook has no revision to bump: uv.lock moves its mypy instead
|
|
32
|
+
skip: [mypy]
|
|
33
|
+
|
|
34
|
+
repos:
|
|
35
|
+
# this file checking itself, and the only two hooks here with no
|
|
36
|
+
# environment to install. A `files` or `exclude` pattern that stops
|
|
37
|
+
# matching anything is a hook that has quietly stopped running: the
|
|
38
|
+
# rule is still written down and no longer enforced, which is the one
|
|
39
|
+
# defect a green run cannot report on itself
|
|
40
|
+
- repo: meta
|
|
41
|
+
hooks:
|
|
42
|
+
- id: check-hooks-apply
|
|
43
|
+
- id: check-useless-excludes
|
|
44
|
+
# this file checking itself further, on the two moves `autoupdate`
|
|
45
|
+
# makes that it must not take. A rev naming only a major version
|
|
46
|
+
# follows every future release of that major, which is the one thing
|
|
47
|
+
# a rev is here to prevent -- and a prerelease is not a release.
|
|
48
|
+
# A commit SHA stays acceptable, should a hook ever want one: the
|
|
49
|
+
# pattern requires the prerelease marker and its digits to end the
|
|
50
|
+
# value, which forty hex characters do not
|
|
51
|
+
- repo: local
|
|
52
|
+
hooks:
|
|
53
|
+
- id: pinned-rev
|
|
54
|
+
name: every pre-commit rev names a released version
|
|
55
|
+
language: pygrep
|
|
56
|
+
entry: '^ *rev: "?v?([0-9]+|[0-9][0-9.]*(a|b|rc|dev)[0-9]+)"?$'
|
|
57
|
+
files: ^\.pre-commit-config\.yaml$
|
|
58
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
59
|
+
rev: v6.0.0
|
|
60
|
+
hooks:
|
|
61
|
+
- id: trailing-whitespace
|
|
62
|
+
- id: end-of-file-fixer
|
|
63
|
+
- id: mixed-line-ending
|
|
64
|
+
# not the default --fix=auto, which normalizes a file to its own
|
|
65
|
+
# most frequent ending: a file entirely in CRLF is consistent by
|
|
66
|
+
# that measure, so it stays, and the LF lines added to it are
|
|
67
|
+
# converted the wrong way. This repository is LF throughout
|
|
68
|
+
args: [--fix=lf]
|
|
69
|
+
- id: check-case-conflict
|
|
70
|
+
# scripts/ has no shebang or executable bit today, and this hook
|
|
71
|
+
# is the pair that keeps it that way: it matches every text file,
|
|
72
|
+
# so the day one of them gains a shebang without chmod +x, or the
|
|
73
|
+
# reverse, one of the two catches it
|
|
74
|
+
- id: check-shebang-scripts-are-executable
|
|
75
|
+
- id: fix-byte-order-marker
|
|
76
|
+
- id: check-yaml
|
|
77
|
+
- id: check-json
|
|
78
|
+
# `.vscode` is jsonc and not json: VSCode reads a comment in its
|
|
79
|
+
# own settings.json and extensions.json, and what those two files
|
|
80
|
+
# carry besides the settings is the reason for each of them. A json
|
|
81
|
+
# parser rejects the file at the first one. It is not a gap:
|
|
82
|
+
# prettier below is given that directory and fails on what it
|
|
83
|
+
# cannot parse, which is the question this hook asks
|
|
84
|
+
exclude: ^\.vscode/
|
|
85
|
+
- id: pretty-format-json
|
|
86
|
+
name: pretty-format-json (in place fixes)
|
|
87
|
+
args: [--autofix]
|
|
88
|
+
# Two directories, for two different reasons.
|
|
89
|
+
# `.vscode`, for the reason check-json above is given the same
|
|
90
|
+
# exclude: those files are jsonc, this hook parses json, and
|
|
91
|
+
# prettier below is what formats them instead -- at its own indent,
|
|
92
|
+
# which is not this hook's and does not have to be, no other tool
|
|
93
|
+
# reading them.
|
|
94
|
+
# tests/**/_data/ is the vendored directory, as tests/_data/
|
|
95
|
+
# README.md declares it: what is in there is upstream's file byte
|
|
96
|
+
# for byte, pinned by a git blob sha, and a reformat voids the pin
|
|
97
|
+
# and the verdict together -- silently, this hook correcting
|
|
98
|
+
# rather than reporting. Excluded by directory rather than by name
|
|
99
|
+
# so that the next file vendored into it is safe before anyone
|
|
100
|
+
# remembers this line; check-json above still asks the question
|
|
101
|
+
# worth asking of them, which is whether they parse.
|
|
102
|
+
exclude: ^(\.vscode/|tests/(.*/)?_data/)
|
|
103
|
+
- id: check-merge-conflict
|
|
104
|
+
- id: check-vcs-permalinks
|
|
105
|
+
- id: detect-private-key
|
|
106
|
+
- id: debug-statements
|
|
107
|
+
- id: check-docstring-first
|
|
108
|
+
# default args, so the pattern it enforces is `*_test.py`, which
|
|
109
|
+
# every test module under tests/ is named. The hook's own
|
|
110
|
+
# exception list is `__init__.py` and `conftest.py`, which is
|
|
111
|
+
# where this suite's shared code lives -- section 7 of the
|
|
112
|
+
# organization standard puts it in a package `__init__.py` rather
|
|
113
|
+
# than in a module whose name says "test" and holds none, so the
|
|
114
|
+
# hook reads every file under tests/ with no exclude of its own
|
|
115
|
+
- id: name-tests-test
|
|
116
|
+
- id: check-toml
|
|
117
|
+
# only files being *added* are measured, the hook intersecting its
|
|
118
|
+
# arguments with git's added set
|
|
119
|
+
- id: check-added-large-files
|
|
120
|
+
# there are none, and a submodule is the one dependency that would
|
|
121
|
+
# not be in uv.lock, not be pinned by dependabot, and not be
|
|
122
|
+
# visible in an sdist
|
|
123
|
+
- id: forbid-submodules
|
|
124
|
+
# the credentials of other systems, which is the half of secret
|
|
125
|
+
# scanning GitHub's free plan does not cover. detect-private-key above
|
|
126
|
+
# covers the PEM case.
|
|
127
|
+
# Not gitleaks: all of its hook ids invoke it with --staged, so under
|
|
128
|
+
# "pre-commit run --all-files" it scans an empty staged set and passes
|
|
129
|
+
- repo: https://github.com/Yelp/detect-secrets
|
|
130
|
+
rev: v1.5.0
|
|
131
|
+
hooks:
|
|
132
|
+
- id: detect-secrets
|
|
133
|
+
name: detect-secrets (credentials of other systems)
|
|
134
|
+
# findings are recorded in .secrets.baseline as already reviewed
|
|
135
|
+
# rather than excluded from the scan: an exclusion makes a file
|
|
136
|
+
# blind for good, where a baseline entry is a finding somebody
|
|
137
|
+
# has read.
|
|
138
|
+
# The baseline was generated with the two entropy plugins off
|
|
139
|
+
# (--disable-plugin Base64HighEntropyString --disable-plugin
|
|
140
|
+
# HexHighEntropyString): with them on, the scan's only findings
|
|
141
|
+
# are the four hex genesis-block constants in chains.py and its
|
|
142
|
+
# test, and a new protocol constant is exactly what a legitimate
|
|
143
|
+
# addition looks like here -- the plugins would flag every one
|
|
144
|
+
# of them and nothing else, forever
|
|
145
|
+
args: [--baseline, .secrets.baseline]
|
|
146
|
+
# a typo in a comment is cosmetic; the same typo in the README is the
|
|
147
|
+
# shop window, and in an exception message it is an interface.
|
|
148
|
+
# Configured in pyproject.toml ([tool.codespell]) rather than in args
|
|
149
|
+
# here: the skip list needs a paragraph of justification, and a hook
|
|
150
|
+
# invocation is the wrong place for one
|
|
151
|
+
- repo: https://github.com/codespell-project/codespell
|
|
152
|
+
rev: v2.4.3
|
|
153
|
+
hooks:
|
|
154
|
+
- id: codespell
|
|
155
|
+
name: codespell (prose and comments, in place fixes)
|
|
156
|
+
# codespell only reads [tool.codespell] when told where to look;
|
|
157
|
+
# without this it neither applies `builtin = "clear"` nor
|
|
158
|
+
# `ignore-words-list`, and reports on its own unconfigured
|
|
159
|
+
# default instead
|
|
160
|
+
args: [--toml, pyproject.toml, --write-changes]
|
|
161
|
+
# --toml is read through tomllib, which is 3.11 and later; the
|
|
162
|
+
# interpreter pre-commit builds this hook's environment with is
|
|
163
|
+
# its own choice and not this project's requires-python, so the
|
|
164
|
+
# backport is declared unconditionally rather than reasoned about
|
|
165
|
+
additional_dependencies: [tomli]
|
|
166
|
+
# the second spell checker, and not a replacement for the one above:
|
|
167
|
+
# codespell matches whole words and keeps the hyphen inside the token,
|
|
168
|
+
# where typos splits hyphens, snake_case and camelCase
|
|
169
|
+
# crate-ci/typos re-tags a moving `v1` alias onto the same commit
|
|
170
|
+
# as each release, and `git describe --tags` breaks the tie between
|
|
171
|
+
# two tags on one commit by creation date, which names the alias.
|
|
172
|
+
# `autoupdate` proposes that alias on every run and `pinned-rev` above
|
|
173
|
+
# refuses it on every run, so the pin stays stuck rather than moving.
|
|
174
|
+
# `autoupdate` walks every `repo:` entry except `local` and `meta`, so
|
|
175
|
+
# a local hook is the one shape it cannot reach; `additional_dependencies`
|
|
176
|
+
# below carries the version pin in its place, and `language`, `entry`,
|
|
177
|
+
# `args` and `types` are upstream's own typos hook definition, copied
|
|
178
|
+
# in rather than fetched
|
|
179
|
+
- repo: local
|
|
180
|
+
hooks:
|
|
181
|
+
- id: typos
|
|
182
|
+
name: typos
|
|
183
|
+
language: python
|
|
184
|
+
additional_dependencies: [typos==1.49.0]
|
|
185
|
+
entry: typos
|
|
186
|
+
args: [--write-changes, --force-exclude]
|
|
187
|
+
types: [text]
|
|
188
|
+
stages: [pre-commit, pre-merge-commit, pre-push, manual]
|
|
189
|
+
- repo: https://github.com/DavidAnson/markdownlint-cli2
|
|
190
|
+
rev: v0.23.2
|
|
191
|
+
hooks:
|
|
192
|
+
- id: markdownlint-cli2
|
|
193
|
+
name: markdownlint-cli2 (in place fixes)
|
|
194
|
+
args: [--fix]
|
|
195
|
+
# how a link destination is spelled, which markdownlint has no rule for
|
|
196
|
+
# and the documentation build depends on. docs.yml greps the built html
|
|
197
|
+
# for `href="#./`: that is what myst renders in place of a link the
|
|
198
|
+
# RootFileLinks transform in docs/source/conf.py cannot resolve -- an
|
|
199
|
+
# anchor to an id no page has, which -W reports today and would stop
|
|
200
|
+
# reporting the day suppress_warnings took myst.xref_missing back. A
|
|
201
|
+
# grep can key on one spelling, so the destinations are spelled one way
|
|
202
|
+
# and this hook is what keeps them that way, in the commit that writes
|
|
203
|
+
# the link rather than in the artifact built from it.
|
|
204
|
+
#
|
|
205
|
+
# The rule is the prefix and not the extension, and the table in
|
|
206
|
+
# btclib-org/btclib#1175 is what decides that: "DOES_NOT_EXIST.txt",
|
|
207
|
+
# "sub/DOES_NOT_EXIST.md", "DOES_NOT_EXIST" and "../DOES_NOT_EXIST.md"
|
|
208
|
+
# each reach myst's fallback, and each is missed by the union of both
|
|
209
|
+
# greps a repository ran. An ".md"-scoped rule leaves all four
|
|
210
|
+
# writable. Measured on this tree by building docs/source with each of
|
|
211
|
+
# the four appended to CONTRIBUTING.md (already included by
|
|
212
|
+
# contributing_link.md): every one renders "#" followed by the bare
|
|
213
|
+
# destination -- "#DOES_NOT_EXIST.md", "#sub/DOES_NOT_EXIST.md",
|
|
214
|
+
# "#DOES_NOT_EXIST", "#../DOES_NOT_EXIST.md" -- none of them the
|
|
215
|
+
# "#./" prefix docs.yml's own grep looks for, and none reachable by
|
|
216
|
+
# widening that grep either: an autodoc anchor renders the identical
|
|
217
|
+
# shape, "#btclib_node.chains.Chain" among them.
|
|
218
|
+
#
|
|
219
|
+
# This tree carries no badge link today (`grep -rn '!\[' *.md` answers
|
|
220
|
+
# nothing), so the badge case the pattern below also has to survive is
|
|
221
|
+
# untested evidence here rather than measured; the pattern itself is
|
|
222
|
+
# the organization's own (btclib-org/.github#20), read from a sibling
|
|
223
|
+
# that does carry one.
|
|
224
|
+
#
|
|
225
|
+
# "../" is the row with nothing downstream behind it at all, which is
|
|
226
|
+
# why it is refused here rather than allowed as an ordinary relative
|
|
227
|
+
# path: conf.py's transform declines a target that normalizes above
|
|
228
|
+
# the repository root -- nothing above the root is a document this
|
|
229
|
+
# build can answer for -- so that shape reaches myst's fallback by
|
|
230
|
+
# design rather than by a gap in the transform, and renders
|
|
231
|
+
# href="#../page.md", which the grep in docs.yml does not match and
|
|
232
|
+
# should not be widened to. This hook is the only place it can be
|
|
233
|
+
# caught.
|
|
234
|
+
#
|
|
235
|
+
# pygrep, and the same hook in every repository of this organization
|
|
236
|
+
# (btclib-org/.github#20): there is no shared hook repository to put
|
|
237
|
+
# it in, and pinned-rev above is that arrangement already. The
|
|
238
|
+
# pattern asks for a whole `[text](destination)`, so grep output of
|
|
239
|
+
# the form `FILE.md:21:](x.md)` carries no "[" and is not matched.
|
|
240
|
+
# The lookbehind refuses a "[" preceded by a backtick, which is what
|
|
241
|
+
# lets prose quote the refused shape in a code span -- and refuses
|
|
242
|
+
# one preceded by "!" or "[" as well, so that a *quoted* badge is
|
|
243
|
+
# escaped whole: without those two the scan would re-enter at the
|
|
244
|
+
# image inside it and report the src. The leading "!?" is what keeps
|
|
245
|
+
# a standalone image's own src checked despite that.
|
|
246
|
+
#
|
|
247
|
+
# A reference definition is a link too, and the second branch is for
|
|
248
|
+
# it: "[label]: page.md" renders the same fallback as the inline
|
|
249
|
+
# form, carries no "(", so the first branch cannot see it. That
|
|
250
|
+
# branch is anchored at the start of the line, which is what keeps it
|
|
251
|
+
# off a *use* site such as "[label][ref]: the" appearing in prose. At
|
|
252
|
+
# most three leading spaces, four making the line an indented code
|
|
253
|
+
# block rather than a definition.
|
|
254
|
+
#
|
|
255
|
+
# What pygrep cannot see is a fenced block, being line based -- an
|
|
256
|
+
# example of the refused shape inside one fails this hook, and the
|
|
257
|
+
# code span is the way round it
|
|
258
|
+
- repo: local
|
|
259
|
+
hooks:
|
|
260
|
+
- id: local-link-prefix
|
|
261
|
+
name: a local markdown link destination begins with ./
|
|
262
|
+
language: pygrep
|
|
263
|
+
# one line, and no literal space in it -- "\x20" is the space the
|
|
264
|
+
# reference branch allows -- so yamllint reads the value as a
|
|
265
|
+
# single unbreakable word and its 100-column rule exempts it. A
|
|
266
|
+
# block scalar rather than a quoted one for the same reason a
|
|
267
|
+
# folded scalar was rejected: folding joins lines with a space,
|
|
268
|
+
# which would land inside the regex
|
|
269
|
+
entry: |-
|
|
270
|
+
(?<![`!\[])(?:!?\[(?:[^]]|\]\([^)]*\))*\]\(|^\x20{0,3}\[[^]]+\]:\s*)(?!\./|#|[A-Za-z][A-Za-z0-9+.-]*:)[^)\s]
|
|
271
|
+
types: [markdown]
|
|
272
|
+
# a line that ends inside a word, at that word's own hyphen.
|
|
273
|
+
# Section 4 of the organization standard is the rule: what such a
|
|
274
|
+
# line renders as, why nothing else here catches it, what this
|
|
275
|
+
# pattern cannot see, and what the measurement was before it was
|
|
276
|
+
# proposed
|
|
277
|
+
- id: no-hyphen-at-end-of-line
|
|
278
|
+
name: a word is not wrapped at its own hyphen
|
|
279
|
+
language: pygrep
|
|
280
|
+
entry: "[A-Za-z0-9]-$"
|
|
281
|
+
types: [markdown]
|
|
282
|
+
# what ruff-format is for Python, on the structured files ruff does
|
|
283
|
+
# not read: yaml and the jsonc that carries a comment. Before
|
|
284
|
+
# yamllint below, so the linter judges the formatted file
|
|
285
|
+
- repo: https://github.com/rbubley/mirrors-prettier
|
|
286
|
+
rev: v3.9.6
|
|
287
|
+
hooks:
|
|
288
|
+
- id: prettier
|
|
289
|
+
name: prettier (yaml and jsonc, in place fixes)
|
|
290
|
+
files: ^(.*\.ya?ml|\.vscode/.*\.json|\.markdownlint\.jsonc)$
|
|
291
|
+
# the same for toml, which here is pyproject.toml: .taplo.toml holds
|
|
292
|
+
# the formatting choices and the reasoning for them. uv.lock is toml
|
|
293
|
+
# to identify and therefore matched by the hook's own types, and it
|
|
294
|
+
# is uv's file to write
|
|
295
|
+
- repo: https://github.com/ComPWA/taplo-pre-commit
|
|
296
|
+
rev: v0.9.3
|
|
297
|
+
hooks:
|
|
298
|
+
- id: taplo-format
|
|
299
|
+
name: taplo (toml, in place fixes)
|
|
300
|
+
exclude: ^uv\.lock$
|
|
301
|
+
# the width of a yaml line, which nothing else here measures.
|
|
302
|
+
# Configured in .yamllint.yaml rather than in args here
|
|
303
|
+
# check-only: yamllint has no fix mode, and its own CLI names none
|
|
304
|
+
- repo: https://github.com/adrienverge/yamllint
|
|
305
|
+
rev: v1.38.0
|
|
306
|
+
hooks:
|
|
307
|
+
- id: yamllint
|
|
308
|
+
name: yamllint (line width and document start)
|
|
309
|
+
# .github/dependabot.yml is validated by nothing else here: check-yaml
|
|
310
|
+
# above asks whether it is yaml, and actionlint below reads workflows
|
|
311
|
+
# and not this. A typo in a package-ecosystem, a directory or a day is
|
|
312
|
+
# not an error to GitHub -- it silently updates nothing, and the
|
|
313
|
+
# evidence is a pull request that never arrives, so "it stopped running
|
|
314
|
+
# and said nothing" is exactly the failure to guard against.
|
|
315
|
+
# check-github-workflows is not added beside it: actionlint already
|
|
316
|
+
# reads every workflow and goes further than the schema does, into
|
|
317
|
+
# expressions, contexts and runner labels.
|
|
318
|
+
# .readthedocs.yaml is the same argument again: yaml that check-yaml
|
|
319
|
+
# reads as yaml and nothing reads as a build definition, on a service
|
|
320
|
+
# whose failure mode is a docs build that stops happening
|
|
321
|
+
- repo: https://github.com/python-jsonschema/check-jsonschema
|
|
322
|
+
rev: 0.38.0
|
|
323
|
+
hooks:
|
|
324
|
+
- id: check-dependabot
|
|
325
|
+
- id: check-readthedocs
|
|
326
|
+
# the workflows are yaml with expressions in it, and nothing else here
|
|
327
|
+
# validates them: an unknown key, a typo in a context reference, an
|
|
328
|
+
# action input that does not exist, a job depending on a job that is
|
|
329
|
+
# not there are all things a run would otherwise discover by failing --
|
|
330
|
+
# and these run weekly or on a merge, where a failure is read late.
|
|
331
|
+
# The Python packaging of actionlint rather than the upstream hook,
|
|
332
|
+
# whose only non-docker id is language: golang, i.e. a go toolchain on
|
|
333
|
+
# every machine that commits and on pre-commit.ci
|
|
334
|
+
- repo: https://github.com/Mateusz-Grzelinski/actionlint-py
|
|
335
|
+
rev: v1.7.12.24
|
|
336
|
+
hooks:
|
|
337
|
+
- id: actionlint
|
|
338
|
+
name: actionlint (github workflows)
|
|
339
|
+
# actionlint delegates the body of a run: step to shellcheck, and
|
|
340
|
+
# of a "shell: python" step to pyflakes, if it finds them on the
|
|
341
|
+
# PATH: without them it validates the yaml around a shell script
|
|
342
|
+
# and not the script -- and the changes job in test.yml is a
|
|
343
|
+
# shell script. Declared here rather than left to the machine, so
|
|
344
|
+
# that a commit checks what CI checks: the runner image carries
|
|
345
|
+
# shellcheck, so leaving it to chance would mean CI checking
|
|
346
|
+
# more.
|
|
347
|
+
# Pinned, unlike the revs above, because nothing bumps an
|
|
348
|
+
# additional dependency: pre-commit.ci moves rev, and dependabot
|
|
349
|
+
# has no pre-commit ecosystem. That is the point rather than the
|
|
350
|
+
# cost -- a shellcheck release adding a check would otherwise
|
|
351
|
+
# turn a pull request red for having changed nothing
|
|
352
|
+
additional_dependencies:
|
|
353
|
+
- shellcheck-py==0.11.0.1
|
|
354
|
+
- pyflakes==3.4.0
|
|
355
|
+
# actionlint asks whether a workflow is correct, zizmor whether it is
|
|
356
|
+
# safe: a token persisted where a later step can read it, a cache
|
|
357
|
+
# restored into a job that writes, an expression interpolated into a
|
|
358
|
+
# shell script, a trigger that runs a fork's code with write access.
|
|
359
|
+
# Every invariant the workflows here promise in a comment -- the SHA
|
|
360
|
+
# pins, the permissions block, persist-credentials: false -- is a
|
|
361
|
+
# comment until this hook reads it. Both this and actionlint report
|
|
362
|
+
# nothing on this tree today, which is the state they are here to keep
|
|
363
|
+
- repo: https://github.com/zizmorcore/zizmor-pre-commit
|
|
364
|
+
rev: v1.29.0
|
|
365
|
+
hooks:
|
|
366
|
+
- id: zizmor
|
|
367
|
+
# offline is what it does by default, said out loud: it warns
|
|
368
|
+
# about the implicit choice on every run, and the choice is the
|
|
369
|
+
# right one. Two audits can query GitHub for the actions a
|
|
370
|
+
# workflow pins -- impostor-commit and known-vulnerable-actions
|
|
371
|
+
# -- which would make the hook want a token and report
|
|
372
|
+
# differently on a machine that has none.
|
|
373
|
+
# --no-progress is repeated rather than added: args replaces what
|
|
374
|
+
# the hook declares, and that flag is the whole of what it
|
|
375
|
+
# declares, so passing --offline alone would drop it
|
|
376
|
+
args: [--offline, --no-progress]
|
|
377
|
+
# the width of a toml comment, the one prose left with no limit:
|
|
378
|
+
# taplo formats values and leaves comments alone by design.
|
|
379
|
+
# `.{80}\S*[ \t]` reports a line only when whitespace is left past
|
|
380
|
+
# column 80, the amnesty MD013 and ruff give a comment ending in a
|
|
381
|
+
# link that cannot be broken
|
|
382
|
+
- repo: local
|
|
383
|
+
hooks:
|
|
384
|
+
- id: toml-comment-width
|
|
385
|
+
name: toml comment width (80 columns, unbreakable links exempt)
|
|
386
|
+
language: pygrep
|
|
387
|
+
entry: '^(?=[ \t]*#).{80}\S*[ \t]'
|
|
388
|
+
files: \.toml$
|
|
389
|
+
# ruff replaces autoflake, bandit, black, copyright_notice_precommit,
|
|
390
|
+
# flake8, isort, and pyupgrade -- and fixes the copyright hook's own
|
|
391
|
+
# defect along the way: CPY001 checks whatever files it is given the
|
|
392
|
+
# same way regardless of who asked, where copyright-notice-precommit
|
|
393
|
+
# checked only staged files unless given --enforce-all, so under
|
|
394
|
+
# "pre-commit run --all-files" it checked nothing
|
|
395
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
396
|
+
rev: v0.16.4
|
|
397
|
+
hooks:
|
|
398
|
+
- id: ruff-check
|
|
399
|
+
name: ruff check (in place fixes)
|
|
400
|
+
args: [--fix]
|
|
401
|
+
- id: ruff-format
|
|
402
|
+
name: ruff format (in place fixes)
|
|
403
|
+
# the other half of pyproject.toml's unspecified-encoding, which reads
|
|
404
|
+
# `open` and the pathlib spellings and stops there. A child process
|
|
405
|
+
# decoded through `text=True` takes the locale's encoding by the same
|
|
406
|
+
# rule, and no linter here has an opinion on that keyword.
|
|
407
|
+
# `encoding=` is what the call wanted anyway, so the fix is one
|
|
408
|
+
# keyword in place of another and never a mode change
|
|
409
|
+
- repo: local
|
|
410
|
+
hooks:
|
|
411
|
+
- id: decoded-subprocess-encoding
|
|
412
|
+
name: a decoded subprocess names its encoding, not text=True
|
|
413
|
+
language: pygrep
|
|
414
|
+
entry: '\b(text|universal_newlines)=True'
|
|
415
|
+
files: \.py$
|
|
416
|
+
# a local hook running mypy from the project environment: every
|
|
417
|
+
# import the tree makes resolves under it, and there is no unstubbed
|
|
418
|
+
# dependency left to declare an override for -- pyproject.toml's
|
|
419
|
+
# [dependency-groups].lint is where that environment (mypy and
|
|
420
|
+
# types-requests) is declared.
|
|
421
|
+
# --locked and not --frozen, for the reason the uv-lock hook below
|
|
422
|
+
# cannot cover: a dependency added without a re-lock would leave mypy
|
|
423
|
+
# checking a stale environment and saying nothing, and this hook
|
|
424
|
+
# produces its verdict before that one runs.
|
|
425
|
+
# No paths on the command line, either: mypy reads [tool.mypy]'s
|
|
426
|
+
# `files` only when it is given none, so an argument list here would
|
|
427
|
+
# replace that key rather than agree with it -- two lists free to
|
|
428
|
+
# drift apart, and the gate silently running on the shorter one
|
|
429
|
+
- repo: local
|
|
430
|
+
hooks:
|
|
431
|
+
- id: mypy
|
|
432
|
+
name: mypy (in the project environment)
|
|
433
|
+
entry: uv run --locked --no-default-groups --group lint --group test mypy
|
|
434
|
+
language: system
|
|
435
|
+
types: [python]
|
|
436
|
+
pass_filenames: false
|
|
437
|
+
require_serial: true
|
|
438
|
+
- repo: https://github.com/astral-sh/uv-pre-commit
|
|
439
|
+
rev: 0.12.5
|
|
440
|
+
hooks:
|
|
441
|
+
# keep uv.lock in sync with pyproject.toml
|
|
442
|
+
- id: uv-lock
|
|
443
|
+
# what is tracked and not in the sdist, and what is in the sdist and not
|
|
444
|
+
# tracked, both ways round, against the patterns of
|
|
445
|
+
# [tool.uv.build-backend] -- which is also where what nothing asked
|
|
446
|
+
# before this hook existed is written down. Nothing is configured here:
|
|
447
|
+
# the hook's own manifest passes --no-isolation and --inject-junk and
|
|
448
|
+
# installs uv, which is the whole of what this needs. --no-isolation is
|
|
449
|
+
# what pre-commit.ci requires -- an isolated build environment cannot be
|
|
450
|
+
# created there -- and it costs nothing to build without one, the
|
|
451
|
+
# backend being the copy bundled in that uv. --inject-junk plants the
|
|
452
|
+
# leftovers a working directory collects, for the length of the run, so
|
|
453
|
+
# the check is made against a tree in the state it is usually in rather
|
|
454
|
+
# than a clean one; which of them an include pattern reaches, and which
|
|
455
|
+
# the backend's own default excludes already drop, is answered beside
|
|
456
|
+
# [tool.uv.build-backend] source-exclude
|
|
457
|
+
- repo: https://github.com/henryiii/check-sdist
|
|
458
|
+
rev: v1.6.0
|
|
459
|
+
hooks:
|
|
460
|
+
- id: check-sdist
|
|
461
|
+
# --installer=pip is what makes the environment decide the
|
|
462
|
+
# backend instead of the outer uv's own bundled copy: it runs
|
|
463
|
+
# `build --no-isolation`, which refuses one that does not
|
|
464
|
+
# satisfy [build-system] requires above. --inject-junk is
|
|
465
|
+
# repeated because args: replaces the manifest's own rather
|
|
466
|
+
# than extending it; --no-isolation stays in the manifest's
|
|
467
|
+
# entry:, which args: does not touch
|
|
468
|
+
args: [--inject-junk, --installer=pip]
|
|
469
|
+
additional_dependencies: ["uv_build>=0.12.5,<0.13"]
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# The newest interpreter every dependency supports, and the version
|
|
2
|
+
# requires-python names. Not 3.14t, and not for the reason this comment
|
|
3
|
+
# used to give: plyvel's Cython source would not compile against the
|
|
4
|
+
# free-threaded build, and plyvel is gone. This tree's runtime closure
|
|
5
|
+
# does carry a compiled extension now: btclib depends on the
|
|
6
|
+
# `secp256k1` extra, pulling in `btclib-secp256k1` and, under it,
|
|
7
|
+
# `cffi`. Neither re-enables the GIL -- btclib-org/btclib-node#361
|
|
8
|
+
# measured `sys._is_gil_enabled()` still False after importing both
|
|
9
|
+
# under 3.14.6+freethreaded, and both ship paired cp314/cp314t wheels.
|
|
10
|
+
# `librt` is a dependency of mypy, a development-only package and not
|
|
11
|
+
# part of the runtime closure at all, and every compiled package in
|
|
12
|
+
# the lock, `librt` included, ships a cp314t wheel too.
|
|
13
|
+
# The pin holds anyway: Node.worker_pool builds a ThreadPool rather
|
|
14
|
+
# than a process Pool where sys._is_gil_enabled() is False
|
|
15
|
+
# (btclib-org/btclib-node#388, building on btclib-org/btclib-node#385),
|
|
16
|
+
# but choosing that at runtime is not the same as switching this
|
|
17
|
+
# interpreter's own default over to 3.14t, which nothing here asks for.
|
|
18
|
+
# btclib-org/btclib-node#112, which asked whether 3.14t was worth it, is
|
|
19
|
+
# answered and closed by this comment.
|
|
20
|
+
# A trailing comment on the version line below would make uv ignore this
|
|
21
|
+
# file, so the explanation stays up here instead.
|
|
22
|
+
3.14
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
---
|
|
2
|
+
# Read the Docs configuration file
|
|
3
|
+
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
|
|
4
|
+
#
|
|
5
|
+
# The dotted name is the canonical one; readthedocs.yml is honored too,
|
|
6
|
+
# but documented as deprecated.
|
|
7
|
+
#
|
|
8
|
+
# The build has to install the project itself, not sphinx alone: the
|
|
9
|
+
# autodoc directives in docs/source/*.rst import the module, a failed
|
|
10
|
+
# import is a sphinx warning rather than an error, and a "requirements:
|
|
11
|
+
# docs/requirements.txt" install therefore publishes a bare module title
|
|
12
|
+
# with no API beneath it, silently.
|
|
13
|
+
#
|
|
14
|
+
# What this file cannot say is *which* versions run it. This repository
|
|
15
|
+
# is not on Read the Docs yet -- REPOSITORY.md's own "No Pages and no
|
|
16
|
+
# Read the Docs" is what #264 leaves this file to answer for the day
|
|
17
|
+
# that changes, since a build config has to exist before a project can
|
|
18
|
+
# be connected to one.
|
|
19
|
+
|
|
20
|
+
# Required
|
|
21
|
+
version: 2
|
|
22
|
+
|
|
23
|
+
# the interpreter is declared rather than left to whatever read the docs
|
|
24
|
+
# defaults to: conf.py reads the version and the project name out of
|
|
25
|
+
# pyproject.toml with tomllib, which is standard library from 3.11 on. Which
|
|
26
|
+
# version above that floor is `.python-version`'s to say, 3.14 -- these
|
|
27
|
+
# docs are built twice, here and by docs.yml, and one interpreter is what
|
|
28
|
+
# keeps the build read on the website and the build that gates a merge from
|
|
29
|
+
# being two different questions
|
|
30
|
+
build:
|
|
31
|
+
os: ubuntu-24.04
|
|
32
|
+
tools:
|
|
33
|
+
python: "3.14"
|
|
34
|
+
# build.commands rather than the sphinx: and python: keys, which cannot
|
|
35
|
+
# express this and are rejected when it is present.
|
|
36
|
+
# autodoc has to import the module, so the project has to be installed,
|
|
37
|
+
# and what read the docs can express natively is "pip install ." plus a
|
|
38
|
+
# requirements file. uv installs the docs dependency group instead,
|
|
39
|
+
# from uv.lock, which is why there is no docs/requirements.txt: the
|
|
40
|
+
# group in pyproject.toml is the single declaration and the lock pins
|
|
41
|
+
# it, where a requirements file would be unpinned and kept in step by a
|
|
42
|
+
# header asking a human to do it.
|
|
43
|
+
# uv itself is not pinned, deliberately: no dependabot ecosystem watches
|
|
44
|
+
# this file, so a pin here is a version nobody bumps, and --locked makes
|
|
45
|
+
# the uv version irrelevant to what gets installed -- uv.lock decides
|
|
46
|
+
# that, and a uv too old to read the lock fails loudly rather than
|
|
47
|
+
# resolving something else.
|
|
48
|
+
# -W turns a failed import into a failed build, which is the point of
|
|
49
|
+
# the whole file; --keep-going reports every problem in the same run
|
|
50
|
+
# instead of one per push, and -n turns an unresolved cross-reference
|
|
51
|
+
# into a warning for -W to catch -- conf.py's own intersphinx_mapping
|
|
52
|
+
# and nitpick_ignore are what -n is checked against
|
|
53
|
+
commands:
|
|
54
|
+
- pip install uv
|
|
55
|
+
- uv sync --locked --no-default-groups --group docs
|
|
56
|
+
- >-
|
|
57
|
+
uv run --locked --no-default-groups --group docs
|
|
58
|
+
sphinx-build -W -n --keep-going -b html docs/source $READTHEDOCS_OUTPUT/html
|