Example #1
0
def test_addition():
    # Numbers are a little complicated, what with all the units
    # Simple case
    assert Number(123) + Number(456) == Number(579)
    # Simple equal units
    assert Number(1, "px") + Number(2, "px") == Number(3, "px")
    # Unitless values inherit units of the other operand
    assert Number(5) + Number(6, "px") == Number(11, "px")
    # Zero values can cast to any units
    assert Number(0, "in") + Number(24, "deg") == Number(24, "deg")
    # With different units, the left operand wins
    assert Number(10, "cm") + Number(100, "mm") == Number(20, "cm")
    assert Number(100, "mm") + Number(10, "cm") == Number(200, "mm")
    # Unconvertible units raise an error
    with pytest.raises(ValueError):
        Number(1, "px") + Number(1, "em")

    # Adding anything to a string makes a string
    assert Number(123) + String('abc') == String('123abc')
    assert String('abc') + Number(123) == String('abc123')

    ret = String('abc', quotes=None) + String('def', quotes=None)
    assert ret == String('abcdef')
    assert ret.quotes is None

    ret = String('abc', quotes='"') + String('def', quotes=None)
    assert ret == String('abcdef')
    assert ret.quotes is '"'

    ret = String('abc', quotes=None) + String('def', quotes='"')
    assert ret == String('abcdef')
    assert ret.quotes is None

    assert Color.from_hex('#010305') + Color.from_hex('#050301') == Color.from_hex('#060606')
    assert Color.from_name('white') + Color.from_name('white') == Color.from_name('white')
def customise_css():
    colour = colours.get_from_qs(flask.request.args)
    namespace = Namespace()
    namespace.set_variable('$fg', Color.from_hex(colour.fg))
    namespace.set_variable('$bg', Color.from_hex(colour.bg))
    namespace.set_variable('$highFg', Color.from_hex(colour.highFg))
    namespace.set_variable('$highBg', Color.from_hex(colour.highBg))

    compiler = Compiler(namespace=namespace)
    res = make_response(compiler.compile('style/index.scss'))
    res.mimetype = 'text/css'
    return res
Example #3
0
def test_reference_operations():
    """Test the example expressions in the reference document:

    http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#operations
    """
    # TODO: break this into its own file and add the entire reference guide

    # Need to build the calculator manually to get at its namespace, and need
    # to use calculate() instead of evaluate_expression() so interpolation
    # works
    ns = CoreExtension.namespace.derive()
    calc = Calculator(ns).calculate

    # Simple example
    assert calc('1in + 8pt') == Number(1.1111111111111112, "in")

    # Division
    ns.set_variable('$width', Number(1000, "px"))
    ns.set_variable('$font-size', Number(12, "px"))
    ns.set_variable('$line-height', Number(30, "px"))
    assert calc('10px/8px') == String('10px / 8px')   # plain CSS; no division
    assert calc('$width/2') == Number(500, "px")      # uses a variable; does division
    assert calc('(500px/2)') == Number(250, "px")     # uses parens; does division
    assert calc('5px + 8px/2px') == Number(9, "px")   # uses +; does division
    # TODO, again: Ruby Sass correctly renders this without spaces
    assert calc('#{$font-size}/#{$line-height}') == String('12px / 30px')
                                            # uses #{}; does no division

    # Modulo
    assert calc('29 % 12') == Number(5)
    assert calc('29px % 12') == Number(5, 'px')
    assert calc('29px % 12px') == Number(5, 'px')

    # Color operations
    ns.set_variable('$translucent-red', Color.from_rgb(1, 0, 0, 0.5))
    ns.set_variable('$green', Color.from_name('lime'))
    assert calc('#010203 + #040506') == Color.from_hex('#050709')
    assert calc('#010203 * 2') == Color.from_hex('#020406')
    assert calc('rgba(255, 0, 0, 0.75) + rgba(0, 255, 0, 0.75)') == Color.from_rgb(1, 1, 0, 0.75)
    assert calc('opacify($translucent-red, 0.3)') == Color.from_rgb(1, 0, 0, 0.8)
    assert calc('transparentize($translucent-red, 0.25)') == Color.from_rgb(1, 0, 0, 0.25)
    assert calc("progid:DXImageTransform.Microsoft.gradient(enabled='false', startColorstr='#{ie-hex-str($green)}', endColorstr='#{ie-hex-str($translucent-red)}')"
                ).render() == "progid:DXImageTransform.Microsoft.gradient(enabled='false', startColorstr='#FF00FF00', endColorstr='#80FF0000')"

    # String operations
    ns.set_variable('$value', Null())
    assert_strict_string_eq(calc('e + -resize'), String('e-resize', quotes=None))
    assert_strict_string_eq(calc('"Foo " + Bar'), String('Foo Bar', quotes='"'))
    assert_strict_string_eq(calc('sans- + "serif"'), String('sans-serif', quotes=None))
    assert calc('3px + 4px auto') == List([Number(7, "px"), String('auto', quotes=None)])
    assert_strict_string_eq(calc('"I ate #{5 + 10} pies!"'), String('I ate 15 pies!', quotes='"'))
    assert_strict_string_eq(calc('"I ate #{$value} pies!"'), String('I ate  pies!', quotes='"'))
Example #4
0
 def kwatom(self):
     _token_ = self._peek(self.kwatom_rsts)
     if _token_ == '":"':
         pass
     elif _token_ == 'KWID':
         KWID = self._scan('KWID')
         return Literal(parse_bareword(KWID))
     elif _token_ == 'KWNUM':
         KWNUM = self._scan('KWNUM')
         UNITS = None
         if self._peek(self.kwatom_rsts_) == 'UNITS':
             UNITS = self._scan('UNITS')
         return Literal(Number(float(KWNUM), unit=UNITS))
     elif _token_ == 'KWSTR':
         KWSTR = self._scan('KWSTR')
         return Literal(String(dequote(KWSTR), quotes="'"))
     elif _token_ == 'KWQSTR':
         KWQSTR = self._scan('KWQSTR')
         return Literal(String(dequote(KWQSTR), quotes='"'))
     elif _token_ == 'KWCOLOR':
         KWCOLOR = self._scan('KWCOLOR')
         return Literal(Color.from_hex(KWCOLOR, literal=True))
     else:  # == 'KWVAR'
         KWVAR = self._scan('KWVAR')
         return Variable(KWVAR)
Example #5
0
def test_reference_operations():
    """Test the example expressions in the reference document:

    http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#operations
    """
    # TODO: break this into its own file and add the entire reference guide

    # Need to build the calculator manually to get at its namespace, and need
    # to use calculate() instead of evaluate_expression() so interpolation
    # works
    ns = Namespace(functions=CORE_LIBRARY)
    calc = Calculator(ns).calculate

    # Simple example
    assert calc('1in + 8pt') == Number(1.11111111, "in")

    # Division
    ns.set_variable('$width', Number(1000, "px"))
    ns.set_variable('$font-size', Number(12, "px"))
    ns.set_variable('$line-height', Number(30, "px"))
    assert calc('10px/8px') == String('10px / 8px') # plain CSS; no division
    assert calc('$width/2') == Number(500, "px")      # uses a variable; does division
    assert calc('(500px/2)') == Number(250, "px")     # uses parens; does division
    assert calc('5px + 8px/2px') == Number(9, "px")   # uses +; does division
    # TODO: Ruby doesn't include these spaces
    assert calc('#{$font-size}/#{$line-height}') == String('12px / 30px')
                                            # uses #{}; does no division

    # Color operations
    ns.set_variable('$translucent-red', Color.from_rgb(1, 0, 0, 0.5))
    ns.set_variable('$green', Color.from_name('lime'))
    assert calc('#010203 + #040506') == Color.from_hex('#050709')
    assert calc('#010203 * 2') == Color.from_hex('#020406')
    assert calc('rgba(255, 0, 0, 0.75) + rgba(0, 255, 0, 0.75)') == Color.from_rgb(1, 1, 0, 0.75)
    assert calc('opacify($translucent-red, 0.3)') == Color.from_rgb(1, 0, 0, 0.9)
    assert calc('transparentize($translucent-red, 0.25)') == Color.from_rgb(1, 0, 0, 0.25)
    assert calc("progid:DXImageTransform.Microsoft.gradient(enabled='false', startColorstr='#{ie-hex-str($green)}', endColorstr='#{ie-hex-str($translucent-red)}')"
                ) == "progid:DXImageTransform.Microsoft.gradient(enabled='false', startColorstr=#FF00FF00, endColorstr=#80FF0000)"

    # String operations
    ns.set_variable('$value', Null())
    assert calc('e + -resize') == 'e-resize'
    assert calc('"Foo " + Bar') == '"Foo Bar"'
    assert calc('sans- + "serif"') == 'sans-serif'
    assert calc('3px + 4px auto') == '7px auto'
    assert calc('"I ate #{5 + 10} pies!"') == '"I ate 15 pies!"'
    assert calc('"I ate #{$value} pies!"') == '"I ate  pies!"'
Example #6
0
def test_addition():
    # Numbers are a little complicated, what with all the units
    # Simple case
    assert Number(123) + Number(456) == Number(579)
    # Simple equal units
    assert Number(1, "px") + Number(2, "px") == Number(3, "px")
    # Unitless values inherit units of the other operand
    assert Number(5) + Number(6, "px") == Number(11, "px")
    # Zero values can cast to any units
    assert Number(0, "in") + Number(24, "deg") == Number(24, "deg")
    # With different units, the left operand wins
    assert Number(10, "cm") + Number(100, "mm") == Number(20, "cm")
    assert Number(100, "mm") + Number(10, "cm") == Number(200, "mm")
    # Unconvertible units raise an error
    with pytest.raises(ValueError):
        Number(1, "px") + Number(1, "em")

    # Adding anything to a string makes a string
    assert Number(123) + String('abc') == String('123abc')
    assert String('abc') + Number(123) == String('abc123')

    ret = String('abc', quotes=None) + String('def', quotes=None)
    assert ret == String('abcdef')
    assert ret.quotes is None

    ret = String('abc', quotes='"') + String('def', quotes=None)
    assert ret == String('abcdef')
    assert ret.quotes == '"'

    ret = String('abc', quotes=None) + String('def', quotes='"')
    assert ret == String('abcdef')
    assert ret.quotes is None

    assert Color.from_hex('#010305') + Color.from_hex(
        '#050301') == Color.from_hex('#060606')
    assert Color.from_name('white') + Color.from_name(
        'white') == Color.from_name('white')
Example #7
0
 def atom(self):
     _token_ = self._peek(self.u_expr_chks)
     if _token_ == 'LPAR':
         LPAR = self._scan('LPAR')
         _token_ = self._peek(self.atom_rsts)
         if _token_ == 'RPAR':
             v = ListLiteral([], comma=False)
         elif _token_ not in self.argspec_item_chks:
             expr_map = self.expr_map()
             v = expr_map
         else:  # in self.argspec_item_chks
             expr_lst = self.expr_lst()
             v = expr_lst
         RPAR = self._scan('RPAR')
         return Parentheses(v)
     elif _token_ == 'FNCT':
         FNCT = self._scan('FNCT')
         LPAR = self._scan('LPAR')
         argspec = self.argspec()
         RPAR = self._scan('RPAR')
         return CallOp(FNCT, argspec)
     elif _token_ == 'BANG_IMPORTANT':
         BANG_IMPORTANT = self._scan('BANG_IMPORTANT')
         return Literal(String(BANG_IMPORTANT, quotes=None))
     elif _token_ == 'ID':
         ID = self._scan('ID')
         return Literal(parse_bareword(ID))
     elif _token_ == 'NUM':
         NUM = self._scan('NUM')
         UNITS = None
         if self._peek(self.atom_rsts_) == 'UNITS':
             UNITS = self._scan('UNITS')
         return Literal(Number(float(NUM), unit=UNITS))
     elif _token_ == 'STR':
         STR = self._scan('STR')
         return Literal(String(STR[1:-1], quotes="'"))
     elif _token_ == 'QSTR':
         QSTR = self._scan('QSTR')
         return Literal(String(QSTR[1:-1], quotes='"'))
     elif _token_ == 'COLOR':
         COLOR = self._scan('COLOR')
         return Literal(Color.from_hex(COLOR, literal=True))
     else:  # == 'VAR'
         VAR = self._scan('VAR')
         return Variable(VAR)
Example #8
0
def test_addition(calc):
    assert calc('123 + 456') == Number(579)

    assert calc('1px + 2px') == Number(3, "px")

    assert calc('123 + abc') == String('123abc')
    assert calc('abc + 123') == String('abc123')

    assert calc('abc + def') == String('abcdef')
    assert calc('abc + "def"') == String('abcdef')
    ret = calc('"abc" + def')
    assert ret == String('abcdef')
    assert ret.quotes == '"'
    ret = calc('"abc" + "def"')
    assert ret == String('abcdef')
    assert ret.quotes == '"'

    assert calc('#010305 + #050301') == Color.from_hex('#060606')
    assert calc('#ffffff + #ffffff') == Color.from_name('white')
Example #9
0
 def atom(self):
     _token_ = self._peek(self.u_expr_chks)
     if _token_ == 'LPAR':
         LPAR = self._scan('LPAR')
         _token_ = self._peek(self.atom_rsts)
         if _token_ not in self.argspec_item_chks:
             expr_map = self.expr_map()
             v = expr_map
         else:  # in self.argspec_item_chks
             expr_lst = self.expr_lst()
             v = expr_lst
         RPAR = self._scan('RPAR')
         return Parentheses(v)
     elif _token_ == 'FNCT':
         FNCT = self._scan('FNCT')
         LPAR = self._scan('LPAR')
         argspec = self.argspec()
         RPAR = self._scan('RPAR')
         return CallOp(FNCT, argspec)
     elif _token_ == 'BANG_IMPORTANT':
         BANG_IMPORTANT = self._scan('BANG_IMPORTANT')
         return Literal(String(BANG_IMPORTANT, quotes=None))
     elif _token_ == 'ID':
         ID = self._scan('ID')
         return Literal(parse_bareword(ID))
     elif _token_ == 'NUM':
         NUM = self._scan('NUM')
         UNITS = None
         if self._peek(self.atom_rsts_) == 'UNITS':
             UNITS = self._scan('UNITS')
         return Literal(Number(float(NUM), unit=UNITS))
     elif _token_ == 'STR':
         STR = self._scan('STR')
         return Literal(String(STR[1:-1], quotes="'"))
     elif _token_ == 'QSTR':
         QSTR = self._scan('QSTR')
         return Literal(String(QSTR[1:-1], quotes='"'))
     elif _token_ == 'COLOR':
         COLOR = self._scan('COLOR')
         return Literal(Color.from_hex(COLOR, literal=True))
     else:  # == 'VAR'
         VAR = self._scan('VAR')
         return Variable(VAR)
Example #10
0
 def atom(self):
     _token_ = self._peek(self.u_expr_chks)
     if _token_ == 'LPAR':
         LPAR = self._scan('LPAR')
         _token_ = self._peek(self.atom_rsts)
         if _token_ == 'RPAR':
             v = ListLiteral([], comma=False)
         else:  # in self.argspec_item_chks
             expr_map_or_list = self.expr_map_or_list()
             v = expr_map_or_list
         RPAR = self._scan('RPAR')
         return Parentheses(v)
     elif _token_ == 'URL_FUNCTION':
         URL_FUNCTION = self._scan('URL_FUNCTION')
         LPAR = self._scan('LPAR')
         interpolated_url = self.interpolated_url()
         RPAR = self._scan('RPAR')
         return interpolated_url
     elif _token_ == 'ALPHA_FUNCTION':
         ALPHA_FUNCTION = self._scan('ALPHA_FUNCTION')
         LPAR = self._scan('LPAR')
         _token_ = self._peek(self.atom_rsts_)
         if _token_ == 'OPACITY':
             OPACITY = self._scan('OPACITY')
             self._scan('"="')
             atom = self.atom()
             RPAR = self._scan('RPAR')
             return AlphaFunctionLiteral(atom)
         else:  # in self.atom_chks
             argspec = self.argspec()
             RPAR = self._scan('RPAR')
             return CallOp("alpha", argspec)
     elif _token_ == 'IF_FUNCTION':
         IF_FUNCTION = self._scan('IF_FUNCTION')
         LPAR = self._scan('LPAR')
         expr_lst = self.expr_lst()
         RPAR = self._scan('RPAR')
         return TernaryOp(expr_lst)
     elif _token_ == 'LITERAL_FUNCTION':
         LITERAL_FUNCTION = self._scan('LITERAL_FUNCTION')
         LPAR = self._scan('LPAR')
         interpolated_function = self.interpolated_function()
         RPAR = self._scan('RPAR')
         return Interpolation.maybe(interpolated_function, type=Function, function_name=LITERAL_FUNCTION)
     elif _token_ == 'FNCT':
         FNCT = self._scan('FNCT')
         LPAR = self._scan('LPAR')
         argspec = self.argspec()
         RPAR = self._scan('RPAR')
         return CallOp(FNCT, argspec)
     elif _token_ == 'BANG_IMPORTANT':
         BANG_IMPORTANT = self._scan('BANG_IMPORTANT')
         return Literal(String.unquoted("!important", literal=True))
     elif _token_ in self.atom_chks_:
         interpolated_bareword = self.interpolated_bareword()
         return Interpolation.maybe(interpolated_bareword)
     elif _token_ == 'NUM':
         NUM = self._scan('NUM')
         UNITS = None
         if self._peek(self.atom_rsts__) == 'UNITS':
             UNITS = self._scan('UNITS')
         return Literal(Number(float(NUM), unit=UNITS))
     elif _token_ not in self.atom_chks__:
         interpolated_string = self.interpolated_string()
         return interpolated_string
     elif _token_ == 'COLOR':
         COLOR = self._scan('COLOR')
         return Literal(Color.from_hex(COLOR, literal=True))
     else:  # == 'VAR'
         VAR = self._scan('VAR')
         return Variable(VAR)
Example #11
0
 def atom(self):
     _token_ = self._peek(self.u_expr_chks)
     if _token_ == 'LPAR':
         LPAR = self._scan('LPAR')
         _token_ = self._peek(self.atom_rsts)
         if _token_ == 'RPAR':
             v = ListLiteral([], comma=False)
         else:  # in self.argspec_item_chks
             expr_map_or_list = self.expr_map_or_list()
             v = expr_map_or_list
         RPAR = self._scan('RPAR')
         return Parentheses(v)
     elif _token_ == 'URL_FUNCTION':
         URL_FUNCTION = self._scan('URL_FUNCTION')
         LPAR = self._scan('LPAR')
         interpolated_url = self.interpolated_url()
         RPAR = self._scan('RPAR')
         return interpolated_url
     elif _token_ == 'ALPHA_FUNCTION':
         ALPHA_FUNCTION = self._scan('ALPHA_FUNCTION')
         LPAR = self._scan('LPAR')
         _token_ = self._peek(self.atom_rsts_)
         if _token_ == '"opacity"':
             self._scan('"opacity"')
             self._scan('"="')
             atom = self.atom()
             RPAR = self._scan('RPAR')
             return AlphaFunctionLiteral(atom)
         else:  # in self.atom_chks
             argspec = self.argspec()
             RPAR = self._scan('RPAR')
             return CallOp("alpha", argspec)
     elif _token_ == 'LITERAL_FUNCTION':
         LITERAL_FUNCTION = self._scan('LITERAL_FUNCTION')
         LPAR = self._scan('LPAR')
         interpolated_function = self.interpolated_function()
         RPAR = self._scan('RPAR')
         return Interpolation.maybe(interpolated_function,
                                    type=Function,
                                    function_name=LITERAL_FUNCTION)
     elif _token_ == 'FNCT':
         FNCT = self._scan('FNCT')
         LPAR = self._scan('LPAR')
         argspec = self.argspec()
         RPAR = self._scan('RPAR')
         return CallOp(FNCT, argspec)
     elif _token_ == 'BANG_IMPORTANT':
         BANG_IMPORTANT = self._scan('BANG_IMPORTANT')
         return Literal(String.unquoted("!important", literal=True))
     elif _token_ in self.atom_chks_:
         interpolated_bareword = self.interpolated_bareword()
         return Interpolation.maybe(interpolated_bareword)
     elif _token_ == 'NUM':
         NUM = self._scan('NUM')
         UNITS = None
         if self._peek(self.atom_rsts__) == 'UNITS':
             UNITS = self._scan('UNITS')
         return Literal(Number(float(NUM), unit=UNITS))
     elif _token_ not in self.atom_chks__:
         interpolated_string = self.interpolated_string()
         return interpolated_string
     elif _token_ == 'COLOR':
         COLOR = self._scan('COLOR')
         return Literal(Color.from_hex(COLOR, literal=True))
     else:  # == 'VAR'
         VAR = self._scan('VAR')
         return Variable(VAR)
Example #12
0
 def atom(self):
     _token_ = self._peek(self.u_expr_chks)
     if _token_ == "LPAR":
         LPAR = self._scan("LPAR")
         _token_ = self._peek(self.atom_rsts)
         if _token_ == "RPAR":
             v = ListLiteral([], comma=False)
         else:  # in self.argspec_item_chks
             expr_map_or_list = self.expr_map_or_list()
             v = expr_map_or_list
         RPAR = self._scan("RPAR")
         return Parentheses(v)
     elif _token_ == "URL_FUNCTION":
         URL_FUNCTION = self._scan("URL_FUNCTION")
         LPAR = self._scan("LPAR")
         interpolated_url = self.interpolated_url()
         RPAR = self._scan("RPAR")
         return interpolated_url
     elif _token_ == "ALPHA_FUNCTION":
         ALPHA_FUNCTION = self._scan("ALPHA_FUNCTION")
         LPAR = self._scan("LPAR")
         _token_ = self._peek(self.atom_rsts_)
         if _token_ == '"opacity"':
             self._scan('"opacity"')
             self._scan('"="')
             NUM = self._scan("NUM")
             RPAR = self._scan("RPAR")
             return FunctionLiteral(Literal(String.unquoted("opacity=" + NUM)), "alpha")
         else:  # in self.atom_chks
             argspec = self.argspec()
             RPAR = self._scan("RPAR")
             return CallOp("alpha", argspec)
     elif _token_ == "LITERAL_FUNCTION":
         LITERAL_FUNCTION = self._scan("LITERAL_FUNCTION")
         LPAR = self._scan("LPAR")
         interpolated_function = self.interpolated_function()
         RPAR = self._scan("RPAR")
         return Interpolation.maybe(interpolated_function, type=Function, function_name=LITERAL_FUNCTION)
     elif _token_ == "FNCT":
         FNCT = self._scan("FNCT")
         LPAR = self._scan("LPAR")
         argspec = self.argspec()
         RPAR = self._scan("RPAR")
         return CallOp(FNCT, argspec)
     elif _token_ == "BANG_IMPORTANT":
         BANG_IMPORTANT = self._scan("BANG_IMPORTANT")
         return Literal(String.unquoted("!important", literal=True))
     elif _token_ in self.atom_chks_:
         interpolated_bareword = self.interpolated_bareword()
         return Interpolation.maybe(interpolated_bareword)
     elif _token_ == "NUM":
         NUM = self._scan("NUM")
         UNITS = None
         if self._peek(self.atom_rsts__) == "UNITS":
             UNITS = self._scan("UNITS")
         return Literal(Number(float(NUM), unit=UNITS))
     elif _token_ not in self.atom_chks__:
         interpolated_string = self.interpolated_string()
         return interpolated_string
     elif _token_ == "COLOR":
         COLOR = self._scan("COLOR")
         return Literal(Color.from_hex(COLOR, literal=True))
     else:  # == 'VAR'
         VAR = self._scan("VAR")
         return Variable(VAR)
Example #13
0
def test_subtraction():
    assert Number(123) - Number(456) == Number(-333)
    assert Number(456) - Number(123) == Number(333)
    # TODO test that subtracting e.g. strings doesn't work

    assert Color.from_hex('#0f0f0f') - Color.from_hex('#050505') == Color.from_hex('#0a0a0a')
Example #14
0
def test_subtraction(calc):
    assert calc('123 - 456') == Number(-333)
    assert calc('456 - 123') == Number(333)
    # TODO test that subtracting e.g. strings doesn't work

    assert calc('#0f0f0f - #050505') == Color.from_hex('#0a0a0a')