soulsync/core/imports
Broque Thomas d97d105b97 fix: substitute \$cdnum in download paths and skip auto disc folder when template uses it
User report: multi-disc albums on the latest dev had literal "\$cdnum"
in their filenames instead of the expected "CDxx" label, plus a
redundant "Disc N" folder on top of the in-filename label.

Two bugs in core/imports/paths.py:

1. _replace_template_variables (the substitution helper used by every
   download path builder) had no handling for \$cdnum or \${cdnum}. The
   matching helper in web_server.py and core/repair_jobs/library_reorganize.py
   did the substitution; this one didn't, so production downloads passed
   the placeholder through unchanged. Added a cdnum_value computation
   (CD%02d when total_discs > 1, empty otherwise) plus the corresponding
   bracket_map entry and \$cdnum replace before \$track (matches the
   ordering in the other path builders).

2. The album-path branch of build_final_path_for_track auto-injected a
   "Disc N" folder whenever total_discs > 1, suppressed only when the
   template contained \$disc. Templates using \$cdnum (or \${disc} /
   \${discnum} / \${cdnum}) got both a "CDxx" label in the filename and
   the auto folder. Widened the user_controls_disc check to cover all
   the disc-bearing placeholders.

Bonus cleanup along the way:

- Folder-part stripping now drops a leading \$cdnum token (mirrors the
  existing \$disc / \$discnum / \$quality strip — defensive against an
  empty cdnum landing alone in a folder segment).
- Filename cleanup now strips a leading "  - " left behind when \$cdnum
  expands to empty on a single-disc album (mirrors the same regex in
  library_reorganize.py).
- album_template config access switched from the dotted-path key to the
  nested-dict access pattern used by the rest of the function — handles
  both production config_manager and the flat _Config used in tests.

Tests: 4 new under tests/imports/test_import_paths.py
- multi-disc cdnum substitution produces "CD02"
- single-disc cdnum collapses to empty
- folder-part containing only \$cdnum is dropped
- build_final_path_for_track with \$cdnum template produces no auto
  "Disc N" folder

Full suite: 1276 passing (was 1272). Ruff clean.
2026-04-28 21:32:24 -07:00
..
__init__.py Rehome import helpers into core/imports 2026-04-27 19:54:44 +03:00
album.py Rehome import helpers into core/imports 2026-04-27 19:54:44 +03:00
album_naming.py Rehome import helpers into core/imports 2026-04-27 19:54:44 +03:00
context.py Drop stale post-PR378 redefs and fix B009 2026-04-27 13:39:16 -07:00
file_ops.py Tighten metadata and import safety 2026-04-27 20:28:05 +03:00
filename.py Rehome import helpers into core/imports 2026-04-27 19:54:44 +03:00
guards.py Tighten metadata and import safety 2026-04-27 20:28:05 +03:00
paths.py fix: substitute \$cdnum in download paths and skip auto disc folder when template uses it 2026-04-28 21:32:24 -07:00
pipeline.py Extract wishlist logic into dedicated package 2026-04-28 21:17:24 +03:00
resolution.py Fix single import source handling 2026-04-27 19:54:45 +03:00
side_effects.py Extract wishlist logic into dedicated package 2026-04-28 21:17:24 +03:00
staging.py Fix single import source handling 2026-04-27 19:54:45 +03:00