frostwork 0.1.0__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.
Files changed (101) hide show
  1. frostwork-0.1.0/.github/dependabot.yml +12 -0
  2. frostwork-0.1.0/.github/workflows/ci.yml +149 -0
  3. frostwork-0.1.0/.github/workflows/publish.yml +164 -0
  4. frostwork-0.1.0/.gitignore +15 -0
  5. frostwork-0.1.0/.pre-commit-config.yaml +10 -0
  6. frostwork-0.1.0/AGENTS.md +385 -0
  7. frostwork-0.1.0/CHANGELOG.md +113 -0
  8. frostwork-0.1.0/CLAUDE.md +7 -0
  9. frostwork-0.1.0/Cargo.lock +171 -0
  10. frostwork-0.1.0/Cargo.toml +47 -0
  11. frostwork-0.1.0/LICENSE +202 -0
  12. frostwork-0.1.0/Makefile +183 -0
  13. frostwork-0.1.0/PKG-INFO +207 -0
  14. frostwork-0.1.0/README.md +177 -0
  15. frostwork-0.1.0/SECURITY.md +36 -0
  16. frostwork-0.1.0/docs/BENCHMARKS.md +447 -0
  17. frostwork-0.1.0/docs/COMPATIBILITY.md +772 -0
  18. frostwork-0.1.0/docs/DESIGN.md +325 -0
  19. frostwork-0.1.0/docs/MIGRATION.md +49 -0
  20. frostwork-0.1.0/docs/PYTHON.md +425 -0
  21. frostwork-0.1.0/docs/SUPPORT_SNAPSHOT.md +49 -0
  22. frostwork-0.1.0/docs/TESTING.md +252 -0
  23. frostwork-0.1.0/docs/WEBPOET_SURFACE.md +62 -0
  24. frostwork-0.1.0/examples/basic.py +20 -0
  25. frostwork-0.1.0/examples/basic.rs +15 -0
  26. frostwork-0.1.0/pyproject.toml +110 -0
  27. frostwork-0.1.0/python/AGENTS.md +8 -0
  28. frostwork-0.1.0/python/CLAUDE.md +6 -0
  29. frostwork-0.1.0/python/frostwork/__init__.py +44 -0
  30. frostwork-0.1.0/python/frostwork/_frostwork.pyi +69 -0
  31. frostwork-0.1.0/python/frostwork/audit.py +356 -0
  32. frostwork-0.1.0/python/frostwork/page.py +760 -0
  33. frostwork-0.1.0/python/frostwork/py.typed +1 -0
  34. frostwork-0.1.0/python/frostwork/scan.py +250 -0
  35. frostwork-0.1.0/python/frostwork/webpoet.py +946 -0
  36. frostwork-0.1.0/requirements-bench.txt +12 -0
  37. frostwork-0.1.0/requirements-test.txt +36 -0
  38. frostwork-0.1.0/src/bin/bench.rs +77 -0
  39. frostwork-0.1.0/src/bin/differ.rs +172 -0
  40. frostwork-0.1.0/src/diagnostics.rs +418 -0
  41. frostwork-0.1.0/src/encoding.rs +672 -0
  42. frostwork-0.1.0/src/entities.rs +237 -0
  43. frostwork-0.1.0/src/implied_close/generated.rs +249 -0
  44. frostwork-0.1.0/src/implied_close/mod.rs +204 -0
  45. frostwork-0.1.0/src/lib.rs +2621 -0
  46. frostwork-0.1.0/src/matcher/compile.rs +176 -0
  47. frostwork-0.1.0/src/matcher/decode.rs +109 -0
  48. frostwork-0.1.0/src/matcher/deferred.rs +84 -0
  49. frostwork-0.1.0/src/matcher/frame.rs +177 -0
  50. frostwork-0.1.0/src/matcher/matching.rs +710 -0
  51. frostwork-0.1.0/src/matcher/mod.rs +3254 -0
  52. frostwork-0.1.0/src/matcher/sig.rs +212 -0
  53. frostwork-0.1.0/src/mutate.rs +141 -0
  54. frostwork-0.1.0/src/page.rs +586 -0
  55. frostwork-0.1.0/src/python.rs +351 -0
  56. frostwork-0.1.0/src/selector.rs +1459 -0
  57. frostwork-0.1.0/src/tokenizer.rs +836 -0
  58. frostwork-0.1.0/src/xpath.rs +940 -0
  59. frostwork-0.1.0/tests/corpus/README.md +20 -0
  60. frostwork-0.1.0/tests/corpus/catalog/pages/test-listing.html +15 -0
  61. frostwork-0.1.0/tests/corpus/catalog/selectors.json +13 -0
  62. frostwork-0.1.0/tests/corpus/docgen/pages/test-api.html +17 -0
  63. frostwork-0.1.0/tests/corpus/docgen/selectors.json +14 -0
  64. frostwork-0.1.0/tests/corpus/tabular/pages/test-report.html +13 -0
  65. frostwork-0.1.0/tests/corpus/tabular/selectors.json +13 -0
  66. frostwork-0.1.0/tests/test_doc_examples.py +130 -0
  67. frostwork-0.1.0/tests/test_gates.py +1093 -0
  68. frostwork-0.1.0/tests/test_python.py +3414 -0
  69. frostwork-0.1.0/tests/test_typing.py +87 -0
  70. frostwork-0.1.0/tests/typing_fixture.py +148 -0
  71. frostwork-0.1.0/tools/AGENTS.md +85 -0
  72. frostwork-0.1.0/tools/CLAUDE.md +6 -0
  73. frostwork-0.1.0/tools/ab_bench.py +238 -0
  74. frostwork-0.1.0/tools/abi3_smoke.py +105 -0
  75. frostwork-0.1.0/tools/audit_tree_rules.py +650 -0
  76. frostwork-0.1.0/tools/bench_corpus.py +351 -0
  77. frostwork-0.1.0/tools/bench_engines.py +885 -0
  78. frostwork-0.1.0/tools/bench_matrix.py +429 -0
  79. frostwork-0.1.0/tools/bench_mem.py +316 -0
  80. frostwork-0.1.0/tools/bench_webpoet.py +454 -0
  81. frostwork-0.1.0/tools/conformant.py +318 -0
  82. frostwork-0.1.0/tools/corpus_fetch.py +242 -0
  83. frostwork-0.1.0/tools/decoder_sweep.py +153 -0
  84. frostwork-0.1.0/tools/diff_fuzz.py +493 -0
  85. frostwork-0.1.0/tools/diff_lxml.py +570 -0
  86. frostwork-0.1.0/tools/diff_webpoet.py +1162 -0
  87. frostwork-0.1.0/tools/enc_check.py +363 -0
  88. frostwork-0.1.0/tools/encpages.py +91 -0
  89. frostwork-0.1.0/tools/families.py +256 -0
  90. frostwork-0.1.0/tools/foreign.py +115 -0
  91. frostwork-0.1.0/tools/gen_tree_rules.py +781 -0
  92. frostwork-0.1.0/tools/mutate_rules.py +340 -0
  93. frostwork-0.1.0/tools/mutate_webpoet.py +562 -0
  94. frostwork-0.1.0/tools/oracle.py +126 -0
  95. frostwork-0.1.0/tools/sel_fuzz.py +657 -0
  96. frostwork-0.1.0/tools/seq_sweep.py +163 -0
  97. frostwork-0.1.0/tools/soak.py +53 -0
  98. frostwork-0.1.0/tools/support_snapshot.py +105 -0
  99. frostwork-0.1.0/tools/webpoet_cases.py +186 -0
  100. frostwork-0.1.0/tools/webpoet_structure.py +45 -0
  101. frostwork-0.1.0/tools/webpoet_surface.py +257 -0
@@ -0,0 +1,12 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: github-actions
4
+ directory: "/"
5
+ schedule:
6
+ interval: monthly
7
+ groups:
8
+ github-actions:
9
+ patterns:
10
+ - "*"
11
+ cooldown:
12
+ default-days: 7
@@ -0,0 +1,149 @@
1
+ name: ci
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ jobs:
12
+ version-sync:
13
+ name: Cargo/pyproject version match
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
17
+ with:
18
+ persist-credentials: false
19
+ # the version is double-sourced (Cargo.toml + pyproject.toml); assert they agree so a release
20
+ # tag can't ship a mismatch between the wheel metadata and the crate.
21
+ - name: assert versions match
22
+ run: |
23
+ cargo_v=$(grep -m1 '^version' Cargo.toml | sed -E 's/.*"(.*)".*/\1/')
24
+ py_v=$(grep -m1 '^version' pyproject.toml | sed -E 's/.*"(.*)".*/\1/')
25
+ echo "Cargo.toml=$cargo_v pyproject.toml=$py_v"
26
+ test "$cargo_v" = "$py_v" || { echo "::error::version mismatch: $cargo_v != $py_v"; exit 1; }
27
+
28
+ rust:
29
+ name: cargo test + clippy
30
+ runs-on: ubuntu-latest
31
+ steps:
32
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
33
+ with:
34
+ persist-credentials: false
35
+ - uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c # stable
36
+ with:
37
+ components: clippy
38
+ - uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
39
+ # `make test` = cargo test + clippy. The `python` feature is OFF here (it links libpython only
40
+ # under maturin); this builds the lib + differ/bench bins.
41
+ - run: make test
42
+
43
+ differential:
44
+ name: differential gate + python
45
+ runs-on: ubuntu-latest
46
+ # EVERY STEP IS A MAKE TARGET, and that is the point rather than a convenience: this job used to
47
+ # inline the same commands, and it drifted — `make ci` grew the sequence sweep and the generated-table
48
+ # drift check, and hosted CI ran neither, so the checks a contributor is told are mandatory were not
49
+ # the checks a pull request had to pass. Add a gate to the Makefile and it lands here for free.
50
+ steps:
51
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
52
+ with:
53
+ persist-credentials: false
54
+ - uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c # stable
55
+ - uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
56
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
57
+ with:
58
+ python-version: "3.12"
59
+ - run: python -m venv .venv
60
+ # pin the oracle exactly: an lxml/parsel upgrade silently moving the reference must be a
61
+ # deliberate bump, not an incidental one that quietly changes what "parity" means.
62
+ - run: .venv/bin/pip install -r requirements-test.txt
63
+ # The gates hosted CI runs are the gates `make ci` runs, by NAME rather than by a second copy of
64
+ # the command list. The copy had already drifted: three targets in the Makefile were missing here,
65
+ # which is the failure the meta-gates exist to catch, one level up.
66
+ #
67
+ # `make gate` — 0 non-whitespace DIVERGE + 0 CRASH vs lxml (flat AND grouped One/Many), then
68
+ # encoding parity. Builds the differ/bench bins the harness drives.
69
+ - run: make gate
70
+ # selector fuzz (no-fallback contract: empty OR equal to lxml, never non-empty-and-wrong) plus
71
+ # malformed-HTML fuzz (CRASH gated absolutely, NOVEL as a rate).
72
+ - run: make fuzz-smoke
73
+ # builds the extension, then: the Python surface, tests/test_gates.py (which seeds a regression
74
+ # into each gate's decision function and asserts it goes red), the support snapshot, the GENERATED
75
+ # rule tables against the oracle, every tree-construction rule cell against lxml, and mypy over the
76
+ # shipped package (its annotations are a promise to every user's type checker).
77
+ - run: make py
78
+ # value parity over PAGES rather than rules: the fixtures are shaped like the doc-generator and
79
+ # table markup that broke the engine while the generated gate read 100%.
80
+ - run: make gate-corpus
81
+ # TAG SEQUENCES, exhaustively, compared on the whole tree — the surface where the state at token N
82
+ # depends on tokens 1..N-1, which no (open x incoming) rule sweep can reach.
83
+ - run: make gate-seq
84
+ # The layer ABOVE the engine: does a page OBJECT return parsel's item? Five defects lived in that
85
+ # gap, three of them silent. Includes the derived upstream-surface snapshot.
86
+ - run: make gate-webpoet
87
+ # And the inverse: break one load-bearing line in webpoet.py, does any gate notice?
88
+ - run: make gate-webpoet-mutate
89
+
90
+ bindings:
91
+ name: bindings (py${{ matrix.python }} / ${{ matrix.os }})
92
+ # The heavy differential runs once (above) on 3.12/linux. This matrix only builds the extension and
93
+ # runs the Python suite, cheaply covering the newest CPython, the next prerelease one, and macOS. The
94
+ # abi3 FLOOR is a separate job below, and since the floor moved to 3.10 it runs this same suite rather
95
+ # than a stand-in.
96
+ strategy:
97
+ fail-fast: false
98
+ matrix:
99
+ include:
100
+ - { os: ubuntu-latest, python: "3.14" }
101
+ - { os: ubuntu-latest, python: "3.15", prerelease: true }
102
+ - { os: macos-latest, python: "3.12" }
103
+ runs-on: ${{ matrix.os }}
104
+ steps:
105
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
106
+ with:
107
+ persist-credentials: false
108
+ - uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c # stable
109
+ - uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
110
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
111
+ with:
112
+ python-version: ${{ matrix.python }}
113
+ allow-prereleases: ${{ matrix.prerelease || false }}
114
+ - run: python -m venv .venv
115
+ # lxml has no prebuilt wheel yet for a prerelease CPython either, so pip falls back to a source
116
+ # build, which needs these headers.
117
+ - if: matrix.prerelease
118
+ run: sudo apt-get update && sudo apt-get install -y libxml2-dev libxslt1-dev
119
+ - run: .venv/bin/pip install -r requirements-test.txt
120
+ # web-poet pulls two mypyc/C test deps whose published wheels don't load on a prerelease CPython
121
+ - if: matrix.prerelease
122
+ run: .venv/bin/pip install --force-reinstall --no-binary charset-normalizer,time-machine charset-normalizer time-machine
123
+ - run: .venv/bin/maturin develop --release
124
+ - run: .venv/bin/python -m pytest tests/test_python.py -q
125
+ - run: .venv/bin/python examples/basic.py # keep the documented example runnable
126
+
127
+ abi3-floor:
128
+ name: abi3 floor (py3.10 / ubuntu-latest)
129
+ # The wheel is abi3-py310, so 3.10 must keep working. At the old 3.9 floor this job could not run the
130
+ # suite at all — `parsel`, `web-poet` and `pytest` each require >= 3.10, so it built the extension and
131
+ # ran tools/abi3_smoke.py (stdlib + frostwork only) as a stand-in. 3.10 is the first version where the
132
+ # pinned toolchain installs, so the floor now gets the SAME suite as every other interpreter, which is
133
+ # strictly more coverage than the smoke test it replaces.
134
+ runs-on: ubuntu-latest
135
+ steps:
136
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
137
+ with:
138
+ persist-credentials: false
139
+ - uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c # stable
140
+ - uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
141
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
142
+ with:
143
+ python-version: "3.10"
144
+ - run: python -m venv .venv
145
+ - run: .venv/bin/pip install -r requirements-test.txt
146
+ - run: .venv/bin/maturin develop --release
147
+ - run: .venv/bin/python -m pytest tests/ -q
148
+ - run: .venv/bin/python tools/abi3_smoke.py # the wheel must also work with NO dependencies present
149
+ - run: .venv/bin/python examples/basic.py # keep the documented example runnable
@@ -0,0 +1,164 @@
1
+ name: publish
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "[0-9]+.[0-9]+.[0-9]+"
7
+ workflow_dispatch:
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ jobs:
13
+ linux:
14
+ name: wheel (linux ${{ matrix.platform.target }} ${{ matrix.platform.libc }})
15
+ runs-on: ${{ matrix.platform.runner }}
16
+ strategy:
17
+ fail-fast: false
18
+ matrix:
19
+ platform:
20
+ - { runner: ubuntu-latest, target: x86_64, libc: manylinux, manylinux: auto }
21
+ - { runner: ubuntu-latest, target: x86, libc: manylinux, manylinux: auto }
22
+ - { runner: ubuntu-24.04-arm, target: aarch64, libc: manylinux, manylinux: auto }
23
+ - { runner: ubuntu-latest, target: armv7, libc: manylinux, manylinux: auto }
24
+ - { runner: ubuntu-latest, target: ppc64le, libc: manylinux, manylinux: auto }
25
+ - { runner: ubuntu-latest, target: riscv64, libc: manylinux, manylinux: auto }
26
+ - { runner: ubuntu-latest, target: x86_64, libc: musllinux, manylinux: musllinux_1_2 }
27
+ - { runner: ubuntu-24.04-arm, target: aarch64, libc: musllinux, manylinux: musllinux_1_2 }
28
+ - { runner: ubuntu-latest, target: armv7, libc: musllinux, manylinux: musllinux_1_2 }
29
+ - { runner: ubuntu-latest, target: ppc64le, libc: musllinux, manylinux: musllinux_1_2 }
30
+ - { runner: ubuntu-latest, target: riscv64, libc: musllinux, manylinux: musllinux_1_2 }
31
+ steps:
32
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
33
+ with:
34
+ persist-credentials: false
35
+ - uses: PyO3/maturin-action@e83996d129638aa358a18fbd1dfb82f0b0fb5d3b # v1.51.0
36
+ with:
37
+ target: ${{ matrix.platform.target }}
38
+ args: --release --out dist
39
+ manylinux: ${{ matrix.platform.manylinux }}
40
+ - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
41
+ with:
42
+ name: wheels-${{ matrix.platform.libc }}-${{ matrix.platform.target }}
43
+ path: dist
44
+
45
+ macos:
46
+ name: wheel (macos ${{ matrix.target }})
47
+ runs-on: macos-latest
48
+ strategy:
49
+ fail-fast: false
50
+ matrix:
51
+ target: [x86_64, aarch64]
52
+ steps:
53
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
54
+ with:
55
+ persist-credentials: false
56
+ - uses: PyO3/maturin-action@e83996d129638aa358a18fbd1dfb82f0b0fb5d3b # v1.51.0
57
+ with:
58
+ target: ${{ matrix.target }}
59
+ args: --release --out dist
60
+ - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
61
+ with:
62
+ name: wheels-macos-${{ matrix.target }}
63
+ path: dist
64
+
65
+ windows:
66
+ name: wheel (windows ${{ matrix.platform.target }})
67
+ runs-on: ${{ matrix.platform.runner }}
68
+ strategy:
69
+ fail-fast: false
70
+ matrix:
71
+ platform:
72
+ - { runner: windows-latest, target: x64, arch: x64 }
73
+ - { runner: windows-latest, target: x86, arch: x86 }
74
+ - { runner: windows-11-arm, target: aarch64, arch: arm64 }
75
+ steps:
76
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
77
+ with:
78
+ persist-credentials: false
79
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
80
+ with:
81
+ python-version: "3.12"
82
+ architecture: ${{ matrix.platform.arch }}
83
+ - uses: PyO3/maturin-action@e83996d129638aa358a18fbd1dfb82f0b0fb5d3b # v1.51.0
84
+ with:
85
+ target: ${{ matrix.platform.target }}
86
+ args: --release --out dist
87
+ - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
88
+ with:
89
+ name: wheels-windows-${{ matrix.platform.target }}
90
+ path: dist
91
+
92
+ sdist:
93
+ name: sdist
94
+ runs-on: ubuntu-latest
95
+ steps:
96
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
97
+ with:
98
+ persist-credentials: false
99
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
100
+ with:
101
+ python-version: "3.12"
102
+ - uses: PyO3/maturin-action@e83996d129638aa358a18fbd1dfb82f0b0fb5d3b # v1.51.0
103
+ with:
104
+ command: sdist
105
+ args: --out dist
106
+ - name: build/install the actual sdist and run the Python suite
107
+ run: |
108
+ python -m pip install -r requirements-test.txt
109
+ python -m pip install --no-build-isolation dist/*.tar.gz
110
+ python -m pytest tests/test_python.py -q
111
+ - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
112
+ with:
113
+ name: wheels-sdist
114
+ path: dist
115
+
116
+ smoke:
117
+ name: smoke-test built wheel (${{ matrix.artifact }})
118
+ needs: [linux, macos, windows, sdist]
119
+ strategy:
120
+ fail-fast: false
121
+ matrix:
122
+ include:
123
+ - { os: ubuntu-latest, artifact: wheels-manylinux-x86_64 }
124
+ - { os: ubuntu-24.04-arm, artifact: wheels-manylinux-aarch64 }
125
+ - { os: macos-latest, artifact: wheels-macos-aarch64 }
126
+ - { os: windows-latest, artifact: wheels-windows-x64 }
127
+ - { os: windows-11-arm, artifact: wheels-windows-aarch64 }
128
+ runs-on: ${{ matrix.os }}
129
+ steps:
130
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
131
+ with:
132
+ persist-credentials: false
133
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
134
+ with:
135
+ python-version: "3.12"
136
+ - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
137
+ with:
138
+ name: ${{ matrix.artifact }}
139
+ path: dist
140
+ - name: install the built wheel + test deps, then run the suite
141
+ shell: bash
142
+ run: |
143
+ python -m pip install --upgrade pip
144
+ python -m pip install -r requirements-test.txt
145
+ python -m pip install --no-index --find-links dist frostwork
146
+ python -m pytest tests/test_python.py -q
147
+
148
+ publish:
149
+ name: Publish to PyPI
150
+ runs-on: ubuntu-latest
151
+ needs: [linux, macos, windows, sdist, smoke]
152
+ if: startsWith(github.ref, 'refs/tags/')
153
+ environment:
154
+ name: pypi
155
+ url: https://pypi.org/p/frostwork
156
+ permissions:
157
+ id-token: write
158
+ steps:
159
+ - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
160
+ with:
161
+ pattern: wheels-*
162
+ merge-multiple: true
163
+ path: dist
164
+ - uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
@@ -0,0 +1,15 @@
1
+ /target
2
+ __pycache__/
3
+ *.pyc
4
+ .venv/
5
+ /fixtures/
6
+ # Python / maturin build artifacts
7
+ *.so
8
+ /dist
9
+ /build
10
+ *.egg-info/
11
+ .pytest_cache/
12
+ # Generated benchmark results (machine-specific paths; docs/BENCHMARKS.md is canonical)
13
+ /tools/results/
14
+ # Fuzzer run logs (fuzz.sh output, one per worker)
15
+ /fuzz-*.log
@@ -0,0 +1,10 @@
1
+ repos:
2
+ - repo: https://github.com/rhysd/actionlint
3
+ rev: v1.7.12
4
+ hooks:
5
+ - id: actionlint
6
+ - repo: https://github.com/zizmorcore/zizmor-pre-commit
7
+ rev: v1.29.0
8
+ hooks:
9
+ - id: zizmor
10
+ args: [--no-progress, --fix]