Skip to content
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

Automatically retrieve external guids from libraries using includeGuids #831

Merged
merged 7 commits into from
Oct 4, 2021
39 changes: 38 additions & 1 deletion plexapi/library.py
Original file line number Diff line number Diff line change
Expand Up @@ -456,10 +456,45 @@ def get(self, title):

Parameters:
title (str): Title of the item to return.

Raises:
:exc:`~plexapi.exceptions.NotFound`: The title is not found in the library.
"""
key = '/library/sections/%s/all?title=%s' % (self.key, quote(title, safe=''))
key = '/library/sections/%s/all?includeGuids=1&title=%s' % (self.key, quote(title, safe=''))
return self.fetchItem(key, title__iexact=title)

def getGuid(self, guid):
""" Returns the media item with the specified external IMDB, TMDB, or TVDB ID.
Note: This search uses a PlexAPI operator so performance may be slow. All items from the
entire Plex library need to be retrieved for each guid search. It is recommended to create
your own lookup dictionary if you are searching for a lot of external guids.

Parameters:
guid (str): The external guid of the item to return.
Examples: IMDB ``imdb://tt0944947``, TMDB ``tmdb://1399``, TVDB ``tvdb://121361``.

Raises:
:exc:`~plexapi.exceptions.NotFound`: The guid is not found in the library.

Example:

.. code-block:: python

# This will retrieve all items in the entire library 3 times
result1 = library.getGuid('imdb://tt0944947')
result2 = library.getGuid('tmdb://1399')
result3 = library.getGuid('tvdb://121361')

# This will only retrieve all items in the library once to create a lookup dictionary
guidLookup = {guid.id: item for item in library.all() for guid in item.guids}
result1 = guidLookup['imdb://tt0944947']
result2 = guidLookup['tmdb://1399']
result3 = guidLookup['tvdb://121361']

"""
key = '/library/sections/%s/all?includeGuids=1' % self.key
return self.fetchItem(key, Guid__id__iexact=guid)

def all(self, libtype=None, **kwargs):
""" Returns a list of all items from this library section.
See description of :func:`~plexapi.library.LibrarySection.search()` for details about filtering / sorting.
Expand Down Expand Up @@ -979,6 +1014,8 @@ def _buildSearchKey(self, title=None, sort=None, libtype=None, limit=None, filte
"""
args = {}
filter_args = []

args['includeGuids'] = int(bool(kwargs.pop('includeGuids', True)))
for field, values in list(kwargs.items()):
if field.split('__')[-1] not in OPERATORS:
filter_args.append(self._validateFilterField(field, values, libtype))
Expand Down
4 changes: 3 additions & 1 deletion plexapi/mixins.py
Original file line number Diff line number Diff line change
Expand Up @@ -601,7 +601,9 @@ def _parseFilters(self, content):
key += '='
value = value[1:]

if key == 'type':
if key == 'includeGuids':
filters['includeGuids'] = int(value)
elif key == 'type':
filters['libtype'] = utils.reverseSearchType(value)
elif key == 'sort':
filters['sort'] = value.split(',')
Expand Down
19 changes: 19 additions & 0 deletions tests/test_library.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from collections import namedtuple
from datetime import datetime, timedelta
import pytest
import plexapi.base
from plexapi.exceptions import BadRequest, NotFound

from . import conftest as utils
Expand Down Expand Up @@ -52,12 +53,30 @@ def test_library_section_get_movie(movies):
assert movies.get("Sita Sings the Blues")


def test_library_MovieSection_getGuid(movies, movie):
result = movies.getGuid(guid=movie.guids[0].id)
assert result == movie


def test_library_section_movies_all(movies):
# size should always be none unless pagenation is being used.
assert movies.totalSize == 4
assert len(movies.all(container_start=0, container_size=1, maxresults=1)) == 1


def test_library_section_movies_all_guids(movies):
plexapi.base.USER_DONT_RELOAD_FOR_KEYS.add('guids')
try:
results = movies.all(includeGuids=False)
assert results[0].guids == []
results = movies.all()
assert results[0].guids
movie = movies.get("Sita Sings the Blues")
assert movie.guids
finally:
plexapi.base.USER_DONT_RELOAD_FOR_KEYS.remove('guids')


def test_library_section_totalViewSize(tvshows):
assert tvshows.totalViewSize() == 2
assert tvshows.totalViewSize(libtype="show") == 2
Expand Down