Skip to content

Commit ee28bef

Browse files
Add support for the new Plex Movie agent (#628)
* guids collection to movie and GuidTag PlexObject * Fix flake8 * Clean up GuidTag and Guid * Add Plex Movie agent to add library doc string * Change test bootstrap server movie library to Plex Movie * Update tests for Plex Movie agent * Mix movie genre test Co-authored-by: andyloree <[email protected]>
1 parent fee5261 commit ee28bef

File tree

7 files changed

+60
-40
lines changed

7 files changed

+60
-40
lines changed

README.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,8 @@ Usage Examples
108108
109109
# Example 6: List all movies directed by the same person as Elephants Dream.
110110
movies = plex.library.section('Movies')
111-
die_hard = movies.get('Elephants Dream')
112-
director = die_hard.directors[0]
111+
elephants_dream = movies.get('Elephants Dream')
112+
director = elephants_dream.directors[0]
113113
for movie in movies.search(None, director=director):
114114
print(movie.title)
115115

plexapi/library.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,11 +167,12 @@ def add(self, name='', type='', agent='', scanner='', location='', language='en'
167167
168168
**Movie Preferences**
169169
170-
* **agent** (str): com.plexapp.agents.none, com.plexapp.agents.imdb, com.plexapp.agents.themoviedb
170+
* **agent** (str): com.plexapp.agents.none, com.plexapp.agents.imdb, tv.plex.agents.movie,
171+
com.plexapp.agents.themoviedb
171172
* **enableBIFGeneration** (bool): Enable video preview thumbnails. Default value true.
172173
* **enableCinemaTrailers** (bool): Enable Cinema Trailers. Default value true.
173174
* **includeInGlobal** (bool): Include in dashboard. Default value true.
174-
* **scanner** (str): Plex Movie Scanner, Plex Video Files Scanner
175+
* **scanner** (str): Plex Movie, Plex Movie Scanner, Plex Video Files Scanner, Plex Video Files
175176
176177
**IMDB Movie Options** (com.plexapp.agents.imdb)
177178

plexapi/media.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -681,6 +681,19 @@ def items(self, *args, **kwargs):
681681
return self.fetchItems(self.key)
682682

683683

684+
class GuidTag(PlexObject):
685+
""" Base class for guid tags used only for Guids, as they contain only a string identifier
686+
687+
Attributes:
688+
id (id): The guid for external metadata sources (e.g. IMDB, TMDB, TVDB).
689+
"""
690+
691+
def _loadData(self, data):
692+
""" Load attribute values from Plex XML response. """
693+
self._data = data
694+
self.id = data.attrib.get('id')
695+
696+
684697
@utils.registerPlexObject
685698
class Collection(MediaTag):
686699
""" Represents a single Collection media tag.
@@ -760,6 +773,16 @@ class Genre(MediaTag):
760773
FILTER = 'genre'
761774

762775

776+
@utils.registerPlexObject
777+
class Guid(GuidTag):
778+
""" Represents a single Guid media tag.
779+
780+
Attributes:
781+
TAG (str): 'Guid'
782+
"""
783+
TAG = "Guid"
784+
785+
763786
@utils.registerPlexObject
764787
class Mood(MediaTag):
765788
""" Represents a single Mood media tag.

plexapi/video.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,7 @@ class Movie(Playable, Video):
275275
directors (List<:class:`~plexapi.media.Director`>): List of director objects.
276276
duration (int): Duration of the movie in milliseconds.
277277
genres (List<:class:`~plexapi.media.Genre`>): List of genre objects.
278+
guids (List<:class:`~plexapi.media.Guid`>): List of guid objects.
278279
labels (List<:class:`~plexapi.media.Label`>): List of label objects.
279280
media (List<:class:`~plexapi.media.Media`>): List of media objects.
280281
originallyAvailableAt (datetime): Datetime the movie was released.
@@ -310,6 +311,7 @@ def _loadData(self, data):
310311
self.directors = self.findItems(data, media.Director)
311312
self.duration = utils.cast(int, data.attrib.get('duration'))
312313
self.genres = self.findItems(data, media.Genre)
314+
self.guids = self.findItems(data, media.Guid)
313315
self.labels = self.findItems(data, media.Label)
314316
self.media = self.findItems(data, media.Media)
315317
self.originallyAvailableAt = utils.toDatetime(data.attrib.get('originallyAvailableAt'), '%Y-%m-%d')

tests/test_library.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ def test_library_Library_sectionByID_is_equal_section(plex, movies):
2222

2323

2424
def test_library_sectionByID_with_attrs(plex, movies):
25-
assert movies.agent == "com.plexapp.agents.imdb"
25+
assert movies.agent == "tv.plex.agents.movie"
2626
# This seems to fail for some reason.
2727
# my account alloew of sync, didnt find any about settings about the library.
2828
# assert movies.allowSync is ('sync' in plex.ownerFeatures)
@@ -34,11 +34,11 @@ def test_library_sectionByID_with_attrs(plex, movies):
3434
assert movies.filters == "1"
3535
assert movies._initpath == "/library/sections"
3636
assert utils.is_int(movies.key)
37-
assert movies.language == "en"
37+
assert movies.language == "en-US"
3838
assert len(movies.locations) == 1
3939
assert len(movies.locations[0]) >= 10
4040
assert movies.refreshing is False
41-
assert movies.scanner == "Plex Movie Scanner"
41+
assert movies.scanner == "Plex Movie"
4242
assert movies._server._baseurl == utils.SERVER_BASEURL
4343
assert movies.thumb == "/:/resources/movie.png"
4444
assert movies.title == "Movies"
@@ -152,8 +152,8 @@ def test_library_MovieSection_refresh(movies, patched_http_call):
152152

153153

154154
def test_library_MovieSection_search_genre(movie, movies):
155-
animation = [i for i in movie.genres if i.tag == "Animation"]
156-
assert len(movies.search(genre=animation[0])) > 1
155+
genre = movie.genres[0]
156+
assert len(movies.search(genre=genre)) >= 1
157157

158158

159159
def test_library_MovieSection_cancelUpdate(movies):
@@ -255,7 +255,7 @@ def test_library_editAdvanced_default(movies):
255255
movies.reload()
256256
movies.defaultAdvanced()
257257
for setting in movies.settings():
258-
assert int(setting.value) == int(setting.default)
258+
assert str(setting.value) == str(setting.default)
259259

260260

261261
def test_library_Collection_modeUpdate(collection):

tests/test_video.py

Lines changed: 21 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ def test_video_Movie_isFullObject_and_reload(plex):
8484
movie_via_section_search.reload()
8585
assert movie_via_section_search.isFullObject() is True
8686
# If the verify that the object has been reloaded. xml from search only returns 3 actors.
87-
assert len(movie_via_section_search.roles) > 3
87+
assert len(movie_via_section_search.roles) >= 3
8888

8989

9090
def test_video_Movie_isPartialObject(movie):
@@ -155,27 +155,30 @@ def test_video_Movie_attrs(movies):
155155
assert utils.is_datetime(movie.addedAt)
156156
assert utils.is_metadata(movie.art)
157157
assert movie.artUrl
158-
assert movie.audienceRating == 8.5
159-
# Disabled this since it failed on the last run, wasnt in the original xml result.
160-
# assert movie.audienceRatingImage == 'rottentomatoes://image.rating.upright'
158+
assert float(movie.rating) >= 6.4
159+
assert movie.ratingImage == 'rottentomatoes://image.rating.ripe'
160+
assert movie.audienceRating >= 8.5
161+
assert movie.audienceRatingImage == 'rottentomatoes://image.rating.upright'
161162
movie.reload() # RELOAD
162163
assert movie.chapterSource is None
163-
assert movie.collections == []
164+
assert not movie.collections
164165
assert movie.contentRating in utils.CONTENTRATINGS
165-
assert all([i.tag in ["US", "USA"] for i in movie.countries])
166-
assert [i.tag for i in movie.directors] == ["Nina Paley"]
166+
if movie.countries:
167+
assert "United States of America" in [i.tag for i in movie.countries]
168+
if movie.producers:
169+
assert "Nina Paley" in [i.tag for i in movie.producers]
170+
if movie.directors:
171+
assert "Nina Paley" in [i.tag for i in movie.directors]
172+
if movie.roles:
173+
assert "Reena Shah" in [i.tag for i in movie.roles]
174+
if movie.writers:
175+
assert "Nina Paley" in [i.tag for i in movie.writers]
167176
assert movie.duration >= 160000
168-
assert movie.fields == []
177+
assert not movie.fields
169178
assert movie.posters()
170-
assert sorted([i.tag for i in movie.genres]) == [
171-
"Animation",
172-
"Comedy",
173-
"Drama",
174-
"Fantasy",
175-
"Musical",
176-
"Romance",
177-
]
178-
assert movie.guid == "com.plexapp.agents.imdb://tt1172203?lang=en"
179+
assert "Animation" in [i.tag for i in movie.genres]
180+
assert "imdb://tt1172203" in [i.id for i in movie.guids]
181+
assert movie.guid == "plex://movie/5d776846880197001ec967c6"
179182
assert utils.is_metadata(movie._initpath)
180183
assert utils.is_metadata(movie.key)
181184
assert utils.is_datetime(movie.lastViewedAt)
@@ -186,16 +189,7 @@ def test_video_Movie_attrs(movies):
186189
assert movie.playlistItemID is None
187190
if movie.primaryExtraKey:
188191
assert utils.is_metadata(movie.primaryExtraKey)
189-
assert [i.tag for i in movie.producers] == []
190-
assert float(movie.rating) >= 6.4
191-
# assert movie.ratingImage == 'rottentomatoes://image.rating.ripe'
192192
assert movie.ratingKey >= 1
193-
assert set(sorted([i.tag for i in movie.roles])) >= {
194-
"Aladdin Ullah",
195-
"Annette Hanshaw",
196-
"Aseem Chhabra",
197-
"Debargo Sanyal",
198-
} # noqa
199193
assert movie._server._baseurl == utils.SERVER_BASEURL
200194
assert movie.sessionKey is None
201195
assert movie.studio == "Nina Paley"
@@ -211,7 +205,6 @@ def test_video_Movie_attrs(movies):
211205
assert movie.viewCount == 0
212206
assert utils.is_int(movie.viewOffset, gte=0)
213207
assert movie.viewedAt is None
214-
assert sorted([i.tag for i in movie.writers][:4]) == ["Nina Paley"] # noqa
215208
assert movie.year == 2008
216209
# Audio
217210
audio = movie.media[0].parts[0].audioStreams()[0]
@@ -329,7 +322,7 @@ def test_video_Movie_attrs(movies):
329322
assert part.container in utils.CONTAINERS
330323
assert part.decision is None
331324
assert part.deepAnalysisVersion is None or utils.is_int(part.deepAnalysisVersion)
332-
assert utils.is_int(part.duration, 160000)
325+
assert utils.is_int(part.duration, gte=160000)
333326
assert part.exists
334327
assert len(part.file) >= 10
335328
assert part.has64bitOffsets is False

tools/plex-bootstraptest.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -520,8 +520,9 @@ def alert_callback(data):
520520
name="Movies",
521521
type="movie",
522522
location="/data/Movies" if opts.no_docker is False else movies_path,
523-
agent="com.plexapp.agents.imdb",
524-
scanner="Plex Movie Scanner",
523+
agent="tv.plex.agents.movie",
524+
scanner="Plex Movie",
525+
language='en-US',
525526
expected_media_count=num_movies,
526527
)
527528
)

0 commit comments

Comments
 (0)