Skip to content

Commit 3460663

Browse files
authored
Merge pull request #667 from JonnyWong16/feature/move_collection
Move collections to a separate module
2 parents 61dc373 + 72244f5 commit 3460663

File tree

6 files changed

+288
-251
lines changed

6 files changed

+288
-251
lines changed

plexapi/collection.py

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
# -*- coding: utf-8 -*-
2+
from plexapi import media, utils
3+
from plexapi.base import PlexPartialObject
4+
from plexapi.exceptions import BadRequest
5+
from plexapi.mixins import ArtMixin, PosterMixin
6+
from plexapi.mixins import LabelMixin
7+
from plexapi.settings import Setting
8+
from plexapi.utils import deprecated
9+
10+
11+
@utils.registerPlexObject
12+
class Collections(PlexPartialObject, ArtMixin, PosterMixin, LabelMixin):
13+
""" Represents a single Collection.
14+
15+
Attributes:
16+
TAG (str): 'Directory'
17+
TYPE (str): 'collection'
18+
addedAt (datetime): Datetime the collection was added to the library.
19+
art (str): URL to artwork image (/library/metadata/<ratingKey>/art/<artid>).
20+
artBlurHash (str): BlurHash string for artwork image.
21+
childCount (int): Number of items in the collection.
22+
collectionMode (str): How the items in the collection are displayed.
23+
collectionSort (str): How to sort the items in the collection.
24+
contentRating (str) Content rating (PG-13; NR; TV-G).
25+
fields (List<:class:`~plexapi.media.Field`>): List of field objects.
26+
guid (str): Plex GUID for the collection (collection://XXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXX).
27+
index (int): Plex index number for the collection.
28+
key (str): API URL (/library/metadata/<ratingkey>).
29+
labels (List<:class:`~plexapi.media.Label`>): List of label objects.
30+
librarySectionID (int): :class:`~plexapi.library.LibrarySection` ID.
31+
librarySectionKey (str): :class:`~plexapi.library.LibrarySection` key.
32+
librarySectionTitle (str): :class:`~plexapi.library.LibrarySection` title.
33+
maxYear (int): Maximum year for the items in the collection.
34+
minYear (int): Minimum year for the items in the collection.
35+
ratingKey (int): Unique key identifying the collection.
36+
subtype (str): Media type of the items in the collection (movie, show, artist, or album).
37+
summary (str): Summary of the collection.
38+
thumb (str): URL to thumbnail image (/library/metadata/<ratingKey>/thumb/<thumbid>).
39+
thumbBlurHash (str): BlurHash string for thumbnail image.
40+
title (str): Name of the collection.
41+
titleSort (str): Title to use when sorting (defaults to title).
42+
type (str): 'collection'
43+
updatedAt (datatime): Datetime the collection was updated.
44+
"""
45+
46+
TAG = 'Directory'
47+
TYPE = 'collection'
48+
49+
def _loadData(self, data):
50+
self.addedAt = utils.toDatetime(data.attrib.get('addedAt'))
51+
self.art = data.attrib.get('art')
52+
self.artBlurHash = data.attrib.get('artBlurHash')
53+
self.childCount = utils.cast(int, data.attrib.get('childCount'))
54+
self.collectionMode = utils.cast(int, data.attrib.get('collectionMode', '-1'))
55+
self.collectionSort = utils.cast(int, data.attrib.get('collectionSort', '0'))
56+
self.contentRating = data.attrib.get('contentRating')
57+
self.fields = self.findItems(data, media.Field)
58+
self.guid = data.attrib.get('guid')
59+
self.index = utils.cast(int, data.attrib.get('index'))
60+
self.key = data.attrib.get('key', '').replace('/children', '') # FIX_BUG_50
61+
self.labels = self.findItems(data, media.Label)
62+
self.librarySectionID = data.attrib.get('librarySectionID')
63+
self.librarySectionKey = data.attrib.get('librarySectionKey')
64+
self.librarySectionTitle = data.attrib.get('librarySectionTitle')
65+
self.maxYear = utils.cast(int, data.attrib.get('maxYear'))
66+
self.minYear = utils.cast(int, data.attrib.get('minYear'))
67+
self.ratingKey = utils.cast(int, data.attrib.get('ratingKey'))
68+
self.subtype = data.attrib.get('subtype')
69+
self.summary = data.attrib.get('summary')
70+
self.thumb = data.attrib.get('thumb')
71+
self.thumbBlurHash = data.attrib.get('thumbBlurHash')
72+
self.title = data.attrib.get('title')
73+
self.titleSort = data.attrib.get('titleSort', self.title)
74+
self.type = data.attrib.get('type')
75+
self.updatedAt = utils.toDatetime(data.attrib.get('updatedAt'))
76+
77+
@property
78+
@deprecated('use "items" instead')
79+
def children(self):
80+
return self.items()
81+
82+
@property
83+
def thumbUrl(self):
84+
""" Return the thumbnail url for the collection."""
85+
return self._server.url(self.thumb, includeToken=True) if self.thumb else None
86+
87+
@property
88+
def artUrl(self):
89+
""" Return the art url for the collection."""
90+
return self._server.url(self.art, includeToken=True) if self.art else None
91+
92+
def item(self, title):
93+
""" Returns the item in the collection that matches the specified title.
94+
95+
Parameters:
96+
title (str): Title of the item to return.
97+
"""
98+
key = '/library/metadata/%s/children' % self.ratingKey
99+
return self.fetchItem(key, title__iexact=title)
100+
101+
def items(self):
102+
""" Returns a list of all items in the collection. """
103+
key = '/library/metadata/%s/children' % self.ratingKey
104+
return self.fetchItems(key)
105+
106+
def get(self, title):
107+
""" Alias to :func:`~plexapi.library.Collection.item`. """
108+
return self.item(title)
109+
110+
def __len__(self):
111+
return self.childCount
112+
113+
def _preferences(self):
114+
""" Returns a list of :class:`~plexapi.settings.Preferences` objects. """
115+
items = []
116+
data = self._server.query(self._details_key)
117+
for item in data.iter('Setting'):
118+
items.append(Setting(data=item, server=self._server))
119+
120+
return items
121+
122+
def modeUpdate(self, mode=None):
123+
""" Update Collection Mode
124+
125+
Parameters:
126+
mode: default (Library default)
127+
hide (Hide Collection)
128+
hideItems (Hide Items in this Collection)
129+
showItems (Show this Collection and its Items)
130+
Example:
131+
132+
collection = 'plexapi.library.Collections'
133+
collection.updateMode(mode="hide")
134+
"""
135+
mode_dict = {'default': -1,
136+
'hide': 0,
137+
'hideItems': 1,
138+
'showItems': 2}
139+
key = mode_dict.get(mode)
140+
if key is None:
141+
raise BadRequest('Unknown collection mode : %s. Options %s' % (mode, list(mode_dict)))
142+
part = '/library/metadata/%s/prefs?collectionMode=%s' % (self.ratingKey, key)
143+
return self._server.query(part, method=self._server._session.put)
144+
145+
def sortUpdate(self, sort=None):
146+
""" Update Collection Sorting
147+
148+
Parameters:
149+
sort: realease (Order Collection by realease dates)
150+
alpha (Order Collection alphabetically)
151+
custom (Custom collection order)
152+
153+
Example:
154+
155+
colleciton = 'plexapi.library.Collections'
156+
collection.updateSort(mode="alpha")
157+
"""
158+
sort_dict = {'release': 0,
159+
'alpha': 1,
160+
'custom': 2}
161+
key = sort_dict.get(sort)
162+
if key is None:
163+
raise BadRequest('Unknown sort dir: %s. Options: %s' % (sort, list(sort_dict)))
164+
part = '/library/metadata/%s/prefs?collectionSort=%s' % (self.ratingKey, key)
165+
return self._server.query(part, method=self._server._session.put)

plexapi/library.py

Lines changed: 1 addition & 165 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@
22
from urllib.parse import quote, quote_plus, unquote, urlencode
33

44
from plexapi import X_PLEX_CONTAINER_SIZE, log, media, utils
5-
from plexapi.base import OPERATORS, PlexObject, PlexPartialObject
5+
from plexapi.base import OPERATORS, PlexObject
66
from plexapi.exceptions import BadRequest, NotFound
7-
from plexapi.mixins import ArtMixin, PosterMixin
8-
from plexapi.mixins import LabelMixin
97
from plexapi.settings import Setting
108
from plexapi.utils import deprecated
119

@@ -1527,168 +1525,6 @@ def _loadData(self, data):
15271525
self.title = data.attrib.get('title')
15281526

15291527

1530-
@utils.registerPlexObject
1531-
class Collections(PlexPartialObject, ArtMixin, PosterMixin, LabelMixin):
1532-
""" Represents a single Collection.
1533-
1534-
Attributes:
1535-
TAG (str): 'Directory'
1536-
TYPE (str): 'collection'
1537-
addedAt (datetime): Datetime the collection was added to the library.
1538-
art (str): URL to artwork image (/library/metadata/<ratingKey>/art/<artid>).
1539-
artBlurHash (str): BlurHash string for artwork image.
1540-
childCount (int): Number of items in the collection.
1541-
collectionMode (str): How the items in the collection are displayed.
1542-
collectionSort (str): How to sort the items in the collection.
1543-
contentRating (str) Content rating (PG-13; NR; TV-G).
1544-
fields (List<:class:`~plexapi.media.Field`>): List of field objects.
1545-
guid (str): Plex GUID for the collection (collection://XXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXX).
1546-
index (int): Plex index number for the collection.
1547-
key (str): API URL (/library/metadata/<ratingkey>).
1548-
labels (List<:class:`~plexapi.media.Label`>): List of label objects.
1549-
librarySectionID (int): :class:`~plexapi.library.LibrarySection` ID.
1550-
librarySectionKey (str): :class:`~plexapi.library.LibrarySection` key.
1551-
librarySectionTitle (str): :class:`~plexapi.library.LibrarySection` title.
1552-
maxYear (int): Maximum year for the items in the collection.
1553-
minYear (int): Minimum year for the items in the collection.
1554-
ratingKey (int): Unique key identifying the collection.
1555-
subtype (str): Media type of the items in the collection (movie, show, artist, or album).
1556-
summary (str): Summary of the collection.
1557-
thumb (str): URL to thumbnail image (/library/metadata/<ratingKey>/thumb/<thumbid>).
1558-
thumbBlurHash (str): BlurHash string for thumbnail image.
1559-
title (str): Name of the collection.
1560-
titleSort (str): Title to use when sorting (defaults to title).
1561-
type (str): 'collection'
1562-
updatedAt (datatime): Datetime the collection was updated.
1563-
"""
1564-
1565-
TAG = 'Directory'
1566-
TYPE = 'collection'
1567-
1568-
def _loadData(self, data):
1569-
self.addedAt = utils.toDatetime(data.attrib.get('addedAt'))
1570-
self.art = data.attrib.get('art')
1571-
self.artBlurHash = data.attrib.get('artBlurHash')
1572-
self.childCount = utils.cast(int, data.attrib.get('childCount'))
1573-
self.collectionMode = data.attrib.get('collectionMode')
1574-
self.collectionSort = data.attrib.get('collectionSort')
1575-
self.contentRating = data.attrib.get('contentRating')
1576-
self.fields = self.findItems(data, media.Field)
1577-
self.guid = data.attrib.get('guid')
1578-
self.index = utils.cast(int, data.attrib.get('index'))
1579-
self.key = data.attrib.get('key', '').replace('/children', '') # FIX_BUG_50
1580-
self.labels = self.findItems(data, media.Label)
1581-
self.librarySectionID = data.attrib.get('librarySectionID')
1582-
self.librarySectionKey = data.attrib.get('librarySectionKey')
1583-
self.librarySectionTitle = data.attrib.get('librarySectionTitle')
1584-
self.maxYear = utils.cast(int, data.attrib.get('maxYear'))
1585-
self.minYear = utils.cast(int, data.attrib.get('minYear'))
1586-
self.ratingKey = utils.cast(int, data.attrib.get('ratingKey'))
1587-
self.subtype = data.attrib.get('subtype')
1588-
self.summary = data.attrib.get('summary')
1589-
self.thumb = data.attrib.get('thumb')
1590-
self.thumbBlurHash = data.attrib.get('thumbBlurHash')
1591-
self.title = data.attrib.get('title')
1592-
self.titleSort = data.attrib.get('titleSort', self.title)
1593-
self.type = data.attrib.get('type')
1594-
self.updatedAt = utils.toDatetime(data.attrib.get('updatedAt'))
1595-
1596-
@property
1597-
@deprecated('use "items" instead')
1598-
def children(self):
1599-
return self.fetchItems(self.key)
1600-
1601-
@property
1602-
def thumbUrl(self):
1603-
""" Return the thumbnail url for the collection."""
1604-
return self._server.url(self.thumb, includeToken=True) if self.thumb else None
1605-
1606-
@property
1607-
def artUrl(self):
1608-
""" Return the art url for the collection."""
1609-
return self._server.url(self.art, includeToken=True) if self.art else None
1610-
1611-
def item(self, title):
1612-
""" Returns the item in the collection that matches the specified title.
1613-
1614-
Parameters:
1615-
title (str): Title of the item to return.
1616-
"""
1617-
key = '/library/metadata/%s/children' % self.ratingKey
1618-
return self.fetchItem(key, title__iexact=title)
1619-
1620-
def items(self):
1621-
""" Returns a list of all items in the collection. """
1622-
key = '/library/metadata/%s/children' % self.ratingKey
1623-
return self.fetchItems(key)
1624-
1625-
def get(self, title):
1626-
""" Alias to :func:`~plexapi.library.Collection.item`. """
1627-
return self.item(title)
1628-
1629-
def __len__(self):
1630-
return self.childCount
1631-
1632-
def _preferences(self):
1633-
""" Returns a list of :class:`~plexapi.settings.Preferences` objects. """
1634-
items = []
1635-
data = self._server.query(self._details_key)
1636-
for item in data.iter('Setting'):
1637-
items.append(Setting(data=item, server=self._server))
1638-
1639-
return items
1640-
1641-
def delete(self):
1642-
part = '/library/metadata/%s' % self.ratingKey
1643-
return self._server.query(part, method=self._server._session.delete)
1644-
1645-
def modeUpdate(self, mode=None):
1646-
""" Update Collection Mode
1647-
1648-
Parameters:
1649-
mode: default (Library default)
1650-
hide (Hide Collection)
1651-
hideItems (Hide Items in this Collection)
1652-
showItems (Show this Collection and its Items)
1653-
Example:
1654-
1655-
collection = 'plexapi.library.Collections'
1656-
collection.updateMode(mode="hide")
1657-
"""
1658-
mode_dict = {'default': '-1',
1659-
'hide': '0',
1660-
'hideItems': '1',
1661-
'showItems': '2'}
1662-
key = mode_dict.get(mode)
1663-
if key is None:
1664-
raise BadRequest('Unknown collection mode : %s. Options %s' % (mode, list(mode_dict)))
1665-
part = '/library/metadata/%s/prefs?collectionMode=%s' % (self.ratingKey, key)
1666-
return self._server.query(part, method=self._server._session.put)
1667-
1668-
def sortUpdate(self, sort=None):
1669-
""" Update Collection Sorting
1670-
1671-
Parameters:
1672-
sort: realease (Order Collection by realease dates)
1673-
alpha (Order Collection Alphabetically)
1674-
1675-
Example:
1676-
1677-
colleciton = 'plexapi.library.Collections'
1678-
collection.updateSort(mode="alpha")
1679-
"""
1680-
sort_dict = {'release': '0',
1681-
'alpha': '1'}
1682-
key = sort_dict.get(sort)
1683-
if key is None:
1684-
raise BadRequest('Unknown sort dir: %s. Options: %s' % (sort, list(sort_dict)))
1685-
part = '/library/metadata/%s/prefs?collectionSort=%s' % (self.ratingKey, key)
1686-
return self._server.query(part, method=self._server._session.put)
1687-
1688-
# def edit(self, **kwargs):
1689-
# TODO
1690-
1691-
16921528
@utils.registerPlexObject
16931529
class Path(PlexObject):
16941530
""" Represents a single directory Path.

plexapi/server.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919
from requests.status_codes import _codes as codes
2020

2121
# Need these imports to populate utils.PLEXOBJECTS
22-
from plexapi import audio as _audio # noqa: F401; noqa: F401
22+
from plexapi import audio as _audio # noqa: F401
23+
from plexapi import collection as _collection # noqa: F401
2324
from plexapi import media as _media # noqa: F401
2425
from plexapi import photo as _photo # noqa: F401
2526
from plexapi import playlist as _playlist # noqa: F401

tests/conftest.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -234,13 +234,11 @@ def movie(movies):
234234
@pytest.fixture()
235235
def collection(movies):
236236
try:
237-
return movies.collections()[0]
237+
return movies.collections(title="marvel")[0]
238238
except IndexError:
239239
movie = movies.get("Elephants Dream")
240-
movie.addCollection(["marvel"])
241-
242-
n = movies.reload()
243-
return n.collections()[0]
240+
movie.addCollection("marvel")
241+
return movies.collections(title="marvel")[0]
244242

245243

246244
@pytest.fixture()

0 commit comments

Comments
 (0)