Finish generic tests; a few things to polish before merge

This commit is contained in:
Michael Shepanski 2017-04-23 01:18:53 -04:00
parent 2513eb0b6d
commit 7ec909dce6
9 changed files with 685 additions and 651 deletions

View file

@ -155,128 +155,139 @@ class Library(PlexObject):
language (str): Two letter language fx en language (str): Two letter language fx en
kwargs (dict): Advanced options should be passed as a dict. where the id is the key. kwargs (dict): Advanced options should be passed as a dict. where the id is the key.
== Prefs for photo == **Photo Preferences**
* agent (str): com.plexapp.agents.none
* enableAutoPhotoTags (bool): Tag photos. Default value false.
* enableBIFGeneration (bool): Enable video preview thumbnails. Default value true.
* includeInGlobal (bool): Include in dashboard. Default value true.
* scanner (str): Plex Photo Scanner
== Prefs for other movies == * **agent** (str): com.plexapp.agents.none
* agent (str): com.plexapp.agents.none, com.plexapp.agents.imdb, com.plexapp.agents.themoviedb * **enableAutoPhotoTags** (bool): Tag photos. Default value false.
* enableBIFGeneration (bool): Enable video preview thumbnails. Default value true. * **enableBIFGeneration** (bool): Enable video preview thumbnails. Default value true.
* enableCinemaTrailers (bool): Enable Cinema Trailers. Default value true. * **includeInGlobal** (bool): Include in dashboard. Default value true.
* includeInGlobal (bool): Include in dashboard. Default value true. * **scanner** (str): Plex Photo Scanner
* scanner (str): Plex Movie Scanner, Plex Video Files Scanner
== other movies com.plexapp.agents.imdb settings options == **Movie Preferences**
* title (bool): Localized titles. Default value false.
* extras (bool): Find trailers and extras automatically (Plex Pass required). Default value true.
* only_trailers (bool): Skip extras which aren't trailers. Default value false.
* redband (bool): Use red band (restricted audiences) trailers when available. Default value false.
* native_subs (bool): Include extras with subtitles in Library language. Default value false.
* cast_list (int): Cast List Source: Default value 1 Possible options: 0:IMDb,1:The Movie Database.
* ratings (int): Ratings Source: Default value 0 Possible options:
0:Rotten Tomatoes,1:IMDb,2:The Movie Database.
* summary (int): Plot Summary Source: Default value 1 Possible options: 0:IMDb,1:The Movie Database.
* country (int): Country: Default value 46 Possible options: 0:Argentina,1:Australia,2:Austria,
3:Belgium,4:Belize,5:Bolivia,6:Brazil,7:Canada,8:Chile,9:Colombia,10:Costa Rica,11:Czech Republic,
12:Denmark,13:Dominican Republic,14:Ecuador,15:El Salvador,16:France,17:Germany,18:Guatemala,
19:Honduras,20:Hong Kong SAR,21:Ireland,22:Italy,23:Jamaica,24:Korea,25:Liechtenstein,
26:Luxembourg,27:Mexico,28:Netherlands,29:New Zealand,30:Nicaragua,31:Panama,32:Paraguay,
33:Peru,34:Portugal,35:Peoples Republic of China,36:Puerto Rico,37:Russia,38:Singapore,
39:South Africa,40:Spain,41:Sweden,42:Switzerland,43:Taiwan,44:Trinidad,45:United Kingdom,
46:United States,47:Uruguay,48:Venezuela.
* collections (bool): Use collection info from The Movie Database. Default value false.
* localart (bool): Prefer artwork based on library language. Default value true.
* adult (bool): Include adult content. Default value false.
* usage (bool): Send anonymous usage data to Plex. Default value true.
== other movies com.plexapp.agents.themoviedb settings options == * **agent** (str): com.plexapp.agents.none, com.plexapp.agents.imdb, com.plexapp.agents.themoviedb
* collections (bool): Use collection info from The Movie Database. Default value false. * **enableBIFGeneration** (bool): Enable video preview thumbnails. Default value true.
* localart (bool): Prefer artwork based on library language. Default value true. * **enableCinemaTrailers** (bool): Enable Cinema Trailers. Default value true.
* adult (bool): Include adult content. Default value false. * **includeInGlobal** (bool): Include in dashboard. Default value true.
* country (int): Country (used for release date and content rating). Default value 47 Possible * **scanner** (str): Plex Movie Scanner, Plex Video Files Scanner
options: 0:,1:Argentina,2:Australia,3:Austria,4:Belgium,5:Belize,6:Bolivia,7:Brazil,8:Canada,
9:Chile,10:Colombia,11:Costa Rica,12:Czech Republic,13:Denmark,14:Dominican Republic,
15:Ecuador,16:El Salvador,17:France,18:Germany,19:Guatemala,20:Honduras,21:Hong Kong SAR,
22:Ireland,23:Italy,24:Jamaica,25:Korea,26:Liechtenstein,27:Luxembourg,28:Mexico,
29:Netherlands,30:New Zealand,31:Nicaragua,32:Panama,33:Paraguay,34:Peru,35:Portugal,
36:Peoples Republic of China,37:Puerto Rico,38:Russia,39:Singapore,40:South Africa,
41:Spain,42:Sweden,43:Switzerland,44:Taiwan,45:Trinidad,46:United Kingdom,
47:United States,48:Uruguay,49:Venezuela.
== Prefs for movie == **IMDB Movie Options** (com.plexapp.agents.imdb)
agent (str): com.plexapp.agents.none, com.plexapp.agents.imdb, com.plexapp.agents.themoviedb
enableBIFGeneration (bool): Enable video preview thumbnails. Default value true.
enableCinemaTrailers (bool): Enable Cinema Trailers. Default value true.
includeInGlobal (bool): Include in dashboard. Default value true.
scanner (str): Plex Movie Scanner, Plex Video Files Scanner
== movie com.plexapp.agents.imdb settings options == * **title** (bool): Localized titles. Default value false.
title (bool): Localized titles. Default value false. * **extras** (bool): Find trailers and extras automatically (Plex Pass required). Default value true.
extras (bool): Find trailers and extras automatically (Plex Pass required). Default value true. * **only_trailers** (bool): Skip extras which aren't trailers. Default value false.
only_trailers (bool): Skip extras which aren't trailers. Default value false. * **redband** (bool): Use red band (restricted audiences) trailers when available. Default value false.
redband (bool): Use red band (restricted audiences) trailers when available. Default value false. * **native_subs** (bool): Include extras with subtitles in Library language. Default value false.
native_subs (bool): Include extras with subtitles in Library language. Default value false. * **cast_list** (int): Cast List Source: Default value 1 Possible options: 0:IMDb,1:The Movie Database.
cast_list (int): Cast List Source: Default value 1 Possible options: 0:IMDb,1:The Movie Database. * **ratings** (int): Ratings Source, Default value 0 Possible options:
ratings (int): Ratings Source: Default value 0 Possible options: 0:Rotten Tomatoes, 1:IMDb, 2:The Movie Database.
0:Rotten Tomatoes,1:IMDb,2:The Movie Database. * **summary** (int): Plot Summary Source: Default value 1 Possible options: 0:IMDb,1:The Movie Database.
summary (int): Plot Summary Source: Default value 1 Possible options: 0:IMDb,1:The Movie Database. * **country** (int): Default value 46 Possible options 0:Argentina, 1:Australia, 2:Austria,
country (int): Country: Default value 46 Possible options: 0:Argentina,1:Australia,2:Austria, 3:Belgium, 4:Belize, 5:Bolivia, 6:Brazil, 7:Canada, 8:Chile, 9:Colombia, 10:Costa Rica,
3:Belgium,4:Belize,5:Bolivia,6:Brazil,7:Canada,8:Chile,9:Colombia,10:Costa Rica, 11:Czech Republic, 12:Denmark, 13:Dominican Republic, 14:Ecuador, 15:El Salvador,
11:Czech Republic,12:Denmark,13:Dominican Republic,14:Ecuador,15:El Salvador, 16:France, 17:Germany, 18:Guatemala, 19:Honduras, 20:Hong Kong SAR, 21:Ireland,
16:France,17:Germany,18:Guatemala,19:Honduras,20:Hong Kong SAR,21:Ireland, 22:Italy, 23:Jamaica, 24:Korea, 25:Liechtenstein, 26:Luxembourg, 27:Mexico, 28:Netherlands,
22:Italy,23:Jamaica,24:Korea,25:Liechtenstein,26:Luxembourg,27:Mexico,28:Netherlands, 29:New Zealand, 30:Nicaragua, 31:Panama, 32:Paraguay, 33:Peru, 34:Portugal,
29:New Zealand,30:Nicaragua,31:Panama,32:Paraguay,33:Peru,34:Portugal, 35:Peoples Republic of China, 36:Puerto Rico, 37:Russia, 38:Singapore, 39:South Africa,
35:Peoples Republic of China,36:Puerto Rico,37:Russia,38:Singapore,39:South Africa, 40:Spain, 41:Sweden, 42:Switzerland, 43:Taiwan, 44:Trinidad, 45:United Kingdom,
40:Spain,41:Sweden,42:Switzerland,43:Taiwan,44:Trinidad,45:United Kingdom, 46:United States, 47:Uruguay, 48:Venezuela.
46:United States,47:Uruguay,48:Venezuela. * **collections** (bool): Use collection info from The Movie Database. Default value false.
collections (bool): Use collection info from The Movie Database. Default value false. * **localart** (bool): Prefer artwork based on library language. Default value true.
localart (bool): Prefer artwork based on library language. Default value true. * **adult** (bool): Include adult content. Default value false.
adult (bool): Include adult content. Default value false. * **usage** (bool): Send anonymous usage data to Plex. Default value true.
usage (bool): Send anonymous usage data to Plex. Default value true.
== movie com.plexapp.agents.themoviedb settings options == **TheMovieDB Movie Options** (com.plexapp.agents.themoviedb)
collections (bool): Use collection info from The Movie Database. Default value false.
localart (bool): Prefer artwork based on library language. Default value true.
adult (bool): Include adult content. Default value false.
country (int): Country (used for release date and content rating). Default value 47 Possible options:
0:,1:Argentina,2:Australia,3:Austria,4:Belgium,5:Belize,6:Bolivia,7:Brazil,8:Canada,9:Chile,
10:Colombia,11:Costa Rica,12:Czech Republic,13:Denmark,14:Dominican Republic,15:Ecuador,
16:El Salvador,17:France,18:Germany,19:Guatemala,20:Honduras,21:Hong Kong SAR,22:Ireland,
23:Italy,24:Jamaica,25:Korea,26:Liechtenstein,27:Luxembourg,28:Mexico,29:Netherlands,
30:New Zealand,31:Nicaragua,32:Panama,33:Paraguay,34:Peru,35:Portugal,36:Peoples Republic of China,
37:Puerto Rico,38:Russia,39:Singapore,40:South Africa,41:Spain,42:Sweden,43:Switzerland,
44:Taiwan,45:Trinidad,46:United Kingdom,47:United States,48:Uruguay,49:Venezuela.
== Prefs for show == * **collections** (bool): Use collection info from The Movie Database. Default value false.
agent (str): com.plexapp.agents.none, com.plexapp.agents.thetvdb, com.plexapp.agents.themoviedb * **localart** (bool): Prefer artwork based on library language. Default value true.
enableBIFGeneration (bool): Enable video preview thumbnails. Default value true. * **adult** (bool): Include adult content. Default value false.
episodeSort (int): Episode order. Default value -1 Possible options: 0:Oldest first,1:Newest first. * **country** (int): Country (used for release date and content rating). Default value 47 Possible
flattenSeasons (int): Seasons. Default value 0 Possible options: 0:Show,1:Hide. options 0:, 1:Argentina, 2:Australia, 3:Austria, 4:Belgium, 5:Belize, 6:Bolivia, 7:Brazil, 8:Canada, 9:Chile,
includeInGlobal (bool): Include in dashboard. Default value true. 10:Colombia, 11:Costa Rica, 12:Czech Republic, 13:Denmark, 14:Dominican Republic, 15:Ecuador,
scanner (str): Plex Series Scanner 16:El Salvador, 17:France, 18:Germany, 19:Guatemala, 20:Honduras, 21:Hong Kong SAR, 22:Ireland,
23:Italy, 24:Jamaica, 25:Korea, 26:Liechtenstein, 27:Luxembourg, 28:Mexico, 29:Netherlands,
30:New Zealand, 31:Nicaragua, 32:Panama, 33:Paraguay, 34:Peru, 35:Portugal, 36:Peoples Republic of China,
37:Puerto Rico, 38:Russia, 39:Singapore, 40:South Africa, 41:Spain, 42:Sweden, 43:Switzerland,
44:Taiwan, 45:Trinidad, 46:United Kingdom, 47:United States, 48:Uruguay, 49:Venezuela.
== show com.plexapp.agents.thetvdb settings options == **Show Preferences**
extras (bool): Find trailers and extras automatically (Plex Pass required). Default value true.
native_subs (bool): Include extras with subtitles in Library language. Default value false.
== show com.plexapp.agents.themoviedb settings == * **agent** (str): com.plexapp.agents.none, com.plexapp.agents.thetvdb, com.plexapp.agents.themoviedb
collections (bool): Use collection info from The Movie Database. Default value false. * **enableBIFGeneration** (bool): Enable video preview thumbnails. Default value true.
localart (bool): Prefer artwork based on library language. Default value true. * **episodeSort** (int): Episode order. Default value -1 Possible options: 0:Oldest first,1:Newest first.
adult (bool): Include adult content. Default value false. * **flattenSeasons** (int): Seasons. Default value 0 Possible options: 0:Show,1:Hide.
country (int): Country (used for release date and content rating). Default value 47 Possible options: * **includeInGlobal** (bool): Include in dashboard. Default value true.
0:,1:Argentina,2:Australia,3:Austria,4:Belgium,5:Belize,6:Bolivia,7:Brazil,8:Canada,9:Chile, * **scanner** (str): Plex Series Scanner
10:Colombia,11:Costa Rica,12:Czech Republic,13:Denmark,14:Dominican Republic,15:Ecuador,
16:El Salvador,17:France,18:Germany,19:Guatemala,20:Honduras,21:Hong Kong SAR,22:Ireland, **TheTVDB Show Options** (com.plexapp.agents.thetvdb)
23:Italy,24:Jamaica,25:Korea,26:Liechtenstein,27:Luxembourg,28:Mexico,29:Netherlands,
30:New Zealand,31:Nicaragua,32:Panama,33:Paraguay,34:Peru,35:Portugal,36:Peoples Republic of China, * **extras** (bool): Find trailers and extras automatically (Plex Pass required). Default value true.
37:Puerto Rico,38:Russia,39:Singapore,40:South Africa,41:Spain,42:Sweden,43:Switzerland, * **native_subs** (bool): Include extras with subtitles in Library language. Default value false.
44:Taiwan,45:Trinidad,46:United Kingdom,47:United States,48:Uruguay,49:Venezuela.
**TheMovieDB Show Options** (com.plexapp.agents.themoviedb)
* **collections** (bool): Use collection info from The Movie Database. Default value false.
* **localart** (bool): Prefer artwork based on library language. Default value true.
* **adult** (bool): Include adult content. Default value false.
* **country** (int): Country (used for release date and content rating). Default value 47 Possible options
0:, 1:Argentina, 2:Australia, 3:Austria, 4:Belgium, 5:Belize, 6:Bolivia, 7:Brazil, 8:Canada, 9:Chile,
10:Colombia, 11:Costa Rica, 12:Czech Republic, 13:Denmark, 14:Dominican Republic, 15:Ecuador,
16:El Salvador, 17:France, 18:Germany, 19:Guatemala, 20:Honduras, 21:Hong Kong SAR, 22:Ireland,
23:Italy, 24:Jamaica, 25:Korea, 26:Liechtenstein, 27:Luxembourg, 28:Mexico, 29:Netherlands,
30:New Zealand, 31:Nicaragua, 32:Panama, 33:Paraguay, 34:Peru, 35:Portugal, 36:Peoples Republic of China,
37:Puerto Rico, 38:Russia, 39:Singapore, 40:South Africa, 41:Spain, 42:Sweden, 43:Switzerland,
44:Taiwan, 45:Trinidad, 46:United Kingdom, 47:United States, 48:Uruguay, 49:Venezuela.
**Other Video Preferences**
* **agent** (str): com.plexapp.agents.none, com.plexapp.agents.imdb, com.plexapp.agents.themoviedb
* **enableBIFGeneration** (bool): Enable video preview thumbnails. Default value true.
* **enableCinemaTrailers** (bool): Enable Cinema Trailers. Default value true.
* **includeInGlobal** (bool): Include in dashboard. Default value true.
* **scanner** (str): Plex Movie Scanner, Plex Video Files Scanner
**IMDB Other Video Options** (com.plexapp.agents.imdb)
* **title** (bool): Localized titles. Default value false.
* **extras** (bool): Find trailers and extras automatically (Plex Pass required). Default value true.
* **only_trailers** (bool): Skip extras which aren't trailers. Default value false.
* **redband** (bool): Use red band (restricted audiences) trailers when available. Default value false.
* **native_subs** (bool): Include extras with subtitles in Library language. Default value false.
* **cast_list** (int): Cast List Source: Default value 1 Possible options: 0:IMDb,1:The Movie Database.
* **ratings** (int): Ratings Source Default value 0 Possible options:
0:Rotten Tomatoes,1:IMDb,2:The Movie Database.
* **summary** (int): Plot Summary Source: Default value 1 Possible options: 0:IMDb,1:The Movie Database.
* **country** (int): Country: Default value 46 Possible options: 0:Argentina, 1:Australia, 2:Austria,
3:Belgium, 4:Belize, 5:Bolivia, 6:Brazil, 7:Canada, 8:Chile, 9:Colombia, 10:Costa Rica, 11:Czech Republic,
12:Denmark, 13:Dominican Republic, 14:Ecuador, 15:El Salvador, 16:France, 17:Germany, 18:Guatemala,
19:Honduras, 20:Hong Kong SAR, 21:Ireland, 22:Italy, 23:Jamaica, 24:Korea, 25:Liechtenstein,
26:Luxembourg, 27:Mexico, 28:Netherlands, 29:New Zealand, 30:Nicaragua, 31:Panama, 32:Paraguay,
33:Peru, 34:Portugal, 35:Peoples Republic of China, 36:Puerto Rico, 37:Russia, 38:Singapore,
39:South Africa, 40:Spain, 41:Sweden, 42:Switzerland, 43:Taiwan, 44:Trinidad, 45:United Kingdom,
46:United States, 47:Uruguay, 48:Venezuela.
* **collections** (bool): Use collection info from The Movie Database. Default value false.
* **localart** (bool): Prefer artwork based on library language. Default value true.
* **adult** (bool): Include adult content. Default value false.
* **usage** (bool): Send anonymous usage data to Plex. Default value true.
**TheMovieDB Other Video Options** (com.plexapp.agents.themoviedb)
* **collections** (bool): Use collection info from The Movie Database. Default value false.
* **localart** (bool): Prefer artwork based on library language. Default value true.
* **adult** (bool): Include adult content. Default value false.
* **country** (int): Country (used for release date and content rating). Default
value 47 Possible options 0:, 1:Argentina, 2:Australia, 3:Austria, 4:Belgium, 5:Belize,
6:Bolivia, 7:Brazil, 8:Canada, 9:Chile, 10:Colombia, 11:Costa Rica, 12:Czech Republic,
13:Denmark, 14:Dominican Republic, 15:Ecuador, 16:El Salvador, 17:France, 18:Germany,
19:Guatemala, 20:Honduras, 21:Hong Kong SAR, 22:Ireland, 23:Italy, 24:Jamaica,
25:Korea, 26:Liechtenstein, 27:Luxembourg, 28:Mexico, 29:Netherlands, 30:New Zealand,
31:Nicaragua, 32:Panama, 33:Paraguay, 34:Peru, 35:Portugal,
36:Peoples Republic of China, 37:Puerto Rico, 38:Russia, 39:Singapore,
40:South Africa, 41:Spain, 42:Sweden, 43:Switzerland, 44:Taiwan, 45:Trinidad,
46:United Kingdom, 47:United States, 48:Uruguay, 49:Venezuela.
""" """
part = '/library/sections?name=%s&type=%s&agent=%s&scanner=%s&language=%s&location=%s' % ( part = '/library/sections?name=%s&type=%s&agent=%s&scanner=%s&language=%s&location=%s' % (
quote_plus(name), type, agent, quote_plus(scanner), language, quote_plus(location)) # noqa E126 quote_plus(name), type, agent, quote_plus(scanner), language, quote_plus(location)) # noqa E126
if kwargs: if kwargs:
part += urlencode(kwargs) part += urlencode(kwargs)
return self._server.query(part, method=self._server._session.post) return self._server.query(part, method=self._server._session.post)
@ -342,7 +353,7 @@ class LibrarySection(PlexObject):
raise raise
def edit(self, **kwargs): def edit(self, **kwargs):
""" Edit a library (Note: agent is required). See :class:`~plexapi.library.Library for example usage. """ Edit a library (Note: agent is required). See :class:`~plexapi.library.Library` for example usage.
Parameters: Parameters:
kwargs (dict): Dict of settings to edit. kwargs (dict): Dict of settings to edit.

View file

@ -160,6 +160,7 @@ def threaded(callback, listargs):
args += [results, len(results)] args += [results, len(results)]
results.append(None) results.append(None)
threads.append(Thread(target=callback, args=args)) threads.append(Thread(target=callback, args=args))
threads[-1].setDaemon(True)
threads[-1].start() threads[-1].start()
for thread in threads: for thread in threads:
thread.join() thread.join()
@ -226,7 +227,7 @@ def downloadSessionImages(server, filename=None, height=150, width=150, opacity=
return info return info
def download(url, filename=None, savepath=None, session=None, chunksize=4024, mocked=False, unpack=False): def download(url, filename=None, savepath=None, session=None, chunksize=4024, unpack=False, mocked=False):
""" Helper to download a thumb, videofile or other media item. Returns the local """ Helper to download a thumb, videofile or other media item. Returns the local
path to the downloaded file. path to the downloaded file.

View file

@ -1,6 +1,9 @@
#--------------------------------------------------------- #---------------------------------------------------------
# PlexAPI requirements to build documentation. # PlexAPI requirements to build documentation.
# pip install -r requirments_doc.txt # pip install -r requirments_doc.txt
#
# If testing locally:
# sudo apt-get install python-sphinx
#--------------------------------------------------------- #---------------------------------------------------------
recommonmark recommonmark
sphinx-rtd-theme sphinx-rtd-theme

View file

@ -1,19 +1,29 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import plexapi, pytest, requests import plexapi, pytest, requests
from plexapi import compat
from datetime import datetime from datetime import datetime
from plexapi.myplex import MyPlexAccount from plexapi.myplex import MyPlexAccount
from plexapi.server import PlexServer from plexapi.server import PlexServer
from functools import partial from functools import partial
MIN_DATETIME = datetime(2017, 1, 1)
REGEX_EMAIL = r'(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)'
REGEX_IPADDR = r'^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$'
SERVER_BASEURL = plexapi.CONFIG.get('auth.server_baseurl') SERVER_BASEURL = plexapi.CONFIG.get('auth.server_baseurl')
SERVER_TOKEN = plexapi.CONFIG.get('auth.server_token') SERVER_TOKEN = plexapi.CONFIG.get('auth.server_token')
MYPLEX_USERNAME = plexapi.CONFIG.get('auth.myplex_username') MYPLEX_USERNAME = plexapi.CONFIG.get('auth.myplex_username')
MYPLEX_PASSWORD = plexapi.CONFIG.get('auth.myplex_password') MYPLEX_PASSWORD = plexapi.CONFIG.get('auth.myplex_password')
MIN_DATETIME = datetime(2017, 1, 1)
REGEX_EMAIL = r'(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)'
REGEX_IPADDR = r'^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$'
AUDIOCHANNELS = [2, 6]
AUDIOLAYOUTS = ['5.1', 'stereo']
CODECS = ['aac', 'h264', 'mp3', 'mpeg4']
CONTAINERS = ['avi', 'mp4']
CONTENTRATINGS = ['TV-14']
FRAMERATES = ['24p', 'PAL']
PROFILES = ['advanced simple', 'main']
RESOLUTIONS = ['720', 'sd']
def pytest_addoption(parser): def pytest_addoption(parser):
parser.addoption('--req_client', action='store_true', help='Run tests that interact with a client') parser.addoption('--req_client', action='store_true', help='Run tests that interact with a client')
@ -120,17 +130,35 @@ def is_datetime(value):
return value > MIN_DATETIME return value > MIN_DATETIME
def is_int(value): def is_int(value, gte=1):
return int(value) >= 1 return int(value) >= gte
def is_metadata(key): def is_float(value, gte=1.0):
return key.startswith('/library/metadata/') return float(value) >= gte
def is_metadata(key, prefix='/library/metadata/', contains='', suffix=''):
try:
assert key.startswith(prefix)
assert contains in key
assert key.endswith(suffix)
return True
except AssertionError:
return False
def is_part(key): def is_part(key):
return key.startswith('/library/parts/') return is_metadata(key, prefix='/library/parts/')
def is_section(key):
return is_metadata(key, prefix='/library/sections/')
def is_string(value, gte=1):
return isinstance(value, compat.string_type) and len(value) >= gte
def is_thumb(key): def is_thumb(key):
return key.startswith('/library/metadata/') and '/thumb/' in key return is_metadata(key, contains='/thumb/')

View file

@ -1,31 +1,29 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from datetime import datetime from datetime import datetime
from .conftest import is_int, is_datetime from . import conftest as utils
from .conftest import is_metadata, is_part, is_thumb
from .conftest import SERVER_BASEURL
def test_audio_Artist_attr(artist): def test_audio_Artist_attr(artist):
artist.reload() artist.reload()
assert is_datetime(artist.addedAt) assert utils.is_datetime(artist.addedAt)
assert artist.countries == [] assert artist.countries == []
assert [i.tag for i in artist.genres] == ['Electronic'] assert [i.tag for i in artist.genres] == ['Electronic']
assert 'lastfm' in artist.guid assert 'lastfm' in artist.guid
assert artist.index == '1' assert artist.index == '1'
assert is_metadata(artist._initpath) assert utils.is_metadata(artist._initpath)
assert is_metadata(artist.key) assert utils.is_metadata(artist.key)
assert is_int(artist.librarySectionID) assert utils.is_int(artist.librarySectionID)
assert artist.listType == 'audio' assert artist.listType == 'audio'
assert len(artist.locations) == 1 assert len(artist.locations) == 1
assert len(artist.locations[0]) >= 10 assert len(artist.locations[0]) >= 10
assert artist.ratingKey >= 1 assert artist.ratingKey >= 1
assert artist._server._baseurl == SERVER_BASEURL assert artist._server._baseurl == utils.SERVER_BASEURL
assert artist.similar == [] assert artist.similar == []
assert artist.summary == '' assert artist.summary == ''
assert artist.title == 'Infinite State' assert artist.title == 'Infinite State'
assert artist.titleSort == 'Infinite State' assert artist.titleSort == 'Infinite State'
assert artist.type == 'artist' assert artist.type == 'artist'
assert is_datetime(artist.updatedAt) assert utils.is_datetime(artist.updatedAt)
assert artist.viewCount == 0 assert artist.viewCount == 0
@ -55,27 +53,27 @@ def test_audio_Artist_albums(artist):
def test_audio_Album_attrs(album): def test_audio_Album_attrs(album):
assert is_datetime(album.addedAt) assert utils.is_datetime(album.addedAt)
assert [i.tag for i in album.genres] == ['Electronic'] assert [i.tag for i in album.genres] == ['Electronic']
assert album.index == '1' assert album.index == '1'
assert is_metadata(album._initpath) assert utils.is_metadata(album._initpath)
assert is_metadata(album.key) assert utils.is_metadata(album.key)
assert is_int(album.librarySectionID) assert utils.is_int(album.librarySectionID)
assert album.listType == 'audio' assert album.listType == 'audio'
assert album.originallyAvailableAt == datetime(2016, 1, 1) assert album.originallyAvailableAt == datetime(2016, 1, 1)
assert is_metadata(album.parentKey) assert utils.is_metadata(album.parentKey)
assert is_int(album.parentRatingKey) assert utils.is_int(album.parentRatingKey)
assert is_thumb(album.parentThumb) assert utils.is_metadata(album.parentThumb, contains='/thumb/')
assert album.parentTitle == 'Infinite State' assert album.parentTitle == 'Infinite State'
assert album.ratingKey >= 1 assert album.ratingKey >= 1
assert album._server._baseurl == SERVER_BASEURL assert album._server._baseurl == utils.SERVER_BASEURL
assert album.studio is None assert album.studio is None
assert album.summary == '' assert album.summary == ''
assert is_thumb(album.thumb) assert utils.is_metadata(album.thumb, contains='/thumb/')
assert album.title == 'Unmastered Impulses' assert album.title == 'Unmastered Impulses'
assert album.titleSort == 'Unmastered Impulses' assert album.titleSort == 'Unmastered Impulses'
assert album.type == 'album' assert album.type == 'album'
assert is_datetime(album.updatedAt) assert utils.is_datetime(album.updatedAt)
assert album.viewCount == 0 assert album.viewCount == 0
assert album.year == 2016 assert album.year == 2016
@ -84,30 +82,30 @@ def test_audio_Album_tracks(album):
tracks = album.tracks() tracks = album.tracks()
track = tracks[0] track = tracks[0]
assert len(tracks) == 14 assert len(tracks) == 14
assert is_metadata(track.grandparentKey) assert utils.is_metadata(track.grandparentKey)
assert is_int(track.grandparentRatingKey) assert utils.is_int(track.grandparentRatingKey)
assert track.grandparentTitle == 'Infinite State' assert track.grandparentTitle == 'Infinite State'
assert track.index == '1' assert track.index == '1'
assert is_metadata(track._initpath) assert utils.is_metadata(track._initpath)
assert is_metadata(track.key) assert utils.is_metadata(track.key)
assert track.listType == 'audio' assert track.listType == 'audio'
assert track.originalTitle == 'Kenneth Reitz' assert track.originalTitle == 'Kenneth Reitz'
assert is_int(track.parentIndex) assert utils.is_int(track.parentIndex)
assert is_metadata(track.parentKey) assert utils.is_metadata(track.parentKey)
assert is_int(track.parentRatingKey) assert utils.is_int(track.parentRatingKey)
assert is_thumb(track.parentThumb) assert utils.is_metadata(track.parentThumb, contains='/thumb/')
assert track.parentTitle == 'Unmastered Impulses' assert track.parentTitle == 'Unmastered Impulses'
assert track.player is None assert track.player is None
assert track.ratingCount == 9 assert track.ratingCount == 9
assert is_int(track.ratingKey) assert utils.is_int(track.ratingKey)
assert track._server._baseurl == SERVER_BASEURL assert track._server._baseurl == utils.SERVER_BASEURL
assert track.summary == "" assert track.summary == ""
assert is_thumb(track.thumb) assert utils.is_metadata(track.thumb, contains='/thumb/')
assert track.title == 'Holy Moment' assert track.title == 'Holy Moment'
assert track.titleSort == 'Holy Moment' assert track.titleSort == 'Holy Moment'
assert track.transcodeSession is None assert track.transcodeSession is None
assert track.type == 'track' assert track.type == 'track'
assert is_datetime(track.updatedAt) assert utils.is_datetime(track.updatedAt)
assert track.username is None assert track.username is None
assert track.viewCount == 0 assert track.viewCount == 0
assert track.viewOffset == 0 assert track.viewOffset == 0
@ -116,34 +114,34 @@ def test_audio_Album_tracks(album):
def test_audio_Album_track(album, track=None): def test_audio_Album_track(album, track=None):
# this is not reloaded. its not that much info missing. # this is not reloaded. its not that much info missing.
track = track or album.track('Holy Moment') track = track or album.track('Holy Moment')
assert is_datetime(track.addedAt) assert utils.is_datetime(track.addedAt)
assert track.duration == 298606 assert track.duration == 298606
assert is_metadata(track.grandparentKey) assert utils.is_metadata(track.grandparentKey)
assert is_int(track.grandparentRatingKey) assert utils.is_int(track.grandparentRatingKey)
assert track.grandparentTitle == 'Infinite State' assert track.grandparentTitle == 'Infinite State'
assert int(track.index) == 1 assert int(track.index) == 1
assert is_metadata(track._initpath) assert utils.is_metadata(track._initpath)
assert is_metadata(track.key) assert utils.is_metadata(track.key)
assert track.listType == 'audio' assert track.listType == 'audio'
# Assign 0 track.media # Assign 0 track.media
media = track.media[0] media = track.media[0]
assert track.originalTitle == 'Kenneth Reitz' assert track.originalTitle == 'Kenneth Reitz'
assert is_int(track.parentIndex) assert utils.is_int(track.parentIndex)
assert is_metadata(track.parentKey) assert utils.is_metadata(track.parentKey)
assert is_int(track.parentRatingKey) assert utils.is_int(track.parentRatingKey)
assert is_thumb(track.parentThumb) assert utils.is_metadata(track.parentThumb, contains='/thumb/')
assert track.parentTitle == 'Unmastered Impulses' assert track.parentTitle == 'Unmastered Impulses'
assert track.player is None assert track.player is None
assert track.ratingCount == 9 assert track.ratingCount == 9
assert is_int(track.ratingKey) assert utils.is_int(track.ratingKey)
assert track._server._baseurl == SERVER_BASEURL assert track._server._baseurl == utils.SERVER_BASEURL
assert track.summary == '' assert track.summary == ''
assert is_thumb(track.thumb) assert utils.is_metadata(track.thumb, contains='/thumb/')
assert track.title == 'Holy Moment' assert track.title == 'Holy Moment'
assert track.titleSort == 'Holy Moment' assert track.titleSort == 'Holy Moment'
assert track.transcodeSession is None assert track.transcodeSession is None
assert track.type == 'track' assert track.type == 'track'
assert is_datetime(track.updatedAt) assert utils.is_datetime(track.updatedAt)
assert track.username is None assert track.username is None
assert track.viewCount == 0 assert track.viewCount == 0
assert track.viewOffset == 0 assert track.viewOffset == 0
@ -155,11 +153,11 @@ def test_audio_Album_track(album, track=None):
assert media.duration == 298606 assert media.duration == 298606
assert media.height is None assert media.height is None
assert media.id == 22 assert media.id == 22
assert is_metadata(media._initpath) assert utils.is_metadata(media._initpath)
assert media.optimizedForStreaming is None assert media.optimizedForStreaming is None
# Assign 0 media.parts # Assign 0 media.parts
part = media.parts[0] part = media.parts[0]
assert media._server._baseurl == SERVER_BASEURL assert media._server._baseurl == utils.SERVER_BASEURL
assert media.videoCodec is None assert media.videoCodec is None
assert media.videoFrameRate is None assert media.videoFrameRate is None
assert media.videoResolution is None assert media.videoResolution is None
@ -167,10 +165,10 @@ def test_audio_Album_track(album, track=None):
assert part.container == 'mp3' assert part.container == 'mp3'
assert part.duration == 298606 assert part.duration == 298606
assert part.file.endswith('.mp3') assert part.file.endswith('.mp3')
assert is_int(part.id) assert utils.is_int(part.id)
assert is_metadata(part._initpath) assert utils.is_metadata(part._initpath)
assert is_part(part.key) assert utils.is_part(part.key)
assert part._server._baseurl == SERVER_BASEURL assert part._server._baseurl == utils.SERVER_BASEURL
assert part.size == 14360402 assert part.size == 14360402
@ -187,45 +185,45 @@ def test_audio_Album_artist(album):
def test_audio_Track_attrs(album): def test_audio_Track_attrs(album):
track = album.get('Holy Moment').reload() track = album.get('Holy Moment').reload()
assert is_datetime(track.addedAt) assert utils.is_datetime(track.addedAt)
assert track.art is None assert track.art is None
assert track.chapterSource is None assert track.chapterSource is None
assert track.duration == 298606 assert track.duration == 298606
assert track.grandparentArt is None assert track.grandparentArt is None
assert is_metadata(track.grandparentKey) assert utils.is_metadata(track.grandparentKey)
assert is_int(track.grandparentRatingKey) assert utils.is_int(track.grandparentRatingKey)
assert is_thumb(track.grandparentThumb) assert utils.is_metadata(track.grandparentThumb, contains='/thumb/')
assert track.grandparentTitle == 'Infinite State' assert track.grandparentTitle == 'Infinite State'
assert track.guid.startswith('local://') assert track.guid.startswith('local://')
assert int(track.index) == 1 assert int(track.index) == 1
assert is_metadata(track._initpath) assert utils.is_metadata(track._initpath)
assert is_metadata(track.key) assert utils.is_metadata(track.key)
assert track.lastViewedAt is None assert track.lastViewedAt is None
assert is_int(track.librarySectionID) assert utils.is_int(track.librarySectionID)
assert track.listType == 'audio' assert track.listType == 'audio'
# Assign 0 track.media # Assign 0 track.media
media = track.media[0] media = track.media[0]
assert track.moods == [] assert track.moods == []
assert track.originalTitle == 'Kenneth Reitz' assert track.originalTitle == 'Kenneth Reitz'
assert int(track.parentIndex) == 1 assert int(track.parentIndex) == 1
assert is_metadata(track.parentKey) assert utils.is_metadata(track.parentKey)
assert is_int(track.parentRatingKey) assert utils.is_int(track.parentRatingKey)
assert is_thumb(track.parentThumb) assert utils.is_metadata(track.parentThumb, contains='/thumb/')
assert track.parentTitle == 'Unmastered Impulses' assert track.parentTitle == 'Unmastered Impulses'
assert track.player is None assert track.player is None
assert track.playlistItemID is None assert track.playlistItemID is None
assert track.primaryExtraKey is None assert track.primaryExtraKey is None
assert track.ratingCount == 9 assert track.ratingCount == 9
assert is_int(track.ratingKey) assert utils.is_int(track.ratingKey)
assert track._server._baseurl == SERVER_BASEURL assert track._server._baseurl == utils.SERVER_BASEURL
assert track.sessionKey is None assert track.sessionKey is None
assert track.summary == '' assert track.summary == ''
assert is_thumb(track.thumb) assert utils.is_metadata(track.thumb, contains='/thumb/')
assert track.title == 'Holy Moment' assert track.title == 'Holy Moment'
assert track.titleSort == 'Holy Moment' assert track.titleSort == 'Holy Moment'
assert track.transcodeSession is None assert track.transcodeSession is None
assert track.type == 'track' assert track.type == 'track'
assert is_datetime(track.updatedAt) assert utils.is_datetime(track.updatedAt)
assert track.username is None assert track.username is None
assert track.viewCount == 0 assert track.viewCount == 0
assert track.viewOffset == 0 assert track.viewOffset == 0
@ -239,11 +237,11 @@ def test_audio_Track_attrs(album):
assert media.duration == 298606 assert media.duration == 298606
assert media.height is None assert media.height is None
assert media.id == 22 assert media.id == 22
assert is_metadata(media._initpath) assert utils.is_metadata(media._initpath)
assert media.optimizedForStreaming is None assert media.optimizedForStreaming is None
# Assign 0 media.parts # Assign 0 media.parts
part = media.parts[0] part = media.parts[0]
assert media._server._baseurl == SERVER_BASEURL assert media._server._baseurl == utils.SERVER_BASEURL
assert media.videoCodec is None assert media.videoCodec is None
assert media.videoFrameRate is None assert media.videoFrameRate is None
assert media.videoResolution is None assert media.videoResolution is None
@ -251,11 +249,11 @@ def test_audio_Track_attrs(album):
assert part.container == 'mp3' assert part.container == 'mp3'
assert part.duration == 298606 assert part.duration == 298606
assert part.file.endswith('.mp3') assert part.file.endswith('.mp3')
assert is_int(part.id) assert utils.is_int(part.id)
assert is_metadata(part._initpath) assert utils.is_metadata(part._initpath)
assert is_part(part.key) assert utils.is_part(part.key)
#assert part.media == <Media:Holy.Moment> #assert part.media == <Media:Holy.Moment>
assert part._server._baseurl == SERVER_BASEURL assert part._server._baseurl == utils.SERVER_BASEURL
assert part.size == 14360402 assert part.size == 14360402
# Assign 0 part.streams # Assign 0 part.streams
stream = part.streams[0] stream = part.streams[0]
@ -268,15 +266,15 @@ def test_audio_Track_attrs(album):
assert stream.codecID is None assert stream.codecID is None
assert stream.dialogNorm is None assert stream.dialogNorm is None
assert stream.duration is None assert stream.duration is None
assert is_int(stream.id) assert utils.is_int(stream.id)
assert stream.index == 0 assert stream.index == 0
assert is_metadata(stream._initpath) assert utils.is_metadata(stream._initpath)
assert stream.language is None assert stream.language is None
assert stream.languageCode is None assert stream.languageCode is None
#assert stream.part == <MediaPart:22> #assert stream.part == <MediaPart:22>
assert stream.samplingRate == 44100 assert stream.samplingRate == 44100
assert stream.selected is True assert stream.selected is True
assert stream._server._baseurl == SERVER_BASEURL assert stream._server._baseurl == utils.SERVER_BASEURL
assert stream.streamType == 2 assert stream.streamType == 2
assert stream.title is None assert stream.title is None
assert stream.type == 2 assert stream.type == 2

View file

@ -1,8 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import pytest import pytest
from plexapi.exceptions import NotFound from plexapi.exceptions import NotFound
from .conftest import is_datetime from . import conftest as utils
from .conftest import SERVER_BASEURL
def test_library_Library_section(plex): def test_library_Library_section(plex):
@ -27,7 +26,7 @@ def test_library_sectionByID_with_attrs(plex):
assert section.allowSync is False assert section.allowSync is False
assert section.art == '/:/resources/movie-fanart.jpg' assert section.art == '/:/resources/movie-fanart.jpg'
assert '/library/sections/1/composite/' in section.composite assert '/library/sections/1/composite/' in section.composite
assert is_datetime(section.createdAt) assert utils.is_datetime(section.createdAt)
assert section.filters == '1' assert section.filters == '1'
assert section._initpath == '/library/sections' assert section._initpath == '/library/sections'
assert section.key == '1' assert section.key == '1'
@ -36,11 +35,11 @@ def test_library_sectionByID_with_attrs(plex):
assert len(section.locations[0]) >= 10 assert len(section.locations[0]) >= 10
assert section.refreshing is False assert section.refreshing is False
assert section.scanner == 'Plex Movie Scanner' assert section.scanner == 'Plex Movie Scanner'
assert section._server._baseurl == SERVER_BASEURL assert section._server._baseurl == utils.SERVER_BASEURL
assert section.thumb == '/:/resources/movie.png' assert section.thumb == '/:/resources/movie.png'
assert section.title == 'Movies' assert section.title == 'Movies'
assert section.type == 'movie' assert section.type == 'movie'
assert is_datetime(section.updatedAt) assert utils.is_datetime(section.updatedAt)
assert len(section.uuid) == 36 assert len(section.uuid) == 36

View file

@ -11,16 +11,19 @@ SKIP_EXAMPLES = ['Example 4']
@pytest.mark.skipif(os.name == 'nt', reason='No make.bat specified for Windows') @pytest.mark.skipif(os.name == 'nt', reason='No make.bat specified for Windows')
def test_build_documentation(): def test_build_documentation():
docroot = join(dirname(dirname(abspath(__file__))), 'docs') docroot = join(dirname(dirname(abspath(__file__))), 'docs')
cmd = shlex.split('sphinx-build . _build') cmd = shlex.split('sphinx-build -aE . _build')
proc = subprocess.Popen(cmd, cwd=docroot, stdout=subprocess.PIPE, stderr=subprocess.PIPE) proc = subprocess.Popen(cmd, cwd=docroot, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
status = proc.wait() status = proc.wait()
assert status == 0 assert status == 0
issues = []
for output in proc.communicate(): for output in proc.communicate():
for line in str(output).split('\\n'): for line in str(output).split('\\n'):
line = line.lower().strip() line = line.lower().strip()
assert 'warning' not in line if 'warning' in line or 'error' in line or 'traceback' in line:
assert 'error' not in line issues.append(line)
assert 'traceback' not in line for line in issues:
print(line)
assert not issues
def test_readme_examples(plex): def test_readme_examples(plex):

View file

@ -5,25 +5,23 @@ from plexapi.server import PlexServer
from plexapi.utils import download from plexapi.utils import download
from PIL import Image, ImageStat from PIL import Image, ImageStat
from requests import Session from requests import Session
from .conftest import is_datetime from . import conftest as utils
from .conftest import REGEX_EMAIL, REGEX_IPADDR
from .conftest import SERVER_BASEURL, SERVER_TOKEN
def test_server_attr(plex): def test_server_attr(plex):
assert plex._baseurl == SERVER_BASEURL assert plex._baseurl == utils.SERVER_BASEURL
assert len(plex.friendlyName) >= 1 assert len(plex.friendlyName) >= 1
assert len(plex.machineIdentifier) == 40 assert len(plex.machineIdentifier) == 40
assert plex.myPlex is True assert plex.myPlex is True
assert plex.myPlexMappingState == 'mapped' assert plex.myPlexMappingState == 'mapped'
assert plex.myPlexSigninState == 'ok' assert plex.myPlexSigninState == 'ok'
assert plex.myPlexSubscription == '0' assert plex.myPlexSubscription == '0'
assert re.match(REGEX_EMAIL, plex.myPlexUsername) assert re.match(utils.REGEX_EMAIL, plex.myPlexUsername)
assert plex.platform in ('Linux', 'Windows') assert plex.platform in ('Linux', 'Windows')
assert len(plex.platformVersion) >= 5 assert len(plex.platformVersion) >= 5
assert plex._token == SERVER_TOKEN assert plex._token == utils.SERVER_TOKEN
assert plex.transcoderActiveVideoSessions == 0 assert plex.transcoderActiveVideoSessions == 0
assert is_datetime(plex.updatedAt) assert utils.is_datetime(plex.updatedAt)
assert len(plex.version) >= 5 assert len(plex.version) >= 5
@ -127,7 +125,7 @@ def test_server_Server_query(plex):
with pytest.raises(BadRequest): with pytest.raises(BadRequest):
# This is really requests.exceptions.HTTPError # This is really requests.exceptions.HTTPError
# 401 Client Error: Unauthorized for url # 401 Client Error: Unauthorized for url
PlexServer(SERVER_BASEURL, '1234') PlexServer(utils.SERVER_BASEURL, '1234')
def test_server_Server_session(): def test_server_Server_session():
@ -137,7 +135,7 @@ def test_server_Server_session():
super(self.__class__, self).__init__() super(self.__class__, self).__init__()
self.plexapi_session_test = True self.plexapi_session_test = True
# Test Code # Test Code
plex = PlexServer(SERVER_BASEURL, SERVER_TOKEN, session=MySession()) plex = PlexServer(utils.SERVER_BASEURL, utils.SERVER_TOKEN, session=MySession())
assert hasattr(plex._session, 'plexapi_session_test') assert hasattr(plex._session, 'plexapi_session_test')
@ -204,15 +202,15 @@ def test_server_account(plex):
# assert account.mappingError == 'publisherror' # assert account.mappingError == 'publisherror'
assert account.mappingErrorMessage is None assert account.mappingErrorMessage is None
assert account.mappingState == 'mapped' assert account.mappingState == 'mapped'
assert re.match(REGEX_IPADDR, account.privateAddress) assert re.match(utils.REGEX_IPADDR, account.privateAddress)
assert int(account.privatePort) >= 1000 assert int(account.privatePort) >= 1000
assert re.match(REGEX_IPADDR, account.publicAddress) assert re.match(utils.REGEX_IPADDR, account.publicAddress)
assert int(account.publicPort) >= 1000 assert int(account.publicPort) >= 1000
assert account.signInState == 'ok' assert account.signInState == 'ok'
assert account.subscriptionActive is False assert account.subscriptionActive is False
assert account.subscriptionFeatures == [] assert account.subscriptionFeatures == []
assert account.subscriptionState == 'Unknown' assert account.subscriptionState == 'Unknown'
assert re.match(REGEX_EMAIL, account.username) assert re.match(utils.REGEX_EMAIL, account.username)
def test_server_downloadLogs(tmpdir, plex): def test_server_downloadLogs(tmpdir, plex):

View file

@ -1,40 +1,38 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import plexapi, pytest import pytest
from datetime import datetime from datetime import datetime
from plexapi.exceptions import BadRequest, NotFound from plexapi.exceptions import BadRequest, NotFound
from . import conftest as utils
def test_video_Movie(a_movie_section): def test_video_Movie(movies):
m = a_movie_section.get('Cars') movie = movies.get('Cars')
assert m.title == 'Cars' assert movie.title == 'Cars'
def test_video_Movie_delete(monkeypatch, pms):
m = pms.library.section('Movies').get('16 blocks')
monkeypatch.delattr("requests.sessions.Session.request")
try:
m.delete()
except AttributeError:
# Silence this because it will always raise beause of monkeypatch
pass
def test_video_Movie_delete(monkeypatch, plex):
def test_video_Movie_getStreamURL(a_movie): movie = plex.library.section('Movies').get('16 blocks')
server_token = plexapi.CONFIG.get('auth.server_token') monkeypatch.delattr('requests.sessions.Session.request')
assert a_movie.getStreamURL() == "http://138.68.157.5:32400/video/:/transcode/universal/start.m3u8?X-Plex-Platform=Chrome&copyts=1&mediaIndex=0&offset=0&path=%2Flibrary%2Fmetadata%2F1&X-Plex-Token={0}".format(server_token) with pytest.raises(AttributeError):
assert a_movie.getStreamURL(videoResolution='800x600') == "http://138.68.157.5:32400/video/:/transcode/universal/start.m3u8?X-Plex-Platform=Chrome&copyts=1&mediaIndex=0&offset=0&path=%2Flibrary%2Fmetadata%2F1&videoResolution=800x600&X-Plex-Token={0}".format(server_token) movie.delete()
def test_video_Movie_isFullObject_and_reload(pms): def test_video_Movie_getStreamURL(movie):
movie = pms.library.section('Movies').get('16 Blocks') key = movie.ratingKey
assert movie.getStreamURL() == '{0}/video/:/transcode/universal/start.m3u8?X-Plex-Platform=Chrome&copyts=1&mediaIndex=0&offset=0&path=%2Flibrary%2Fmetadata%2F{1}&X-Plex-Token={2}'.format(utils.SERVER_BASEURL, key, utils.SERVER_TOKEN) # noqa
assert movie.getStreamURL(videoResolution='800x600') == '{0}/video/:/transcode/universal/start.m3u8?X-Plex-Platform=Chrome&copyts=1&mediaIndex=0&offset=0&path=%2Flibrary%2Fmetadata%2F{1}&videoResolution=800x600&X-Plex-Token={2}'.format(utils.SERVER_BASEURL, key, utils.SERVER_TOKEN) # noqa
def test_video_Movie_isFullObject_and_reload(plex):
movie = plex.library.section('Movies').get('Cars')
assert movie.isFullObject() is False assert movie.isFullObject() is False
movie.reload() movie.reload()
assert movie.isFullObject() is True assert movie.isFullObject() is True
movie_via_search = pms.library.search('16 Blocks')[0] movie_via_search = plex.library.search('Cars')[0]
assert movie_via_search.isFullObject() is False assert movie_via_search.isFullObject() is False
movie_via_search.reload() movie_via_search.reload()
assert movie_via_search.isFullObject() is True assert movie_via_search.isFullObject() is True
movie_via_section_search = pms.library.section('Movies').search('16 Blocks')[0] movie_via_section_search = plex.library.section('Movies').search('Cars')[0]
assert movie_via_section_search.isFullObject() is False assert movie_via_section_search.isFullObject() is False
movie_via_section_search.reload() movie_via_section_search.reload()
assert movie_via_section_search.isFullObject() is True assert movie_via_section_search.isFullObject() is True
@ -42,501 +40,496 @@ def test_video_Movie_isFullObject_and_reload(pms):
assert len(movie_via_section_search.roles) > 3 assert len(movie_via_section_search.roles) > 3
def test_video_Movie_isPartialObject(a_movie): def test_video_Movie_isPartialObject(movie):
assert a_movie.isPartialObject() assert movie.isPartialObject()
def test_video_Movie_iterParts(a_movie): def test_video_Movie_iterParts(movie):
assert len(list(a_movie.iterParts())) == 1 assert len(list(movie.iterParts())) >= 1
def test_video_Movie_download(monkeydownload, tmpdir, a_movie): def test_video_Movie_download(monkeydownload, tmpdir, movie):
downloaded_movie = a_movie.download(savepath=str(tmpdir)) filepaths1 = movie.download(savepath=str(tmpdir))
assert len(downloaded_movie) == 1 assert len(filepaths1) >= 1
downloaded_movie2 = a_movie.download(savepath=str(tmpdir), **{'videoResolution': '500x300'}) filepaths2 = movie.download(savepath=str(tmpdir), videoResolution='500x300')
assert len(downloaded_movie2) == 1 assert len(filepaths2) >= 1
def test_video_Movie_attrs_as_much_as_possible(a_movie_section): def test_video_Movie_attrs(movies):
m = a_movie_section.get('Cars') movie = movies.get('Cars')
assert m.locations == ['/media/movies/cars/cars.mp4'] assert len(movie.locations[0]) >= 10
assert m.addedAt > datetime(2017, 1, 1) assert utils.is_datetime(movie.addedAt)
assert '/library/metadata/2/art/' in m.art assert utils.is_metadata(movie.art)
assert m.audienceRating == 7.9 assert movie.audienceRating == 7.9
assert m.audienceRatingImage == 'rottentomatoes://image.rating.upright' assert movie.audienceRatingImage == 'rottentomatoes://image.rating.upright'
# Assign 0 m.audioStreams movie.reload() # RELOAD
m.reload() assert movie.chapterSource == 'agent'
aud0 = m.media[0].parts[0].audioStreams[0] assert movie.collections == []
assert m.chapterSource == 'agent' assert movie.contentRating == 'G'
assert m.collections == [] assert [i.tag for i in movie.countries] == ['USA']
assert m.contentRating == 'G' assert [i.tag for i in movie.directors] == ['John Lasseter', 'Joe Ranft']
#assert m.countries == [<Country:35:USA>] assert movie.duration >= 3600000
assert [i.tag for i in m.directors] == ['John Lasseter', 'Joe Ranft'] assert movie.fields == []
assert m.duration == 170859 assert sorted([i.tag for i in movie.genres]) == ['Adventure', 'Animation', 'Comedy', 'Family', 'Sport']
assert m.fields == [] assert movie.guid == 'com.plexapp.agents.imdb://tt0317219?lang=en'
assert [i.tag for i in m.genres] == ['Animation', 'Family', 'Comedy', 'Sport', 'Adventure'] assert utils.is_metadata(movie._initpath)
assert m.guid == 'com.plexapp.agents.imdb://tt0317219?lang=en' assert utils.is_metadata(movie.key)
assert m._initpath == '/library/metadata/2' assert movie.lastViewedAt is None
assert m.key == '/library/metadata/2' assert int(movie.librarySectionID) >= 1
assert m.lastViewedAt > datetime(2017, 1, 1) assert movie.listType == 'video'
assert m.librarySectionID == '1' assert movie.originalTitle is None
assert m.listType == 'video' assert movie.originallyAvailableAt.strftime('%Y-%m-%d') == '2006-06-09'
# Assign 0 m.media assert movie.player is None
med0 = m.media[0] assert movie.playlistItemID is None
assert m.originalTitle is None assert movie.primaryExtraKey is None
assert str(m.originallyAvailableAt.date()) == '2006-06-09' assert [i.tag for i in movie.producers] == ['Darla K. Anderson']
assert m.player is None assert movie.rating == '7.4'
assert m.playlistItemID is None assert movie.ratingImage == 'rottentomatoes://image.rating.certified'
assert m.primaryExtraKey is None assert movie.ratingKey >= 1
#assert m.producers == [<Producer:130:Darla.K..Anderson>] assert sorted([i.tag for i in movie.roles]) == ['Adrian Ochoa', 'Andrew Stanton', 'Billy Crystal', 'Bob Costas', 'Bonnie Hunt', 'Cheech Marin', 'Dale Earnhardt Jr.', 'Darrell Waltrip', 'Dave Foley', 'Douglas Keever', 'E.J. Holowicki', 'Edie McClurg', 'Elissa Knight', 'George Carlin', 'Guido Quaroni', 'Humpy Wheeler', 'Jay Leno', 'Jenifer Lewis', 'Jeremy Piven', 'Joe Ranft', 'Joe Ranft', 'John Goodman', 'John Ratzenberger', 'John Ratzenberger', 'John Ratzenberger', 'John Ratzenberger', 'Jonas Rivera', 'Katherine Helmond', 'Larry Benton', 'Larry the Cable Guy', 'Lindsey Collins', 'Lou Romano', 'Lynda Petty', 'Michael Keaton', 'Michael Schumacher', 'Michael Wallis', 'Mike Nelson', 'Owen Wilson', 'Paul Dooley', 'Paul Newman', 'Ray Magliozzi', 'Richard Kind', 'Richard Petty', 'Sarah Clark', 'Tim Allen', 'Tom Hanks', 'Tom Magliozzi', 'Tony Shalhoub', 'Vanness Wu'] # noqa
assert m.rating == '7.4' assert movie._server._baseurl == utils.SERVER_BASEURL
assert m.ratingImage == 'rottentomatoes://image.rating.certified' assert movie.sessionKey is None
assert m.ratingKey == 2 assert movie.studio == 'Walt Disney Pictures'
assert [i.tag for i in m.roles] == ['Owen Wilson', 'Paul Newman', 'Bonnie Hunt', 'Larry the Cable Guy', 'Cheech Marin', 'Tony Shalhoub', 'Guido Quaroni', 'Jenifer Lewis', 'Paul Dooley', 'Michael Wallis', 'George Carlin', 'Katherine Helmond', 'John Ratzenberger', 'Michael Keaton', 'Joe Ranft', 'Richard Petty', 'Jeremy Piven', 'Bob Costas', 'Darrell Waltrip', 'Richard Kind', 'Edie McClurg', 'Humpy Wheeler', 'Tom Magliozzi', 'Ray Magliozzi', 'Lynda Petty', 'Andrew Stanton', 'Dale Earnhardt Jr.', 'Michael Schumacher', 'Jay Leno', 'Sarah Clark', 'Mike Nelson', 'Joe Ranft', 'Jonas Rivera', 'Lou Romano', 'Adrian Ochoa', 'E.J. Holowicki', 'Elissa Knight', 'Lindsey Collins', 'Larry Benton', 'Douglas Keever', 'Tom Hanks', 'Tim Allen', 'John Ratzenberger', 'Billy Crystal', 'John Goodman', 'John Ratzenberger', 'Dave Foley', 'John Ratzenberger', 'Vanness Wu'] assert utils.is_string(movie.summary, gte=100)
assert m._server._baseurl == 'http://138.68.157.5:32400' assert movie.tagline == "Ahhh... it's got that new movie smell."
assert m.sessionKey is None assert utils.is_thumb(movie.thumb)
assert m.studio == 'Walt Disney Pictures' assert movie.title == 'Cars'
assert m.summary == u"Lightning McQueen, a hotshot rookie race car driven to succeed, discovers that life is about the journey, not the finish line, when he finds himself unexpectedly detoured in the sleepy Route 66 town of Radiator Springs. On route across the country to the big Piston Cup Championship in California to compete against two seasoned pros, McQueen gets to know the town's offbeat characters." assert movie.titleSort == 'Cars'
assert m.tagline == "Ahhh... it's got that new movie smell." assert movie.transcodeSession is None
assert '/library/metadata/2/thumb/' in m.thumb assert movie.type == 'movie'
assert m.title == 'Cars' assert movie.updatedAt > datetime(2017, 1, 1)
assert m.titleSort == 'Cars' assert movie.userRating is None
assert m.transcodeSession is None assert movie.username is None
assert m.type == 'movie' assert movie.viewCount == 0
assert m.updatedAt > datetime(2017, 1, 1) assert movie.viewOffset == 0
assert m.userRating is None assert movie.viewedAt is None
assert m.username is None assert sorted([i.tag for i in movie.writers]) == ['Dan Fogelman', 'Joe Ranft', 'John Lasseter', 'Jorgen Klubien', 'Kiel Murray', 'Phil Lorin'] # noqa
# Assign 0 m.videoStreams assert movie.year == 2006
vid0 = m.media[0].parts[0].videoStreams[0] # Audio
assert m.viewCount == 0 audio = movie.media[0].parts[0].audioStreams[0]
assert m.viewOffset == 88870 assert audio.audioChannelLayout in utils.AUDIOLAYOUTS
assert m.viewedAt is None assert audio.bitDepth is None
assert [i.tag for i in m.writers] == ['Dan Fogelman', 'Joe Ranft', 'John Lasseter', 'Kiel Murray', 'Phil Lorin', 'Jorgen Klubien'] assert utils.is_int(audio.bitrate)
assert m.year == 2006 assert audio.bitrateMode is None
assert aud0.audioChannelLayout == '5.1' assert audio.channels in utils.AUDIOCHANNELS
assert aud0.bitDepth is None assert audio.codec in utils.CODECS
assert aud0.bitrate == 388 assert audio.codecID is None
assert aud0.bitrateMode is None assert audio.dialogNorm is None
assert aud0.channels == 6 assert audio.duration is None
assert aud0.codec == 'aac' assert audio.id >= 1
assert aud0.codecID is None assert audio.index == 1
assert aud0.dialogNorm is None assert utils.is_metadata(audio._initpath)
assert aud0.duration is None assert audio.language is None
assert aud0.id == 10 assert audio.languageCode is None
assert aud0.index == 1 assert audio.samplingRate == 48000
assert aud0._initpath == '/library/metadata/2' assert audio.selected is True
assert aud0.language is None assert audio._server._baseurl == utils.SERVER_BASEURL
assert aud0.languageCode is None assert audio.streamType == 2
#assert aud0.part == <MediaPart:2> assert audio.title is None
assert aud0.samplingRate == 48000 assert audio.type == 2
assert aud0.selected is True # Media
assert aud0._server._baseurl == 'http://138.68.157.5:32400' media = movie.media[0]
assert aud0.streamType == 2 assert media.aspectRatio == 1.78
assert aud0.title is None assert media.audioChannels in utils.AUDIOCHANNELS
assert aud0.type == 2 assert media.audioCodec in utils.CODECS
assert med0.aspectRatio == 1.78 assert utils.is_int(media.bitrate)
assert med0.audioChannels == 6 assert media.container in utils.CONTAINERS
assert med0.audioCodec == 'aac' assert utils.is_int(media.duration, gte=3600000)
assert med0.bitrate == 1474 assert utils.is_int(media.height)
assert med0.container == 'mp4' assert utils.is_int(media.id)
assert med0.duration == 170859 assert utils.is_metadata(media._initpath)
assert med0.height == 720 assert media.optimizedForStreaming in [None, False]
assert med0.id == 2 assert media._server._baseurl == utils.SERVER_BASEURL
assert med0._initpath == '/library/metadata/2' assert media.videoCodec in utils.CODECS
assert med0.optimizedForStreaming is False assert media.videoFrameRate in utils.FRAMERATES
# Assign 0 med0.parts assert media.videoResolution in utils.RESOLUTIONS
par0 = med0.parts[0] assert utils.is_int(media.width, gte=200)
assert med0._server._baseurl == 'http://138.68.157.5:32400' # Video
assert med0.videoCodec == 'h264' video = movie.media[0].parts[0].videoStreams[0]
assert med0.videoFrameRate == 'PAL' assert video.bitDepth == 8
assert med0.videoResolution == '720' assert utils.is_int(video.bitrate)
assert med0.width == 1280 assert video.cabac is None
assert vid0.bitDepth == 8 assert video.chromaSubsampling == '4:2:0'
assert vid0.bitrate == 1086 assert video.codec in utils.CODECS
assert vid0.cabac is None assert video.codecID is None
assert vid0.chromaSubsampling == '4:2:0' assert video.colorSpace is None
assert vid0.codec == 'h264' assert video.duration is None
assert vid0.codecID is None assert utils.is_float(video.frameRate, gte=20.0)
assert vid0.colorSpace is None assert video.frameRateMode is None
assert vid0.duration is None assert video.hasScallingMatrix is None
assert vid0.frameRate == 25.0 assert utils.is_int(video.height, gte=300)
assert vid0.frameRateMode is None assert utils.is_int(video.id)
assert vid0.hasScallingMatrix is None assert utils.is_int(video.index, gte=0)
assert vid0.height == 720 assert utils.is_metadata(video._initpath)
assert vid0.id == 9 assert video.language is None
assert vid0.index == 0 assert video.languageCode is None
assert vid0._initpath == '/library/metadata/2' assert utils.is_int(video.level)
assert vid0.language is None assert video.profile in utils.PROFILES
assert vid0.languageCode is None assert utils.is_int(video.refFrames)
assert vid0.level == 31 assert video.scanType is None
#assert vid0.part == <MediaPart:2> assert video.selected is False
assert vid0.profile == 'main' assert video._server._baseurl == utils.SERVER_BASEURL
assert vid0.refFrames == 1 assert utils.is_int(video.streamType)
assert vid0.scanType is None assert video.title is None
assert vid0.selected is False assert video.type == 1
assert vid0._server._baseurl == 'http://138.68.157.5:32400' assert utils.is_int(video.width, gte=400)
assert vid0.streamType == 1 # Part
assert vid0.title is None part = media.parts[0]
assert vid0.type == 1 assert part.container in utils.CONTAINERS
assert vid0.width == 1280 assert utils.is_int(part.duration, 1600000)
assert par0.container == 'mp4' assert len(part.file) >= 10
assert par0.duration == 170859 assert utils.is_int(part.id)
assert par0.file == '/media/movies/cars/cars.mp4' assert utils.is_metadata(part._initpath)
assert par0.id == 2 assert len(part.key) >= 10
assert par0._initpath == '/library/metadata/2' assert part._server._baseurl == utils.SERVER_BASEURL
assert par0.key == '/library/parts/2/1484679008/file.mp4' assert utils.is_int(part.size, gte=1000000)
#assert par0.media == <Media:Cars> # Stream 1
assert par0._server._baseurl == 'http://138.68.157.5:32400' stream1 = part.streams[0]
assert par0.size == 31491130 assert stream1.bitDepth == 8
# Assign 0 par0.streams assert utils.is_int(stream1.bitrate)
str0 = par0.streams[0] assert stream1.cabac is None
# Assign 1 par0.streams assert stream1.chromaSubsampling == '4:2:0'
str1 = par0.streams[1] assert stream1.codec in utils.CODECS
assert str0.bitDepth == 8 assert stream1.codecID is None
assert str0.bitrate == 1086 assert stream1.colorSpace is None
assert str0.cabac is None assert stream1.duration is None
assert str0.chromaSubsampling == '4:2:0' assert utils.is_float(stream1.frameRate, gte=20.0)
assert str0.codec == 'h264' assert stream1.frameRateMode is None
assert str0.codecID is None assert stream1.hasScallingMatrix is None
assert str0.colorSpace is None assert utils.is_int(stream1.height, gte=300)
assert str0.duration is None assert utils.is_int(stream1.id)
assert str0.frameRate == 25.0 assert utils.is_int(stream1.index, gte=0)
assert str0.frameRateMode is None assert utils.is_metadata(stream1._initpath)
assert str0.hasScallingMatrix is None assert stream1.language is None
assert str0.height == 720 assert stream1.languageCode is None
assert str0.id == 9 assert utils.is_int(stream1.level)
assert str0.index == 0 assert stream1.profile in utils.PROFILES
assert str0._initpath == '/library/metadata/2' assert stream1.refFrames == 1
assert str0.language is None assert stream1.scanType is None
assert str0.languageCode is None assert stream1.selected is False
assert str0.level == 31 assert stream1._server._baseurl == utils.SERVER_BASEURL
#assert str0.part == <MediaPart:2> assert utils.is_int(stream1.streamType)
assert str0.profile == 'main' assert stream1.title is None
assert str0.refFrames == 1 assert stream1.type == 1
assert str0.scanType is None assert utils.is_int(stream1.width, gte=400)
assert str0.selected is False # Stream 2
assert str0._server._baseurl == 'http://138.68.157.5:32400' stream2 = part.streams[1]
assert str0.streamType == 1 assert stream2.audioChannelLayout in utils.AUDIOLAYOUTS
assert str0.title is None assert stream2.bitDepth is None
assert str0.type == 1 assert utils.is_int(stream2.bitrate)
assert str0.width == 1280 assert stream2.bitrateMode is None
assert str1.audioChannelLayout == '5.1' assert stream2.channels in utils.AUDIOCHANNELS
assert str1.bitDepth is None assert stream2.codec in utils.CODECS
assert str1.bitrate == 388 assert stream2.codecID is None
assert str1.bitrateMode is None assert stream2.dialogNorm is None
assert str1.channels == 6 assert stream2.duration is None
assert str1.codec == 'aac' assert utils.is_int(stream2.id)
assert str1.codecID is None assert utils.is_int(stream2.index)
assert str1.dialogNorm is None assert utils.is_metadata(stream2._initpath)
assert str1.duration is None assert stream2.language is None
assert str1.id == 10 assert stream2.languageCode is None
assert str1.index == 1 assert utils.is_int(stream2.samplingRate)
assert str1._initpath == '/library/metadata/2' assert stream2.selected is True
assert str1.language is None assert stream2._server._baseurl == utils.SERVER_BASEURL
assert str1.languageCode is None assert stream2.streamType == 2
#assert str1.part == <MediaPart:2> assert stream2.title is None
assert str1.samplingRate == 48000 assert stream2.type == 2
assert str1.selected is True
assert str1._server._baseurl == 'http://138.68.157.5:32400'
assert str1.streamType == 2
assert str1.title is None
assert str1.type == 2
def test_video_Show(a_show): def test_video_Show(show):
assert a_show.title == 'The 100' assert show.title == 'The 100'
def test_video_Show_attrs(a_show): def test_video_Show_attrs(show):
m = a_show assert show.addedAt > datetime(2017, 1, 1)
assert m.addedAt > datetime(2017, 1, 1) assert utils.is_metadata(show.art, contains='/art/')
assert '/library/metadata/12/art/' in m.art assert utils.is_metadata(show.banner, contains='/banner/')
assert '/library/metadata/12/banner/' in m.banner assert utils.is_int(show.childCount)
assert m.childCount == 2 assert show.contentRating in utils.CONTENTRATINGS
assert m.contentRating == 'TV-14' assert utils.is_int(show.duration, gte=1600000)
assert m.duration == 2700000 assert utils.is_section(show._initpath)
assert m._initpath == '/library/sections/2/all'
# Check reloading the show loads the full list of genres # Check reloading the show loads the full list of genres
assert [i.tag for i in m.genres] == ['Drama', 'Science-Fiction', 'Suspense'] assert sorted([i.tag for i in show.genres]) == ['Drama', 'Science-Fiction', 'Suspense']
m.reload() show.reload()
assert [i.tag for i in m.genres] == ['Drama', 'Science-Fiction', 'Suspense', 'Thriller'] assert sorted([i.tag for i in show.genres]) == ['Drama', 'Science-Fiction', 'Suspense', 'Thriller']
# So the initkey should have changed because of the reload # So the initkey should have changed because of the reload
assert m._initpath == '/library/metadata/12' assert utils.is_metadata(show._initpath)
assert m.index == '1' assert utils.is_int(show.index)
assert m.key == '/library/metadata/12' assert utils.is_metadata(show.key)
assert m.lastViewedAt > datetime(2017, 1, 1) assert utils.is_datetime(show.lastViewedAt)
assert m.leafCount == 9 assert utils.is_int(show.leafCount)
assert m.listType == 'video' assert show.listType == 'video'
assert m.locations == ['/media/tvshows/the 100'] assert len(show.locations[0]) >= 10
assert str(m.originallyAvailableAt.date()) == '2014-03-19' assert show.originallyAvailableAt.strftime('%Y-%m-%d') == '2014-03-19'
assert m.rating == 8.1 assert show.rating >= 8.0
assert m.ratingKey == 12 assert utils.is_int(show.ratingKey)
assert [i.tag for i in m.roles][:3] == ['Richard Harmon', 'Alycia Debnam-Carey', 'Lindsey Morgan'] assert sorted([i.tag for i in show.roles][:3]) == ['Alycia Debnam-Carey', 'Lindsey Morgan', 'Richard Harmon']
assert [i.tag for i in m.actors][:3] == ['Richard Harmon', 'Alycia Debnam-Carey', 'Lindsey Morgan'] assert sorted([i.tag for i in show.actors][:3]) == ['Alycia Debnam-Carey', 'Lindsey Morgan', 'Richard Harmon']
assert m._server._baseurl == 'http://138.68.157.5:32400' assert show._server._baseurl == utils.SERVER_BASEURL
assert m.studio == 'The CW' assert show.studio == 'The CW'
assert m.summary == u"When nuclear Armageddon destroys civilization on Earth, the only survivors are those on the 12 international space stations in orbit at the time. Three generations later, the 4,000 survivors living on a space ark of linked stations see their resources dwindle and face draconian measures established to ensure humanity's future. Desperately looking for a solution, the ark's leaders send 100 juvenile prisoners back to the planet to test its habitability. Having always lived in space, the exiles find the planet fascinating and terrifying, but with the fate of the human race in their hands, they must forge a path into the unknown." assert utils.is_string(show.summary, gte=100)
assert '/library/metadata/12/theme/' in m.theme assert utils.is_metadata(show.theme, contains='/theme/')
assert '/library/metadata/12/thumb/' in m.thumb assert utils.is_metadata(show.thumb, contains='/thumb/')
assert m.title == 'The 100' assert show.title == 'The 100'
assert m.titleSort == '100' assert show.titleSort == '100'
assert m.type == 'show' assert show.type == 'show'
assert m.updatedAt > datetime(2017, 1, 1) assert utils.is_datetime(show.updatedAt)
assert m.viewCount == 1 assert utils.is_int(show.viewCount, gte=0)
assert m.viewedLeafCount == 1 assert utils.is_int(show.viewedLeafCount, gte=0)
assert m.year == 2014 assert show.year == 2014
def test_video_Show_watched(a_show): def test_video_Show_watched(show):
watched = a_show.watched() show.episodes()[0].markWatched()
watched = show.watched()
assert len(watched) == 1 and watched[0].title == 'Pilot' assert len(watched) == 1 and watched[0].title == 'Pilot'
def test_video_Show_unwatched(a_show): def test_video_Show_unwatched(show):
assert len(a_show.unwatched()) == 8 episodes = show.episodes()
episodes[0].markWatched()
unwatched = show.unwatched()
assert len(unwatched) == len(episodes) - 1
def test_video_Show_location(pms): def test_video_Show_location(plex):
# This should be a part of test test_video_Show_attrs # This should be a part of test test_video_Show_attrs but is excluded
# But is excluded because of https://github.com/mjs7231/python-plexapi/issues/97 # because of https://github.com/mjs7231/python-plexapi/issues/97
s = pms.library.section('TV Shows').get('The 100') show = plex.library.section('TV Shows').get('The 100')
# This will require a reload since the xml from http://138.68.157.5:32400/library/sections/2/all assert len(show.locations) >= 1
# Does not contain a location
assert s.locations == ['/media/tvshows/the 100']
def test_video_Show_reload(pms):
s = pms.library.section('TV Shows').get('Game of Thrones')
assert s._initpath == '/library/sections/2/all'
s.reload()
assert s._initpath == '/library/metadata/6'
assert len(s.roles) > 3
def test_video_Show_episodes(a_show): def test_video_Show_reload(plex):
inc_watched = a_show.episodes() show = plex.library.section('TV Shows').get('Game of Thrones')
ex_watched = a_show.episodes(viewCount=0) assert utils.is_metadata(show._initpath, prefix='/library/sections/')
assert len(inc_watched) == 9 assert len(show.roles) == 3
assert len(ex_watched) == 8 show.reload()
assert utils.is_metadata(show._initpath, prefix='/library/metadata/')
assert len(show.roles) > 3
def test_video_Show_download(monkeydownload, tmpdir, a_show): def test_video_Show_episodes(show):
f = a_show.download(savepath=str(tmpdir)) episodes = show.episodes()
assert len(f) == 9 episodes[0].markWatched()
unwatched = show.episodes(viewCount=0)
assert len(unwatched) == len(episodes) - 1
def test_video_Season_download(monkeydownload, tmpdir, a_show): def test_video_Show_download(monkeydownload, tmpdir, show):
sn = a_show.season('Season 1') episodes = show.episodes()
f = sn.download(savepath=str(tmpdir)) filepaths = show.download(savepath=str(tmpdir))
assert len(f) == 8 assert len(filepaths) == len(episodes)
def test_video_Episode_download(monkeydownload, tmpdir, a_episode): def test_video_Season_download(monkeydownload, tmpdir, show):
f = a_episode.download(savepath=str(tmpdir)) season = show.season('Season 1')
filepaths = season.download(savepath=str(tmpdir))
assert len(filepaths) == 8
def test_video_Episode_download(monkeydownload, tmpdir, episode):
f = episode.download(savepath=str(tmpdir))
assert len(f) == 1 assert len(f) == 1
with_sceen_size = a_episode.download(savepath=str(tmpdir), **{'videoResolution': '500x300'}) with_sceen_size = episode.download(savepath=str(tmpdir), **{'videoResolution': '500x300'})
assert len(with_sceen_size) == 1 assert len(with_sceen_size) == 1
def test_video_Show_thumbUrl(a_show): def test_video_Show_thumbUrl(show):
assert 'http://138.68.157.5:32400/library/metadata/12/thumb/' in a_show.thumbUrl assert utils.SERVER_BASEURL in show.thumbUrl
assert '/library/metadata/' in show.thumbUrl
assert '/thumb/' in show.thumbUrl
@pytest.mark.xfail def test_video_Show_analyze(show):
def test_video_Show_analyze(a_show): show = show.analyze()
show = a_show.analyze() # this isnt possble.. should it even be available?
def test_video_Show_markWatched(a_tv_section): def test_video_Show_markWatched(tvshows):
show = a_tv_section.get("Marvel's Daredevil") show = tvshows.get("Marvel's Daredevil")
show.markWatched() show.markWatched()
assert a_tv_section.get("Marvel's Daredevil").isWatched assert tvshows.get("Marvel's Daredevil").isWatched
def test_video_Show_markUnwatched(a_tv_section): def test_video_Show_markUnwatched(tvshows):
show = a_tv_section.get("Marvel's Daredevil") show = tvshows.get("Marvel's Daredevil")
show.markUnwatched() show.markUnwatched()
assert not a_tv_section.get("Marvel's Daredevil").isWatched assert not tvshows.get("Marvel's Daredevil").isWatched
def test_video_Show_refresh(a_tv_section): def test_video_Show_refresh(tvshows):
show = a_tv_section.get("Marvel's Daredevil") show = tvshows.get("Marvel's Daredevil")
show.refresh() show.refresh()
def test_video_Show_get(a_show): def test_video_Show_get(show):
assert a_show.get('Pilot').title == 'Pilot' assert show.get('Pilot').title == 'Pilot'
def test_video_Show_isWatched(a_show): def test_video_Show_isWatched(show):
assert not a_show.isWatched assert not show.isWatched
def test_video_Show_section(a_show): def test_video_Show_section(show):
section = a_show.section() section = show.section()
assert section.title == 'TV Shows' assert section.title == 'TV Shows'
def test_video_Episode(a_show): def test_video_Episode(show):
pilot = a_show.episode('Pilot') episode = show.episode('Pilot')
assert pilot == a_show.episode(season=1, episode=1) assert episode == show.episode(season=1, episode=1)
with pytest.raises(BadRequest): with pytest.raises(BadRequest):
a_show.episode() show.episode()
with pytest.raises(NotFound): with pytest.raises(NotFound):
a_show.episode(season=1337, episode=1337) show.episode(season=1337, episode=1337)
def test_video_Episode_analyze(a_tv_section): def test_video_Episode_analyze(tvshows):
ep = a_tv_section.get("Marvel's Daredevil").episode(season=1, episode=1) episode = tvshows.get("Marvel's Daredevil").episode(season=1, episode=1)
ep.analyze() episode.analyze()
def test_video_Episode_attrs(a_episode): def test_video_Episode_attrs(episode):
ep = a_episode assert utils.is_datetime(episode.addedAt)
assert ep.addedAt > datetime(2017, 1, 1) assert episode.contentRating in utils.CONTENTRATINGS
assert ep.contentRating == 'TV-14' assert [i.tag for i in episode.directors] == ['Bharat Nalluri']
assert [i.tag for i in ep.directors] == ['Bharat Nalluri'] assert utils.is_int(episode.duration, gte=120000)
assert ep.duration == 170859 assert episode.grandparentTitle == 'The 100'
assert ep.grandparentTitle == 'The 100' assert episode.index == 1
assert ep.index == 1 assert utils.is_metadata(episode._initpath)
assert ep._initpath == '/library/metadata/12/allLeaves' assert utils.is_metadata(episode.key)
assert ep.key == '/library/metadata/14' assert episode.listType == 'video'
assert ep.listType == 'video' assert episode.originallyAvailableAt.strftime('%Y-%m-%d') == '2014-03-19'
# Assign 0 ep.media assert utils.is_int(episode.parentIndex)
med0 = ep.media[0] assert utils.is_metadata(episode.parentKey)
assert str(ep.originallyAvailableAt.date()) == '2014-03-19' assert utils.is_int(episode.parentRatingKey)
assert ep.parentIndex == '1' assert utils.is_metadata(episode.parentThumb, contains='/thumb/')
assert ep.parentKey == '/library/metadata/13' assert episode.player is None
assert ep.parentRatingKey == 13 assert episode.rating == 7.4
assert '/library/metadata/13/thumb/' in ep.parentThumb assert utils.is_int(episode.ratingKey)
#assert ep.parentThumb == '/library/metadata/13/thumb/1485096623' assert episode._server._baseurl == utils.SERVER_BASEURL
assert ep.player is None assert utils.is_string(episode.summary, gte=100)
assert ep.rating == 7.4 assert utils.is_metadata(episode.thumb, contains='/thumb/')
assert ep.ratingKey == 14 assert episode.title == 'Pilot'
assert ep._server._baseurl == 'http://138.68.157.5:32400' assert episode.titleSort == 'Pilot'
assert ep.summary == u'Ninety-seven years ago, nuclear Armageddon decimated planet Earth, destroying civilization. The only survivors were the 400 inhabitants of 12 international space stations that were in orbit at the time. Three generations have been born in space, the survivors now number 4,000, and resources are running out on their dying "Ark." Among the 100 young exiles are Clarke, the bright teenage daughter of the Arks chief medical officer; the daredevil Finn; the brother/sister duo of Bellamy and Octavia, whose illegal sibling status has always led them to flaunt the rules, the lighthearted Jasper and the resourceful Monty. Technologically blind to whats happening on the planet below them, the Arks leaders — Clarkes widowed mother, Abby; Chancellor Jaha; and his shadowy second in command, Kane — are faced with difficult decisions about life, death and the continued existence of the human race.' assert episode.transcodeSession is None
assert ep.thumb == '/library/metadata/14/thumb/1485115318' assert episode.type == 'episode'
assert ep.title == 'Pilot' assert utils.is_datetime(episode.updatedAt)
assert ep.titleSort == 'Pilot' assert episode.username is None
assert ep.transcodeSession is None assert utils.is_int(episode.viewCount)
assert ep.type == 'episode' assert episode.viewOffset == 0
assert ep.updatedAt > datetime(2017, 1, 1) assert [i.tag for i in episode.writers] == ['Jason Rothenberg']
assert ep.username is None assert episode.year == 2014
assert ep.viewCount == 1 assert episode.isWatched is True
assert ep.viewOffset == 0 # Media
assert [i.tag for i in ep.writers] == ['Jason Rothenberg'] media = episode.media[0]
assert ep.year == 2014 assert media.aspectRatio == 1.78
assert med0.aspectRatio == 1.78 assert media.audioChannels in utils.AUDIOCHANNELS
assert med0.audioChannels == 6 assert media.audioCodec in utils.CODECS
assert med0.audioCodec == 'aac' assert utils.is_int(media.bitrate)
assert med0.bitrate == 1474 assert media.container in utils.CONTAINERS
assert med0.container == 'mp4' assert utils.is_int(media.duration, gte=150000)
assert med0.duration == 170859 assert utils.is_int(media.height, gte=200)
assert med0.height == 720 assert utils.is_int(media.id)
assert med0.id == 12 assert utils.is_metadata(media._initpath)
assert med0._initpath == '/library/metadata/12/allLeaves' assert isinstance(media.optimizedForStreaming, bool)
assert med0.optimizedForStreaming is False assert media._server._baseurl == utils.SERVER_BASEURL
# Assign 0 med0.parts assert media.videoCodec in utils.CODECS
par0 = med0.parts[0] assert media.videoFrameRate in utils.FRAMERATES
assert med0._server._baseurl == 'http://138.68.157.5:32400' assert media.videoResolution in utils.RESOLUTIONS
#assert med0.video == <Episode:14:The 100:S1:E1:Pilot> assert utils.is_int(media.width, gte=400)
assert med0.videoCodec == 'h264' # Part
assert med0.videoFrameRate == 'PAL' part = media.parts[0]
assert med0.videoResolution == '720' assert part.container in utils.CONTAINERS
assert med0.width == 1280 assert utils.is_int(part.duration, gte=150000)
assert par0.container == 'mp4' assert len(part.file) >= 10
assert par0.duration == 170859 assert utils.is_int(part.id)
assert par0.file == '/media/tvshows/the 100/season 1/the.100.s01e01.mp4' assert utils.is_metadata(part._initpath)
assert par0.id == 12 assert len(part.key) >= 10
assert par0._initpath == '/library/metadata/12/allLeaves' assert part._server._baseurl == utils.SERVER_BASEURL
assert par0.key == '/library/parts/12/1484679008/file.mp4' assert utils.is_int(part.size, gte=30000000)
#assert par0.media == <Media:Pilot>
assert par0._server._baseurl == 'http://138.68.157.5:32400'
assert par0.size == 31491130
assert ep.isWatched is True
def test_video_Season(a_show): def test_video_Season(show):
seasons = a_show.seasons() seasons = show.seasons()
assert len(seasons) == 2 assert len(seasons) == 2
assert ['Season 1', 'Season 2'] == [s.title for s in seasons] assert ['Season 1', 'Season 2'] == [s.title for s in seasons]
assert a_show.season('Season 1') == seasons[0] assert show.season('Season 1') == seasons[0]
def test_video_Season_attrs(a_show): def test_video_Season_attrs(show):
m = a_show.season('Season 1') season = show.season('Season 1')
assert m.addedAt > datetime(2017, 1, 1) assert utils.is_datetime(season.addedAt)
assert m.index == 1 assert season.index == 1
assert m._initpath == '/library/metadata/12/children' assert utils.is_metadata(season._initpath)
assert m.key == '/library/metadata/13' assert utils.is_metadata(season.key)
assert m.lastViewedAt > datetime(2017, 1, 1) assert utils.is_datetime(season.lastViewedAt)
assert m.leafCount == 8 assert utils.is_int(season.leafCount, gte=3)
assert m.listType == 'video' assert season.listType == 'video'
assert m.parentKey == '/library/metadata/12' assert utils.is_metadata(season.parentKey)
assert m.parentRatingKey == 12 assert utils.is_int(season.parentRatingKey)
assert m.parentTitle == 'The 100' assert season.parentTitle == 'The 100'
assert m.ratingKey == 13 assert utils.is_int(season.ratingKey)
assert m._server._baseurl == 'http://138.68.157.5:32400' assert season._server._baseurl == utils.SERVER_BASEURL
assert m.summary == '' assert season.summary == ''
assert '/library/metadata/13/thumb/' in m.thumb assert utils.is_metadata(season.thumb, contains='/thumb/')
#assert m.thumb == '/library/metadata/13/thumb/1485096623' assert season.title == 'Season 1'
assert m.title == 'Season 1' assert season.titleSort == 'Season 1'
assert m.titleSort == 'Season 1' assert season.type == 'season'
assert m.type == 'season' assert utils.is_datetime(season.updatedAt)
assert m.updatedAt > datetime(2017, 1, 1) assert utils.is_int(season.viewCount)
assert m.viewCount == 1 assert utils.is_int(season.viewedLeafCount)
assert m.viewedLeafCount == 1 assert utils.is_int(season.seasonNumber)
assert m.seasonNumber == 1
def test_video_Season_show(a_show): def test_video_Season_show(show):
sn = a_show.seasons()[0] season = show.seasons()[0]
season_by_name = a_show.season('Season 1') season_by_name = show.season('Season 1')
assert a_show.ratingKey == sn.parentRatingKey and season_by_name.parentRatingKey assert show.ratingKey == season.parentRatingKey and season_by_name.parentRatingKey
assert sn.ratingKey == season_by_name.ratingKey assert season.ratingKey == season_by_name.ratingKey
def test_video_Season_watched(a_tv_section): def test_video_Season_watched(tvshows):
show = a_tv_section.get("Marvel's Daredevil") show = tvshows.get("Marvel's Daredevil")
sn = show.season(1) season = show.season(1)
sne = show.season('Season 1') sne = show.season('Season 1')
assert sn == sne assert season == sne
sn.markWatched() season.markWatched()
assert sn.isWatched assert season.isWatched
def test_video_Season_unwatched(a_tv_section): def test_video_Season_unwatched(tvshows):
sn = a_tv_section.get("Marvel's Daredevil").season(1) season = tvshows.get("Marvel's Daredevil").season(1)
sn.markUnwatched() season.markUnwatched()
assert not sn.isWatched assert not season.isWatched
def test_video_Season_get(a_show): def test_video_Season_get(show):
ep = a_show.season(1).get('Pilot') episode = show.season(1).get('Pilot')
assert ep.title == 'Pilot' assert episode.title == 'Pilot'
def test_video_Season_episode(a_show): def test_video_Season_episode(show):
ep = a_show.season(1).get('Pilot') episode = show.season(1).get('Pilot')
assert ep.title == 'Pilot' assert episode.title == 'Pilot'
def test_video_Season_episodes(a_show): def test_video_Season_episodes(show):
sn_eps = a_show.season(2).episodes() episodes = show.season(2).episodes()
assert len(sn_eps) == 1 assert len(episodes) >= 1
def test_that_reload_return_the_same_object(pms): def test_that_reload_return_the_same_object(plex):
# we want to check this that all the urls are correct # we want to check this that all the urls are correct
movie_library_search = pms.library.section('Movies').search('16 Blocks')[0] movie_library_search = plex.library.section('Movies').search('16 Blocks')[0]
movie_search = pms.search('16 Blocks')[0] movie_search = plex.search('16 Blocks')[0]
movie_section_get = pms.library.section('Movies').get('16 Blocks') movie_section_get = plex.library.section('Movies').get('16 Blocks')
movie_library_search_key = movie_library_search.key movie_library_search_key = movie_library_search.key
movie_search_key = movie_search.key movie_search_key = movie_search.key
movie_section_get_key = movie_section_get.key movie_section_get_key = movie_section_get.key
assert movie_library_search_key == movie_library_search.reload().key == movie_search_key == movie_search.reload().key == movie_section_get_key == movie_section_get.reload().key assert movie_library_search_key == movie_library_search.reload().key == movie_search_key == movie_search.reload().key == movie_section_get_key == movie_section_get.reload().key
tvshow_library_search = pms.library.section('TV Shows').search('The 100')[0] tvshow_library_search = plex.library.section('TV Shows').search('The 100')[0]
tvshow_search = pms.search('The 100')[0] tvshow_search = plex.search('The 100')[0]
tvshow_section_get = pms.library.section('TV Shows').get('The 100') tvshow_section_get = plex.library.section('TV Shows').get('The 100')
tvshow_library_search_key = tvshow_library_search.key tvshow_library_search_key = tvshow_library_search.key
tvshow_search_key = tvshow_search.key tvshow_search_key = tvshow_search.key
tvshow_section_get_key = tvshow_section_get.key tvshow_section_get_key = tvshow_section_get.key