Skip to content

Commit 85ed32b

Browse files
committed
Move imports to where they are being used
May be controversial, but if we want to keep inputstreamhelper's footprint as small as possible to add-ons using it, this may help.
1 parent e93091f commit 85ed32b

File tree

1 file changed

+58
-31
lines changed

1 file changed

+58
-31
lines changed

lib/inputstreamhelper/__init__.py

Lines changed: 58 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,9 @@
33
from __future__ import absolute_import, division, unicode_literals
44

55
import os
6-
import platform
7-
import json
8-
import subprocess
9-
import shutil
10-
from distutils.version import LooseVersion # pylint: disable=import-error,no-name-in-module
11-
from datetime import datetime, timedelta
12-
13-
try: # Python 3
14-
from http.client import BadStatusLine
15-
from urllib.error import HTTPError
16-
from urllib.request import build_opener, install_opener, ProxyHandler, urlopen
17-
except ImportError: # Python 2
18-
from httplib import BadStatusLine
19-
from urllib2 import build_opener, HTTPError, install_opener, ProxyHandler, urlopen
20-
216
from inputstreamhelper import config
227

23-
import xbmc
24-
from xbmcaddon import Addon
258
from xbmcgui import Dialog, DialogProgress
26-
import xbmcvfs
279
from .kodiutils import execute_jsonrpc, get_addon_info, get_proxies, get_setting, localize, log, set_setting, translate_path
2810
from .unicodehelper import to_unicode
2911

@@ -42,9 +24,11 @@ def system_os():
4224

4325
# If it wasn't stored before, get the correct value
4426
if not hasattr(system_os, 'name'):
45-
if xbmc.getCondVisibility('system.platform.android'):
27+
from xbmc import getCondVisibility
28+
if getCondVisibility('system.platform.android'):
4629
system_os.name = 'Android'
4730
else:
31+
import platform
4832
system_os.name = platform.system()
4933

5034
# Return the stored value
@@ -64,6 +48,7 @@ def __init__(self, protocol, drm=None):
6448
self.protocol = protocol
6549
self.drm = drm
6650

51+
import platform
6752
log('Platform information: {platform}', platform=platform.uname())
6853

6954
if self.protocol not in config.INPUTSTREAM_PROTOCOLS:
@@ -78,7 +63,13 @@ def __init__(self, protocol, drm=None):
7863
self.drm = config.DRM_SCHEMES[drm]
7964

8065
# Add proxy support to HTTP requests
81-
install_opener(build_opener(ProxyHandler(get_proxies())))
66+
proxies = get_proxies()
67+
if proxies:
68+
try: # Python 3
69+
from urllib.request import build_opener, install_opener, ProxyHandler
70+
except ImportError: # Python 2
71+
from urllib2 import build_opener, install_opener, ProxyHandler
72+
install_opener(build_opener(ProxyHandler(proxies)))
8273

8374
def __repr__(self):
8475
''' String representation of Helper class '''
@@ -93,31 +84,36 @@ def _diskspace(cls):
9384
@classmethod
9485
def _temp_path(cls):
9586
''' Return temporary path, usually ~/.kodi/userdata/addon_data/script.module.inputstreamhelper/temp '''
87+
from xbmcvfs import exists, mkdirs
9688
temp_path = translate_path(os.path.join(get_setting('temp_path', 'special://masterprofile/addon_data/script.module.inputstreamhelper'), 'temp'))
97-
if not xbmcvfs.exists(temp_path):
98-
xbmcvfs.mkdirs(temp_path)
89+
if not exists(temp_path):
90+
mkdirs(temp_path)
9991

10092
return temp_path
10193

10294
@classmethod
10395
def _mnt_path(cls):
10496
''' Return mount path, usually ~/.kodi/userdata/addon_data/script.module.inputstreamhelper/temp/mnt '''
97+
from xbmcvfs import exists, mkdir
10598
mnt_path = os.path.join(cls._temp_path(), 'mnt')
106-
if not xbmcvfs.exists(mnt_path):
107-
xbmcvfs.mkdir(mnt_path)
99+
if not exists(mnt_path):
100+
mkdir(mnt_path)
108101

109102
return mnt_path
110103

111104
@classmethod
112105
def _ia_cdm_path(cls):
113106
''' Return the specified CDM path for inputstream.adaptive, usually ~/.kodi/cdm '''
107+
from xbmcaddon import Addon
114108
try:
115109
addon = Addon('inputstream.adaptive')
116110
except RuntimeError:
117111
return None
112+
118113
cdm_path = translate_path(addon.getSetting('DECRYPTERPATH'))
119-
if not xbmcvfs.exists(cdm_path):
120-
xbmcvfs.mkdir(cdm_path)
114+
from xbmcvfs import exists, mkdir
115+
if not exists(cdm_path):
116+
mkdir(cdm_path)
121117

122118
return cdm_path
123119

@@ -131,6 +127,7 @@ def _widevine_config_path(cls):
131127
@classmethod
132128
def _load_widevine_config(cls):
133129
''' Load the widevine or recovery config in JSON format '''
130+
import json
134131
with open(cls._widevine_config_path(), 'r') as config_file:
135132
return json.loads(config_file.read())
136133

@@ -143,20 +140,23 @@ def _widevine_path(cls):
143140

144141
if cls._ia_cdm_path():
145142
widevine_path = os.path.join(cls._ia_cdm_path(), widevine_cdm_filename)
146-
if xbmcvfs.exists(widevine_path):
143+
from xbmcvfs import exists
144+
if exists(widevine_path):
147145
return widevine_path
148146

149147
return False
150148

151149
@classmethod
152150
def _kodi_version(cls):
153151
''' Return the current Kodi version '''
154-
version = xbmc.getInfoLabel('System.BuildVersion')
152+
from xbmc import getInfoLabel
153+
version = getInfoLabel('System.BuildVersion')
155154
return version.split(' ')[0]
156155

157156
@classmethod
158157
def _arch(cls):
159158
"""Map together and return the system architecture."""
159+
import platform
160160
arch = platform.machine()
161161
if arch == 'aarch64':
162162
import struct
@@ -191,6 +191,7 @@ def _sizeof_fmt(num, suffix='B'):
191191
def _cmd_exists(cmd):
192192
"""Check whether cmd exists on system."""
193193
# https://stackoverflow.com/questions/377017/test-if-executable-exists-in-python
194+
import subprocess
194195
return subprocess.call('type ' + cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) == 0
195196

196197
def _update_temp_path(self, new_temp_path):
@@ -199,6 +200,7 @@ def _update_temp_path(self, new_temp_path):
199200

200201
set_setting('temp_path', new_temp_path)
201202
if old_temp_path != self._temp_path():
203+
import shutil
202204
shutil.move(old_temp_path, self._temp_path())
203205

204206
def _helper_disabled(self):
@@ -228,6 +230,7 @@ def enable():
228230

229231
def _inputstream_version(self):
230232
''' Return the requested inputstream version '''
233+
from xbmcaddon import Addon
231234
try:
232235
addon = Addon(self.inputstream_addon)
233236
except RuntimeError:
@@ -265,6 +268,7 @@ def _chromeos_offset(self, bin_path):
265268

266269
def _run_cmd(self, cmd, sudo=False, shell=False):
267270
''' Run subprocess command and return if it succeeds as a bool '''
271+
import subprocess
268272
output = ''
269273
success = False
270274
if sudo and os.getuid() != 0 and self._cmd_exists('sudo'):
@@ -345,6 +349,15 @@ def _has_widevine(self):
345349
@staticmethod
346350
def _http_request(url):
347351
''' Perform an HTTP request and return request '''
352+
353+
try: # Python 3
354+
from http.client import BadStatusLine
355+
from urllib.error import HTTPError
356+
from urllib.request import urlopen
357+
except ImportError: # Python 2
358+
from httplib import BadStatusLine
359+
from urllib2 import HTTPError, urlopen
360+
348361
log('Request URL: {url}', url=url)
349362
filename = url.split('/')[-1]
350363

@@ -448,6 +461,7 @@ def _supports_widevine(self):
448461
Dialog().ok(localize(30004), localize(30011, os=system_os())) # Operating system not supported by Widevine
449462
return False
450463

464+
from distutils.version import LooseVersion # pylint: disable=import-error,no-name-in-module
451465
if LooseVersion(config.WIDEVINE_MINIMUM_KODI_VERSION[system_os()]) > LooseVersion(self._kodi_version()):
452466
log('Unsupported Kodi version for Widevine: {version}', version=self._kodi_version())
453467
Dialog().ok(localize(30004), localize(30010, version=config.WIDEVINE_MINIMUM_KODI_VERSION[system_os()])) # Kodi too old
@@ -486,6 +500,7 @@ def _select_best_chromeos_image(devices):
486500
continue
487501

488502
# Select the newest version
503+
from distutils.version import LooseVersion # pylint: disable=import-error,no-name-in-module
489504
if LooseVersion(device['version']) > LooseVersion(best['version']):
490505
log('{device[hwid]} ({device[version]}) is newer than {best[hwid]} ({best[version]})', # pylint: disable=invalid-format-index
491506
device=device,
@@ -511,6 +526,7 @@ def _latest_widevine_version(self, eula=False):
511526
versions = self._http_get(url)
512527
return versions.split()[-1]
513528

529+
from datetime import datetime
514530
import time
515531
set_setting('last_update', str(time.mktime(datetime.utcnow().timetuple())))
516532
if 'x86' in self._arch():
@@ -648,6 +664,7 @@ def _install_widevine_arm(self): # pylint: disable=too-many-statements
648664
progress_dialog.update(97, line1=localize(30050)) # Finishing
649665
self._cleanup()
650666
if self._has_widevine():
667+
import json
651668
set_setting('chromeos_version', arm_device['version'])
652669
with open(self._widevine_config_path(), 'w') as config_file:
653670
config_file.write(json.dumps(devices, indent=4))
@@ -679,9 +696,10 @@ def install_widevine(self):
679696
def remove_widevine(self):
680697
"""Removes Widevine CDM"""
681698
widevinecdm = self._widevine_path()
682-
if widevinecdm and xbmcvfs.exists(widevinecdm):
699+
from xbmcvfs import delete, exists
700+
if widevinecdm and exists(widevinecdm):
683701
log('Remove Widevine CDM at {path}', path=widevinecdm)
684-
xbmcvfs.delete(widevinecdm)
702+
delete(widevinecdm)
685703
Dialog().notification(localize(30037), localize(30052)) # Success! Widevine successfully removed.
686704
return True
687705
Dialog().notification(localize(30004), localize(30053)) # Error. Widevine CDM not found.
@@ -696,6 +714,7 @@ def _first_run():
696714
addon_version = get_addon_info('version')
697715

698716
# Compare versions
717+
from distutils.version import LooseVersion # pylint: disable=import-error,no-name-in-module
699718
if LooseVersion(addon_version) > LooseVersion(settings_version):
700719
# New version found, save addon_version to settings
701720
set_setting('version', addon_version)
@@ -707,6 +726,7 @@ def _update_widevine(self):
707726
"""Prompts user to upgrade Widevine CDM when a newer version is available."""
708727
last_update = get_setting('last_update')
709728
if last_update and not self._first_run():
729+
from datetime import datetime, timedelta
710730
last_update_dt = datetime.fromtimestamp(float(get_setting('last_update')))
711731
if last_update_dt + timedelta(days=int(get_setting('update_frequency', '14'))) >= datetime.utcnow():
712732
log('Widevine update check was made on {date}', date=last_update_dt.isoformat())
@@ -723,6 +743,7 @@ def _update_widevine(self):
723743
log('Latest {component} version is {version}', component=component, version=latest_version)
724744
log('Current {component} version installed is {version}', component=component, version=current_version)
725745

746+
from distutils.version import LooseVersion # pylint: disable=import-error,no-name-in-module
726747
if LooseVersion(latest_version) > LooseVersion(current_version):
727748
log('There is an update available for {component}', component=component)
728749
if Dialog().yesno(localize(30040), localize(30033), yeslabel=localize(30034), nolabel=localize(30028)):
@@ -754,6 +775,7 @@ def _widevine_eula(self):
754775

755776
def _extract_widevine_from_img(self):
756777
''' Extract the Widevine CDM binary from the mounted Chrome OS image '''
778+
import shutil
757779
for root, dirs, files in os.walk(str(self._mnt_path())): # pylint: disable=unused-variable
758780
if str('libwidevinecdm.so') not in files:
759781
continue
@@ -859,6 +881,7 @@ def _unmount(self):
859881

860882
def _cleanup(self):
861883
''' Clean up function after Widevine CDM installation '''
884+
import shutil
862885
self._unmount()
863886
if self._attached_loop_dev:
864887
cmd = ['losetup', '-d', self._loop_dev]
@@ -875,6 +898,7 @@ def _cleanup(self):
875898

876899
def _supports_hls(self):
877900
"""Return if HLS support is available in inputstream.adaptive."""
901+
from distutils.version import LooseVersion # pylint: disable=import-error,no-name-in-module
878902
if LooseVersion(self._inputstream_version()) >= LooseVersion(config.HLS_MINIMUM_IA_VERSION):
879903
return True
880904

@@ -899,9 +923,11 @@ def _check_drm(self):
899923

900924
def _install_inputstream(self):
901925
"""Install inputstream addon."""
926+
from xbmc import executebuiltin
927+
from xbmcaddon import Addon
902928
try:
903929
# See if there's an installed repo that has it
904-
xbmc.executebuiltin('InstallAddon({})'.format(self.inputstream_addon), wait=True)
930+
executebuiltin('InstallAddon({})'.format(self.inputstream_addon), wait=True)
905931

906932
# Check if InputStream add-on exists!
907933
Addon('{}'.format(self.inputstream_addon))
@@ -955,6 +981,7 @@ def info_dialog(self):
955981

956982
if system_os() != 'Android':
957983
text += ' - ' + localize(30820) + '\n' # Widevine information
984+
from datetime import datetime
958985
wv_updated = datetime.fromtimestamp(float(get_setting('last_update'))).strftime("%Y-%m-%d %H:%M") if get_setting('last_update') else 'Never'
959986
text += ' - ' + localize(30821, version=self._get_lib_version(self._widevine_path()), date=wv_updated) + '\n'
960987
text += ' - ' + localize(30822, path=self._ia_cdm_path()) + '\n'

0 commit comments

Comments
 (0)