-
-
Notifications
You must be signed in to change notification settings - Fork 419
PICARD-3118: Allow user to save/load current Picard session #2731
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
zas
merged 31 commits into
metabrainz:master
from
knguyen1:feat/PICARD-3118/add-save-session-feature
Sep 30, 2025
Merged
Changes from 30 commits
Commits
Show all changes
31 commits
Select commit
Hold shift + click to select a range
b049904
Complete session save/load roundtrip
knguyen1 16f21c7
Refactor sessions manager and add unit tests
knguyen1 a596368
Session files should be compressed
knguyen1 b44d36e
Enable caching of mb data in sessions
knguyen1 8383a97
Do not catch blind exceptions
knguyen1 1251e9c
Apply single quote on dict/attr keys
knguyen1 b8c0b42
Zas code review 20250908; own close session confirm box
knguyen1 7bff0c4
Use try...except...else pattern
knguyen1 86eef7a
Add flyout menu for recent sessions
knguyen1 1c14bc4
Make session_folder configurable and default
knguyen1 69ca212
Clean up menus; add default filenames
knguyen1 7b7506c
`load_session` should default to the last_session_path
knguyen1 11de913
Fix failing Windows tests
knguyen1 722b3fc
Add atomic writes; fix crash during load session
knguyen1 a644edb
Refactor ; remove redundant code
knguyen1 6da5c74
Switch from json to yaml for session files
knguyen1 f18eb91
Refactor session loader for dry/srp
knguyen1 f437291
Fix bug with blank albums (no cache, no web)
knguyen1 c3ca44e
Fix bug with web requests suppression
knguyen1 325bbc4
Fix some inconsistencies with `last_session_path`
knguyen1 847bd33
Apply zas code review recs 20250910
knguyen1 1bee982
Merge master into feat/PICARD-3118/add-save-session-feature
knguyen1 14e952b
Apply zas code review 20250924
knguyen1 31d7bc3
Rename `dont_write_tags` -> `enable_tag_saving`
knguyen1 499c052
Make `_atomic_write` its own utility
knguyen1 8eef846
Apply zas code review 20250925
knguyen1 cd61cb8
Improve type hints
knguyen1 9479f39
Make `restore_options` more generic
knguyen1 7e7654b
Fix: `dir` -> `directory`
knguyen1 3ebd96b
refactor: `session_loader` more readable
knguyen1 1c189b0
Refactor: Centralize RESTORABLE_CONFIG_KEYS for session management
knguyen1 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# -*- coding: utf-8 -*- | ||
# | ||
# Picard, the next-generation MusicBrainz tagger | ||
# | ||
# Copyright (C) 2025 The MusicBrainz Team | ||
# | ||
# This program is free software; you can redistribute it and/or | ||
# modify it under the terms of the GNU General Public License | ||
# as published by the Free Software Foundation; either version 2 | ||
# of the License, or (at your option) any later version. | ||
# | ||
# This program is distributed in the hope that it will be useful, | ||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
# GNU General Public License for more details. | ||
# | ||
# You should have received a copy of the GNU General Public License | ||
# along with this program; if not, write to the Free Software | ||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
|
||
"""Session management package for Picard.""" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
# -*- coding: utf-8 -*- | ||
# | ||
# Picard, the next-generation MusicBrainz tagger | ||
# | ||
# Copyright (C) 2025 The MusicBrainz Team | ||
# | ||
# This program is free software; you can redistribute it and/or | ||
# modify it under the terms of the GNU General Public License | ||
# as published by the Free Software Foundation; either version 2 | ||
# of the License, or (at your option) any later version. | ||
# | ||
# This program is distributed in the hope that it will be useful, | ||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
# GNU General Public License for more details. | ||
# | ||
# You should have received a copy of the GNU General Public License | ||
# along with this program; if not, write to the Free Software | ||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
|
||
"""Constants for session management. | ||
|
||
This module contains all constants used throughout the session management system, | ||
including retry delays, file extensions, and excluded tags. | ||
""" | ||
|
||
from picard.i18n import N_ | ||
|
||
|
||
class SessionConstants: | ||
"""Constants for session management operations. | ||
|
||
Retry delays | ||
------------ | ||
These delays govern how often we re-check readiness during session | ||
load/restore using Qt timers. They coordinate operations across | ||
asynchronous components (file scanning, network lookups, album/track | ||
population, UI creation) without requiring deep refactors. | ||
|
||
Attributes | ||
---------- | ||
DEFAULT_RETRY_DELAY_MS : int | ||
General-purpose delay (milliseconds) for deferred actions that need | ||
other subsystems to settle first. Used for: | ||
- Applying saved metadata / tag deltas once files are loaded | ||
(see `MetadataHandler.apply_saved_metadata_if_any`, | ||
`MetadataHandler.apply_tag_deltas_if_any`). | ||
- Restoring UI state (expanding albums) once UI items exist | ||
(see `SessionLoader._restore_ui_state`). | ||
- Finalizing the restoring flag when network/disk operations are idle | ||
(see `SessionLoader._unset_restoring_flag_when_idle`). | ||
|
||
Trade-offs | ||
---------- | ||
- Too short: Excess CPU wake-ups, risk of race-condition flapping, | ||
unnecessary network/UI churn. | ||
- Too long: Noticeable lag for metadata application and UI finalize. | ||
|
||
Tuning | ||
------ | ||
- Shorten for tests, small sessions, fast machines (snappier UI). | ||
- Lengthen for very large sessions, slow I/O/network (reduce churn). | ||
|
||
FAST_RETRY_DELAY_MS : int | ||
Lower-latency delay (milliseconds) for local readiness checks where | ||
objects stabilize quickly (e.g., file/album becomes ready) and we want | ||
prompt feedback. Used for: | ||
- Moving files to tracks once file/album are ready | ||
(see `TrackMover.move_files_to_tracks`). | ||
- Specialized helpers like `RetryHelper.retry_until_file_ready` and | ||
`RetryHelper.retry_until_album_ready`. | ||
|
||
Trade-offs | ||
---------- | ||
- Too short: High-frequency polling of local state, potential CPU | ||
spikes on large batches. | ||
- Too long: Sluggish track moves and perceived restore latency. | ||
|
||
Notes | ||
----- | ||
What is being retried | ||
Readiness checks and deferred execution (polling until conditions are | ||
true), not re-execution of failed logic. | ||
|
||
Why retries are needed | ||
In an event-driven Qt architecture not all components emit precise | ||
"ready" signals, and many operations require multiple conditions to be | ||
true simultaneously (e.g., file loaded AND album tracks available AND | ||
UI node created). Timed re-checks are a pragmatic coordination | ||
mechanism. | ||
|
||
Alternative (fully async/signals) | ||
We could replace polls with explicit signals/awaitables | ||
(e.g., file_ready, album_tracks_loaded, ui_item_created, webservice_idle), | ||
but this requires cross-cutting changes across `File`, `Album`, UI, | ||
WebService, and `Tagger`. Incremental migration is possible; until then | ||
these delays balance responsiveness and load. | ||
""" | ||
|
||
# File handling | ||
SESSION_FILE_EXTENSION = ".mbps.gz" | ||
SESSION_FORMAT_VERSION = 1 | ||
|
||
# Recent sessions | ||
# Number of recent session entries shown in the UI flyout menu. | ||
RECENT_SESSIONS_MAX = 5 | ||
|
||
# Retry delays in milliseconds | ||
# Used by Qt timers for retry/poll loops during session load/restore. | ||
# Balance responsiveness with CPU/network load: shorter feels snappier | ||
# but risks busy-looping and churn; longer reduces load but adds visible lag. | ||
DEFAULT_RETRY_DELAY_MS = 200 | ||
|
||
# General retries (e.g. metadata application, UI finalize). | ||
# Adjust up for huge sessions/slow I/O; down for tests/small sessions/fast | ||
# machines. | ||
FAST_RETRY_DELAY_MS = 150 | ||
# Local readiness checks (files/albums becoming ready, track moves). | ||
# Too short ⇒ high CPU/race flapping; too long ⇒ sluggish moves/restore. | ||
|
||
# Location types | ||
LOCATION_UNCLUSTERED = "unclustered" | ||
LOCATION_TRACK = "track" | ||
LOCATION_ALBUM_UNMATCHED = "album_unmatched" | ||
LOCATION_CLUSTER = "cluster" | ||
LOCATION_NAT = "nat" | ||
|
||
|
||
class SessionMessages: | ||
"""Centralized session-related message strings. | ||
|
||
Define raw, untranslated strings. Call sites should mark for translation: | ||
- API/config titles: wrap with N_() | ||
- UI labels: wrap with _() | ||
""" | ||
|
||
# Option titles (API/config) | ||
SESSION_SAFE_RESTORE_TITLE = N_("Honor local edits and placement on load (no auto-matching)") | ||
SESSION_LOAD_LAST_TITLE = N_("Load last saved session on startup") | ||
SESSION_AUTOSAVE_TITLE = N_("Auto-save session every N minutes (0 disables)") | ||
SESSION_BACKUP_TITLE = N_("Attempt to keep a session backup on unexpected shutdown") | ||
SESSION_INCLUDE_MB_DATA_TITLE = N_("Include MusicBrainz data in saved sessions (warm cache)") | ||
SESSION_NO_MB_REQUESTS_ON_LOAD = N_( | ||
"Do not make MusicBrainz requests on restore (faster loads, risk of stale data)" | ||
) | ||
SESSION_FOLDER_PATH_TITLE = N_("Sessions folder path (leave empty for default)") |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.