def subfunc(match): # TODO: readd indentation attrs, script = match.groups() if not script.strip(): return "<script type='text/javascript'%s></script>" % attrs proc = Popen(csargs, stdin=PIPE, stdout=PIPE, stderr=PIPE) stdout, stderr = proc.communicate(kaa.py3_b(script)) if stderr: # Compile failed. Figure out what line caused the error. errmsg = stderr.lstrip().splitlines()[0] error = re.sub(r'\s+on line \d+', '', stderr.lstrip().splitlines()[0]) linematch = re.search('on line (\d+)', stderr) if linematch: # This is the line relative to the coffescript portion linenum = int(linematch.group(1)) # Grab the bad line. badline = script.splitlines()[linenum-1] # Now translate the number it into an absolute line from the # source file. Count the number of newlines in the source up # to the match start. linenum += data.count('\n', 0, match.start()) dump = 'File "%s", line %d\n %s\n\n%s' % (src, linenum, badline.lstrip(), error) else: dump = 'Unable to determine line number. Full coffee output follows:\n\n' + stderr raise CSCompileError('CoffeeScript ' + error, dump) if is_html: return "<script type='text/javascript'%s>\n%s</script>" % (attrs, kaa.py3_str(stdout)) else: return kaa.py3_str(stdout)
def sort(self, mode='name'): """ Returns the string how to sort this item """ if mode in ('name', 'smart'): try: track = int(self.info.get('trackno')) except (ValueError, KeyError, TypeError): track = 0 return u'%20d %s' % (track, kaa.py3_str(self.name.lower())) return super(AudioItem, self).sort(mode)
def get_series(self, name): """ Fetch a series by the series name or associated alias. """ if self.__get_series_cache and self.__get_series_cache[0] == self.version and \ self.__get_series_cache[1] == name: return self.__get_series_cache[2] obj, series = self._db.query_one(type='alias', tvdb=kaa.py3_str(name)), None if obj: series = Series(self, self._db.query_one(type='series', id=obj['parent_id'])) self.__get_series_cache = self.version, name, series return series
def get_series(self, name): """ Fetch a series by the series name or associated alias. """ if self.__get_series_cache and self.__get_series_cache[0] == self.version and \ self.__get_series_cache[1] == name: return self.__get_series_cache[2] obj, series = self._db.query_one(type='alias', tvdb=kaa.py3_str(name)), None if obj: series = Series( self, self._db.query_one(type='series', id=obj['parent_id'])) self.__get_series_cache = self.version, name, series return series
def add_series_by_id(self, id, alias=None): """ Adds the TV series specified by the TVDB id number to the local database. :param id: the TVDB id number :param alias: optional alias with which to associate this TV series for later lookup. If the series is already added to the database, the given alias will be associated with it. """ if isinstance(alias, basestring): alias = kaa.py3_str(alias) if id.startswith(TVDB.scheme): id = id[len(TVDB.scheme):] if not self._db.get_metadata('webmetadata::servertime'): # DB does not contain server time. Fetch and set. attr, data = yield parse(self.hostname + '/api/Updates.php?type=none') data = dict(data) self._db.set_metadata('webmetadata::servertime', int(data['Time'])) self._db.commit() series = self._db.query_one(type='series', tvdb=id) if not series: log.info('query thetvdb for %s' % id) for i in range(3): # try to get results three times before giving up yield self._update_series(id) series = self._db.query_one(type='series', tvdb=id) if series: break else: log.error('TheTVDB failed to provide a result') yield False self._update_db('alias', series['name'], parent=series) if alias: for old in self._db.query(type='alias', tvdb=alias): # remove old (wrong) mapping (if given) self._db.delete(old) self._update_db('alias', alias, parent=series) self._db.commit() self.notify_resync() yield Series(self, series)
def get_series(self, id): STAY_LOCAL = os.getenv('STAY_LOCAL', 0) log.debug('retrieving series data for %s', id) if not self.get_last_updated(): # DB doesn't know about server time. Set to current time so that # subsequent calls to get_changed_series_ids() have a reference # point. self.db.set_metadata('thetvdb::servertime', int(time.time())) series = {'episodes': []} # TODO: if language doesn't exist, retry english. Or (probaby better) # fetch and cache languages.xml and make sure the user choice is there. z = yield self._get_api_zipfile('series/%s/all/%s.zip' % (id, config.misc.language.lower())) # Find the highest rated banner for the given language. banner = (-1, None) # (rating, url) for tag, attrs, data in (yield parse_xml(z.open('banners.xml'))): if tag != 'Banner' or data.get('BannerType') != 'series' or \ data.get('Language', '').lower() != config.misc.language.lower(): continue try: rating = float(data.get('Rating', 0)) except ValueError: rating = 0.0 if rating > banner[0] and 'BannerPath' in data: banner = rating, data['BannerPath'] # Get series and episode data. for tag, attrs, data in (yield parse_xml(z.open('%s.xml' % config.misc.language.lower()))): if tag == 'Series': try: series['runtime'] = int(data['Runtime']) except (ValueError, KeyError): pass try: # XXX: is Airs_Time guaranteed to be well formatted? # Should we be more robust? timetuple = time.strptime(data.get('Airs_Time', ''), '%I:%M %p') series['airtime'] = kaa.py3_str(time.strftime('%H:%M', timetuple)) except ValueError: pass # Get any existing series and see if we need to fetch banner data. existing = self.db.get_series_by_id('thetvdb:' + data['id']) missing = not existing or not existing.banner_data if not STAY_LOCAL and banner[1] and (missing or not existing.banner.endswith(banner[1])): # Need to fetch banner, either because it changed (different banner with # a higher rating?) or because we never had one. url = self.hostname + '/banners/' + banner[1] log.debug('refresh series banner %s', url) status, banner_data = yield download(url, retry=3) if status == 200: series['banner_data'] = banner_data else: log.error('banner download failed for series %s', data.get('SeriesName', data['id'])) from ..tvdb import Series status_str = data.get('Status', '').lower() if status_str.startswith('cont'): # continuing status = Series.STATUS_RUNNING elif status_str.startswith('on'): # on hiaitus status = Series.STATUS_SUSPENDED elif status_str.startswith('end'): # ended status = Series.STATUS_ENDED else: status = Series.STATUS_UNKNOWN series.update({ 'id': data['id'], 'name': data.get('SeriesName'), 'poster': self.hostname + '/banners/' + data.get('poster'), 'banner': self.hostname + '/banners/' + kaa.py3_str(banner[1]), 'overview': data.get('Overview'), # TODO: do a sanity check on FirstAired format. 'started': data.get('FirstAired'), # TODO: use constants for status 'status': status, 'imdbid': data.get('IMDB_ID') }) elif tag == 'Episode': series['episodes'].append({ 'id': data['id'], 'name': data.get('EpisodeName'), 'season': int(data['SeasonNumber']), 'episode': int(data['EpisodeNumber']), # TODO: do a sanity check on FirstAired format. 'airdate': data.get('FirstAired'), 'overview': data.get('Overview') }) else: log.error('unknown element: %s', name) if not STAY_LOCAL: os.unlink(z.filename) yield series