Example #1
0
    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)
Example #2
0
 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)
Example #3
0
 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)
Example #4
0
 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
Example #5
0
 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
Example #6
0
    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)
Example #7
0
    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)
Example #8
0
    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