samplerdisc 0.5.1__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.
- samplerdisc-0.5.1/.dockerignore +8 -0
- samplerdisc-0.5.1/.github/ISSUE_TEMPLATE/config.yml +1 -0
- samplerdisc-0.5.1/.github/ISSUE_TEMPLATE/disc-wont-read.yml +43 -0
- samplerdisc-0.5.1/.github/ISSUE_TEMPLATE/new-format.yml +33 -0
- samplerdisc-0.5.1/.github/pull_request_template.md +24 -0
- samplerdisc-0.5.1/.github/workflows/ci.yml +60 -0
- samplerdisc-0.5.1/.github/workflows/release.yml +71 -0
- samplerdisc-0.5.1/.gitignore +44 -0
- samplerdisc-0.5.1/CHANGELOG.md +313 -0
- samplerdisc-0.5.1/CLAUDE.md +73 -0
- samplerdisc-0.5.1/CODE_OF_CONDUCT.md +27 -0
- samplerdisc-0.5.1/CONTRIBUTING.md +47 -0
- samplerdisc-0.5.1/Containerfile +31 -0
- samplerdisc-0.5.1/LICENSE +21 -0
- samplerdisc-0.5.1/PKG-INFO +226 -0
- samplerdisc-0.5.1/README.md +207 -0
- samplerdisc-0.5.1/SECURITY.md +80 -0
- samplerdisc-0.5.1/docs/README.md +106 -0
- samplerdisc-0.5.1/docs/adr/0001-pure-python-stdlib-only.md +27 -0
- samplerdisc-0.5.1/docs/adr/0002-mit-license.md +23 -0
- samplerdisc-0.5.1/docs/adr/0003-brand-neutral-pluggable-backends.md +33 -0
- samplerdisc-0.5.1/docs/adr/0004-detect-by-signature.md +25 -0
- samplerdisc-0.5.1/docs/adr/0005-probe-for-the-filesystem-origin.md +31 -0
- samplerdisc-0.5.1/docs/adr/0006-mdx-blocks-classified-by-decode-attempt.md +35 -0
- samplerdisc-0.5.1/docs/adr/0007-emit-mono-and-stereo.md +27 -0
- samplerdisc-0.5.1/docs/adr/0008-no-media-in-the-repo.md +35 -0
- samplerdisc-0.5.1/docs/adr/0009-export-iso-escape-hatch.md +27 -0
- samplerdisc-0.5.1/docs/adr/0010-build-the-instrument-layer-ourselves.md +31 -0
- samplerdisc-0.5.1/docs/adr/0011-the-deliverable-is-daw-ready-wav.md +35 -0
- samplerdisc-0.5.1/docs/adr/0012-a-probe-must-confirm-a-file.md +50 -0
- samplerdisc-0.5.1/docs/adr/0013-cueless-audio-is-reported-not-guessed.md +43 -0
- samplerdisc-0.5.1/docs/adr/0014-one-backend-per-on-disc-format.md +45 -0
- samplerdisc-0.5.1/docs/adr/0015-locate-banks-by-signature.md +52 -0
- samplerdisc-0.5.1/docs/adr/0016-the-s7xx-hierarchy-is-located-not-walked.md +35 -0
- samplerdisc-0.5.1/docs/adr/0017-the-stereo-side-marker-is-a-character-class.md +39 -0
- samplerdisc-0.5.1/docs/adr/0018-the-s7xx-sample-rate-is-measured.md +35 -0
- samplerdisc-0.5.1/docs/adr/0019-prefer-joliet-names.md +37 -0
- samplerdisc-0.5.1/docs/adr/0020-read-e-iv-through-its-sample-directory.md +57 -0
- samplerdisc-0.5.1/docs/adr/0021-a-bank-owns-the-run-its-header-declares.md +69 -0
- samplerdisc-0.5.1/docs/adr/0022-a-volume-is-explained-by-the-allocation-map.md +71 -0
- samplerdisc-0.5.1/docs/adr/0023-partitions-come-from-the-table-the-disc-declares.md +65 -0
- samplerdisc-0.5.1/docs/adr/0024-the-aiff-twin-is-converted-and-deduplicated.md +59 -0
- samplerdisc-0.5.1/docs/adr/0025-the-loop-is-decoded-the-root-key-is-not.md +107 -0
- samplerdisc-0.5.1/docs/adr/0026-the-record-declares-the-channel-count.md +95 -0
- samplerdisc-0.5.1/docs/adr/0027-a-payload-must-be-the-file-its-entry-placed.md +121 -0
- samplerdisc-0.5.1/docs/adr/0028-a-displaced-partition-is-anchored-quantised-and-floored.md +109 -0
- samplerdisc-0.5.1/docs/adr/0029-a-record-is-closed-by-the-channel-it-declares.md +102 -0
- samplerdisc-0.5.1/docs/adr/0030-the-whole-extent-no-loop-is-refused-at-both-ends.md +73 -0
- samplerdisc-0.5.1/docs/adr/0031-a-bank-binds-the-near-named-header-its-placement-predicts.md +59 -0
- samplerdisc-0.5.1/docs/adr/0032-read-the-eiv-form-e4b0-bank-and-its-embedded-samples.md +49 -0
- samplerdisc-0.5.1/docs/adr/0033-ebl-is-converted-on-a-disc-and-verified-by-a-render.md +49 -0
- samplerdisc-0.5.1/docs/adr/0034-each-directory-entry-binds-its-own-header.md +52 -0
- samplerdisc-0.5.1/docs/adr/0035-kmsi-is-fat16-read-behind-the-kurzweil-signature.md +43 -0
- samplerdisc-0.5.1/docs/adr/0036-the-krz-bank-is-read-as-objects-and-verified-against-mpc2emu.md +47 -0
- samplerdisc-0.5.1/docs/adr/0037-a-fragmented-form-bank-is-read-along-the-fat-chain.md +49 -0
- samplerdisc-0.5.1/docs/adr/0038-the-container-is-a-runner-not-the-distribution-channel.md +35 -0
- samplerdisc-0.5.1/docs/adr/0039-samplecell-is-read-as-hfs-behind-an-apple-partition-map.md +38 -0
- samplerdisc-0.5.1/docs/adr/0040-sound-designer-ii-is-decoded-from-the-data-fork.md +41 -0
- samplerdisc-0.5.1/docs/adr/0041-stereo-ebl-is-interleaved-and-verified-by-the-render.md +40 -0
- samplerdisc-0.5.1/docs/adr/0042-loose-sample-banks-are-a-source-not-a-container.md +39 -0
- samplerdisc-0.5.1/docs/adr/0043-eiv-credits-are-metadata-read-from-the-e4p1-name-field.md +45 -0
- samplerdisc-0.5.1/docs/adr/0044-the-eiv-residual-loop-is-confirmed-by-its-period.md +54 -0
- samplerdisc-0.5.1/docs/adr/0045-a-displaced-sample-is-recovered-by-its-own-name-and-word-count.md +67 -0
- samplerdisc-0.5.1/docs/adr/0046-the-sd2-loop-is-decoded-from-sdll.md +49 -0
- samplerdisc-0.5.1/docs/adr/README.md +54 -0
- samplerdisc-0.5.1/docs/architecture.md +75 -0
- samplerdisc-0.5.1/docs/formats/README.md +56 -0
- samplerdisc-0.5.1/docs/formats/aiff.md +120 -0
- samplerdisc-0.5.1/docs/formats/akai-fs.md +361 -0
- samplerdisc-0.5.1/docs/formats/audio-cd.md +56 -0
- samplerdisc-0.5.1/docs/formats/emu-ebl.md +150 -0
- samplerdisc-0.5.1/docs/formats/emu3.md +820 -0
- samplerdisc-0.5.1/docs/formats/hfs.md +150 -0
- samplerdisc-0.5.1/docs/formats/iso9660.md +93 -0
- samplerdisc-0.5.1/docs/formats/kurzweil-krz.md +122 -0
- samplerdisc-0.5.1/docs/formats/kurzweil.md +80 -0
- samplerdisc-0.5.1/docs/formats/mdx.md +169 -0
- samplerdisc-0.5.1/docs/formats/nrg.md +82 -0
- samplerdisc-0.5.1/docs/formats/rawcd.md +53 -0
- samplerdisc-0.5.1/docs/formats/roland-s7xx.md +301 -0
- samplerdisc-0.5.1/pyproject.toml +47 -0
- samplerdisc-0.5.1/scripts/benchmark.py +264 -0
- samplerdisc-0.5.1/src/samplerdisc/__init__.py +3 -0
- samplerdisc-0.5.1/src/samplerdisc/audiocd.py +212 -0
- samplerdisc-0.5.1/src/samplerdisc/banks.py +83 -0
- samplerdisc-0.5.1/src/samplerdisc/batch.py +260 -0
- samplerdisc-0.5.1/src/samplerdisc/cli.py +450 -0
- samplerdisc-0.5.1/src/samplerdisc/container/__init__.py +1 -0
- samplerdisc-0.5.1/src/samplerdisc/container/base.py +110 -0
- samplerdisc-0.5.1/src/samplerdisc/container/detect.py +74 -0
- samplerdisc-0.5.1/src/samplerdisc/container/flat.py +16 -0
- samplerdisc-0.5.1/src/samplerdisc/container/mdsmdf.py +62 -0
- samplerdisc-0.5.1/src/samplerdisc/container/mdx.py +312 -0
- samplerdisc-0.5.1/src/samplerdisc/container/nrg.py +174 -0
- samplerdisc-0.5.1/src/samplerdisc/container/rawcd.py +79 -0
- samplerdisc-0.5.1/src/samplerdisc/cue.py +108 -0
- samplerdisc-0.5.1/src/samplerdisc/export.py +48 -0
- samplerdisc-0.5.1/src/samplerdisc/extract.py +749 -0
- samplerdisc-0.5.1/src/samplerdisc/fs/__init__.py +17 -0
- samplerdisc-0.5.1/src/samplerdisc/fs/akai.py +781 -0
- samplerdisc-0.5.1/src/samplerdisc/fs/base.py +187 -0
- samplerdisc-0.5.1/src/samplerdisc/fs/emu3.py +1545 -0
- samplerdisc-0.5.1/src/samplerdisc/fs/hfs.py +451 -0
- samplerdisc-0.5.1/src/samplerdisc/fs/iso9660.py +268 -0
- samplerdisc-0.5.1/src/samplerdisc/fs/kurzweil.py +818 -0
- samplerdisc-0.5.1/src/samplerdisc/fs/probe.py +53 -0
- samplerdisc-0.5.1/src/samplerdisc/fs/roland_s7xx.py +472 -0
- samplerdisc-0.5.1/src/samplerdisc/sample/__init__.py +38 -0
- samplerdisc-0.5.1/src/samplerdisc/sample/aiff.py +248 -0
- samplerdisc-0.5.1/src/samplerdisc/sample/akai.py +271 -0
- samplerdisc-0.5.1/src/samplerdisc/sample/emu3.py +259 -0
- samplerdisc-0.5.1/src/samplerdisc/sample/emu_ebl.py +291 -0
- samplerdisc-0.5.1/src/samplerdisc/sample/kurzweil.py +163 -0
- samplerdisc-0.5.1/src/samplerdisc/sample/roland_s7xx.py +113 -0
- samplerdisc-0.5.1/src/samplerdisc/sample/sd2.py +231 -0
- samplerdisc-0.5.1/src/samplerdisc/stereo.py +164 -0
- samplerdisc-0.5.1/src/samplerdisc/wav.py +224 -0
- samplerdisc-0.5.1/tests/__init__.py +0 -0
- samplerdisc-0.5.1/tests/fixtures.py +1895 -0
- samplerdisc-0.5.1/tests/test_aiff.py +154 -0
- samplerdisc-0.5.1/tests/test_akai_fs.py +929 -0
- samplerdisc-0.5.1/tests/test_akai_payload.py +232 -0
- samplerdisc-0.5.1/tests/test_audiocd.py +193 -0
- samplerdisc-0.5.1/tests/test_banks.py +95 -0
- samplerdisc-0.5.1/tests/test_batch.py +173 -0
- samplerdisc-0.5.1/tests/test_cli.py +86 -0
- samplerdisc-0.5.1/tests/test_containers.py +460 -0
- samplerdisc-0.5.1/tests/test_discs.py +2877 -0
- samplerdisc-0.5.1/tests/test_emu3.py +1313 -0
- samplerdisc-0.5.1/tests/test_emu_ebl.py +186 -0
- samplerdisc-0.5.1/tests/test_extract.py +441 -0
- samplerdisc-0.5.1/tests/test_hfs.py +292 -0
- samplerdisc-0.5.1/tests/test_iso9660.py +348 -0
- samplerdisc-0.5.1/tests/test_keep_originals.py +111 -0
- samplerdisc-0.5.1/tests/test_kurzweil_fs.py +233 -0
- samplerdisc-0.5.1/tests/test_kurzweil_sample.py +103 -0
- samplerdisc-0.5.1/tests/test_loops.py +163 -0
- samplerdisc-0.5.1/tests/test_roland_s7xx.py +473 -0
- samplerdisc-0.5.1/tests/test_stereo.py +260 -0
- samplerdisc-0.5.1/tests/test_wav.py +107 -0
- samplerdisc-0.5.1/uv.lock +108 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Keep the build context to what the hatchling build needs: pyproject.toml,
|
|
2
|
+
# src/, README.md and LICENSE are COPYed explicitly in the Containerfile, so
|
|
3
|
+
# everything else is noise that only slows the build and busts its cache.
|
|
4
|
+
*
|
|
5
|
+
!pyproject.toml
|
|
6
|
+
!README.md
|
|
7
|
+
!LICENSE
|
|
8
|
+
!src/
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
blank_issues_enabled: true
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
name: A disc won't read
|
|
2
|
+
description: A disc image fails to list or extract, or yields fewer samples than it should
|
|
3
|
+
labels: ["disc"]
|
|
4
|
+
body:
|
|
5
|
+
- type: markdown
|
|
6
|
+
attributes:
|
|
7
|
+
value: |
|
|
8
|
+
Thanks for the report. **Do not attach the disc image or any extracted audio** — these are commercial libraries and this repo is public. A description of the failure is what we need, not the library itself.
|
|
9
|
+
- type: dropdown
|
|
10
|
+
id: container
|
|
11
|
+
attributes:
|
|
12
|
+
label: Container format
|
|
13
|
+
description: The kind of image file. Detect by signature if you're unsure — the extension is often wrong.
|
|
14
|
+
options:
|
|
15
|
+
- .mdx (DAEMON Tools, often compressed)
|
|
16
|
+
- .nrg (Nero)
|
|
17
|
+
- .bin / .iso (raw)
|
|
18
|
+
- .cue / .bin pair
|
|
19
|
+
- Other / not sure
|
|
20
|
+
validations:
|
|
21
|
+
required: true
|
|
22
|
+
- type: input
|
|
23
|
+
id: source
|
|
24
|
+
attributes:
|
|
25
|
+
label: Where the image came from
|
|
26
|
+
description: e.g. archive.org, a personal FTP, a physical rip you made. Don't link to copyrighted material.
|
|
27
|
+
validations:
|
|
28
|
+
required: false
|
|
29
|
+
- type: textarea
|
|
30
|
+
id: command
|
|
31
|
+
attributes:
|
|
32
|
+
label: Command and full output
|
|
33
|
+
description: The exact command you ran and everything it printed. Paste text, not a screenshot.
|
|
34
|
+
render: shell
|
|
35
|
+
validations:
|
|
36
|
+
required: true
|
|
37
|
+
- type: textarea
|
|
38
|
+
id: expected
|
|
39
|
+
attributes:
|
|
40
|
+
label: What you expected
|
|
41
|
+
description: How many volumes or samples you believe are on the disc, and which specific one fails if you know it.
|
|
42
|
+
validations:
|
|
43
|
+
required: false
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
name: Support a new format
|
|
2
|
+
description: A container, filesystem, or sample format the tool doesn't handle yet
|
|
3
|
+
labels: ["enhancement"]
|
|
4
|
+
body:
|
|
5
|
+
- type: markdown
|
|
6
|
+
attributes:
|
|
7
|
+
value: |
|
|
8
|
+
A new manufacturer is usually one new module in `fs/` and/or `sample/`, and nothing else — that separation is deliberate. Tell us which layer this is.
|
|
9
|
+
- type: dropdown
|
|
10
|
+
id: layer
|
|
11
|
+
attributes:
|
|
12
|
+
label: Which layer
|
|
13
|
+
options:
|
|
14
|
+
- Container (a new image wrapper, e.g. sector geometry / compression)
|
|
15
|
+
- Filesystem (how a sampler laid files onto the disc)
|
|
16
|
+
- Sample format (the bytes inside one file)
|
|
17
|
+
- Not sure
|
|
18
|
+
validations:
|
|
19
|
+
required: true
|
|
20
|
+
- type: input
|
|
21
|
+
id: hardware
|
|
22
|
+
attributes:
|
|
23
|
+
label: Sampler / hardware
|
|
24
|
+
description: e.g. E-mu ESI-32, Roland S-760, Ensoniq ASR-10
|
|
25
|
+
validations:
|
|
26
|
+
required: false
|
|
27
|
+
- type: textarea
|
|
28
|
+
id: what-we-know
|
|
29
|
+
attributes:
|
|
30
|
+
label: What's known about the format
|
|
31
|
+
description: Magic numbers, sector sizes, existing documentation or tools, sample images available. The more concrete the bytes, the better.
|
|
32
|
+
validations:
|
|
33
|
+
required: false
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<!-- One deliverable per branch, one issue per deliverable. The issue is the spec. -->
|
|
2
|
+
|
|
3
|
+
Closes #
|
|
4
|
+
|
|
5
|
+
## What this changes
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
## Which layer
|
|
10
|
+
|
|
11
|
+
<!-- Keep the layers independent. Tick what this touches. -->
|
|
12
|
+
|
|
13
|
+
- [ ] `container/` — sectors in, flat 2048-byte sectors out (no sampler knowledge)
|
|
14
|
+
- [ ] `fs/` — a sampler filesystem
|
|
15
|
+
- [ ] `sample/` — a sample format
|
|
16
|
+
- [ ] `docs/` only
|
|
17
|
+
|
|
18
|
+
## Checklist
|
|
19
|
+
|
|
20
|
+
- [ ] No disc images or extracted audio added (CI enforces this; see [ADR-0008](docs/adr/0008-no-media-in-the-repo.md))
|
|
21
|
+
- [ ] New format constants are documented in `docs/formats/` and asserted in a test
|
|
22
|
+
- [ ] `uv run ruff check .` and `uv run ruff format --check .` pass
|
|
23
|
+
- [ ] `uv run pytest -q` passes
|
|
24
|
+
- [ ] `uv tool install --editable . && samplerdisc --version` works
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
verify:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
steps:
|
|
12
|
+
- uses: actions/checkout@v4
|
|
13
|
+
|
|
14
|
+
- name: Install uv
|
|
15
|
+
uses: astral-sh/setup-uv@v5
|
|
16
|
+
with:
|
|
17
|
+
enable-cache: true
|
|
18
|
+
|
|
19
|
+
- run: uv sync --all-extras --dev
|
|
20
|
+
|
|
21
|
+
- name: Lint
|
|
22
|
+
run: uv run ruff check .
|
|
23
|
+
|
|
24
|
+
- name: Format
|
|
25
|
+
run: uv run ruff format --check .
|
|
26
|
+
|
|
27
|
+
- name: Test
|
|
28
|
+
run: uv run pytest -q
|
|
29
|
+
|
|
30
|
+
# A passing suite and a working installed entrypoint are not the same
|
|
31
|
+
# thing, and that gap is where a broken `bin` hides.
|
|
32
|
+
- name: Installed entrypoint
|
|
33
|
+
run: |
|
|
34
|
+
uv tool install --editable .
|
|
35
|
+
samplerdisc --version
|
|
36
|
+
|
|
37
|
+
# ADR-0008: no disc images or audio, ever. Enforced, not remembered.
|
|
38
|
+
- name: No media in tracked files
|
|
39
|
+
run: |
|
|
40
|
+
if git ls-files | grep -iE '\.(mdx|nrg|iso|img|bin|cue|mds|mdf|cdr|tao|wav|aif|aiff)$'; then
|
|
41
|
+
echo "::error::Disc image or audio file is tracked. See docs/adr/0008-no-media-in-the-repo.md"
|
|
42
|
+
exit 1
|
|
43
|
+
fi
|
|
44
|
+
echo "clean"
|
|
45
|
+
|
|
46
|
+
# The Containerfile is a runner for untrusted images (ADR-0038), and a
|
|
47
|
+
# Containerfile nobody builds is one that quietly stops working. This job
|
|
48
|
+
# builds it and smoke-tests the entrypoint. It is deliberately separate from
|
|
49
|
+
# `verify` and not part of branch protection's required check: a registry
|
|
50
|
+
# hiccup pulling the base image should not block a merge.
|
|
51
|
+
container:
|
|
52
|
+
runs-on: ubuntu-latest
|
|
53
|
+
steps:
|
|
54
|
+
- uses: actions/checkout@v4
|
|
55
|
+
|
|
56
|
+
- name: Build image
|
|
57
|
+
run: docker build -f Containerfile -t samplerdisc .
|
|
58
|
+
|
|
59
|
+
- name: Installed entrypoint
|
|
60
|
+
run: docker run --rm samplerdisc --version
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
# Publish to PyPI when a v* tag is pushed. The tag is the trigger, so a release
|
|
4
|
+
# is `git tag vX.Y.Z && git push --tags` and nothing else — no token lives here.
|
|
5
|
+
# Uploads go through PyPI Trusted Publishing (OIDC): PyPI is configured to trust
|
|
6
|
+
# this repository's `pypi` environment, and the `publish` job mints a short-lived
|
|
7
|
+
# credential per run. There is no API token to leak from a public repo.
|
|
8
|
+
#
|
|
9
|
+
# One-time setup on PyPI (Trusted Publisher, "pending" until the first release):
|
|
10
|
+
# https://pypi.org/manage/account/publishing/
|
|
11
|
+
# PyPI project name: samplerdisc
|
|
12
|
+
# Owner: bmxcode
|
|
13
|
+
# Repository: samplerdisc
|
|
14
|
+
# Workflow name: release.yml
|
|
15
|
+
# Environment: pypi
|
|
16
|
+
# and create a repository environment named `pypi` (Settings -> Environments),
|
|
17
|
+
# optionally restricted to tags matching v*.
|
|
18
|
+
|
|
19
|
+
on:
|
|
20
|
+
push:
|
|
21
|
+
tags: ["v*"]
|
|
22
|
+
|
|
23
|
+
permissions: {}
|
|
24
|
+
|
|
25
|
+
jobs:
|
|
26
|
+
build:
|
|
27
|
+
runs-on: ubuntu-latest
|
|
28
|
+
steps:
|
|
29
|
+
- uses: actions/checkout@v4
|
|
30
|
+
|
|
31
|
+
- name: Install uv
|
|
32
|
+
uses: astral-sh/setup-uv@v5
|
|
33
|
+
|
|
34
|
+
# The tag is the version, and a tag that disagrees with pyproject would
|
|
35
|
+
# publish the wrong number under the right name. Fail loud instead — the
|
|
36
|
+
# same "enforced, not remembered" reflex as the no-media check in ci.yml.
|
|
37
|
+
- name: Tag matches project version
|
|
38
|
+
run: |
|
|
39
|
+
tag="${GITHUB_REF_NAME#v}"
|
|
40
|
+
proj="$(uv version --short)"
|
|
41
|
+
if [ "$tag" != "$proj" ]; then
|
|
42
|
+
echo "::error::tag v$tag != pyproject version $proj"
|
|
43
|
+
exit 1
|
|
44
|
+
fi
|
|
45
|
+
echo "v$tag matches pyproject"
|
|
46
|
+
|
|
47
|
+
- name: Build sdist and wheel
|
|
48
|
+
run: uv build
|
|
49
|
+
|
|
50
|
+
- name: Check metadata renders
|
|
51
|
+
run: uvx twine check dist/*
|
|
52
|
+
|
|
53
|
+
- uses: actions/upload-artifact@v4
|
|
54
|
+
with:
|
|
55
|
+
name: dist
|
|
56
|
+
path: dist/
|
|
57
|
+
|
|
58
|
+
publish:
|
|
59
|
+
needs: build
|
|
60
|
+
runs-on: ubuntu-latest
|
|
61
|
+
environment: pypi
|
|
62
|
+
permissions:
|
|
63
|
+
id-token: write # OIDC token for Trusted Publishing; nothing else
|
|
64
|
+
steps:
|
|
65
|
+
- uses: actions/download-artifact@v4
|
|
66
|
+
with:
|
|
67
|
+
name: dist
|
|
68
|
+
path: dist/
|
|
69
|
+
|
|
70
|
+
- name: Publish to PyPI
|
|
71
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Disc images and extracted audio are never committed. See ADR-0008.
|
|
2
|
+
# These are commercial sample libraries; the repo is public and git history
|
|
3
|
+
# is exposed retroactively. This list comes before anything else on purpose.
|
|
4
|
+
*.mdx
|
|
5
|
+
*.nrg
|
|
6
|
+
*.iso
|
|
7
|
+
*.img
|
|
8
|
+
*.bin
|
|
9
|
+
*.cue
|
|
10
|
+
*.mds
|
|
11
|
+
*.mdf
|
|
12
|
+
*.cdr
|
|
13
|
+
*.tao
|
|
14
|
+
*.ccd
|
|
15
|
+
*.wav
|
|
16
|
+
*.aif
|
|
17
|
+
*.aiff
|
|
18
|
+
out/
|
|
19
|
+
discs/
|
|
20
|
+
retro-sample-cds/
|
|
21
|
+
|
|
22
|
+
# Archives holding disc images are the same rule: a .zip of a sample library
|
|
23
|
+
# is still a sample library.
|
|
24
|
+
*.zip
|
|
25
|
+
*.7z
|
|
26
|
+
*.rar
|
|
27
|
+
*.tar
|
|
28
|
+
*.tar.gz
|
|
29
|
+
*.tgz
|
|
30
|
+
|
|
31
|
+
# Python
|
|
32
|
+
__pycache__/
|
|
33
|
+
*.py[cod]
|
|
34
|
+
.venv/
|
|
35
|
+
dist/
|
|
36
|
+
build/
|
|
37
|
+
*.egg-info/
|
|
38
|
+
.pytest_cache/
|
|
39
|
+
.ruff_cache/
|
|
40
|
+
|
|
41
|
+
# Editor / OS
|
|
42
|
+
.DS_Store
|
|
43
|
+
.idea/
|
|
44
|
+
.claude/
|