Skip to content

Fix/plex section id library identity - #1738

Open
chazlarson wants to merge 40 commits into
developfrom
fix/plex-section-id-library-identity
Open

Fix/plex section id library identity#1738
chazlarson wants to merge 40 commits into
developfrom
fix/plex-section-id-library-identity

Conversation

@chazlarson

Copy link
Copy Markdown
Contributor

What type of PR is this?

  • Bug Fix (non-breaking change which fixes an issue)
  • Feature/Tweak (non-breaking change which adds new functionality or enhances existing functionality)
  • Breaking Change (fix or feature that would break any existing functionality for users)
  • Documentation Update
  • Other

Description

A variety of changes related to spaces in names, using library IDs, and other QOL.

Which Environment Did You Test On?

  • Local Install (Windows/Linux/Mac via python quickstart.py)
  • Windows Executable
  • Linux Executable
  • macOS Executable
  • Docker
  • Other

@badja-dev badja-dev added build Trigger Short Builds on PRs and removed build Trigger Short Builds on PRs labels Aug 5, 2026
@chazlarson
chazlarson force-pushed the fix/plex-section-id-library-identity branch 2 times, most recently from 85c1c96 to 51d5fe5 Compare August 11, 2026 16:07
@chazlarson
chazlarson requested review from bullmoose20 and a lite review from Copilot August 11, 2026 16:22

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves how Plex libraries are identified and represented across the Quickstart UI and config-generation pipeline by moving from name-based identifiers to stable Plex section IDs, while also adding dev-quality-of-life support (Vite dev-server mode) and preserving significant whitespace in library names.

Changes:

  • Switch library selection/storage/telemetry from library names to Plex section IDs, with migration of existing saved settings.
  • Preserve leading/trailing whitespace in library names end-to-end (rendering, parsing, config/header output, resume hints).
  • Add optional Vite dev-server support (QS_VITE_DEV*) and UI tweaks for better dev ergonomics.

Reviewed changes

Copilot reviewed 40 out of 42 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
vite.config.js Bind/dev-server configuration update.
uv.lock Updates Python requirement for uv lock usage.
tests/test_vite_manifest.py Adds coverage for new Vite dev-mode helpers and asset URL behavior.
tests/test_resume_hint.py Adds coverage for whitespace-preserving resume and command parsing.
tests/test_importer_library_services.py Updates expected importer payload for library toggles/IDs.
tests/test_importer_edge_cases.py Updates expected importer payload for library toggles/IDs in edge cases.
tests/test_core_backend.py Updates fake Plex sections + expected payload shape to include IDs.
templates/partials/_library_card.html Switch include toggle value to boolean-ish and render whitespace-preserved names.
templates/900-kometa.html Improves library label rendering + run-progress table whitespace handling.
templates/025-libraries.html Update telemetry/library rendering and dropdown labels for whitespace-preserved names.
templates/010-plex.html Adds hidden name-map field and changes db_cache minimum.
templates/000-base.html Injects Vite dev client when dev origin is enabled.
static/local-js/modules/kometa/_util.js Adds shared nbspLeadingSpaces helper.
static/local-js/modules/kometa/_runProgress.js Uses nbspLeadingSpaces for progress table rendering.
static/local-js/905-analytics.js Uses nbspLeadingSpaces to render snapshot names without collapsing spaces.
static/local-js/025-libraries.js Preserves whitespace in picker labels and includes a local nbspLeadingSpaces.
static/local-js/010-plex.js Stores library lists as ID CSV + JSON name map; improves db_cache mismatch warning logic.
static/css/styles.css Ensures dropdown/progress labels preserve whitespace and use monospace where appropriate.
quickstart.py Wires Vite dev origin + adds Jinja filter for whitespace preservation; adjusts library ID decoding usage.
PART Build “part” marker update.
package.json Adds a new production dependency.
package-lock.json Lockfile update reflecting the new dependency tree.
modules/validations_services.py Plex validation now returns ID/name objects and logs names only.
modules/process_run_context.py Updates --run-libraries parsing to preserve whitespace.
modules/persistence.py Adds library ID decoding, name-map storage, and migration from name-based keys to ID-based keys.
modules/output_yaml_header.py Switch header library summaries to ID-based lookup.
modules/output_libraries_data.py Prefer authoritative Plex name map when building output bundle.
modules/output_dump.py Improves YAML header injection handling for quoted keys.
modules/logscan_resume.py Preserves quoted whitespace and refines resume-scope normalization/quoting.
modules/logscan_progress.py Preserves library-name whitespace and improves name/type lookup using ID→name mapping.
modules/logscan_library_stats.py Adds exact-match precedence to avoid conflating whitespace-distinct names.
modules/logscan_incomplete_resume.py Preserves whitespace in current library detection.
modules/importer.py Imports library keys using Plex IDs when available; sets library toggles to "true".
modules/helpers/_vite_manifest.py Adds Vite dev-mode helpers and dev-origin asset URL behavior.
modules/helpers/_plex.py Switch Plex metadata indexing and summaries to use section IDs.
modules/helpers/_forms.py Avoids stripping library fields in form building.
modules/helpers/_constants.py Normalizes BASE_DIR to an absolute path.
blueprints/validation_routes.py Runs library-key migration during Plex validation/refresh; stores name map.
blueprints/library_routes.py Build library lists from decoded IDs + name map.
blueprints/import_config_routes.py Uses helper to derive Plex library name sets under new storage format.
blueprints/import_config_helpers.py Adds ID-aware Plex library name extraction helpers and whitespace-preserving parsing.
.pre-commit-config.yaml Bumps ruff hook revision.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread modules/helpers/_vite_manifest.py
Comment thread modules/helpers/_vite_manifest.py Outdated
Comment thread modules/process_run_context.py
Comment thread modules/persistence.py Outdated
Comment thread static/local-js/025-libraries.js Outdated
Comment thread vite.config.js
Comment thread package.json Outdated

@bullmoose20 bullmoose20 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In all cases, these are the two libraries checked for spacing throughout QS:

[ TestMovies-4kk] and [ TestTV Shows - 4k ]

Unreal, that even here in GH, when I put braces within a code block, GH removes the extra spaces.... basically TestMovies-4kk has about 5 prepended spaces and the TestTV Shows has about 10 prepended and appended.

Here we go:

1 - So it seems that appended spaces are in the header of the dropdown, but prepended spaces are not. They are shown when you expand the dropdown.

image image

2 - Here is the issue with Importer in terms of spaces, the dropdown does not show the spaces on the plex server:
image

image

3 - Below is a strange message in the kometa final output page within the config where it cannot find it, but its there in the config so not sure why it cannot match the library name and produce the stats in the upper section of the output within the config?
image

Comment thread templates/900-kometa.html
Comment thread templates/010-plex.html
@bullmoose20
bullmoose20 self-requested a review August 11, 2026 22:06
@bullmoose20

bullmoose20 commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator
image

Should we enforce the spaces in the run command even though we know that this does not work in kometa? And by not putting the spaces here, aren't we still going to have a broken run?

Maybe we make it consistent and then put a FR against kometa to support spaces within the run command?

Similar for recovery command:
image

Comment thread templates/900-kometa.html Outdated
@bullmoose20

Copy link
Copy Markdown
Collaborator

image

Support info seems to be unable to get the library info.

@bullmoose20

Copy link
Copy Markdown
Collaborator

image

Support info seems to be unable to get the library info.

This could be because of an existing config as opposed to a config from scratch.

chazlarson and others added 6 commits August 14, 2026 15:50
Replaces normalised-name keys (e.g. mov-library_moviesl-*) with Plex
integer section IDs (mov-library_59-*) so that library identity is stable
regardless of display-name whitespace or special characters.

Key changes:
- persistence.py: decode_library_ids(), get_library_names(),
  migrate_library_keys_to_plex_ids(); clean_form_data() no longer strips
  library display-name values (leading/trailing spaces are significant)
- helpers/_forms.py: build_simple_dict() no longer strips -library or
  libraries values
- output_dump.py: strip YAML quote characters from section-header names
  so ruamel-quoted keys like ' Movies L': resolve correctly
- output_yaml_header.py: _sorted_library_display_names() preserves names
  with spaces for the Plex metadata lookup; only strips for empty-check
  and sort key
- quickstart.py: _nbsp_leading_spaces Jinja filter replaces leading
  ASCII spaces with EM SPACE (U+2003) for visible indentation in
  native OS select dropdowns
- 025-libraries.js: nbspLeadingSpaces() mirrors the Jinja filter so
  refreshPickerLabels() does not overwrite EM-SPACE option text with
  the raw data-label value
- validation_routes.py: triggers migration at Plex validation time
- validations_services.py, library_routes.py, import_config_helpers.py,
  importer.py: updated to work with {id, name} dicts and integer IDs
- 010-plex.js / 010-plex.html: hidden inputs store Plex section IDs
- 248 tests passing

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When visiting the libraries page, migrate_library_keys_to_plex_ids runs
inside refresh_plex_libraries() at line 2278, renaming old name-based DB
keys (e.g. mov-library_moviesl-*) to ID-based keys (mov-library_59-*).
However, `data` was loaded at line 2234 before the migration ran, so
configured_ids was built from stale name-based keys while movie_libraries
was built from the new ID-based tmp_movie_libraries — zero intersection,
all libraries appeared unconfigured.

Fix: re-read `data` from the DB for the libraries page after the refresh
so configured_ids reflects the post-migration key format.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
retrieve_settings(config_name) was called with the user's config name
(e.g. "nervous_johnson"). extract_names() splits on "-" and takes the
last segment, producing "johnson" — a nonexistent section — so the DB
read returned empty, libraries={}, and the migration returned 0 without
renaming any keys.

Fix: call retrieve_settings("025-libraries") so extract_names correctly
derives section="libraries" and reads the actual library settings.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The card header h4 was rendering {{ library.name }} without the filter,
so libraries with leading spaces (e.g. ' Movies') showed as 'Movies'
in the card title. Apply the same EM-SPACE filter used in the picker
options so the leading indentation is visible in the card heading.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Leading-only conversion left trailing spaces as regular ASCII, which
browsers collapse in dropdown option text and HTML headings. Now both
the Python Jinja filter and the JS nbspLeadingSpaces() helper convert
leading AND trailing ASCII spaces to EM SPACE (U+2003) so names like
'Movies T ' display as 'Movies T⁃' rather than 'Movies T'.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copilot AI and others added 4 commits August 14, 2026 15:51
@chazlarson

Copy link
Copy Markdown
Contributor Author

image image
So it seems that appended spaces are in the header of the dropdown, but prepended spaces are not. They are shown when you expand the dropdown.

Here is the issue with Importer in terms of spaces, the dropdown does not show the spaces on the plex server: image

image Below is a strange message in the output where it cannot find it, but its there? image

There are quite a few things here? Are they all related in some way?

bullmoose20 and others added 4 commits August 14, 2026 15:56
Co-authored-by: YozoraXCII <96386153+YozoraXCII@users.noreply.github.com>
Co-authored-by: badja-dev <180163201+badja-dev@users.noreply.github.com>
Updated GitHub Actions workflows to use newer versions of actions and added a new step to run tests.
Updated the GitHub Actions workflow to improve permissions, concurrency handling, and environment variable usage. Enhanced error handling and output formatting for better clarity.
@chazlarson
chazlarson force-pushed the fix/plex-section-id-library-identity branch from 83cb56d to 70866d8 Compare August 14, 2026 20:57
@bullmoose20

Copy link
Copy Markdown
Collaborator

image image

So it seems that appended spaces are in the header of the dropdown, but prepended spaces are not. They are shown when you expand the dropdown.

Here is the issue with Importer in terms of spaces, the dropdown does not show the spaces on the plex server: image

image

Below is a strange message in the output where it cannot find it, but its there? image

There are quite a few things here? Are they all related in some way?

I rewrote the comment earlier to specify the 3 findings. They are only related in that the spacing issue shows up.

@chazlarson

Copy link
Copy Markdown
Contributor Author

image
Support info seems to be unable to get the library info.

This could be because of an existing config as opposed to a config from scratch.

does is behave differently in those two cases? Which case is this?

@chazlarson

Copy link
Copy Markdown
Contributor Author

1 - So it seems that appended spaces are in the header of the dropdown, but prepended spaces are not. They are shown when you expand the dropdown.

As I recall that was judged accpetable previously given that the name of the library with spaces is displayed immediately below the menu once selected, but I'll have a look. The solution is "fully custom dropdown replacement" or "wrap names in brackets in the dropdown".

@chazlarson

chazlarson commented Aug 15, 2026

Copy link
Copy Markdown
Contributor Author

2 - Here is the issue with Importer in terms of spaces, the dropdown does not show the spaces on the plex server:

I can't load those images to see them clearly. What is that showing? If I import an existing config with spaces in names, everything is fine. However, I don't see a dialog that contains whatever that extra stuff is on the bottom, whether I merge or create a new one.

Looks like you're choosing libraries to import, but I don't see any place to do that.

I can't reproduce any problems here.

@bullmoose20

Copy link
Copy Markdown
Collaborator

image

Support info seems to be unable to get the library info.

This could be because of an existing config as opposed to a config from scratch.

does is behave differently in those two cases? Which case is this?

This case is not a fresh config.

@bullmoose20

Copy link
Copy Markdown
Collaborator

1 - So it seems that appended spaces are in the header of the dropdown, but prepended spaces are not. They are shown when you expand the dropdown.

As I recall that was judged accpetable previously given that the name of the library with spaces is displayed immediately below the menu once selected, but I'll have a look. The solution is "fully custom dropdown replacement" or "wrap names in brackets in the dropdown".

Sure, maybe leave it. I found it peculiar that spaces appended showed properly but not prepended spaces and only in the header of the dropdown.

@bullmoose20

Copy link
Copy Markdown
Collaborator

2 - Here is the issue with Importer in terms of spaces, the dropdown does not show the spaces on the plex server:

I can't load those images to see them clearly. What is that showing? If I import an existing config with spaces in names, everything is fine. However, I don't see a dialog that contains whatever that extra stuff is on the bottom, whether I merge or create a new one.

Looks like you're choosing libraries to import, but I don't see any place to do that.

I can't reproduce any problems here.

To reproduce this import scenario.

Case 1:

  • Take plex server with libraries with no spaces and get to the final config and export it
  • Now rename some libraries to include spaces
  • On start page, in utilities menu, manage configs, import the bundle you exported from above
  • Make that a "merge" type of import and this is where you will see this issue of spaces not showing

Case 2:

  • Take plex server with libraries WITH spaces and get to the final config and export it
  • Now remove spaces from libraries in plex
  • On start page, in utilities menu, manage configs, import the bundle you exported from above
  • Make that a "merge" type of import and this is where you will see this issue of spaces not showing

Case 3:

  • Take plex server with libraries WITH spaces and get to the final config and export it
  • On start page, in utilities menu, manage configs, import the bundle you exported from above
  • Make that a "merge" type of import and this is where you will see this issue of spaces not showing

@chazlarson

chazlarson commented Aug 17, 2026

Copy link
Copy Markdown
Contributor Author

Honestly this seems like a really unlikely edge case, but I can see what is going on.

If the user has renamed libraries in Plex, and presumably has an existing Quickstart setup for the pre-rename setup, why are they abandoning that and importing an old Quickstart config?

The import only knows names, so if you change names and then try to import a config expecting Quickstart to match "Foo" to "Bar" I don't see how that can work. We have nothing to base the match on.

What's the practical use case where this comes up?

@bullmoose20

Copy link
Copy Markdown
Collaborator

Honestly this seems like a really unlikely edge case, but I can see what is going on.

If the user has renamed libraries in Plex, and presumably has an existing Quickstart setup for the pre-rename setup, why are they abandoning that and importing an old Quickstart config?

The import only knows names, so if you change names and then try to import a config expecting Quickstart to match "Foo" to "Bar" I don't see how that can work. We have nothing to base the match on.

What's the practical use case where this comes up?

2 cases:
1 - as a support team we see a config that we want to try, so we import it
2 - users share their bundles with other users but their libraries are not named the same so when they import it they perform the mapping

@bullmoose20

bullmoose20 commented Aug 18, 2026

Copy link
Copy Markdown
Collaborator

image

Strange and not sure why this is happening however if you visually look at the command output, there are clearly spaces missing however when you copy using the button and paste elsewhere, you get:

C:\Users\bullmoose20\Quickstart\config\kometa\kometa-venv\Scripts\python.exe C:\Users\bullmoose20\Quickstart\config\kometa\kometa.py --run-libraries " TestMovies-4kk| TestTV Shows - 4k " --config C:\Users\bullmoose20\Quickstart\config\kometa\config\hopeful_jennings_config.yml

Which has the spaces. I am puzzled.

And even as I paste it here, in the edit I see the spaces...from the paste but not when I save it and GH displays it.

image

@bullmoose20

Copy link
Copy Markdown
Collaborator

image

Strange and not sure why this is happening however if you visually look at the command output, there are clearly spaces missing however when you copy using the button and paste elsewhere, you get:

C:\Users\bullmoose20\Quickstart\config\kometa\kometa-venv\Scripts\python.exe C:\Users\bullmoose20\Quickstart\config\kometa\kometa.py --run-libraries " TestMovies-4kk| TestTV Shows - 4k " --config C:\Users\bullmoose20\Quickstart\config\kometa\config\hopeful_jennings_config.yml

Which has the spaces. I am puzzled.

And even as I paste it here, in the edit I see the spaces...from the paste but not when I save it and GH displays it.

image

Adding this to line 3385 of styles.css resolves the visual display issue in QuickStart:


#run-command-output,
.qs-recovery-command-output {
    white-space: pre-wrap !important;
    overflow-wrap: anywhere;
}

@chazlarson

Copy link
Copy Markdown
Contributor Author

Adding this to line 3385 of styles.css resolves the visual display issue in QuickStart:


#run-command-output,
.qs-recovery-command-output {
    white-space: pre-wrap !important;
    overflow-wrap: anywhere;
}

I'll add that, but hopefully it doesn't break anything else.

@chazlarson

chazlarson commented Aug 18, 2026

Copy link
Copy Markdown
Contributor Author

1 - So it seems that appended spaces are in the header of the dropdown, but prepended spaces are not. They are shown when you expand the dropdown.

As I recall that was judged accpetable previously given that the name of the library with spaces is displayed immediately below the menu once selected, but I'll have a look. The solution is "fully custom dropdown replacement" or "wrap names in brackets in the dropdown".

Sure, maybe leave it. I found it peculiar that spaces appended showed properly but not prepended spaces and only in the header of the dropdown.

This has been addressed.

image

@chazlarson

Copy link
Copy Markdown
Contributor Author

Honestly this seems like a really unlikely edge case, but I can see what is going on.
If the user has renamed libraries in Plex, and presumably has an existing Quickstart setup for the pre-rename setup, why are they abandoning that and importing an old Quickstart config?
The import only knows names, so if you change names and then try to import a config expecting Quickstart to match "Foo" to "Bar" I don't see how that can work. We have nothing to base the match on.
What's the practical use case where this comes up?

2 cases: 1 - as a support team we see a config that we want to try, so we import it 2 - users share their bundles with other users but their libraries are not named the same so when they import it they perform the mapping

I had never seen any "mapping" facility anywhere, so it seemed like this was expected to be some sort of automatic process.

@bullmoose20

bullmoose20 commented Aug 21, 2026

Copy link
Copy Markdown
Collaborator

automatic

It's "semi" automatic. Because not everyone has the same set of library names.

If you are creating different bundles against the same plex server with the same names, then the import is fully automatic.

As long as the names of the libraries you import are the same as the libraries on the plex server you have, then the import is fully automatic

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants