From 007e68406505a0a9956a5fcaa1d9f716e02c4e03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Arnauts?= Date: Fri, 20 Mar 2020 13:32:55 +0100 Subject: [PATCH] Update xbmc stubs --- test/xbmcaddon.py | 57 +++++++++---- test/xbmcextra.py | 83 ++++++++++++++---- test/xbmcgui.py | 204 ++++++++++++++++++++++++++++++++++----------- test/xbmcplugin.py | 27 +++--- test/xbmcvfs.py | 37 ++++---- 5 files changed, 299 insertions(+), 109 deletions(-) diff --git a/test/xbmcaddon.py b/test/xbmcaddon.py index edc4b3b..7890c6a 100644 --- a/test/xbmcaddon.py +++ b/test/xbmcaddon.py @@ -1,28 +1,31 @@ # -*- coding: utf-8 -*- # Copyright: (c) 2019, Dag Wieers (@dagwieers) # GNU General Public License v3.0 (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -''' This file implements the Kodi xbmcaddon module, either using stubs or alternative functionality ''' +"""This file implements the Kodi xbmcaddon module, either using stubs or alternative functionality""" # pylint: disable=invalid-name from __future__ import absolute_import, division, print_function, unicode_literals from xbmc import getLocalizedString -from xbmcextra import ADDON_INFO, ADDON_ID, addon_settings, global_settings, import_language +from xbmcextra import ADDON_ID, ADDON_INFO, addon_settings -GLOBAL_SETTINGS = global_settings() -ADDON_SETTINGS = addon_settings() -PO = import_language(language=GLOBAL_SETTINGS.get('locale.language')) +# Ensure the addon settings are retained (as we don't write to disk) +ADDON_SETTINGS = addon_settings(ADDON_ID) class Addon: - ''' A reimplementation of the xbmcaddon Addon class ''' + """A reimplementation of the xbmcaddon Addon class""" def __init__(self, id=ADDON_ID): # pylint: disable=redefined-builtin - ''' A stub constructor for the xbmcaddon Addon class ''' + """A stub constructor for the xbmcaddon Addon class""" self.id = id + if id == ADDON_ID: + self.settings = ADDON_SETTINGS + else: + self.settings = addon_settings(id) def getAddonInfo(self, key): - ''' A working implementation for the xbmcaddon Addon class getAddonInfo() method ''' + """A working implementation for the xbmcaddon Addon class getAddonInfo() method""" stub_info = dict(id=self.id, name=self.id, version='2.3.4', type='kodi.inputstream', profile='special://userdata', path='special://userdata') # Add stub_info values to ADDON_INFO when missing (e.g. path and profile) addon_info = dict(stub_info, **ADDON_INFO) @@ -30,22 +33,44 @@ class Addon: @staticmethod def getLocalizedString(msgctxt): - ''' A working implementation for the xbmcaddon Addon class getLocalizedString() method ''' + """A working implementation for the xbmcaddon Addon class getLocalizedString() method""" return getLocalizedString(msgctxt) def getSetting(self, key): - ''' A working implementation for the xbmcaddon Addon class getSetting() method ''' - return ADDON_SETTINGS.get(self.id, {}).get(key, '') + """A working implementation for the xbmcaddon Addon class getSetting() method""" + return self.settings.get(key, '') + + def getSettingBool(self, key): + """A working implementation for the xbmcaddon Addon class getSettingBool() method""" + return bool(self.settings.get(key, False)) + + def getSettingInt(self, key): + """A working implementation for the xbmcaddon Addon class getSettingInt() method""" + return int(self.settings.get(key, 0)) + + def getSettingNumber(self, key): + """A working implementation for the xbmcaddon Addon class getSettingNumber() method""" + return float(self.settings.get(key, 0.0)) @staticmethod def openSettings(): - ''' A stub implementation for the xbmcaddon Addon class openSettings() method ''' + """A stub implementation for the xbmcaddon Addon class openSettings() method""" def setSetting(self, key, value): - ''' A stub implementation for the xbmcaddon Addon class setSetting() method ''' - if not ADDON_SETTINGS.get(self.id): - ADDON_SETTINGS[self.id] = dict() - ADDON_SETTINGS[self.id][key] = value + """A stub implementation for the xbmcaddon Addon class setSetting() method""" + self.settings[key] = value # NOTE: Disable actual writing as it is no longer needed for testing # with open('test/userdata/addon_settings.json', 'w') as fd: # json.dump(filtered_settings, fd, sort_keys=True, indent=4) + + def setSettingBool(self, key, value): + """A stub implementation for the xbmcaddon Addon class setSettingBool() method""" + self.settings[key] = value + + def setSettingInt(self, key, value): + """A stub implementation for the xbmcaddon Addon class setSettingInt() method""" + self.settings[key] = value + + def setSettingNumber(self, key, value): + """A stub implementation for the xbmcaddon Addon class setSettingNumber() method""" + self.settings[key] = value diff --git a/test/xbmcextra.py b/test/xbmcextra.py index 317c5dc..1fdad15 100644 --- a/test/xbmcextra.py +++ b/test/xbmcextra.py @@ -1,20 +1,18 @@ # -*- coding: utf-8 -*- # Copyright: (c) 2019, Dag Wieers (@dagwieers) # GNU General Public License v3.0 (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -''' Extra functions for testing ''' +"""Extra functions for testing""" # pylint: disable=invalid-name from __future__ import absolute_import, division, print_function, unicode_literals - import os import xml.etree.ElementTree as ET - import polib def kodi_to_ansi(string): - ''' Convert Kodi format tags to ANSI codes ''' + """Convert Kodi format tags to ANSI codes""" if string is None: return None string = string.replace('[B]', '\033[1m') @@ -34,17 +32,17 @@ def kodi_to_ansi(string): def uri_to_path(uri): - ''' Shorten a plugin URI to just the path ''' + """Shorten a plugin URI to just the path""" if uri is None: return None return ' \033[33m→ \033[34m%s\033[39;0m' % uri.replace('plugin://' + ADDON_ID, '') def read_addon_xml(path): - ''' Parse the addon.xml and return an info dictionary ''' + """Parse the addon.xml and return an info dictionary""" info = dict( - path='./', # '/storage/.kodi/addons/plugin.video.viervijfzes - profile='special://userdata', # 'special://profile/addon_data/plugin.video.viervijfzes/', + path='./', # '/storage/.kodi/addons/plugin.video.vrt.nu', + profile='special://userdata', # 'special://profile/addon_data/plugin.video.vrt.nu/', type='xbmc.python.pluginsource', ) @@ -73,7 +71,7 @@ def read_addon_xml(path): def global_settings(): - ''' Use the global_settings file ''' + """Use the global_settings file""" import json try: with open('test/userdata/global_settings.json') as f: @@ -102,8 +100,8 @@ def global_settings(): return settings -def addon_settings(): - ''' Use the addon_settings file ''' +def addon_settings(addon_id=None): + """Use the addon_settings file""" import json try: with open('test/userdata/addon_settings.json') as f: @@ -114,23 +112,76 @@ def addon_settings(): # Read credentials from environment or credentials.json if 'ADDON_USERNAME' in os.environ and 'ADDON_PASSWORD' in os.environ: - print('Using credentials from the environment variables ADDON_USERNAME and ADDON_PASSWORD') + # print('Using credentials from the environment variables ADDON_USERNAME and ADDON_PASSWORD') settings[ADDON_ID]['username'] = os.environ.get('ADDON_USERNAME') settings[ADDON_ID]['password'] = os.environ.get('ADDON_PASSWORD') - settings[ADDON_ID]['profile'] = os.environ.get('ADDON_PROFILE') elif os.path.exists('test/userdata/credentials.json'): - print('Using credentials from test/userdata/credentials.json') + # print('Using credentials from test/userdata/credentials.json') with open('test/userdata/credentials.json') as f: credentials = json.load(f) settings[ADDON_ID].update(credentials) else: print("Error: Cannot use 'test/userdata/credentials.json'") + + if addon_id: + return settings[addon_id] + return settings def import_language(language): - ''' Process the language.po file ''' - return polib.pofile('resources/language/{language}/strings.po'.format(language=language)) + """Process the language.po file""" + try: + podb = polib.pofile('resources/language/{language}/strings.po'.format(language=language)) + except IOError: + podb = polib.pofile('resources/language/resource.language.en_gb/strings.po') + + podb.extend([ + # WEEKDAY_LONG + polib.POEntry(msgctxt='#11', msgstr='Monday'), + polib.POEntry(msgctxt='#12', msgstr='Tuesday'), + polib.POEntry(msgctxt='#13', msgstr='Wednesday'), + polib.POEntry(msgctxt='#14', msgstr='Thursday'), + polib.POEntry(msgctxt='#15', msgstr='Friday'), + polib.POEntry(msgctxt='#16', msgstr='Saturday'), + polib.POEntry(msgctxt='#17', msgstr='Sunday'), + # MONTH_LONG + polib.POEntry(msgctxt='#21', msgstr='January'), + polib.POEntry(msgctxt='#22', msgstr='February'), + polib.POEntry(msgctxt='#23', msgstr='March'), + polib.POEntry(msgctxt='#24', msgstr='April'), + polib.POEntry(msgctxt='#25', msgstr='May'), + polib.POEntry(msgctxt='#26', msgstr='June'), + polib.POEntry(msgctxt='#27', msgstr='July'), + polib.POEntry(msgctxt='#28', msgstr='August'), + polib.POEntry(msgctxt='#29', msgstr='September'), + polib.POEntry(msgctxt='#30', msgstr='October'), + polib.POEntry(msgctxt='#31', msgstr='November'), + polib.POEntry(msgctxt='#32', msgstr='December'), + # WEEKDAY_SHORT + polib.POEntry(msgctxt='#41', msgstr='Mon'), + polib.POEntry(msgctxt='#42', msgstr='Tue'), + polib.POEntry(msgctxt='#43', msgstr='Wed'), + polib.POEntry(msgctxt='#44', msgstr='Thu'), + polib.POEntry(msgctxt='#45', msgstr='Fri'), + polib.POEntry(msgctxt='#46', msgstr='Sat'), + polib.POEntry(msgctxt='#47', msgstr='Sun'), + # MONTH_LONG + polib.POEntry(msgctxt='#51', msgstr='Jan'), + polib.POEntry(msgctxt='#52', msgstr='Feb'), + polib.POEntry(msgctxt='#53', msgstr='Mar'), + polib.POEntry(msgctxt='#54', msgstr='Apr'), + polib.POEntry(msgctxt='#55', msgstr='May'), + polib.POEntry(msgctxt='#56', msgstr='Jun'), + polib.POEntry(msgctxt='#57', msgstr='Jul'), + polib.POEntry(msgctxt='#58', msgstr='Aug'), + polib.POEntry(msgctxt='#59', msgstr='Sep'), + polib.POEntry(msgctxt='#50', msgstr='Oct'), + polib.POEntry(msgctxt='#51', msgstr='Nov'), + polib.POEntry(msgctxt='#52', msgstr='Dec'), + ]) + + return podb ADDON_INFO = read_addon_xml('addon.xml') diff --git a/test/xbmcgui.py b/test/xbmcgui.py index 343679e..d1103be 100644 --- a/test/xbmcgui.py +++ b/test/xbmcgui.py @@ -1,42 +1,79 @@ # -*- coding: utf-8 -*- # Copyright: (c) 2019, Dag Wieers (@dagwieers) # GNU General Public License v3.0 (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -''' This file implements the Kodi xbmcgui module, either using stubs or alternative functionality ''' +"""This file implements the Kodi xbmcgui module, either using stubs or alternative functionality""" -# pylint: disable=invalid-name,too-many-arguments,unused-argument +# pylint: disable=invalid-name,super-on-old-class,too-many-arguments,unused-argument,useless-super-delegation from __future__ import absolute_import, division, print_function, unicode_literals - +import sys from xbmcextra import kodi_to_ansi -class Dialog: - ''' A reimplementation of the xbmcgui Dialog class ''' +class Control: + """A reimplementation of the xbmcgui Control class""" def __init__(self): - ''' A stub constructor for the xbmcgui Dialog class ''' + """A stub constructor for the xbmcgui Control class""" + + @staticmethod + def selectItem(index): + """A stub implementation for the xbmcgui Control class selectItem() method""" + return + + +class ControlLabel(Control): + """A reimplementation of the xbmcgui ControlLabel class""" + + def __init__(self): # pylint: disable=super-init-not-called + """A stub constructor for the xbmcgui ControlLabel class""" + + @staticmethod + def getLabel(): + """A stub implementation for the xbmcgui ControlLabel class getLabel() method""" + return 'Label' + + @staticmethod + def setLabel(label='', font=None, textColor=None, disabledColor=None, shadowColor=None, focusedColor=None, label2=''): + """A stub implementation for the xbmcgui ControlLabel class getLabel() method""" + + +class Dialog: + """A reimplementation of the xbmcgui Dialog class""" + + def __init__(self): + """A stub constructor for the xbmcgui Dialog class""" @staticmethod def notification(heading, message, icon=None, time=None, sound=None): - ''' A working implementation for the xbmcgui Dialog class notification() method ''' + """A working implementation for the xbmcgui Dialog class notification() method""" heading = kodi_to_ansi(heading) message = kodi_to_ansi(message) print('\033[37;44;1mNOTIFICATION:\033[35;49;1m [%s] \033[37;1m%s\033[39;0m' % (heading, message)) @staticmethod def ok(heading, line1, line2=None, line3=None): - ''' A stub implementation for the xbmcgui Dialog class ok() method ''' + """A stub implementation for the xbmcgui Dialog class ok() method""" heading = kodi_to_ansi(heading) line1 = kodi_to_ansi(line1) print('\033[37;44;1mOK:\033[35;49;1m [%s] \033[37;1m%s\033[39;0m' % (heading, line1)) @staticmethod def info(listitem): - ''' A stub implementation for the xbmcgui Dialog class info() method ''' + """A stub implementation for the xbmcgui Dialog class info() method""" + + @staticmethod + def select(heading, opt_list, autoclose=0, preselect=None, useDetails=False): + """A stub implementation for the xbmcgui Dialog class select() method""" + if preselect is None: + preselect = [] + heading = kodi_to_ansi(heading) + print('\033[37;44;1mSELECT:\033[35;49;1m [%s] \033[37;1m%s\033[39;0m' % (heading, ', '.join(opt_list))) + return -1 @staticmethod def multiselect(heading, options, autoclose=0, preselect=None, useDetails=False): # pylint: disable=useless-return - ''' A stub implementation for the xbmcgui Dialog class multiselect() method ''' + """A stub implementation for the xbmcgui Dialog class multiselect() method""" if preselect is None: preselect = [] heading = kodi_to_ansi(heading) @@ -45,13 +82,13 @@ class Dialog: @staticmethod def contextmenu(items): - ''' A stub implementation for the xbmcgui Dialog class contextmenu() method ''' + """A stub implementation for the xbmcgui Dialog class contextmenu() method""" print('\033[37;44;1mCONTEXTMENU:\033[35;49;1m \033[37;1m%s\033[39;0m' % (', '.join(items))) return -1 @staticmethod def yesno(heading, line1, line2=None, line3=None, nolabel=None, yeslabel=None, autoclose=0): - ''' A stub implementation for the xbmcgui Dialog class yesno() method ''' + """A stub implementation for the xbmcgui Dialog class yesno() method""" heading = kodi_to_ansi(heading) line1 = kodi_to_ansi(line1) print('\033[37;44;1mYESNO:\033[35;49;1m [%s] \033[37;1m%s\033[39;0m' % (heading, line1)) @@ -59,44 +96,45 @@ class Dialog: @staticmethod def textviewer(heading, text=None, usemono=None): - ''' A stub implementation for the xbmcgui Dialog class textviewer() method ''' + """A stub implementation for the xbmcgui Dialog class textviewer() method""" heading = kodi_to_ansi(heading) text = kodi_to_ansi(text) print('\033[37;44;1mTEXTVIEWER:\033[35;49;1m [%s]\n\033[37;1m%s\033[39;0m' % (heading, text)) @staticmethod - def browseSingle(type, heading, shares, mask=None, useThumbs=None, treatAsFolder=None, default=None): # pylint: disable=redefined-builtin - ''' A stub implementation for the xbmcgui Dialog class browseSingle() method ''' + def browseSingle(type, heading, shares, mask=None, useThumbs=None, treatAsFolder=None, defaultt=None): # pylint: disable=redefined-builtin + """A stub implementation for the xbmcgui Dialog class browseSingle() method""" print('\033[37;44;1mBROWSESINGLE:\033[35;49;1m [%s] \033[37;1m%s\033[39;0m' % (type, heading)) return 'special://masterprofile/addon_data/script.module.inputstreamhelper/' class DialogProgress: - ''' A reimplementation of the xbmcgui DialogProgress ''' + """A reimplementation of the xbmcgui DialogProgress""" def __init__(self): - ''' A stub constructor for the xbmcgui DialogProgress class ''' + """A stub constructor for the xbmcgui DialogProgress class""" self.percentage = 0 - @staticmethod - def close(): - ''' A stub implementation for the xbmcgui DialogProgress class close() method ''' + def close(self): + """A stub implementation for the xbmcgui DialogProgress class close() method""" + self.percentage = 0 print() + sys.stdout.flush() - @staticmethod - def create(heading, line1, line2=None, line3=None): - ''' A stub implementation for the xbmcgui DialogProgress class create() method ''' + def create(self, heading, line1, line2=None, line3=None): + """A stub implementation for the xbmcgui DialogProgress class create() method""" + self.percentage = 0 heading = kodi_to_ansi(heading) line1 = kodi_to_ansi(line1) print('\033[37;44;1mPROGRESS:\033[35;49;1m [%s] \033[37;1m%s\033[39;0m' % (heading, line1)) + sys.stdout.flush() @staticmethod def iscanceled(): - ''' A stub implementation for the xbmcgui DialogProgress class iscanceled() method ''' - return True + """A stub implementation for the xbmcgui DialogProgress class iscanceled() method""" def update(self, percentage, line1=None, line2=None, line3=None): - ''' A stub implementation for the xbmcgui DialogProgress class update() method ''' + """A stub implementation for the xbmcgui DialogProgress class update() method""" if (percentage - 5) < self.percentage: return self.percentage = percentage @@ -104,36 +142,37 @@ class DialogProgress: line2 = kodi_to_ansi(line2) line3 = kodi_to_ansi(line3) if line1 or line2 or line3: - print('\033[37;44;1mPROGRESS:\033[35;49;1m [%d%%] \033[37;1m%s\033[39;0m' % (percentage, line1 or line2 or line3)) + print('\033[1G\033[37;44;1mPROGRESS:\033[35;49;1m [%d%%] \033[37;1m%s\033[39;0m' % (percentage, line1 or line2 or line3), end='') else: print('\033[1G\033[37;44;1mPROGRESS:\033[35;49;1m [%d%%]\033[39;0m' % (percentage), end='') + sys.stdout.flush() class DialogProgressBG: - ''' A reimplementation of the xbmcgui DialogProgressBG ''' + """A reimplementation of the xbmcgui DialogProgressBG""" def __init__(self): - ''' A stub constructor for the xbmcgui DialogProgressBG class ''' + """A stub constructor for the xbmcgui DialogProgressBG class""" self.percentage = 0 @staticmethod def close(): - ''' A stub implementation for the xbmcgui DialogProgressBG class close() method ''' + """A stub implementation for the xbmcgui DialogProgressBG class close() method""" print() @staticmethod def create(heading, message): - ''' A stub implementation for the xbmcgui DialogProgressBG class create() method ''' + """A stub implementation for the xbmcgui DialogProgressBG class create() method""" heading = kodi_to_ansi(heading) message = kodi_to_ansi(message) print('\033[37;44;1mPROGRESS:\033[35;49;1m [%s] \033[37;1m%s\033[39;0m' % (heading, message)) @staticmethod def isfinished(): - ''' A stub implementation for the xbmcgui DialogProgressBG class isfinished() method ''' + """A stub implementation for the xbmcgui DialogProgressBG class isfinished() method""" def update(self, percentage, heading=None, message=None): - ''' A stub implementation for the xbmcgui DialogProgressBG class update() method ''' + """A stub implementation for the xbmcgui DialogProgressBG class update() method""" if (percentage - 5) < self.percentage: return self.percentage = percentage @@ -145,79 +184,144 @@ class DialogProgressBG: class DialogBusy: - ''' A reimplementation of the xbmcgui DialogBusy ''' + """A reimplementation of the xbmcgui DialogBusy""" def __init__(self): - ''' A stub constructor for the xbmcgui DialogBusy class ''' + """A stub constructor for the xbmcgui DialogBusy class""" @staticmethod def close(): - ''' A stub implementation for the xbmcgui DialogBusy class close() method ''' + """A stub implementation for the xbmcgui DialogBusy class close() method""" @staticmethod def create(): - ''' A stub implementation for the xbmcgui DialogBusy class create() method ''' + """A stub implementation for the xbmcgui DialogBusy class create() method""" class ListItem: - ''' A reimplementation of the xbmcgui ListItem class ''' + """A reimplementation of the xbmcgui ListItem class""" def __init__(self, label='', label2='', iconImage='', thumbnailImage='', path='', offscreen=False): - ''' A stub constructor for the xbmcgui ListItem class ''' + """A stub constructor for the xbmcgui ListItem class""" self.label = kodi_to_ansi(label) self.label2 = kodi_to_ansi(label2) self.path = path @staticmethod def addContextMenuItems(items, replaceItems=False): - ''' A stub implementation for the xbmcgui ListItem class addContextMenuItems() method ''' + """A stub implementation for the xbmcgui ListItem class addContextMenuItems() method""" return @staticmethod def addStreamInfo(stream_type, stream_values): - ''' A stub implementation for the xbmcgui LitItem class addStreamInfo() method ''' + """A stub implementation for the xbmcgui LitItem class addStreamInfo() method""" return @staticmethod def setArt(key): - ''' A stub implementation for the xbmcgui ListItem class setArt() method ''' + """A stub implementation for the xbmcgui ListItem class setArt() method""" return @staticmethod def setContentLookup(enable): - ''' A stub implementation for the xbmcgui ListItem class setContentLookup() method ''' + """A stub implementation for the xbmcgui ListItem class setContentLookup() method""" return @staticmethod def setInfo(type, infoLabels): # pylint: disable=redefined-builtin - ''' A stub implementation for the xbmcgui ListItem class setInfo() method ''' + """A stub implementation for the xbmcgui ListItem class setInfo() method""" return @staticmethod def setIsFolder(isFolder): - ''' A stub implementation for the xbmcgui ListItem class setIsFolder() method ''' + """A stub implementation for the xbmcgui ListItem class setIsFolder() method""" return @staticmethod def setMimeType(mimetype): - ''' A stub implementation for the xbmcgui ListItem class setMimeType() method ''' + """A stub implementation for the xbmcgui ListItem class setMimeType() method""" return def setPath(self, path): - ''' A stub implementation for the xbmcgui ListItem class setPath() method ''' + """A stub implementation for the xbmcgui ListItem class setPath() method""" self.path = path @staticmethod def setProperty(key, value): - ''' A stub implementation for the xbmcgui ListItem class setProperty() method ''' + """A stub implementation for the xbmcgui ListItem class setProperty() method""" return @staticmethod def setProperties(dictionary): - ''' A stub implementation for the xbmcgui ListItem class setProperties() method ''' + """A stub implementation for the xbmcgui ListItem class setProperties() method""" return @staticmethod def setSubtitles(subtitleFiles): - ''' A stub implementation for the xbmcgui ListItem class setSubtitles() method ''' + """A stub implementation for the xbmcgui ListItem class setSubtitles() method""" return + + @staticmethod + def setUniqueIDs(values, defaultrating=None): + """A stub implementation for the xbmcgui ListItem class setUniqueIDs() method""" + return + + +class Window: + """A reimplementation of the xbmcgui Window""" + + def __init__(self, windowId): + """A stub constructor for the xbmcgui Window class""" + return None + + def close(self): + """A stub implementation for the xbmcgui Window class close() method""" + + @staticmethod + def getControl(): + """A stub implementation for the xbmcgui Window class getControl() method""" + return ControlLabel() + + @staticmethod + def getFocusId(): + """A stub implementation for the xbmcgui Window class getFocusId() method""" + return 0 + + @staticmethod + def getProperty(key): + """A stub implementation for the xbmcgui Window class getProperty() method""" + return '' + + @staticmethod + def setProperty(key, value): + """A stub implementation for the xbmcgui Window class setProperty() method""" + return + + @staticmethod + def clearProperty(key): + """A stub implementation for the xbmcgui Window class clearProperty() method""" + return + + def show(self): + """A stub implementation for the xbmcgui Window class show() method""" + + +class WindowXML(Window): + """A reimplementation of the xbmcgui WindowXML""" + + def __init__(self): + """A stub constructor for the xbmcgui WindowXML class""" + super(WindowXML, self).__init__() + + +class WindowXMLDialog(WindowXML): + """A reimplementation of the xbmcgui WindowXMLDialog""" + + def __init__(self): + """A stub constructor for the xbmcgui WindowXMLDialog class""" + super(WindowXMLDialog, self).__init__() + + +def getCurrentWindowId(): + """A stub implementation of the xbmcgui getCurrentWindowId() method""" + return 0 diff --git a/test/xbmcplugin.py b/test/xbmcplugin.py index b5da85a..b8a0305 100644 --- a/test/xbmcplugin.py +++ b/test/xbmcplugin.py @@ -1,12 +1,12 @@ # -*- coding: utf-8 -*- # Copyright: (c) 2019, Dag Wieers (@dagwieers) # GNU General Public License v3.0 (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -''' This file implements the Kodi xbmcplugin module, either using stubs or alternative functionality ''' +"""This file implements the Kodi xbmcplugin module, either using stubs or alternative functionality""" # pylint: disable=invalid-name,unused-argument from __future__ import absolute_import, division, print_function, unicode_literals -from xbmc import log, LOGERROR +from xbmc import LOGFATAL, LOGINFO, log from xbmcextra import kodi_to_ansi, uri_to_path try: # Python 3 @@ -63,49 +63,50 @@ SORT_METHOD_DATE_TAKEN = 44 def addDirectoryItem(handle, path, listitem, isFolder=False): - ''' A reimplementation of the xbmcplugin addDirectoryItems() function ''' + """A reimplementation of the xbmcplugin addDirectoryItems() function""" label = kodi_to_ansi(listitem.label) path = uri_to_path(path) if path else '' + # perma = kodi_to_ansi(listitem.label) # FIXME: Add permalink bullet = '»' if isFolder else '·' print('{bullet} {label}{path}'.format(bullet=bullet, label=label, path=path)) return True def addDirectoryItems(handle, listing, length): - ''' A reimplementation of the xbmcplugin addDirectoryItems() function ''' + """A reimplementation of the xbmcplugin addDirectoryItems() function""" for item in listing: addDirectoryItem(handle, item[0], item[1], item[2]) return True def addSortMethod(handle, sortMethod): - ''' A stub implementation of the xbmcplugin addSortMethod() function ''' + """A stub implementation of the xbmcplugin addSortMethod() function""" def endOfDirectory(handle, succeeded=True, updateListing=True, cacheToDisc=True): - ''' A stub implementation of the xbmcplugin endOfDirectory() function ''' - print(kodi_to_ansi('[B]-=( [COLOR cyan]--------[/COLOR] )=-[/B]')) + """A stub implementation of the xbmcplugin endOfDirectory() function""" + # print(kodi_to_ansi('[B]-=( [COLOR cyan]--------[/COLOR] )=-[/B]')) def setContent(handle, content): - ''' A stub implementation of the xbmcplugin setContent() function ''' + """A stub implementation of the xbmcplugin setContent() function""" def setPluginFanart(handle, image, color1=None, color2=None, color3=None): - ''' A stub implementation of the xbmcplugin setPluginFanart() function ''' + """A stub implementation of the xbmcplugin setPluginFanart() function""" def setPluginCategory(handle, category): - ''' A reimplementation of the xbmcplugin setPluginCategory() function ''' + """A reimplementation of the xbmcplugin setPluginCategory() function""" print(kodi_to_ansi('[B]-=( [COLOR cyan]%s[/COLOR] )=-[/B]' % category)) def setResolvedUrl(handle, succeeded, listitem): - ''' A stub implementation of the xbmcplugin setResolvedUrl() function ''' + """A stub implementation of the xbmcplugin setResolvedUrl() function""" request = Request(listitem.path) request.get_method = lambda: 'HEAD' try: response = urlopen(request) - log('Stream playing successfully: %s' % response.code) + log('Stream playing successfully: %s' % response.code, LOGINFO) except HTTPError as exc: - log('Playing stream returned: %s' % exc, LOGERROR) + log('Playing stream returned: %s' % exc, LOGFATAL) diff --git a/test/xbmcvfs.py b/test/xbmcvfs.py index 0daf157..f2ebb1c 100644 --- a/test/xbmcvfs.py +++ b/test/xbmcvfs.py @@ -1,38 +1,44 @@ # -*- coding: utf-8 -*- # Copyright: (c) 2019, Dag Wieers (@dagwieers) # GNU General Public License v3.0 (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -''' This file implements the Kodi xbmcvfs module, either using stubs or alternative functionality ''' +"""This file implements the Kodi xbmcvfs module, either using stubs or alternative functionality""" # pylint: disable=invalid-name from __future__ import absolute_import, division, print_function, unicode_literals import os +from shutil import copyfile def File(path, flags='r'): - ''' A reimplementation of the xbmcvfs File() function ''' + """A reimplementation of the xbmcvfs File() function""" return open(path, flags) def Stat(path): - ''' A reimplementation of the xbmcvfs Stat() function ''' + """A reimplementation of the xbmcvfs Stat() function""" class stat: - ''' A reimplementation of the xbmcvfs stat class ''' + """A reimplementation of the xbmcvfs stat class""" def __init__(self, path): - ''' The constructor xbmcvfs stat class ''' + """The constructor xbmcvfs stat class""" self._stat = os.stat(path) def st_mtime(self): - ''' The xbmcvfs stat class st_mtime method ''' + """The xbmcvfs stat class st_mtime method""" return self._stat.st_mtime return stat(path) +def copy(src, dst): + """A reimplementation of the xbmcvfs mkdir() function""" + return copyfile(src, dst) == dst + + def delete(path): - ''' A reimplementation of the xbmcvfs delete() function ''' + """A reimplementation of the xbmcvfs delete() function""" try: os.remove(path) except OSError: @@ -40,32 +46,35 @@ def delete(path): def exists(path): - ''' A reimplementation of the xbmcvfs exists() function ''' + """A reimplementation of the xbmcvfs exists() function""" return os.path.exists(path) def listdir(path): - ''' A reimplementation of the xbmcvfs listdir() function ''' + """A reimplementation of the xbmcvfs listdir() function""" files = [] dirs = [] + if not exists(path): + return dirs, files for filename in os.listdir(path): - if os.path.isfile(filename): + fullname = os.path.join(path, filename) + if os.path.isfile(fullname): files.append(filename) - if os.path.isdir(filename): + if os.path.isdir(fullname): dirs.append(filename) return dirs, files def mkdir(path): - ''' A reimplementation of the xbmcvfs mkdir() function ''' + """A reimplementation of the xbmcvfs mkdir() function""" return os.mkdir(path) def mkdirs(path): - ''' A reimplementation of the xbmcvfs mkdirs() function ''' + """A reimplementation of the xbmcvfs mkdirs() function""" return os.makedirs(path) def rmdir(path): - ''' A reimplementation of the xbmcvfs rmdir() function ''' + """A reimplementation of the xbmcvfs rmdir() function""" return os.rmdir(path)