Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
5a04ce4
lets begin
andrey-yantsen Sep 8, 2018
0c5574f
skip plexpass tests if there is not plexpass on account
andrey-yantsen Sep 9, 2018
470aca4
test new myplex attrubutes
andrey-yantsen Sep 9, 2018
2924495
bootstrap: proper photos organisation
andrey-yantsen Sep 9, 2018
7d8b61a
fix rest of photos tests
andrey-yantsen Sep 9, 2018
90f7867
fix myplex new attributes test
andrey-yantsen Sep 9, 2018
ab2e856
fix music bootstrap by setting agent to lastfm
andrey-yantsen Sep 9, 2018
cdac7b6
fix sync tests
andrey-yantsen Sep 9, 2018
a923db6
increase bootstrap timeout
andrey-yantsen Sep 9, 2018
31a9f53
remove timeout from .travis.yml
andrey-yantsen Sep 9, 2018
8acc125
do not create playlist-style photoalbums in plex-bootstraptest.py
andrey-yantsen Sep 9, 2018
92d5b96
allow negative filtering in LibrarySection.search()
andrey-yantsen Sep 9, 2018
c1abf50
fix sync tests once again
andrey-yantsen Sep 9, 2018
faeaaba
use sendCrashReports in test_settings
andrey-yantsen Sep 9, 2018
6410fe0
fix test_settings
andrey-yantsen Sep 9, 2018
c582a80
fix test_video
andrey-yantsen Sep 9, 2018
28e0883
do not accept eula in bootstrap
andrey-yantsen Sep 9, 2018
fee3c81
fix PlexServer.isLatest()
andrey-yantsen Sep 9, 2018
5043d07
add test against old version of PlexServer
andrey-yantsen Sep 9, 2018
b3a6658
fix MyPlexAccount.OutOut
andrey-yantsen Sep 9, 2018
aa7c052
add flag for one-time testing in Travis
andrey-yantsen Sep 9, 2018
fe3972d
fix test_library onDeck tests
andrey-yantsen Sep 9, 2018
4bdf372
fix more tests
andrey-yantsen Sep 9, 2018
440b8ba
use tqdm in plex-bootstraptest for media scanning progress
andrey-yantsen Sep 9, 2018
ef9ec7b
create sections one-by-one
andrey-yantsen Sep 9, 2018
df874b0
update docs on AlertListener for timeline entries
andrey-yantsen Sep 9, 2018
7ccca8e
fix plex-bootstraptest for server version 1.3.2
andrey-yantsen Sep 9, 2018
04befe2
display skip/xpass/xfail reasons
andrey-yantsen Sep 9, 2018
34a7c5e
fix tests on 1.3
andrey-yantsen Sep 9, 2018
0902567
wait for music to be fully processed in plex-bootstraptest
andrey-yantsen Sep 9, 2018
1e294bf
fix misplaced TEST_ACCOUNT_ONCE
andrey-yantsen Sep 9, 2018
604325d
fix test_myplex_users, not sure if in proper-way
andrey-yantsen Sep 9, 2018
580e4c9
add pytest-rerunfailures; mark test_myplex_optout as flaky
andrey-yantsen Sep 9, 2018
18a3cb1
fix comment
andrey-yantsen Sep 9, 2018
18e31cd
Revert "add pytest-rerunfailures; mark test_myplex_optout as flaky"
andrey-yantsen Sep 10, 2018
987401b
restart plex container on failure
andrey-yantsen Sep 10, 2018
0087764
add conftest.wait_until() and used where some retries are required
andrey-yantsen Sep 10, 2018
e3d2707
add more wait_until() usage in test_sync
andrey-yantsen Sep 10, 2018
7d2f2b0
fix managed user search
andrey-yantsen Sep 10, 2018
90b5477
fix updating managed users in myplex
andrey-yantsen Sep 10, 2018
78aa09f
allow to add new servers to existent users
andrey-yantsen Sep 10, 2018
20c4eff
add new server to a shared user while bootstrapping
andrey-yantsen Sep 10, 2018
24ceba7
add some docs on testing process
andrey-yantsen Sep 10, 2018
fcce22b
perform few attemps when unable to get the claim token
andrey-yantsen Sep 10, 2018
0d536bd
unlock websocket-client in requirements_dev
andrey-yantsen Sep 10, 2018
99a3bb1
fix docblock in tools/plex-teardowntest
andrey-yantsen Sep 10, 2018
ae93093
do not hardcode mediapart size in test_video
andrey-yantsen Sep 10, 2018
1df20d2
remove cache:pip from travis
andrey-yantsen Sep 10, 2018
bde68d0
Revert "unlock websocket-client in requirements_dev"
andrey-yantsen Sep 10, 2018
ada447a
remove debug from server.py
andrey-yantsen Sep 10, 2018
af069e5
improve webhook tests
andrey-yantsen Sep 11, 2018
8b0430a
fix type() check to isinstance()
andrey-yantsen Sep 11, 2018
6a95845
remove excessive `else` branch due to Hellowlol advice
andrey-yantsen Sep 11, 2018
415e3a4
add `unknown` as allowed `myPlexMappingState` in test_server
andrey-yantsen Sep 11, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 67 additions & 22 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,27 +1,72 @@
language:
- python
language: python

stages:
- test
- name: deploy
if: tag IS present

sudo: required
services:
- docker

python:
- '2.7'
- '3.4'
- '3.6'
- 2.7
- 3.4
- 3.6

env:
global:
- PLEXAPI_AUTH_SERVER_BASEURL=http://127.0.0.1:32400
matrix:
- PLEX_CONTAINER_TAG=latest

before_install:
- pip install --upgrade pip
- pip install --upgrade setuptools
- pip install --upgrade pytest pytest-cov coveralls
- pip install --upgrade pip
- pip install --upgrade setuptools
- pip install --upgrade pytest pytest-cov coveralls
install:
- pip install -r requirements_dev.txt
- pip install -r requirements_dev.txt
- PYTHONPATH="$PWD:$PYTHONPATH" python -u tools/plex-bootstraptest.py --destination plex --advertise-ip=127.0.0.1
--bootstrap-timeout 540 --docker-tag $PLEX_CONTAINER_TAG

script:
- if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then py.test tests --tb=native --verbose
--cov-config .coveragerc --cov=plexapi; fi
- flake8 plexapi --exclude=compat.py --max-line-length=120 --ignore=E128,E701,E702,E731,W293
- py.test tests -rxXs --ignore=tests/test_sync.py --tb=native --verbose --cov-config .coveragerc --cov=plexapi
- PLEXAPI_HEADER_PROVIDES='controller,sync-target' PLEXAPI_HEADER_PLATFORM=iOS PLEXAPI_HEADER_PLATFORM_VERSION=11.4.1
PLEXAPI_HEADER_DEVICE=iPhone py.test tests/test_sync.py -rxXs --tb=native --verbose --cov-config .coveragerc
--cov=plexapi --cov-append

after_success:
- coveralls
matrix:
fast_finish: true
deploy:
provider: pypi
user: mjs7231
password:
secure: UhuEN9GAp9zMEXdVTxSrbhfYf4HjTcj47l093Qh1HYKmZACxJM/+JkQCm7+oHPJpo7YDLk2we9oEsQ41maZBr9WgZI1lwR6m590M12vPhPI7NCVzINxJqebc0uZhCFsAFFKA3kzpRQbDfsBUG4yL/AzeMcvJMgIg3m07KRVhBywnnRhQ77trbBI0Io5MBzfW9PYDeGJqlNDBM7SbB4tK0udGZQT9wmFwvIoJODPDnM15Ry4vpkVNww/vVgyHklmnYlPzQgvhSMOXk0+MWlYtaKmu6uuLAiRccT1Fsmi1POKuFEq8S0Z7w4LmwxCVRaCvsZdNW5eXWgPDhZXNcLrKMwjgJt9Vj3VcD+NCywux/C1hTq7tecBocA13kzbgg4fd2sATOjQT5iaRPGrDtKm8e00hxr125n0StDxXdYGl2W5sH0LCkZE6Vq1GjXYjKFXZeTk3Fzav/3N8IxHBX3CliJB/vbloJ2mpz1kXL4UTORl9pghPyGOOq2yJPYSSWly/RsAD7UDrL1/lezaPSJGKbZJ0CMyfA83kd82/hgZflOuBuTcPHCZSU3zMCs0fsImZZxr6Qm1tbff+iyNS/ufoYgeVfsWhlEl9FoLv1g4HG6oA+uDHz+jKz9uSRHcGqD6P4JJK+H+yy0PeYfo7b6eSqFxgt8q8QfifUaCrVoCiY+c=
on:
tags: true
- coveralls

after_script:
- PYTHONPATH="$PWD:$PYTHONPATH" python -u tools/plex-teardowntest.py

jobs:
include:
- python: 3.6
env:
- PLEX_CONTAINER_TAG=1.3.2.3112-1751929
- TEST_ACCOUNT_ONCE=1
- python: 3.6
name: "Flake8"
install:
- pip install -r requirements_dev.txt
script: flake8 plexapi --exclude=compat.py --max-line-length=120 --ignore=E128,E701,E702,E731,W293
after_success: true
after_script: true
env:
- PLEX_CONTAINER_TAG=latest
- stage: deploy
name: "Deploy to PyPi"
python: 3.6
install: true
script: true
env:
- PLEX_CONTAINER_TAG=latest
deploy:
provider: pypi
user: mjs7231
password:
secure: UhuEN9GAp9zMEXdVTxSrbhfYf4HjTcj47l093Qh1HYKmZACxJM/+JkQCm7+oHPJpo7YDLk2we9oEsQ41maZBr9WgZI1lwR6m590M12vPhPI7NCVzINxJqebc0uZhCFsAFFKA3kzpRQbDfsBUG4yL/AzeMcvJMgIg3m07KRVhBywnnRhQ77trbBI0Io5MBzfW9PYDeGJqlNDBM7SbB4tK0udGZQT9wmFwvIoJODPDnM15Ry4vpkVNww/vVgyHklmnYlPzQgvhSMOXk0+MWlYtaKmu6uuLAiRccT1Fsmi1POKuFEq8S0Z7w4LmwxCVRaCvsZdNW5eXWgPDhZXNcLrKMwjgJt9Vj3VcD+NCywux/C1hTq7tecBocA13kzbgg4fd2sATOjQT5iaRPGrDtKm8e00hxr125n0StDxXdYGl2W5sH0LCkZE6Vq1GjXYjKFXZeTk3Fzav/3N8IxHBX3CliJB/vbloJ2mpz1kXL4UTORl9pghPyGOOq2yJPYSSWly/RsAD7UDrL1/lezaPSJGKbZJ0CMyfA83kd82/hgZflOuBuTcPHCZSU3zMCs0fsImZZxr6Qm1tbff+iyNS/ufoYgeVfsWhlEl9FoLv1g4HG6oA+uDHz+jKz9uSRHcGqD6P4JJK+H+yy0PeYfo7b6eSqFxgt8q8QfifUaCrVoCiY+c=
on:
tags: true
62 changes: 62 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,68 @@ Usage Examples
print(playlist.title)


Running tests over PlexAPI
--------------------------

In order to test the PlexAPI library you have to prepare a Plex Server instance with following libraries:

1. Movies section (agent `com.plexapp.agents.imdb`) containing both movies:
* Sintel - https://durian.blender.org/
* Elephants Dream - https://orange.blender.org/
* Sita Sings the Blues - http://www.sitasingstheblues.com/
* Big Buck Bunny - https://peach.blender.org/
2. TV Show section (agent `com.plexapp.agents.thetvdb`) containing the shows:
* Game of Thrones (Season 1 and 2)
* The 100 (Seasons 1 and 2)
* (or symlink the above movies with proper names)
3. Music section (agent `com.plexapp.agents.lastfm`) containing the albums:
* Infinite State - Unmastered Impulses - https://github.com/kennethreitz/unmastered-impulses
* Broke For Free - Layers - http://freemusicarchive.org/music/broke_for_free/Layers/
4. A Photos section (any agent) containing the photoalbums (photoalbum is just a folder on your disk):
* `Cats`
* Within `Cats` album you need to place 3 photos (cute cat photos, of course)
* Within `Cats` album you should place 3 more photoalbums (one of them should be named `Cats in bed`,
names of others doesn't matter)
* Within `Cats in bed` you need to place 7 photos
* Within other 2 albums you should place 1 photo in each

Instead of manual creation of the library you could use a script `tools/plex-boostraptest.py` with appropriate
arguments and add this new server to a shared user which username is defined in environment veriable `SHARED_USERNAME`.
It uses `official docker image`_ to create a proper instance.

Also in order to run most of the tests you have to provide some environment variables:

* `PLEXAPI_AUTH_SERVER_BASEURL` containing an URL to your Plex instance, e.g. `http://127.0.0.1:32400` (without trailing
slash)
* `PLEXAPI_AUTH_MYPLEX_USERNAME` and `PLEXAPI_AUTH_MYPLEX_PASSWORD` with your MyPlex username and password accordingly

After this step you can run tests with following command:

.. code-block:: bash

py.test tests -rxXs --ignore=tests/test_sync.py

Some of the tests in main test-suite require a shared user in your account (e.g. `test_myplex_users`,
`test_myplex_updateFriend`, etc.), you need to provide a valid shared user's username to get them running you need to
provide the username of the shared user as an environment variable `SHARED_USERNAME`. You can enable a Guest account and
simply pass `Guest` as `SHARED_USERNAME` (or just create a user like `plexapitest` and play with it).

To be able to run tests over Mobile Sync api you have to some some more environment variables, to following values
exactly:

* PLEXAPI_HEADER_PROVIDES='controller,sync-target'
* PLEXAPI_HEADER_PLATFORM=iOS
* PLEXAPI_HEADER_PLATFORM_VERSION=11.4.1
* PLEXAPI_HEADER_DEVICE=iPhone

And finally run the sync-related tests:

.. code-block:: bash

py.test tests/test_sync.py -rxXs

.. _official docker image: https://hub.docker.com/r/plexinc/pms-docker/

Common Questions
----------------

Expand Down
12 changes: 12 additions & 0 deletions plexapi/alert.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,18 @@ class AlertListener(threading.Thread):
alerts you must call .start() on the object once it's created. When calling
`PlexServer.startAlertListener()`, the thread will be started for you.

Known `state`-values for timeline entries, with identifier=`com.plexapp.plugins.library`:

:0: The item was created
:1: Reporting progress on item processing
:2: Matching the item
:3: Downloading the metadata
:4: Processing downloaded metadata
:5: The item processed
:9: The item deleted

When metadata agent is not set for the library processing ends with state=1.

Parameters:
server (:class:`~plexapi.server.PlexServer`): PlexServer this listener is connected to.
callback (func): Callback function to call on recieved messages. The callback function
Expand Down
22 changes: 13 additions & 9 deletions plexapi/library.py
Original file line number Diff line number Diff line change
Expand Up @@ -470,8 +470,8 @@ def search(self, title=None, sort=None, maxresults=999999, libtype=None, **kwarg
libtype (str): Filter results to a spcifiec libtype (movie, show, episode, artist,
album, track; optional).
**kwargs (dict): Any of the available filters for the current library section. Partial string
matches allowed. Multiple matches OR together. All inputs will be compared with the
available options and a warning logged if the option does not appear valid.
matches allowed. Multiple matches OR together. Negative filtering also possible, just add an
exclamation mark to the end of filter name, e.g. `resolution!=1x1`.

* unwatched: Display or hide unwatched content (True, False). [all]
* duplicate: Display or hide duplicate items (True, False). [movie]
Expand All @@ -486,6 +486,9 @@ def search(self, title=None, sort=None, maxresults=999999, libtype=None, **kwarg
* resolution: List of video resolutions to search within ([resolution_or_key, ...]). [movie]
* studio: List of studios to search within ([studio_or_key, ...]). [music]
* year: List of years to search within ([yyyy, ...]). [all]

Raises:
:class:`plexapi.exceptions.BadRequest`: when applying unknown filter
"""
# cleanup the core arguments
args = {}
Expand All @@ -510,7 +513,10 @@ def search(self, title=None, sort=None, maxresults=999999, libtype=None, **kwarg

def _cleanSearchFilter(self, category, value, libtype=None):
# check a few things before we begin
if category not in self.ALLOWED_FILTERS:
if category.endswith('!'):
if category[:-1] not in self.ALLOWED_FILTERS:
raise BadRequest('Unknown filter category: %s' % category[:-1])
elif category not in self.ALLOWED_FILTERS:
raise BadRequest('Unknown filter category: %s' % category)
if category in self.BOOLEAN_FILTERS:
return '1' if value else '0'
Expand Down Expand Up @@ -839,12 +845,12 @@ class PhotoSection(LibrarySection):

Attributes:
ALLOWED_FILTERS (list<str>): List of allowed search filters. ('all', 'iso',
'make', 'lens', 'aperture', 'exposure')
'make', 'lens', 'aperture', 'exposure', 'device', 'resolution')
ALLOWED_SORT (list<str>): List of allowed sorting keys. ('addedAt')
TAG (str): 'Directory'
TYPE (str): 'photo'
"""
ALLOWED_FILTERS = ('all', 'iso', 'make', 'lens', 'aperture', 'exposure')
ALLOWED_FILTERS = ('all', 'iso', 'make', 'lens', 'aperture', 'exposure', 'device', 'resolution')
ALLOWED_SORT = ('addedAt',)
TAG = 'Directory'
TYPE = 'photo'
Expand All @@ -853,13 +859,11 @@ class PhotoSection(LibrarySection):

def searchAlbums(self, title, **kwargs):
""" Search for an album. See :func:`~plexapi.library.LibrarySection.search()` for usage. """
key = '/library/sections/%s/all?type=14' % self.key
return self.fetchItems(key, title=title)
return self.search(libtype='photoalbum', title=title, **kwargs)

def searchPhotos(self, title, **kwargs):
""" Search for a photo. See :func:`~plexapi.library.LibrarySection.search()` for usage. """
key = '/library/sections/%s/all?type=13' % self.key
return self.fetchItems(key, title=title)
return self.search(libtype='photo', title=title, **kwargs)

def sync(self, resolution, limit=None, **kwargs):
""" Add current Music library section as sync item for specified device.
Expand Down
9 changes: 5 additions & 4 deletions plexapi/myplex.py
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ def updateFriend(self, user, server, sections=None, removeSections=False, allowS
# Update friend servers
response_filters = ''
response_servers = ''
user = self.user(user.username if isinstance(user, MyPlexUser) else user)
user = user if isinstance(user, MyPlexUser) else self.user(user)
machineId = server.machineIdentifier if isinstance(server, PlexServer) else server
sectionIds = self._getSectionIds(machineId, sections)
headers = {'Content-Type': 'application/json'}
Expand All @@ -278,7 +278,7 @@ def updateFriend(self, user, server, sections=None, removeSections=False, allowS
"invited_id": user.id}}
url = self.FRIENDINVITE.format(machineId=machineId)
# Remove share sections, add shares to user without shares, or update shares
if sectionIds:
if not user_servers or sectionIds:
if removeSections is True:
response_servers = self.query(url, self._session.delete, json=params, headers=headers)
elif 'invited_id' in params.get('shared_server', ''):
Expand Down Expand Up @@ -376,7 +376,8 @@ def deleteWebhook(self, url):

def setWebhooks(self, urls):
log.info('Setting webhooks: %s' % urls)
data = self.query(self.WEBHOOKS, self._session.post, data={'urls[]': urls})
data = {'urls[]': urls} if len(urls) else {'urls': ''}
data = self.query(self.WEBHOOKS, self._session.post, data=data)
self._webhooks = self.listAttrs(data, 'url', etag='webhook')
return self._webhooks

Expand All @@ -395,7 +396,7 @@ def optOut(self, playback=None, library=None):
if library is not None:
params['optOutLibraryStats'] = int(library)
url = 'https://plex.tv/api/v2/user/privacy'
return self.query(url, method=self._session.put, params=params)
return self.query(url, method=self._session.put, data=params)

def syncItems(self, client=None, clientId=None):
""" Returns an instance of :class:`plexapi.sync.SyncList` for specified client.
Expand Down
2 changes: 1 addition & 1 deletion plexapi/photo.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ def sync(self, resolution, client=None, clientId=None, limit=None, title=None):
sync_item.metadataType = self.METADATA_TYPE
sync_item.machineIdentifier = self._server.machineIdentifier

section = self._server.library.sectionByID(self.librarySectionID)
section = self.section()

sync_item.location = 'library://%s/item/%s' % (section.uuid, quote_plus(self.key))
sync_item.policy = Policy.create(limit)
Expand Down
4 changes: 2 additions & 2 deletions plexapi/playlist.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,8 +168,8 @@ def sync(self, videoQuality=None, photoResolution=None, audioBitrate=None, clien
:mod:`plexapi.sync` module. Used only when playlist contains video.
photoResolution (str): maximum allowed resolution for synchronized photos, see PHOTO_QUALITY_* values in
the module :mod:`plexapi.sync`. Used only when playlist contains photos.
audioBitrate (int): maximum bitrate for synchronized music, better use one of MUSIC_BITRATE_* values from the
module :mod:`plexapi.sync`. Used only when playlist contains audio.
audioBitrate (int): maximum bitrate for synchronized music, better use one of MUSIC_BITRATE_* values
from the module :mod:`plexapi.sync`. Used only when playlist contains audio.
client (:class:`plexapi.myplex.MyPlexDevice`): sync destination, see
:func:`plexapi.myplex.MyPlexAccount.sync`.
clientId (str): sync destination, see :func:`plexapi.myplex.MyPlexAccount.sync`.
Expand Down
6 changes: 4 additions & 2 deletions plexapi/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,12 +290,14 @@ def check_for_update(self, force=True, download=False):
part = '/updater/check?download=%s' % (1 if download else 0)
if force:
self.query(part, method=self._session.put)
return self.fetchItem('/updater/status')
releases = self.fetchItems('/updater/status')
if len(releases):
return releases[0]

def isLatest(self):
""" Check if the installed version of PMS is the latest. """
release = self.check_for_update(force=True)
return bool(release.version == self.version)
return release is None

def installUpdate(self):
""" Install the newest version of Plex Media Server. """
Expand Down
2 changes: 1 addition & 1 deletion plexapi/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ class Setting(PlexObject):
group (str): Group name this setting is categorized as.
enumValues (list,dict): List or dictionary of valis values for this setting.
"""
_bool_cast = lambda x: True if x == 'true' else False
_bool_cast = lambda x: True if x == 'true' or x == '1' else False
_bool_str = lambda x: str(x).lower()
TYPES = {
'bool': {'type': bool, 'cast': _bool_cast, 'tostr': _bool_str},
Expand Down
6 changes: 3 additions & 3 deletions plexapi/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@

# Search Types - Plex uses these to filter specific media types when searching.
# Library Types - Populated at runtime
SEARCHTYPES = {'movie': 1, 'show': 2, 'season': 3, 'episode': 4,
'artist': 8, 'album': 9, 'track': 10, 'photo': 14,
'collection': 18}
SEARCHTYPES = {'movie': 1, 'show': 2, 'season': 3, 'episode': 4, 'trailer': 5, 'comic': 6, 'person': 7,
'artist': 8, 'album': 9, 'track': 10, 'picture': 11, 'clip': 12, 'photo': 13, 'photoalbum': 14,
'playlist': 15, 'playlistFolder': 16, 'collection': 18, 'userPlaylistItem': 1001}
PLEXOBJECTS = {}


Expand Down
2 changes: 1 addition & 1 deletion plexapi/video.py
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ def isWatched(self):

def seasons(self, **kwargs):
""" Returns a list of :class:`~plexapi.video.Season` objects. """
key = '/library/metadata/%s/children' % self.ratingKey
key = '/library/metadata/%s/children?excludeAllLeaves=1' % self.ratingKey
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whats the benefit by excludeAllLeaves? Faster?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without it we'd have "All Seasons" as one more seasons, I think it's a bit unexpected.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Im not sure i understand. This is supposed to returns all seasons. does that still happen?

Copy link
Contributor Author

@andrey-yantsen andrey-yantsen Sep 11, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, sure. If the show has 2 seasons it'll return [<Season 1>, <Season 2>], but if you'd omit excludeAllLeaves you'll receive [<All Seasons>, <Season 1>, <Season 2>].

return self.fetchItems(key, **kwargs)

def season(self, title=None):
Expand Down
2 changes: 1 addition & 1 deletion requirements_dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ sphinx
sphinx-rtd-theme
sphinxcontrib-napoleon
tqdm
websocket-client
websocket-client==0.48.0
Loading