rekordbox-edit 0.4.0.dev40__tar.gz → 0.4.0.dev41__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 (48) hide show
  1. {rekordbox_edit-0.4.0.dev40 → rekordbox_edit-0.4.0.dev41}/CHANGELOG.md +2 -1
  2. {rekordbox_edit-0.4.0.dev40 → rekordbox_edit-0.4.0.dev41}/PKG-INFO +1 -1
  3. {rekordbox_edit-0.4.0.dev40 → rekordbox_edit-0.4.0.dev41}/pyproject.toml +1 -1
  4. {rekordbox_edit-0.4.0.dev40 → rekordbox_edit-0.4.0.dev41}/rekordbox_edit/args.py +23 -0
  5. {rekordbox_edit-0.4.0.dev40 → rekordbox_edit-0.4.0.dev41}/rekordbox_edit/commands/convert.py +43 -18
  6. {rekordbox_edit-0.4.0.dev40 → rekordbox_edit-0.4.0.dev41}/rekordbox_edit/commands/edit.py +43 -18
  7. {rekordbox_edit-0.4.0.dev40 → rekordbox_edit-0.4.0.dev41}/uv.lock +1 -1
  8. {rekordbox_edit-0.4.0.dev40 → rekordbox_edit-0.4.0.dev41}/.agent-style/RULES.md +0 -0
  9. {rekordbox_edit-0.4.0.dev40 → rekordbox_edit-0.4.0.dev41}/.agent-style/claude-code.md +0 -0
  10. {rekordbox_edit-0.4.0.dev40 → rekordbox_edit-0.4.0.dev41}/.github/actions/commitizen-bump/action.yml +0 -0
  11. {rekordbox_edit-0.4.0.dev40 → rekordbox_edit-0.4.0.dev41}/.github/actions/commitizen-bump/commitizen-bump.sh +0 -0
  12. {rekordbox_edit-0.4.0.dev40 → rekordbox_edit-0.4.0.dev41}/.github/actions/install/action.yml +0 -0
  13. {rekordbox_edit-0.4.0.dev40 → rekordbox_edit-0.4.0.dev41}/.github/actions/lint/action.yml +0 -0
  14. {rekordbox_edit-0.4.0.dev40 → rekordbox_edit-0.4.0.dev41}/.github/actions/test/action.yml +0 -0
  15. {rekordbox_edit-0.4.0.dev40 → rekordbox_edit-0.4.0.dev41}/.github/workflows/cd.yml +0 -0
  16. {rekordbox_edit-0.4.0.dev40 → rekordbox_edit-0.4.0.dev41}/.github/workflows/ci.yml +0 -0
  17. {rekordbox_edit-0.4.0.dev40 → rekordbox_edit-0.4.0.dev41}/.github/workflows/publish.yml +0 -0
  18. {rekordbox_edit-0.4.0.dev40 → rekordbox_edit-0.4.0.dev41}/.github/workflows/release.yml +0 -0
  19. {rekordbox_edit-0.4.0.dev40 → rekordbox_edit-0.4.0.dev41}/.gitignore +0 -0
  20. {rekordbox_edit-0.4.0.dev40 → rekordbox_edit-0.4.0.dev41}/.pre-commit-config.yaml +0 -0
  21. {rekordbox_edit-0.4.0.dev40 → rekordbox_edit-0.4.0.dev41}/AGENTS.md +0 -0
  22. {rekordbox_edit-0.4.0.dev40 → rekordbox_edit-0.4.0.dev41}/CLAUDE.md +0 -0
  23. {rekordbox_edit-0.4.0.dev40 → rekordbox_edit-0.4.0.dev41}/CONTRIBUTING.md +0 -0
  24. {rekordbox_edit-0.4.0.dev40 → rekordbox_edit-0.4.0.dev41}/LICENSE +0 -0
  25. {rekordbox_edit-0.4.0.dev40 → rekordbox_edit-0.4.0.dev41}/Makefile +0 -0
  26. {rekordbox_edit-0.4.0.dev40 → rekordbox_edit-0.4.0.dev41}/README.md +0 -0
  27. {rekordbox_edit-0.4.0.dev40 → rekordbox_edit-0.4.0.dev41}/codecov.yml +0 -0
  28. {rekordbox_edit-0.4.0.dev40 → rekordbox_edit-0.4.0.dev41}/rekordbox_edit/__init__.py +0 -0
  29. {rekordbox_edit-0.4.0.dev40 → rekordbox_edit-0.4.0.dev41}/rekordbox_edit/_click.py +0 -0
  30. {rekordbox_edit-0.4.0.dev40 → rekordbox_edit-0.4.0.dev41}/rekordbox_edit/cli.py +0 -0
  31. {rekordbox_edit-0.4.0.dev40 → rekordbox_edit-0.4.0.dev41}/rekordbox_edit/commands/__init__.py +0 -0
  32. {rekordbox_edit-0.4.0.dev40 → rekordbox_edit-0.4.0.dev41}/rekordbox_edit/commands/search.py +0 -0
  33. {rekordbox_edit-0.4.0.dev40 → rekordbox_edit-0.4.0.dev41}/rekordbox_edit/display.py +0 -0
  34. {rekordbox_edit-0.4.0.dev40 → rekordbox_edit-0.4.0.dev41}/rekordbox_edit/logger.py +0 -0
  35. {rekordbox_edit-0.4.0.dev40 → rekordbox_edit-0.4.0.dev41}/rekordbox_edit/query.py +0 -0
  36. {rekordbox_edit-0.4.0.dev40 → rekordbox_edit-0.4.0.dev41}/rekordbox_edit/utils.py +0 -0
  37. {rekordbox_edit-0.4.0.dev40 → rekordbox_edit-0.4.0.dev41}/renovate.json5 +0 -0
  38. {rekordbox_edit-0.4.0.dev40 → rekordbox_edit-0.4.0.dev41}/ruff.toml +0 -0
  39. {rekordbox_edit-0.4.0.dev40 → rekordbox_edit-0.4.0.dev41}/tests/__init__.py +0 -0
  40. {rekordbox_edit-0.4.0.dev40 → rekordbox_edit-0.4.0.dev41}/tests/commands/__init__.py +0 -0
  41. {rekordbox_edit-0.4.0.dev40 → rekordbox_edit-0.4.0.dev41}/tests/commands/test_convert.py +0 -0
  42. {rekordbox_edit-0.4.0.dev40 → rekordbox_edit-0.4.0.dev41}/tests/commands/test_edit.py +0 -0
  43. {rekordbox_edit-0.4.0.dev40 → rekordbox_edit-0.4.0.dev41}/tests/commands/test_search.py +0 -0
  44. {rekordbox_edit-0.4.0.dev40 → rekordbox_edit-0.4.0.dev41}/tests/conftest.py +0 -0
  45. {rekordbox_edit-0.4.0.dev40 → rekordbox_edit-0.4.0.dev41}/tests/test_display.py +0 -0
  46. {rekordbox_edit-0.4.0.dev40 → rekordbox_edit-0.4.0.dev41}/tests/test_logger.py +0 -0
  47. {rekordbox_edit-0.4.0.dev40 → rekordbox_edit-0.4.0.dev41}/tests/test_query.py +0 -0
  48. {rekordbox_edit-0.4.0.dev40 → rekordbox_edit-0.4.0.dev41}/tests/test_utils.py +0 -0
@@ -1,6 +1,7 @@
1
- ## v0.4.0.dev40 (2026-06-05)
1
+ ## v0.4.0.dev41 (2026-06-05)
2
2
 
3
3
 
4
+ - refactor(commands): group confirmation flags into ConfirmationArgs dataclass
4
5
  - docs: update README.md
5
6
  - refactor(query): group filter args into FilterArgs dataclass
6
7
  - refactor(cli): extract convert-specific options into convert_click_options
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rekordbox-edit
3
- Version: 0.4.0.dev40
3
+ Version: 0.4.0.dev41
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
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "rekordbox-edit"
7
- version = "0.4.0.dev40"
7
+ version = "0.4.0.dev41"
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"
@@ -52,3 +52,26 @@ def filter_args_from_kwargs(**kwargs) -> FilterArgs:
52
52
  format=list(kwargs.get("format") or []),
53
53
  match_all=bool(kwargs.get("match_all", False)),
54
54
  )
55
+
56
+
57
+ @dataclass
58
+ class ConfirmationArgs:
59
+ """How the user gates a side effect before it lands.
60
+
61
+ `dry_run` skips the change entirely. `yes` skips confirmation and applies
62
+ the batch. `interactive` prompts per item. With all three false, the
63
+ caller is expected to prompt once for the batch.
64
+ """
65
+
66
+ dry_run: bool = False
67
+ yes: bool = False
68
+ interactive: bool = False
69
+
70
+
71
+ def confirmation_args_from_kwargs(**kwargs) -> ConfirmationArgs:
72
+ """Pack the flat Click kwargs for the `global_click_confirmations` group into a ConfirmationArgs."""
73
+ return ConfirmationArgs(
74
+ dry_run=bool(kwargs.get("dry_run", False)),
75
+ yes=bool(kwargs.get("yes", False)),
76
+ interactive=bool(kwargs.get("interactive", False)),
77
+ )
@@ -22,7 +22,12 @@ from rekordbox_edit._click import (
22
22
  print_option,
23
23
  track_ids_argument,
24
24
  )
25
- from rekordbox_edit.args import filter_args_from_kwargs
25
+ from rekordbox_edit.args import (
26
+ ConfirmationArgs,
27
+ FilterArgs,
28
+ confirmation_args_from_kwargs,
29
+ filter_args_from_kwargs,
30
+ )
26
31
  from rekordbox_edit.logger import get_debug_file_path, set_level
27
32
  from rekordbox_edit.query import get_filtered_content
28
33
  from rekordbox_edit.display import PrintableField, print_track_info
@@ -286,15 +291,51 @@ def convert_command(
286
291
 
287
292
  Skips lossy formats and files already in the target format.
288
293
  """
294
+ filters = filter_args_from_kwargs(
295
+ track_id=track_id,
296
+ track_ids=track_ids,
297
+ playlist=playlist,
298
+ exact_playlist=exact_playlist,
299
+ album=album,
300
+ exact_album=exact_album,
301
+ artist=artist,
302
+ exact_artist=exact_artist,
303
+ title=title,
304
+ exact_title=exact_title,
305
+ path=path,
306
+ exact_path=exact_path,
307
+ format=format,
308
+ match_all=match_all,
309
+ )
310
+ confirmation = confirmation_args_from_kwargs(
311
+ dry_run=dry_run, yes=yes, interactive=interactive
312
+ )
313
+ _convert(filters, confirmation, format_out, delete, overwrite, print_opt)
314
+
315
+
316
+ def _convert(
317
+ filters: FilterArgs,
318
+ confirmation: ConfirmationArgs,
319
+ format_out: str,
320
+ delete: bool | None,
321
+ overwrite: bool,
322
+ print_opt: PrintChoice | None,
323
+ ) -> None:
324
+ """Convert audio files for tracks matching `filters`."""
289
325
  from rekordbox_edit.utils import ffmpeg_in_path, get_ffmpeg_directions
290
326
 
327
+ dry_run, yes, interactive = (
328
+ confirmation.dry_run,
329
+ confirmation.yes,
330
+ confirmation.interactive,
331
+ )
291
332
  set_level(print_opt)
292
333
 
293
334
  piped_stdin = not sys.stdin.isatty()
294
335
  if piped_stdin:
295
336
  stdin_data = sys.stdin.read().strip()
296
337
  if stdin_data:
297
- track_ids = list(track_ids or []) + stdin_data.split()
338
+ filters.track_ids = list(filters.track_ids) + stdin_data.split()
298
339
 
299
340
  # Validate --print option requirements
300
341
  scripting_mode = print_opt in (PrintChoice.IDS, PrintChoice.SILENT)
@@ -362,22 +403,6 @@ def convert_command(
362
403
  logger.debug("Database connection established")
363
404
 
364
405
  # === QUERY & FILTER ===
365
- filters = filter_args_from_kwargs(
366
- track_id=track_id,
367
- track_ids=track_ids,
368
- playlist=playlist,
369
- exact_playlist=exact_playlist,
370
- album=album,
371
- exact_album=exact_album,
372
- artist=artist,
373
- exact_artist=exact_artist,
374
- title=title,
375
- exact_title=exact_title,
376
- path=path,
377
- exact_path=exact_path,
378
- format=format,
379
- match_all=match_all,
380
- )
381
406
  result = get_filtered_content(db, filters)
382
407
  filtered_content = result.scalars().all()
383
408
  logger.debug(f"Query returned {len(filtered_content)} tracks")
@@ -16,7 +16,12 @@ from rekordbox_edit._click import (
16
16
  print_option,
17
17
  track_ids_argument,
18
18
  )
19
- from rekordbox_edit.args import filter_args_from_kwargs
19
+ from rekordbox_edit.args import (
20
+ ConfirmationArgs,
21
+ FilterArgs,
22
+ confirmation_args_from_kwargs,
23
+ filter_args_from_kwargs,
24
+ )
20
25
  from rekordbox_edit.logger import get_debug_file_path, set_level
21
26
  from rekordbox_edit.query import get_filtered_content
22
27
  from rekordbox_edit.display import PrintableField, print_track_info
@@ -84,7 +89,43 @@ def edit_command(
84
89
  print_opt: PrintChoice | None,
85
90
  ):
86
91
  """Edit a metadata field on tracks in the RekordBox database."""
92
+ filters = filter_args_from_kwargs(
93
+ track_id=track_id,
94
+ track_ids=track_ids,
95
+ playlist=playlist,
96
+ exact_playlist=exact_playlist,
97
+ album=album,
98
+ exact_album=exact_album,
99
+ artist=artist,
100
+ exact_artist=exact_artist,
101
+ title=title,
102
+ exact_title=exact_title,
103
+ path=path,
104
+ exact_path=exact_path,
105
+ format=format,
106
+ match_all=match_all,
107
+ )
108
+ confirmation = confirmation_args_from_kwargs(
109
+ dry_run=dry_run, yes=yes, interactive=interactive
110
+ )
111
+ _edit(filters, confirmation, field, replace_value, match_pattern, multi, print_opt)
112
+
87
113
 
114
+ def _edit(
115
+ filters: FilterArgs,
116
+ confirmation: ConfirmationArgs,
117
+ field: str,
118
+ replace_value: str,
119
+ match_pattern: str | None,
120
+ multi: bool,
121
+ print_opt: PrintChoice | None,
122
+ ) -> None:
123
+ """Apply a field edit to tracks matching `filters`."""
124
+ dry_run, yes, interactive = (
125
+ confirmation.dry_run,
126
+ confirmation.yes,
127
+ confirmation.interactive,
128
+ )
88
129
  set_level(print_opt)
89
130
 
90
131
  piped_stdin = False
@@ -92,7 +133,7 @@ def edit_command(
92
133
  stdin_data = sys.stdin.read().strip()
93
134
  if stdin_data:
94
135
  piped_stdin = True
95
- track_ids = list(track_ids or []) + stdin_data.split()
136
+ filters.track_ids = list(filters.track_ids) + stdin_data.split()
96
137
 
97
138
  scripting_mode = print_opt in (PrintChoice.IDS, PrintChoice.SILENT)
98
139
  if scripting_mode and not (dry_run or yes):
@@ -107,22 +148,6 @@ def edit_command(
107
148
  if not db.session:
108
149
  raise RuntimeError("Failed to connect to Rekordbox Database: No Session.")
109
150
 
110
- filters = filter_args_from_kwargs(
111
- track_id=track_id,
112
- track_ids=track_ids,
113
- playlist=playlist,
114
- exact_playlist=exact_playlist,
115
- album=album,
116
- exact_album=exact_album,
117
- artist=artist,
118
- exact_artist=exact_artist,
119
- title=title,
120
- exact_title=exact_title,
121
- path=path,
122
- exact_path=exact_path,
123
- format=format,
124
- match_all=match_all,
125
- )
126
151
  result = get_filtered_content(db, filters)
127
152
  tracks = result.scalars().all()
128
153
 
@@ -1010,7 +1010,7 @@ wheels = [
1010
1010
 
1011
1011
  [[package]]
1012
1012
  name = "rekordbox-edit"
1013
- version = "0.4.0.dev40"
1013
+ version = "0.4.0.dev41"
1014
1014
  source = { editable = "." }
1015
1015
  dependencies = [
1016
1016
  { name = "click" },