Skip to content

Commit

Permalink
Remove all external dependencies - fix Kodi 19 repo
Browse files Browse the repository at this point in the history
  • Loading branch information
i96751414 committed Feb 24, 2021
1 parent 42cc5ed commit 7d918b3
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 58 deletions.
10 changes: 3 additions & 7 deletions addon.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,22 @@
<addon id="repository.github" name="GitHub Add-on repository" provider-name="i96751414" version="0.0.6">
<requires>
<!--<import addon="xbmc.python" version="3.0.0"/>-->
<import addon="script.module.requests" version="2.22.0"/>
<import addon="script.module.defusedxml" version="0.6.0"/>
<!-- futures must be optional so we have py2/3 compatibility -->
<import addon="script.module.futures" version="2.2.0" optional="true"/>
</requires>
<extension point="xbmc.python.script" library="default.py"/>
<extension point="xbmc.service" library="service.py"/>
<extension point="xbmc.addon.repository">
<info>http://127.0.0.1:61234/addons.xml</info>
<checksum>http://127.0.0.1:61234/addons.xml.md5</checksum>
<datadir>http://127.0.0.1:61234/</datadir>
</extension>
<extension point="xbmc.python.script" library="default.py"/>
<extension point="xbmc.service" library="service.py"/>
<extension point="xbmc.addon.metadata">
<platform>all</platform>
<license>See https://github.com/i96751414/repository.github/blob/master/LICENSE</license>
<source>https://github.com/i96751414/repository.github</source>
<summary lang="en">GitHub virtual Add-on repository</summary>
<description lang="en">Customizable repository which acts as a proxy for defined GitHub users' add-ons updates.</description>
<news>
- Initial release
- Add support to Kodi 19
</news>
<assets>
<icon>icon.png</icon>
Expand Down
82 changes: 45 additions & 37 deletions lib/compatibility.py
Original file line number Diff line number Diff line change
@@ -1,37 +1,45 @@
import importlib
import os
import sys

import xbmc
import xbmcaddon
from defusedxml import ElementTree

PY3 = sys.version_info.major >= 3


class UndefinedModuleError(ImportError):
pass


def register_module(name, py2_module=None, py3_module=None):
try:
importlib.import_module(name)
xbmc.log("{} module is already installed".format(name), xbmc.LOGDEBUG)
except ImportError:
xbmc.log("Failed to import module. Going to register it.", xbmc.LOGDEBUG)
module = py3_module if PY3 else py2_module
if module is None:
raise UndefinedModuleError("No module was defined")
install_and_register_module(name, module)


def install_and_register_module(name, module):
xbmc.log("Installing and registering module {}:{}".format(name, module), xbmc.LOGINFO)
xbmc.executebuiltin("InstallAddon(" + module + ")", wait=True)
path = xbmcaddon.Addon(module).getAddonInfo("path")
if not PY3:
# noinspection PyUnresolvedReferences
path = path.decode("utf-8")
tree = ElementTree.parse(os.path.join(path, "addon.xml"))
library_path = tree.find("./extension[@point='xbmc.python.module']").attrib["library"]
sys.path.append(os.path.join(path, library_path))
import importlib
import os
import sys
from xml.etree import ElementTree # nosec

import xbmc
import xbmcaddon

PY3 = sys.version_info.major >= 3


class UndefinedModuleError(ImportError):
pass


def register_module(name, py2_module=None, py3_module=None):
try:
importlib.import_module(name)
xbmc.log("{} module is already installed".format(name), xbmc.LOGDEBUG)
except ImportError:
xbmc.log("Failed to import module. Going to register it.", xbmc.LOGDEBUG)
module = py3_module if PY3 else py2_module
if module is None:
raise UndefinedModuleError("No module was defined")
try:
import_module(module)
xbmc.log("{} module was already installed, but missing on addon.xml".format(name), xbmc.LOGDEBUG)
except RuntimeError:
install_and_import_module(name, module)


def import_module(module):
path = xbmcaddon.Addon(module).getAddonInfo("path")
if not PY3:
# noinspection PyUnresolvedReferences
path = path.decode("utf-8")
tree = ElementTree.parse(os.path.join(path, "addon.xml"))
library_path = tree.find("./extension[@point='xbmc.python.module']").attrib["library"]
sys.path.append(os.path.join(path, library_path))


def install_and_import_module(name, module):
xbmc.log("Installing and registering module {}:{}".format(name, module), xbmc.LOGINFO)
xbmc.executebuiltin("InstallAddon(" + module + ")", wait=True)
import_module(module)
5 changes: 2 additions & 3 deletions lib/entries.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@
import sys
from zipfile import ZipFile

import requests
import xbmc
import xbmcgui

from lib.kodi import ADDON_DATA, ADDON_NAME, translate, notification, get_repository_port, str_to_unicode
from lib.repository import validate_json_schema
from lib.repository import validate_json_schema, get_request

if not os.path.exists(ADDON_DATA):
os.makedirs(ADDON_DATA)
Expand Down Expand Up @@ -76,7 +75,7 @@ def _add_entries_from_data(self, data):


def update_repository(notify=False):
requests.get("http://127.0.0.1:{}/update".format(get_repository_port()), timeout=2)
get_request("http://127.0.0.1:{}/update".format(get_repository_port()), timeout=2)
if notify:
notification(translate(30013))

Expand Down
26 changes: 16 additions & 10 deletions lib/repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@
import logging
import re
from collections import namedtuple, OrderedDict
from concurrent.futures import ThreadPoolExecutor
from hashlib import md5
from xml.etree.ElementTree import Element # nosec
from xml.etree import ElementTree # nosec

try:
from urllib import request as ul
except ImportError:
# noinspection PyUnresolvedReferences
import urllib2 as ul

import requests
from defusedxml import ElementTree
from concurrent.futures import ThreadPoolExecutor

from lib.cache import cached
from lib.kodi import string_types
Expand Down Expand Up @@ -63,6 +67,10 @@ def validate_json_schema(data):
validate_entry_schema(entry)


def get_request(url, **kwargs):
return ul.urlopen(url, **kwargs).read()


class Repository(object):
def __init__(self, **kwargs):
self.files = kwargs.get("files", [])
Expand All @@ -84,9 +92,7 @@ def _load_file(self, path):
self._load_data(json.load(f))

def _load_url(self, url):
r = requests.get(url)
r.raise_for_status()
self._load_data(r.json())
self._load_data(json.loads(get_request(url)))

def _load_data(self, data):
for addon_data in data:
Expand All @@ -102,7 +108,7 @@ def clear_cache(self):

@cached(seconds=60 * 60)
def get_latest_release(self, username, repository, default="master"):
data = requests.get(GITHUB_LATEST_RELEASE_URL.format(username=username, repository=repository)).json()
data = json.loads(get_request(GITHUB_LATEST_RELEASE_URL.format(username=username, repository=repository)))
try:
return data["tag_name"]
except KeyError:
Expand All @@ -120,14 +126,14 @@ def _get_addon_xml(self, addon):
branch=self._get_addon_branch(addon)) + "/addon.xml"

try:
return ElementTree.fromstring(requests.get(addon_xml_url).content)
return ElementTree.fromstring(get_request(addon_xml_url))
except Exception as e:
logging.error("failed getting '%s': %s", addon.id, e, exc_info=True)
return None

@cached(seconds=60 * 60)
def get_addons_xml(self):
root = Element("addons")
root = ElementTree.Element("addons")
num_threads = min(self._max_threads, len(self._addons))
if num_threads <= 1:
results = [self._get_addon_xml(a) for a in self._addons.values()]
Expand Down
2 changes: 1 addition & 1 deletion lib/service.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import logging
import os
import threading
from xml.etree import ElementTree # nosec

import xbmc
from defusedxml import ElementTree

from lib import routes # noqa
from lib.httpserver import threaded_http_server
Expand Down

0 comments on commit 7d918b3

Please sign in to comment.