From ca8ad96a053bc233418df94166780b0f3926ce5b Mon Sep 17 00:00:00 2001 From: croneter Date: Sun, 11 Feb 2018 12:59:04 +0100 Subject: [PATCH] Prettify --- default.py | 4 +- resources/lib/PlexAPI.py | 24 +- resources/lib/PlexFunctions.py | 8 +- resources/lib/artwork.py | 20 +- resources/lib/entrypoint.py | 28 +- resources/lib/initialsetup.py | 10 +- resources/lib/itemtypes.py | 10 +- resources/lib/kodidb_functions.py | 4 +- resources/lib/librarysync.py | 46 ++-- resources/lib/loghandler.py | 4 +- resources/lib/playback.py | 10 +- resources/lib/playlist_func.py | 6 +- resources/lib/playutils.py | 8 +- resources/lib/plex_tv.py | 4 +- resources/lib/plexdb_functions.py | 4 +- resources/lib/utils.py | 429 +++++++++++++----------------- resources/lib/variables.py | 16 +- resources/lib/videonodes.py | 26 +- resources/lib/websocket.py | 2 +- 19 files changed, 301 insertions(+), 362 deletions(-) diff --git a/default.py b/default.py index ec25242f..2da11307 100644 --- a/default.py +++ b/default.py @@ -32,7 +32,7 @@ sys_path.append(_base_resource) ############################################################################### import entrypoint -from utils import window, reset, passwordsXML, language as lang, dialog, \ +from utils import window, reset, passwords_xml, language as lang, dialog, \ plex_command from pickler import unpickle_me, pickl_window from PKC_listitem import convert_PKC_to_listitem @@ -115,7 +115,7 @@ class Main(): entrypoint.resetAuth() elif mode == 'passwords': - passwordsXML() + passwords_xml() elif mode == 'switchuser': entrypoint.switchPlexUser() diff --git a/resources/lib/PlexAPI.py b/resources/lib/PlexAPI.py index f8d33038..513e9e75 100644 --- a/resources/lib/PlexAPI.py +++ b/resources/lib/PlexAPI.py @@ -40,8 +40,8 @@ from xbmcvfs import exists import clientinfo as client from downloadutils import DownloadUtils as DU -from utils import window, settings, language as lang, tryDecode, tryEncode, \ - DateToKodi, exists_dir, slugify, dialog +from utils import window, settings, language as lang, try_decode, try_encode, \ + unix_date_to_kodi, exists_dir, slugify, dialog import PlexFunctions as PF import plexdb_functions as plexdb import variables as v @@ -139,7 +139,7 @@ class API(): ans = None if ans is not None: try: - ans = tryDecode(unquote(ans)) + ans = try_decode(unquote(ans)) except UnicodeDecodeError: # Sometimes, Plex seems to have encoded in latin1 ans = unquote(ans).decode('latin1') @@ -167,7 +167,7 @@ class API(): self.item[0][0].attrib['key'])) # Attach Plex id to url to let it be picked up by our playqueue agent # later - return tryEncode('%s&plex_id=%s' % (path, self.getRatingKey())) + return try_encode('%s&plex_id=%s' % (path, self.getRatingKey())) def getTVShowPath(self): """ @@ -194,7 +194,7 @@ class API(): """ res = self.item.attrib.get('addedAt') if res is not None: - res = DateToKodi(res) + res = unix_date_to_kodi(res) else: res = '2000-01-01 10:00:00' return res @@ -231,7 +231,7 @@ class API(): played = True if playcount else False try: - lastPlayedDate = DateToKodi(int(item['lastViewedAt'])) + lastPlayedDate = unix_date_to_kodi(int(item['lastViewedAt'])) except (KeyError, ValueError): lastPlayedDate = None @@ -884,7 +884,7 @@ class API(): parameters = { 'api_key': apiKey, 'language': v.KODILANGUAGE, - 'query': tryEncode(title) + 'query': try_encode(title) } data = DU().downloadUrl(url, authenticate=False, @@ -1196,12 +1196,12 @@ class API(): languages.append(stream.attrib['language']) languages = ', '.join(languages) if filename: - option = tryEncode(filename) + option = try_encode(filename) if languages: if option: - option = '%s (%s): ' % (option, tryEncode(languages)) + option = '%s (%s): ' % (option, try_encode(languages)) else: - option = '%s: ' % tryEncode(languages) + option = '%s: ' % try_encode(languages) if 'videoResolution' in entry.attrib: option = '%s%sp ' % (option, entry.attrib.get('videoResolution')) @@ -1544,7 +1544,7 @@ class API(): # exist() needs a / or \ at the end to work for directories if folder is False: # files - check = exists(tryEncode(path)) + check = exists(try_encode(path)) else: # directories if "\\" in path: @@ -1640,7 +1640,7 @@ class API(): plexitem = "plex_%s" % playurl window('%s.runtime' % plexitem, value=str(userdata['Runtime'])) window('%s.type' % plexitem, value=itemtype) - state.PLEX_IDS[tryDecode(playurl)] = self.getRatingKey() + state.PLEX_IDS[try_decode(playurl)] = self.getRatingKey() # window('%s.itemid' % plexitem, value=self.getRatingKey()) window('%s.playcount' % plexitem, value=str(userdata['PlayCount'])) diff --git a/resources/lib/PlexFunctions.py b/resources/lib/PlexFunctions.py index 3bf7d197..1cbebb88 100644 --- a/resources/lib/PlexFunctions.py +++ b/resources/lib/PlexFunctions.py @@ -11,7 +11,7 @@ from threading import Thread from xbmc import sleep from downloadutils import DownloadUtils as DU -from utils import settings, tryEncode, tryDecode +from utils import settings, try_encode, try_decode from variables import PLEX_TO_KODI_TIMEFACTOR import plex_tv @@ -306,11 +306,11 @@ def _plex_gdm(): } for line in response['data'].split('\n'): if 'Content-Type:' in line: - pms['product'] = tryDecode(line.split(':')[1].strip()) + pms['product'] = try_decode(line.split(':')[1].strip()) elif 'Host:' in line: pms['baseURL'] = line.split(':')[1].strip() elif 'Name:' in line: - pms['name'] = tryDecode(line.split(':')[1].strip()) + pms['name'] = try_decode(line.split(':')[1].strip()) elif 'Port:' in line: pms['port'] = line.split(':')[1].strip() elif 'Resource-Identifier:' in line: @@ -820,7 +820,7 @@ def transcode_image_path(key, AuthToken, path, width, height): path = 'http://127.0.0.1:32400' + key else: # internal path, add-on path = 'http://127.0.0.1:32400' + path + '/' + key - path = tryEncode(path) + path = try_encode(path) # This is bogus (note the extra path component) but ATV is stupid when it # comes to caching images, it doesn't use querystrings. Fortunately PMS is # lenient... diff --git a/resources/lib/artwork.py b/resources/lib/artwork.py index 61768b04..a7d2466d 100644 --- a/resources/lib/artwork.py +++ b/resources/lib/artwork.py @@ -12,8 +12,8 @@ import requests from xbmc import sleep, translatePath from xbmcvfs import exists -from utils import window, settings, language as lang, kodiSQL, tryEncode, \ - thread_methods, dialog, exists_dir, tryDecode +from utils import window, settings, language as lang, kodi_sql, try_encode, \ + thread_methods, dialog, exists_dir, try_decode import state # Disable annoying requests warnings @@ -134,13 +134,13 @@ class Artwork(): if dialog('yesno', "Image Texture Cache", lang(39251)): LOG.info("Resetting all cache data first") # Remove all existing textures first - path = tryDecode(translatePath("special://thumbnails/")) + path = try_decode(translatePath("special://thumbnails/")) if exists_dir(path): rmtree(path, ignore_errors=True) self.restoreCacheDirectories() # remove all existing data from texture DB - connection = kodiSQL('texture') + connection = kodi_sql('texture') cursor = connection.cursor() query = 'SELECT tbl_name FROM sqlite_master WHERE type=?' cursor.execute(query, ('table', )) @@ -153,7 +153,7 @@ class Artwork(): connection.close() # Cache all entries in video DB - connection = kodiSQL('video') + connection = kodi_sql('video') cursor = connection.cursor() # dont include actors query = "SELECT url FROM art WHERE media_type != ?" @@ -166,7 +166,7 @@ class Artwork(): for url in result: self.cacheTexture(url[0]) # Cache all entries in music DB - connection = kodiSQL('music') + connection = kodi_sql('music') cursor = connection.cursor() cursor.execute("SELECT url FROM art") result = cursor.fetchall() @@ -179,7 +179,7 @@ class Artwork(): def cacheTexture(self, url): # Cache a single image url to the texture cache if url and self.enableTextureCache: - self.queue.put(double_urlencode(tryEncode(url))) + self.queue.put(double_urlencode(try_encode(url))) def addArtwork(self, artwork, kodiId, mediaType, cursor): # Kodi conversion table @@ -323,7 +323,7 @@ class Artwork(): def deleteCachedArtwork(self, url): # Only necessary to remove and apply a new backdrop or poster - connection = kodiSQL('texture') + connection = kodi_sql('texture') cursor = connection.cursor() try: cursor.execute("SELECT cachedurl FROM texture WHERE url = ?", @@ -336,7 +336,7 @@ class Artwork(): path = translatePath("special://thumbnails/%s" % cachedurl) LOG.debug("Deleting cached thumbnail: %s" % path) if exists(path): - rmtree(tryDecode(path), ignore_errors=True) + rmtree(try_decode(path), ignore_errors=True) cursor.execute("DELETE FROM texture WHERE url = ?", (url,)) connection.commit() finally: @@ -347,4 +347,4 @@ class Artwork(): LOG.info("Restoring cache directories...") paths = ("","0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f","Video","plex") for p in paths: - makedirs(tryDecode(translatePath("special://thumbnails/%s" % p))) + makedirs(try_decode(translatePath("special://thumbnails/%s" % p))) diff --git a/resources/lib/entrypoint.py b/resources/lib/entrypoint.py index 4268f622..619801f6 100644 --- a/resources/lib/entrypoint.py +++ b/resources/lib/entrypoint.py @@ -11,8 +11,8 @@ import xbmcplugin from xbmc import sleep, executebuiltin, translatePath from xbmcgui import ListItem -from utils import window, settings, language as lang, dialog, tryEncode, \ - CatchExceptions, exists_dir, plex_command, tryDecode +from utils import window, settings, language as lang, dialog, try_encode, \ + CatchExceptions, exists_dir, plex_command, try_decode import downloadutils from PlexFunctions import GetPlexMetadata, GetPlexSectionResults, \ @@ -53,11 +53,11 @@ def chooseServer(): if not __LogOut(): return - from utils import deletePlaylists, deleteNodes + from utils import delete_playlists, delete_nodes # First remove playlists - deletePlaylists() + delete_playlists() # Remove video nodes - deleteNodes() + delete_nodes() # Log in again __LogIn() @@ -175,10 +175,10 @@ def switchPlexUser(): return # First remove playlists of old user - from utils import deletePlaylists, deleteNodes - deletePlaylists() + from utils import delete_playlists, delete_nodes + delete_playlists() # Remove video nodes - deleteNodes() + delete_nodes() __LogIn() @@ -455,14 +455,14 @@ def getVideoFiles(plexId, params): if exists_dir(path): for root, dirs, files in walk(path): for directory in dirs: - item_path = tryEncode(join(root, directory)) + item_path = try_encode(join(root, directory)) li = ListItem(item_path, path=item_path) xbmcplugin.addDirectoryItem(handle=HANDLE, url=item_path, listitem=li, isFolder=True) for file in files: - item_path = tryEncode(join(root, file)) + item_path = try_encode(join(root, file)) li = ListItem(item_path, path=item_path) xbmcplugin.addDirectoryItem(handle=HANDLE, url=file, @@ -490,7 +490,7 @@ def getExtraFanArt(plexid, plexPath): # We need to store the images locally for this to work # because of the caching system in xbmc - fanartDir = tryDecode(translatePath( + fanartDir = try_decode(translatePath( "special://thumbnails/plex/%s/" % plexid)) if not exists_dir(fanartDir): # Download the images to the cache directory @@ -504,19 +504,19 @@ def getExtraFanArt(plexid, plexPath): backdrops = api.getAllArtwork()['Backdrop'] for count, backdrop in enumerate(backdrops): # Same ordering as in artwork - fanartFile = tryEncode(join(fanartDir, "fanart%.3d.jpg" % count)) + fanartFile = try_encode(join(fanartDir, "fanart%.3d.jpg" % count)) li = ListItem("%.3d" % count, path=fanartFile) xbmcplugin.addDirectoryItem( handle=HANDLE, url=fanartFile, listitem=li) - copyfile(backdrop, tryDecode(fanartFile)) + copyfile(backdrop, try_decode(fanartFile)) else: log.info("Found cached backdrop.") # Use existing cached images for root, dirs, files in walk(fanartDir): for file in files: - fanartFile = tryEncode(join(root, file)) + fanartFile = try_encode(join(root, file)) li = ListItem(file, path=fanartFile) xbmcplugin.addDirectoryItem(handle=HANDLE, url=fanartFile, diff --git a/resources/lib/initialsetup.py b/resources/lib/initialsetup.py index 517ec811..bd756f6b 100644 --- a/resources/lib/initialsetup.py +++ b/resources/lib/initialsetup.py @@ -6,7 +6,7 @@ import xml.etree.ElementTree as etree from xbmc import executebuiltin, translatePath -from utils import settings, window, language as lang, tryEncode, tryDecode, \ +from utils import settings, window, language as lang, try_encode, try_decode, \ XmlKodiSetting, reboot_kodi, dialog from migration import check_migration from downloadutils import DownloadUtils as DU @@ -76,7 +76,7 @@ def reload_pkc(): set_webserver() # To detect Kodi profile switches window('plex_kodiProfile', - value=tryDecode(translatePath("special://profile"))) + value=try_decode(translatePath("special://profile"))) getDeviceId() # Initialize the PKC playqueues PQ.init_playqueues() @@ -355,7 +355,7 @@ class InitialSetup(object): dialog('ok', lang(29999), '%s %s' % (lang(39214), - tryEncode(server['name']))) + try_encode(server['name']))) return else: return @@ -610,8 +610,8 @@ class InitialSetup(object): line1=lang(39029), line2=lang(39030)): LOG.debug("Presenting network credentials dialog.") - from utils import passwordsXML - passwordsXML() + from utils import passwords_xml + passwords_xml() # Disable Plex music? if dialog('yesno', heading=lang(29999), line1=lang(39016)): LOG.debug("User opted to disable Plex music library.") diff --git a/resources/lib/itemtypes.py b/resources/lib/itemtypes.py index b7c5307b..25414cb4 100644 --- a/resources/lib/itemtypes.py +++ b/resources/lib/itemtypes.py @@ -6,7 +6,7 @@ from ntpath import dirname from datetime import datetime from artwork import Artwork -from utils import window, kodiSQL, CatchExceptions +from utils import window, kodi_sql, CatchExceptions import plexdb_functions as plexdb import kodidb_functions as kodidb @@ -43,9 +43,9 @@ class Items(object): """ Open DB connections and cursors """ - self.plexconn = kodiSQL('plex') + self.plexconn = kodi_sql('plex') self.plexcursor = self.plexconn.cursor() - self.kodiconn = kodiSQL('video') + self.kodiconn = kodi_sql('video') self.kodicursor = self.kodiconn.cursor() self.plex_db = plexdb.Plex_DB_Functions(self.plexcursor) self.kodi_db = kodidb.Kodidb_Functions(self.kodicursor) @@ -1273,10 +1273,10 @@ class Music(Items): OVERWRITE this method, because we need to open another DB. Open DB connections and cursors """ - self.plexconn = kodiSQL('plex') + self.plexconn = kodi_sql('plex') self.plexcursor = self.plexconn.cursor() # Here it is, not 'video' but 'music' - self.kodiconn = kodiSQL('music') + self.kodiconn = kodi_sql('music') self.kodicursor = self.kodiconn.cursor() self.plex_db = plexdb.Plex_DB_Functions(self.plexcursor) self.kodi_db = kodidb.Kodidb_Functions(self.kodicursor) diff --git a/resources/lib/kodidb_functions.py b/resources/lib/kodidb_functions.py index 4b8b1d87..5390c8e6 100644 --- a/resources/lib/kodidb_functions.py +++ b/resources/lib/kodidb_functions.py @@ -5,7 +5,7 @@ from logging import getLogger from ntpath import dirname import artwork -from utils import kodiSQL +from utils import kodi_sql import variables as v ############################################################################### @@ -30,7 +30,7 @@ class GetKodiDB(): self.db_type = db_type def __enter__(self): - self.kodiconn = kodiSQL(self.db_type) + self.kodiconn = kodi_sql(self.db_type) kodi_db = Kodidb_Functions(self.kodiconn.cursor()) return kodi_db diff --git a/resources/lib/librarysync.py b/resources/lib/librarysync.py index 55983170..150fa594 100644 --- a/resources/lib/librarysync.py +++ b/resources/lib/librarysync.py @@ -8,10 +8,10 @@ from random import shuffle import xbmc from xbmcvfs import exists -from utils import window, settings, getUnixTimestamp, \ - thread_methods, create_actor_db_index, dialog, LogTime, playlistXSP,\ - language as lang, DateToKodi, reset, tryDecode, deletePlaylists, \ - deleteNodes, tryEncode, compare_version +from utils import window, settings, unix_timestamp, thread_methods, \ + create_actor_db_index, dialog, LogTime, playlist_xsp, language as lang, \ + unix_date_to_kodi, reset, try_decode, delete_playlists, delete_nodes, \ + try_encode, compare_version import downloadutils import itemtypes import plexdb_functions as plexdb @@ -155,7 +155,7 @@ class LibrarySync(Thread): log.debug('No timestamp; using 0') # Set the timer - koditime = getUnixTimestamp() + koditime = unix_timestamp() # Toggle watched state scrobble(plexId, 'watched') # Let the PMS process this first! @@ -329,7 +329,7 @@ class LibrarySync(Thread): # Create playlist for the video library if (foldername not in playlists and mediatype in (v.PLEX_TYPE_MOVIE, v.PLEX_TYPE_SHOW)): - playlistXSP(mediatype, foldername, folderid, viewtype) + playlist_xsp(mediatype, foldername, folderid, viewtype) playlists.append(foldername) # Create the video node if (foldername not in nodes and @@ -371,7 +371,7 @@ class LibrarySync(Thread): # The tag could be a combined view. Ensure there's # no other tags with the same name before deleting # playlist. - playlistXSP(mediatype, + playlist_xsp(mediatype, current_viewname, folderid, current_viewtype, @@ -388,7 +388,7 @@ class LibrarySync(Thread): # Added new playlist if (foldername not in playlists and mediatype in (v.PLEX_TYPE_MOVIE, v.PLEX_TYPE_SHOW)): - playlistXSP(mediatype, + playlist_xsp(mediatype, foldername, folderid, viewtype) @@ -414,7 +414,7 @@ class LibrarySync(Thread): if mediatype != v.PLEX_TYPE_ARTIST: if (foldername not in playlists and mediatype in (v.PLEX_TYPE_MOVIE, v.PLEX_TYPE_SHOW)): - playlistXSP(mediatype, + playlist_xsp(mediatype, foldername, folderid, viewtype) @@ -1102,7 +1102,7 @@ class LibrarySync(Thread): """ self.videoLibUpdate = False self.musicLibUpdate = False - now = getUnixTimestamp() + now = unix_timestamp() deleteListe = [] for i, item in enumerate(self.itemsToProcess): if self.thread_stopped() or self.thread_suspended(): @@ -1220,7 +1220,7 @@ class LibrarySync(Thread): 'state': status, 'type': typus, 'ratingKey': str(item['itemID']), - 'timestamp': getUnixTimestamp(), + 'timestamp': unix_timestamp(), 'attempt': 0 }) elif typus in (v.PLEX_TYPE_MOVIE, @@ -1237,7 +1237,7 @@ class LibrarySync(Thread): 'state': status, 'type': typus, 'ratingKey': plex_id, - 'timestamp': getUnixTimestamp(), + 'timestamp': unix_timestamp(), 'attempt': 0 }) @@ -1276,7 +1276,7 @@ class LibrarySync(Thread): 'state': None, # Don't need a state here 'type': kodi_info[5], 'ratingKey': plex_id, - 'timestamp': getUnixTimestamp(), + 'timestamp': unix_timestamp(), 'attempt': 0 }) @@ -1386,7 +1386,7 @@ class LibrarySync(Thread): resume, session['duration'], session['file_id'], - DateToKodi(getUnixTimestamp())) + unix_date_to_kodi(unix_timestamp())) def fanartSync(self, refresh=False): """ @@ -1430,9 +1430,9 @@ class LibrarySync(Thread): window('plex_dbScan', value="true") state.DB_SCAN = True # First remove playlists - deletePlaylists() + delete_playlists() # Remove video nodes - deleteNodes() + delete_nodes() # Kick off refresh if self.maintainViews() is True: # Ran successfully @@ -1549,11 +1549,11 @@ class LibrarySync(Thread): # Also runs when first installed # Verify the video database can be found videoDb = v.DB_VIDEO_PATH - if not exists(tryEncode(videoDb)): + if not exists(try_encode(videoDb)): # Database does not exists log.error("The current Kodi version is incompatible " "to know which Kodi versions are supported.") - log.error('Current Kodi version: %s' % tryDecode( + log.error('Current Kodi version: %s' % try_decode( xbmc.getInfoLabel('System.BuildVersion'))) # "Current Kodi version is unsupported, cancel lib sync" dialog('ok', heading='{plex}', line1=lang(39403)) @@ -1562,10 +1562,10 @@ class LibrarySync(Thread): state.DB_SCAN = True window('plex_dbScan', value="true") log.info("Db version: %s" % settings('dbCreatedWithVersion')) - lastTimeSync = getUnixTimestamp() + lastTimeSync = unix_timestamp() # Initialize time offset Kodi - PMS self.syncPMStime() - lastSync = getUnixTimestamp() + lastSync = unix_timestamp() if settings('FanartTV') == 'true': # Start getting additional missing artwork with plexdb.Get_Plex_DB() as plex_db: @@ -1579,8 +1579,8 @@ class LibrarySync(Thread): 'refresh': True }) log.info('Refreshing video nodes and playlists now') - deletePlaylists() - deleteNodes() + delete_playlists() + delete_nodes() log.info("Initial start-up full sync starting") librarySync = fullSync() window('plex_dbScan', clear=True) @@ -1604,7 +1604,7 @@ class LibrarySync(Thread): self.triage_lib_scans() self.force_dialog = False continue - now = getUnixTimestamp() + now = unix_timestamp() # Standard syncs - don't force-show dialogs self.force_dialog = False if (now - lastSync > FULL_SYNC_INTERVALL and diff --git a/resources/lib/loghandler.py b/resources/lib/loghandler.py index f81c962d..5a91a214 100644 --- a/resources/lib/loghandler.py +++ b/resources/lib/loghandler.py @@ -12,7 +12,7 @@ LEVELS = { ############################################################################### -def tryEncode(uniString, encoding='utf-8'): +def try_encode(uniString, encoding='utf-8'): """ Will try to encode uniString (in unicode) to encoding. This possibly fails with e.g. Android TV's Python, which does not accept arguments for @@ -43,5 +43,5 @@ class LogHandler(logging.StreamHandler): try: xbmc.log(self.format(record), level=LEVELS[record.levelno]) except UnicodeEncodeError: - xbmc.log(tryEncode(self.format(record)), + xbmc.log(try_encode(self.format(record)), level=LEVELS[record.levelno]) diff --git a/resources/lib/playback.py b/resources/lib/playback.py index ed8747de..35010d17 100644 --- a/resources/lib/playback.py +++ b/resources/lib/playback.py @@ -18,7 +18,7 @@ from playutils import PlayUtils from PKC_listitem import PKC_ListItem from pickler import pickle_me, Playback_Successful import json_rpc as js -from utils import settings, dialog, language as lang, tryEncode +from utils import settings, dialog, language as lang, try_encode from plexbmchelper.subscribers import LOCKER import variables as v import state @@ -167,7 +167,7 @@ def _prep_playlist_stack(xml): path = ('plugin://plugin.video.plexkodiconnect?%s' % urlencode(params)) listitem = api.CreateListItemFromPlexItem() - listitem.setPath(tryEncode(path)) + listitem.setPath(try_encode(path)) else: # Will add directly via the Kodi DB path = None @@ -244,7 +244,7 @@ def conclude_playback(playqueue, pos): playurl = playutils.getPlayUrl() else: playurl = item.file - listitem.setPath(tryEncode(playurl)) + listitem.setPath(try_encode(playurl)) if item.playmethod in ('DirectStream', 'DirectPlay'): listitem.setSubtitles(api.externalSubs()) else: @@ -322,14 +322,14 @@ def process_indirect(key, offset, resolve=True): return playurl = xml[0].attrib['key'] item.file = playurl - listitem.setPath(tryEncode(playurl)) + listitem.setPath(try_encode(playurl)) playqueue.items.append(item) if resolve is True: result.listitem = listitem pickle_me(result) else: thread = Thread(target=Player().play, - args={'item': tryEncode(playurl), + args={'item': try_encode(playurl), 'listitem': listitem}) thread.setDaemon(True) LOG.info('Done initializing PKC playback, starting Kodi player') diff --git a/resources/lib/playlist_func.py b/resources/lib/playlist_func.py index a233c6a0..041414ea 100644 --- a/resources/lib/playlist_func.py +++ b/resources/lib/playlist_func.py @@ -8,7 +8,7 @@ from re import compile as re_compile import plexdb_functions as plexdb from downloadutils import DownloadUtils as DU -from utils import tryEncode, escape_html +from utils import try_encode, escape_html from PlexAPI import API from PlexFunctions import GetPlexMetadata import json_rpc as js @@ -60,7 +60,7 @@ class PlaylistObjectBaseclase(object): continue if isinstance(getattr(self, key), (str, unicode)): answ += '\'%s\': \'%s\', ' % (key, - tryEncode(getattr(self, key))) + try_encode(getattr(self, key))) else: # e.g. int answ += '\'%s\': %s, ' % (key, str(getattr(self, key))) @@ -168,7 +168,7 @@ class Playlist_Item(object): continue if isinstance(getattr(self, key), (str, unicode)): answ += '\'%s\': \'%s\', ' % (key, - tryEncode(getattr(self, key))) + try_encode(getattr(self, key))) else: # e.g. int answ += '\'%s\': %s, ' % (key, str(getattr(self, key))) diff --git a/resources/lib/playutils.py b/resources/lib/playutils.py index 7fbadede..b4753532 100644 --- a/resources/lib/playutils.py +++ b/resources/lib/playutils.py @@ -4,7 +4,7 @@ from logging import getLogger from downloadutils import DownloadUtils as DU -from utils import window, settings, language as lang, dialog, tryEncode +from utils import window, settings, language as lang, dialog, try_encode import variables as v ############################################################################### @@ -274,7 +274,7 @@ class PlayUtils(): codec, channellayout) audio_streams_list.append(index) - audio_streams.append(tryEncode(track)) + audio_streams.append(try_encode(track)) audio_numb += 1 # Subtitles @@ -306,7 +306,7 @@ class PlayUtils(): "%s%s" % (window('pms_server'), stream.attrib['key'])) downloadable_streams.append(index) - download_subs.append(tryEncode(path)) + download_subs.append(try_encode(path)) else: track = "%s (%s)" % (track, lang(39710)) # burn-in if stream.attrib.get('selected') == '1' and downloadable: @@ -315,7 +315,7 @@ class PlayUtils(): default_sub = index subtitle_streams_list.append(index) - subtitle_streams.append(tryEncode(track)) + subtitle_streams.append(try_encode(track)) sub_num += 1 if audio_numb > 1: diff --git a/resources/lib/plex_tv.py b/resources/lib/plex_tv.py index f805bee5..fa28cb67 100644 --- a/resources/lib/plex_tv.py +++ b/resources/lib/plex_tv.py @@ -4,7 +4,7 @@ from logging import getLogger from xbmc import sleep, executebuiltin from downloadutils import DownloadUtils as DU -from utils import dialog, language as lang, settings, tryEncode +from utils import dialog, language as lang, settings, try_encode import variables as v import state @@ -39,7 +39,7 @@ def choose_home_user(token): username = user['title'] userlist.append(username) # To take care of non-ASCII usernames - userlist_coded.append(tryEncode(username)) + userlist_coded.append(try_encode(username)) usernumber = len(userlist) username = '' usertoken = '' diff --git a/resources/lib/plexdb_functions.py b/resources/lib/plexdb_functions.py index 239d25df..742a461d 100644 --- a/resources/lib/plexdb_functions.py +++ b/resources/lib/plexdb_functions.py @@ -3,7 +3,7 @@ ############################################################################### from logging import getLogger -from utils import kodiSQL +from utils import kodi_sql import variables as v ############################################################################### @@ -22,7 +22,7 @@ class Get_Plex_DB(): and the db gets closed """ def __enter__(self): - self.plexconn = kodiSQL('plex') + self.plexconn = kodi_sql('plex') return Plex_DB_Functions(self.plexconn.cursor()) def __exit__(self, type, value, traceback): diff --git a/resources/lib/utils.py b/resources/lib/utils.py index 6ff5f68b..3c40057c 100644 --- a/resources/lib/utils.py +++ b/resources/lib/utils.py @@ -1,5 +1,7 @@ # -*- coding: utf-8 -*- - +""" +Various functions and decorators for PKC +""" ############################################################################### from logging import getLogger from cProfile import Profile @@ -7,7 +9,7 @@ from pstats import Stats from sqlite3 import connect, OperationalError from datetime import datetime, timedelta from StringIO import StringIO -from time import localtime, strftime, strptime +from time import localtime, strftime from unicodedata import normalize import xml.etree.ElementTree as etree from functools import wraps, partial @@ -21,12 +23,13 @@ import xbmc import xbmcaddon import xbmcgui from xbmcvfs import exists, delete + import variables as v import state ############################################################################### -log = getLogger("PLEX."+__name__) +LOG = getLogger("PLEX." + __name__) WINDOW = xbmcgui.Window(10000) ADDON = xbmcaddon.Addon(id='plugin.video.plexkodiconnect') @@ -46,7 +49,8 @@ def reboot_kodi(message=None): dialog('ok', heading='{plex}', line1=message) xbmc.executebuiltin('RestartApp') -def window(property, value=None, clear=False, windowid=10000): + +def window(prop, value=None, clear=False, windowid=10000): """ Get or set window property - thread safe! @@ -60,11 +64,11 @@ def window(property, value=None, clear=False, windowid=10000): win = WINDOW if clear: - win.clearProperty(property) + win.clearProperty(prop) elif value is not None: - win.setProperty(tryEncode(property), tryEncode(value)) + win.setProperty(try_encode(prop), try_encode(value)) else: - return tryDecode(win.getProperty(property)) + return try_decode(win.getProperty(prop)) def plex_command(key, value): @@ -90,10 +94,10 @@ def settings(setting, value=None): addon = xbmcaddon.Addon(id='plugin.video.plexkodiconnect') if value is not None: # Takes string or unicode by default! - addon.setSetting(tryEncode(setting), tryEncode(value)) + addon.setSetting(try_encode(setting), try_encode(value)) else: # Should return unicode by default, but just in case - return tryDecode(addon.getSetting(setting)) + return try_decode(addon.getSetting(setting)) def exists_dir(path): @@ -104,24 +108,26 @@ def exists_dir(path): Feed with encoded string or unicode """ if v.KODIVERSION >= 17: - answ = exists(tryEncode(path)) + answ = exists(try_encode(path)) else: - dummyfile = join(tryDecode(path), 'dummyfile.txt') + dummyfile = join(try_decode(path), 'dummyfile.txt') try: - with open(dummyfile, 'w') as f: - f.write('text') + with open(dummyfile, 'w') as filer: + filer.write('text') except IOError: # folder does not exist yet answ = 0 else: # Folder exists. Delete file again. - delete(tryEncode(dummyfile)) + delete(try_encode(dummyfile)) answ = 1 return answ def language(stringid): - # Central string retrieval + """ + Central string retrieval from strings.po + """ return ADDON.getLocalizedString(stringid) @@ -236,7 +242,7 @@ def kodi_time_to_millis(time): return ret -def tryEncode(uniString, encoding='utf-8'): +def try_encode(uniString, encoding='utf-8'): """ Will try to encode uniString (in unicode) to encoding. This possibly fails with e.g. Android TV's Python, which does not accept arguments for @@ -252,7 +258,7 @@ def tryEncode(uniString, encoding='utf-8'): return uniString -def tryDecode(string, encoding='utf-8'): +def try_decode(string, encoding='utf-8'): """ Will try to decode string (encoded) using encoding. This possibly fails with e.g. Android TV's Python, which does not accept arguments for @@ -295,7 +301,7 @@ def escape_html(string): return string -def DateToKodi(stamp): +def unix_date_to_kodi(stamp): """ converts a Unix time stamp (seconds passed sinceJanuary 1 1970) to a propper, human-readable time stamp used by Kodi @@ -313,49 +319,42 @@ def DateToKodi(stamp): return localdate -def IntFromStr(string): - """ - Returns an int from string or the int 0 if something happened - """ - try: - result = int(string) - except: - result = 0 - return result - - -def getUnixTimestamp(secondsIntoTheFuture=None): +def unix_timestamp(seconds_into_the_future=None): """ Returns a Unix time stamp (seconds passed since January 1 1970) for NOW as an integer. - Optionally, pass secondsIntoTheFuture: positive int's will result in a + Optionally, pass seconds_into_the_future: positive int's will result in a future timestamp, negative the past """ - if secondsIntoTheFuture: - future = datetime.utcnow() + timedelta(seconds=secondsIntoTheFuture) + if seconds_into_the_future: + future = datetime.utcnow() + timedelta(seconds=seconds_into_the_future) else: future = datetime.utcnow() return timegm(future.timetuple()) -def kodiSQL(media_type="video"): +def kodi_sql(media_type=None): + """ + Open a connection to the Kodi database. + media_type: 'video' (standard if not passed), 'plex', 'music', 'texture' + """ if media_type == "plex": - dbPath = v.DB_PLEX_PATH + db_path = v.DB_PLEX_PATH elif media_type == "music": - dbPath = v.DB_MUSIC_PATH + db_path = v.DB_MUSIC_PATH elif media_type == "texture": - dbPath = v.DB_TEXTURE_PATH + db_path = v.DB_TEXTURE_PATH else: - dbPath = v.DB_VIDEO_PATH - return connect(dbPath, timeout=60.0) + db_path = v.DB_VIDEO_PATH + return connect(db_path, timeout=60.0) def create_actor_db_index(): """ Index the "actors" because we got a TON - speed up SELECT and WHEN """ - conn = kodiSQL('video') + conn = kodi_sql('video') cursor = conn.cursor() try: cursor.execute(""" @@ -370,6 +369,10 @@ def create_actor_db_index(): def reset(): + """ + User navigated to the PKC settings, Advanced, and wants to reset the Kodi + database and possibly PKC entirely + """ # Are you sure you want to reset your local Kodi database? if not dialog('yesno', heading='{plex} %s ' % language(30132), @@ -380,7 +383,7 @@ def reset(): plex_command('STOP_SYNC', 'True') count = 10 while window('plex_dbScan') == "true": - log.debug("Sync is running, will retry: %s..." % count) + LOG.debug("Sync is running, will retry: %s...", count) count -= 1 if count == 0: # Could not stop the database from running. Please try again later. @@ -391,14 +394,14 @@ def reset(): xbmc.sleep(1000) # Clean up the playlists - deletePlaylists() + delete_playlists() # Clean up the video nodes - deleteNodes() + delete_nodes() # Wipe the kodi databases - log.info("Resetting the Kodi video database.") - connection = kodiSQL('video') + LOG.info("Resetting the Kodi video database.") + connection = kodi_sql('video') cursor = connection.cursor() cursor.execute('SELECT tbl_name FROM sqlite_master WHERE type="table"') rows = cursor.fetchall() @@ -410,8 +413,8 @@ def reset(): cursor.close() if settings('enableMusic') == "true": - log.info("Resetting the Kodi music database.") - connection = kodiSQL('music') + LOG.info("Resetting the Kodi music database.") + connection = kodi_sql('music') cursor = connection.cursor() cursor.execute('SELECT tbl_name FROM sqlite_master WHERE type="table"') rows = cursor.fetchall() @@ -423,8 +426,8 @@ def reset(): cursor.close() # Wipe the Plex database - log.info("Resetting the Plex database.") - connection = kodiSQL('plex') + LOG.info("Resetting the Plex database.") + connection = kodi_sql('plex') cursor = connection.cursor() cursor.execute('SELECT tbl_name FROM sqlite_master WHERE type="table"') rows = cursor.fetchall() @@ -441,21 +444,21 @@ def reset(): if dialog('yesno', heading='{plex} %s ' % language(30132), line1=language(39602)): - log.info("Resetting all cached artwork.") + LOG.info("Resetting all cached artwork.") # Remove all existing textures first path = xbmc.translatePath("special://thumbnails/") if exists(path): - rmtree(tryDecode(path), ignore_errors=True) + rmtree(try_decode(path), ignore_errors=True) # remove all existing data from texture DB - connection = kodiSQL('texture') + connection = kodi_sql('texture') cursor = connection.cursor() query = 'SELECT tbl_name FROM sqlite_master WHERE type=?' cursor.execute(query, ("table", )) rows = cursor.fetchall() for row in rows: - tableName = row[0] - if(tableName != "version"): - cursor.execute("DELETE FROM %s" % tableName) + table_name = row[0] + if table_name != "version": + cursor.execute("DELETE FROM %s" % table_name) connection.commit() cursor.close() @@ -469,44 +472,36 @@ def reset(): line1=language(39603)): # Delete the settings addon = xbmcaddon.Addon() - addondir = tryDecode(xbmc.translatePath(addon.getAddonInfo('profile'))) - dataPath = "%ssettings.xml" % addondir - log.info("Deleting: settings.xml") - remove(dataPath) + addondir = try_decode(xbmc.translatePath(addon.getAddonInfo('profile'))) + LOG.info("Deleting: settings.xml") + remove("%ssettings.xml" % addondir) reboot_kodi() def profiling(sortby="cumulative"): - # Will print results to Kodi log + """ + Will print results to Kodi log. Must be enabled in the Python source code + """ def decorator(func): + """ + decorator construct + """ def wrapper(*args, **kwargs): - - pr = Profile() - - pr.enable() + """ + wrapper construct + """ + profile = Profile() + profile.enable() result = func(*args, **kwargs) - pr.disable() - - s = StringIO() - ps = Stats(pr, stream=s).sort_stats(sortby) - ps.print_stats() - log.info(s.getvalue()) - + profile.disable() + string_io = StringIO() + stats = Stats(profile, stream=string_io).sort_stats(sortby) + stats.print_stats() + LOG.info(string_io.getvalue()) return result - return wrapper return decorator -def convertdate(date): - try: - date = datetime.strptime(date, "%Y-%m-%dT%H:%M:%SZ") - except TypeError: - # TypeError: attribute of type 'NoneType' is not callable - # Known Kodi/python error - date = datetime(*(strptime(date, "%Y-%m-%dT%H:%M:%SZ")[0:6])) - - return date - def compare_version(current, minimum): """ @@ -515,38 +510,36 @@ def compare_version(current, minimum): Input strings: e.g. "1.2.3"; always with Major, Minor and Patch! """ - log.info("current DB: %s minimum DB: %s" % (current, minimum)) + LOG.info("current DB: %s minimum DB: %s", current, minimum) try: - currMajor, currMinor, currPatch = current.split(".") + curr_major, curr_minor, curr_patch = current.split(".") except ValueError: # there WAS no current DB, e.g. deleted. return True - minMajor, minMinor, minPatch = minimum.split(".") - currMajor = int(currMajor) - currMinor = int(currMinor) - currPatch = int(currPatch) - minMajor = int(minMajor) - minMinor = int(minMinor) - minPatch = int(minPatch) + min_major, min_minor, min_patch = minimum.split(".") + curr_major = int(curr_major) + curr_minor = int(curr_minor) + curr_patch = int(curr_patch) + min_major = int(min_major) + min_minor = int(min_minor) + min_patch = int(min_patch) - if currMajor > minMajor: + if curr_major > min_major: return True - elif currMajor < minMajor: + elif curr_major < min_major: return False - if currMinor > minMinor: + if curr_minor > min_minor: return True - elif currMinor < minMinor: - return False - - if currPatch >= minPatch: - return True - else: + elif curr_minor < min_minor: return False + return curr_patch >= min_patch def normalize_nodes(text): - # For video nodes + """ + For video nodes + """ text = text.replace(":", "") text = text.replace("/", "-") text = text.replace("\\", "-") @@ -561,13 +554,15 @@ def normalize_nodes(text): # Remove dots from the last character as windows can not have directories # with dots at the end text = text.rstrip('.') - text = tryEncode(normalize('NFKD', unicode(text, 'utf-8'))) + text = try_encode(normalize('NFKD', unicode(text, 'utf-8'))) return text + def normalize_string(text): - # For theme media, do not modify unless - # modified in TV Tunes + """ + For theme media, do not modify unless modified in TV Tunes + """ text = text.replace(":", "") text = text.replace("/", "-") text = text.replace("\\", "-") @@ -580,7 +575,7 @@ def normalize_string(text): # Remove dots from the last character as windows can not have directories # with dots at the end text = text.rstrip('.') - text = tryEncode(normalize('NFKD', unicode(text, 'utf-8'))) + text = try_encode(normalize('NFKD', unicode(text, 'utf-8'))) return text @@ -595,8 +590,8 @@ def indent(elem, level=0): elem.text = i + " " if not elem.tail or not elem.tail.strip(): elem.tail = i - for elem in elem: - indent(elem, level+1) + for item in elem: + indent(item, level+1) if not elem.tail or not elem.tail.strip(): elem.tail = i else: @@ -604,30 +599,6 @@ def indent(elem, level=0): elem.tail = i -def guisettingsXML(): - """ - Returns special://userdata/guisettings.xml as an etree xml root element - """ - path = tryDecode(xbmc.translatePath("special://profile/")) - xmlpath = "%sguisettings.xml" % path - - try: - xmlparse = etree.parse(xmlpath) - except IOError: - # Document is blank or missing - root = etree.Element('settings') - except etree.ParseError: - log.error('Error parsing %s' % xmlpath) - # "Kodi cannot parse {0}. PKC will not function correctly. Please visit - # {1} and correct your file!" - dialog('ok', language(29999), language(39716).format( - 'guisettings.xml', 'http://kodi.wiki/view/userdata')) - return - else: - root = xmlparse.getroot() - return root - - class XmlKodiSetting(object): """ Used to load a Kodi XML settings file from special://profile as an etree @@ -670,7 +641,7 @@ class XmlKodiSetting(object): except IOError: # Document is blank or missing if self.force_create is False: - log.debug('%s does not seem to exist; not creating', self.path) + LOG.debug('%s does not seem to exist; not creating', self.path) # This will abort __enter__ self.__exit__(IOError, None, None) # Create topmost xml entry @@ -678,7 +649,7 @@ class XmlKodiSetting(object): element=etree.Element(self.top_element)) self.write_xml = True except etree.ParseError: - log.error('Error parsing %s', self.path) + LOG.error('Error parsing %s', self.path) # "Kodi cannot parse {0}. PKC will not function correctly. Please # visit {1} and correct your file!" dialog('ok', language(29999), language(39716).format( @@ -775,7 +746,7 @@ class XmlKodiSetting(object): elif old.attrib != attrib: already_set = False if already_set is True: - log.debug('Element has already been found') + LOG.debug('Element has already been found') return old # Need to set new setting, indeed self.write_xml = True @@ -790,34 +761,35 @@ class XmlKodiSetting(object): return element -def passwordsXML(): - # To add network credentials - path = tryDecode(xbmc.translatePath("special://userdata/")) +def passwords_xml(): + """ + To add network credentials to Kodi's password xml + """ + path = try_decode(xbmc.translatePath("special://userdata/")) xmlpath = "%spasswords.xml" % path - dialog = xbmcgui.Dialog() - try: xmlparse = etree.parse(xmlpath) except IOError: # Document is blank or missing root = etree.Element('passwords') - skipFind = True + skip_find = True except etree.ParseError: - log.error('Error parsing %s' % xmlpath) + LOG.error('Error parsing %s', xmlpath) # "Kodi cannot parse {0}. PKC will not function correctly. Please visit # {1} and correct your file!" - dialog.ok(language(29999), language(39716).format( + dialog('ok', language(29999), language(39716).format( 'passwords.xml', 'http://forum.kodi.tv/')) return else: root = xmlparse.getroot() - skipFind = False + skip_find = False credentials = settings('networkCreds') if credentials: # Present user with options - option = dialog.select( - "Modify/Remove network credentials", ["Modify", "Remove"]) + option = dialog('select', + "Modify/Remove network credentials", + ["Modify", "Remove"]) if option < 0: # User cancelled dialog @@ -825,76 +797,86 @@ def passwordsXML(): elif option == 1: # User selected remove + success = False for paths in root.getiterator('passwords'): for path in paths: if path.find('.//from').text == "smb://%s/" % credentials: paths.remove(path) - log.info("Successfully removed credentials for: %s" - % credentials) + LOG.info("Successfully removed credentials for: %s", + credentials) etree.ElementTree(root).write(xmlpath, encoding="UTF-8") - break - else: - log.error("Failed to find saved server: %s in passwords.xml" - % credentials) - + success = True + if not success: + LOG.error("Failed to find saved server: %s in passwords.xml", + credentials) + dialog('notification', + heading='{plex}', + message="%s not found" % credentials, + icon='{warning}', + sound=False) + return settings('networkCreds', value="") - xbmcgui.Dialog().notification( - heading='PlexKodiConnect', - message="%s removed from passwords.xml" % credentials, - icon="special://home/addons/plugin.video.plexkodiconnect/icon.png", - time=1000, - sound=False) + dialog('notification', + heading='{plex}', + message="%s removed from passwords.xml" % credentials, + icon='{plex}', + sound=False) return elif option == 0: # User selected to modify - server = dialog.input("Modify the computer name or ip address", credentials) + server = dialog('input', + "Modify the computer name or ip address", + credentials) if not server: return else: # No credentials added - dialog.ok( - heading="Network credentials", - line1= ( - "Input the server name or IP address as indicated in your plex library paths. " - 'For example, the server name: \\\\SERVER-PC\\path\\ or smb://SERVER-PC/path is "SERVER-PC".')) - server = dialog.input("Enter the server name or IP address") + dialog('ok', + "Network credentials", + 'Input the server name or IP address as indicated in your plex ' + 'library paths. For example, the server name: ' + '\\\\SERVER-PC\\path\\ or smb://SERVER-PC/path is SERVER-PC') + server = dialog('input', "Enter the server name or IP address") if not server: return server = quote_plus(server) # Network username - user = dialog.input("Enter the network username") + user = dialog('input', "Enter the network username") if not user: return user = quote_plus(user) # Network password - password = dialog.input("Enter the network password", - '', # Default input - xbmcgui.INPUT_ALPHANUM, - xbmcgui.ALPHANUM_HIDE_INPUT) + password = dialog('input', + "Enter the network password", + '', # Default input + type='{alphanum}', + option='{hide}') # Need to url-encode the password password = quote_plus(password) # Add elements. Annoying etree bug where findall hangs forever - if skipFind is False: - skipFind = True + if skip_find is False: + skip_find = True for path in root.findall('.//path'): if path.find('.//from').text.lower() == "smb://%s/" % server.lower(): # Found the server, rewrite credentials - path.find('.//to').text = "smb://%s:%s@%s/" % (user, password, server) - skipFind = False + path.find('.//to').text = ("smb://%s:%s@%s/" + % (user, password, server)) + skip_find = False break - if skipFind: + if skip_find: # Server not found, add it. path = etree.SubElement(root, 'path') - etree.SubElement(path, 'from', attrib={'pathversion': "1"}).text = "smb://%s/" % server + etree.SubElement(path, 'from', attrib={'pathversion': "1"}).text = \ + "smb://%s/" % server topath = "smb://%s:%s@%s/" % (user, password, server) etree.SubElement(path, 'to', attrib={'pathversion': "1"}).text = topath # Add credentials settings('networkCreds', value="%s" % server) - log.info("Added server: %s to passwords.xml" % server) + LOG.info("Added server: %s to passwords.xml", server) # Prettify and write to file try: indent(root) @@ -902,19 +884,12 @@ def passwordsXML(): pass etree.ElementTree(root).write(xmlpath, encoding="UTF-8") - # dialog.notification( - # heading="PlexKodiConnect", - # message="Added to passwords.xml", - # icon="special://home/addons/plugin.video.plexkodiconnect/icon.png", - # time=5000, - # sound=False) - -def playlistXSP(mediatype, tagname, viewid, viewtype="", delete=False): +def playlist_xsp(mediatype, tagname, viewid, viewtype="", delete=False): """ Feed with tagname as unicode """ - path = tryDecode(xbmc.translatePath("special://profile/playlists/video/")) + path = try_decode(xbmc.translatePath("special://profile/playlists/video/")) if viewtype == "mixed": plname = "%s - %s" % (tagname, mediatype) xsppath = "%sPlex %s - %s.xsp" % (path, viewid, mediatype) @@ -923,16 +898,16 @@ def playlistXSP(mediatype, tagname, viewid, viewtype="", delete=False): xsppath = "%sPlex %s.xsp" % (path, viewid) # Create the playlist directory - if not exists(tryEncode(path)): - log.info("Creating directory: %s" % path) + if not exists(try_encode(path)): + LOG.info("Creating directory: %s", path) makedirs(path) # Only add the playlist if it doesn't already exists - if exists(tryEncode(xsppath)): - log.info('Path %s does exist' % xsppath) + if exists(try_encode(xsppath)): + LOG.info('Path %s does exist', xsppath) if delete: remove(xsppath) - log.info("Successfully removed playlist: %s." % tagname) + LOG.info("Successfully removed playlist: %s.", tagname) return # Using write process since there's no guarantee the xml declaration works @@ -942,9 +917,9 @@ def playlistXSP(mediatype, tagname, viewid, viewtype="", delete=False): 'movie': 'movies', 'show': 'tvshows' } - log.info("Writing playlist file to: %s" % xsppath) - with open(xsppath, 'wb') as f: - f.write(tryEncode( + LOG.info("Writing playlist file to: %s", xsppath) + with open(xsppath, 'wb') as filer: + filer.write(try_encode( '\n' '\n\t' 'Plex %s\n\t' @@ -954,20 +929,24 @@ def playlistXSP(mediatype, tagname, viewid, viewtype="", delete=False): '\n' '\n' % (itemtypes.get(mediatype, mediatype), plname, tagname))) - log.info("Successfully added playlist: %s" % tagname) + LOG.info("Successfully added playlist: %s", tagname) -def deletePlaylists(): - # Clean up the playlists - path = tryDecode(xbmc.translatePath("special://profile/playlists/video/")) +def delete_playlists(): + """ + Clean up the playlists + """ + path = try_decode(xbmc.translatePath("special://profile/playlists/video/")) for root, _, files in walk(path): for file in files: if file.startswith('Plex'): remove(join(root, file)) -def deleteNodes(): - # Clean up video nodes - path = tryDecode(xbmc.translatePath("special://profile/library/video/")) +def delete_nodes(): + """ + Clean up video nodes + """ + path = try_decode(xbmc.translatePath("special://profile/library/video/")) for root, dirs, _ in walk(path): for directory in dirs: if directory.startswith('Plex-'): @@ -993,9 +972,9 @@ def CatchExceptions(warnuser=False): try: return func(*args, **kwargs) except Exception as e: - log.error('%s has crashed. Error: %s' % (func.__name__, e)) + LOG.error('%s has crashed. Error: %s', func.__name__, e) import traceback - log.error("Traceback:\n%s" % traceback.format_exc()) + LOG.error("Traceback:\n%s", traceback.format_exc()) if warnuser: window('plex_scancrashed', value='true') return @@ -1012,8 +991,8 @@ def LogTime(func): starttotal = datetime.now() result = func(*args, **kwargs) elapsedtotal = datetime.now() - starttotal - log.info('It took %s to run the function %s' - % (elapsedtotal, func.__name__)) + LOG.info('It took %s to run the function %s', + elapsedtotal, func.__name__) return result return wrapper @@ -1117,43 +1096,3 @@ class Lock_Function(object): result = func(*args, **kwargs) return result return wrapper - -############################################################################### -# UNUSED METHODS - - -# def changePlayState(itemType, kodiId, playCount, lastplayed): -# """ -# YET UNUSED - -# kodiId: int or str -# playCount: int or str -# lastplayed: str or int unix timestamp -# """ -# lastplayed = DateToKodi(lastplayed) - -# kodiId = int(kodiId) -# playCount = int(playCount) -# method = { -# 'movie': ' VideoLibrary.SetMovieDetails', -# 'episode': 'VideoLibrary.SetEpisodeDetails', -# 'musicvideo': ' VideoLibrary.SetMusicVideoDetails', # TODO -# 'show': 'VideoLibrary.SetTVShowDetails', # TODO -# '': 'AudioLibrary.SetAlbumDetails', # TODO -# '': 'AudioLibrary.SetArtistDetails', # TODO -# 'track': 'AudioLibrary.SetSongDetails' -# } -# params = { -# 'movie': { -# 'movieid': kodiId, -# 'playcount': playCount, -# 'lastplayed': lastplayed -# }, -# 'episode': { -# 'episodeid': kodiId, -# 'playcount': playCount, -# 'lastplayed': lastplayed -# } -# } -# result = jsonrpc(method[itemType]).execute(params[itemType]) -# log.debug("JSON result was: %s" % result) diff --git a/resources/lib/variables.py b/resources/lib/variables.py index 4a7f6d33..fef8e4ca 100644 --- a/resources/lib/variables.py +++ b/resources/lib/variables.py @@ -6,7 +6,7 @@ from xbmcaddon import Addon # For any file operations with KODI function, use encoded strings! -def tryDecode(string, encoding='utf-8'): +def try_decode(string, encoding='utf-8'): """ Will try to decode string (encoded) using encoding. This possibly fails with e.g. Android TV's Python, which does not accept arguments for @@ -37,7 +37,7 @@ ADDON_VERSION = _ADDON.getAddonInfo('version') KODILANGUAGE = xbmc.getLanguage(xbmc.ISO_639_1) KODIVERSION = int(xbmc.getInfoLabel("System.BuildVersion")[:2]) KODILONGVERSION = xbmc.getInfoLabel('System.BuildVersion') -KODI_PROFILE = tryDecode(xbmc.translatePath("special://profile")) +KODI_PROFILE = try_decode(xbmc.translatePath("special://profile")) if xbmc.getCondVisibility('system.platform.osx'): PLATFORM = "MacOSX" @@ -56,7 +56,7 @@ elif xbmc.getCondVisibility('system.platform.android'): else: PLATFORM = "Unknown" -DEVICENAME = tryDecode(_ADDON.getSetting('deviceName')) +DEVICENAME = try_decode(_ADDON.getSetting('deviceName')) DEVICENAME = DEVICENAME.replace(":", "") DEVICENAME = DEVICENAME.replace("/", "-") DEVICENAME = DEVICENAME.replace("\\", "-") @@ -86,7 +86,7 @@ _DB_VIDEO_VERSION = { 17: 107, # Krypton 18: 108 # Leia } -DB_VIDEO_PATH = tryDecode(xbmc.translatePath( +DB_VIDEO_PATH = try_decode(xbmc.translatePath( "special://database/MyVideos%s.db" % _DB_VIDEO_VERSION[KODIVERSION])) _DB_MUSIC_VERSION = { @@ -97,7 +97,7 @@ _DB_MUSIC_VERSION = { 17: 60, # Krypton 18: 62 # Leia } -DB_MUSIC_PATH = tryDecode(xbmc.translatePath( +DB_MUSIC_PATH = try_decode(xbmc.translatePath( "special://database/MyMusic%s.db" % _DB_MUSIC_VERSION[KODIVERSION])) _DB_TEXTURE_VERSION = { @@ -108,12 +108,12 @@ _DB_TEXTURE_VERSION = { 17: 13, # Krypton 18: 13 # Leia } -DB_TEXTURE_PATH = tryDecode(xbmc.translatePath( +DB_TEXTURE_PATH = try_decode(xbmc.translatePath( "special://database/Textures%s.db" % _DB_TEXTURE_VERSION[KODIVERSION])) -DB_PLEX_PATH = tryDecode(xbmc.translatePath("special://database/plex.db")) +DB_PLEX_PATH = try_decode(xbmc.translatePath("special://database/plex.db")) -EXTERNAL_SUBTITLE_TEMP_PATH = tryDecode(xbmc.translatePath( +EXTERNAL_SUBTITLE_TEMP_PATH = try_decode(xbmc.translatePath( "special://profile/addon_data/%s/temp/" % ADDON_ID)) diff --git a/resources/lib/videonodes.py b/resources/lib/videonodes.py index 659894e5..5636fb3c 100644 --- a/resources/lib/videonodes.py +++ b/resources/lib/videonodes.py @@ -8,8 +8,8 @@ from os import makedirs import xbmc from xbmcvfs import exists -from utils import window, settings, language as lang, tryEncode, indent, \ - normalize_nodes, exists_dir, tryDecode +from utils import window, settings, language as lang, try_encode, indent, \ + normalize_nodes, exists_dir, try_decode import variables as v ############################################################################### @@ -62,9 +62,9 @@ class VideoNodes(object): dirname = viewid # Returns strings - path = tryDecode(xbmc.translatePath( + path = try_decode(xbmc.translatePath( "special://profile/library/video/")) - nodepath = tryDecode(xbmc.translatePath( + nodepath = try_decode(xbmc.translatePath( "special://profile/library/video/Plex-%s/" % dirname)) if delete: @@ -77,9 +77,9 @@ class VideoNodes(object): # Verify the video directory if not exists_dir(path): copytree( - src=tryDecode(xbmc.translatePath( + src=try_decode(xbmc.translatePath( "special://xbmc/system/library/video")), - dst=tryDecode(xbmc.translatePath( + dst=try_decode(xbmc.translatePath( "special://profile/library/video"))) # Create the node directory @@ -292,7 +292,7 @@ class VideoNodes(object): # To do: add our photos nodes to kodi picture sources somehow continue - if exists(tryEncode(nodeXML)): + if exists(try_encode(nodeXML)): # Don't recreate xml if already exists continue @@ -378,9 +378,9 @@ class VideoNodes(object): etree.ElementTree(root).write(nodeXML, encoding="UTF-8") def singleNode(self, indexnumber, tagname, mediatype, itemtype): - tagname = tryEncode(tagname) - cleantagname = tryDecode(normalize_nodes(tagname)) - nodepath = tryDecode(xbmc.translatePath( + tagname = try_encode(tagname) + cleantagname = try_decode(normalize_nodes(tagname)) + nodepath = try_decode(xbmc.translatePath( "special://profile/library/video/")) nodeXML = "%splex_%s.xml" % (nodepath, cleantagname) path = "library://video/plex_%s.xml" % cleantagname @@ -394,9 +394,9 @@ class VideoNodes(object): if not exists_dir(nodepath): # We need to copy over the default items copytree( - src=tryDecode(xbmc.translatePath( + src=try_decode(xbmc.translatePath( "special://xbmc/system/library/video")), - dst=tryDecode(xbmc.translatePath( + dst=try_decode(xbmc.translatePath( "special://profile/library/video"))) labels = { @@ -411,7 +411,7 @@ class VideoNodes(object): window('%s.content' % embynode, value=path) window('%s.type' % embynode, value=itemtype) - if exists(tryEncode(nodeXML)): + if exists(try_encode(nodeXML)): # Don't recreate xml if already exists return diff --git a/resources/lib/websocket.py b/resources/lib/websocket.py index 8cd3134a..ce7a00f1 100644 --- a/resources/lib/websocket.py +++ b/resources/lib/websocket.py @@ -292,7 +292,7 @@ class ABNF(object): opcode: operation code. please see OPCODE_XXX. """ if opcode == ABNF.OPCODE_TEXT and isinstance(data, unicode): - data = utils.tryEncode(data) + data = utils.try_encode(data) # mask must be set if send data from client return ABNF(1, 0, 0, 0, opcode, 1, data)