diff --git a/plexapi/library.py b/plexapi/library.py index d98f684df..79c94027c 100644 --- a/plexapi/library.py +++ b/plexapi/library.py @@ -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. @@ -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)) diff --git a/plexapi/mixins.py b/plexapi/mixins.py index 16c35b1e3..af5d1da5e 100644 --- a/plexapi/mixins.py +++ b/plexapi/mixins.py @@ -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(',') diff --git a/tests/test_library.py b/tests/test_library.py index 66a1df3f1..7dd8200bb 100644 --- a/tests/test_library.py +++ b/tests/test_library.py @@ -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 @@ -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