rekordbox-edit 0.6.0.dev13__tar.gz → 0.6.0.dev29__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 (86) hide show
  1. rekordbox_edit-0.6.0.dev29/.github/actions/e2e/action.yml +27 -0
  2. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/.github/workflows/ci.yml +26 -1
  3. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/.pre-commit-config.yaml +3 -0
  4. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/CHANGELOG.md +68 -3
  5. rekordbox_edit-0.6.0.dev29/Makefile +36 -0
  6. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/PKG-INFO +1 -1
  7. rekordbox_edit-0.6.0.dev29/docker-compose.yml +14 -0
  8. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/pyproject.toml +8 -1
  9. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/rekordbox_edit/cli/main.py +7 -0
  10. rekordbox_edit-0.6.0.dev29/tests/e2e/Dockerfile +14 -0
  11. rekordbox_edit-0.6.0.dev29/tests/e2e/__init__.py +0 -0
  12. rekordbox_edit-0.6.0.dev29/tests/e2e/__snapshots__/test_journey/test_search_full_json_snapshot[macos].json +824 -0
  13. rekordbox_edit-0.6.0.dev29/tests/e2e/__snapshots__/test_journey/test_search_full_json_snapshot[windows].json +824 -0
  14. rekordbox_edit-0.6.0.dev29/tests/e2e/__snapshots__/test_journey.ambr +13 -0
  15. rekordbox_edit-0.6.0.dev29/tests/e2e/conftest.py +163 -0
  16. rekordbox_edit-0.6.0.dev29/tests/e2e/fixtures/audio/01-flac-44_1k-16b.flac +0 -0
  17. rekordbox_edit-0.6.0.dev29/tests/e2e/fixtures/audio/02-flac-96k-24b.flac +0 -0
  18. rekordbox_edit-0.6.0.dev29/tests/e2e/fixtures/audio/03-alac-44_1k-16b.m4a +0 -0
  19. rekordbox_edit-0.6.0.dev29/tests/e2e/fixtures/audio/04-alac-48k-24b.m4a +0 -0
  20. rekordbox_edit-0.6.0.dev29/tests/e2e/fixtures/audio/05-aiff-44_1k-16b.aiff +0 -0
  21. rekordbox_edit-0.6.0.dev29/tests/e2e/fixtures/audio/06-wav-96k-24b.wav +0 -0
  22. rekordbox_edit-0.6.0.dev29/tests/e2e/fixtures/audio/07-mp3-44_1k-320cbr.mp3 +0 -0
  23. rekordbox_edit-0.6.0.dev29/tests/e2e/fixtures/audio/08-mp3-44_1k-v0vbr.mp3 +0 -0
  24. rekordbox_edit-0.6.0.dev29/tests/e2e/fixtures/audio/09-aac-44_1k-256kbps.m4a +0 -0
  25. rekordbox_edit-0.6.0.dev29/tests/e2e/fixtures/audio/10-/303/274/303/261/303/256c/303/266d/303/251-flac-44_1k-16b.flac +0 -0
  26. rekordbox_edit-0.6.0.dev29/tests/e2e/fixtures/macos/master.6.8.6.db +0 -0
  27. rekordbox_edit-0.6.0.dev29/tests/e2e/fixtures/windows/master.6.8.6.db +0 -0
  28. rekordbox_edit-0.6.0.dev29/tests/e2e/test_journey.py +213 -0
  29. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/uv.lock +15 -1
  30. rekordbox_edit-0.6.0.dev13/Makefile +0 -25
  31. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/.agent-style/RULES.md +0 -0
  32. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/.agent-style/claude-code.md +0 -0
  33. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/.github/actions/build-release-notes/action.yml +0 -0
  34. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/.github/actions/commitizen-bump/action.yml +0 -0
  35. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/.github/actions/commitizen-bump/commitizen-bump.sh +0 -0
  36. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/.github/actions/install/action.yml +0 -0
  37. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/.github/actions/lint/action.yml +0 -0
  38. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/.github/actions/test/action.yml +0 -0
  39. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/.github/workflows/cd.yml +0 -0
  40. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/.github/workflows/publish.yml +0 -0
  41. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/.github/workflows/release.yml +0 -0
  42. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/.gitignore +0 -0
  43. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/.python-version +0 -0
  44. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/AGENTS.md +0 -0
  45. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/CLAUDE.md +0 -0
  46. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/CONTRIBUTING.md +0 -0
  47. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/LICENSE +0 -0
  48. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/README.md +0 -0
  49. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/codecov.yml +0 -0
  50. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/rekordbox_edit/__init__.py +0 -0
  51. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/rekordbox_edit/_click.py +0 -0
  52. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/rekordbox_edit/api/__init__.py +0 -0
  53. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/rekordbox_edit/api/_utils.py +0 -0
  54. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/rekordbox_edit/api/convert.py +0 -0
  55. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/rekordbox_edit/api/edit.py +0 -0
  56. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/rekordbox_edit/api/search.py +0 -0
  57. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/rekordbox_edit/cli/__init__.py +0 -0
  58. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/rekordbox_edit/cli/_utils.py +0 -0
  59. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/rekordbox_edit/cli/convert.py +0 -0
  60. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/rekordbox_edit/cli/edit.py +0 -0
  61. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/rekordbox_edit/cli/search.py +0 -0
  62. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/rekordbox_edit/display.py +0 -0
  63. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/rekordbox_edit/logger.py +0 -0
  64. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/rekordbox_edit/models.py +0 -0
  65. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/rekordbox_edit/query.py +0 -0
  66. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/rekordbox_edit/utils.py +0 -0
  67. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/renovate.json5 +0 -0
  68. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/ruff.toml +0 -0
  69. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/tests/__init__.py +0 -0
  70. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/tests/api/__init__.py +0 -0
  71. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/tests/api/test_convert.py +0 -0
  72. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/tests/api/test_edit.py +0 -0
  73. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/tests/api/test_search.py +0 -0
  74. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/tests/api/test_utils.py +0 -0
  75. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/tests/cli/__init__.py +0 -0
  76. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/tests/cli/test_convert.py +0 -0
  77. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/tests/cli/test_edit.py +0 -0
  78. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/tests/cli/test_main.py +0 -0
  79. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/tests/cli/test_search.py +0 -0
  80. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/tests/cli/test_utils.py +0 -0
  81. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/tests/conftest.py +0 -0
  82. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/tests/test_display.py +0 -0
  83. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/tests/test_logger.py +0 -0
  84. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/tests/test_models.py +0 -0
  85. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/tests/test_query.py +0 -0
  86. {rekordbox_edit-0.6.0.dev13 → rekordbox_edit-0.6.0.dev29}/tests/test_utils.py +0 -0
@@ -0,0 +1,27 @@
1
+ name: "Run E2E Tests"
2
+ description: "Install platform ffmpeg, set up Python, run the e2e journey suite"
3
+
4
+ runs:
5
+ using: "composite"
6
+ steps:
7
+ - name: Setup UV
8
+ uses: ./.github/actions/install
9
+
10
+ - name: Install ffmpeg (macOS)
11
+ if: runner.os == 'macOS'
12
+ shell: bash
13
+ run: brew install ffmpeg
14
+
15
+ - name: Install ffmpeg (Windows)
16
+ if: runner.os == 'Windows'
17
+ shell: pwsh
18
+ run: choco install ffmpeg -y
19
+
20
+ - name: Run e2e suite
21
+ shell: bash
22
+ env:
23
+ RBE_RUN_E2E: "1"
24
+ TZ: "UTC"
25
+ run: |
26
+ : "${RBE_DB_VERSION:?RBE_DB_VERSION must be set by the caller (matrix dimension).}"
27
+ uv run pytest tests/e2e --snapshot-warn-unused
@@ -66,16 +66,41 @@ jobs:
66
66
 
67
67
  - name: Run unit tests
68
68
  uses: ./.github/actions/test
69
+
70
+ e2e-tests:
71
+ name: 🎚️ E2E
72
+ needs: code-change
73
+ if: ${{ needs.code-change.outputs.should_skip != 'true' && !fromJSON(needs.code-change.outputs.paths_result || '{}').code.should_skip }}
74
+ strategy:
75
+ fail-fast: false
76
+ matrix:
77
+ os: ["macos-latest", "windows-latest"]
78
+ python-version: ["3.11", "3.14"]
79
+ rb-version: ["6.8.6"]
80
+ runs-on: ${{ matrix.os }}
81
+ env:
82
+ OS: ${{ matrix.os }}
83
+ PYTHON: ${{ matrix.python-version }}
84
+ RBE_DB_VERSION: ${{ matrix.rb-version }}
85
+
86
+ steps:
87
+ - name: Checkout code
88
+ uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
89
+
90
+ - name: Run e2e tests
91
+ uses: ./.github/actions/e2e
92
+
69
93
  all-green:
70
94
  name: ✅ All Green
71
95
  if: always()
72
96
  needs:
73
97
  - lint
74
98
  - unit-tests
99
+ - e2e-tests
75
100
  runs-on: Ubuntu-latest
76
101
 
77
102
  steps:
78
103
  - uses: re-actors/alls-green@05ac9388f0aebcb5727afa17fcccfecd6f8ec5fe # release/v1
79
104
  with:
80
- allowed-skips: unit-tests, lint
105
+ allowed-skips: unit-tests, lint, e2e-tests
81
106
  jobs: ${{ toJSON(needs) }}
@@ -7,9 +7,12 @@ repos:
7
7
  rev: v6.0.0
8
8
  hooks:
9
9
  - id: trailing-whitespace
10
+ exclude: '^tests/e2e/__snapshots__/'
10
11
  - id: end-of-file-fixer
12
+ exclude: '^tests/e2e/__snapshots__/'
11
13
  - id: check-yaml
12
14
  - id: check-added-large-files
15
+ args: [--maxkb=1024]
13
16
  - id: check-merge-conflict
14
17
  - id: debug-statements
15
18
  - id: check-toml
@@ -1,6 +1,71 @@
1
- ## v0.6.0.dev13 (2026-06-09)
2
-
3
-
1
+ ## v0.6.0.dev29 (2026-06-10)
2
+
3
+
4
+ - test(e2e): update windows snapshot with unicode representation
5
+ - test(e2e): force utf-8 encoding of stdout
6
+ - test(e2e): align TZ to UTC
7
+ - test(ci): parameterize the db version as an env var
8
+ - ci(e2e): add windows-latest to the e2e matrix
9
+ - test: add windows snapshots for e2e journey
10
+ - test(e2e): parameterize snapshots by fixture DB
11
+ - Routes the two contract snapshots through SNAPSHOT_KEY (macos/windows)
12
+ so the Windows fixture can land its own snapshot alongside the macOS
13
+ one. Docker reuses the macOS DB and therefore the macos key.
14
+ Renames the existing snapshot entries to the [macos] variant.
15
+ - test: adds 6.8.6 db fixture for windows
16
+ - test(e2e): pretty-print JSON snapshots via JSONSnapshotExtension
17
+ - The single-line raw CLI output made snapshot diffs unreadable when a contract
18
+ field changed. Use syrupy's JSONSnapshotExtension for the search-json test:
19
+ the parsed payload is dumped as indented JSON to its own .json file under
20
+ __snapshots__/test_journey/, so post-update diffs land per-field.
21
+ - The IDs snapshot stays on AmberExtension; it's already one short line.
22
+ - ci(e2e): add macos-latest e2e job to the matrix and require it
23
+ - Adds a new e2e-tests job to ci.yml matrix'd over macos-latest × Python
24
+ {3.11, 3.14}, wiring it into the all-green aggregate so branch protection
25
+ gates on it. Windows joins in a follow-up PR once a windows master.db
26
+ fixture exists.
27
+ - The composite action at .github/actions/e2e/ installs ffmpeg on the runner,
28
+ sets RBE_RUN_E2E=1, and runs pytest against tests/e2e directly.
29
+ - test(e2e): add docker leg and make targets
30
+ - Local e2e validation runs through a Linux container; the conftest refuses to
31
+ run on bare macOS/Windows. `make test-e2e-docker` builds the image (Python
32
+ 3.14 + ffmpeg + uv-synced project) and runs the journey suite;
33
+ `make test-e2e-snapshot-update` regenerates snapshots inside the container so
34
+ the host's working tree picks them up via the volume mount.
35
+ - `make test-e2e` runs the suite directly with uv; useful inside the container
36
+ itself or in CI runners where the platform check passes.
37
+ - test(e2e): add journey suite, conftest, and macOS snapshots
38
+ - A single ordered file walks search → edit → convert against the committed
39
+ macOS master.6.8.6.db, exercising filter narrowing, dry-run safety, stdin-pipe
40
+ edits, unicode metadata, and the convert row-swap. Snapshots lock the JSON
41
+ and IDs print contracts for `search`.
42
+ - The conftest gates the suite behind RBE_RUN_E2E=1 and refuses to run on
43
+ macOS/Windows outside CI, pointing local users at the Docker leg. The
44
+ canonical staging path is /private/tmp/rbedit-e2e/music — macOS resolves
45
+ /tmp through that symlink, so the DB stores the canonical form.
46
+ - Excludes tests/e2e/__snapshots__/ from the trailing-whitespace and
47
+ end-of-file pre-commit hooks; syrupy-generated whitespace is meaningful.
48
+ - test(e2e): register marker, exclude from default collection, add syrupy
49
+ - Adds the `e2e` pytest marker, sets `norecursedirs` so default `make test` runs
50
+ do not collect the suite, and pins syrupy>=5 for snapshot assertions.
51
+ - test: add macos 6.8.6 db fixture
52
+ - test(e2e): rename audio fixtures to property-encoded scheme
53
+ - Filenames now describe the audio's discriminating properties
54
+ (NN-<codec>-<rate>-<depth-or-bitrate>[-encmode].<ext>) so each file's purpose
55
+ is obvious in a directory listing and in test code. Codec stays in the name
56
+ even for unambiguous extensions to keep the convention uniform and to
57
+ disambiguate ALAC vs AAC inside .m4a.
58
+ - Required before Phase 3 (Rekordbox import) so master.db references the new
59
+ paths. Generator script and library table updated in gist
60
+ https://gist.github.com/jviall/18107ca35e0e7f38cf02ba50e3b9cc77
61
+ - test(e2e): add 10-track audio fixture for end-to-end suite
62
+ - Synthesized sine-wave audio covering FLAC (16/24-bit), ALAC, AIFF, WAV,
63
+ MP3 (CBR + VBR), AAC, and a unicode-tagged FLAC. Used by the e2e journey
64
+ suite (search/edit/convert) against the committed master.db fixtures.
65
+ - Bumps pre-commit's check-added-large-files threshold to 1 MB to admit the
66
+ WAV fixture (563 KB at 96 kHz / 24-bit / 2 s mono).
67
+ - Generator script and Phase 3 (Rekordbox import) instructions:
68
+ https://gist.github.com/jviall/18107ca35e0e7f38cf02ba50e3b9cc77
4
69
  - fix(query): order results by folder, then ID, for stable output
5
70
  - feat: adds global --database-path argument
6
71
  - chore(deps): update linters to v0.0.44 (#79)
@@ -0,0 +1,36 @@
1
+ .PHONY: test test-e2e test-e2e-docker test-e2e-snapshot-update coverage lint format typecheck install-hooks run-hooks
2
+
3
+ test:
4
+ uv run pytest tests
5
+
6
+ RBE_DB_VERSION ?= 6.8.6
7
+
8
+ test-e2e:
9
+ RBE_DB_VERSION=$(RBE_DB_VERSION) uv run pytest tests/e2e --snapshot-warn-unused
10
+
11
+ test-e2e-docker:
12
+ RBE_DB_VERSION=$(RBE_DB_VERSION) docker compose run --rm e2e
13
+
14
+ test-e2e-snapshot-update:
15
+ RBE_DB_VERSION=$(RBE_DB_VERSION) docker compose run --rm e2e uv run pytest tests/e2e --snapshot-update
16
+
17
+ watch:
18
+ uv run ptw .
19
+
20
+ coverage:
21
+ uv run pytest tests --cov=rekordbox_edit --junitxml=.coverage/junit.xml --cov-report=term-missing --cov-report=html --cov-report=xml
22
+
23
+ lint:
24
+ uv run ruff check --fix
25
+
26
+ format:
27
+ uv run ruff format
28
+
29
+ typecheck:
30
+ uv run ty check
31
+
32
+ install-hooks:
33
+ uv run pre-commit install --hook-type pre-commit --hook-type commit-msg
34
+
35
+ run-hooks:
36
+ uv run pre-commit run --all-files
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rekordbox-edit
3
- Version: 0.6.0.dev13
3
+ Version: 0.6.0.dev29
4
4
  Summary: Tools for managing and modifying a RekordBox library en-masse
5
5
  Project-URL: Homepage, https://github.com/jviall/rekordbox-edit
6
6
  Project-URL: Repository, https://github.com/jviall/rekordbox-edit
@@ -0,0 +1,14 @@
1
+ services:
2
+ e2e:
3
+ build:
4
+ context: .
5
+ dockerfile: tests/e2e/Dockerfile
6
+ environment:
7
+ RBE_RUN_E2E: "1"
8
+ RBE_DB_VERSION: "${RBE_DB_VERSION:?RBE_DB_VERSION must be set (e.g. 6.8.6)}"
9
+ TZ: "UTC"
10
+ volumes:
11
+ # Mount the source tree so generated snapshots flow back to the host;
12
+ # uv.lock is read from the image's pre-built .venv at /app/.venv.
13
+ - .:/app
14
+ - /app/.venv
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "rekordbox-edit"
7
- version = "0.6.0.dev13"
7
+ version = "0.6.0.dev29"
8
8
  description = "Tools for managing and modifying a RekordBox library en-masse"
9
9
  authors = [{ name = "James Viall", email= "jamesviall@pm.me"}]
10
10
  license = "MIT"
@@ -31,8 +31,15 @@ dev = [
31
31
  "pytest-watcher>=0.6.3,<1",
32
32
  "callee>=0.3.1,<1",
33
33
  "ty>=0.0.1,<1",
34
+ "syrupy>=5,<6",
34
35
  ]
35
36
 
37
+ [tool.pytest.ini_options]
38
+ markers = [
39
+ "e2e: end-to-end tests requiring audio fixtures and RBE_RUN_E2E=1",
40
+ ]
41
+ norecursedirs = ["tests/e2e"]
42
+
36
43
  [project.urls]
37
44
  Homepage = "https://github.com/jviall/rekordbox-edit"
38
45
  Repository = "https://github.com/jviall/rekordbox-edit"
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env python3
2
2
  """Command line interface for rekordbox-edit."""
3
3
 
4
+ import io
4
5
  import logging
5
6
  import sys
6
7
 
@@ -30,6 +31,12 @@ cli.add_command(convert_command)
30
31
 
31
32
  def main():
32
33
  """Entry point for the CLI."""
34
+ # Force UTF-8 on the standard streams so non-ASCII titles, paths, and
35
+ # artist names survive piping on Windows (default cp1252 mangles them to
36
+ # '?'). This is the in-script equivalent of running with PYTHONUTF8=1.
37
+ for stream in (sys.stdin, sys.stdout, sys.stderr):
38
+ if isinstance(stream, io.TextIOWrapper):
39
+ stream.reconfigure(encoding="utf-8")
33
40
  try:
34
41
  setup_logging()
35
42
  logger.debug(f"Running with input: {' '.join(sys.argv)}")
@@ -0,0 +1,14 @@
1
+ FROM python:3.14-slim
2
+
3
+ RUN apt-get update \
4
+ && apt-get install -y --no-install-recommends ffmpeg make ca-certificates \
5
+ && rm -rf /var/lib/apt/lists/*
6
+
7
+ RUN pip install --no-cache-dir uv
8
+
9
+ WORKDIR /app
10
+ COPY . .
11
+ RUN uv sync --frozen
12
+
13
+ ENV RBE_RUN_E2E=1
14
+ CMD ["make", "test-e2e"]
File without changes