Skip to content

Commit

Permalink
Use sake for Kodi stubs (#191)
Browse files Browse the repository at this point in the history
* Use sake for kodi stubs
  • Loading branch information
michaelarnauts committed Jul 20, 2020
1 parent db4935a commit 409d3d6
Show file tree
Hide file tree
Showing 30 changed files with 73 additions and 930 deletions.
5 changes: 4 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ jobs:
env:
PYTHONIOENCODING: utf-8
PYTHONPATH: ${{ github.workspace }}/resources/lib:${{ github.workspace }}/tests
KODI_HOME: ${{ github.workspace }}/tests/home
KODI_INTERACTIVE: 0
KODI_STUB_RPC_RESPONSES: ${{ github.workspace }}/tests/rpc
strategy:
fail-fast: false
matrix:
Expand Down Expand Up @@ -39,7 +42,7 @@ jobs:
ADDON_USERNAME: ${{ secrets.ADDON_USERNAME }}
ADDON_PROFILE: ${{ secrets.ADDON_PROFILE }}
- name: Run addon service
run: coverage run -a service.py
run: timeout --preserve-status -s SIGINT 10 coverage run -a service.py
env:
ADDON_PASSWORD: ${{ secrets.ADDON_PASSWORD }}
ADDON_USERNAME: ${{ secrets.ADDON_USERNAME }}
Expand Down
7 changes: 1 addition & 6 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,4 @@ Thumbs.db

.coverage
.tox/
tests/userdata/credentials.json
tests/userdata/temp
tests/userdata/token.json
tests/userdata/cache
tests/userdata/addon_data
tests/cdm
tests/home/userdata/addon_data
4 changes: 3 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export PYTHONPATH := $(CURDIR):$(CURDIR)/tests
export KODI_HOME := $(CURDIR)/tests/home
export KODI_INTERACTIVE := 0
export KODI_STUB_RPC_RESPONSES := $(CURDIR)/tests/rpc
PYTHON := python

# Collect information to build as sensible package name
Expand Down
4 changes: 3 additions & 1 deletion plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
""" Addon entry point """

from __future__ import absolute_import, division, unicode_literals
from resources.lib import kodiwrapper, kodilogging

from xbmcaddon import Addon

from resources.lib import kodiwrapper, kodilogging

# Reinitialise ADDON every invocation to fix an issue that settings are not fresh.
kodiwrapper.ADDON = Addon()
kodilogging.ADDON = Addon()
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
coverage
git+git://github.com/emilsvennesson/script.module.inputstreamhelper.git@master#egg=inputstreamhelper
polib
pylint
python-dateutil
requests
git+git://github.com/dagwieers/kodi-plugin-routing.git@setup#egg=routing
tox
sakee
1 change: 0 additions & 1 deletion resources/lib/kodilogging.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,3 @@ def config():
""" Setup the logger with this handler """
logger = logging.getLogger()
logger.addHandler(KodiLogHandler())
logger.setLevel(logging.DEBUG)
17 changes: 9 additions & 8 deletions resources/lib/kodiwrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from __future__ import absolute_import, division, unicode_literals

import logging
import os
from contextlib import contextmanager

import xbmc
Expand Down Expand Up @@ -109,7 +110,7 @@ def __init__(self, addon=None):
self._url = None
self._addon_name = ADDON.getAddonInfo('name')
self._addon_id = ADDON.getAddonInfo('id')
self._cache_path = self.get_userdata_path() + 'cache/'
self._cache_path = os.path.join(self.get_userdata_path(), 'cache')

def url_for(self, name, *args, **kwargs):
""" Wrapper for routing.url_for() to lookup by name """
Expand Down Expand Up @@ -254,7 +255,7 @@ def show_ok_dialog(self, heading='', message=''):
if not heading:
heading = ADDON.getAddonInfo('name')
if self.kodi_version_major() < 19:
return Dialog().ok(heading=heading, line1=message)
return Dialog().ok(heading=heading, line1=message) # pylint: disable=unexpected-keyword-arg,no-value-for-parameter
return Dialog().ok(heading=heading, message=message)

def show_yesno_dialog(self, heading='', message='', nolabel=None, yeslabel=None, autoclose=0):
Expand All @@ -263,7 +264,7 @@ def show_yesno_dialog(self, heading='', message='', nolabel=None, yeslabel=None,
if not heading:
heading = ADDON.getAddonInfo('name')
if self.kodi_version_major() < 19:
return Dialog().yesno(heading=heading, line1=message, nolabel=nolabel, yeslabel=yeslabel, autoclose=autoclose)
return Dialog().yesno(heading=heading, line1=message, nolabel=nolabel, yeslabel=yeslabel, autoclose=autoclose) # pylint: disable=unexpected-keyword-arg,no-value-for-parameter
return Dialog().yesno(heading=heading, message=message, nolabel=nolabel, yeslabel=yeslabel, autoclose=autoclose)

@staticmethod
Expand Down Expand Up @@ -297,15 +298,15 @@ def create(self, heading, message=''): # pylint: disable=arguments-differ
if KodiWrapper().kodi_version_major() < 19:
lines = message.split('\n', 2)
line1, line2, line3 = (lines + [None] * (3 - len(lines)))
return super(KodiWrapper.show_progress, self).create(heading, line1=line1, line2=line2, line3=line3)
return super(KodiWrapper.show_progress, self).create(heading, line1=line1, line2=line2, line3=line3) # pylint: disable=unexpected-keyword-arg,no-value-for-parameter
return super(KodiWrapper.show_progress, self).create(heading, message=message)

def update(self, percent, message=''): # pylint: disable=arguments-differ
"""Update the progress dialog"""
if KodiWrapper().kodi_version_major() < 19:
lines = message.split('\n', 2)
line1, line2, line3 = (lines + [None] * (3 - len(lines)))
return super(KodiWrapper.show_progress, self).update(percent, line1=line1, line2=line2, line3=line3)
return super(KodiWrapper.show_progress, self).update(percent, line1=line1, line2=line2, line3=line3) # pylint: disable=unexpected-keyword-arg,no-value-for-parameter
return super(KodiWrapper.show_progress, self).update(percent, message=message)

@staticmethod
Expand Down Expand Up @@ -376,7 +377,7 @@ def get_cache(self, key, ttl=None):
"""
import time

fullpath = self._cache_path + '.'.join(key)
fullpath = os.path.join(self._cache_path, '.'.join(key))

if not self.check_if_path_exists(fullpath):
return None
Expand All @@ -401,7 +402,7 @@ def set_cache(self, key, data):
if not self.check_if_path_exists(self._cache_path):
self.mkdirs(self._cache_path)

fullpath = self._cache_path + '.'.join(key)
fullpath = os.path.join(self._cache_path, '.'.join(key))
with self.open_file(fullpath, 'w') as fdesc:
import json
_LOGGER.debug('Storing to cache as %s', fullpath)
Expand All @@ -415,7 +416,7 @@ def invalidate_cache(self, ttl=None):
import time
now = time.mktime(time.localtime())
for filename in files:
fullpath = self._cache_path + filename
fullpath = os.path.join(self._cache_path, filename)
if ttl and now - self.stat_file(fullpath).st_mtime() < ttl:
continue
self.delete_file(fullpath)
Expand Down
2 changes: 1 addition & 1 deletion resources/lib/modules/player.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ def play(self, category, item):
return

# Send Up Next data
if upnext_data:
if upnext_data and self._kodi.get_setting_as_bool('useupnext'):
_LOGGER.debug("Sending Up Next data: %s", upnext_data)
self.send_upnext(upnext_data)

Expand Down
2 changes: 1 addition & 1 deletion resources/lib/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ def __check_subtitles(self):
_LOGGER.debug('Player: Disabling subtitles')
self.showSubtitles(False)

def onPlayBackSeek(self, seekTime, seekOffset): # pylint: disable=invalid-name, unused-argument
def onPlayBackSeek(self, time, seekOffset): # pylint: disable=invalid-name, unused-argument, redefined-outer-name
""" Will be called when user seeks to a time """
if not self.__listen:
return
Expand Down
5 changes: 3 additions & 2 deletions resources/lib/vtmgo/vtmgoauth.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import hashlib
import logging
import os
import re

import requests
Expand Down Expand Up @@ -53,7 +54,7 @@ def clear_token(self):
""" Remove the cached JWT. """
_LOGGER.debug('Clearing token cache')
self._token = None
path = self._kodi.get_userdata_path() + 'token.json'
path = os.path.join(self._kodi.get_userdata_path(), 'token.json')
if self._kodi.check_if_path_exists(path):
self._kodi.delete_file(path)
self._kodi.set_setting('profile', None)
Expand All @@ -73,7 +74,7 @@ def get_token(self):
return self._token

# Try to load from cache
path = self._kodi.get_userdata_path() + 'token.json'
path = os.path.join(self._kodi.get_userdata_path(), 'token.json')
if self._kodi.check_if_path_exists(path):
_LOGGER.debug('Returning token from cache')

Expand Down
4 changes: 2 additions & 2 deletions resources/lib/vtmgo/vtmgostream.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import json
import logging
import os
import random
from datetime import timedelta

Expand Down Expand Up @@ -252,7 +253,7 @@ def _delay_subtitles(self, subtitles, json_manifest):
:rtype list[str]
"""
# Clean up old subtitles
temp_dir = self._kodi.get_userdata_path() + 'temp/'
temp_dir = os.path.join(self._kodi.get_userdata_path(), 'temp')
_, files = self._kodi.listdir(temp_dir)
if files:
for item in files:
Expand Down Expand Up @@ -300,7 +301,6 @@ def _anvato_get_anvacks(self, access_key):
},
headers={
'X-Anvato-User-Agent': self._ANVATO_USER_AGENT,
'User-Agent': self._ANVATO_USER_AGENT,
})

_LOGGER.debug('Got response (status=%s): %s', response.status_code, response.text)
Expand Down
18 changes: 17 additions & 1 deletion tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,21 @@
from __future__ import absolute_import, division, unicode_literals

import logging
import os
import sys

logging.basicConfig()
import xbmcaddon

logging.basicConfig(level=logging.DEBUG)

# Make UTF-8 the default encoding in Python 2
if sys.version_info[0] == 2:
reload(sys) # pylint: disable=undefined-variable
sys.setdefaultencoding("utf-8") # pylint: disable=no-member

# Set credentials based on environment data
if os.environ.get('ADDON_USERNAME') and os.environ.get('ADDON_PASSWORD'):
ADDON = xbmcaddon.Addon()
ADDON.setSetting('username', os.environ.get('ADDON_USERNAME'))
ADDON.setSetting('password', os.environ.get('ADDON_PASSWORD'))
ADDON.setSetting('profile', os.environ.get('ADDON_PROFILE'))
3 changes: 3 additions & 0 deletions tests/home/addons/inputstream.adaptive/addon.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<addon id="inputstream.adaptive" version="2.4.4" name="InputStream Adaptive" provider-name="peak3d">
</addon>
3 changes: 3 additions & 0 deletions tests/home/addons/script.module.inputstreamhelper/addon.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<addon id="script.module.inputstreamhelper" name="InputStream Helper" version="0.5.0" provider-name="emilsvennesson, dagwieers, mediaminister, horstle">
</addon>
Empty file added tests/home/system/.gitkeep
Empty file.
4 changes: 4 additions & 0 deletions tests/home/userdata/guisettings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<settings version="2">
<setting id="videolibrary.showallitems" default="true">true</setting>
<setting id="network.bandwidth" default="true">0</setting>
</settings>
6 changes: 0 additions & 6 deletions tests/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,6 @@
sys.path.insert(0, cwd)
from resources.lib import plugin # noqa: E402 pylint: disable=wrong-import-position

xbmc = __import__('xbmc')
xbmcaddon = __import__('xbmcaddon')
xbmcgui = __import__('xbmcgui')
xbmcplugin = __import__('xbmcplugin')
xbmcvfs = __import__('xbmcvfs')

if len(sys.argv) <= 1:
print("%s: URI argument missing\nTry '%s plugin://plugin.video.vtm.go/' to test." % (sys.argv[0], sys.argv[0]))
sys.exit(1)
Expand Down
15 changes: 5 additions & 10 deletions tests/test_routing.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,11 @@

import unittest

import xbmc

from resources.lib import plugin
from resources.lib.kodiwrapper import KodiWrapper

xbmc = __import__('xbmc')
xbmcaddon = __import__('xbmcaddon')
xbmcgui = __import__('xbmcgui')
xbmcplugin = __import__('xbmcplugin')
xbmcvfs = __import__('xbmcvfs')

routing = plugin.routing
kodi = KodiWrapper(globals())

Expand All @@ -31,6 +27,9 @@ def setUp(self):
# warnings.simplefilter("ignore", ResourceWarning)
pass

def tearDown(self):
xbmc.Player().stop()

def test_main_menu(self):
routing.run([routing.url_for(plugin.show_main_menu), '0', ''])

Expand Down Expand Up @@ -86,10 +85,6 @@ def test_play_epg(self):
timestamp = datetime.datetime.now().replace(hour=6, minute=0, second=0)
plugin.run([routing.url_for(plugin.play_epg_datetime, channel='vtm', timestamp=timestamp.isoformat()), '0', ''])

def test_metadata_update(self):
routing.run([routing.url_for(plugin.metadata_clean), '0', ''])
routing.run([routing.url_for(plugin.metadata_update), '0', ''])


if __name__ == '__main__':
unittest.main()
5 changes: 5 additions & 0 deletions tests/test_vtmgo.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

import unittest

import xbmc

from resources.lib.kodiwrapper import KodiWrapper
from resources.lib.modules.player import Player
from resources.lib.vtmgo import vtmgo, vtmgostream, vtmgoauth
Expand All @@ -32,6 +34,9 @@ def setUp(self):
# warnings.simplefilter("ignore", ResourceWarning)
pass

def tearDown(self):
xbmc.Player().stop()

@unittest.skipUnless(kodi.has_credentials(), 'Skipping since we have no credentials.')
def test_login(self):
token = self._vtmgoauth.get_token()
Expand Down
8 changes: 7 additions & 1 deletion tests/test_vtmgoepg.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

import unittest

import xbmc

from resources.lib import plugin
from resources.lib.kodiwrapper import KodiWrapper
from resources.lib.vtmgo import vtmgoepg
Expand All @@ -28,6 +30,9 @@ def setUp(self):
# warnings.simplefilter("ignore", ResourceWarning)
pass

def tearDown(self):
xbmc.Player().stop()

def test_get_broadcast(self):
import datetime
import dateutil
Expand Down Expand Up @@ -66,7 +71,8 @@ def test_get_epg(self):

broadcast = next(b for b in combined_broadcasts if b.playable_type == 'movies')
if broadcast:
plugin.run([routing.url_for(plugin.play, category=broadcast.playable_type, item=broadcast.playable_uuid), '0', ''])
plugin.run(
[routing.url_for(plugin.play, category=broadcast.playable_type, item=broadcast.playable_uuid), '0', ''])


if __name__ == '__main__':
Expand Down
19 changes: 0 additions & 19 deletions tests/userdata/addon_settings.json

This file was deleted.

6 changes: 0 additions & 6 deletions tests/userdata/credentials.json.example

This file was deleted.

6 changes: 0 additions & 6 deletions tests/userdata/global_settings.json

This file was deleted.

Loading

0 comments on commit 409d3d6

Please sign in to comment.