Skip to content
This repository has been archived by the owner on Oct 13, 2024. It is now read-only.

fix(collections): add migration for collection metadata #345

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Contents/Code/default_prefs.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,5 @@
int_webapp_http_port='9494',
bool_webapp_log_werkzeug_messages='False',
bool_migrate_locked_themes='False',
bool_migrate_locked_collection_fields='False',
)
51 changes: 50 additions & 1 deletion Contents/Code/migration_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
"""
# Define the migration keys as class attributes for dot notation access
LOCKED_THEMES = 'locked_themes'
LOCKED_COLLECTION_FIELDS = 'locked_collection_fields'

def __init__(self):
self.migration_status_file = os.path.join(themerr_data_directory, 'migration_status.json')
Expand All @@ -57,6 +58,7 @@
# Map keys to their respective functions
self.migration_functions = {
self.LOCKED_THEMES: self.migrate_locked_themes,
self.LOCKED_COLLECTION_FIELDS: self.migrate_locked_collection_fields,
}

def _validate_migration_key(self, key, raise_exception=False):
Expand Down Expand Up @@ -189,13 +191,16 @@
'tv.plex.agents.movie',
'com.plexapp.agents.imdb',
'com.plexapp.agents.themoviedb',
'dev.lizardbyte.retroarcher-plex'
'dev.lizardbyte.retroarcher-plex',
)

for section in sections:
if section.agent not in contributes_to:
continue # skip items with unsupported metadata agents for < v0.3.0

if section.type != 'movie':
continue # skip non-movie sections

Check warning on line 202 in Contents/Code/migration_helper.py

View check run for this annotation

Codecov / codecov/patch

Contents/Code/migration_helper.py#L202

Added line #L202 was not covered by tests

field = 'theme'

# not sure if this unlocks themes for collections
Expand All @@ -221,6 +226,50 @@
if item.isLocked(field=field):
plex_api_helper.change_lock_status(item=item, field=field, lock=False)

@staticmethod
def migrate_locked_collection_fields():
"""
Unlock fields locked in collections.

Prior to v0.3.0, fields for collections modified by Themerr-plex were locked which leads to an issue in v0.3.0
and newer, since Themerr-plex will not update locked fields.
"""
plex = plex_api_helper.setup_plexapi()

plex_library = plex.library

sections = plex_library.sections()

# never update this list, it needs to match what was available before v0.3.0
contributes_to = (
'tv.plex.agents.movie',
'com.plexapp.agents.imdb',
'com.plexapp.agents.themoviedb',
'dev.lizardbyte.retroarcher-plex',
)

for section in sections:
if section.agent not in contributes_to:
continue # skip items with unsupported metadata agents for < v0.3.0

Check warning on line 253 in Contents/Code/migration_helper.py

View check run for this annotation

Codecov / codecov/patch

Contents/Code/migration_helper.py#L253

Added line #L253 was not covered by tests

if section.type != 'movie':
continue # skip non-movie sections

Check warning on line 256 in Contents/Code/migration_helper.py

View check run for this annotation

Codecov / codecov/patch

Contents/Code/migration_helper.py#L256

Added line #L256 was not covered by tests

fields = [
'art',
'summary',
'thumb',
]

# collections were added in v0.3.0, but collect them as well for anyone who may have used a nightly build
# get all collections in the section
collections = section.collections()

for item in collections:
for field in fields:
if item.isLocked(field=field) and item.theme: # only unlock fields for collections with themes
plex_api_helper.change_lock_status(item=item, field=field, lock=False)

Check warning on line 271 in Contents/Code/migration_helper.py

View check run for this annotation

Codecov / codecov/patch

Contents/Code/migration_helper.py#L269-L271

Added lines #L269 - L271 were not covered by tests

def perform_migration(self, key):
# type: (str) -> None
"""
Expand Down
9 changes: 8 additions & 1 deletion Contents/DefaultPrefs.json
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,14 @@
{
"id": "bool_migrate_locked_themes",
"type": "bool",
"label": "Migrate from < v0.3.0 (If you used Themerr before v0.3.0, set this to True)",
"label": "Migrate themes from < v0.3.0 (If you used Themerr before v0.3.0, set this to True)",
"default": "False",
"secure": "false"
},
{
"id": "bool_migrate_locked_collection_fields",
"type": "bool",
"label": "Migrate collection metadata from < v0.3.0 (If you used Themerr before v0.3.0, set this to True)",
"default": "False",
"secure": "false"
}
Expand Down
25 changes: 25 additions & 0 deletions docs/source/about/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -294,3 +294,28 @@ Description

Default
``False``

Migrate themes from < v0.3.0
^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Description
Prior to v0.3.0, Themerr-plex uploaded themes were locked and there was no way to determine if a theme was supplied
by Themerr-plex. Therefore, if you used Themerr-plex prior to v0.3.0, you will need to enable this setting to
automatically unlock all existing themes (for agents that Themerr-plex supports). Once the migration has completed,
the unlock function will never run again.

If you see many of the ``Unknown provider`` status in the web UI, it is a good indication that you need to enable
this option, unless you have many themes provided by other tools.

Default
``False``

Migrate collection metadata from < v0.3.0
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Description
Prior to v0.3.0, fields for collections modified by Themerr-plex were locked which leads to an issue in v0.3.0
and newer, since Themerr-plex will not update locked fields.

Default
``False``
23 changes: 23 additions & 0 deletions tests/unit/test_migration_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ def migration_status_file(migration_helper_fixture):
@pytest.mark.parametrize('key, raise_exception, expected_return, expected_raise', [
(migration_helper_object.LOCKED_THEMES, False, True, None),
(migration_helper_object.LOCKED_THEMES, True, True, None),
(migration_helper_object.LOCKED_COLLECTION_FIELDS, False, True, None),
(migration_helper_object.LOCKED_COLLECTION_FIELDS, True, True, None),
('invalid', False, False, None),
('invalid', True, False, AttributeError),
])
Expand All @@ -51,6 +53,7 @@ def test_validate_migration_key(migration_helper_fixture, key, raise_exception,

@pytest.mark.parametrize('key, expected', [
(migration_helper_object.LOCKED_THEMES, None),
(migration_helper_object.LOCKED_COLLECTION_FIELDS, None),
pytest.param('invalid', None, marks=pytest.mark.xfail(raises=AttributeError)),
])
def test_get_migration_status(migration_helper_fixture, migration_status_file, key, expected):
Expand All @@ -60,6 +63,7 @@ def test_get_migration_status(migration_helper_fixture, migration_status_file, k

@pytest.mark.parametrize('key', [
migration_helper_object.LOCKED_THEMES,
migration_helper_object.LOCKED_COLLECTION_FIELDS,
pytest.param('invalid', marks=pytest.mark.xfail(raises=AttributeError)),
])
def test_set_migration_status(migration_helper_fixture, migration_status_file, key):
Expand All @@ -72,6 +76,7 @@ def test_set_migration_status(migration_helper_fixture, migration_status_file, k

@pytest.mark.parametrize('key', [
migration_helper_object.LOCKED_THEMES,
migration_helper_object.LOCKED_COLLECTION_FIELDS,
])
def test_perform_migration(migration_helper_fixture, migration_status_file, key):
# perform the migration twice, should return early on the second run
Expand All @@ -97,3 +102,21 @@ def test_migrate_locked_themes(movies):

for movie in movies.all():
assert movie.isLocked(field=field) is False, '{} for movie is still locked'.format(field)


@pytest.mark.parametrize('field', [
'art',
'summary',
'thumb',
])
def test_migrate_locked_collection_fields(field, movies):
# lock all is not working, so lock manually
for item in movies.collections():
plex_api_helper.change_lock_status(item=item, field=field, lock=True)
assert item.isLocked(field=field) is True, '{} for collection is not locked'.format(field)

migration_helper_object.migrate_locked_collection_fields()
movies.reload()

for item in movies.collections():
assert item.isLocked(field=field) is False, '{} for collection is still locked'.format(field)
Loading