mirror of
https://github.com/pkkid/python-plexapi
synced 2024-11-26 21:50:20 +00:00
Merge pull request #649 from JonnyWong16/feature/edit_tags
Add more tag editing methods and move to a mixin
This commit is contained in:
commit
aca85d150c
12 changed files with 356 additions and 59 deletions
|
@ -4,6 +4,7 @@ from urllib.parse import quote_plus
|
||||||
from plexapi import library, media, utils
|
from plexapi import library, media, utils
|
||||||
from plexapi.base import Playable, PlexPartialObject
|
from plexapi.base import Playable, PlexPartialObject
|
||||||
from plexapi.exceptions import BadRequest
|
from plexapi.exceptions import BadRequest
|
||||||
|
from plexapi.mixins import CollectionMixin, CountryMixin, GenreMixin, LabelMixin, MoodMixin, SimilarArtistMixin, StyleMixin
|
||||||
|
|
||||||
|
|
||||||
class Audio(PlexPartialObject):
|
class Audio(PlexPartialObject):
|
||||||
|
@ -123,7 +124,7 @@ class Audio(PlexPartialObject):
|
||||||
|
|
||||||
|
|
||||||
@utils.registerPlexObject
|
@utils.registerPlexObject
|
||||||
class Artist(Audio):
|
class Artist(Audio, CollectionMixin, CountryMixin, GenreMixin, MoodMixin, SimilarArtistMixin, StyleMixin):
|
||||||
""" Represents a single Artist.
|
""" Represents a single Artist.
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
|
@ -226,7 +227,7 @@ class Artist(Audio):
|
||||||
|
|
||||||
|
|
||||||
@utils.registerPlexObject
|
@utils.registerPlexObject
|
||||||
class Album(Audio):
|
class Album(Audio, CollectionMixin, GenreMixin, LabelMixin, MoodMixin, StyleMixin):
|
||||||
""" Represents a single Album.
|
""" Represents a single Album.
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
|
@ -332,7 +333,7 @@ class Album(Audio):
|
||||||
|
|
||||||
|
|
||||||
@utils.registerPlexObject
|
@utils.registerPlexObject
|
||||||
class Track(Audio, Playable):
|
class Track(Audio, Playable, MoodMixin):
|
||||||
""" Represents a single Track.
|
""" Represents a single Track.
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
|
|
|
@ -5,7 +5,7 @@ from urllib.parse import quote_plus, urlencode
|
||||||
|
|
||||||
from plexapi import log, utils
|
from plexapi import log, utils
|
||||||
from plexapi.exceptions import BadRequest, NotFound, UnknownType, Unsupported
|
from plexapi.exceptions import BadRequest, NotFound, UnknownType, Unsupported
|
||||||
from plexapi.utils import tag_helper
|
from plexapi.utils import tag_plural, tag_helper
|
||||||
|
|
||||||
DONT_RELOAD_FOR_KEYS = ['key', 'session']
|
DONT_RELOAD_FOR_KEYS = ['key', 'session']
|
||||||
OPERATORS = {
|
OPERATORS = {
|
||||||
|
@ -462,40 +462,12 @@ class PlexPartialObject(PlexObject):
|
||||||
"""
|
"""
|
||||||
if not isinstance(items, list):
|
if not isinstance(items, list):
|
||||||
items = [items]
|
items = [items]
|
||||||
value = getattr(self, tag + 's')
|
value = getattr(self, tag_plural(tag))
|
||||||
existing_cols = [t.tag for t in value if t and remove is False]
|
existing_cols = [t.tag for t in value if t and remove is False]
|
||||||
d = tag_helper(tag, existing_cols + items, locked, remove)
|
d = tag_helper(tag, existing_cols + items, locked, remove)
|
||||||
self.edit(**d)
|
self.edit(**d)
|
||||||
self.refresh()
|
self.refresh()
|
||||||
|
|
||||||
def addCollection(self, collections):
|
|
||||||
""" Add a collection(s).
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
collections (list): list of strings
|
|
||||||
"""
|
|
||||||
self._edit_tags('collection', collections)
|
|
||||||
|
|
||||||
def removeCollection(self, collections):
|
|
||||||
""" Remove a collection(s). """
|
|
||||||
self._edit_tags('collection', collections, remove=True)
|
|
||||||
|
|
||||||
def addLabel(self, labels):
|
|
||||||
""" Add a label(s). """
|
|
||||||
self._edit_tags('label', labels)
|
|
||||||
|
|
||||||
def removeLabel(self, labels):
|
|
||||||
""" Remove a label(s). """
|
|
||||||
self._edit_tags('label', labels, remove=True)
|
|
||||||
|
|
||||||
def addGenre(self, genres):
|
|
||||||
""" Add a genre(s). """
|
|
||||||
self._edit_tags('genre', genres)
|
|
||||||
|
|
||||||
def removeGenre(self, genres):
|
|
||||||
""" Remove a genre(s). """
|
|
||||||
self._edit_tags('genre', genres, remove=True)
|
|
||||||
|
|
||||||
def refresh(self):
|
def refresh(self):
|
||||||
""" Refreshing a Library or individual item causes the metadata for the item to be
|
""" Refreshing a Library or individual item causes the metadata for the item to be
|
||||||
refreshed, even if it already has metadata. You can think of refreshing as
|
refreshed, even if it already has metadata. You can think of refreshing as
|
||||||
|
|
|
@ -4,6 +4,7 @@ from urllib.parse import quote, quote_plus, unquote, urlencode
|
||||||
from plexapi import X_PLEX_CONTAINER_SIZE, log, media, utils
|
from plexapi import X_PLEX_CONTAINER_SIZE, log, media, utils
|
||||||
from plexapi.base import OPERATORS, PlexObject, PlexPartialObject
|
from plexapi.base import OPERATORS, PlexObject, PlexPartialObject
|
||||||
from plexapi.exceptions import BadRequest, NotFound
|
from plexapi.exceptions import BadRequest, NotFound
|
||||||
|
from plexapi.mixins import LabelMixin
|
||||||
from plexapi.settings import Setting
|
from plexapi.settings import Setting
|
||||||
from plexapi.utils import deprecated
|
from plexapi.utils import deprecated
|
||||||
|
|
||||||
|
@ -1526,7 +1527,7 @@ class FirstCharacter(PlexObject):
|
||||||
|
|
||||||
|
|
||||||
@utils.registerPlexObject
|
@utils.registerPlexObject
|
||||||
class Collections(PlexPartialObject):
|
class Collections(PlexPartialObject, LabelMixin):
|
||||||
""" Represents a single Collection.
|
""" Represents a single Collection.
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
|
|
221
plexapi/mixins.py
Normal file
221
plexapi/mixins.py
Normal file
|
@ -0,0 +1,221 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
|
||||||
|
class CollectionMixin(object):
|
||||||
|
""" Mixin for Plex objects that can have collections. """
|
||||||
|
|
||||||
|
def addCollection(self, collections):
|
||||||
|
""" Add a collection tag(s).
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
collections (list): List of strings.
|
||||||
|
"""
|
||||||
|
self._edit_tags('collection', collections)
|
||||||
|
|
||||||
|
def removeCollection(self, collections):
|
||||||
|
""" Remove a collection tag(s).
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
collections (list): List of strings.
|
||||||
|
"""
|
||||||
|
self._edit_tags('collection', collections, remove=True)
|
||||||
|
|
||||||
|
|
||||||
|
class CountryMixin(object):
|
||||||
|
""" Mixin for Plex objects that can have countries. """
|
||||||
|
|
||||||
|
def addCountry(self, countries):
|
||||||
|
""" Add a country tag(s).
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
countries (list): List of strings.
|
||||||
|
"""
|
||||||
|
self._edit_tags('country', countries)
|
||||||
|
|
||||||
|
def removeCountry(self, countries):
|
||||||
|
""" Remove a country tag(s).
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
countries (list): List of strings.
|
||||||
|
"""
|
||||||
|
self._edit_tags('country', countries, remove=True)
|
||||||
|
|
||||||
|
|
||||||
|
class DirectorMixin(object):
|
||||||
|
""" Mixin for Plex objects that can have directors. """
|
||||||
|
|
||||||
|
def addDirector(self, directors):
|
||||||
|
""" Add a director tag(s).
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
directors (list): List of strings.
|
||||||
|
"""
|
||||||
|
self._edit_tags('director', directors)
|
||||||
|
|
||||||
|
def removeDirector(self, directors):
|
||||||
|
""" Remove a director tag(s).
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
directors (list): List of strings.
|
||||||
|
"""
|
||||||
|
self._edit_tags('director', directors, remove=True)
|
||||||
|
|
||||||
|
|
||||||
|
class GenreMixin(object):
|
||||||
|
""" Mixin for Plex objects that can have genres. """
|
||||||
|
|
||||||
|
def addGenre(self, genres):
|
||||||
|
""" Add a genre tag(s).
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
genres (list): List of strings.
|
||||||
|
"""
|
||||||
|
self._edit_tags('genre', genres)
|
||||||
|
|
||||||
|
def removeGenre(self, genres):
|
||||||
|
""" Remove a genre tag(s).
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
genres (list): List of strings.
|
||||||
|
"""
|
||||||
|
self._edit_tags('genre', genres, remove=True)
|
||||||
|
|
||||||
|
|
||||||
|
class LabelMixin(object):
|
||||||
|
""" Mixin for Plex objects that can have labels. """
|
||||||
|
|
||||||
|
def addLabel(self, labels):
|
||||||
|
""" Add a label tag(s).
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
labels (list): List of strings.
|
||||||
|
"""
|
||||||
|
self._edit_tags('label', labels)
|
||||||
|
|
||||||
|
def removeLabel(self, labels):
|
||||||
|
""" Remove a label tag(s).
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
labels (list): List of strings.
|
||||||
|
"""
|
||||||
|
self._edit_tags('label', labels, remove=True)
|
||||||
|
|
||||||
|
|
||||||
|
class MoodMixin(object):
|
||||||
|
""" Mixin for Plex objects that can have moods. """
|
||||||
|
|
||||||
|
def addMood(self, moods):
|
||||||
|
""" Add a mood tag(s).
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
moods (list): List of strings.
|
||||||
|
"""
|
||||||
|
self._edit_tags('mood', moods)
|
||||||
|
|
||||||
|
def removeMood(self, moods):
|
||||||
|
""" Remove a mood tag(s).
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
moods (list): List of strings.
|
||||||
|
"""
|
||||||
|
self._edit_tags('mood', moods, remove=True)
|
||||||
|
|
||||||
|
|
||||||
|
class ProducerMixin(object):
|
||||||
|
""" Mixin for Plex objects that can have producers. """
|
||||||
|
|
||||||
|
def addProducer(self, producers):
|
||||||
|
""" Add a producer tag(s).
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
producers (list): List of strings.
|
||||||
|
"""
|
||||||
|
self._edit_tags('producer', producers)
|
||||||
|
|
||||||
|
def removeProducer(self, producers):
|
||||||
|
""" Remove a producer tag(s).
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
producers (list): List of strings.
|
||||||
|
"""
|
||||||
|
self._edit_tags('producer', producers, remove=True)
|
||||||
|
|
||||||
|
|
||||||
|
class SimilarArtistMixin(object):
|
||||||
|
""" Mixin for Plex objects that can have similar artists. """
|
||||||
|
|
||||||
|
def addSimilarArtist(self, artists):
|
||||||
|
""" Add a similar artist tag(s).
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
artists (list): List of strings.
|
||||||
|
"""
|
||||||
|
self._edit_tags('similar', artists)
|
||||||
|
|
||||||
|
def removeSimilarArtist(self, artists):
|
||||||
|
""" Remove a similar artist tag(s).
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
artists (list): List of strings.
|
||||||
|
"""
|
||||||
|
self._edit_tags('similar', artists, remove=True)
|
||||||
|
|
||||||
|
|
||||||
|
class StyleMixin(object):
|
||||||
|
""" Mixin for Plex objects that can have styles. """
|
||||||
|
|
||||||
|
def addStyle(self, styles):
|
||||||
|
""" Add a style tag(s).
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
styles (list): List of strings.
|
||||||
|
"""
|
||||||
|
self._edit_tags('style', styles)
|
||||||
|
|
||||||
|
def removeStyle(self, styles):
|
||||||
|
""" Remove a style tag(s).
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
styles (list): List of strings.
|
||||||
|
"""
|
||||||
|
self._edit_tags('style', styles, remove=True)
|
||||||
|
|
||||||
|
|
||||||
|
class TagMixin(object):
|
||||||
|
""" Mixin for Plex objects that can have tags. """
|
||||||
|
|
||||||
|
def addTag(self, tags):
|
||||||
|
""" Add a tag(s).
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
tags (list): List of strings.
|
||||||
|
"""
|
||||||
|
self._edit_tags('tag', tags)
|
||||||
|
|
||||||
|
def removeTag(self, tags):
|
||||||
|
""" Remove a tag(s).
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
tags (list): List of strings.
|
||||||
|
"""
|
||||||
|
self._edit_tags('tag', tags, remove=True)
|
||||||
|
|
||||||
|
|
||||||
|
class EditWriter(object):
|
||||||
|
""" Mixin for Plex objects that can have writers. """
|
||||||
|
|
||||||
|
def addWriter(self, writers):
|
||||||
|
""" Add a writer tag(s).
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
writers (list): List of strings.
|
||||||
|
"""
|
||||||
|
self._edit_tags('writer', writers)
|
||||||
|
|
||||||
|
def removeWriter(self, writers):
|
||||||
|
""" Remove a writer tag(s).
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
writers (list): List of strings.
|
||||||
|
"""
|
||||||
|
self._edit_tags('writer', writers, remove=True)
|
|
@ -4,6 +4,7 @@ from urllib.parse import quote_plus
|
||||||
from plexapi import media, utils, video
|
from plexapi import media, utils, video
|
||||||
from plexapi.base import Playable, PlexPartialObject
|
from plexapi.base import Playable, PlexPartialObject
|
||||||
from plexapi.exceptions import BadRequest
|
from plexapi.exceptions import BadRequest
|
||||||
|
from plexapi.mixins import TagMixin
|
||||||
|
|
||||||
|
|
||||||
@utils.registerPlexObject
|
@utils.registerPlexObject
|
||||||
|
@ -136,7 +137,7 @@ class Photoalbum(PlexPartialObject):
|
||||||
|
|
||||||
|
|
||||||
@utils.registerPlexObject
|
@utils.registerPlexObject
|
||||||
class Photo(PlexPartialObject, Playable):
|
class Photo(PlexPartialObject, Playable, TagMixin):
|
||||||
""" Represents a single Photo.
|
""" Represents a single Photo.
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
|
@ -163,7 +164,7 @@ class Photo(PlexPartialObject, Playable):
|
||||||
parentTitle (str): Name of the photo album for the photo.
|
parentTitle (str): Name of the photo album for the photo.
|
||||||
ratingKey (int): Unique key identifying the photo.
|
ratingKey (int): Unique key identifying the photo.
|
||||||
summary (str): Summary of the photo.
|
summary (str): Summary of the photo.
|
||||||
tag (List<:class:`~plexapi.media.Tag`>): List of tag objects.
|
tags (List<:class:`~plexapi.media.Tag`>): List of tag objects.
|
||||||
thumb (str): URL to thumbnail image (/library/metadata/<ratingKey>/thumb/<thumbid>).
|
thumb (str): URL to thumbnail image (/library/metadata/<ratingKey>/thumb/<thumbid>).
|
||||||
title (str): Name of the photo.
|
title (str): Name of the photo.
|
||||||
titleSort (str): Title to use when sorting (defaults to title).
|
titleSort (str): Title to use when sorting (defaults to title).
|
||||||
|
@ -199,7 +200,7 @@ class Photo(PlexPartialObject, Playable):
|
||||||
self.parentTitle = data.attrib.get('parentTitle')
|
self.parentTitle = data.attrib.get('parentTitle')
|
||||||
self.ratingKey = utils.cast(int, data.attrib.get('ratingKey'))
|
self.ratingKey = utils.cast(int, data.attrib.get('ratingKey'))
|
||||||
self.summary = data.attrib.get('summary')
|
self.summary = data.attrib.get('summary')
|
||||||
self.tag = self.findItems(data, media.Tag)
|
self.tags = self.findItems(data, media.Tag)
|
||||||
self.thumb = data.attrib.get('thumb')
|
self.thumb = data.attrib.get('thumb')
|
||||||
self.title = data.attrib.get('title')
|
self.title = data.attrib.get('title')
|
||||||
self.titleSort = data.attrib.get('titleSort', self.title)
|
self.titleSort = data.attrib.get('titleSort', self.title)
|
||||||
|
|
|
@ -335,6 +335,15 @@ def download(url, token, filename=None, savepath=None, session=None, chunksize=4
|
||||||
return fullpath
|
return fullpath
|
||||||
|
|
||||||
|
|
||||||
|
def tag_plural(tag):
|
||||||
|
if tag == 'country':
|
||||||
|
return 'countries'
|
||||||
|
elif tag == 'similar':
|
||||||
|
return 'similar'
|
||||||
|
else:
|
||||||
|
return tag + 's'
|
||||||
|
|
||||||
|
|
||||||
def tag_helper(tag, items, locked=True, remove=False):
|
def tag_helper(tag, items, locked=True, remove=False):
|
||||||
""" Simple tag helper for editing a object. """
|
""" Simple tag helper for editing a object. """
|
||||||
if not isinstance(items, list):
|
if not isinstance(items, list):
|
||||||
|
|
|
@ -5,6 +5,7 @@ from urllib.parse import quote_plus, urlencode
|
||||||
from plexapi import library, media, settings, utils
|
from plexapi import library, media, settings, utils
|
||||||
from plexapi.base import Playable, PlexPartialObject
|
from plexapi.base import Playable, PlexPartialObject
|
||||||
from plexapi.exceptions import BadRequest, NotFound
|
from plexapi.exceptions import BadRequest, NotFound
|
||||||
|
from plexapi.mixins import CollectionMixin, CountryMixin, DirectorMixin, GenreMixin, LabelMixin, ProducerMixin, EditWriter
|
||||||
|
|
||||||
|
|
||||||
class Video(PlexPartialObject):
|
class Video(PlexPartialObject):
|
||||||
|
@ -259,7 +260,7 @@ class Video(PlexPartialObject):
|
||||||
|
|
||||||
|
|
||||||
@utils.registerPlexObject
|
@utils.registerPlexObject
|
||||||
class Movie(Playable, Video):
|
class Movie(Playable, Video, CollectionMixin, CountryMixin, DirectorMixin, GenreMixin, LabelMixin, ProducerMixin, EditWriter):
|
||||||
""" Represents a single Movie.
|
""" Represents a single Movie.
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
|
@ -385,7 +386,7 @@ class Movie(Playable, Video):
|
||||||
|
|
||||||
|
|
||||||
@utils.registerPlexObject
|
@utils.registerPlexObject
|
||||||
class Show(Video):
|
class Show(Video, CollectionMixin, GenreMixin, LabelMixin):
|
||||||
""" Represents a single Show (including all seasons and episodes).
|
""" Represents a single Show (including all seasons and episodes).
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
|
@ -709,7 +710,7 @@ class Season(Video):
|
||||||
|
|
||||||
|
|
||||||
@utils.registerPlexObject
|
@utils.registerPlexObject
|
||||||
class Episode(Playable, Video):
|
class Episode(Playable, Video, DirectorMixin, EditWriter):
|
||||||
""" Represents a single Shows Episode.
|
""" Represents a single Shows Episode.
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
|
|
|
@ -227,14 +227,14 @@ def movie(movies):
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
def collection(plex):
|
def collection(movies):
|
||||||
try:
|
try:
|
||||||
return plex.library.section("Movies").collections()[0]
|
return movies.collections()[0]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
movie = plex.library.section("Movies").get("Elephants Dream")
|
movie = movies.get("Elephants Dream")
|
||||||
movie.addCollection(["marvel"])
|
movie.addCollection(["marvel"])
|
||||||
|
|
||||||
n = plex.library.section("Movies").reload()
|
n = movies.reload()
|
||||||
return n.collections()[0]
|
return n.collections()[0]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from . import conftest as utils
|
from . import conftest as utils
|
||||||
|
from . import test_mixins
|
||||||
|
|
||||||
|
|
||||||
def test_audio_Artist_attr(artist):
|
def test_audio_Artist_attr(artist):
|
||||||
|
@ -63,6 +64,15 @@ def test_audio_Artist_albums(artist):
|
||||||
assert len(albums) == 1 and albums[0].title == "Layers"
|
assert len(albums) == 1 and albums[0].title == "Layers"
|
||||||
|
|
||||||
|
|
||||||
|
def test_audio_Artist_mixins_tags(artist):
|
||||||
|
test_mixins.edit_collection(artist)
|
||||||
|
test_mixins.edit_country(artist)
|
||||||
|
test_mixins.edit_genre(artist)
|
||||||
|
test_mixins.edit_mood(artist)
|
||||||
|
test_mixins.edit_similar_artist(artist)
|
||||||
|
test_mixins.edit_style(artist)
|
||||||
|
|
||||||
|
|
||||||
def test_audio_Album_attrs(album):
|
def test_audio_Album_attrs(album):
|
||||||
assert utils.is_datetime(album.addedAt)
|
assert utils.is_datetime(album.addedAt)
|
||||||
assert isinstance(album.genres, list)
|
assert isinstance(album.genres, list)
|
||||||
|
@ -211,6 +221,14 @@ def test_audio_Album_artist(album):
|
||||||
artist.title == "Broke For Free"
|
artist.title == "Broke For Free"
|
||||||
|
|
||||||
|
|
||||||
|
def test_audio_Album_mixins_tags(album):
|
||||||
|
test_mixins.edit_collection(album)
|
||||||
|
test_mixins.edit_genre(album)
|
||||||
|
test_mixins.edit_label(album)
|
||||||
|
test_mixins.edit_mood(album)
|
||||||
|
test_mixins.edit_style(album)
|
||||||
|
|
||||||
|
|
||||||
def test_audio_Track_attrs(album):
|
def test_audio_Track_attrs(album):
|
||||||
track = album.get("As Colourful As Ever").reload()
|
track = album.get("As Colourful As Ever").reload()
|
||||||
assert utils.is_datetime(track.addedAt)
|
assert utils.is_datetime(track.addedAt)
|
||||||
|
@ -328,6 +346,10 @@ def test_audio_Track_artist(album, artist):
|
||||||
assert tracks[0].artist() == artist
|
assert tracks[0].artist() == artist
|
||||||
|
|
||||||
|
|
||||||
|
def test_audio_Track_mixins_tags(track):
|
||||||
|
test_mixins.edit_mood(track)
|
||||||
|
|
||||||
|
|
||||||
def test_audio_Audio_section(artist, album, track):
|
def test_audio_Audio_section(artist, album, track):
|
||||||
assert artist.section()
|
assert artist.section()
|
||||||
assert album.section()
|
assert album.section()
|
||||||
|
@ -348,7 +370,3 @@ def test_audio_album_download(monkeydownload, album, tmpdir):
|
||||||
def test_audio_Artist_download(monkeydownload, artist, tmpdir):
|
def test_audio_Artist_download(monkeydownload, artist, tmpdir):
|
||||||
f = artist.download(savepath=str(tmpdir))
|
f = artist.download(savepath=str(tmpdir))
|
||||||
assert len(f) == 1
|
assert len(f) == 1
|
||||||
|
|
||||||
|
|
||||||
def test_audio_Album_label(album, patched_http_call):
|
|
||||||
album.addLabel("YO")
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import pytest
|
||||||
from plexapi.exceptions import NotFound
|
from plexapi.exceptions import NotFound
|
||||||
|
|
||||||
from . import conftest as utils
|
from . import conftest as utils
|
||||||
|
from . import test_mixins
|
||||||
|
|
||||||
|
|
||||||
def test_library_Library_section(plex):
|
def test_library_Library_section(plex):
|
||||||
|
@ -323,6 +324,10 @@ def test_library_Collection_artUrl(collection):
|
||||||
assert collection.artUrl is None # Collections don't have default art
|
assert collection.artUrl is None # Collections don't have default art
|
||||||
|
|
||||||
|
|
||||||
|
def test_library_Collection_mixins_tags(collection):
|
||||||
|
test_mixins.edit_label(collection)
|
||||||
|
|
||||||
|
|
||||||
def test_search_with_weird_a(plex):
|
def test_search_with_weird_a(plex):
|
||||||
ep_title = "Coup de Grâce"
|
ep_title = "Coup de Grâce"
|
||||||
result_root = plex.search(ep_title)
|
result_root = plex.search(ep_title)
|
||||||
|
@ -366,6 +371,6 @@ def test_library_section_timeline(plex):
|
||||||
assert tl.mediaTagVersion > 1
|
assert tl.mediaTagVersion > 1
|
||||||
assert tl.thumb == "/:/resources/movie.png"
|
assert tl.thumb == "/:/resources/movie.png"
|
||||||
assert tl.title1 == "Movies"
|
assert tl.title1 == "Movies"
|
||||||
assert tl.updateQueueSize == 0
|
assert utils.is_int(tl.updateQueueSize, gte=0)
|
||||||
assert tl.viewGroup == "secondary"
|
assert tl.viewGroup == "secondary"
|
||||||
assert tl.viewMode == 65592
|
assert tl.viewMode == 65592
|
||||||
|
|
58
tests/test_mixins.py
Normal file
58
tests/test_mixins.py
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
TEST_MIXIN_TAG = "Test Tag"
|
||||||
|
|
||||||
|
|
||||||
|
def _test_mixins_tag(obj, attr, tag_method):
|
||||||
|
add_tag_method = getattr(obj, 'add' + tag_method)
|
||||||
|
remove_tag_method = getattr(obj, 'remove' + tag_method)
|
||||||
|
assert TEST_MIXIN_TAG not in [tag.tag for tag in getattr(obj, attr)]
|
||||||
|
add_tag_method(TEST_MIXIN_TAG)
|
||||||
|
obj.reload()
|
||||||
|
assert TEST_MIXIN_TAG in [tag.tag for tag in getattr(obj, attr)]
|
||||||
|
remove_tag_method(TEST_MIXIN_TAG)
|
||||||
|
obj.reload()
|
||||||
|
assert TEST_MIXIN_TAG not in [tag.tag for tag in getattr(obj, attr)]
|
||||||
|
|
||||||
|
|
||||||
|
def edit_collection(obj):
|
||||||
|
_test_mixins_tag(obj, 'collections', 'Collection')
|
||||||
|
|
||||||
|
|
||||||
|
def edit_country(obj):
|
||||||
|
_test_mixins_tag(obj, 'countries', 'Country')
|
||||||
|
|
||||||
|
|
||||||
|
def edit_director(obj):
|
||||||
|
_test_mixins_tag(obj, 'directors', 'Director')
|
||||||
|
|
||||||
|
|
||||||
|
def edit_genre(obj):
|
||||||
|
_test_mixins_tag(obj, 'genres', 'Genre')
|
||||||
|
|
||||||
|
|
||||||
|
def edit_label(obj):
|
||||||
|
_test_mixins_tag(obj, 'labels', 'Label')
|
||||||
|
|
||||||
|
|
||||||
|
def edit_mood(obj):
|
||||||
|
_test_mixins_tag(obj, 'moods', 'Mood')
|
||||||
|
|
||||||
|
|
||||||
|
def edit_producer(obj):
|
||||||
|
_test_mixins_tag(obj, 'producers', 'Producer')
|
||||||
|
|
||||||
|
|
||||||
|
def edit_similar_artist(obj):
|
||||||
|
_test_mixins_tag(obj, 'similar', 'SimilarArtist')
|
||||||
|
|
||||||
|
|
||||||
|
def edit_style(obj):
|
||||||
|
_test_mixins_tag(obj, 'styles', 'Style')
|
||||||
|
|
||||||
|
|
||||||
|
def edit_tag(obj):
|
||||||
|
_test_mixins_tag(obj, 'tags', 'Tag')
|
||||||
|
|
||||||
|
|
||||||
|
def edit_writer(obj):
|
||||||
|
_test_mixins_tag(obj, 'writers', 'Writer')
|
|
@ -8,6 +8,7 @@ import pytest
|
||||||
from plexapi.exceptions import BadRequest, NotFound
|
from plexapi.exceptions import BadRequest, NotFound
|
||||||
|
|
||||||
from . import conftest as utils
|
from . import conftest as utils
|
||||||
|
from . import test_mixins
|
||||||
|
|
||||||
|
|
||||||
def test_video_Movie(movies, movie):
|
def test_video_Movie(movies, movie):
|
||||||
|
@ -39,16 +40,14 @@ def test_video_Movie_merge(movie, patched_http_call):
|
||||||
movie.merge(1337)
|
movie.merge(1337)
|
||||||
|
|
||||||
|
|
||||||
def test_video_Movie_addCollection(movie):
|
def test_video_Movie_mixins_tags(movie):
|
||||||
labelname = "Random_label"
|
test_mixins.edit_collection(movie)
|
||||||
org_collection = [tag.tag for tag in movie.collections if tag]
|
test_mixins.edit_country(movie)
|
||||||
assert labelname not in org_collection
|
test_mixins.edit_director(movie)
|
||||||
movie.addCollection(labelname)
|
test_mixins.edit_genre(movie)
|
||||||
movie.reload()
|
test_mixins.edit_label(movie)
|
||||||
assert labelname in [tag.tag for tag in movie.collections if tag]
|
test_mixins.edit_producer(movie)
|
||||||
movie.removeCollection(labelname)
|
test_mixins.edit_writer(movie)
|
||||||
movie.reload()
|
|
||||||
assert labelname not in [tag.tag for tag in movie.collections if tag]
|
|
||||||
|
|
||||||
|
|
||||||
def test_video_Movie_getStreamURL(movie, account):
|
def test_video_Movie_getStreamURL(movie, account):
|
||||||
|
@ -723,6 +722,12 @@ def test_video_Show_section(show):
|
||||||
assert section.title == "TV Shows"
|
assert section.title == "TV Shows"
|
||||||
|
|
||||||
|
|
||||||
|
def test_video_Show_mixins_tags(show):
|
||||||
|
test_mixins.edit_collection(show)
|
||||||
|
test_mixins.edit_genre(show)
|
||||||
|
test_mixins.edit_label(show)
|
||||||
|
|
||||||
|
|
||||||
def test_video_Episode(show):
|
def test_video_Episode(show):
|
||||||
episode = show.episode("Winter Is Coming")
|
episode = show.episode("Winter Is Coming")
|
||||||
assert episode == show.episode(season=1, episode=1)
|
assert episode == show.episode(season=1, episode=1)
|
||||||
|
@ -813,6 +818,11 @@ def test_video_Episode_attrs(episode):
|
||||||
assert part.accessible
|
assert part.accessible
|
||||||
|
|
||||||
|
|
||||||
|
def test_video_Episode_mixins_tags(episode):
|
||||||
|
test_mixins.edit_director(episode)
|
||||||
|
test_mixins.edit_writer(episode)
|
||||||
|
|
||||||
|
|
||||||
def test_video_Season(show):
|
def test_video_Season(show):
|
||||||
seasons = show.seasons()
|
seasons = show.seasons()
|
||||||
assert len(seasons) == 2
|
assert len(seasons) == 2
|
||||||
|
|
Loading…
Reference in a new issue