Skip to content

Commit 78dfd6c

Browse files
committed
Remove manual cache attributes
1 parent 0d4124f commit 78dfd6c

File tree

4 files changed

+124
-108
lines changed

4 files changed

+124
-108
lines changed

plexapi/collection.py

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,6 @@ def _loadData(self, data):
104104
self.type = data.attrib.get('type')
105105
self.updatedAt = utils.toDatetime(data.attrib.get('updatedAt'))
106106
self.userRating = utils.cast(float, data.attrib.get('userRating'))
107-
self._items = None # cache for self.items
108-
self._section = None # cache for self.section
109-
self._filters = None # cache for self.filters
110107

111108
@cached_data_property
112109
def fields(self):
@@ -174,20 +171,26 @@ def isPhoto(self):
174171
def children(self):
175172
return self.items()
176173

174+
@cached_data_property
175+
def _filters(self):
176+
""" Cache for filters. """
177+
return self._parseFilters(self.content)
178+
177179
def filters(self):
178180
""" Returns the search filter dict for smart collection.
179181
The filter dict be passed back into :func:`~plexapi.library.LibrarySection.search`
180182
to get the list of items.
181183
"""
182-
if self.smart and self._filters is None:
183-
self._filters = self._parseFilters(self.content)
184184
return self._filters
185185

186+
@cached_data_property
187+
def _section(self):
188+
""" Cache for section. """
189+
return super(Collection, self).section()
190+
186191
def section(self):
187192
""" Returns the :class:`~plexapi.library.LibrarySection` this collection belongs to.
188193
"""
189-
if self._section is None:
190-
self._section = super(Collection, self).section()
191194
return self._section
192195

193196
def item(self, title):
@@ -204,12 +207,14 @@ def item(self, title):
204207
return item
205208
raise NotFound(f'Item with title "{title}" not found in the collection')
206209

210+
@cached_data_property
211+
def _items(self):
212+
""" Cache for the items. """
213+
key = f'{self.key}/children'
214+
return self.fetchItems(key)
215+
207216
def items(self):
208217
""" Returns a list of all items in the collection. """
209-
if self._items is None:
210-
key = f'{self.key}/children'
211-
items = self.fetchItems(key)
212-
self._items = items
213218
return self._items
214219

215220
def visibility(self):

plexapi/library.py

Lines changed: 42 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
import warnings
77
from collections import defaultdict
88
from datetime import datetime
9-
from functools import cached_property
109
from urllib.parse import parse_qs, quote_plus, urlencode, urlparse
1110

1211
from plexapi import log, media, utils
@@ -44,9 +43,8 @@ def _loadData(self, data):
4443
self.mediaTagVersion = data.attrib.get('mediaTagVersion')
4544
self.title1 = data.attrib.get('title1')
4645
self.title2 = data.attrib.get('title2')
47-
self._sectionsByID = {} # cached sections by key
48-
self._sectionsByTitle = {} # cached sections by title
4946

47+
@cached_data_property
5048
def _loadSections(self):
5149
""" Loads and caches all the library sections. """
5250
key = '/library/sections'
@@ -64,15 +62,23 @@ def _loadSections(self):
6462
sectionsByID[section.key] = section
6563
sectionsByTitle[section.title.lower().strip()].append(section)
6664

67-
self._sectionsByID = sectionsByID
68-
self._sectionsByTitle = dict(sectionsByTitle)
65+
return sectionsByID, dict(sectionsByTitle)
66+
67+
@property
68+
def _sectionsByID(self):
69+
""" Returns a dictionary of all library sections by ID. """
70+
return self._loadSections[0]
71+
72+
@property
73+
def _sectionsByTitle(self):
74+
""" Returns a dictionary of all library sections by title. """
75+
return self._loadSections[1]
6976

7077
def sections(self):
7178
""" Returns a list of all media sections in this library. Library sections may be any of
7279
:class:`~plexapi.library.MovieSection`, :class:`~plexapi.library.ShowSection`,
7380
:class:`~plexapi.library.MusicSection`, :class:`~plexapi.library.PhotoSection`.
7481
"""
75-
self._loadSections()
7682
return list(self._sectionsByID.values())
7783

7884
def section(self, title):
@@ -87,8 +93,6 @@ def section(self, title):
8793
:exc:`~plexapi.exceptions.NotFound`: The library section title is not found on the server.
8894
"""
8995
normalized_title = title.lower().strip()
90-
if not self._sectionsByTitle or normalized_title not in self._sectionsByTitle:
91-
self._loadSections()
9296
try:
9397
sections = self._sectionsByTitle[normalized_title]
9498
except KeyError:
@@ -110,8 +114,6 @@ def sectionByID(self, sectionID):
110114
Raises:
111115
:exc:`~plexapi.exceptions.NotFound`: The library section ID is not found on the server.
112116
"""
113-
if not self._sectionsByID or sectionID not in self._sectionsByID:
114-
self._loadSections()
115117
try:
116118
return self._sectionsByID[sectionID]
117119
except KeyError:
@@ -448,35 +450,25 @@ def _loadData(self, data):
448450
self.type = data.attrib.get('type')
449451
self.updatedAt = utils.toDatetime(data.attrib.get('updatedAt'))
450452
self.uuid = data.attrib.get('uuid')
451-
# Private attrs as we don't want a reload.
452-
self._filterTypes = None
453-
self._fieldTypes = None
454-
self._totalViewSize = None
455-
self._totalDuration = None
456-
self._totalStorage = None
457453

458454
@cached_data_property
459455
def locations(self):
460456
return self.listAttrs(self._data, 'path', etag='Location')
461457

462-
@cached_property
458+
@cached_data_property
463459
def totalSize(self):
464460
""" Returns the total number of items in the library for the default library type. """
465461
return self.totalViewSize(includeCollections=False)
466462

467463
@property
468464
def totalDuration(self):
469465
""" Returns the total duration (in milliseconds) of items in the library. """
470-
if self._totalDuration is None:
471-
self._getTotalDurationStorage()
472-
return self._totalDuration
466+
return self._getTotalDurationStorage[0]
473467

474468
@property
475469
def totalStorage(self):
476470
""" Returns the total storage (in bytes) of items in the library. """
477-
if self._totalStorage is None:
478-
self._getTotalDurationStorage()
479-
return self._totalStorage
471+
return self._getTotalDurationStorage[1]
480472

481473
def __getattribute__(self, attr):
482474
# Intercept to call EditFieldMixin and EditTagMixin methods
@@ -492,6 +484,7 @@ def __getattribute__(self, attr):
492484
)
493485
return value
494486

487+
@cached_data_property
495488
def _getTotalDurationStorage(self):
496489
""" Queries the Plex server for the total library duration and storage and caches the values. """
497490
data = self._server.query('/media/providers?includeStorage=1')
@@ -502,8 +495,10 @@ def _getTotalDurationStorage(self):
502495
)
503496
directory = next(iter(data.findall(xpath)), None)
504497
if directory:
505-
self._totalDuration = utils.cast(int, directory.attrib.get('durationTotal'))
506-
self._totalStorage = utils.cast(int, directory.attrib.get('storageTotal'))
498+
totalDuration = utils.cast(int, directory.attrib.get('durationTotal'))
499+
totalStorage = utils.cast(int, directory.attrib.get('storageTotal'))
500+
return totalDuration, totalStorage
501+
return None, None
507502

508503
def totalViewSize(self, libtype=None, includeCollections=True):
509504
""" Returns the total number of items in the library for a specified libtype.
@@ -875,6 +870,7 @@ def deleteMediaPreviews(self):
875870
self._server.query(key, method=self._server._session.delete)
876871
return self
877872

873+
@cached_data_property
878874
def _loadFilters(self):
879875
""" Retrieves and caches the list of :class:`~plexapi.library.FilteringType` and
880876
list of :class:`~plexapi.library.FilteringFieldType` for this library section.
@@ -884,23 +880,23 @@ def _loadFilters(self):
884880

885881
key = _key.format(key=self.key, filter='all')
886882
data = self._server.query(key)
887-
self._filterTypes = self.findItems(data, FilteringType, rtag='Meta')
888-
self._fieldTypes = self.findItems(data, FilteringFieldType, rtag='Meta')
883+
filterTypes = self.findItems(data, FilteringType, rtag='Meta')
884+
fieldTypes = self.findItems(data, FilteringFieldType, rtag='Meta')
889885

890886
if self.TYPE != 'photo': # No collections for photo library
891887
key = _key.format(key=self.key, filter='collections')
892888
data = self._server.query(key)
893-
self._filterTypes.extend(self.findItems(data, FilteringType, rtag='Meta'))
889+
filterTypes.extend(self.findItems(data, FilteringType, rtag='Meta'))
894890

895891
# Manually add guid field type, only allowing "is" operator
896892
guidFieldType = '<FieldType type="guid"><Operator key="=" title="is"/></FieldType>'
897-
self._fieldTypes.append(self._manuallyLoadXML(guidFieldType, FilteringFieldType))
893+
fieldTypes.append(self._manuallyLoadXML(guidFieldType, FilteringFieldType))
894+
895+
return filterTypes, fieldTypes
898896

899897
def filterTypes(self):
900898
""" Returns a list of available :class:`~plexapi.library.FilteringType` for this library section. """
901-
if self._filterTypes is None:
902-
self._loadFilters()
903-
return self._filterTypes
899+
return self._loadFilters[0]
904900

905901
def getFilterType(self, libtype=None):
906902
""" Returns a :class:`~plexapi.library.FilteringType` for a specified libtype.
@@ -922,9 +918,7 @@ def getFilterType(self, libtype=None):
922918

923919
def fieldTypes(self):
924920
""" Returns a list of available :class:`~plexapi.library.FilteringFieldType` for this library section. """
925-
if self._fieldTypes is None:
926-
self._loadFilters()
927-
return self._fieldTypes
921+
return self._loadFilters[1]
928922

929923
def getFieldType(self, fieldType):
930924
""" Returns a :class:`~plexapi.library.FilteringFieldType` for a specified fieldType.
@@ -2233,10 +2227,13 @@ def _loadData(self, data):
22332227
self.style = data.attrib.get('style')
22342228
self.title = data.attrib.get('title')
22352229
self.type = data.attrib.get('type')
2236-
self._section = None # cache for self.section
2230+
2231+
def __len__(self):
2232+
return self.size
22372233

22382234
@cached_data_property
2239-
def items(self):
2235+
def _items(self):
2236+
""" Cache for items. """
22402237
if self.more and self.key: # If there are more items to load, fetch them
22412238
items = self.fetchItems(self.key)
22422239
self.more = False
@@ -2245,8 +2242,9 @@ def items(self):
22452242
# Otherwise, all the data is in the initial _data XML response
22462243
return self.findItems(self._data)
22472244

2248-
def __len__(self):
2249-
return self.size
2245+
def items(self):
2246+
""" Returns a list of all items in the hub. """
2247+
return self._items
22502248

22512249
def reload(self):
22522250
""" Delete cached data to allow reloading of hub items. """
@@ -2255,11 +2253,14 @@ def reload(self):
22552253
self.more = utils.cast(bool, self._data.attrib.get('more'))
22562254
self.size = utils.cast(int, self._data.attrib.get('size'))
22572255

2256+
@cached_data_property
2257+
def _section(self):
2258+
""" Cache for section. """
2259+
return self._server.library.sectionByID(self.librarySectionID)
2260+
22582261
def section(self):
22592262
""" Returns the :class:`~plexapi.library.LibrarySection` this hub belongs to.
22602263
"""
2261-
if self._section is None:
2262-
self._section = self._server.library.sectionByID(self.librarySectionID)
22632264
return self._section
22642265

22652266

0 commit comments

Comments
 (0)