44import re
55import weakref
66from functools import cached_property
7- from typing import (TYPE_CHECKING , Any , Callable , Dict , List , Optional , Set ,
8- Type , TypeVar , Union , cast , overload )
7+ from typing import (
8+ TYPE_CHECKING ,
9+ Any ,
10+ Callable ,
11+ Dict ,
12+ List ,
13+ Optional ,
14+ Set ,
15+ Type ,
16+ TypeVar ,
17+ Union ,
18+ cast ,
19+ overload ,
20+ )
921from urllib .parse import urlencode
1022from xml .etree import ElementTree
1123from xml .etree .ElementTree import Element
3345 'icontains' : lambda v , q : q .lower () in v .lower (),
3446 'ne' : lambda v , q : v != q ,
3547 'in' : lambda v , q : v in q ,
36- 'gt' : lambda v , q : v > q , # ? Should this be `int(v) > int(q)`?
48+ 'gt' : lambda v , q : v > q ,
3749 'gte' : lambda v , q : v >= q ,
3850 'lt' : lambda v , q : v < q ,
3951 'lte' : lambda v , q : v <= q ,
@@ -59,27 +71,7 @@ class PlexObject:
5971 TAG : Optional [str ] = None # xml element tag
6072 TYPE : Optional [str ] = None # xml element type
6173 key : Optional [str ] = None # plex relative url
62- _INCLUDES = {
63- 'checkFiles' : 1 ,
64- 'includeAllConcerts' : 1 ,
65- 'includeBandwidths' : 1 ,
66- 'includeChapters' : 1 ,
67- 'includeChildren' : 1 ,
68- 'includeConcerts' : 1 ,
69- 'includeExternalMedia' : 1 ,
70- 'includeExtras' : 1 ,
71- 'includeFields' : 'thumbBlurHash,artBlurHash' ,
72- 'includeGeolocation' : 1 ,
73- 'includeLoudnessRamps' : 1 ,
74- 'includeMarkers' : 1 ,
75- 'includeOnDeck' : 1 ,
76- 'includePopularLeaves' : 1 ,
77- 'includePreferences' : 1 ,
78- 'includeRelated' : 1 ,
79- 'includeRelatedCount' : 1 ,
80- 'includeReviews' : 1 ,
81- 'includeStations' : 1
82- }
74+ _INCLUDES : Dict [str , Any ] = {}
8375
8476 def __init__ (
8577 self ,
@@ -191,7 +183,7 @@ def _buildItemOrNone(
191183 elem : Element ,
192184 cls : Optional [Type [PlexObjectT ]] = None ,
193185 initpath : Optional [str ] = None ,
194- ):
186+ ) -> Optional [ Union [ PlexObjectT , PlexObject ]] :
195187 """ Calls :func:`~plexapi.base.PlexObject._buildItem` but returns
196188 None if elem is an unknown type.
197189 """
@@ -200,12 +192,12 @@ def _buildItemOrNone(
200192 except UnknownType :
201193 return None
202194
203- def _buildDetailsKey (self , ** kwargs : Any ):
195+ def _buildDetailsKey (self , ** kwargs : Any ) -> Optional [ str ] :
204196 """ Builds the details key with the XML include parameters.
205197 All parameters are included by default with the option to override each parameter
206198 or disable each parameter individually by setting it to False or 0.
207199 """
208- details_key = str ( self .key )
200+ details_key = self .key
209201 if details_key and hasattr (self , '_INCLUDES' ):
210202 includes = {}
211203 for k , v in self ._INCLUDES .items ():
@@ -247,7 +239,7 @@ def _manuallyLoadXML(
247239 ) -> PlexObject :
248240 ...
249241
250- def _manuallyLoadXML (self , xml : str , cls : Optional [Type [PlexObjectT ]] = None ):
242+ def _manuallyLoadXML (self , xml : str , cls : Optional [Type [PlexObjectT ]] = None ) -> Optional [ Union [ PlexObjectT , PlexObject ]] :
251243 """ Manually load an XML string as a :class:`~plexapi.base.PlexObject`.
252244
253245 Parameters:
@@ -551,7 +543,7 @@ def _reload(self, key: Optional[str] = None, _overwriteNone: bool = True, **kwar
551543 raise Unsupported ('Cannot reload an object not built from a URL.' )
552544 self ._initpath = key
553545 data = self ._server .query (key )
554- if not data :
546+ if data is None :
555547 raise NotFound (f'Unable to find elem: { key = } ' )
556548 self ._overwriteNone = _overwriteNone
557549 self ._loadData (data [0 ])
@@ -591,7 +583,7 @@ def _getAttrValue(self, elem: Element, attrstr: str, results: Optional[List[str]
591583 attrstr = parts [1 ] if len (parts ) == 2 else ""
592584 if attrstr :
593585 results = [] if results is None else results
594- for child in filter ( lambda c : c .tag .lower () == attr .lower (), elem ) :
586+ for child in [ c for c in elem if c .tag .lower () == attr .lower ()] :
595587 results += self ._getAttrValue (child , attrstr , results )
596588 return [r for r in results if r is not None ]
597589 # check were looking for the tag
@@ -630,6 +622,27 @@ class PlexPartialObject(PlexObject):
630622 and if the specified value you request is None it will fetch the full object
631623 automatically and update itself.
632624 """
625+ _INCLUDES = {
626+ 'checkFiles' : 1 ,
627+ 'includeAllConcerts' : 1 ,
628+ 'includeBandwidths' : 1 ,
629+ 'includeChapters' : 1 ,
630+ 'includeChildren' : 1 ,
631+ 'includeConcerts' : 1 ,
632+ 'includeExternalMedia' : 1 ,
633+ 'includeExtras' : 1 ,
634+ 'includeFields' : 'thumbBlurHash,artBlurHash' ,
635+ 'includeGeolocation' : 1 ,
636+ 'includeLoudnessRamps' : 1 ,
637+ 'includeMarkers' : 1 ,
638+ 'includeOnDeck' : 1 ,
639+ 'includePopularLeaves' : 1 ,
640+ 'includePreferences' : 1 ,
641+ 'includeRelated' : 1 ,
642+ 'includeRelatedCount' : 1 ,
643+ 'includeReviews' : 1 ,
644+ 'includeStations' : 1
645+ }
633646
634647 def __eq__ (self , other : Any ) -> bool :
635648 if isinstance (other , PlexPartialObject ):
@@ -1054,7 +1067,7 @@ def _reload(self, _autoReload=False, **kwargs):
10541067
10551068 def source (self ):
10561069 """ Return the source media object for the session. """
1057- return self .fetchItem (self ._details_key )
1070+ return self ._details_key and self . fetchItem (self ._details_key )
10581071
10591072 def stop (self , reason = '' ):
10601073 """ Stop playback for the session.
0 commit comments