track_sync
¶
Track List Synchronization Module.
This module handles track list persistence and synchronization between the Music.app library and CSV storage, including AppleScript-based field fetching.
ParsedTrackFields
¶
Bases: TypedDict
Typed dict for parsed AppleScript track fields.
Contains the 4 fields extracted from AppleScript output that are needed for track synchronization and delta detection.
Note: 'year' is the CURRENT year in Music.app (position 9 in AppleScript). This may be used to populate TrackDict.year_before_mgu for new tracks.
validate_csv_header
¶
Validate CSV header and return fields to read.
Source code in src/metrics/track_sync.py
create_track_from_row
¶
Create TrackDict from CSV row data.
Source code in src/metrics/track_sync.py
load_track_list
¶
Load the track list from the CSV file into a dictionary.
The track ID is used as the key. Reads columns: id, name, artist, album, genre, date_added, track_status, year_before_mgu, year_set_by_mgu.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
csv_path
|
str
|
Path to the CSV file. |
required |
Returns:
| Type | Description |
|---|---|
dict[str, TrackDict]
|
Dictionary of track dictionaries. |
Source code in src/metrics/track_sync.py
get_processed_albums_from_csv
¶
Return a mapping album_key -> year_set_by_mgu for albums already processed in CSV.
Source code in src/metrics/track_sync.py
build_musicapp_track_map
async
¶
build_musicapp_track_map(
all_tracks,
processed_albums,
cache_service,
partial_sync,
error_logger,
)
Build normalized map {track_id: TrackDict} from Music.app tracks.
Handles partial_sync logic and ensures year consistency with cache & CSV.
Source code in src/metrics/track_sync.py
normalize_track_year_fields
¶
Ensure mandatory year fields exist in track.
handle_partial_sync_cache
async
¶
handle_partial_sync_cache(
track,
processed_albums,
cache_service,
album_key,
artist,
album,
error_logger,
)
Handle partial sync logic with cache coordination.
Source code in src/metrics/track_sync.py
create_normalized_track_dict
¶
Create normalized TrackDict with clean field values.
Source code in src/metrics/track_sync.py
get_musicapp_syncable_fields
¶
Fields that sync FROM Music.app TO CSV during resync.
Note: year_before_mgu and year_set_by_mgu are EXCLUDED because: - They are tracking fields managed by year_batch.py, not sync - AppleScript doesn't provide them (only Music.app's current year) - During sync, we preserve CSV's historical tracking data
However, _merge_musicapp_into_csv() will initialize empty year_before_mgu from musicapp_track.year to prevent redundant fetches in sync_track_list_with_current. See Issue #126 for context.
Source code in src/metrics/track_sync.py
track_fields_differ
¶
Check if CSV track differs from Music.app track in specified fields.
Source code in src/metrics/track_sync.py
update_csv_track_from_musicapp
¶
Update CSV track with values from Music.app track.
Only updates fields that exist on both tracks and have non-None values in Music.app track. Logs warning for missing fields.
Source code in src/metrics/track_sync.py
merge_musicapp_into_csv
¶
Merge Music.app tracks into CSV tracks dict.
- New tracks (in Music.app but not CSV): added to csv_tracks
- Existing tracks: CSV updated with Music.app values for syncable fields
- Tracking fields (year_before_mgu, year_set_by_mgu): preserved from CSV if present, otherwise initialized from Music.app's current year
Returns count of added/updated tracks.
Source code in src/metrics/track_sync.py
build_osascript_command
¶
Build osascript command with optional artist filter.
resolve_field_indices
¶
Return indices for date_added, modification_date, status, and year columns.
Source code in src/metrics/track_sync.py
sanitize_applescript_field
¶
parse_single_track_line
¶
Parse fields into ParsedTrackFields using resolved indices.
Source code in src/metrics/track_sync.py
parse_osascript_output
¶
Parse AppleScript output into track cache dictionary.
Validates field count to detect AppleScript output format changes and logs warnings for lines with incorrect field counts to aid debugging.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
raw_output
|
str
|
Raw AppleScript output with ASCII or TSV separators. |
required |
Returns:
| Type | Description |
|---|---|
dict[str, ParsedTrackFields]
|
Dict mapping track_id to ParsedTrackFields with date_added, |
dict[str, ParsedTrackFields]
|
last_modified, track_status, and year. |
Source code in src/metrics/track_sync.py
handle_osascript_error
¶
Handle and log osascript execution errors.
Source code in src/metrics/track_sync.py
execute_osascript_process
async
¶
Execute osascript subprocess and return results.
Source code in src/metrics/track_sync.py
fetch_track_fields_direct
async
¶
Fetch track fields using direct osascript call.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
script_path
|
str
|
Path to AppleScript file |
required |
artist_filter
|
str | None
|
Artist filter to limit query scope |
required |
Returns:
| Type | Description |
|---|---|
dict[str, ParsedTrackFields]
|
Dict mapping track_id to ParsedTrackFields with date_added, |
dict[str, ParsedTrackFields]
|
last_modified, track_status, year fields. |
Source code in src/metrics/track_sync.py
fetch_missing_track_fields_for_sync
async
¶
Fetch missing track fields via AppleScript if needed for sync operation.
Source code in src/metrics/track_sync.py
update_track_with_cached_fields_for_sync
¶
Update track with cached fields if they were empty for sync operation.
Populates date_added, last_modified, track_status from AppleScript cache. The last_modified field enables idempotent delta detection by tracking when Music.app metadata was last changed.
For 'year' field: AppleScript returns the CURRENT year in Music.app. - Populates track.year for delta detection - Populates track.year_before_mgu ONLY if empty (preserves original value for rollback)
Source code in src/metrics/track_sync.py
convert_track_to_csv_dict
¶
Convert TrackDict to CSV dictionary format.
Source code in src/metrics/track_sync.py
sync_track_list_with_current
async
¶
sync_track_list_with_current(
all_tracks,
csv_path,
cache_service,
console_logger,
error_logger,
partial_sync=False,
applescript_client=None,
)
Synchronize the current track list with the data in a CSV file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
all_tracks
|
Sequence[TrackDict]
|
List of track dictionaries to sync. |
required |
csv_path
|
str
|
Path to the CSV file. |
required |
cache_service
|
CacheServiceProtocol
|
Cache service protocol for album year caching. |
required |
console_logger
|
Logger
|
Logger for console output. |
required |
error_logger
|
Logger
|
Logger for error output. |
required |
partial_sync
|
bool
|
Whether to perform a partial sync (only update year_set_by_mgu if missing). |
False
|
applescript_client
|
AppleScriptClientProtocol | None
|
AppleScript client for fetching missing track fields. |
None
|
Source code in src/metrics/track_sync.py
596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 | |
save_track_map_to_csv
¶
Persist the provided track map to CSV using standard field ordering.