From a58decf2434d695482e142e945cd32d266012cf5 Mon Sep 17 00:00:00 2001 From: Dag Wieers Date: Tue, 24 Mar 2020 21:27:12 +0100 Subject: [PATCH] Use GitHub actions for CI testing (#702) This PR includes: - Add a GitHub Actions workflow for CI testing - Remove Travis CI support - Move test/ to tests/ (unittest standard?) - Fix a coloring issue in xbmcextra - Various new fixes to tracebacks in GitHub CI --- .github/workflows/ci.yml | 56 +++++++++++++++++ .gitignore | 11 ++-- .travis.yml | 32 ---------- Makefile | 60 ++++++++++--------- README.md | 2 +- .codecov.yml => codecov.yml | 2 +- requirements.txt | 8 ++- .../resource.language.nl_nl/strings.po | 8 +-- resources/lib/apihelper.py | 2 +- resources/lib/kodiutils.py | 2 +- resources/lib/resumepoints.py | 2 +- resources/lib/tokenresolver.py | 9 ++- resources/lib/tvguide.py | 4 +- {test => tests}/__init__.py | 0 {test => tests}/read_profiling_stats.py | 0 {test => tests}/run.py | 0 {test => tests}/test_apihelper.py | 0 {test => tests}/test_favorites.py | 0 {test => tests}/test_kodiutils.py | 0 {test => tests}/test_language.py | 0 {test => tests}/test_proxy.py | 4 +- {test => tests}/test_resumepoints.py | 0 {test => tests}/test_routing.py | 0 {test => tests}/test_search.py | 0 {test => tests}/test_settings.py | 0 {test => tests}/test_streamservice.py | 16 ++--- {test => tests}/test_tokenresolver.py | 0 {test => tests}/test_tvguide.py | 0 {test => tests}/test_utils.py | 0 {test => tests}/test_vrtplayer.py | 0 {test => tests}/test_webscraper.py | 0 {test => tests}/userdata/addon_settings.json | 0 {test => tests}/userdata/global_settings.json | 0 {test => tests}/userdata/search_history.json | 0 {test => tests}/xbmc.py | 8 +-- {test => tests}/xbmcaddon.py | 0 {test => tests}/xbmcextra.py | 38 ++++++------ {test => tests}/xbmcgui.py | 0 {test => tests}/xbmcplugin.py | 4 +- {test => tests}/xbmcvfs.py | 0 tox.ini | 1 + 41 files changed, 153 insertions(+), 116 deletions(-) create mode 100644 .github/workflows/ci.yml delete mode 100644 .travis.yml rename .codecov.yml => codecov.yml (95%) rename {test => tests}/__init__.py (100%) rename {test => tests}/read_profiling_stats.py (100%) rename {test => tests}/run.py (100%) rename {test => tests}/test_apihelper.py (100%) rename {test => tests}/test_favorites.py (100%) rename {test => tests}/test_kodiutils.py (100%) rename {test => tests}/test_language.py (100%) rename {test => tests}/test_proxy.py (94%) rename {test => tests}/test_resumepoints.py (100%) rename {test => tests}/test_routing.py (100%) rename {test => tests}/test_search.py (100%) rename {test => tests}/test_settings.py (100%) rename {test => tests}/test_streamservice.py (92%) rename {test => tests}/test_tokenresolver.py (100%) rename {test => tests}/test_tvguide.py (100%) rename {test => tests}/test_utils.py (100%) rename {test => tests}/test_vrtplayer.py (100%) rename {test => tests}/test_webscraper.py (100%) rename {test => tests}/userdata/addon_settings.json (100%) rename {test => tests}/userdata/global_settings.json (100%) rename {test => tests}/userdata/search_history.json (100%) rename {test => tests}/xbmc.py (98%) rename {test => tests}/xbmcaddon.py (100%) rename {test => tests}/xbmcextra.py (85%) rename {test => tests}/xbmcgui.py (100%) rename {test => tests}/xbmcplugin.py (96%) rename {test => tests}/xbmcvfs.py (100%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..673b7ec1 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,56 @@ +name: CI +on: + push: + branches: + - master + - tests-overhaul + pull_request: + branches: + - master + - tests-overhaul +jobs: + tests: + name: Add-on testing + runs-on: ubuntu-latest + env: + PYTHONIOENCODING: utf-8 + PYTHONPATH: ${{ github.workspace }}/resources/lib:${{ github.workspace }}/tests + strategy: + fail-fast: false + matrix: +# max-parallel: 2 + python-version: [ 2.7, 3.5, 3.6, 3.7, 3.8 ] + steps: + - name: Check out ${{ github.sha }} from repository ${{ github.repository }} + uses: actions/checkout@v2 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v1 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + sudo apt-get install gettext + python -m pip install --upgrade pip + pip install -r requirements.txt + - name: Run tox + run: python -m tox -q + - name: Run pylint + run: python -m pylint resources/lib/ tests/ + - name: Compare translations + run: make check-translations + # Python 2.7 and Python 3.5 are no longer supported by proxy.py + - name: Start proxy server, when supported + run: python -m proxy --hostname 127.0.0.1 --log-level DEBUG & +# if: contains([ '3.6', '3.7', '3.8' ], matrix.python-version) + if: matrix.python-version == '3.6' || matrix.python-version == '3.7' || matrix.python-version == '3.8' + - name: Run unit tests + run: coverage run -m unittest discover + env: + ADDON_PASSWORD: ${{ secrets.ADDON_PASSWORD }} + ADDON_USERNAME: ${{ secrets.ADDON_USERNAME }} + - name: Run addon service + run: coverage run resources/lib/service_entry.py + - name: Run addon using cli + run: coverage run tests/run.py / + - name: Upload code coverage + uses: codecov/codecov-action@v1 diff --git a/.gitignore b/.gitignore index f1ea913a..45e301f3 100644 --- a/.gitignore +++ b/.gitignore @@ -88,10 +88,11 @@ kodi-addon-checker-report.log # Temporary experiment/ +nohup.out # Userdata -test/cdm/ -test/userdata/cache/ -test/userdata/credentials.json -test/userdata/search_history.json -test/userdata/tokens/ +tests/cdm/ +tests/userdata/cache/ +tests/userdata/credentials.json +tests/userdata/search_history.json +tests/userdata/tokens/ diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 35463699..00000000 --- a/.travis.yml +++ /dev/null @@ -1,32 +0,0 @@ -language: python - -python: -- '2.7' -- '3.5' -- '3.6' -- '3.7' -- '3.8' - -sudo: false - -env: - PYTHONPATH: resources/lib:test - PYTHONIOENCODING: utf-8 - -install: -- pip install -r requirements.txt - -script: -- tox -- tox -e flake8 -- pylint resources/lib/ test/ -- msgcmp resources/language/resource.language.{nl_nl,en_gb}/strings.po -#- kodi-addon-checker . --branch=krypton -#- kodi-addon-checker . --branch=leia -- proxy.py & -- coverage run -m unittest discover -- coverage run -a resources/lib/service_entry.py -- coverage run -a test/run.py / - -after_success: -- codecov diff --git a/Makefile b/Makefile index 072b025f..35c52242 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -export PYTHONPATH := $(CURDIR)/resources/lib:$(CURDIR)/test +export PYTHONPATH := $(CURDIR)/resources/lib:$(CURDIR)/tests PYTHON := python name = $(shell xmllint --xpath 'string(/addon/@id)' addon.xml) @@ -20,63 +20,67 @@ blue = \e[1;34m white = \e[1;37m reset = \e[0;39m -.PHONY: test +all: check test build +zip: build +test: check test-unit test-service test-run -all: test zip +check: check-tox check-pylint check-translations -package: zip - -test: sanity unit run - -sanity: tox pylint language - -tox: +check-tox: @echo -e "$(white)=$(blue) Starting sanity tox test$(reset)" $(PYTHON) -m tox -q -pylint: +check-pylint: @echo -e "$(white)=$(blue) Starting sanity pylint test$(reset)" - $(PYTHON) -m pylint resources/lib/ test/ + $(PYTHON) -m pylint resources/lib/ tests/ -language: +check-translations: @echo -e "$(white)=$(blue) Starting language test$(reset)" @-$(foreach lang,$(languages), \ msgcmp resources/language/resource.language.$(lang)/strings.po resources/language/resource.language.en_gb/strings.po; \ ) -addon: clean +check-addon: clean @echo -e "$(white)=$(blue) Starting sanity addon tests$(reset)" kodi-addon-checker . --branch=krypton kodi-addon-checker . --branch=leia -unit: clean - @echo -e "$(white)=$(blue) Starting unit tests$(reset)" +check-codecov: + @echo -e "$(white)=$(blue) Test codecov.yml syntax$(reset)" + curl --data-binary @codecov.yml https://codecov.io/validate + +kill-proxy: -pkill -ef '$(PYTHON) -m proxy' - $(PYTHON) -m proxy & + +unit: test-unit +run: test-run + +test-unit: clean kill-proxy + @echo -e "$(white)=$(blue) Starting unit tests$(reset)" + -$(PYTHON) -m proxy --hostname 127.0.0.1 --log-level DEBUG & $(PYTHON) -m unittest discover - pkill -ef '$(PYTHON) -m proxy' + -pkill -ef '$(PYTHON) -m proxy' -run: - @echo -e "$(white)=$(blue) Run CLI$(reset)" +test-service: + @echo -e "$(white)=$(blue) Run service$(reset)" $(PYTHON) resources/lib/service_entry.py - $(PYTHON) test/run.py $(path) + +test-run: + @echo -e "$(white)=$(blue) Run CLI$(reset)" + $(PYTHON) tests/run.py $(path) profile: @echo -e "$(white)=$(blue) Profiling $(white)$(path)$(reset)" - $(PYTHON) -m cProfile -o profiling_stats-$(git_branch)-$(git_hash).bin test/run.py $(path) + $(PYTHON) -m cProfile -o profiling_stats-$(git_branch)-$(git_hash).bin tests/run.py $(path) -zip: clean +build: clean @echo -e "$(white)=$(blue) Building new package$(reset)" @rm -f ../$(zip_name) cd ..; zip -r $(zip_name) $(include_paths) -x $(exclude_files) @echo -e "$(white)=$(blue) Successfully wrote package as: $(white)../$(zip_name)$(reset)" -codecov: - @echo -e "$(white)=$(blue) Test .codecov.yml syntax$(reset)" - curl --data-binary @.github/codecov.yml https://codecov.io/validate - clean: find . -name '*.py[cod]' -type f -delete find . -name '__pycache__' -type d -delete rm -rf .pytest_cache/ .tox/ - rm -f *.log test/userdata/tokens/*.tkn + rm -f *.log tests/userdata/tokens/*.tkn diff --git a/README.md b/README.md index 3bf43696..0d61605c 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ [![GitHub release](https://img.shields.io/github/release/pietje666/plugin.video.vrt.nu.svg)](https://github.com/pietje666/plugin.video.vrt.nu/releases) -[![Build Status](https://travis-ci.org/pietje666/plugin.video.vrt.nu.svg?branch=master)](https://travis-ci.org/pietje666/plugin.video.vrt.nu) +[![Build status](https://github.com/pietje666/plugin.video.vrt.nu/workflows/CI/badge.svg)](https://github.com/pietje666/plugin.video.vrt.nu/actions) [![Codecov status](https://img.shields.io/codecov/c/github/pietje666/plugin.video.vrt.nu/master)](https://codecov.io/gh/pietje666/plugin.video.vrt.nu/branch/master) [![License: GPLv3](https://img.shields.io/badge/License-GPLv3-yellow.svg)](https://opensource.org/licenses/GPL-3.0) [![Contributors](https://img.shields.io/github/contributors/pietje666/plugin.video.vrt.nu.svg)](https://github.com/pietje666/plugin.video.vrt.nu/graphs/contributors) diff --git a/.codecov.yml b/codecov.yml similarity index 95% rename from .codecov.yml rename to codecov.yml index 102c5447..d273e341 100644 --- a/.codecov.yml +++ b/codecov.yml @@ -10,4 +10,4 @@ coverage: patch: false comment: false ignore: -- test/ +- tests/ diff --git a/requirements.txt b/requirements.txt index 7a06f6de..123b91bf 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,10 +3,12 @@ codecov git+git://github.com/emilsvennesson/script.module.inputstreamhelper.git@master#egg=inputstreamhelper kodi-addon-checker polib -proxy.py==0.3 +#proxy.py == 0.3; python_version != '2.7' +proxy.py; python_version != '2.7' python-dateutil pylint git+git://github.com/tamland/kodi-plugin-routing.git@master#egg=routing setuptools >= 41 -tox-travis -xmlschema==1.0.18; python_version == '2.7' +tox +typing-extensions == 3.7.4.1; python_version != '2.7' +xmlschema == 1.0.18; python_version == '2.7' diff --git a/resources/language/resource.language.nl_nl/strings.po b/resources/language/resource.language.nl_nl/strings.po index 1b8b186d..57c80018 100644 --- a/resources/language/resource.language.nl_nl/strings.po +++ b/resources/language/resource.language.nl_nl/strings.po @@ -798,7 +798,7 @@ msgstr "InputStream Helper informatie" msgctxt "#30911" msgid "InputStream Helper settings… [COLOR=gray][I](for protected content)[/I][/COLOR]" -msgstr "InputStream Helper instellingen…[COLOR=gray][I](voor beveiligde video's)[/I][/COLOR]" +msgstr "InputStream Helper instellingen… [COLOR=gray][I](voor beveiligde video's)[/I][/COLOR]" msgctxt "#30913" msgid "Cache" @@ -834,11 +834,11 @@ msgstr "Maak lokale HTTP caches ongeldig" msgctxt "#30927" msgid "Direct HTTP cache time-to-live [COLOR=gray](in minutes)[/COLOR]" -msgstr "Directe HTTP cache time-to-live [COLOR=gray](in minuten)[/COLOR]" +msgstr "Directe HTTP cache levensduur [COLOR=gray](in minuten)[/COLOR]" msgctxt "#30929" msgid "Indirect HTTP cache time-to-live [COLOR=gray](in minutes)[/COLOR]" -msgstr "Indirecte HTTP cache time-to-live [COLOR=gray](in minuten)[/COLOR]" +msgstr "Indirecte HTTP cache levensduur [COLOR=gray](in minuten)[/COLOR]" msgctxt "#30931" msgid "Logging" @@ -956,4 +956,4 @@ msgstr "VRT tokens werden verwijderd." msgctxt "#30986" msgid "No on demand stream available for {title}." -msgstr "Geen on demand stream beschikbaar voor {title}" +msgstr "Geen on demand stream beschikbaar voor {title}." diff --git a/resources/lib/apihelper.py b/resources/lib/apihelper.py index 2468c712..f21c1895 100644 --- a/resources/lib/apihelper.py +++ b/resources/lib/apihelper.py @@ -638,7 +638,7 @@ def list_channels(self, channels=None, live=True): label = localize(30141, **channel) # Channel live playing_now = _tvguide.playing_now(channel.get('name')) if playing_now: - label += ' [COLOR yellow]| %s[/COLOR]' % playing_now + label += ' [COLOR=yellow]| %s[/COLOR]' % playing_now # A single Live channel means it is the entry for channel's TV Show listing, so make it stand out if channels and len(channels) == 1: label = '[B]%s[/B]' % label diff --git a/resources/lib/kodiutils.py b/resources/lib/kodiutils.py index 386c1f24..dafa3b8e 100644 --- a/resources/lib/kodiutils.py +++ b/resources/lib/kodiutils.py @@ -997,7 +997,7 @@ def get_json_data(response, fail=None): """Return json object from HTTP response""" from json import load, loads try: - if (3, 0, 0) <= version_info <= (3, 5, 9): # the JSON object must be str, not 'bytes' + if (3, 0, 0) <= version_info < (3, 6, 0): # the JSON object must be str, not 'bytes' return loads(to_unicode(response.read())) return load(response) except TypeError as exc: # 'NoneType' object is not callable diff --git a/resources/lib/resumepoints.py b/resources/lib/resumepoints.py index f05cb53d..d6093bf2 100644 --- a/resources/lib/resumepoints.py +++ b/resources/lib/resumepoints.py @@ -34,7 +34,7 @@ def resumepoint_headers(url=None): """Generate http headers for VRT NU Resumepoints API""" from tokenresolver import TokenResolver xvrttoken = TokenResolver().get_xvrttoken(token_variant='user') - headers = None + headers = {} if xvrttoken: url = 'https://www.vrt.be' + url if url else 'https://www.vrt.be/vrtnu' headers = { diff --git a/resources/lib/tokenresolver.py b/resources/lib/tokenresolver.py index 10401319..56b0a787 100644 --- a/resources/lib/tokenresolver.py +++ b/resources/lib/tokenresolver.py @@ -109,7 +109,7 @@ def _get_cached_token(self, token_name, token_variant=None): now = datetime.now(dateutil.tz.tzlocal()) exp = dateutil.parser.parse(token.get('expirationDate')) if exp <= now: - log(2, "Cached token '{path}' deleted", path=path) + log(2, "Token expired, cached token '{path}' deleted", path=path) delete(path) return None @@ -298,7 +298,8 @@ def _get_roaming_xvrttoken(self, xvrttoken): @staticmethod def _create_token_dictionary(cookie_data, cookie_name='X-VRT-Token'): """Create a dictionary with token name and token expirationDate from a Python cookielib.CookieJar or urllib2 Set-Cookie http header""" - token_dictionary = None + if cookie_data is None: + return None if isinstance(cookie_data, cookielib.CookieJar): # Get token dict from cookiejar token_cookie = next((cookie for cookie in cookie_data if cookie.name == cookie_name), None) @@ -308,6 +309,8 @@ def _create_token_dictionary(cookie_data, cookie_name='X-VRT-Token'): token_cookie.name: token_cookie.value, 'expirationDate': datetime.utcfromtimestamp(token_cookie.expires).strftime('%Y-%m-%dT%H:%M:%S.%fZ'), } + else: + token_dictionary = None elif cookie_name in cookie_data: # Get token dict from http header import dateutil.parser @@ -316,6 +319,8 @@ def _create_token_dictionary(cookie_data, cookie_name='X-VRT-Token'): cookie_name: cookie_data[0], 'expirationDate': dateutil.parser.parse(cookie_data[2].strip('Expires=')).strftime('%Y-%m-%dT%H:%M:%S.%fZ') } + else: + token_dictionary = None return token_dictionary @staticmethod diff --git a/resources/lib/tvguide.py b/resources/lib/tvguide.py index 3050d288..450e7b23 100644 --- a/resources/lib/tvguide.py +++ b/resources/lib/tvguide.py @@ -191,10 +191,10 @@ def get_episode_items(self, date, channel): info_labels = self._metadata.get_info_labels(episode, date=date, channel=entry) # FIXME: Due to a bug in Kodi, ListItem.Title is used when Sort methods are used, not ListItem.Label - info_labels['title'] = label + info_labels['title'] = colour(label) episode_items.append(TitleItem( - label=label, + label=colour(label), path=path, art_dict=self._metadata.get_art(episode), info_dict=info_labels, diff --git a/test/__init__.py b/tests/__init__.py similarity index 100% rename from test/__init__.py rename to tests/__init__.py diff --git a/test/read_profiling_stats.py b/tests/read_profiling_stats.py similarity index 100% rename from test/read_profiling_stats.py rename to tests/read_profiling_stats.py diff --git a/test/run.py b/tests/run.py similarity index 100% rename from test/run.py rename to tests/run.py diff --git a/test/test_apihelper.py b/tests/test_apihelper.py similarity index 100% rename from test/test_apihelper.py rename to tests/test_apihelper.py diff --git a/test/test_favorites.py b/tests/test_favorites.py similarity index 100% rename from test/test_favorites.py rename to tests/test_favorites.py diff --git a/test/test_kodiutils.py b/tests/test_kodiutils.py similarity index 100% rename from test/test_kodiutils.py rename to tests/test_kodiutils.py diff --git a/test/test_language.py b/tests/test_language.py similarity index 100% rename from test/test_language.py rename to tests/test_language.py diff --git a/test/test_proxy.py b/tests/test_proxy.py similarity index 94% rename from test/test_proxy.py rename to tests/test_proxy.py index 663e9c0b..24a422d6 100644 --- a/test/test_proxy.py +++ b/tests/test_proxy.py @@ -18,7 +18,7 @@ plugin = addon.plugin -@unittest.skipIf(sys.version_info[0] < 3, 'Skipping proxy tests on Python 2') +@unittest.skipIf(sys.version_info < (3, 6, 0), 'Skipping proxy tests on Python 3.5 and older') class TestProxy(unittest.TestCase): """TestCase class""" @@ -26,7 +26,7 @@ def setUp(self): """Build up function for TestCase class""" xbmc.settings['network.usehttpproxy'] = True xbmc.settings['network.httpproxytype'] = 0 - xbmc.settings['network.httpproxyserver'] = '127.0.0.1' + xbmc.settings['network.httpproxyserver'] = 'localhost' xbmc.settings['network.httpproxyport'] = '8899' def tearDown(self): diff --git a/test/test_resumepoints.py b/tests/test_resumepoints.py similarity index 100% rename from test/test_resumepoints.py rename to tests/test_resumepoints.py diff --git a/test/test_routing.py b/tests/test_routing.py similarity index 100% rename from test/test_routing.py rename to tests/test_routing.py diff --git a/test/test_search.py b/tests/test_search.py similarity index 100% rename from test/test_search.py rename to tests/test_search.py diff --git a/test/test_settings.py b/tests/test_settings.py similarity index 100% rename from test/test_settings.py rename to tests/test_settings.py diff --git a/test/test_streamservice.py b/tests/test_streamservice.py similarity index 92% rename from test/test_streamservice.py rename to tests/test_streamservice.py index 1d408465..8c5b7304 100644 --- a/test/test_streamservice.py +++ b/tests/test_streamservice.py @@ -67,7 +67,7 @@ def test_get_mpd_live_stream_from_url_does_not_crash_returns_stream_and_licensek video = dict(video_url=CHANNELS[1]['live_stream'], video_id=None, publication_id=None) stream = self._streamservice.get_stream(video) # NOTE: Testing live streams only works within Europe - if os.environ.get('TRAVIS') != 'true': + if os.environ.get('GITHUB_ACTIONS') != 'true': self.assertTrue(stream is not None) # self.assertTrue(stream.license_key is not None) @@ -78,7 +78,7 @@ def test_get_hls_live_stream_from_url_does_not_crash_returns_stream_and_licensek video = dict(video_url=CHANNELS[1]['live_stream'], video_id=None, publication_id=None) stream = self._streamservice.get_stream(video) # NOTE: Testing live streams only works within Europe - if os.environ.get('TRAVIS') != 'true': + if os.environ.get('GITHUB_ACTIONS') != 'true': self.assertTrue(stream is not None) def test_get_mpd_live_stream_from_url_does_not_crash(self): @@ -87,7 +87,7 @@ def test_get_mpd_live_stream_from_url_does_not_crash(self): video = dict(video_url=CHANNELS[1]['live_stream'], video_id=None, publication_id=None) stream = self._streamservice.get_stream(video) # NOTE: Testing live streams only works within Europe - if os.environ.get('TRAVIS') != 'true': + if os.environ.get('GITHUB_ACTIONS') != 'true': self.assertTrue(stream is not None) def test_get_hls_live_stream_from_url_does_not_crash(self): @@ -97,7 +97,7 @@ def test_get_hls_live_stream_from_url_does_not_crash(self): video = dict(video_url=CHANNELS[1]['live_stream'], video_id=None, publication_id=None) stream = self._streamservice.get_stream(video) # NOTE: Testing live streams only works within Europe - if os.environ.get('TRAVIS') != 'true': + if os.environ.get('GITHUB_ACTIONS') != 'true': self.assertTrue(stream is not None) def test_get_mpd_live_stream_from_id_does_not_crash(self): @@ -107,13 +107,13 @@ def test_get_mpd_live_stream_from_id_does_not_crash(self): video = dict(video_url=None, video_id=CHANNELS[1]['live_stream_id'], publication_id=None) stream = self._streamservice.get_stream(video) # NOTE: Testing live streams only works within Europe - if os.environ.get('TRAVIS') != 'true': + if os.environ.get('GITHUB_ACTIONS') != 'true': self.assertTrue(stream is not None) video = dict(video_url=None, video_id=CHANNELS[3]['live_stream_id'], publication_id=None) stream = self._streamservice.get_stream(video) # NOTE: Testing live streams only works within Europe - if os.environ.get('TRAVIS') != 'true': + if os.environ.get('GITHUB_ACTIONS') != 'true': self.assertTrue(stream is not None) def test_get_hls_live_stream_from_id_does_not_crash(self): @@ -123,13 +123,13 @@ def test_get_hls_live_stream_from_id_does_not_crash(self): video = dict(video_url=None, video_id=CHANNELS[1]['live_stream_id'], publication_id=None) stream = self._streamservice.get_stream(video) # NOTE: Testing live streams only works within Europe - if os.environ.get('TRAVIS') != 'true': + if os.environ.get('GITHUB_ACTIONS') != 'true': self.assertTrue(stream is not None) video = dict(video_url=None, video_id=CHANNELS[3]['live_stream_id'], publication_id=None) stream = self._streamservice.get_stream(video) # NOTE: Testing live streams only works within Europe - if os.environ.get('TRAVIS') != 'true': + if os.environ.get('GITHUB_ACTIONS') != 'true': self.assertTrue(stream is not None) diff --git a/test/test_tokenresolver.py b/tests/test_tokenresolver.py similarity index 100% rename from test/test_tokenresolver.py rename to tests/test_tokenresolver.py diff --git a/test/test_tvguide.py b/tests/test_tvguide.py similarity index 100% rename from test/test_tvguide.py rename to tests/test_tvguide.py diff --git a/test/test_utils.py b/tests/test_utils.py similarity index 100% rename from test/test_utils.py rename to tests/test_utils.py diff --git a/test/test_vrtplayer.py b/tests/test_vrtplayer.py similarity index 100% rename from test/test_vrtplayer.py rename to tests/test_vrtplayer.py diff --git a/test/test_webscraper.py b/tests/test_webscraper.py similarity index 100% rename from test/test_webscraper.py rename to tests/test_webscraper.py diff --git a/test/userdata/addon_settings.json b/tests/userdata/addon_settings.json similarity index 100% rename from test/userdata/addon_settings.json rename to tests/userdata/addon_settings.json diff --git a/test/userdata/global_settings.json b/tests/userdata/global_settings.json similarity index 100% rename from test/userdata/global_settings.json rename to tests/userdata/global_settings.json diff --git a/test/userdata/search_history.json b/tests/userdata/search_history.json similarity index 100% rename from test/userdata/search_history.json rename to tests/userdata/search_history.json diff --git a/test/xbmc.py b/tests/xbmc.py similarity index 98% rename from test/xbmc.py rename to tests/xbmc.py index 5750f253..4ecf54d8 100644 --- a/test/xbmc.py +++ b/tests/xbmc.py @@ -289,11 +289,11 @@ def sleep(timemillis): def translatePath(path): """A stub implementation of the xbmc translatePath() function""" if path.startswith('special://home'): - return path.replace('special://home', os.path.join(os.getcwd(), 'test/')) + return path.replace('special://home', os.path.join(os.getcwd(), 'tests/')) if path.startswith('special://masterprofile'): - return path.replace('special://masterprofile', os.path.join(os.getcwd(), 'test/userdata/')) + return path.replace('special://masterprofile', os.path.join(os.getcwd(), 'tests/userdata/')) if path.startswith('special://profile'): - return path.replace('special://profile', os.path.join(os.getcwd(), 'test/userdata/')) + return path.replace('special://profile', os.path.join(os.getcwd(), 'tests/userdata/')) if path.startswith('special://userdata'): - return path.replace('special://userdata', os.path.join(os.getcwd(), 'test/userdata/')) + return path.replace('special://userdata', os.path.join(os.getcwd(), 'tests/userdata/')) return path diff --git a/test/xbmcaddon.py b/tests/xbmcaddon.py similarity index 100% rename from test/xbmcaddon.py rename to tests/xbmcaddon.py diff --git a/test/xbmcextra.py b/tests/xbmcextra.py similarity index 85% rename from test/xbmcextra.py rename to tests/xbmcextra.py index 1fdad159..93d85cee 100644 --- a/test/xbmcextra.py +++ b/tests/xbmcextra.py @@ -19,14 +19,14 @@ def kodi_to_ansi(string): string = string.replace('[/B]', '\033[21m') string = string.replace('[I]', '\033[3m') string = string.replace('[/I]', '\033[23m') - string = string.replace('[COLOR gray]', '\033[30;1m') - string = string.replace('[COLOR red]', '\033[31m') - string = string.replace('[COLOR green]', '\033[32m') - string = string.replace('[COLOR yellow]', '\033[33m') - string = string.replace('[COLOR blue]', '\033[34m') - string = string.replace('[COLOR purple]', '\033[35m') - string = string.replace('[COLOR cyan]', '\033[36m') - string = string.replace('[COLOR white]', '\033[37m') + string = string.replace('[COLOR=gray]', '\033[30;1m') + string = string.replace('[COLOR=red]', '\033[31m') + string = string.replace('[COLOR=green]', '\033[32m') + string = string.replace('[COLOR=yellow]', '\033[33m') + string = string.replace('[COLOR=blue]', '\033[34m') + string = string.replace('[COLOR=purple]', '\033[35m') + string = string.replace('[COLOR=cyan]', '\033[36m') + string = string.replace('[COLOR=white]', '\033[37m') string = string.replace('[/COLOR]', '\033[39;0m') return string @@ -74,10 +74,10 @@ def global_settings(): """Use the global_settings file""" import json try: - with open('test/userdata/global_settings.json') as f: - settings = json.load(f) + with open('tests/userdata/global_settings.json') as fdesc: + settings = json.load(fdesc) except OSError as e: - print("Error: Cannot use 'test/userdata/global_settings.json' : %s" % e) + print("Error: Cannot use 'tests/userdata/global_settings.json' : %s" % e) settings = { 'locale.language': 'resource.language.en_gb', 'network.bandwidth': 0, @@ -104,10 +104,10 @@ def addon_settings(addon_id=None): """Use the addon_settings file""" import json try: - with open('test/userdata/addon_settings.json') as f: - settings = json.load(f) + with open('tests/userdata/addon_settings.json') as fdesc: + settings = json.load(fdesc) except OSError as e: - print("Error: Cannot use 'test/userdata/addon_settings.json' : %s" % e) + print("Error: Cannot use 'tests/userdata/addon_settings.json' : %s" % e) settings = {} # Read credentials from environment or credentials.json @@ -115,13 +115,13 @@ def addon_settings(addon_id=None): # 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') - elif os.path.exists('test/userdata/credentials.json'): - # print('Using credentials from test/userdata/credentials.json') - with open('test/userdata/credentials.json') as f: - credentials = json.load(f) + elif os.path.exists('tests/userdata/credentials.json'): + # print('Using credentials from tests/userdata/credentials.json') + with open('tests/userdata/credentials.json') as fdesc: + credentials = json.load(fdesc) settings[ADDON_ID].update(credentials) else: - print("Error: Cannot use 'test/userdata/credentials.json'") + print("Error: Cannot use 'tests/userdata/credentials.json'") if addon_id: return settings[addon_id] diff --git a/test/xbmcgui.py b/tests/xbmcgui.py similarity index 100% rename from test/xbmcgui.py rename to tests/xbmcgui.py diff --git a/test/xbmcplugin.py b/tests/xbmcplugin.py similarity index 96% rename from test/xbmcplugin.py rename to tests/xbmcplugin.py index b8a03053..de02e475 100644 --- a/test/xbmcplugin.py +++ b/tests/xbmcplugin.py @@ -85,7 +85,7 @@ def addSortMethod(handle, sortMethod): 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]')) + # print(kodi_to_ansi('[B]-=( [COLOR=cyan]--------[/COLOR] )=-[/B]')) def setContent(handle, content): @@ -98,7 +98,7 @@ def setPluginFanart(handle, image, color1=None, color2=None, color3=None): def setPluginCategory(handle, category): """A reimplementation of the xbmcplugin setPluginCategory() function""" - print(kodi_to_ansi('[B]-=( [COLOR cyan]%s[/COLOR] )=-[/B]' % category)) + print(kodi_to_ansi('[B]-=( [COLOR=cyan]%s[/COLOR] )=-[/B]' % category)) def setResolvedUrl(handle, succeeded, listitem): diff --git a/test/xbmcvfs.py b/tests/xbmcvfs.py similarity index 100% rename from test/xbmcvfs.py rename to tests/xbmcvfs.py diff --git a/tox.ini b/tox.ini index d74a05a2..c0689e46 100644 --- a/tox.ini +++ b/tox.ini @@ -4,6 +4,7 @@ skipsdist = True skip_missing_interpreters = True [testenv:flake8] +passenv = PYTHONPATH commands = - {envbindir}/flake8 deps =