def wrapper(tokens, *args): results = [] for part in split_on_comma(tokens): result = function(remove_whitespace(part), *args) if result is None: return None results.append(result) return results
def preprocess_declarations(base_url, declarations): """ Expand shorthand properties and filter unsupported properties and values. Log a warning for every ignored declaration. Return a iterable of ``(name, value, priority)`` tuples. """ def validation_error(level, reason): getattr(LOGGER, level)('Ignored `%s: %s` at %i:%i, %s.', declaration.name, declaration.value.as_css(), declaration.line, declaration.column, reason) for declaration in declarations: name = declaration.name if name in PREFIXED and not name.startswith(PREFIX): validation_error( 'warn', 'the property is experimental or non-standard, use ' + PREFIX + name) continue if name in NOT_PRINT_MEDIA: validation_error( 'info', 'the property does not apply for the print media') continue if name.startswith(PREFIX): unprefixed_name = name[len(PREFIX):] if unprefixed_name in UNPREFIXED: validation_error( 'warn', 'the property was unprefixed, use ' + unprefixed_name) continue if unprefixed_name in PREFIXED: name = unprefixed_name expander_ = EXPANDERS.get(name, validate_non_shorthand) tokens = remove_whitespace(declaration.value) try: # Use list() to consume generators now and catch any error. result = list(expander_(base_url, name, tokens)) except InvalidValues as exc: validation_error( 'warn', exc.args[0] if exc.args and exc.args[0] else 'invalid value') continue priority = declaration.priority for long_name, value in result: yield long_name.replace('-', '_'), value, priority
def preprocess_declarations(base_url, declarations): """ Expand shorthand properties and filter unsupported properties and values. Log a warning for every ignored declaration. Return a iterable of ``(name, value, priority)`` tuples. """ def validation_error(level, reason): getattr(LOGGER, level)('Ignored `%s: %s` at %i:%i, %s.', declaration.name, declaration.value.as_css(), declaration.line, declaration.column, reason) for declaration in declarations: name = declaration.name if name in PREFIXED and not name.startswith(PREFIX): validation_error('warn', 'the property is experimental or non-standard, use ' + PREFIX + name) continue if name in NOT_PRINT_MEDIA: validation_error('info', 'the property does not apply for the print media') continue if name.startswith(PREFIX): unprefixed_name = name[len(PREFIX):] if unprefixed_name in UNPREFIXED: validation_error('warn', 'the property was unprefixed, use ' + unprefixed_name) continue if unprefixed_name in PREFIXED: name = unprefixed_name expander_ = EXPANDERS.get(name, validate_non_shorthand) tokens = remove_whitespace(declaration.value) try: # Use list() to consume generators now and catch any error. result = list(expander_(base_url, name, tokens)) except InvalidValues as exc: validation_error('warn', exc.args[0] if exc.args and exc.args[0] else 'invalid value') continue priority = declaration.priority for long_name, value in result: yield long_name.replace('-', '_'), value, priority
def preprocess_descriptors(base_url, descriptors): """Filter unsupported names and values for descriptors. Log a warning for every ignored descriptor. Return a iterable of ``(name, value)`` tuples. """ for descriptor in descriptors: tokens = remove_whitespace(descriptor.value) try: # Use list() to consume generators now and catch any error. result = list(validate(base_url, descriptor.name, tokens)) except InvalidValues as exc: LOGGER.warning( 'Ignored `%s: %s` at %i:%i, %s.', descriptor.name, descriptor.value.as_css(), descriptor.line, descriptor.column, exc.args[0] if exc.args and exc.args[0] else 'invalid value') continue for long_name, value in result: yield long_name.replace('-', '_'), value
def parse_media(self, tokens, errors): """For CSS 2.1, parse a list of media types. Media Queries are expected to override this. :param tokens: A list of tokens :raises: :class:`~.parsing.ParseError` on invalid media types/queries :returns: For CSS 2.1, a list of media types as strings """ if not tokens: return ['all'] media_types = [] for part in split_on_comma(remove_whitespace(tokens)): types = [token.type for token in part] if types == ['IDENT']: media_types.append(part[0].value) else: raise ParseError(tokens[0], 'expected a media type' + ((', got ' + ', '.join(types)) if types else '')) return media_types
def parse_media(self, tokens, errors): if not tokens: return [MediaQuery('all')] queries = [] for part in split_on_comma(remove_whitespace(tokens)): negated = False media_type = None expressions = [] try: for i, tok in enumerate(part): if i == 0 and tok.type == 'IDENT': val = tok.value.lower() if val == 'only': continue # ignore leading ONLY if val == 'not': negated = True continue if media_type is None and tok.type == 'IDENT': media_type = tok.value continue elif media_type is None: media_type = 'all' if tok.type == 'IDENT' and tok.value.lower() == 'and': continue if not tok.is_container: raise MalformedExpression( tok, 'expected a media expression not a %s' % tok.type) if tok.type != '(': raise MalformedExpression( tok, 'media expressions must be in parentheses not %s' % tok.type) content = remove_whitespace(tok.content) if len(content) == 0: raise MalformedExpression( tok, 'media expressions cannot be empty') if content[0].type != 'IDENT': raise MalformedExpression( content[0], 'expected a media feature not a %s' % tok.type) media_feature, expr = content[0].value, None if len(content) > 1: if len(content) < 3: raise MalformedExpression( content[1], 'malformed media feature definition') if content[1].type != ':': raise MalformedExpression(content[1], 'expected a :') expr = content[2:] if len(expr) == 1: expr = expr[0] elif len(expr) == 3 and ( expr[0].type, expr[1].type, expr[1].value, expr[2].type) == ('INTEGER', 'DELIM', '/', 'INTEGER'): # This should really be moved into token_data, but # since RATIO is not part of CSS 2.1 and does not # occur anywhere else, we special case it here. r = expr[0] r.value = (expr[0].value, expr[2].value) r.type = 'RATIO' r._as_css = expr[0]._as_css + expr[ 1]._as_css + expr[2]._as_css expr = r else: raise MalformedExpression( expr[0], 'malformed media feature definition') expressions.append((media_feature, expr)) except MalformedExpression as err: errors.extend(ParseError(err.tok, err.message)) media_type, negated, expressions = 'all', True, () queries.append( MediaQuery(media_type or 'all', expressions=tuple(expressions), negated=negated)) return queries
def parse_media(self, tokens, errors): if not tokens: return [MediaQuery('all')] queries = [] for part in split_on_comma(remove_whitespace(tokens)): negated = False media_type = None expressions = [] try: for i, tok in enumerate(part): if i == 0 and tok.type == 'IDENT': val = tok.value.lower() if val == 'only': continue # ignore leading ONLY if val == 'not': negated = True continue if media_type is None and tok.type == 'IDENT': media_type = tok.value continue elif media_type is None: media_type = 'all' if tok.type == 'IDENT' and tok.value.lower() == 'and': continue if not tok.is_container: raise MalformedExpression(tok, 'expected a media expression not a %s' % tok.type) if tok.type != '(': raise MalformedExpression(tok, 'media expressions must be in parentheses not %s' % tok.type) content = remove_whitespace(tok.content) if len(content) == 0: raise MalformedExpression(tok, 'media expressions cannot be empty') if content[0].type != 'IDENT': raise MalformedExpression(content[0], 'expected a media feature not a %s' % tok.type) media_feature, expr = content[0].value, None if len(content) > 1: if len(content) < 3: raise MalformedExpression(content[1], 'malformed media feature definition') if content[1].type != ':': raise MalformedExpression(content[1], 'expected a :') expr = content[2:] if len(expr) == 1: expr = expr[0] elif len(expr) == 3 and (expr[0].type, expr[1].type, expr[1].value, expr[2].type) == ( 'INTEGER', 'DELIM', '/', 'INTEGER'): # This should really be moved into token_data, but # since RATIO is not part of CSS 2.1 and does not # occur anywhere else, we special case it here. r = expr[0] r.value = (expr[0].value, expr[2].value) r.type = 'RATIO' r._as_css = expr[0]._as_css + expr[1]._as_css + expr[2]._as_css expr = r else: raise MalformedExpression(expr[0], 'malformed media feature definition') expressions.append((media_feature, expr)) except MalformedExpression as err: errors.extend(ParseError(err.tok, err.message)) media_type, negated, expressions = 'all', True, () queries.append(MediaQuery(media_type or 'all', expressions=tuple(expressions), negated=negated)) return queries