コード例 #1
0
def test_comparison_stringerific():
    abc = String('abc')
    xyz = String('xyz')

    assert abc == abc
    assert abc != xyz
    assert not abc == xyz
    assert not abc != abc

    # Interaction with other types
    assert Number(123) != String('123')
    assert String('123') != Number(123)

    # Sass strings don't support ordering
    with pytest.raises(TypeError):
        abc < xyz

    with pytest.raises(TypeError):
        abc <= xyz

    with pytest.raises(TypeError):
        abc > xyz

    with pytest.raises(TypeError):
        abc >= xyz

    with pytest.raises(TypeError):
        Number(123) < String('123')
コード例 #2
0
def __grad_position(index, default, radial, color_stops):
    try:
        stops = Number(color_stops[index][0])
        if radial and not stops.is_simple_unit('px') and (index == 0 or index == -1 or index == len(color_stops) - 1):
            log.warn("Webkit only supports pixels for the start and end stops for radial gradients. Got %s", stops)
    except IndexError:
        stops = Number(default)
    return stops
コード例 #3
0
def __radial_svg(color_stops, cx, cy, r):
    gradient = '<radialGradient id="grad" gradientUnits="userSpaceOnUse" cx="%s" cy="%s" r="%s">%s</radialGradient>' % (
        to_str(Number(cx)),
        to_str(Number(cy)),
        to_str(Number(r)),
        __color_stops_svg(color_stops)
    )
    return __svg_template(gradient)
コード例 #4
0
def _linear_svg(color_stops, x1, y1, x2, y2):
    gradient = '<linearGradient id="grad" x1="%s" y1="%s" x2="%s" y2="%s">%s</linearGradient>' % (
        to_str(Number(x1)),
        to_str(Number(y1)),
        to_str(Number(x2)),
        to_str(Number(y2)),
        __color_stops_svg(color_stops)
    )
    return __svg_template(gradient)
コード例 #5
0
ファイル: helpers.py プロジェクト: return42/pyScss
def dash_compass_slice(lst, start_index, end_index=None):
    start_index = Number(start_index).value
    end_index = Number(end_index).value if end_index is not None else None
    ret = {}
    lst = List(lst)
    if end_index:
        # This function has an inclusive end, but Python slicing is exclusive
        end_index += 1
    ret = lst.value[start_index:end_index]
    return List(ret, use_comma=lst.use_comma)
コード例 #6
0
def _render_standard_color_stops(color_stops):
    pairs = []
    for i, (stop, color) in enumerate(color_stops):
        if ((i == 0 and stop == Number(0, '%')) or
                (i == len(color_stops) - 1 and stop == Number(100, '%'))):
            pairs.append(color)
        else:
            pairs.append(List([color, stop], use_comma=False))

    return List(pairs, use_comma=True)
コード例 #7
0
def background_noise(density=None,
                     opacity=None,
                     size=None,
                     monochrome=False,
                     intensity=(),
                     color=None,
                     background=None,
                     inline=False):
    if not Image:
        raise Exception("Images manipulation require PIL")

    density = [Number(v).value for v in List.from_maybe(density)]
    intensity = [Number(v).value for v in List.from_maybe(intensity)]
    color = [Color(v).value for v in List.from_maybe(color) if v]
    opacity = [Number(v).value for v in List.from_maybe(opacity)]

    size = int(Number(size).value) if size else 0
    if size < 1 or size > 512:
        size = 200

    monochrome = bool(monochrome)

    background = Color(background).value if background else None

    new_image = Image.new(mode='RGBA', size=(size, size))

    pixdata = new_image.load()
    _image_noise(pixdata, size, density, intensity, color, opacity, monochrome)

    if not inline:
        key = (size, density, intensity, color, opacity, monochrome)
        asset_file = 'noise-%s%sx%s' % ('mono-' if monochrome else '', size,
                                        size)
        # asset_file += '-[%s][%s]' % ('-'.join(to_str(s).replace('.', '_') for s in density or []), '-'.join(to_str(s).replace('.', '_') for s in opacity or []))
        asset_file += '-' + base64.urlsafe_b64encode(
            hashlib.md5(repr(key)).digest()).rstrip('=').replace('-', '_')
        asset_file += '.png'
        asset_path = os.path.join(
            config.ASSETS_ROOT or os.path.join(config.STATIC_ROOT, 'assets'),
            asset_file)
        try:
            new_image.save(asset_path)
        except IOError:
            log.exception("Error while saving image")
            inline = True  # Retry inline version
        url = '%s%s' % (config.ASSETS_URL, asset_file)
    if inline:
        output = six.BytesIO()
        new_image.save(output, format='PNG')
        contents = output.getvalue()
        output.close()
        url = 'data:image/png;base64,' + base64.b64encode(contents)

    inline = 'url("%s")' % escape(url)
    return String.unquoted(inline)
コード例 #8
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

    # 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='"'))
コード例 #9
0
def grad_point(*p):
    pos = set()
    hrz = vrt = Number(0.5, '%')
    for _p in p:
        pos.update(String.unquoted(_p).value.split())
    if 'left' in pos:
        hrz = Number(0, '%')
    elif 'right' in pos:
        hrz = Number(1, '%')
    if 'top' in pos:
        vrt = Number(0, '%')
    elif 'bottom' in pos:
        vrt = Number(1, '%')
    return List([v for v in (hrz, vrt) if v is not None])
コード例 #10
0
ファイル: webchat.py プロジェクト: tesla1856/LalkaChat
    def style_scss(self, *path):
        css_namespace = Namespace()
        for key, value in self.settings['keys'].items():
            if isinstance(value, LCText):
                css_value = String(value)
            elif isinstance(value, LCColour):
                css_value = Color.from_hex(value)
            elif isinstance(value, LCBool):
                css_value = Boolean(value.simple())
            elif isinstance(value, LCSpin):
                css_value = Number(value.simple())
            else:
                raise ValueError("Unable to find comparable values")
            css_namespace.set_variable('${}'.format(key), css_value)

        cherrypy.response.headers['Content-Type'] = 'text/css'
        with open(os.path.join(self.settings['location'], *path), 'r') as css:
            css_content = css.read()
            compiler = Compiler(namespace=css_namespace, output_style='nested')
            # Something wrong with PyScss,
            #  Syntax error: Found u'100%' but expected one of ADD.
            # Doesn't happen on next attempt, so we are doing bad thing
            attempts = 0
            while attempts < 100:
                try:
                    attempts += 1
                    ret_string = compiler.compile_string(css_content)
                    return ret_string
                except Exception as exc:
                    if attempts == 100:
                        log.debug(exc)
コード例 #11
0
ファイル: helpers.py プロジェクト: return42/pyScss
def enumerate_(prefix, frm, through, separator='-'):
    separator = String.unquoted(separator).value
    try:
        frm = int(getattr(frm, 'value', frm))
    except ValueError:
        frm = 1
    try:
        through = int(getattr(through, 'value', through))
    except ValueError:
        through = frm
    if frm > through:
        # DEVIATION: allow reversed enumerations (and ranges as range() uses enumerate, like '@for .. from .. through')
        frm, through = through, frm
        rev = reversed
    else:
        rev = lambda x: x

    ret = []
    for i in rev(range(frm, through + 1)):
        if prefix and prefix.value:
            ret.append(
                String.unquoted(prefix.value + separator + six.text_type(i)))
        else:
            ret.append(Number(i))

    return List(ret, use_comma=True)
コード例 #12
0
def adjust_color(
        color, red=None, green=None, blue=None,
        hue=None, saturation=None, lightness=None, alpha=None):
    do_rgb = red or green or blue
    do_hsl = hue or saturation or lightness
    if do_rgb and do_hsl:
        raise ValueError(
            "Can't adjust both RGB and HSL channels at the same time")

    zero = Number(0)
    a = color.alpha + (alpha or zero).value

    if do_rgb:
        r, g, b = color.rgba[:3]
        channels = [
            current + (adjustment or zero).value / 255
            for (current, adjustment) in zip(color.rgba, (red, green, blue))]
        return Color.from_rgb(*channels, alpha=a)

    else:
        h, s, l = color.hsl
        h = (h + (hue or zero).value / 360) % 1
        s += _interpret_percentage(saturation or zero, relto=100, clamp=False)
        l += _interpret_percentage(lightness or zero, relto=100, clamp=False)
        return Color.from_hsl(h, s, l, a)
コード例 #13
0
ファイル: images.py プロジェクト: lamby/31bananas
def image_height(image):
    """
    Returns the height of the image found at the path supplied by `image`
    relative to your project's images directory.
    """
    if not Image:
        raise Exception("Images manipulation require PIL")
    filepath = String.unquoted(image).value
    path = None
    try:
        height = _image_size_cache[filepath][1]
    except KeyError:
        height = 0
        IMAGES_ROOT = _images_root()
        if callable(IMAGES_ROOT):
            try:
                _file, _storage = list(IMAGES_ROOT(filepath))[0]
            except IndexError:
                pass
            else:
                path = _storage.open(_file)
        else:
            _path = os.path.join(IMAGES_ROOT, filepath.strip('/'))
            if os.path.exists(_path):
                path = open(_path, 'rb')
        if path:
            image = Image.open(path)
            size = image.size
            height = size[1]
            _image_size_cache[filepath] = size
    return Number(height, 'px')
コード例 #14
0
def image_width(image):
    """
    Returns the width of the image found at the path supplied by `image`
    relative to your project's images directory.
    """
    if not Image:
        raise SassMissingDependency('PIL', 'image manipulation')

    image_size_cache = _get_cache('image_size_cache')

    filepath = String.unquoted(image).value
    path = None
    try:
        width = image_size_cache[filepath][0]
    except KeyError:
        width = 0
        IMAGES_ROOT = _images_root()
        if callable(IMAGES_ROOT):
            try:
                _file, _storage = list(IMAGES_ROOT(filepath))[0]
            except IndexError:
                pass
            else:
                path = _storage.open(_file)
        else:
            _path = os.path.join(IMAGES_ROOT, filepath.strip(os.sep))
            if os.path.exists(_path):
                path = open(_path, 'rb')
        if path:
            image = Image.open(path)
            size = image.size
            width = size[0]
            image_size_cache[filepath] = size
    return Number(width, 'px')
コード例 #15
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(KWSTR[1:-1], quotes="'"))
     elif _token_ == 'KWQSTR':
         KWQSTR = self._scan('KWQSTR')
         return Literal(String(KWQSTR[1:-1], quotes='"'))
     elif _token_ == 'KWCOLOR':
         KWCOLOR = self._scan('KWCOLOR')
         return Literal(Color.from_hex(COLOR, literal=True))
     else:  # == 'KWVAR'
         KWVAR = self._scan('KWVAR')
         return Variable(KWVAR)
コード例 #16
0
def test_comparison_null():
    null = Null()

    assert null == null
    assert null != Number(0)

    with pytest.raises(TypeError):
        null < null
コード例 #17
0
ファイル: test_gradients.py プロジェクト: ziotoie00/pyScss
def test_linear_gradient():
    # Set up some values
    to = String.unquoted('to')
    bottom = String.unquoted('bottom')
    left = String.unquoted('left')

    red = Color.from_name('red')
    blue = Color.from_name('blue')

    start = Number(0, "%")
    middle = Number(50, "%")
    end = Number(100, "%")

    assert (linear_gradient(left, List((red, start)), List(
        (blue, middle))) == String('linear-gradient(left, red, blue 50%)'))

    assert (linear_gradient(List((to, bottom)), blue, List(
        (red, end))) == String('linear-gradient(to bottom, blue, red)'))
コード例 #18
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')
コード例 #19
0
ファイル: extra.py プロジェクト: incidunt/pyScss
def image_color(color, width=1, height=1):
    if not Image:
        raise Exception("Images manipulation require PIL")
    w = int(Number(width).value)
    h = int(Number(height).value)
    if w <= 0 or h <= 0:
        raise ValueError
    new_image = Image.new(
        mode='RGB' if color.alpha == 1 else 'RGBA',
        size=(w, h),
        color=color.rgba255,
    )
    output = six.BytesIO()
    new_image.save(output, format='PNG')
    contents = output.getvalue()
    output.close()
    url = make_data_url('image/png', contents)
    inline = 'url("%s")' % escape(url)
    return String.unquoted(inline)
コード例 #20
0
ファイル: helpers.py プロジェクト: return42/pyScss
def _position(opposite, positions):
    if positions is None:
        positions = DEFAULT_POSITION
    else:
        positions = List.from_maybe(positions)

    ret = []
    for pos in positions:
        if isinstance(pos, (String, six.string_types)):
            pos_value = getattr(pos, 'value', pos)
            if pos_value in OPPOSITE_POSITIONS:
                if opposite:
                    ret.append(OPPOSITE_POSITIONS[pos_value])
                else:
                    ret.append(pos)
                continue
            elif pos_value == 'to':
                # Gradient syntax keyword; leave alone
                ret.append(pos)
                continue

        elif isinstance(pos, Number):
            if pos.is_simple_unit('%'):
                if opposite:
                    ret.append(Number(100 - pos.value, '%'))
                else:
                    ret.append(pos)
                continue
            elif pos.is_simple_unit('deg'):
                # TODO support other angle types?
                if opposite:
                    ret.append(Number((pos.value + 180) % 360, 'deg'))
                else:
                    ret.append(pos)
                continue

        if opposite:
            log.warn("Can't find opposite for position %r" % (pos, ))
        ret.append(pos)

    return List(ret, use_comma=False).maybe()
コード例 #21
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')
コード例 #22
0
def sprite_position(map, sprite, offset_x=None, offset_y=None):
    """
    Returns the position for the original image in the sprite.
    This is suitable for use as a value to background-position.
    """
    map = map.render()
    sprite_map = sprite_maps.get(map)
    sprite_name = String.unquoted(sprite).value
    sprite = sprite_map and sprite_map.get(sprite_name)
    if not sprite_map:
        log.error("No sprite map found: %s", map, extra={'stack': True})
    elif not sprite:
        log.error("No sprite found: %s in %s", sprite_name, sprite_map['*n*'], extra={'stack': True})
    if sprite:
        x = None
        if offset_x is not None and not isinstance(offset_x, Number):
            x = offset_x
        if not x or x.value not in ('left', 'right', 'center'):
            if x:
                offset_x = None
            x = Number(offset_x or 0, 'px')
            if not x.value or (x.value <= -1 or x.value >= 1) and not x.is_simple_unit('%'):
                x -= Number(sprite[2], 'px')
        y = None
        if offset_y is not None and not isinstance(offset_y, Number):
            y = offset_y
        if not y or y.value not in ('top', 'bottom', 'center'):
            if y:
                offset_y = None
            y = Number(offset_y or 0, 'px')
            if not y.value or (y.value <= -1 or y.value >= 1) and not y.is_simple_unit('%'):
                y -= Number(sprite[3], 'px')
        return List([x, y])
    return List([Number(0), Number(0)])
コード例 #23
0
ファイル: sprites.py プロジェクト: 571451370/devstack_mitaka
def sprite(map, sprite, offset_x=None, offset_y=None, cache_buster=True):
    """
    Returns the image and background position for use in a single shorthand
    property
    """
    map = map.render()
    sprite_maps = _get_cache('sprite_maps')
    sprite_map = sprite_maps.get(map)
    sprite_name = String.unquoted(sprite).value
    sprite = sprite_map and sprite_map.get(sprite_name)
    if not sprite_map:
        log.error("No sprite map found: %s", map, extra={'stack': True})
    elif not sprite:
        log.error("No sprite found: %s in %s",
                  sprite_name,
                  sprite_map['*n*'],
                  extra={'stack': True})
    if sprite:
        url = '%s%s' % (config.ASSETS_URL, sprite_map['*f*'])
        if cache_buster:
            url += '?_=%s' % sprite_map['*t*']
        x = Number(offset_x or 0, 'px')
        y = Number(offset_y or 0, 'px')
        if not x.value or (x.value <= -1
                           or x.value >= 1) and not x.is_simple_unit('%'):
            x -= Number(sprite[2], 'px')
        if not y.value or (y.value <= -1
                           or y.value >= 1) and not y.is_simple_unit('%'):
            y -= Number(sprite[3], 'px')
        url = "url(%s)" % escape(url)
        return List([String.unquoted(url), x, y])
    return List([Number(0), Number(0)])
コード例 #24
0
ファイル: test_expression.py プロジェクト: ziotoie00/pyScss
def test_parse_bang_important(calc):
    # The !important flag is treated as part of a spaced list.
    assert calc('40px !important') == List([
        Number(40, 'px'),
        String.unquoted('!important'),
    ],
                                           use_comma=False)

    # And is allowed anywhere in the string.
    assert calc('foo !important bar') == List([
        String('foo'),
        String('!important'),
        String('bar'),
    ],
                                              use_comma=False)

    # And may have space before the !.
    assert calc('40px ! important') == List([
        Number(40, 'px'),
        String.unquoted('!important'),
    ],
                                            use_comma=False)
コード例 #25
0
def test_alpha_opacity():
    assert calc('alpha(black)') == Number(1.)
    assert calc('alpha(rgba(black, 0.5))') == Number(0.5)
    assert calc('alpha(rgba(black, 0))') == Number(0.)

    # opacity is a synonym
    assert calc('opacity(black)') == Number(1.)
    assert calc('opacity(rgba(black, 0.5))') == Number(0.5)
    assert calc('opacity(rgba(black, 0))') == Number(0.)
コード例 #26
0
ファイル: test_expression.py プロジェクト: ziotoie00/pyScss
def test_parse_special_functions():
    ns = CoreExtension.namespace.derive()
    calc = Calculator(ns).calculate

    # expression() allows absolutely any old garbage inside
    # TODO we can't deal with an unmatched { due to the block locator, but ruby
    # can
    for gnarly_expression in (
            "not ~* remotely *~ valid {syntax}",
            "expression( ( -0 - floater.offsetHeight + ( document"
            ".documentElement.clientHeight ? document.documentElement"
            ".clientHeight : document.body.clientHeight ) + ( ignoreMe"
            " = document.documentElement.scrollTop ? document"
            ".documentElement.scrollTop : document.body.scrollTop ) ) +"
            " 'px' )"):
        expr = 'expression(' + gnarly_expression + ')'
        assert calc(expr).render() == expr

    # alpha() doubles as a special function if it contains opacity=n, the IE
    # filter syntax
    assert calc('alpha(black)') == Number(1)
    assert calc('alpha(opacity = 5)') == Function('opacity=5', 'alpha')
    assert calc('alpha(opacity = 5)').render() == 'alpha(opacity=5)'

    # url() allows both an opaque URL and a Sass expression, based on some
    # heuristics
    ns.set_variable('$foo', String.unquoted('foo'))
    assert calc('url($foo)').render() == "url(foo)"
    assert calc('url(#{$foo}foo)').render() == "url(foofoo)"
    assert calc('url($foo + $foo)').render() == "url(foofoo)"
    # TODO this one doesn't work if $foo has quotes; Url.render() tries to
    # escape them.  which i'm not sure is wrong, but we're getting into
    # territory where it's obvious bad output...
    assert calc('url($foo + #{$foo})').render() == "url(foo + foo)"
    assert calc('url(foo #{$foo} foo)').render() == "url(foo foo foo)"
    with pytest.raises(SassSyntaxError):
        # Starting with #{} means it's a url, which can't contain spaces
        calc('url(#{$foo} foo)')
    with pytest.raises(SassSyntaxError):
        # Or variables
        calc('url(#{$foo}$foo)')
    with pytest.raises(SassSyntaxError):
        # This looks like a URL too
        calc('url(foo#{$foo} foo)')
コード例 #27
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)
コード例 #28
0
ファイル: helpers.py プロジェクト: return42/pyScss
def log_(number, base=None):
    if not isinstance(number, Number):
        raise TypeError("Expected number, got %r" % (number, ))
    elif not number.is_unitless:
        raise ValueError("Expected unitless number, got %r" % (number, ))

    if base is None:
        pass
    elif not isinstance(base, Number):
        raise TypeError("Expected number, got %r" % (base, ))
    elif not base.is_unitless:
        raise ValueError("Expected unitless number, got %r" % (base, ))

    if base is None:
        ret = math.log(number.value)
    else:
        ret = math.log(number.value, base.value)

    return Number(ret)
コード例 #29
0
ファイル: extra.py プロジェクト: incidunt/pyScss
def background_brushed(density=None, intensity=None, color=None, opacity=None, size=None, monochrome=False, direction=(), spread=(), background=None, inline=False):
    if not Image:
        raise Exception("Images manipulation require PIL")

    density = [Number(v).value for v in List.from_maybe(density)]
    intensity = [Number(v).value for v in List.from_maybe(intensity)]
    color = [Color(v).value for v in List.from_maybe(color) if v]
    opacity = [Number(v).value for v in List.from_maybe(opacity)]

    size = int(Number(size).value) if size else -1
    if size < 0 or size > 512:
        size = 200

    monochrome = bool(monochrome)

    direction = [Number(v).value for v in List.from_maybe(direction)]
    spread = [Number(v).value for v in List.from_maybe(spread)]

    background = Color(background).value if background else None

    new_image = Image.new(
        mode='RGBA',
        size=(size, size)
    )

    pixdata = new_image.load()
    _image_brushed(pixdata, size, density, intensity, color, opacity, monochrome, direction, spread, background)

    if not inline:
        key = (size, density, intensity, color, opacity, monochrome, direction, spread, background)
        asset_file = 'brushed-%s%sx%s' % ('mono-' if monochrome else '', size, size)
        # asset_file += '-[%s][%s][%s]' % ('-'.join(to_str(s).replace('.', '_') for s in density or []), '-'.join(to_str(s).replace('.', '_') for s in opacity or []), '-'.join(to_str(s).replace('.', '_') for s in direction or []))
        asset_file += '-' + make_filename_hash(key)
        asset_file += '.png'
        asset_path = os.path.join(config.ASSETS_ROOT or os.path.join(config.STATIC_ROOT, 'assets'), asset_file)
        try:
            new_image.save(asset_path)
        except IOError:
            log.exception("Error while saving image")
            inline = True  # Retry inline version
        url = '%s%s' % (config.ASSETS_URL, asset_file)
    if inline:
        output = six.BytesIO()
        new_image.save(output, format='PNG')
        contents = output.getvalue()
        output.close()
        url = make_data_url('image/png', contents)

    inline = 'url("%s")' % escape(url)
    return String.unquoted(inline)
コード例 #30
0
def test_comparison_numeric():
    lo = Number(123)
    hi = Number(456)
    assert lo < hi
    assert lo <= hi
    assert lo <= lo
    assert hi > lo
    assert hi >= lo
    assert hi >= hi
    assert lo == lo
    assert lo != hi

    # Same tests, negated
    assert not lo > hi
    assert not lo >= hi
    assert not hi < lo
    assert not hi <= lo
    assert not lo != lo
    assert not lo == hi

    # Numbers with units should also auto-cast numbers with units
    units = Number(123, "px")
    plain = Number(123)
    assert units == plain
    assert units <= plain
    assert units >= plain
    assert not units != plain
    assert not units < plain
    assert not units > plain

    # Incompatible units have...  rules.
    ems = Number(100, "em")
    pxs = Number(100, "px")

    with pytest.raises(ValueError):
        ems < pxs
    with pytest.raises(ValueError):
        ems > pxs
    with pytest.raises(ValueError):
        ems <= pxs
    with pytest.raises(ValueError):
        ems >= pxs

    assert not ems == pxs
    assert ems != pxs