def populate_global_scope(self): """ Populate the global scope with: - css colors - user-defined globals :return: """ self.common._scope = Scope() # colors for color, value in colors.items(): rgba = RGBA(value[0], value[1], value[2], value[3]) ident = Ident(color, rgba) rgba.name = color self.common.scope().add(ident) # todo: should this be here? # self.common.scope().add(Ident('embedurl', # Function('embedurl', url.fn, # lineno=self.parser.lineno, # column=self.parser.column))) # user defined globals commons = self.commons for common, val in commons.items(): if val.name: self.common.scope().add(Ident(common, val))
def test_parser_property(): parser = Parser("color: red\n", {}) property = parser.property() assert property.segments[0] == Ident( "color", null, False, lineno=1, column=1 ) assert property.expr.nodes[0] == Ident( "red", null, False, lineno=1, column=8 )
def test_scope_add(): scope = Scope() scope.add(Ident("one", 1)) assert scope.commons["one"] == 1 scope.add(Ident(None, None)) assert scope.commons[None] == null scope.add(Ident("two")) assert scope.commons["two"] == null assert str(scope) == "[Scope @one, @None, @two]"
def test_stack(): stack = Stack() block = Block(Ident("hello", "there"), Ident("foo", "bar")) assert stack.get_block_frame(block) is None frame = Frame(block) stack.append(frame) assert len(stack) == 1 assert stack.get_block_frame(block) == frame assert stack.current_frame() == frame
def test_feature(): foo = Ident("foo") bar = Ident("bar") feature = Feature([foo, bar]) assert feature.node_name == "feature" assert feature.segments == [foo, bar] assert feature.expr is None expression = Expression() feature.expr = expression assert feature.expr == expression
def test_lexer_ident_space(): lexer = Lexer("abc def klm:\n xyz abc\n", {}) tokens = [token for token in lexer] from stilus.nodes.null import null assert tokens[0] == Token("ident", Ident("abc", null), lineno=1, column=1) assert tokens[1] == Token("space", lineno=1, column=4) assert tokens[2] == Token("ident", Ident("def", null), lineno=1, column=5) assert tokens[3] == Token("space", lineno=1, column=8) assert tokens[4] == Token("ident", Ident("klm", null), lineno=1, column=9)
def split(delim, value, evaluator=None): assert_string(delim, "delimiter") assert_string(value, "val") words = value.string.split(delim.string) expr = Expression() for word in words: if isinstance(value, Ident): addition = Ident(word) else: addition = String(word) expr.append(Ident(addition)) return expr
def test_scope_lookup(): scope = Scope() scope.add(Ident("one", 1)) scope.add(Ident("two")) scope.add(Ident("three", true)) assert len(scope.commons) == 3 assert scope.lookup("one") == 1 assert scope.lookup("two") == null assert scope.lookup("three") == true assert scope.lookup("four") is None assert scope.lookup(None) is None assert str(scope) == "[Scope @one, @two, @three]"
def test_lexer_is_part_of_selector(): lexer = Lexer("^if.null,[bar],abc color: black\n", {}) assert lexer.next() == Token("selector", "^", lineno=1, column=1) assert lexer.next() == Token("if", "if", lineno=1, column=2) assert lexer.next() == Token(".", ".", "", lineno=1, column=4) assert lexer.next() == Token("ident", Ident("null"), lineno=1, column=5) lexer = Lexer("^#fif: black\n", {}) assert lexer.next() == Token("selector", "^", lineno=1, column=1) assert lexer.next() == Token( "color", RGBA(255, 255, 255, 1), lineno=1, column=2 ) assert lexer.next() == Token("ident", Ident("if"), lineno=1, column=4)
def test_lexer_ident_colon_null_newline_eos(): lexer = Lexer("abc:\n color: null\n", {}) tokens = [token for token in lexer] from stilus.nodes.null import null assert tokens[0] == Token("ident", Ident("abc", null), lineno=1, column=1) assert tokens[1] == Token(":", ":", "", lineno=1, column=4) assert tokens[2] == Token( "ident", Ident("color", null), lineno=1, column=5 ) assert tokens[3] == Token(":", ":", " ", lineno=2, column=11) assert tokens[4] == Token("null", value=null, lineno=2, column=13) assert tokens[5] == Token("newline", lineno=2, column=17) assert tokens[6] == Token("eos", lineno=3, column=1)
def test_parser_parse_basic(): parser = Parser("abc\n color: red\n", {}) root = parser.parse() assert root.node_name == "root" assert root.nodes[0].node_name == "group" selector = root.nodes[0].nodes[0] assert selector.segments[0] == Literal("abc") assert selector.block.parent == root assert selector.block.node.node_name == "group" property = selector.block.nodes[0] assert property.node_name == "property" assert len(property.segments) == 1 assert property.segments[0] == Ident("color", null, lineno=2, column=3) assert len(property.expr.nodes) == 1 assert property.expr.nodes[0] == Ident("red", null, lineno=2, column=10)
def test_lexer_ident_colon_colors(): lexer = Lexer("abc: #11223311, #aabbcc, #abc1, #fff, #dd, #e", {}) tokens = [token for token in lexer] from stilus.nodes.null import null assert tokens[0] == Token("ident", Ident("abc", null), lineno=1, column=1) assert tokens[1] == Token(":", ":", " ", lineno=1, column=4) assert tokens[2] == Token( "color", RGBA(17, 34, 51, 0.67), lineno=1, column=6 ) assert tokens[4] == Token( "color", RGBA(170, 187, 204, 1), lineno=1, column=17 ) assert tokens[6] == Token( "color", RGBA(170, 187, 204, 0.067), lineno=1, column=26 ) assert tokens[8] == Token( "color", RGBA(255, 255, 255, 1), lineno=1, column=33 ) assert tokens[10] == Token( "color", RGBA(221, 221, 221, 1), lineno=1, column=39 ) assert tokens[12] == Token( "color", RGBA(238, 238, 238, 1), lineno=1, column=44 )
def test_parser_peek_lookahead_and_next(): parser = Parser("abc\n color: red\n", {}) # next node = parser.next() assert node.type == "ident" assert node.value == Ident("abc", lineno=1, column=1) node = parser.next() assert node.type == "indent" assert node.value is None # peek assert parser.peek().type == "ident" assert parser.peek().type == "ident" assert parser.peek().type == "ident" # lookahead assert parser.lookahead(1) == parser.peek() assert parser.lookahead(2).type == ":" assert parser.lookahead(2).value == ":" assert parser.lookahead(2).space == " " # next parser.next() node = parser.next() assert node.type == ":" assert node.value == ":" assert node.space == " " # combo assert parser.peek().type == "ident" parser.next() assert parser.peek().type == "outdent" parser.next() assert parser.peek().type == "eos"
def test_ident(): ident = Ident("string", "value", True) assert ident.string == "string" assert ident.value == "value" assert ident.mixin is True assert ident.node_name == "ident" assert ident.is_empty() is False
def test_ident_no_value(): ident = Ident("node_name", None, True) assert ident.node_name == "ident" assert ident.string == "node_name" assert ident.value == null assert ident.mixin is True assert ident.is_empty() is False
def test_frame_lookup(): frame = Frame(Block("hello", "there")) scope = Scope() scope.add(Ident("foo", "bar")) frame._scope = scope assert frame.lookup("foo") == "bar" assert frame.lookup("unknown") is None
def test_lexer_functions(): lexer = Lexer( "mixin(add) {\n" " mul = @(c, d) {\n" " c * d\n" " }\n" " width: add(2, 3) + mul(4, 5)\n" "}\n", {}, ) tokens = [token for token in lexer] assert tokens[0] == Token( "function", Ident("mixin", null), "", lineno=1, column=1 ) anon_fun_token = Token("function", Ident("anonymous"), lineno=2, column=9) anon_fun_token.anonymous = True assert tokens[8] == anon_fun_token
def test_property_color_red(): # color: red expression = Expression() expression.append(Ident("red")) property = Property(["color"], expression) assert property.expr == expression assert len(property.segments) == 1 assert f"{property}" == "property(color, (red))"
def test_parser_selector(): parser = Parser("abc\n color: red\n", {}) selector = parser.stmt_selector() assert selector.node_name == "group" assert type(selector) == Group assert len(selector.nodes) == 1 assert selector.nodes[0].node_name == "selector" assert len(selector.nodes[0].segments) == 1 assert selector.nodes[0].segments[0] == Literal("abc") block = selector.nodes[0].block assert block.node_name == "block" assert len(block.nodes) == 1 property = block.nodes[0] assert property.node_name == "property" assert len(property.segments) == 1 assert property.segments[0] == Ident("color", null, lineno=2, column=3) assert len(property.expr.nodes) == 1 assert property.expr.nodes[0] == Ident("red", null, lineno=2, column=10)
def replace(pattern, replacement, value, evaluator=None): assert_string(pattern, "pattern") assert_string(replacement, "replacement") assert_string(value, "value") result = value.string.replace(pattern.string, replacement.string) if isinstance(value, Ident): return Ident(result) else: return String(result)
def test_lexer_peek(): lexer = Lexer("abc:\n color: #11223311\n", {}) abc = Token("ident", Ident("abc", null), lineno=1, column=1) assert lexer.peek() == abc assert lexer.peek() == abc assert lexer.next() == abc colon = Token(":", ":", "", lineno=1, column=4) assert lexer.peek() == Token(":", ":", "", lineno=1, column=4) assert lexer.next() == colon
def define(name, expr, common=None, evaluator=None): assert_type(name, "string", "name") expr = unwrap(expr) scope = evaluator.get_current_scope() if common and common.to_boolean().is_true(): scope = evaluator.common.scope() node = Ident(name.value, expr) scope.add(node) return null
def visit_each(self, each): self.result += 1 expr = utils.unwrap(self.visit(each.expr)) length = len(expr.nodes) val = Ident(each.value) key = Ident("__index__") if each.key: key = Ident(each.key) scope = self.get_current_scope() block = self.get_current_block() vals = [] self.result -= 1 each.block.scope = False def visit_body(key, value): scope.add(value) scope.add(key) body = self.visit(each.block.clone()) vals.extend(body.nodes) # for prop in obj if length == 1 and "objectnode" == expr.nodes[0].node_name: obj = expr.nodes[0] for prop in obj.values: val.value = String(prop, lineno=self.parser.lineno, column=self.parser.column) key.value = obj.get(prop) # checkme: works? visit_body(key, val) else: for i, n in enumerate(expr.nodes): val.value = n key.value = Unit(i) visit_body(key, val) self.mixin(vals, block) if vals and len(vals) > 0: return vals[len(vals) - 1] else: return null
def test_expression_hash(): expression = Expression() assert expression.hash() == "" expression = Expression() expression.append(Ident("foo")) assert expression.hash() == "foo" other_expression = Expression() other_expression.append(Ident("foo")) other_expression.append(Ident("bar")) assert other_expression.hash() == "foo::bar" from stilus.nodes.null import null from stilus.nodes.boolean import true from stilus.nodes.boolean import false expression = Expression() expression.append(null) expression.append(true) expression.append(false) # in stylus null::true::false is returned; stilus returns the Python types assert expression.hash() == "None::True::False"
def test_coerce(): first = String("hello") other = String("there") assert first.coerce(other) == other expression = Expression() expression.append(String("one")) expression.append(String("two")) expression.append(String("three")) assert first.coerce(expression) == String("one two three") assert first.coerce(null) == String("null") assert first.coerce(Ident("foobar")) == String("foobar")
def substr(value, start, length=None, evaluator=None): assert_string(value, "val") assert_type(start, "unit", "start") start = int(start.value) if length: length = start + int(length.value) result = value.string[start:length] if isinstance(value, Ident): return Ident(result) else: return String(result)
def convert(content, prefix=None): if prefix: prefix = prefix + "-" else: prefix = "" for key in content: val = content[key] name = prefix + key if isinstance(val, dict): convert(val, name) else: val = coerce(val, raw=False) if val.node_name == "string": val = parse_string(val.string) scope.add(Ident(name_prefix + name, val))
def test_lexer_function_paren_braces_sep_unit(): lexer = Lexer( "bg()\n" " background: blue\n" "\n" "body {\n" " bg(); width: 100px\n" "}\n", {}, ) tokens = [token for token in lexer] from stilus.nodes.null import null assert tokens[0] == Token( "function", Ident("bg", null), "", lineno=1, column=1 ) assert tokens[1] == Token(")", ")", "", lineno=1, column=4) assert tokens[9] == Token("{", "{", lineno=4, column=6) assert tokens[11] == Token( "function", Ident("bg", null), "", lineno=5, column=3 ) assert tokens[13] == Token(";", None, lineno=5, column=7) assert tokens[16] == Token("unit", Unit(100.0, "px"), lineno=5, column=16) assert tokens[18] == Token("}", "}", lineno=6, column=1)
def test_frame_scopes(): # regular block (scope is True) and frame has no parent -> scope == Scope() block = Block(Ident("hello"), Ident("there")) frame = Frame(block) assert frame.scope() == Scope() assert frame.block == block assert frame.parent is None # irregular block (scope is False) frame has no parent... block = Block(Ident("hello"), Ident("there"), scope=False) frame = Frame(block) # ...raises TypeError since no parent with raises(TypeError): frame.scope() assert frame.block == block assert frame.parent is None # regular block (scope is True) and frame has a parent -> scope == Scope() block = Block(Ident("hello"), Ident("there")) parent = Block(Ident("fizz"), Ident("fuzz")) frame = Frame(block, parent) assert frame.scope() == Scope() assert frame.block == block assert frame.parent is parent
def slice(values, start, end=None, evaluator=None): start = int(start.nodes[0].value) if end and len(end.nodes) > 0: end = int(end.nodes[0].value) values = utils.unwrap(values).nodes if len(values) > 1: if end: return utils.coerce(values[start:end], raw=True) else: return utils.coerce(values[start:], raw=True) if end: result = values[0].string[start:end] else: result = values[0].string[start:] if isinstance(values[0], Ident): return Ident(result) else: return String(result)