@@ -59,7 +59,7 @@ def __init__(self, server, data, initpath=None, parent=None):
5959 def __repr__ (self ):
6060 uid = self ._clean (self .firstAttr ('_baseurl' , 'ratingKey' , 'id' , 'key' , 'playQueueID' , 'uri' ))
6161 name = self ._clean (self .firstAttr ('title' , 'name' , 'username' , 'product' , 'tag' , 'value' ))
62- return '<%s>' % ' :' .join ([p for p in [self .__class__ .__name__ , uid , name ] if p ])
62+ return f"< { ' :' .join ([p for p in [self .__class__ .__name__ , uid , name ] if p ])} >"
6363
6464 def __setattr__ (self , attr , value ):
6565 overwriteNone = self .__dict__ .get ('_overwriteNone' )
@@ -84,14 +84,14 @@ def _buildItem(self, elem, cls=None, initpath=None):
8484 return cls (self ._server , elem , initpath , parent = self )
8585 # cls is not specified, try looking it up in PLEXOBJECTS
8686 etype = elem .attrib .get ('streamType' , elem .attrib .get ('tagType' , elem .attrib .get ('type' )))
87- ehash = '%s.%s' % ( elem .tag , etype ) if etype else elem .tag
87+ ehash = f' { elem .tag } . { etype } ' if etype else elem .tag
8888 if initpath == '/status/sessions' :
89- ehash = '%s.%s' % ( ehash , ' session')
89+ ehash = f" { ehash } . { ' session'} "
9090 ecls = utils .PLEXOBJECTS .get (ehash , utils .PLEXOBJECTS .get (elem .tag ))
9191 # log.debug('Building %s as %s', elem.tag, ecls.__name__)
9292 if ecls is not None :
9393 return ecls (self ._server , elem , initpath )
94- raise UnknownType ("Unknown library type <%s type='%s '../>" % ( elem . tag , etype ) )
94+ raise UnknownType (f "Unknown library type <{ elem . tag } type='{ etype } '../>" )
9595
9696 def _buildItemOrNone (self , elem , cls = None , initpath = None ):
9797 """ Calls :func:`~plexapi.base.PlexObject._buildItem` but returns
@@ -167,7 +167,7 @@ def fetchItem(self, ekey, cls=None, **kwargs):
167167 if ekey is None :
168168 raise BadRequest ('ekey was not provided' )
169169 if isinstance (ekey , int ):
170- ekey = '/library/metadata/%s' % ekey
170+ ekey = f '/library/metadata/{ ekey } '
171171
172172 data = self ._server .query (ekey )
173173 item = self .findItem (data , cls , ekey , ** kwargs )
@@ -179,7 +179,7 @@ def fetchItem(self, ekey, cls=None, **kwargs):
179179 return item
180180
181181 clsname = cls .__name__ if cls else 'None'
182- raise NotFound ('Unable to find elem: cls=%s , attrs=%s' % ( clsname , kwargs ) )
182+ raise NotFound (f 'Unable to find elem: cls={ clsname } , attrs={ kwargs } ' )
183183
184184 def fetchItems (self , ekey , cls = None , container_start = None , container_size = None , ** kwargs ):
185185 """ Load the specified key to find and build all items with the specified tag
@@ -328,7 +328,7 @@ def listAttrs(self, data, attr, rtag=None, **kwargs):
328328 if rtag :
329329 data = next (utils .iterXMLBFS (data , rtag ), [])
330330 for elem in data :
331- kwargs ['%s__exists' % attr ] = True
331+ kwargs [f' { attr } __exists' ] = True
332332 if self ._checkAttrs (elem , ** kwargs ):
333333 results .append (elem .attrib .get (attr ))
334334 return results
@@ -399,7 +399,7 @@ def _checkAttrs(self, elem, **kwargs):
399399
400400 def _getAttrOperator (self , attr ):
401401 for op , operator in OPERATORS .items ():
402- if attr .endswith ('__%s' % op ):
402+ if attr .endswith (f '__{ op } ' ):
403403 attr = attr .rsplit ('__' , 1 )[0 ]
404404 return attr , op , operator
405405 # default to exact match
@@ -496,7 +496,7 @@ def __getattribute__(self, attr):
496496 # Log the reload.
497497 clsname = self .__class__ .__name__
498498 title = self .__dict__ .get ('title' , self .__dict__ .get ('name' ))
499- objname = "%s '%s'" % ( clsname , title ) if title else clsname
499+ objname = f" { clsname } ' { title } '" if title else clsname
500500 log .debug ("Reloading %s for attr '%s'" , objname , attr )
501501 # Reload and return the value
502502 self ._reload (_overwriteNone = False )
@@ -521,7 +521,7 @@ def analyze(self):
521521 * Generate intro video markers: Detects show intros, exposing the
522522 'Skip Intro' button in clients.
523523 """
524- key = '/%s/analyze' % self .key .lstrip ('/' )
524+ key = f"/ { self .key .lstrip ('/' )} /analyze"
525525 self ._server .query (key , method = self ._server ._session .put )
526526
527527 def isFullObject (self ):
@@ -547,8 +547,7 @@ def _edit(self, **kwargs):
547547 if 'type' not in kwargs :
548548 kwargs ['type' ] = utils .searchType (self ._searchType )
549549
550- part = '/library/sections/%s/all%s' % (self .librarySectionID ,
551- utils .joinArgs (kwargs ))
550+ part = f'/library/sections/{ self .librarySectionID } /all{ utils .joinArgs (kwargs )} '
552551 self ._server .query (part , method = self ._server ._session .put )
553552 return self
554553
@@ -627,7 +626,7 @@ def refresh(self):
627626 the refresh process is interrupted (the Server is turned off, internet
628627 connection dies, etc).
629628 """
630- key = '%s/refresh' % self .key
629+ key = f' { self .key } /refresh'
631630 self ._server .query (key , method = self ._server ._session .put )
632631
633632 def section (self ):
@@ -700,7 +699,7 @@ def getStreamURL(self, **params):
700699 :exc:`~plexapi.exceptions.Unsupported`: When the item doesn't support fetching a stream URL.
701700 """
702701 if self .TYPE not in ('movie' , 'episode' , 'track' , 'clip' ):
703- raise Unsupported ('Fetching stream URL for %s is unsupported.' % self . TYPE )
702+ raise Unsupported (f 'Fetching stream URL for { self . TYPE } is unsupported.' )
704703 mvb = params .get ('maxVideoBitrate' )
705704 vr = params .get ('videoResolution' , '' )
706705 params = {
@@ -718,8 +717,10 @@ def getStreamURL(self, **params):
718717 streamtype = 'audio' if self .TYPE in ('track' , 'album' ) else 'video'
719718 # sort the keys since the randomness fucks with my tests..
720719 sorted_params = sorted (params .items (), key = lambda val : val [0 ])
721- return self ._server .url ('/%s/:/transcode/universal/start.m3u8?%s' %
722- (streamtype , urlencode (sorted_params )), includeToken = True )
720+ return self ._server .url (
721+ f'/{ streamtype } /:/transcode/universal/start.m3u8?{ urlencode (sorted_params )} ' ,
722+ includeToken = True
723+ )
723724
724725 def iterParts (self ):
725726 """ Iterates over the parts of this media item. """
@@ -759,15 +760,15 @@ def download(self, savepath=None, keep_original_name=False, **kwargs):
759760
760761 for part in parts :
761762 if not keep_original_name :
762- filename = utils .cleanFilename ('%s.%s' % ( self ._prettyfilename (), part .container ) )
763+ filename = utils .cleanFilename (f' { self ._prettyfilename ()} . { part .container } ' )
763764 else :
764765 filename = part .file
765766
766767 if kwargs :
767768 # So this seems to be a a lot slower but allows transcode.
768769 download_url = self .getStreamURL (** kwargs )
769770 else :
770- download_url = self ._server .url ('%s ?download=1' % part . key )
771+ download_url = self ._server .url (f' { part . key } ?download=1' )
771772
772773 filepath = utils .download (
773774 download_url ,
@@ -794,8 +795,7 @@ def updateProgress(self, time, state='stopped'):
794795 time (int): milliseconds watched
795796 state (string): state of the video, default 'stopped'
796797 """
797- key = '/:/progress?key=%s&identifier=com.plexapp.plugins.library&time=%d&state=%s' % (self .ratingKey ,
798- time , state )
798+ key = f'/:/progress?key={ self .ratingKey } &identifier=com.plexapp.plugins.library&time={ time } &state={ state } '
799799 self ._server .query (key )
800800 self ._reload (_overwriteNone = False )
801801
0 commit comments