def _add_account(self): request_params = { 'waiting_retry': lambda request, remaining: self._progress_dialog_bg. update(int((request.current_delay - remaining) / request. current_delay * 100), heading=self._common_addon.getLocalizedString(32043) % ('' if request.current_tries == 1 else ' again'), message=self._common_addon.getLocalizedString(32044) % str( int(remaining) ) + ' ' + self._common_addon.getLocalizedString(32045) % (str(request.current_tries + 1), str(request.tries))), 'on_complete': lambda request: (self._progress_dialog.close(), self._progress_dialog_bg.close()), 'cancel_operation': self.cancel_operation, 'wait': self._system_monitor.waitForAbort } provider = self.get_provider() self._progress_dialog.update( 0, self._common_addon.getLocalizedString(32008)) self._ip_before_pin = Request(KodiUtils.get_signin_server() + '/ip', None).request() pin_info = provider.create_pin(request_params) self._progress_dialog.close() if self.cancel_operation(): return if not pin_info: raise Exception('Unable to retrieve a pin code') tokens_info = {} request_params[ 'on_complete'] = lambda request: self._progress_dialog_bg.close() self._pin_dialog = QRDialogProgress.create( self._addon_name, KodiUtils.get_signin_server() + '/signin/%s' % pin_info['pin'], self._common_addon.getLocalizedString(32009), self._common_addon.getLocalizedString(32010) % ('[B]%s[/B]' % KodiUtils.get_signin_server(), '[B][COLOR lime]%s[/COLOR][/B]' % pin_info['pin'])) self._pin_dialog.show() max_waiting_time = time.time() + self._DEFAULT_SIGNIN_TIMEOUT while not self.cancel_operation() and max_waiting_time > time.time(): remaining = round(max_waiting_time - time.time()) percent = int(remaining / self._DEFAULT_SIGNIN_TIMEOUT * 100) self._pin_dialog.update( percent, line3='[CR]' + self._common_addon.getLocalizedString(32011) % str(int(remaining)) + '[CR][CR]Your source id is: %s' % Utils.get_source_id(self._ip_before_pin)) if int(remaining) % 5 == 0 or remaining == 1: tokens_info = provider.fetch_tokens_info( pin_info, request_params=request_params) if self.cancel_operation() or tokens_info: break if self._system_monitor.waitForAbort(1): break self._pin_dialog.close() if self.cancel_operation() or time.time() >= max_waiting_time: return if not tokens_info: raise Exception('Unable to retrieve the auth2 tokens') self._progress_dialog.update( 25, self._common_addon.getLocalizedString(32064), ' ', ' ') try: account = provider.get_account(request_params=request_params, access_tokens=tokens_info) except Exception as e: raise UIException(32065, e) if self.cancel_operation(): return self._progress_dialog.update( 50, self._common_addon.getLocalizedString(32017)) try: account['drives'] = provider.get_drives( request_params=request_params, access_tokens=tokens_info) except Exception as e: raise UIException(32018, e) if self.cancel_operation(): return self._progress_dialog.update( 75, self._common_addon.getLocalizedString(32020)) try: account['access_tokens'] = tokens_info self._account_manager.save_account(account) except Exception as e: raise UIException(32021, e) if self.cancel_operation(): return self._progress_dialog.update(90) try: accounts = self._account_manager.get_accounts() for drive in account['drives']: driveid = drive['id'] Logger.debug('Looking for account %s...' % driveid) if driveid in accounts: drive = accounts[driveid]['drives'][0] Logger.debug(drive) if drive['id'] == driveid and drive['type'] == 'migrated': Logger.debug('Account %s removed.' % driveid) self._account_manager.remove_account(driveid) except Exception as e: pass if self.cancel_operation(): return self._progress_dialog.close() KodiUtils.executebuiltin('Container.Refresh')
def _process_items(self, items, driveid): listing = [] for item in items: Logger.debug(item) item_id = item['id'] item_name = Utils.unicode(item['name']) item_name_extension = item['name_extension'] item_driveid = Utils.default( Utils.get_safe_value(item, 'drive_id'), driveid) list_item = xbmcgui.ListItem(item_name) url = None is_folder = 'folder' in item params = { 'content_type': self._content_type, 'item_driveid': item_driveid, 'item_id': item_id, 'driveid': driveid } if 'extra_params' in item: params.update(item['extra_params']) context_options = [] info = { 'size': item['size'], 'date': KodiUtils.to_kodi_item_date_str( KodiUtils.to_datetime( Utils.get_safe_value(item, 'last_modified_date'))) } if is_folder: params['action'] = '_list_folder' url = self._addon_url + '?' + urllib.urlencode(params) params['action'] = '_search' cmd = 'ActivateWindow(%d,%s?%s)' % (xbmcgui.getCurrentWindowId( ), self._addon_url, urllib.urlencode(params)) context_options.append( (self._common_addon.getLocalizedString(32039), cmd)) if self._content_type == 'audio' or self._content_type == 'video': params['action'] = '_open_export' params['name'] = urllib.quote(Utils.str(item_name)) context_options.append( (self._common_addon.getLocalizedString(32004), 'RunPlugin(' + self._addon_url + '?' + urllib.urlencode(params) + ')')) del params['name'] elif self._content_type == 'image' and self._auto_refreshed_slideshow_supported: params['action'] = '_slideshow' context_options.append( (self._common_addon.getLocalizedString(32032), 'RunPlugin(' + self._addon_url + '?' + urllib.urlencode(params) + ')')) elif (('video' in item or (item_name_extension and item_name_extension in self._video_file_extensions)) and self._content_type == 'video') or ( ('audio' in item or (item_name_extension and item_name_extension in self._audio_file_extensions)) and self._content_type == 'audio'): list_item.setProperty('IsPlayable', 'true') params['action'] = 'download' cmd = 'RunPlugin(' + self._addon_url + '?' + urllib.urlencode( params) + ')' context_options.append( (self._common_addon.getLocalizedString(32051), cmd)) params['action'] = 'play' url = self._addon_url + '?' + urllib.urlencode(params) info_type = self._content_type if 'audio' in item: info.update(item['audio']) info_type = 'music' elif 'video' in item: list_item.addStreamInfo('video', item['video']) list_item.setInfo(info_type, info) if 'thumbnail' in item: list_item.setArt({ 'icon': item['thumbnail'], 'thumb': item['thumbnail'] }) elif ('image' in item or (item_name_extension and item_name_extension in self._image_file_extensions) ) and self._content_type == 'image': Logger.debug( 'image in item: %s' % (Utils.str('image' in item)), ) Logger.debug( 'item_name_extension in self._image_file_extensions: %s' % (Utils.str( item_name_extension in self._image_file_extensions), )) params['action'] = 'download' cmd = 'RunPlugin(' + self._addon_url + '?' + urllib.urlencode( params) + ')' context_options.append( (self._common_addon.getLocalizedString(32051), cmd)) if 'url' in item: url = item['url'] else: url = self._get_item_play_url( urllib.quote(Utils.str(item_name)), driveid, item_driveid, item_id) if 'image' in item: info.update(item['image']) list_item.setInfo('pictures', info) if 'thumbnail' in item and item['thumbnail']: list_item.setArt({ 'icon': item['thumbnail'], 'thumb': item['thumbnail'] }) if url: context_options.extend( self.get_context_options(list_item, params, is_folder)) list_item.addContextMenuItems(context_options) mimetype = Utils.default( Utils.get_mimetype_by_extension(item_name_extension), Utils.get_safe_value(item, 'mimetype')) if mimetype: list_item.setProperty('mimetype', mimetype) listing.append((url, list_item, is_folder)) xbmcplugin.addDirectoryItems(self._addon_handle, listing, len(listing)) xbmcplugin.endOfDirectory(self._addon_handle, True)
def timed(*args, **kw): ts = timer() result = method(*args, **kw) te = timer() Logger.debug('%r: %2.2f ms' % (method.__name__, (te - ts) * 1000)) return result
def process_change(self, change, items_info, export): change_type = None changed_item_id = change['id'] Logger.debug('Change: %s' % Utils.str(change)) if changed_item_id != export['id']: changed_item_name = Utils.get_safe_value(change, 'name', '') deleted = Utils.get_safe_value(change, 'removed') parent_id = Utils.get_safe_value(change, 'parent', '') if changed_item_id in items_info: item_info = items_info[changed_item_id] item_type = item_info['type'] is_folder = item_type == 'folder' Logger.debug('item_info: %s' % Utils.str(item_info)) item_info_path = item_info['full_local_path'] if KodiUtils.file_exists(item_info_path): if deleted: change_type = self.process_change_delete( items_info, changed_item_id, is_folder) elif parent_id != item_info[ 'parent'] or changed_item_name != item_info['name']: if parent_id in items_info: change_type = 'move' Logger.debug('Change is move') parent_item_info = items_info[parent_id] parent_item_path = parent_item_info[ 'full_local_path'] new_path = os.path.join( parent_item_path, Utils.unicode(changed_item_name)) if is_folder: new_path = os.path.join(new_path, '') if KodiUtils.file_rename(item_info_path, new_path): ExportManager.remove_item_info( items_info, changed_item_id) ExportManager.add_item_info( items_info, changed_item_id, Utils.unicode(changed_item_name), new_path, parent_id, item_type) else: change_type = 'retry' else: Logger.debug( 'Change is move but parent not in item list. Change is delete' ) change_type = self.process_change_delete( items_info, changed_item_id, is_folder) else: Logger.debug( 'Invalid state. Changed item not found: %s. Deleting from item list.' % item_info_path) change_type = self.process_change_delete( items_info, changed_item_id, is_folder) elif parent_id in items_info and not deleted: is_folder = 'application/vnd.google-apps.folder' in change.get( 'mimetype') content_type = export['content_type'] item_name_extension = change['name_extension'] is_stream_file = ( ('video' in change or item_name_extension in self._video_file_extensions) and content_type == 'video') or ('audio' in change and content_type == 'audio') item_type = 'folder' if is_folder else 'file' if is_folder or is_stream_file or ( 'nfo_export' in export and export['nfo_export'] and ('nfo' in item_name_extension or 'text/x-nfo' in change.get("mimetype"))): change_type = 'add' Logger.debug('Change is new item') parent_item_info = items_info[parent_id] parent_item_path = parent_item_info['full_local_path'] new_path = os.path.join(parent_item_path, Utils.unicode(changed_item_name)) if is_folder: new_path = os.path.join(new_path, '') if not KodiUtils.mkdirs(new_path): change_type = 'retry' elif is_stream_file: new_path += '.strm' ExportManager.create_strm( export['driveid'], change, new_path, content_type, 'plugin://%s/' % self.addonid) else: ExportManager.create_nfo(changed_item_id, export['item_driveid'], new_path, self.provider) if change_type != 'retry': ExportManager.add_item_info( items_info, changed_item_id, Utils.unicode(changed_item_name), new_path, parent_id, item_type) Logger.debug('change type: %s ' % Utils.str(change_type)) return change_type
def process_change_create(self, change, items_info, export): content_type = export['content_type'] changed_item_id = change['id'] changed_item_name = Utils.get_safe_value(change, 'name', '') changed_item_extension = Utils.get_safe_value(change, 'name_extension', '') parent_id = Utils.get_safe_value(change, 'parent', '') is_folder = 'folder' in change item_type = 'folder' if is_folder else 'file' parent_item_info = Utils.get_safe_value(items_info, parent_id) if parent_item_info: parent_item_path = parent_item_info['full_local_path'] new_path = os.path.join(parent_item_path, Utils.unicode(changed_item_name)) change_type = 'create' if is_folder: change_type += '_folder' new_path = os.path.join(new_path, '') if parent_id == 'root-folder' and KodiUtils.get_addon_setting( 'clean_folder') == 'true' and KodiUtils.file_exists( new_path): if not Utils.remove_folder(new_path): error = self._common_addon.getLocalizedString( 32066) % new_path KodiUtils.show_notification(error) Logger.debug(error) if not KodiUtils.file_exists(new_path): Logger.debug('creating folder: %s' % (new_path, )) if not KodiUtils.mkdirs(new_path): change_type += '_retry' Logger.debug('unable to create folder %s' % (new_path, )) else: change_type += '_ignored' Logger.debug('folder %s already exists' % (new_path, )) else: download_artwork = 'download_artwork' in export and export[ 'download_artwork'] is_download = changed_item_extension \ and ( changed_item_extension in ['strm', 'nomedia'] or ( download_artwork and ( changed_item_extension in ['nfo'] or ( changed_item_extension in ['jpg', 'png'] and ( any(s in changed_item_name for s in self._artwork_file_extensions) or parent_item_info['name'] in ['.actors', 'extrafanart'] ) ) ) ) ) if is_download: Logger.debug('downloading file: %s' % (new_path, )) change_type = 'download_file' cloud_size = Utils.get_safe_value(change, 'size', 0) local_size = KodiUtils.file(new_path).size() if cloud_size != local_size: Logger.debug( 'Download requested. File changed: Local file size (%s) - cloud file size (%s)' % ( Utils.str(local_size), Utils.str(cloud_size), )) if not ExportManager.download(change, new_path, self.provider): change_type += "_retry" Logger.debug('Unable to download file: %s' % (new_path, )) else: change_type += '_ignored' Logger.debug( 'Download ignored: Local file size (%s) is equal to cloud file size (%s)' % ( Utils.str(local_size), Utils.str(cloud_size), )) else: is_stream_file = (('video' in change or (changed_item_extension and changed_item_extension in self._video_file_extensions)) and content_type == 'video') \ or (('audio' in change or (changed_item_extension and changed_item_extension in self._audio_file_extensions)) and content_type == 'audio') if is_stream_file: change_type += '_file' if KodiUtils.get_addon_setting( 'no_extension_strm') == 'true': new_path = Utils.remove_extension(new_path) new_path += ExportManager._strm_extension strm_content = ExportManager.get_strm_link( export['driveid'], change, content_type, 'plugin://%s/' % self.addonid) Logger.debug('creating strm file: %s' % (new_path, )) if not KodiUtils.file_exists( new_path) or KodiUtils.file( new_path).size() != len(strm_content): if not ExportManager.create_text_file( new_path, strm_content): change_type += '_retry' else: change_type += '_ignored' Logger.debug( 'ignoring strm creation: %s, strm file already exists. same expected size.' % (new_path, )) else: change_type = None Logger.debug('ignoring file: %s' % (new_path, )) if change_type: ExportManager.add_item_info(items_info, changed_item_id, Utils.unicode(changed_item_name), new_path, parent_id, item_type) else: Logger.debug('invalid state. no parent info found') change_type = None return change_type
def _print_slideshow_info(self): if xbmc.getCondVisibility('Slideshow.IsActive'): Logger.debug('Slideshow is there...') elif self.cancel_operation(): Logger.debug('Abort requested...')
def process_change(self, change, items_info, export): change_type = None changed_item_id = change['id'] Logger.debug('Change: %s' % Utils.str(change)) if changed_item_id != export['id']: changed_item_name = change['name'] deleted = Utils.get_safe_value(change, 'deleted') parent_id = change['parent'] is_folder = 'folder' in change if not is_folder: changed_item_name += ExportManager._strm_extension if changed_item_id in items_info: item_info = items_info[changed_item_id] Logger.debug('item_info: %s' % Utils.str(item_info)) item_info_path = item_info['full_local_path'] if KodiUtils.file_exists(item_info_path): if deleted: change_type = self.process_change_delete(items_info, changed_item_id, is_folder) elif parent_id != item_info['parent'] or changed_item_name != item_info['name']: if parent_id in items_info: change_type = 'move' Logger.debug('Change is move') parent_item_info = items_info[parent_id] parent_item_path = parent_item_info['full_local_path'] new_path = os.path.join(parent_item_path, changed_item_name) if is_folder: new_path = os.path.join(new_path, '') if KodiUtils.file_rename(item_info_path, new_path): ExportManager.remove_item_info(items_info, changed_item_id) ExportManager.add_item_info(items_info, changed_item_id, changed_item_name, new_path, parent_id) else: change_type = 'retry' else: Logger.debug('Change is move but parent not in item list. Change is delete') change_type = self.process_change_delete(items_info, changed_item_id, is_folder) else: Logger.debug('Invalid state. Changed item not found: %s. Deleting from item list.' % item_info_path) change_type = self.process_change_delete(items_info, changed_item_id, is_folder) elif parent_id in items_info and not deleted: content_type = export['content_type'] item_name_extension = change['name_extension'] if is_folder or (('video' in change or item_name_extension in self._video_file_extensions) and content_type == 'video') or ('audio' in change and content_type == 'audio'): change_type = 'add' Logger.debug('Change is new item') parent_item_info = items_info[parent_id] parent_item_path = parent_item_info['full_local_path'] new_path = os.path.join(parent_item_path, changed_item_name) if is_folder: new_path = os.path.join(new_path, '') if not KodiUtils.mkdirs(new_path): change_type = 'retry' else: ExportManager.create_strm(export['driveid'], change, new_path, content_type, 'plugin://%s/' % self.addonid) if change_type != 'retry': ExportManager.add_item_info(items_info, changed_item_id, changed_item_name, new_path, parent_id) Logger.debug('change type: %s ' % Utils.str(change_type)) return change_type
def clear(self): self._execute_sql("delete from cache") Logger.debug("Cache '%s' cleared" % self._name) self.checkpoint()
def request(self): self.response_text = self._DEFAULT_RESPONSE if not self.exceptions: self.exceptions = Exception if not self.wait: self.wait = time.sleep if not self.headers: self.headers = {} for i in xrange(self.tries): self.current_tries = i + 1 if self.before_request: self.before_request(self) if self.cancel_operation and self.cancel_operation(): break request_report = 'Request URL: ' + self.get_url_for_report( self.url) request_report += '\nRequest data: ' + Utils.str(self.data) request_report += '\nRequest headers: ' + Utils.str( self.get_headers_for_report(self.headers)) response_report = '<response_not_set>' response = None try: Logger.debug(request_report) req = urllib2.Request(self.url, self.data, self.headers) response = urllib2.urlopen(req) self.response_code = response.getcode() self.response_info = response.info() self.response_url = response.geturl() cookiejar = CookieJar() cookiejar._policy._now = cookiejar._now = int(time.time()) self.response_cookies = cookiejar.make_cookies(response, req) if self.read_content: self.response_text = response.read() content_length = self.response_info.getheader( 'content-length', -1) response_report = '\nResponse Headers:\n%s' % Utils.str( self.response_info) response_report += '\nResponse (%d) content-length=%s, len=<%s>:\n%s' % ( self.response_code, content_length, len( self.response_text), self.response_text) self.success = True break except self.exceptions as e: root_exception = e response_report = '\nResponse <Exception>: ' if isinstance(e, urllib2.HTTPError): self.response_text = Utils.str(e.read()) response_report += self.response_text else: response_report += Utils.str(e) rex = RequestException(Utils.str(e), root_exception, request_report, response_report) if self.on_exception: self.on_exception(self, rex) if self.cancel_operation and self.cancel_operation(): break if self.current_tries == self.tries: if self.on_failure: self.on_failure(self) if self.on_complete: self.on_complete(self) Logger.debug('Raising exception...') raise rex current_time = time.time() max_waiting_time = current_time + self.current_delay while (not self.cancel_operation or not self.cancel_operation() ) and max_waiting_time > current_time: remaining = round(max_waiting_time - current_time) if self.waiting_retry: self.waiting_retry(self, remaining) self.wait(1) current_time = time.time() self.current_delay *= self.backoff finally: Logger.debug(response_report) if response: response.close() if self.success and self.on_success: self.on_success(self) if self.on_complete: self.on_complete(self) return self.response_text
def __del__(self): del self._system_monitor del self._account_manager Logger.debug('Request destroyed.')
def do_GET(self): Logger.debug(self.path + ': Requested') if self._system_monitor.abortRequested(): Logger.debug(self.path + ': abort requested') return data = self.path.split('/') size = len(data) cached_page = self._page_cache.get(self.path) if cached_page: if cached_page['pending']: Logger.debug(self.path + ': Already requested. Waiting for original request...') max_waiting_time = time.time() + 30 while not self._system_monitor.abortRequested() and max_waiting_time > time.time() and cached_page['pending']: if self._system_monitor.waitForAbort(1): break cached_page = self._page_cache.get(self.path) if not self._system_monitor.abortRequested(): if cached_page['pending']: self.write_response(504) Logger.debug(self.path + ': 504 - Gateway timeout') self._page_cache.remove(self.path) else: if 'content' in cached_page and cached_page['content']: content = Utils.get_file_buffer() content.write(cached_page['content']) cached_page['content'] = content self.write_response(cached_page['response_code'], content=Utils.get_safe_value(cached_page, 'content'), headers=Utils.get_safe_value(cached_page, 'headers', {})) Logger.debug(self.path + ': %d - Served from cache' % cached_page['response_code']) else: cached_page = {'pending': True} self._page_cache.set(self.path, cached_page) if size > 1 and data[1] == self.server.service.name: try: if size == 2: cached_page['response_code'] = 303 cached_page['headers'] = {'location': self.path + '/'} elif size > 2 and data[2]: cached_page = self.handle_resource_request(data) else: cached_page = self.show_addon_list() except Exception as e: httpex = ExceptionUtils.extract_exception(e, HTTPError) if httpex: cached_page['response_code'] = httpex.code else: cached_page['response_code'] = 500 ErrorReport.handle_exception(e) content = Utils.get_file_buffer() content.write(ExceptionUtils.full_stacktrace(e)) cached_page['content'] = content else: cached_page['response_code'] = 404 cached_page['pending'] = False content_value = None if 'content' in cached_page: content_value = cached_page['content'].getvalue() self.write_response(cached_page['response_code'], content=Utils.get_safe_value(cached_page, 'content'), headers=Utils.get_safe_value(cached_page, 'headers', {})) cached_page['content'] = content_value if Utils.get_safe_value(cached_page, 'response_code', 0) >= 500: self._page_cache.remove(self.path) else: self._page_cache.set(self.path, cached_page) Logger.debug(self.path + ': Response code ' + Utils.str(cached_page['response_code']))
def play(self, driveid, item_driveid=None, item_id=None): self.get_provider().configure(self._account_manager, driveid) find_subtitles = self._addon.getSetting( 'set_subtitle') == 'true' and self._content_type == 'video' item = self.get_provider().get_item(item_driveid, item_id, find_subtitles=find_subtitles) file_name = Utils.unicode(item['name']) list_item = xbmcgui.ListItem(file_name) succeeded = True info = KodiUtils.get_current_library_info() if not info: info = KodiUtils.find_exported_video_in_library( item_id, file_name + ExportManager._strm_extension) if info and info['id']: Logger.debug('library info: %s' % Utils.str(info)) KodiUtils.set_home_property('dbid', Utils.str(info['id'])) KodiUtils.set_home_property('dbtype', info['type']) KodiUtils.set_home_property('addonid', self._addonid) details = KodiUtils.get_video_details(info['type'], info['id']) Logger.debug('library details: %s' % Utils.str(details)) if details and 'resume' in details: KodiUtils.set_home_property('playcount', Utils.str(details['playcount'])) resume = details['resume'] if resume['position'] > 0: play_resume = False if self.iskrypton: play_resume = KodiUtils.get_addon_setting( 'resume_playing') == 'true' elif KodiUtils.get_addon_setting('ask_resume') == 'true': d = datetime(1, 1, 1) + timedelta(seconds=resume['position']) t = '%02d:%02d:%02d' % (d.hour, d.minute, d.second) Logger.debug(t) option = self._dialog.contextmenu([ KodiUtils.localize(32054, addon=self._common_addon) % t, KodiUtils.localize(12021) ]) Logger.debug('selected option: %d' % option) if option == -1: succeeded = False elif option == 0: play_resume = True if play_resume: list_item.setProperty('resumetime', Utils.str(resume['position'])) list_item.setProperty('startoffset', Utils.str(resume['position'])) list_item.setProperty('totaltime', Utils.str(resume['total'])) else: from clouddrive.common.service.player import KodiPlayer KodiPlayer.cleanup() if 'audio' in item: list_item.setInfo('music', item['audio']) elif 'video' in item: list_item.addStreamInfo('video', item['video']) list_item.select(True) list_item.setPath( self._get_item_play_url(file_name, driveid, item_driveid, item_id)) list_item.setProperty('mimetype', Utils.get_safe_value(item, 'mimetype')) if find_subtitles and 'subtitles' in item: subtitles = [] for subtitle in item['subtitles']: subtitles.append( self._get_item_play_url( urllib.quote(Utils.str(subtitle['name'])), driveid, Utils.default( Utils.get_safe_value(subtitle, 'drive_id'), driveid), subtitle['id'], True)) list_item.setSubtitles(subtitles) if not self.cancel_operation(): xbmcplugin.setResolvedUrl(self._addon_handle, succeeded, list_item)
def request(self): self.response_text = self._DEFAULT_RESPONSE if not self.exceptions: self.exceptions = Exception if not self.wait: self.wait = time.sleep if not self.headers: self.headers = {} for i in range(self.tries): self.current_tries = i + 1 if self.before_request: self.before_request(self) if self.cancel_operation and self.cancel_operation(): break request_report = 'Request URL: ' + self.get_url_for_report( self.url) request_report += '\nRequest data: ' + Utils.str(self.data) request_report += '\nRequest headers: ' + Utils.str( self.get_headers_for_report(self.headers)) response_report = '<response_not_set>' response = None rex = None download_file = None try: Logger.debug(request_report) req = urllib.request.Request(self.url, self.data, self.headers) response = urllib.request.urlopen(req) self.response_code = response.getcode() self.response_info = response.info() self.response_url = response.geturl() cookiejar = CookieJar() cookiejar._policy._now = cookiejar._now = int(time.time()) self.response_cookies = cookiejar.make_cookies(response, req) if self.read_content: if self.download_path: self.response_text = 'Downloading to: ' + self.download_path + '... ' download_file = KodiUtils.file(self.download_path, 'wb') self.download_progress = 0 while True: chunk = response.read(self.DOWNLOAD_CHUNK_SIZE) if not chunk: break download_file.write(chunk) self.download_progress += self.DOWNLOAD_CHUNK_SIZE if self.on_update_download: self.on_update_download(self) self.response_text += ' OK.' else: self.response_text = response.read() content_length = self.response_info.get('content-length', -1) response_report = '\nResponse Headers:\n%s' % Utils.str( self.response_info) response_report += '\nResponse (%d) content-length=%s, len=<%s>:\n' % ( self.response_code, content_length, len(self.response_text), ) try: response_report += Utils.str(self.response_text) except: response_report += '<possible binary content>' self.success = True break except self.exceptions as e: Logger.debug('Exception...') root_exception = e response_report = '\nResponse <Exception>: ' if isinstance(e, HTTPError): self.response_code = e.code self.response_text = Utils.str(e.read()) response_report += self.response_text else: response_report += Utils.str(e) rex = RequestException(Utils.str(e), root_exception, request_report, response_report) finally: try: if download_file: download_file.close() Logger.debug(response_report) except: Logger.debug('unable to print response_report') if response: response.close() if rex: if self.on_exception: Logger.debug('calling self.on_exception...') self.on_exception(self, rex) if self.cancel_operation and self.cancel_operation(): break Logger.debug('current_tries: ' + str(self.current_tries) + ' maximum tries: ' + str(self.tries) + ' i: ' + str(i)) if self.current_tries == self.tries: Logger.debug('max retries reached') if self.on_failure: self.on_failure(self) if self.on_complete: self.on_complete(self) Logger.debug('Raising exception...') raise rex current_time = time.time() max_waiting_time = current_time + self.current_delay Logger.debug('current_delay: ' + str(self.current_delay) + ' seconds. Waiting...') while (not self.cancel_operation or not self.cancel_operation() ) and max_waiting_time > current_time: remaining = round(max_waiting_time - current_time) if self.waiting_retry: Logger.debug('calling self.waiting_retry...') self.waiting_retry(self, remaining) self.wait(1) current_time = time.time() Logger.debug('Done waiting.') self.current_delay *= self.backoff if self.success and self.on_success: self.on_success(self) if self.on_complete: self.on_complete(self) return self.response_text