diff -Nru python-lesscpy-0.13.0+ds/AUTHORS python-lesscpy-0.15.0+ds/AUTHORS --- python-lesscpy-0.13.0+ds/AUTHORS 1970-01-01 00:00:00.000000000 +0000 +++ python-lesscpy-0.15.0+ds/AUTHORS 2019-10-08 18:40:38.000000000 +0000 @@ -0,0 +1,5 @@ +James Page +Patrick +Sascha Peilicke +Simon de Haan +Jóhann T Maríusson diff -Nru python-lesscpy-0.13.0+ds/debian/changelog python-lesscpy-0.15.0+ds/debian/changelog --- python-lesscpy-0.13.0+ds/debian/changelog 2019-11-12 10:07:24.000000000 +0000 +++ python-lesscpy-0.15.0+ds/debian/changelog 2022-08-10 01:29:18.000000000 +0000 @@ -1,3 +1,12 @@ +python-lesscpy (0.15.0+ds-0.1) unstable; urgency=high + + * Non-maintainer upload. + * New upstream release. + + Fix FTBFS due to collections module. (Closes: #1009425) + * debian/control: Bump Standards-Version to 4.6.1. + + -- Boyuan Yang Tue, 09 Aug 2022 21:29:18 -0400 + python-lesscpy (0.13.0+ds-2) unstable; urgency=medium * Unnecessary postinst and prerm and add preinst for upgrade diff -Nru python-lesscpy-0.13.0+ds/debian/control python-lesscpy-0.15.0+ds/debian/control --- python-lesscpy-0.13.0+ds/debian/control 2019-11-12 10:07:24.000000000 +0000 +++ python-lesscpy-0.15.0+ds/debian/control 2022-08-10 01:28:00.000000000 +0000 @@ -8,7 +8,7 @@ python3-all, python3-ply, python3-setuptools, -Standards-Version: 4.4.1 +Standards-Version: 4.6.1 Vcs-Browser: https://salsa.debian.org/totol-guest/python-lesscpy Vcs-Git: https://salsa.debian.org/totol-guest/python-lesscpy.git Homepage: https://pypi.python.org/pypi/lesscpy diff -Nru python-lesscpy-0.13.0+ds/lesscpy/__init__.py python-lesscpy-0.15.0+ds/lesscpy/__init__.py --- python-lesscpy-0.13.0+ds/lesscpy/__init__.py 2018-02-05 14:46:27.000000000 +0000 +++ python-lesscpy-0.15.0+ds/lesscpy/__init__.py 2021-07-15 06:45:16.000000000 +0000 @@ -1,4 +1,4 @@ -__version_info__ = ('0', '13', '0') +__version_info__ = ('0', '15', '0') __version__ = '.'.join(__version_info__) @@ -18,4 +18,3 @@ p.parse(file=file) f = formatter.Formatter(opt) return f.format(p) - diff -Nru python-lesscpy-0.13.0+ds/lesscpy/lessc/color.py python-lesscpy-0.15.0+ds/lesscpy/lessc/color.py --- python-lesscpy-0.13.0+ds/lesscpy/lessc/color.py 2017-12-28 15:17:44.000000000 +0000 +++ python-lesscpy-0.15.0+ds/lesscpy/lessc/color.py 2020-01-24 14:00:33.000000000 +0000 @@ -12,13 +12,12 @@ import colorsys import re -import six +from six import string_types from . import utility from lesscpy.lib import colors -class Color(): - +class Color: def process(self, expression): """ Process color expression args: @@ -70,10 +69,9 @@ return self._rgbatohex(list(map(int, args))) except ValueError: if all((a for a in args - if a[-1] == '%' - and 100 >= int(a[:-1]) >= 0)): - return self._rgbatohex([int(a[:-1]) * 255 / 100.0 - for a in args]) + if a[-1] == '%' and 100 >= int(a[:-1]) >= 0)): + return self._rgbatohex( + [int(a[:-1]) * 255 / 100.0 for a in args]) raise ValueError('Illegal color values') def rgba(self, *args): @@ -94,15 +92,14 @@ return self._rgbatohex(list(map(int, args))) except ValueError: if all((a for a in args - if a[-1] == '%' - and 100 >= int(a[:-1]) >= 0)): + if a[-1] == '%' and 100 >= int(a[:-1]) >= 0)): alpha = list(args)[3] if alpha[-1] == '%' and float(alpha[:-1]) == 0: - values = self._rgbatohex_raw([int(a[:-1]) * 255 / 100.0 - for a in args]) + values = self._rgbatohex_raw( + [int(a[:-1]) * 255 / 100.0 for a in args]) return "rgba(%s)" % ','.join([str(a) for a in values]) - return self._rgbatohex([int(a[:-1]) * 255 / 100.0 - for a in args]) + return self._rgbatohex( + [int(a[:-1]) * 255 / 100.0 for a in args]) raise ValueError('Illegal color values') def argb(self, *args): @@ -135,16 +132,17 @@ if fval > 1: rgb = [255] + rgb[1:] # Clip invalid integer/float values elif 1 >= fval >= 0: - rgb = [fval * 256] + rgb[1:] # Convert 0-1 to 0-255 range for _rgbatohex + rgb = [ + fval * 256 + ] + rgb[1:] # Convert 0-1 to 0-255 range for _rgbatohex else: rgb = [0] + rgb[1:] # Clip lower bound return self._rgbatohex(list(map(int, rgb))) except ValueError: if all((a for a in rgb - if a[-1] == '%' - and 100 >= int(a[:-1]) >= 0)): - return self._rgbatohex([int(a[:-1]) * 255 / 100.0 - for a in rgb]) + if a[-1] == '%' and 100 >= int(a[:-1]) >= 0)): + return self._rgbatohex( + [int(a[:-1]) * 255 / 100.0 for a in rgb]) raise ValueError('Illegal color values') def hsl(self, *args): @@ -158,7 +156,8 @@ return self.hsla(*args) elif len(args) == 3: h, s, l = args - rgb = colorsys.hls_to_rgb(int(h) / 360.0, utility.pc_or_float(l), utility.pc_or_float(s)) + rgb = colorsys.hls_to_rgb( + int(h) / 360.0, utility.pc_or_float(l), utility.pc_or_float(s)) color = (utility.convergent_round(c * 255) for c in rgb) return self._rgbatohex(color) raise ValueError('Illegal color values') @@ -172,7 +171,8 @@ """ if len(args) == 4: h, s, l, a = args - rgb = colorsys.hls_to_rgb(int(h) / 360.0, utility.pc_or_float(l), utility.pc_or_float(s)) + rgb = colorsys.hls_to_rgb( + int(h) / 360.0, utility.pc_or_float(l), utility.pc_or_float(s)) color = [float(utility.convergent_round(c * 255)) for c in rgb] color.append(utility.pc_or_float(a)) return "rgba(%s,%s,%s,%s)" % tuple(color) @@ -304,7 +304,7 @@ str """ if color and degree: - if isinstance(degree, six.string_types): + if isinstance(degree, string_types): degree = float(degree.strip('%')) h, l, s = self._hextohls(color) h = ((h * 360.0) + degree) % 360.0 @@ -348,14 +348,14 @@ str """ if color1 and color2: - if isinstance(weight, six.string_types): + if isinstance(weight, string_types): weight = float(weight.strip('%')) weight = ((weight / 100.0) * 2) - 1 rgb1 = self._hextorgb(color1) rgb2 = self._hextorgb(color2) alpha = 0 - w1 = (((weight if weight * alpha == -1 - else weight + alpha) / (1 + weight * alpha)) + 1) + w1 = (((weight if weight * alpha == -1 else weight + alpha) / + (1 + weight * alpha)) + 1) w1 = w1 / 2.0 w2 = 1 - w1 rgb = [ @@ -384,17 +384,17 @@ raise ValueError('Cannot format non-color') def _rgbatohex_raw(self, rgba): - values = ["%x" % int(v) for v in - [0xff if h > 0xff else 0 if h < 0 else h for h in rgba]] + values = [ + "%x" % int(v) + for v in [0xff if h > 0xff else 0 if h < 0 else h for h in rgba] + ] return values def _rgbatohex(self, rgba): - return '#%s' % ''.join(["%02x" % int(v) for v in - [0xff - if h > 0xff else - 0 if h < 0 else h - for h in rgba] - ]) + return '#%s' % ''.join([ + "%02x" % int(v) + for v in [0xff if h > 0xff else 0 if h < 0 else h for h in rgba] + ]) def _hextorgb(self, hex): if hex.lower() in colors.lessColors: @@ -417,7 +417,7 @@ return colorsys.rgb_to_hls(*[c / 255.0 for c in rgb]) def _ophsl(self, color, diff, idx, operation): - if isinstance(diff, six.string_types): + if isinstance(diff, string_types): diff = float(diff.strip('%')) hls = list(self._hextohls(color)) hls[idx] = self._clamp(operation(hls[idx], diff / 100.0)) diff -Nru python-lesscpy-0.13.0+ds/lesscpy/lessc/formatter.py python-lesscpy-0.15.0+ds/lesscpy/lessc/formatter.py --- python-lesscpy-0.13.0+ds/lesscpy/lessc/formatter.py 2017-06-06 16:56:43.000000000 +0000 +++ python-lesscpy-0.15.0+ds/lesscpy/lessc/formatter.py 2019-10-08 18:40:38.000000000 +0000 @@ -10,7 +10,6 @@ class Formatter(object): - def __init__(self, args): self.args = args @@ -25,21 +24,9 @@ self.args.minify = True self.items = {} if self.args.minify: - self.items.update({ - 'nl': '', - 'tab': '', - 'ws': '', - 'eb': eb - }) + self.items.update({'nl': '', 'tab': '', 'ws': '', 'eb': eb}) else: tab = '\t' if self.args.tabs else ' ' * int(self.args.spaces) - self.items.update({ - 'nl': '\n', - 'tab': tab, - 'ws': ' ', - 'eb': eb - }) - self.out = [u.fmt(self.items) - for u in parse.result - if u] + self.items.update({'nl': '\n', 'tab': tab, 'ws': ' ', 'eb': eb}) + self.out = [u.fmt(self.items) for u in parse.result if u] return ''.join(self.out).strip() diff -Nru python-lesscpy-0.13.0+ds/lesscpy/lessc/lexer.py python-lesscpy-0.15.0+ds/lesscpy/lessc/lexer.py --- python-lesscpy-0.13.0+ds/lesscpy/lessc/lexer.py 2017-06-06 16:56:43.000000000 +0000 +++ python-lesscpy-0.15.0+ds/lesscpy/lessc/lexer.py 2021-07-15 06:31:53.000000000 +0000 @@ -31,73 +31,21 @@ ) literals = '<>=%!/*-+&' tokens = [ - 'css_ident', - 'css_dom', - 'css_class', - 'css_id', - 'css_property', - 'css_vendor_property', - 'css_comment', - 'css_string', - 'css_color', - 'css_filter', - 'css_number', - 'css_important', - 'css_vendor_hack', - 'css_uri', - 'css_ms_filter', - 'css_keyframe_selector', - - 'css_media_type', - 'css_media_feature', - - 't_and', - 't_not', - 't_only', - - 'less_variable', - 'less_comment', - 'less_open_format', - 'less_when', - 'less_and', - 'less_not', - - 't_ws', - 't_popen', - 't_pclose', - 't_semicolon', - 't_tilde', - 't_colon', - 't_comma', - - 't_eopen', - 't_eclose', - - 't_isopen', - 't_isclose', - - 't_bopen', - 't_bclose' + 'css_ident', 'css_dom', 'css_class', 'css_id', 'css_property', + 'css_vendor_property', 'css_user_property', 'css_comment', + 'css_string', 'css_color', 'css_filter', 'css_number', 'css_important', + 'css_vendor_hack', 'css_uri', 'css_ms_filter', 'css_keyframe_selector', + 'css_media_type', 'css_media_feature', 't_and', 't_not', 't_only', + 'less_variable', 'less_comment', 'less_open_format', 'less_when', + 'less_and', 'less_not', 't_ws', 't_popen', 't_pclose', 't_semicolon', + 't_tilde', 't_colon', 't_comma', 't_eopen', 't_eclose', 't_isopen', + 't_isclose', 't_bopen', 't_bclose' ] tokens += list(set(reserved.tokens.values())) # Tokens with significant following whitespace - significant_ws = set([ - 'css_class', - 'css_id', - 'css_dom', - 'css_property', - 'css_vendor_property', - 'css_ident', - 'css_number', - 'css_color', - 'css_media_type', - 'css_filter', - 'less_variable', - 't_and', - 't_not', - 't_only', - '&', - ]) + significant_ws = {'css_class', 'css_id', 'css_dom', 'css_property', 'css_vendor_property', 'css_user_property', 'css_ident', + 'css_number', 'css_color', 'css_media_type', 'css_filter', 'less_variable', 't_and', 't_not', + 't_only', '&'} significant_ws.update(reserved.tokens.values()) def __init__(self): @@ -139,7 +87,7 @@ return t def t_css_ident(self, t): - (r'([\-\.\#]?' + (r'((\-|\.|\#|\-\-)?' '([_a-z]' '|[\200-\377]' '|\\\[0-9a-f]{1,6}' @@ -176,13 +124,17 @@ t.type = 'less_not' elif v in ('from', 'to'): t.type = 'css_keyframe_selector' - elif v in css.propertys: + elif v in css.properties: t.type = 'css_property' t.lexer.in_property_decl = True - elif (v in dom.elements or v.lower() in dom.elements) and not t.lexer.in_property_decl: + elif (v in dom.elements + or v.lower() in dom.elements) and not t.lexer.in_property_decl: # DOM elements can't be part of property declarations, avoids ambiguity between 'rect' DOM # element and rect() CSS function. t.type = 'css_dom' + elif v.startswith("--"): + t.type = 'css_user_property' + t.lexer.in_property_decl = True elif c == '-': t.type = 'css_vendor_property' t.lexer.in_property_decl = True @@ -447,8 +399,8 @@ # Error handling rule def t_error(self, t): - raise SyntaxError("Illegal character '%s' line %d" % - (t.value[0], t.lexer.lineno)) + raise SyntaxError( + "Illegal character '%s' line %d" % (t.value[0], t.lexer.lineno)) t.lexer.skip(1) # Build the lexer @@ -493,8 +445,8 @@ if not t: return t if t.type == 't_ws' and ( - self.pretok or (self.last - and self.last.type not in self.significant_ws)): + self.pretok or + (self.last and self.last.type not in self.significant_ws)): continue self.pretok = False if t.type == 't_bclose' and self.last and self.last.type not in ['t_bopen', 't_bclose'] and self.last.type != 't_semicolon' \ diff -Nru python-lesscpy-0.13.0+ds/lesscpy/lessc/parser.py python-lesscpy-0.15.0+ds/lesscpy/lessc/parser.py --- python-lesscpy-0.13.0+ds/lesscpy/lessc/parser.py 2017-06-06 16:56:43.000000000 +0000 +++ python-lesscpy-0.15.0+ds/lesscpy/lessc/parser.py 2021-07-15 06:31:53.000000000 +0000 @@ -18,7 +18,7 @@ import tempfile import sys import ply.yacc -import six +from six import string_types from . import lexer from . import utility @@ -27,12 +27,14 @@ from lesscpy.exceptions import CompilationError from lesscpy.plib import Block, Call, Deferred, Expression, Identifier, Mixin, NegatedExpression, Property, Statement, Variable, Import, KeyframeSelector + class ErrorRegister(object): """ Raises CompilationError when an error occurs. """ + def __init__(self): self.errors = [] @@ -45,12 +47,14 @@ close = __close__ + class PrintErrorRegister(object): """ Colored error output to stderr. """ + def __init__(self): self.has_errored = False @@ -80,8 +84,7 @@ outputdir=tempfile.gettempdir(), importlvl=0, verbose=False, - fail_with_exc=False - ): + fail_with_exc=False): """ Parser object Kwargs: @@ -102,19 +105,16 @@ if not tabfile: tabfile = 'yacctab' - self.ignored = ('css_comment', 'less_comment', - 'css_vendor_hack') + self.ignored = ('css_comment', 'less_comment', 'css_vendor_hack') - self.tokens = [t for t in self.lex.tokens - if t not in self.ignored] + self.tokens = [t for t in self.lex.tokens if t not in self.ignored] self.parser = ply.yacc.yacc( module=self, start='tunit', debug=yacc_debug, optimize=yacc_optimize, tabmodule=tabfile, - outputdir=outputdir - ) + outputdir=outputdir) self.scope = scope if scope else Scope() self.stash = {} self.result = None @@ -125,7 +125,6 @@ else: self.register = PrintErrorRegister() - def parse(self, filename=None, file=None, debuglevel=0): """ Parse file. kwargs: @@ -150,8 +149,7 @@ self.target = filename if self.verbose and not self.fail_with_exc: print('Compiling target: %s' % filename, file=sys.stderr) - self.result = self.parser.parse( - file, lexer=self.lex, debug=debuglevel) + self.result = self.parser.parse(file, lexer=self.lex, debug=debuglevel) self.post_parse() self.register.close() @@ -236,7 +234,7 @@ if self.importlvl > 8: raise ImportError( 'Recrusive import level too deep > 8 (circular import ?)') - if isinstance(p[3], six.string_types): + if isinstance(p[3], string_types): ipath = utility.destring(p[3]) elif isinstance(p[3], list): p[3] = Import(p[3], p.lineno(4)).parse(self.scope) @@ -244,7 +242,8 @@ elif isinstance(p[3], Call): # NOTE(saschpe): Always in the form of 'url("...");', so parse it # and retrieve the inner css_string. This whole func is messy. - p[3] = p[3].parse(self.scope) # Store it as string, Statement.fmt expects it. + p[3] = p[3].parse( + self.scope) # Store it as string, Statement.fmt expects it. ipath = utility.destring(p[3][4:-1]) fn, fe = os.path.splitext(ipath) if not fe or fe.lower() == '.less': @@ -254,8 +253,10 @@ ipath += '.less' filename = "%s%s%s" % (cpath, os.sep, ipath) if os.path.exists(filename): - recurse = LessParser(importlvl=self.importlvl + 1, - verbose=self.verbose, scope=self.scope) + recurse = LessParser( + importlvl=self.importlvl + 1, + verbose=self.verbose, + scope=self.scope) recurse.parse(filename=filename, debuglevel=0) p[0] = recurse.result else: @@ -493,6 +494,7 @@ def p_prop_open(self, p): """ prop_open : property t_colon | vendor_property t_colon + | user_property t_colon | word t_colon """ p[0] = (p[1][0], '') @@ -770,6 +772,7 @@ | word | id | css_uri + | css_user_property | '=' | fcall """ @@ -871,7 +874,7 @@ """ variable : less_variable | less_variable t_ws """ -# p[0] = p[1] + # p[0] = p[1] p[0] = tuple(list(p)[1:]) def p_color(self, p): @@ -883,8 +886,8 @@ if len(p) > 2: p[0] = [p[0], p[2]] except ValueError: - self.handle_error( - 'Illegal color value `%s`' % p[1], p.lineno(1), 'W') + self.handle_error('Illegal color value `%s`' % p[1], p.lineno(1), + 'W') p[0] = p[1] def p_number(self, p): @@ -966,6 +969,12 @@ """ p[0] = tuple(list(p)[1:]) + def p_user_property(self, p): + """ user_property : css_user_property + | css_user_property t_ws + """ + p[0] = tuple(list(p)[1:]) + def p_media_type(self, p): """ media_type : css_media_type | css_media_type t_ws @@ -1023,6 +1032,7 @@ 'empty :' pass + # # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # diff -Nru python-lesscpy-0.13.0+ds/lesscpy/lessc/scope.py python-lesscpy-0.15.0+ds/lesscpy/lessc/scope.py --- python-lesscpy-0.13.0+ds/lesscpy/lessc/scope.py 2017-06-06 16:56:43.000000000 +0000 +++ python-lesscpy-0.15.0+ds/lesscpy/lessc/scope.py 2020-01-24 14:00:33.000000000 +0000 @@ -7,13 +7,12 @@ See LICENSE for details. .. moduleauthor:: Johann T. Mariusson """ -import six +from six import string_types from . import utility class Scope(list): - """ Scope class. A stack implementation. """ @@ -53,9 +52,7 @@ Returns: list """ - return [r['__current__'] - for r in self - if r['__current__']] + return [r['__current__'] for r in self if r['__current__']] def add_block(self, block): """Add block element to scope @@ -125,9 +122,7 @@ def _smixins(self, name): """Inner wrapper to search for mixins by name. """ - return (self._mixins[name] - if name in self._mixins - else False) + return self._mixins[name] if name in self._mixins else False def blocks(self, name): """ @@ -195,7 +190,7 @@ var = self.variables('@' + name[2:-1]) if var is False: raise SyntaxError('Unknown escaped variable %s' % name) - if isinstance(var.value[0], six.string_types): + if isinstance(var.value[0], string_types): var.value[0] = utility.destring(var.value[0]) else: var = self.variables(name) diff -Nru python-lesscpy-0.13.0+ds/lesscpy/lessc/utility.py python-lesscpy-0.15.0+ds/lesscpy/lessc/utility.py --- python-lesscpy-0.13.0+ds/lesscpy/lessc/utility.py 2017-06-06 16:56:43.000000000 +0000 +++ python-lesscpy-0.15.0+ds/lesscpy/lessc/utility.py 2020-01-24 14:00:33.000000000 +0000 @@ -10,13 +10,18 @@ from __future__ import print_function -import collections import itertools import math import re import sys from six import string_types +try: + from collections.abc import Iterable +except ImportError: + from collections import Iterable + + def flatten(lst): """Flatten list. Args: @@ -25,7 +30,8 @@ generator """ for elm in lst: - if isinstance(elm, collections.Iterable) and not isinstance(elm, string_types): + if isinstance(elm, Iterable) and not isinstance( + elm, string_types): for sub in flatten(elm): yield sub else: @@ -74,8 +80,8 @@ """ if hasattr(block, 'tokens'): for b in block.tokens[1]: - b = (b if hasattr(b, 'raw') and b.raw() == name - else blocksearch(b, name)) + b = (b if hasattr(b, 'raw') and b.raw() == name else blocksearch( + b, name)) if b: return b return False @@ -89,12 +95,7 @@ returns: list """ - rev = { - '<': '>=', - '>': '=<', - '>=': '<', - '=<': '>' - } + rev = {'<': '>=', '>': '=<', '>=': '<', '=<': '>'} return [rev[l] if l in rev else l for l in lst] @@ -138,16 +139,16 @@ """ n, u = split_unit(var) if not isinstance(var, string_types): - return (var, u) + return var, u if is_color(var): - return (var, 'color') + return var, 'color' if is_int(n): n = int(n) elif is_float(n): n = float(n) else: raise SyntaxError('%s ´%s´' % (err, var)) - return (n, u) + return n, u def with_unit(number, unit=None): @@ -196,10 +197,10 @@ bool """ if isinstance(value, string_types): - return (value.startswith('@') or value.startswith('-@')) + return value.startswith('@') or value.startswith('-@') elif isinstance(value, tuple): value = ''.join(value) - return (value.startswith('@') or value.startswith('-@')) + return value.startswith('@') or value.startswith('-@') return False @@ -278,6 +279,7 @@ return math.ceil(nearest_even) return round(value, ndigits) + def pc_or_float(s): """ Utility function to process strings that contain either percentiles or floats args: @@ -289,6 +291,7 @@ return float(s.strip('%')) / 100.0 return float(s) + def permutations_with_replacement(iterable, r=None): """Return successive r length permutations of elements in the iterable. diff -Nru python-lesscpy-0.13.0+ds/lesscpy/lib/css.py python-lesscpy-0.15.0+ds/lesscpy/lib/css.py --- python-lesscpy-0.13.0+ds/lesscpy/lib/css.py 2017-06-06 16:56:43.000000000 +0000 +++ python-lesscpy-0.15.0+ds/lesscpy/lib/css.py 2020-01-24 14:00:33.000000000 +0000 @@ -334,7 +334,7 @@ 'behavior', 'zoom', ] -propertys = css2 + css3 + svg + vendor_ugly +properties = css2 + css3 + svg + vendor_ugly # CSS-2(.1) media types: http://www.w3.org/TR/CSS2/media.html#media-types # Include media types as defined in HTML4: http://www.w3.org/TR/1999/REC-html401-19991224/types.html#h-6.13 @@ -374,7 +374,6 @@ 'min-aspect-ratio', 'max-aspect-ratio', 'device-aspect-ratio', - 'min-device-aspect-ratio', 'max-device-aspect-ratio', 'color', diff -Nru python-lesscpy-0.13.0+ds/lesscpy/lib/dom.py python-lesscpy-0.15.0+ds/lesscpy/lib/dom.py --- python-lesscpy-0.13.0+ds/lesscpy/lib/dom.py 2017-06-06 16:56:43.000000000 +0000 +++ python-lesscpy-0.15.0+ds/lesscpy/lib/dom.py 2019-10-08 18:40:38.000000000 +0000 @@ -135,7 +135,6 @@ 'track', 'video', 'wbr', - 'only', # TODO/FIXME: What is this?!? ] diff -Nru python-lesscpy-0.13.0+ds/lesscpy/lib/reserved.py python-lesscpy-0.15.0+ds/lesscpy/lib/reserved.py --- python-lesscpy-0.13.0+ds/lesscpy/lib/reserved.py 2017-06-06 16:56:43.000000000 +0000 +++ python-lesscpy-0.15.0+ds/lesscpy/lib/reserved.py 2019-10-08 18:40:38.000000000 +0000 @@ -18,9 +18,7 @@ '@-webkit-keyframes': 'css_keyframes', '@-ms-keyframes': 'css_keyframes', '@-o-keyframes': 'css_keyframes', - '@viewport': 'css_viewport', '@-ms-viewport': 'css_viewport', - '@arguments': 'less_arguments', } diff -Nru python-lesscpy-0.13.0+ds/lesscpy/__main__.py python-lesscpy-0.15.0+ds/lesscpy/__main__.py --- python-lesscpy-0.13.0+ds/lesscpy/__main__.py 2017-12-28 15:18:57.000000000 +0000 +++ python-lesscpy-0.15.0+ds/lesscpy/__main__.py 2019-10-08 18:40:38.000000000 +0000 @@ -2,4 +2,3 @@ if __name__ == '__main__': run() - diff -Nru python-lesscpy-0.13.0+ds/lesscpy/plib/block.py python-lesscpy-0.15.0+ds/lesscpy/plib/block.py --- python-lesscpy-0.13.0+ds/lesscpy/plib/block.py 2017-06-06 16:56:43.000000000 +0000 +++ python-lesscpy-0.15.0+ds/lesscpy/plib/block.py 2021-07-15 06:31:53.000000000 +0000 @@ -13,7 +13,6 @@ class Block(Node): - """ Block node. Represents one parse-block. Can contain property nodes or other block nodes. identifier { @@ -29,7 +28,7 @@ raises: SyntaxError returns: - self + self, or a list of new blocks if media queries need to be rotated """ if not self.parsed: scope.push() @@ -43,89 +42,81 @@ inner = list(utility.flatten([p.parse(scope) for p in inner if p])) self.parsed = [] self.inner = [] - if not hasattr(self, "inner_media_queries"): - self.inner_media_queries = [] + # Because media queries need to be at the root in CSS, we rotate them + # up the parse tree. More specifically, in a situation like this where + # the current node is .foo: + # + # .foo { + # @media print { + # /* ... */ + # } + # .bar { + # /* ... */ + # } + # } + # + # The media query is rotated out after splitting the node, resulting in + # this tree: + # + # @media print { + # .foo { + # /* ... */ + # } + # } + # .foo { + # .bar { + # /* ... */ + # } + # } + # + # New media queries are returned as siblings of self. If .foo is a + # media query itself, conditions are merged. This process is recursive + # so that media queries bubble up and split nodes along the way. + inner_media_queries = [] + sibling_media_queries = [] for p in inner: - if p is not None: - if isinstance(p, Block): - if (len(scope) == 2 and p.tokens[1] is not None): - p_is_mediaquery = p.name.tokens[0] == '@media' - # Inner block @media ... { ... } is a nested media - # query. But double-nested media queries have to be - # removed and marked as well. While parsing ".foo", - # both nested "@media print" and double-nested - # "@media all" will be handled as we have to - # re-arrange the scope and block layout quite a bit: - # - # .foo { - # @media print { - # color: blue; - # @media screen { font-size: 12em; } - # } - # } - # - # Expected result: - # - # @media print { - # .foo { color: blue; } - # } - # @media print and screen { - # .foo { font-size: 12 em; } - # } - append_list = [] - reparse_p = False - for child in p.tokens[1]: - if isinstance(child, Block) and child.name.raw().startswith("@media"): - # Remove child from the nested media query, it will be re-added to - # the parent with 'merged' media query (see above example). - p.tokens[1].remove(child) - if p_is_mediaquery: # Media query inside a & block - # Double-nested media query found. We remove it from 'p' and add - # it to this block with a new 'name'. - reparse_p = True - part_a = p.name.tokens[2:][0][0][0] - part_b = child.name.tokens[2:][0][0] - new_ident_tokens = ['@media', ' ', [part_a, (' ', 'and', ' '), part_b]] - # Parse child again with new @media $BLA {} part - child.tokens[0] = Identifier(new_ident_tokens) - child.parsed = None - child = child.parse(scope) - else: - child.block_name = p.name - append_list.append(child) - if reparse_p: - p.parsed = None - p = p.parse(scope) - if not p_is_mediaquery and not append_list: - self.inner.append(p) - else: - append_list.insert(0, p) # This media query should occur before it's children - for media_query in append_list: - self.inner_media_queries.append(media_query) - # NOTE(saschpe): The code is not recursive but we hope that people - # wont use triple-nested media queries. - else: - self.inner.append(p) - else: - self.parsed.append(p) - if self.inner_media_queries: - # Nested media queries, we have to remove self from scope and - # push all nested @media ... {} blocks. - scope.remove_block(self, index=-2) - for mb in self.inner_media_queries: - # New inner block with current name and media block contents - if hasattr(mb, 'block_name'): - cb_name = mb.block_name - else: - cb_name = self.tokens[0] - cb = Block([cb_name, mb.tokens[1]]).parse(scope) - # Replace inner block contents with new block - new_mb = Block([mb.tokens[0], [cb]]).parse(scope) - self.inner.append(new_mb) - scope.add_block(new_mb) + if not isinstance(p, Block): + self.parsed.append(p) + # TODO: By separating in two lists (inner and inner_media_queries), + # we change the final order of declarations. + elif p.tokens[1] is not None and p.name.tokens[0] == '@media': + inner_media_queries.append(p) + else: + self.inner.append(p) + for mb in inner_media_queries: + # If the current node is also a media query, create a merged media + # query for each inner media query. + if self.name.tokens[0] == '@media': + part_a = self.name.tokens[2:][0][0][0] + part_b = mb.name.tokens[2:][0] + cond = [ + '@media', ' ', [ + part_a, (' ', 'and', ' '), + part_b + ] + ] + # TODO: mb.parsed + mb.inner reorders things again + mb = Block([Identifier(cond), mb.parsed + mb.inner]).parse(scope) + sibling_media_queries += mb + for block in mb: + scope.add_block(block) + # Otherwise, rotate inner media queries out of self. + else: + cbs = Block([self.tokens[0], mb.parsed + mb.inner]).parse(scope) + for cb in cbs: + # Replace inner block contents with new block + new_mb = Block([mb.tokens[0], [cb]]).parse(scope) + sibling_media_queries += new_mb + for block in new_mb: + scope.add_block(block) scope.real.pop() scope.pop() - return self + if self.inner or self.parsed: + return [self] + sibling_media_queries + else: + return sibling_media_queries + else: + return [self] def raw(self, clean=False): """Raw block name @@ -149,17 +140,22 @@ f = "%(identifier)s%(ws)s{%(nl)s%(proplist)s}%(eb)s" out = [] name = self.name.fmt(fills) - if self.parsed and any(p for p in self.parsed if str(type(p)) != ""): + if self.parsed and any( + p for p in self.parsed + if str(type(p)) != ""): fills.update({ - 'identifier': name, - 'proplist': ''.join([p.fmt(fills) for p in self.parsed if p]), + 'identifier': + name, + 'proplist': + ''.join([p.fmt(fills) for p in self.parsed if p]), }) out.append(f % fills) if hasattr(self, 'inner'): if self.name.subparse and len(self.inner) > 0: # @media inner = ''.join([p.fmt(fills) for p in self.inner]) inner = inner.replace(fills['nl'], - fills['nl'] + fills['tab']).rstrip(fills['tab']) + fills['nl'] + fills['tab']).rstrip( + fills['tab']) if not fills['nl']: inner = inner.strip() fills.update({ @@ -177,8 +173,7 @@ """ name, inner = self.tokens if inner: - inner = [u.copy() if u else u - for u in inner] + inner = [u.copy() if u else u for u in inner] if name: name = name.copy() return Block([name, inner], 0) @@ -193,8 +188,7 @@ list (block contents) """ if self.tokens[1]: - tokens = [u.copy() if u else u - for u in self.tokens[1]] + tokens = [u.copy() if u else u for u in self.tokens[1]] out = [p for p in tokens if p] utility.rename(out, scope, Block) return out diff -Nru python-lesscpy-0.13.0+ds/lesscpy/plib/call.py python-lesscpy-0.15.0+ds/lesscpy/plib/call.py --- python-lesscpy-0.13.0+ds/lesscpy/plib/call.py 2017-06-06 16:56:43.000000000 +0000 +++ python-lesscpy-0.15.0+ds/lesscpy/plib/call.py 2020-01-24 14:00:33.000000000 +0000 @@ -13,7 +13,7 @@ from urllib.parse import quote as urlquote except ImportError: from urllib import quote as urlquote -import six +from six import string_types from .node import Node import lesscpy.lessc.utility as utility import lesscpy.lessc.color as Color @@ -21,7 +21,6 @@ class Call(Node): - """Call node. Node represents a function call. All builtin none-color functions are in this node. This node attempts calls on built-ins and lets non-builtins @@ -45,8 +44,10 @@ elif name in ('~', 'e'): name = 'escape' color = Color.Color() - args = [t for t in parsed - if not isinstance(t, six.string_types) or t not in '(),'] + args = [ + t for t in parsed + if not isinstance(t, string_types) or t not in '(),' + ] if hasattr(self, name): try: return getattr(self, name)(*args) @@ -118,7 +119,7 @@ returns: bool """ - return (string in lessColors) + return string in lessColors def isurl(self, string, *args): """Is url @@ -128,15 +129,17 @@ bool """ arg = utility.destring(string) - regex = re.compile(r'^(?:http|ftp)s?://' # http:// or https:// - r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+' - r'(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)|' # domain... - # localhost... - r'localhost|' - r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})' # ...or ip - # optional port - r'(?::\d+)?' - r'(?:/?|[/?]\S+)$', re.IGNORECASE) + regex = re.compile( + r'^(?:http|ftp)s?://' # http:// or https:// + r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+' + r'(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)|' # domain... + # localhost... + r'localhost|' + r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})' # ...or ip + # optional port + r'(?::\d+)?' + r'(?:/?|[/?]\S+)$', + re.IGNORECASE) return regex.match(arg) def isstring(self, string, *args): @@ -156,7 +159,7 @@ returns: bool """ - return (string in ('when', 'and', 'not')) + return string in ('when', 'and', 'not') def increment(self, value, *args): """ Increment function @@ -185,7 +188,7 @@ returns: str """ - if(len(args) <= 1): + if len(args) <= 1: return 0 return sum([int(v) for v in args]) @@ -197,7 +200,8 @@ str """ n, u = utility.analyze_number(value) - return utility.with_unit(int(utility.away_from_zero_round(float(n))), u) + return utility.with_unit( + int(utility.away_from_zero_round(float(n))), u) def ceil(self, value, *args): """ Ceil number diff -Nru python-lesscpy-0.13.0+ds/lesscpy/plib/deferred.py python-lesscpy-0.15.0+ds/lesscpy/plib/deferred.py --- python-lesscpy-0.13.0+ds/lesscpy/plib/deferred.py 2017-06-06 16:56:43.000000000 +0000 +++ python-lesscpy-0.15.0+ds/lesscpy/plib/deferred.py 2019-10-08 18:40:38.000000000 +0000 @@ -11,7 +11,6 @@ class Deferred(Node): - def __init__(self, mixin, args, lineno=0): """This node represents mixin calls. The calls to these mixins are deferred until the second @@ -91,8 +90,8 @@ break if res: - store = [t for t in scope.deferred.parsed[ - -1]] if scope.deferred else False + store = [t for t in scope.deferred.parsed[-1] + ] if scope.deferred else False tmp_res = [] for p in res: if p: @@ -102,7 +101,7 @@ tmp_res.append(p.parse(scope)) res = tmp_res #res = [p.parse(scope, depth=depth+1) for p in res if p] - while(any(t for t in res if isinstance(t, Deferred))): + while (any(t for t in res if isinstance(t, Deferred))): res = [p.parse(scope) for p in res if p] if store: scope.deferred.parsed[-1] = store diff -Nru python-lesscpy-0.13.0+ds/lesscpy/plib/expression.py python-lesscpy-0.15.0+ds/lesscpy/plib/expression.py --- python-lesscpy-0.13.0+ds/lesscpy/plib/expression.py 2017-06-06 16:56:43.000000000 +0000 +++ python-lesscpy-0.15.0+ds/lesscpy/plib/expression.py 2019-10-08 18:40:38.000000000 +0000 @@ -16,7 +16,6 @@ class Expression(Node): - """Expression node. Parses all expression except color expressions (handled in the color class) and unary negation (handled in the NegatedExpression class). @@ -31,19 +30,18 @@ returns: str """ - assert(len(self.tokens) == 3) + assert (len(self.tokens) == 3) expr = self.process(self.tokens, scope) - A, O, B = [e[0] - if isinstance(e, tuple) - else e - for e in expr - if str(e).strip()] + A, O, B = [ + e[0] if isinstance(e, tuple) else e for e in expr + if str(e).strip() + ] try: a, ua = utility.analyze_number(A, 'Illegal element in expression') b, ub = utility.analyze_number(B, 'Illegal element in expression') except SyntaxError: return ' '.join([str(A), str(O), str(B)]) - if(a is False or b is False): + if (a is False or b is False): return ' '.join([str(A), str(O), str(B)]) if ua == 'color' or ub == 'color': return color.Color().process((A, O, B)) diff -Nru python-lesscpy-0.13.0+ds/lesscpy/plib/identifier.py python-lesscpy-0.15.0+ds/lesscpy/plib/identifier.py --- python-lesscpy-0.13.0+ds/lesscpy/plib/identifier.py 2017-06-06 16:56:43.000000000 +0000 +++ python-lesscpy-0.15.0+ds/lesscpy/plib/identifier.py 2019-10-08 18:40:38.000000000 +0000 @@ -14,7 +14,6 @@ class Identifier(Node): - """Identifier node. Represents block identifier. """ @@ -30,14 +29,14 @@ """ names = [] name = [] - self._subp = ( - '@media', '@keyframes', - '@-moz-keyframes', '@-webkit-keyframes', - '@-ms-keyframes' - ) + self._subp = ('@media', '@keyframes', '@-moz-keyframes', + '@-webkit-keyframes', '@-ms-keyframes') if self.tokens and hasattr(self.tokens, 'parse'): - self.tokens = list(utility.flatten([id.split() + [','] - for id in self.tokens.parse(scope).split(',')])) + self.tokens = list( + utility.flatten([ + id.split() + [','] + for id in self.tokens.parse(scope).split(',') + ])) self.tokens.pop() if self.tokens and any(hasattr(t, 'parse') for t in self.tokens): tmp_tokens = [] @@ -73,15 +72,21 @@ # But: '@media print' results in [['@media', ' ', 'print']] # def replace_variables(tokens, scope): - return [scope.swap(t) - if (utility.is_variable(t) and not t in reserved.tokens) - else t - for t in tokens] - parsed = [list(utility.flatten(replace_variables(part, scope))) for part in parsed] - - self.parsed = [[i for i, j in utility.pairwise(part) - if i != ' ' or (j and '?' not in j)] - for part in parsed] + return [ + scope.swap(t) + if (utility.is_variable(t) and not t in reserved.tokens) else t + for t in tokens + ] + + parsed = [ + list(utility.flatten(replace_variables(part, scope))) + for part in parsed + ] + + self.parsed = [[ + i for i, j in utility.pairwise(part) + if i != ' ' or (j and '?' not in j) + ] for part in parsed] return self def root(self, scope, names): @@ -104,7 +109,9 @@ for part in parent.parsed: if part and part[0] not in self._subp: filtered_parts.append(part) - permutations = list(utility.permutations_with_replacement(filtered_parts, ampersand_count)) + permutations = list( + utility.permutations_with_replacement( + filtered_parts, ampersand_count)) for permutation in permutations: parsed = [] for name_part in name: @@ -153,8 +160,7 @@ Identifier object """ tokens = ([t for t in self.tokens] - if isinstance(self.tokens, list) - else self.tokens) + if isinstance(self.tokens, list) else self.tokens) return Identifier(tokens, 0) def fmt(self, fills): @@ -164,7 +170,6 @@ returns: str (CSS) """ - name = ',$$'.join(''.join(p).strip() - for p in self.parsed) + name = ',$$'.join(''.join(p).strip() for p in self.parsed) name = re.sub('\?(.)\?', '%(ws)s\\1%(ws)s', name) % fills return name.replace('$$', fills['nl']).replace(' ', ' ') diff -Nru python-lesscpy-0.13.0+ds/lesscpy/plib/import_.py python-lesscpy-0.15.0+ds/lesscpy/plib/import_.py --- python-lesscpy-0.13.0+ds/lesscpy/plib/import_.py 2017-06-06 16:56:43.000000000 +0000 +++ python-lesscpy-0.15.0+ds/lesscpy/plib/import_.py 2019-10-08 18:40:38.000000000 +0000 @@ -11,7 +11,6 @@ class Import(Node): - """Represents CSS property declaration. """ diff -Nru python-lesscpy-0.13.0+ds/lesscpy/plib/keyframe_selector.py python-lesscpy-0.15.0+ds/lesscpy/plib/keyframe_selector.py --- python-lesscpy-0.13.0+ds/lesscpy/plib/keyframe_selector.py 2017-12-28 15:35:01.000000000 +0000 +++ python-lesscpy-0.15.0+ds/lesscpy/plib/keyframe_selector.py 2019-10-08 18:40:38.000000000 +0000 @@ -27,8 +27,10 @@ returns: self """ - self.keyframe, = [e[0] if isinstance(e, tuple) else e - for e in self.tokens if str(e).strip()] + self.keyframe, = [ + e[0] if isinstance(e, tuple) else e for e in self.tokens + if str(e).strip() + ] self.subparse = False return self diff -Nru python-lesscpy-0.13.0+ds/lesscpy/plib/mixin.py python-lesscpy-0.15.0+ds/lesscpy/plib/mixin.py --- python-lesscpy-0.13.0+ds/lesscpy/plib/mixin.py 2017-06-06 16:56:43.000000000 +0000 +++ python-lesscpy-0.15.0+ds/lesscpy/plib/mixin.py 2019-10-08 18:40:38.000000000 +0000 @@ -18,7 +18,6 @@ class Mixin(Node): - """ Mixin Node. Represents callable mixin types. """ @@ -34,9 +33,10 @@ self.name, args, self.guards = self.tokens[0] self.args = [a for a in utility.flatten(args) if a] self.body = Block([None, self.tokens[1]], 0) - self.vars = list(utility.flatten([list(v.values()) - for v in [s['__variables__'] - for s in scope]])) + self.vars = list( + utility.flatten([ + list(v.values()) for v in [s['__variables__'] for s in scope] + ])) return self def raw(self): @@ -56,15 +56,19 @@ raises: SyntaxError """ - arguments = list(zip(args, [' '] * len(args))) if args and args[0] else None + arguments = list(zip(args, + [' '] * len(args))) if args and args[0] else None zl = itertools.zip_longest if sys.version_info[ 0] == 3 else itertools.izip_longest if self.args: - parsed = [v if hasattr(v, 'parse') else v - for v in copy.copy(self.args)] + parsed = [ + v if hasattr(v, 'parse') else v for v in copy.copy(self.args) + ] args = args if isinstance(args, list) else [args] - vars = [self._parse_arg(var, arg, scope) - for arg, var in zl([a for a in args], parsed)] + vars = [ + self._parse_arg(var, arg, scope) + for arg, var in zl([a for a in args], parsed) + ] for var in vars: if var: var.parse(scope) @@ -125,8 +129,7 @@ for g in self.guards: if isinstance(g, list): res = (g[0].parse(scope) - if len(g) == 1 - else Expression(g).parse(scope)) + if len(g) == 1 else Expression(g).parse(scope)) if cor: if res: return True @@ -147,11 +150,9 @@ """ ret = False if args: - args = [[a.parse(scope) - if isinstance(a, Expression) - else a for a in arg] - if arg else arg - for arg in args] + args = [[ + a.parse(scope) if isinstance(a, Expression) else a for a in arg + ] if arg else arg for arg in args] try: self.parse_args(args, scope) except SyntaxError: diff -Nru python-lesscpy-0.13.0+ds/lesscpy/plib/negated_expression.py python-lesscpy-0.15.0+ds/lesscpy/plib/negated_expression.py --- python-lesscpy-0.13.0+ds/lesscpy/plib/negated_expression.py 2017-06-06 16:56:43.000000000 +0000 +++ python-lesscpy-0.15.0+ds/lesscpy/plib/negated_expression.py 2019-10-08 18:40:38.000000000 +0000 @@ -7,17 +7,16 @@ See LICENSE for details. """ -import six +from six import string_types from .node import Node class NegatedExpression(Node): - """Expressions preceded by unary negation.""" def parse(self, scope): val, = self.process(self.tokens, scope) - if isinstance(val, six.string_types): + if isinstance(val, string_types): return '-' + val return -val diff -Nru python-lesscpy-0.13.0+ds/lesscpy/plib/node.py python-lesscpy-0.15.0+ds/lesscpy/plib/node.py --- python-lesscpy-0.13.0+ds/lesscpy/plib/node.py 2017-06-06 16:56:43.000000000 +0000 +++ python-lesscpy-0.15.0+ds/lesscpy/plib/node.py 2019-10-08 18:40:38.000000000 +0000 @@ -11,7 +11,6 @@ class Node(object): - def __init__(self, tokens, lineno=0): """ Base Node args: @@ -43,12 +42,15 @@ tokens = list(utility.flatten(tokens)) done = True if any(t for t in tokens if hasattr(t, 'parse')): - tokens = [t.parse(scope) - if hasattr(t, 'parse') - else t - for t in tokens] + tokens = [ + t.parse(scope) if hasattr(t, 'parse') else t + for t in tokens + ] done = False - if any(t for t in tokens if (utility.is_variable(t)) or str(type(t)) == ""): + if any( + t for t in tokens + if (utility.is_variable(t)) or str(type(t)) == + ""): tokens = self.replace_variables(tokens, scope) done = False if done: diff -Nru python-lesscpy-0.13.0+ds/lesscpy/plib/property.py python-lesscpy-0.15.0+ds/lesscpy/plib/property.py --- python-lesscpy-0.13.0+ds/lesscpy/plib/property.py 2017-06-06 16:56:43.000000000 +0000 +++ python-lesscpy-0.15.0+ds/lesscpy/plib/property.py 2019-10-08 18:40:38.000000000 +0000 @@ -12,7 +12,6 @@ class Property(Node): - """Represents CSS property declaration. """ @@ -48,14 +47,12 @@ list """ if self.property == 'font': - style = [''.join(u.expression()) - if hasattr(u, 'expression') - else u - for u in style] + style = [ + ''.join(u.expression()) if hasattr(u, 'expression') else u + for u in style + ] else: - style = [(u, ' ') - if hasattr(u, 'expression') - else u + style = [(u, ' ') if hasattr(u, 'expression') else u for u in style] return style @@ -69,14 +66,12 @@ f = "%(tab)s%(property)s:%(ws)s%(style)s%(important)s;%(nl)s" imp = ' !important' if self.important else '' if fills['nl']: - self.parsed = [',%s' % fills['ws'] - if p == ',' - else p - for p in self.parsed] - style = ''.join([p.fmt(fills) - if hasattr(p, 'fmt') - else str(p) - for p in self.parsed]) + self.parsed = [ + ',%s' % fills['ws'] if p == ',' else p for p in self.parsed + ] + style = ''.join([ + p.fmt(fills) if hasattr(p, 'fmt') else str(p) for p in self.parsed + ]) # IE cannot handle no space after url() style = re.sub("(url\([^\)]*\))([^\s,])", "\\1 \\2", style) fills.update({ diff -Nru python-lesscpy-0.13.0+ds/lesscpy/plib/statement.py python-lesscpy-0.15.0+ds/lesscpy/plib/statement.py --- python-lesscpy-0.13.0+ds/lesscpy/plib/statement.py 2017-06-06 16:56:43.000000000 +0000 +++ python-lesscpy-0.15.0+ds/lesscpy/plib/statement.py 2019-10-08 18:40:38.000000000 +0000 @@ -12,7 +12,6 @@ class Statement(Node): - """Represents CSS statement (@import, @charset...) """ diff -Nru python-lesscpy-0.13.0+ds/lesscpy/plib/variable.py python-lesscpy-0.15.0+ds/lesscpy/plib/variable.py --- python-lesscpy-0.13.0+ds/lesscpy/plib/variable.py 2017-06-06 16:56:43.000000000 +0000 +++ python-lesscpy-0.15.0+ds/lesscpy/plib/variable.py 2019-10-08 18:40:38.000000000 +0000 @@ -11,7 +11,6 @@ class Variable(Node): - def parse(self, scope): """ Parse function args: diff -Nru python-lesscpy-0.13.0+ds/lesscpy/scripts/compiler.py python-lesscpy-0.15.0+ds/lesscpy/scripts/compiler.py --- python-lesscpy-0.13.0+ds/lesscpy/scripts/compiler.py 2017-12-28 15:32:23.000000000 +0000 +++ python-lesscpy-0.15.0+ds/lesscpy/scripts/compiler.py 2019-10-08 18:40:38.000000000 +0000 @@ -55,12 +55,13 @@ recompile = True if recompile: print('%s -> %s' % (lf, outf)) - p = parser.LessParser(yacc_debug=(args.debug), - lex_optimize=True, - yacc_optimize=(not args.debug), - scope=scope, - tabfile=yacctab, - verbose=args.verbose) + p = parser.LessParser( + yacc_debug=(args.debug), + lex_optimize=True, + yacc_optimize=(not args.debug), + scope=scope, + tabfile=yacctab, + verbose=args.verbose) p.parse(filename=lf, debuglevel=0) css = f.format(p) if not args.dry_run: @@ -70,54 +71,110 @@ print('skipping %s, not modified' % lf, file=sys.stderr) sys.stdout.flush() if args.recurse: - [ldirectory(os.path.join(inpath, name), os.path.join(outpath, name), args, scope) - for name in os.listdir(inpath) - if os.path.isdir(os.path.join(inpath, name)) and - not name.startswith('.') and not name == outpath] + [ + ldirectory( + os.path.join(inpath, name), os.path.join(outpath, name), args, + scope) for name in os.listdir(inpath) + if os.path.isdir(os.path.join(inpath, name)) + and not name.startswith('.') and not name == outpath + ] def run(): """Run compiler """ - aparse = argparse.ArgumentParser(description='LessCss Compiler', - epilog='<< jtm@robot.is @_o >>') - aparse.add_argument('-v', '--version', action='version', - version=VERSION_STR) - aparse.add_argument('-I', '--include', action="store", type=str, - help="Included less-files (comma separated)") - aparse.add_argument('-V', '--verbose', action="store_true", - default=False, help="Verbose mode") - aparse.add_argument('-C', '--dont_create_dirs', action="store_true", - default=False, help="Creates directories when outputing files (lessc non-compatible)") + aparse = argparse.ArgumentParser( + description='LessCss Compiler', epilog='<< jtm@robot.is @_o >>') + aparse.add_argument( + '-v', '--version', action='version', version=VERSION_STR) + aparse.add_argument( + '-I', + '--include', + action="store", + type=str, + help="Included less-files (comma separated)") + aparse.add_argument( + '-V', + '--verbose', + action="store_true", + default=False, + help="Verbose mode") + aparse.add_argument( + '-C', + '--dont_create_dirs', + action="store_true", + default=False, + help="Creates directories when outputing files (lessc non-compatible)") fgroup = aparse.add_argument_group('Formatting options') - fgroup.add_argument('-x', '--minify', action="store_true", - default=False, help="Minify output") - fgroup.add_argument('-X', '--xminify', action="store_true", - default=False, help="Minify output, no end of block newlines") + fgroup.add_argument( + '-x', + '--minify', + action="store_true", + default=False, + help="Minify output") + fgroup.add_argument( + '-X', + '--xminify', + action="store_true", + default=False, + help="Minify output, no end of block newlines") fgroup.add_argument('-t', '--tabs', help="Use tabs", action="store_true") fgroup.add_argument( - '-s', '--spaces', help="Number of startline spaces (default 2)", default=2) - dgroup = aparse.add_argument_group('Directory options', - 'Compiles all *.less files in directory that ' - 'have a newer timestamp than it\'s css file.') + '-s', + '--spaces', + help="Number of startline spaces (default 2)", + default=2) + dgroup = aparse.add_argument_group( + 'Directory options', 'Compiles all *.less files in directory that ' + 'have a newer timestamp than it\'s css file.') dgroup.add_argument('-o', '--out', action="store", help="Output directory") dgroup.add_argument( - '-r', '--recurse', action="store_true", help="Recursive into subdirectorys") + '-r', + '--recurse', + action="store_true", + help="Recursive into subdirectorys") + dgroup.add_argument( + '-f', + '--force', + action="store_true", + help="Force recompile on all files") + dgroup.add_argument( + '-m', + '--min-ending', + action="store_true", + default=False, + help="Add '.min' into output filename. eg, name.min.css") dgroup.add_argument( - '-f', '--force', action="store_true", help="Force recompile on all files") - dgroup.add_argument('-m', '--min-ending', action="store_true", - default=False, help="Add '.min' into output filename. eg, name.min.css") - dgroup.add_argument('-D', '--dry-run', action="store_true", - default=False, help="Dry run, do not write files") + '-D', + '--dry-run', + action="store_true", + default=False, + help="Dry run, do not write files") group = aparse.add_argument_group('Debugging') - group.add_argument('-g', '--debug', action="store_true", - default=False, help="Debugging information") - group.add_argument('-S', '--scopemap', action="store_true", - default=False, help="Scopemap") - group.add_argument('-L', '--lex-only', action="store_true", - default=False, help="Run lexer on target") - group.add_argument('-N', '--no-css', action="store_true", - default=False, help="No css output") + group.add_argument( + '-g', + '--debug', + action="store_true", + default=False, + help="Debugging information") + group.add_argument( + '-S', + '--scopemap', + action="store_true", + default=False, + help="Scopemap") + group.add_argument( + '-L', + '--lex-only', + action="store_true", + default=False, + help="Run lexer on target") + group.add_argument( + '-N', + '--no-css', + action="store_true", + default=False, + help="No css output") aparse.add_argument('target', help="less file or directory") aparse.add_argument('output', nargs='?', help="output file path") args = aparse.parse_args() @@ -132,7 +189,8 @@ tok = ll.token() if not tok: break - if hasattr(tok, "lexer"): # literals don't have the lexer attribute + if hasattr(tok, + "lexer"): # literals don't have the lexer attribute print(tok, "State:", tok.lexer.lexstate) else: print(tok) @@ -146,11 +204,12 @@ if args.include: for u in args.include.split(','): if os.path.exists(u): - p = parser.LessParser(yacc_debug=(args.debug), - lex_optimize=True, - yacc_optimize=(not args.debug), - tabfile=yacctab, - verbose=args.verbose) + p = parser.LessParser( + yacc_debug=(args.debug), + lex_optimize=True, + yacc_optimize=(not args.debug), + tabfile=yacctab, + verbose=args.verbose) p.parse(filename=u, debuglevel=args.debug) if not scope: scope = p.scope @@ -168,11 +227,12 @@ if args.dry_run: print('Dry run, nothing done.', file=sys.stderr) else: - p = parser.LessParser(yacc_debug=(args.debug), - lex_optimize=True, - yacc_optimize=(not args.debug), - scope=copy.deepcopy(scope), - verbose=args.verbose) + p = parser.LessParser( + yacc_debug=(args.debug), + lex_optimize=True, + yacc_optimize=(not args.debug), + scope=copy.deepcopy(scope), + verbose=args.verbose) p.parse(filename=args.target, debuglevel=args.debug) if args.scopemap: args.no_css = True @@ -180,7 +240,8 @@ if not args.no_css and p: out = f.format(p) if args.output: - if not args.dont_create_dirs and not os.path.exists(os.path.dirname(args.output)): + if not args.dont_create_dirs and not os.path.exists( + os.path.dirname(args.output)): try: os.makedirs(os.path.dirname(args.output)) except OSError as exc: # Guard against race condition diff -Nru python-lesscpy-0.13.0+ds/lesscpy.egg-info/PKG-INFO python-lesscpy-0.15.0+ds/lesscpy.egg-info/PKG-INFO --- python-lesscpy-0.13.0+ds/lesscpy.egg-info/PKG-INFO 2018-02-05 14:47:45.000000000 +0000 +++ python-lesscpy-0.15.0+ds/lesscpy.egg-info/PKG-INFO 2021-07-15 06:55:00.000000000 +0000 @@ -1,181 +1,11 @@ -Metadata-Version: 1.1 +Metadata-Version: 2.1 Name: lesscpy -Version: 0.13.0 +Version: 0.15.0 Summary: Python LESS compiler Home-page: https://github.com/lesscpy/lesscpy Author: Jóhann T Maríusson Author-email: jtm@robot.is License: MIT -Description-Content-Type: UNKNOWN -Description: LESSCPY - ======= - - .. image:: https://travis-ci.org/lesscpy/lesscpy.png?branch=master - :target: https://travis-ci.org/lesscpy/lesscpy - - .. image:: https://coveralls.io/repos/lesscpy/lesscpy/badge.png - :target: https://coveralls.io/r/lesscpy/lesscpy - - .. image:: https://pypip.in/d/lesscpy/badge.png - :target: https://pypi.python.org/pypi/lesscpy - - .. image:: https://pypip.in/v/lesscpy/badge.png - :target: https://pypi.python.org/pypi/lesscpy - - .. image:: https://pypip.in/wheel/lesscpy/badge.png - :target: https://pypi.python.org/pypi/lesscpy - :alt: Wheel Status - - .. image:: https://pypip.in/license/lesscpy/badge.png - :target: https://pypi.python.org/pypi/lesscpy - :alt: License - - Python LESS Compiler. - - A compiler written in Python for the LESS language. For those of us not willing - or able to have node.js installed in our environment. Not all features of LESS - are supported (yet). Some features wil probably never be supported (JavaScript - evaluation). This program uses PLY (Python Lex-Yacc) to tokenize / parse the - input and is considerably slower than the NodeJS compiler. The plan is to - utilize this to build in proper syntax checking and perhaps YUI compressing. - - This is an early version, so you are likely to find bugs. - - For more information on LESS: - http://lesscss.org/ or https://github.com/cloudhead/less.js - - Development files: - https://github.com/lesscpy/lesscpy - - - Supported features - ------------------ - - - Variables - - String interpolation - - Mixins (nested, calls, closures, recursive) - - Guard expressions - - Parametered mixins (class / id) - - @arguments - - Nesting - - Escapes ~/e() - - Expressions - - Keyframe blocks - - Color functions (lighten, darken, saturate, desaturate, spin, hue, mix, - saturation, lightness) - - Other functions (round, increment, decrement, format '%(', ...) - - - Differences from less.js - ------------------------ - - - All colors are auto-formatted to #nnnnnn. eg, #f7e923 - - Does not preserve CSS comments - - - Not supported - ------------- - - - JavaScript evaluation - - - Requirements - ------------ - - - Python 2.6, 2.7, 3.3, 3.4, or 3.5 - - ply (Python Lex-Yacc) (check requirements.txt) - - - Installation - ------------ - - To install lesscpy from the `Python Package Index`_, simply: - - .. code-block:: bash - - $ pip install lesscpy - - To do a local system-wide install: - - .. code-block:: bash - - python setup.py install - - Or simply place the package into your Python path. Or rather use packages - provided by your distribution (openSUSE has them at least). - - - Compiler script Usage - --------------------- - - .. code-block:: text - - usage: lesscpy [-h] [-v] [-I INCLUDE] [-V] [-x] [-X] [-t] [-s SPACES] [-o OUT] - [-r] [-f] [-m] [-D] [-g] [-S] [-L] [-N] - target - - LessCss Compiler - - positional arguments: - target less file or directory - - optional arguments: - -h, --help show this help message and exit - -v, --version show program's version number and exit - -I INCLUDE, --include INCLUDE - Included less-files (comma separated) - -V, --verbose Verbose mode - - Formatting options: - -x, --minify Minify output - -X, --xminify Minify output, no end of block newlines - -t, --tabs Use tabs - -s SPACES, --spaces SPACES - Number of startline spaces (default 2) - - Directory options: - Compiles all \*.less files in directory that have a newer timestamp than - it's css file. - - -o OUT, --out OUT Output directory - -r, --recurse Recursive into subdirectorys - -f, --force Force recompile on all files - -m, --min-ending Add '.min' into output filename. eg, name.min.css - -D, --dry-run Dry run, do not write files - - Debugging: - -g, --debug Debugging information - -S, --scopemap Scopemap - -L, --lex-only Run lexer on target - -N, --no-css No css output - - - Python usage - ------------ - - If you want to use the compiler from within Python, you can do it like this: - - .. code-block:: python - - import lesscpy - from six import StringIO - - print(lesscpy.compile(StringIO(u"a { border-width: 2px * 3; }"), minify=True)) - - The output will be: - - .. code-block:: text - - a{border-width:6px;} - - License - ------- - - See the LICENSE file - - - .. _`Python Package Index`: https://pypi.python.org/pypi/lesscpy - Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Console @@ -185,10 +15,192 @@ Classifier: License :: OSI Approved :: MIT License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 2.6 -Classifier: Programming Language :: Python :: 2.7 -Classifier: Programming Language :: Python :: 3.3 +Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: Topic :: Software Development :: Code Generators Classifier: Topic :: Software Development :: Pre-processors +License-File: LICENSE +License-File: AUTHORS + +LESSCPY +======= + +.. image:: https://travis-ci.org/lesscpy/lesscpy.png?branch=master + :target: https://travis-ci.org/lesscpy/lesscpy + +.. image:: https://coveralls.io/repos/lesscpy/lesscpy/badge.png + :target: https://coveralls.io/r/lesscpy/lesscpy + +.. image:: https://img.shields.io/pypi/dm/lesscpy.svg + :target: https://pypi.python.org/pypi/lesscpy + +.. image:: https://img.shields.io/pypi/v/lesscpy.svg + :target: https://pypi.python.org/pypi/lesscpy + +.. image:: https://img.shields.io/pypi/wheel/lesscpy.svg + :target: https://pypi.python.org/pypi/lesscpy + :alt: Wheel Status + +.. image:: https://img.shields.io/pypi/l/lesscpy.svg + :target: https://pypi.python.org/pypi/lesscpy + :alt: License + +Python LESS Compiler. + +A compiler written in Python for the LESS language. For those of us not willing +or able to have node.js installed in our environment. Not all features of LESS +are supported (yet). Some features wil probably never be supported (JavaScript +evaluation). This program uses PLY (Python Lex-Yacc) to tokenize / parse the +input and is considerably slower than the NodeJS compiler. The plan is to +utilize this to build in proper syntax checking and perhaps YUI compressing. + +This is an early version, so you are likely to find bugs. + +For more information on LESS: + http://lesscss.org/ or https://github.com/cloudhead/less.js + +Development files: + https://github.com/lesscpy/lesscpy + + +Supported features +------------------ + +- Variables +- String interpolation +- Mixins (nested, calls, closures, recursive) +- Guard expressions +- Parametered mixins (class / id) +- @arguments +- Nesting +- Escapes ~/e() +- Expressions +- Keyframe blocks +- Color functions (lighten, darken, saturate, desaturate, spin, hue, mix, + saturation, lightness) +- Other functions (round, increment, decrement, format '%(', ...) + + +Differences from less.js +------------------------ + +- All colors are auto-formatted to #nnnnnn. eg, #f7e923 +- Does not preserve CSS comments + + +Not supported +------------- + +- JavaScript evaluation + + +Requirements +------------ + +- Python 3.4 - 3.9, +- ply (Python Lex-Yacc) (check requirements.txt) +- six + +Installation +------------ + +To install lesscpy from the `Python Package Index`_, simply: + +.. code-block:: bash + + $ pip install lesscpy + +To do a local system-wide install: + +.. code-block:: bash + + python setup.py install + +Or simply place the package into your Python path. Or rather use packages +provided by your distribution (openSUSE has them at least). + + +Compiler script Usage +--------------------- + +.. code-block:: text + + usage: lesscpy [-h] [-v] [-I INCLUDE] [-V] [-C] [-x] [-X] [-t] [-s SPACES] + [-o OUT] [-r] [-f] [-m] [-D] [-g] [-S] [-L] [-N] + target [output] + + LessCss Compiler + + positional arguments: + target less file or directory + output output file path + + optional arguments: + -h, --help show this help message and exit + -v, --version show program's version number and exit + -I INCLUDE, --include INCLUDE + Included less-files (comma separated) + -V, --verbose Verbose mode + -C, --dont_create_dirs + Creates directories when outputing files (lessc non- + compatible) + + Formatting options: + -x, --minify Minify output + -X, --xminify Minify output, no end of block newlines + -t, --tabs Use tabs + -s SPACES, --spaces SPACES + Number of startline spaces (default 2) + + Directory options: + Compiles all *.less files in directory that have a newer timestamp than + it's css file. + + -o OUT, --out OUT Output directory + -r, --recurse Recursive into subdirectorys + -f, --force Force recompile on all files + -m, --min-ending Add '.min' into output filename. eg, name.min.css + -D, --dry-run Dry run, do not write files + + Debugging: + -g, --debug Debugging information + -S, --scopemap Scopemap + -L, --lex-only Run lexer on target + -N, --no-css No css output + + << jtm@robot.is @_o >> + +Python usage +------------ + +If you want to use the compiler from within Python, you can do it like this: + +.. code-block:: python + + import lesscpy + from six import StringIO + + print(lesscpy.compile(StringIO(u"a { border-width: 2px * 3; }"), minify=True)) + +The output will be: + +.. code-block:: text + + a{border-width:6px;} + +License +------- + +See the LICENSE file + + +.. _`Python Package Index`: https://pypi.python.org/pypi/lesscpy + + diff -Nru python-lesscpy-0.13.0+ds/lesscpy.egg-info/SOURCES.txt python-lesscpy-0.15.0+ds/lesscpy.egg-info/SOURCES.txt --- python-lesscpy-0.13.0+ds/lesscpy.egg-info/SOURCES.txt 2018-02-05 14:47:45.000000000 +0000 +++ python-lesscpy-0.15.0+ds/lesscpy.egg-info/SOURCES.txt 2021-07-15 06:55:00.000000000 +0000 @@ -1,3 +1,4 @@ +AUTHORS LICENSE MANIFEST.in README.rst @@ -53,7 +54,6 @@ test/test_color.pyc test/test_expression.py test/test_expression.pyc -test/test_font_awesome.pyc test/test_identifier.py test/test_identifier.pyc test/test_issues.py @@ -68,6 +68,30 @@ test/test_pycompile.pyc test/test_utility.py test/test_utility.pyc +test/__pycache__/__init__.cpython-37.pyc +test/__pycache__/__init__.cpython-39.pyc +test/__pycache__/core.cpython-37.pyc +test/__pycache__/core.cpython-39.pyc +test/__pycache__/test_bootstrap3.cpython-37.pyc +test/__pycache__/test_bootstrap3.cpython-39.pyc +test/__pycache__/test_color.cpython-37.pyc +test/__pycache__/test_color.cpython-39.pyc +test/__pycache__/test_expression.cpython-37.pyc +test/__pycache__/test_expression.cpython-39.pyc +test/__pycache__/test_identifier.cpython-37.pyc +test/__pycache__/test_identifier.cpython-39.pyc +test/__pycache__/test_issues.cpython-37.pyc +test/__pycache__/test_issues.cpython-39.pyc +test/__pycache__/test_less.cpython-37.pyc +test/__pycache__/test_less.cpython-39.pyc +test/__pycache__/test_lexer.cpython-37.pyc +test/__pycache__/test_lexer.cpython-39.pyc +test/__pycache__/test_parser.cpython-37.pyc +test/__pycache__/test_parser.cpython-39.pyc +test/__pycache__/test_pycompile.cpython-37.pyc +test/__pycache__/test_pycompile.cpython-39.pyc +test/__pycache__/test_utility.cpython-37.pyc +test/__pycache__/test_utility.cpython-39.pyc test/bootstrap3/css/bootstrap.css test/bootstrap3/css/bootstrap.min.css test/bootstrap3/css/theme.css @@ -120,6 +144,8 @@ test/css/colors.min.css test/css/comments.css test/css/comments.min.css +test/css/css-variables.css +test/css/css-variables.min.css test/css/elements.css test/css/elements.min.css test/css/escapes.css @@ -138,6 +164,10 @@ test/css/imports.min.css test/css/keyframes.css test/css/keyframes.min.css +test/css/media-nested-2.css +test/css/media-nested-2.min.css +test/css/media-nested.css +test/css/media-nested.min.css test/css/media.css test/css/media.min.css test/css/mixin-args-guards.css @@ -184,11 +214,14 @@ test/css/issues/issue4.css test/css/issues/issue5.css test/css/issues/issue6.css +test/css/issues/issue61.css +test/css/issues/issue65.css test/css/issues/issue67.css test/less/argb.less test/less/calls.less test/less/colors.less test/less/comments.less +test/less/css-variables.less test/less/elements.less test/less/escapes.less test/less/expressions.less @@ -198,6 +231,8 @@ test/less/ie.less test/less/imports.less test/less/keyframes.less +test/less/media-nested-2.less +test/less/media-nested.less test/less/media.less test/less/mixin-args-guards.less test/less/mixin-args-local-calls.less @@ -228,4 +263,6 @@ test/less/issues/issue4.less test/less/issues/issue5.less test/less/issues/issue6.less +test/less/issues/issue61.less +test/less/issues/issue65.less test/less/issues/issue67.less \ No newline at end of file diff -Nru python-lesscpy-0.13.0+ds/PKG-INFO python-lesscpy-0.15.0+ds/PKG-INFO --- python-lesscpy-0.13.0+ds/PKG-INFO 2018-02-05 14:47:45.000000000 +0000 +++ python-lesscpy-0.15.0+ds/PKG-INFO 2021-07-15 06:55:01.007032000 +0000 @@ -1,181 +1,11 @@ -Metadata-Version: 1.1 +Metadata-Version: 2.1 Name: lesscpy -Version: 0.13.0 +Version: 0.15.0 Summary: Python LESS compiler Home-page: https://github.com/lesscpy/lesscpy Author: Jóhann T Maríusson Author-email: jtm@robot.is License: MIT -Description-Content-Type: UNKNOWN -Description: LESSCPY - ======= - - .. image:: https://travis-ci.org/lesscpy/lesscpy.png?branch=master - :target: https://travis-ci.org/lesscpy/lesscpy - - .. image:: https://coveralls.io/repos/lesscpy/lesscpy/badge.png - :target: https://coveralls.io/r/lesscpy/lesscpy - - .. image:: https://pypip.in/d/lesscpy/badge.png - :target: https://pypi.python.org/pypi/lesscpy - - .. image:: https://pypip.in/v/lesscpy/badge.png - :target: https://pypi.python.org/pypi/lesscpy - - .. image:: https://pypip.in/wheel/lesscpy/badge.png - :target: https://pypi.python.org/pypi/lesscpy - :alt: Wheel Status - - .. image:: https://pypip.in/license/lesscpy/badge.png - :target: https://pypi.python.org/pypi/lesscpy - :alt: License - - Python LESS Compiler. - - A compiler written in Python for the LESS language. For those of us not willing - or able to have node.js installed in our environment. Not all features of LESS - are supported (yet). Some features wil probably never be supported (JavaScript - evaluation). This program uses PLY (Python Lex-Yacc) to tokenize / parse the - input and is considerably slower than the NodeJS compiler. The plan is to - utilize this to build in proper syntax checking and perhaps YUI compressing. - - This is an early version, so you are likely to find bugs. - - For more information on LESS: - http://lesscss.org/ or https://github.com/cloudhead/less.js - - Development files: - https://github.com/lesscpy/lesscpy - - - Supported features - ------------------ - - - Variables - - String interpolation - - Mixins (nested, calls, closures, recursive) - - Guard expressions - - Parametered mixins (class / id) - - @arguments - - Nesting - - Escapes ~/e() - - Expressions - - Keyframe blocks - - Color functions (lighten, darken, saturate, desaturate, spin, hue, mix, - saturation, lightness) - - Other functions (round, increment, decrement, format '%(', ...) - - - Differences from less.js - ------------------------ - - - All colors are auto-formatted to #nnnnnn. eg, #f7e923 - - Does not preserve CSS comments - - - Not supported - ------------- - - - JavaScript evaluation - - - Requirements - ------------ - - - Python 2.6, 2.7, 3.3, 3.4, or 3.5 - - ply (Python Lex-Yacc) (check requirements.txt) - - - Installation - ------------ - - To install lesscpy from the `Python Package Index`_, simply: - - .. code-block:: bash - - $ pip install lesscpy - - To do a local system-wide install: - - .. code-block:: bash - - python setup.py install - - Or simply place the package into your Python path. Or rather use packages - provided by your distribution (openSUSE has them at least). - - - Compiler script Usage - --------------------- - - .. code-block:: text - - usage: lesscpy [-h] [-v] [-I INCLUDE] [-V] [-x] [-X] [-t] [-s SPACES] [-o OUT] - [-r] [-f] [-m] [-D] [-g] [-S] [-L] [-N] - target - - LessCss Compiler - - positional arguments: - target less file or directory - - optional arguments: - -h, --help show this help message and exit - -v, --version show program's version number and exit - -I INCLUDE, --include INCLUDE - Included less-files (comma separated) - -V, --verbose Verbose mode - - Formatting options: - -x, --minify Minify output - -X, --xminify Minify output, no end of block newlines - -t, --tabs Use tabs - -s SPACES, --spaces SPACES - Number of startline spaces (default 2) - - Directory options: - Compiles all \*.less files in directory that have a newer timestamp than - it's css file. - - -o OUT, --out OUT Output directory - -r, --recurse Recursive into subdirectorys - -f, --force Force recompile on all files - -m, --min-ending Add '.min' into output filename. eg, name.min.css - -D, --dry-run Dry run, do not write files - - Debugging: - -g, --debug Debugging information - -S, --scopemap Scopemap - -L, --lex-only Run lexer on target - -N, --no-css No css output - - - Python usage - ------------ - - If you want to use the compiler from within Python, you can do it like this: - - .. code-block:: python - - import lesscpy - from six import StringIO - - print(lesscpy.compile(StringIO(u"a { border-width: 2px * 3; }"), minify=True)) - - The output will be: - - .. code-block:: text - - a{border-width:6px;} - - License - ------- - - See the LICENSE file - - - .. _`Python Package Index`: https://pypi.python.org/pypi/lesscpy - Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Console @@ -185,10 +15,192 @@ Classifier: License :: OSI Approved :: MIT License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 2.6 -Classifier: Programming Language :: Python :: 2.7 -Classifier: Programming Language :: Python :: 3.3 +Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: Topic :: Software Development :: Code Generators Classifier: Topic :: Software Development :: Pre-processors +License-File: LICENSE +License-File: AUTHORS + +LESSCPY +======= + +.. image:: https://travis-ci.org/lesscpy/lesscpy.png?branch=master + :target: https://travis-ci.org/lesscpy/lesscpy + +.. image:: https://coveralls.io/repos/lesscpy/lesscpy/badge.png + :target: https://coveralls.io/r/lesscpy/lesscpy + +.. image:: https://img.shields.io/pypi/dm/lesscpy.svg + :target: https://pypi.python.org/pypi/lesscpy + +.. image:: https://img.shields.io/pypi/v/lesscpy.svg + :target: https://pypi.python.org/pypi/lesscpy + +.. image:: https://img.shields.io/pypi/wheel/lesscpy.svg + :target: https://pypi.python.org/pypi/lesscpy + :alt: Wheel Status + +.. image:: https://img.shields.io/pypi/l/lesscpy.svg + :target: https://pypi.python.org/pypi/lesscpy + :alt: License + +Python LESS Compiler. + +A compiler written in Python for the LESS language. For those of us not willing +or able to have node.js installed in our environment. Not all features of LESS +are supported (yet). Some features wil probably never be supported (JavaScript +evaluation). This program uses PLY (Python Lex-Yacc) to tokenize / parse the +input and is considerably slower than the NodeJS compiler. The plan is to +utilize this to build in proper syntax checking and perhaps YUI compressing. + +This is an early version, so you are likely to find bugs. + +For more information on LESS: + http://lesscss.org/ or https://github.com/cloudhead/less.js + +Development files: + https://github.com/lesscpy/lesscpy + + +Supported features +------------------ + +- Variables +- String interpolation +- Mixins (nested, calls, closures, recursive) +- Guard expressions +- Parametered mixins (class / id) +- @arguments +- Nesting +- Escapes ~/e() +- Expressions +- Keyframe blocks +- Color functions (lighten, darken, saturate, desaturate, spin, hue, mix, + saturation, lightness) +- Other functions (round, increment, decrement, format '%(', ...) + + +Differences from less.js +------------------------ + +- All colors are auto-formatted to #nnnnnn. eg, #f7e923 +- Does not preserve CSS comments + + +Not supported +------------- + +- JavaScript evaluation + + +Requirements +------------ + +- Python 3.4 - 3.9, +- ply (Python Lex-Yacc) (check requirements.txt) +- six + +Installation +------------ + +To install lesscpy from the `Python Package Index`_, simply: + +.. code-block:: bash + + $ pip install lesscpy + +To do a local system-wide install: + +.. code-block:: bash + + python setup.py install + +Or simply place the package into your Python path. Or rather use packages +provided by your distribution (openSUSE has them at least). + + +Compiler script Usage +--------------------- + +.. code-block:: text + + usage: lesscpy [-h] [-v] [-I INCLUDE] [-V] [-C] [-x] [-X] [-t] [-s SPACES] + [-o OUT] [-r] [-f] [-m] [-D] [-g] [-S] [-L] [-N] + target [output] + + LessCss Compiler + + positional arguments: + target less file or directory + output output file path + + optional arguments: + -h, --help show this help message and exit + -v, --version show program's version number and exit + -I INCLUDE, --include INCLUDE + Included less-files (comma separated) + -V, --verbose Verbose mode + -C, --dont_create_dirs + Creates directories when outputing files (lessc non- + compatible) + + Formatting options: + -x, --minify Minify output + -X, --xminify Minify output, no end of block newlines + -t, --tabs Use tabs + -s SPACES, --spaces SPACES + Number of startline spaces (default 2) + + Directory options: + Compiles all *.less files in directory that have a newer timestamp than + it's css file. + + -o OUT, --out OUT Output directory + -r, --recurse Recursive into subdirectorys + -f, --force Force recompile on all files + -m, --min-ending Add '.min' into output filename. eg, name.min.css + -D, --dry-run Dry run, do not write files + + Debugging: + -g, --debug Debugging information + -S, --scopemap Scopemap + -L, --lex-only Run lexer on target + -N, --no-css No css output + + << jtm@robot.is @_o >> + +Python usage +------------ + +If you want to use the compiler from within Python, you can do it like this: + +.. code-block:: python + + import lesscpy + from six import StringIO + + print(lesscpy.compile(StringIO(u"a { border-width: 2px * 3; }"), minify=True)) + +The output will be: + +.. code-block:: text + + a{border-width:6px;} + +License +------- + +See the LICENSE file + + +.. _`Python Package Index`: https://pypi.python.org/pypi/lesscpy + + diff -Nru python-lesscpy-0.13.0+ds/README.rst python-lesscpy-0.15.0+ds/README.rst --- python-lesscpy-0.13.0+ds/README.rst 2017-12-28 15:17:44.000000000 +0000 +++ python-lesscpy-0.15.0+ds/README.rst 2021-07-15 06:36:54.000000000 +0000 @@ -7,17 +7,17 @@ .. image:: https://coveralls.io/repos/lesscpy/lesscpy/badge.png :target: https://coveralls.io/r/lesscpy/lesscpy -.. image:: https://pypip.in/d/lesscpy/badge.png +.. image:: https://img.shields.io/pypi/dm/lesscpy.svg :target: https://pypi.python.org/pypi/lesscpy -.. image:: https://pypip.in/v/lesscpy/badge.png +.. image:: https://img.shields.io/pypi/v/lesscpy.svg :target: https://pypi.python.org/pypi/lesscpy -.. image:: https://pypip.in/wheel/lesscpy/badge.png +.. image:: https://img.shields.io/pypi/wheel/lesscpy.svg :target: https://pypi.python.org/pypi/lesscpy :alt: Wheel Status -.. image:: https://pypip.in/license/lesscpy/badge.png +.. image:: https://img.shields.io/pypi/l/lesscpy.svg :target: https://pypi.python.org/pypi/lesscpy :alt: License @@ -73,9 +73,9 @@ Requirements ------------ -- Python 2.6, 2.7, 3.3, 3.4, or 3.5 +- Python 3.4 - 3.9, - ply (Python Lex-Yacc) (check requirements.txt) - +- six Installation ------------ @@ -101,14 +101,15 @@ .. code-block:: text - usage: lesscpy [-h] [-v] [-I INCLUDE] [-V] [-x] [-X] [-t] [-s SPACES] [-o OUT] - [-r] [-f] [-m] [-D] [-g] [-S] [-L] [-N] - target + usage: lesscpy [-h] [-v] [-I INCLUDE] [-V] [-C] [-x] [-X] [-t] [-s SPACES] + [-o OUT] [-r] [-f] [-m] [-D] [-g] [-S] [-L] [-N] + target [output] LessCss Compiler positional arguments: target less file or directory + output output file path optional arguments: -h, --help show this help message and exit @@ -116,6 +117,9 @@ -I INCLUDE, --include INCLUDE Included less-files (comma separated) -V, --verbose Verbose mode + -C, --dont_create_dirs + Creates directories when outputing files (lessc non- + compatible) Formatting options: -x, --minify Minify output @@ -125,7 +129,7 @@ Number of startline spaces (default 2) Directory options: - Compiles all \*.less files in directory that have a newer timestamp than + Compiles all *.less files in directory that have a newer timestamp than it's css file. -o OUT, --out OUT Output directory @@ -140,6 +144,7 @@ -L, --lex-only Run lexer on target -N, --no-css No css output + << jtm@robot.is @_o >> Python usage ------------ diff -Nru python-lesscpy-0.13.0+ds/setup.py python-lesscpy-0.15.0+ds/setup.py --- python-lesscpy-0.13.0+ds/setup.py 2017-12-28 15:17:44.000000000 +0000 +++ python-lesscpy-0.15.0+ds/setup.py 2021-07-15 06:41:17.000000000 +0000 @@ -8,12 +8,13 @@ import lesscpy - with codecs.open('README.rst', encoding='utf-8') as f: long_description = f.read() with open("requirements.txt", "r") as f: - install_requires = [str(req) for req in pkg_resources.parse_requirements(f)] + install_requires = [ + str(req) for req in pkg_resources.parse_requirements(f) + ] with open("test-requirements.txt", "r") as f: test_requires = [] for line in f.readlines(): @@ -32,10 +33,8 @@ url='https://github.com/lesscpy/lesscpy', packages=find_packages(exclude=['*test*']), package_data={'': ['LICENSE']}, - entry_points = { - 'console_scripts' : [ - 'lesscpy = lesscpy.scripts.compiler:run' - ] + entry_points={ + 'console_scripts': ['lesscpy = lesscpy.scripts.compiler:run'] }, install_requires=install_requires, tests_require=test_requires, @@ -49,11 +48,15 @@ 'License :: OSI Approved :: MIT License', 'Operating System :: OS Independent', 'Programming Language :: Python', - 'Programming Language :: Python :: 2.6', - 'Programming Language :: Python :: 2.7', - 'Programming Language :: Python :: 3.3', + 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', + 'Programming Language :: Python :: Implementation :: CPython', + 'Programming Language :: Python :: Implementation :: PyPy', 'Topic :: Software Development :: Code Generators', 'Topic :: Software Development :: Pre-processors', ], diff -Nru python-lesscpy-0.13.0+ds/test/core.py python-lesscpy-0.15.0+ds/test/core.py --- python-lesscpy-0.13.0+ds/test/core.py 2017-06-06 16:56:43.000000000 +0000 +++ python-lesscpy-0.15.0+ds/test/core.py 2020-01-24 14:00:33.000000000 +0000 @@ -15,7 +15,11 @@ self.tabs = True -def find_and_load_cases(cls, less_dir, css_dir, less_files=None, css_minimized=True): +def find_and_load_cases(cls, + less_dir, + css_dir, + less_files=None, + css_minimized=True): _less_path = os.path.join(os.path.dirname(__file__), less_dir) _css_path = os.path.join(os.path.dirname(__file__), css_dir) @@ -24,14 +28,15 @@ else: LESS = glob.glob(os.path.join(_less_path, '*.less')) for less in LESS: - lessf = less.split('.')[0].split('/')[-1] + lessf = less.rpartition('.')[0].split('/')[-1] css = os.path.join(_css_path, lessf + '.css') if css_minimized: mincss = os.path.join(_css_path, lessf + '.min.css') test_method = create_case((less, css, mincss)) else: test_method = create_case((less, css, None)) - test_method.__name__ = 'test_%s' % "_".join(reversed(os.path.basename(less).split('.'))) + test_method.__name__ = 'test_%s' % "_".join( + reversed(os.path.basename(less).split('.'))) setattr(cls, test_method.__name__, test_method) @@ -48,13 +53,13 @@ with open(cssf) as cssf: for line in cssf.readlines(): if i >= pl: - self.fail( - "%s: result has less lines (%d < %d)" % (cssf, i, pl)) + self.fail("%s: result has less lines (%d < %d)" % + (cssf, i, pl)) line = line.rstrip() if not line: continue - self.assertEqual( - line, pout[i], '%s: Line %d' % (cssf, i + 1)) + self.assertEqual(line, pout[i], + '%s: Line %d' % (cssf, i + 1)) i += 1 if pl > i and i: self.fail( @@ -74,14 +79,15 @@ with open(minf) as cssf: for line in cssf.readlines(): if i >= ml: - self.fail( - "%s: result has less lines (%d < %d)" % (minf, i, ml)) - self.assertEqual( - line.rstrip(), mout[i], '%s: Line %d' % (minf, i + 1)) + self.fail("%s: result has less lines (%d < %d)" % + (minf, i, ml)) + self.assertEqual(line.rstrip(), mout[i], + '%s: Line %d' % (minf, i + 1)) i += 1 if ml > i and i: self.fail( "%s: result has more lines (%d > %d)" % (minf, i, ml)) else: self.fail("%s not found..." % minf) + return do_case_expected diff -Nru python-lesscpy-0.13.0+ds/test/css/css-variables.css python-lesscpy-0.15.0+ds/test/css/css-variables.css --- python-lesscpy-0.13.0+ds/test/css/css-variables.css 1970-01-01 00:00:00.000000000 +0000 +++ python-lesscpy-0.15.0+ds/test/css/css-variables.css 2021-07-15 06:31:53.000000000 +0000 @@ -0,0 +1,17 @@ +:root { + --bg: #e0e0e0; +} +p { + --bg: white; +} +* { + background: var(--bg); + color: var(--fg,var(--text-fg,black)); +} +div { + --bg: red; +} +div span { + --bg: purple; + background: var(--bg); +} diff -Nru python-lesscpy-0.13.0+ds/test/css/css-variables.min.css python-lesscpy-0.15.0+ds/test/css/css-variables.min.css --- python-lesscpy-0.13.0+ds/test/css/css-variables.min.css 1970-01-01 00:00:00.000000000 +0000 +++ python-lesscpy-0.15.0+ds/test/css/css-variables.min.css 2021-07-15 06:31:53.000000000 +0000 @@ -0,0 +1,5 @@ +:root{--bg:#e0e0e0;} +p{--bg:white;} +*{background:var(--bg);color:var(--fg,var(--text-fg,black));} +div{--bg:red;} +div span{--bg:purple;background:var(--bg);} diff -Nru python-lesscpy-0.13.0+ds/test/css/issues/issue61.css python-lesscpy-0.15.0+ds/test/css/issues/issue61.css --- python-lesscpy-0.13.0+ds/test/css/issues/issue61.css 1970-01-01 00:00:00.000000000 +0000 +++ python-lesscpy-0.15.0+ds/test/css/issues/issue61.css 2021-07-15 06:31:53.000000000 +0000 @@ -0,0 +1,10 @@ +@media screen and (max-width:460px) { + h1.title { + background: url("image_460.jpg"); + } +} +@media screen and (min-width:461px) { + h1.title { + background: url("image_740.jpg"); + } +} diff -Nru python-lesscpy-0.13.0+ds/test/css/issues/issue65.css python-lesscpy-0.15.0+ds/test/css/issues/issue65.css --- python-lesscpy-0.13.0+ds/test/css/issues/issue65.css 1970-01-01 00:00:00.000000000 +0000 +++ python-lesscpy-0.15.0+ds/test/css/issues/issue65.css 2021-07-15 06:31:53.000000000 +0000 @@ -0,0 +1,10 @@ +@media (max-width:400px) { + body { + color: green; + } +} +@media (max-width:30px) { + body h3 .before { + color: red; + } +} diff -Nru python-lesscpy-0.13.0+ds/test/css/media.css python-lesscpy-0.15.0+ds/test/css/media.css --- python-lesscpy-0.13.0+ds/test/css/media.css 2017-06-06 16:56:43.000000000 +0000 +++ python-lesscpy-0.15.0+ds/test/css/media.css 2021-07-15 06:31:53.000000000 +0000 @@ -53,46 +53,3 @@ @media only screen and (min--moz-device-pixel-ratio:2.5),only screen and (-o-min-device-pixel-ratio:2),only screen and (min-device-pixel-ratio:2),only screen and (min-resolution:192dpi),only screen and (min-resolution:2dppx) { background-size: 10px; } -@media (width:768px) { - .lead { - font-size: 21px; - } -} -@media (width:400px) { - .one { - font-size: 1.2em; - } -} -@media (width:400px) and print and (color) { - .one { - color: blue; - } -} -.two { - width: 100px; -} -@media (width:400px) { - .two { - font-size: 1.2em; - } -} -@media print and (color) { - .two { - color: blue; - } -} -@media print { - .visible { - color: green; - } -} -@media screen { - .visible.visible-sm { - color: green; - } -} -@media (max-width:10px) { - .navbar .form { - margin-bottom: 5px; - } -} diff -Nru python-lesscpy-0.13.0+ds/test/css/media.min.css python-lesscpy-0.15.0+ds/test/css/media.min.css --- python-lesscpy-0.13.0+ds/test/css/media.min.css 2017-06-06 16:56:43.000000000 +0000 +++ python-lesscpy-0.15.0+ds/test/css/media.min.css 2021-07-15 06:31:53.000000000 +0000 @@ -10,12 +10,3 @@ @media (min-width:12px){body{margin:0 auto;}} @media (width:767px){.visible-xs{display:block;}} @media only screen and (min--moz-device-pixel-ratio:2.5),only screen and (-o-min-device-pixel-ratio:2),only screen and (min-device-pixel-ratio:2),only screen and (min-resolution:192dpi),only screen and (min-resolution:2dppx){background-size:10px;} -@media (width:768px){.lead{font-size:21px;}} -@media (width:400px){.one{font-size:1.2em;}} -@media (width:400px) and print and (color){.one{color:blue;}} -.two{width:100px;} -@media (width:400px){.two{font-size:1.2em;}} -@media print and (color){.two{color:blue;}} -@media print{.visible{color:green;}} -@media screen{.visible.visible-sm{color:green;}} -@media (max-width:10px){.navbar .form{margin-bottom:5px;}} diff -Nru python-lesscpy-0.13.0+ds/test/css/media-nested-2.css python-lesscpy-0.15.0+ds/test/css/media-nested-2.css --- python-lesscpy-0.13.0+ds/test/css/media-nested-2.css 1970-01-01 00:00:00.000000000 +0000 +++ python-lesscpy-0.15.0+ds/test/css/media-nested-2.css 2021-07-15 06:31:53.000000000 +0000 @@ -0,0 +1,23 @@ +@media screen { + div span p { + color: auto; + } +} +@media screen and (max-width:100px) and (min-width:50px) and print { + p { + color: auto; + } +} +@media (width:400px) { + .one { + font-size: 1.2em; + } + .one .sub { + background: red; + } +} +@media (width:400px) and print and (color) { + .one { + color: blue; + } +} diff -Nru python-lesscpy-0.13.0+ds/test/css/media-nested-2.min.css python-lesscpy-0.15.0+ds/test/css/media-nested-2.min.css --- python-lesscpy-0.13.0+ds/test/css/media-nested-2.min.css 1970-01-01 00:00:00.000000000 +0000 +++ python-lesscpy-0.15.0+ds/test/css/media-nested-2.min.css 2021-07-15 06:31:53.000000000 +0000 @@ -0,0 +1,5 @@ +@media screen{div span p{color:auto;}} +@media screen and (max-width:100px) and (min-width:50px) and print{p{color:auto;}} +@media (width:400px){.one{font-size:1.2em;} +.one .sub{background:red;}} +@media (width:400px) and print and (color){.one{color:blue;}} diff -Nru python-lesscpy-0.13.0+ds/test/css/media-nested.css python-lesscpy-0.15.0+ds/test/css/media-nested.css --- python-lesscpy-0.13.0+ds/test/css/media-nested.css 1970-01-01 00:00:00.000000000 +0000 +++ python-lesscpy-0.15.0+ds/test/css/media-nested.css 2021-07-15 06:31:53.000000000 +0000 @@ -0,0 +1,43 @@ +@media (width:768px) { + .lead { + font-size: 21px; + } +} +@media (width:400px) { + .one { + font-size: 1.2em; + } +} +@media (width:400px) and print and (color) { + .one { + color: blue; + } +} +.two { + width: 100px; +} +@media (width:400px) { + .two { + font-size: 1.2em; + } +} +@media print and (color) { + .two { + color: blue; + } +} +@media print { + .visible { + color: green; + } +} +@media screen { + .visible.visible-sm { + color: green; + } +} +@media (max-width:10px) { + .navbar .form { + margin-bottom: 5px; + } +} diff -Nru python-lesscpy-0.13.0+ds/test/css/media-nested.min.css python-lesscpy-0.15.0+ds/test/css/media-nested.min.css --- python-lesscpy-0.13.0+ds/test/css/media-nested.min.css 1970-01-01 00:00:00.000000000 +0000 +++ python-lesscpy-0.15.0+ds/test/css/media-nested.min.css 2021-07-15 06:31:53.000000000 +0000 @@ -0,0 +1,9 @@ +@media (width:768px){.lead{font-size:21px;}} +@media (width:400px){.one{font-size:1.2em;}} +@media (width:400px) and print and (color){.one{color:blue;}} +.two{width:100px;} +@media (width:400px){.two{font-size:1.2em;}} +@media print and (color){.two{color:blue;}} +@media print{.visible{color:green;}} +@media screen{.visible.visible-sm{color:green;}} +@media (max-width:10px){.navbar .form{margin-bottom:5px;}} diff -Nru python-lesscpy-0.13.0+ds/test/__init__.py python-lesscpy-0.15.0+ds/test/__init__.py --- python-lesscpy-0.13.0+ds/test/__init__.py 2017-06-06 16:56:43.000000000 +0000 +++ python-lesscpy-0.15.0+ds/test/__init__.py 2019-10-08 18:40:38.000000000 +0000 @@ -6,7 +6,6 @@ import sys import unittest - here = os.path.dirname(__file__) path = os.path.abspath(here) while os.path.dirname(path) != path: diff -Nru python-lesscpy-0.13.0+ds/test/less/css-variables.less python-lesscpy-0.15.0+ds/test/less/css-variables.less --- python-lesscpy-0.13.0+ds/test/less/css-variables.less 1970-01-01 00:00:00.000000000 +0000 +++ python-lesscpy-0.15.0+ds/test/less/css-variables.less 2021-07-15 06:31:53.000000000 +0000 @@ -0,0 +1,21 @@ +:root { + --bg: #e0e0e0; +} + +p { + --bg: white; +} + +* { + background: var(--bg); + color: var(--fg, var(--text-fg, black)); +} + +div { + --bg: red; + + span { + --bg: purple; + background: var(--bg); + } +} diff -Nru python-lesscpy-0.13.0+ds/test/less/issues/issue61.less python-lesscpy-0.15.0+ds/test/less/issues/issue61.less --- python-lesscpy-0.13.0+ds/test/less/issues/issue61.less 1970-01-01 00:00:00.000000000 +0000 +++ python-lesscpy-0.15.0+ds/test/less/issues/issue61.less 2021-07-15 06:31:53.000000000 +0000 @@ -0,0 +1,10 @@ +h1 { + &.title { + @media screen and (max-width: 460px) { + background: url("image_460.jpg"); + } + @media screen and (min-width: 461px) { + background: url("image_740.jpg"); + } + } +} diff -Nru python-lesscpy-0.13.0+ds/test/less/issues/issue65.less python-lesscpy-0.15.0+ds/test/less/issues/issue65.less --- python-lesscpy-0.13.0+ds/test/less/issues/issue65.less 1970-01-01 00:00:00.000000000 +0000 +++ python-lesscpy-0.15.0+ds/test/less/issues/issue65.less 2021-07-15 06:31:53.000000000 +0000 @@ -0,0 +1,12 @@ +body { + @media (max-width: 400px) { + color:green; + } + h3 { + .before { + @media (max-width: 30px) { + color: red; + } + } + } +} diff -Nru python-lesscpy-0.13.0+ds/test/less/media.less python-lesscpy-0.15.0+ds/test/less/media.less --- python-lesscpy-0.13.0+ds/test/less/media.less 2017-06-06 16:56:43.000000000 +0000 +++ python-lesscpy-0.15.0+ds/test/less/media.less 2021-07-15 06:31:53.000000000 +0000 @@ -70,45 +70,3 @@ only screen and ( min-resolution: 2dppx) { background-size: 10px; } -/* - Nested media queries -*/ -.lead { - @media (width: 768px) { - font-size: 21px; - } -} -.one { - @media (width: 400px){ - font-size: 1.2em; - @media print and (color) { - color: blue; - } - } -} -.two { - @media (width: 400px){ - font-size: 1.2em; - } - @media print and (color) { - color: blue; - } - width: 100px; -} -.visible { - @media print { - color: green; - } - &.visible-sm { - @media screen { - color: green; - } - } -} -.navbar { - .form { - @media (max-width: 10px) { - margin-bottom: 5px; - } - } -} diff -Nru python-lesscpy-0.13.0+ds/test/less/media-nested-2.less python-lesscpy-0.15.0+ds/test/less/media-nested-2.less --- python-lesscpy-0.13.0+ds/test/less/media-nested-2.less 1970-01-01 00:00:00.000000000 +0000 +++ python-lesscpy-0.15.0+ds/test/less/media-nested-2.less 2021-07-15 06:31:53.000000000 +0000 @@ -0,0 +1,35 @@ +/* Media queries nested deep in the tree */ +div { + span { + p { + @media screen { + color: auto; + } + } + } +} +/* Streak of media queries to be merged */ +@media screen { + @media (max-width: 100px) { + @media (min-width: 50px) { + @media print { + p { + color: auto; + } + } + } + } +} +/* Interaction of media queries with properties, smaller blocks, and other + media queries at once */ +.one { + @media (width: 400px){ + font-size: 1.2em; + .sub { + background: red; + } + @media print and (color) { + color: blue; + } + } +} diff -Nru python-lesscpy-0.13.0+ds/test/less/media-nested.less python-lesscpy-0.15.0+ds/test/less/media-nested.less --- python-lesscpy-0.13.0+ds/test/less/media-nested.less 1970-01-01 00:00:00.000000000 +0000 +++ python-lesscpy-0.15.0+ds/test/less/media-nested.less 2021-07-15 06:31:53.000000000 +0000 @@ -0,0 +1,42 @@ +/* + Nested media queries +*/ +.lead { + @media (width: 768px) { + font-size: 21px; + } +} +.one { + @media (width: 400px){ + font-size: 1.2em; + @media print and (color) { + color: blue; + } + } +} +.two { + @media (width: 400px){ + font-size: 1.2em; + } + @media print and (color) { + color: blue; + } + width: 100px; +} +.visible { + @media print { + color: green; + } + &.visible-sm { + @media screen { + color: green; + } + } +} +.navbar { + .form { + @media (max-width: 10px) { + margin-bottom: 5px; + } + } +} diff -Nru python-lesscpy-0.13.0+ds/test/test_bootstrap3.py python-lesscpy-0.15.0+ds/test/test_bootstrap3.py --- python-lesscpy-0.13.0+ds/test/test_bootstrap3.py 2017-06-06 16:56:43.000000000 +0000 +++ python-lesscpy-0.15.0+ds/test/test_bootstrap3.py 2019-10-08 18:40:38.000000000 +0000 @@ -15,12 +15,14 @@ pass -find_and_load_cases(Bootstrap3TestCase, - less_dir='bootstrap3/less', - less_files=['bootstrap'], - css_dir='bootstrap3/css') +find_and_load_cases( + Bootstrap3TestCase, + less_dir='bootstrap3/less', + less_files=['bootstrap'], + css_dir='bootstrap3/css') -find_and_load_cases(Bootstrap3ThemeTestCase, - less_dir='bootstrap3/less', - less_files=['theme'], - css_dir='bootstrap3/css') +find_and_load_cases( + Bootstrap3ThemeTestCase, + less_dir='bootstrap3/less', + less_files=['theme'], + css_dir='bootstrap3/css') diff -Nru python-lesscpy-0.13.0+ds/test/test_color.py python-lesscpy-0.15.0+ds/test/test_color.py --- python-lesscpy-0.13.0+ds/test/test_color.py 2017-06-06 16:56:43.000000000 +0000 +++ python-lesscpy-0.15.0+ds/test/test_color.py 2019-10-08 18:40:38.000000000 +0000 @@ -133,7 +133,6 @@ ('#29332f', '40%', '#174533'), ('#29332f', '60%', '#0d4f35'), ('#29332f', '100%', '#005c37'), - ]: self.assertEqual(test(c, p), v, v) @@ -156,7 +155,6 @@ ('#29332f', '40%', '#2e2e2e'), ('#29332f', '60%', '#2e2e2e'), ('#29332f', '100%', '#2e2e2e'), - ]: self.assertEqual(test(c, p), v, v) @@ -179,6 +177,5 @@ ('#29332f', '40%', '#293033'), ('#29332f', '60%', '#292d33'), ('#29332f', '100%', '#2c2933'), - ]: self.assertEqual(test(c, p), v, v) diff -Nru python-lesscpy-0.13.0+ds/test/test_expression.py python-lesscpy-0.15.0+ds/test/test_expression.py --- python-lesscpy-0.13.0+ds/test/test_expression.py 2017-06-06 16:56:43.000000000 +0000 +++ python-lesscpy-0.15.0+ds/test/test_expression.py 2019-10-08 18:40:38.000000000 +0000 @@ -14,8 +14,8 @@ ['2.0', '+', '2', '4'], ['2', '+', '2.0', '4'], ['2.0', '+', '2.0', '4'], - [('2.0',), '+', '2.0', '4'], - [('2.0',), '+', ('2.0',), '4'], + [('2.0', ), '+', '2.0', '4'], + [('2.0', ), '+', ('2.0', ), '4'], ['0px', '+', '0', '0'], ['2px', '+', '2', '4px'], ['2.0px', '+', '2', '4px'], diff -Nru python-lesscpy-0.13.0+ds/test/test_identifier.py python-lesscpy-0.15.0+ds/test/test_identifier.py --- python-lesscpy-0.13.0+ds/test/test_identifier.py 2017-06-06 16:56:43.000000000 +0000 +++ python-lesscpy-0.15.0+ds/test/test_identifier.py 2019-10-08 18:40:38.000000000 +0000 @@ -5,7 +5,6 @@ class TestIdentifier(unittest.TestCase): - def test_basic(self): fl = {'ws': ' ', 'nl': '\n'} for i in [ @@ -77,21 +76,23 @@ sc.push() sc.current = Identifier(['.c', ',', '.d'], 0).parse(sc) id = Identifier(['.deep'], 0) - self.assertEqual(id.parse(sc).fmt(fl), '.a .next .c .deep,\n' - '.b .next .c .deep,\n' - '.a .next .d .deep,\n' - '.b .next .d .deep') - self.assertEqual(id.raw(), '.a% %.next% %.c% %.deep%' - '.b% %.next% %.c% %.deep%' - '.a% %.next% %.d% %.deep%' - '.b% %.next% %.d% %.deep') + self.assertEqual( + id.parse(sc).fmt(fl), '.a .next .c .deep,\n' + '.b .next .c .deep,\n' + '.a .next .d .deep,\n' + '.b .next .d .deep') + self.assertEqual( + id.raw(), '.a% %.next% %.c% %.deep%' + '.b% %.next% %.c% %.deep%' + '.a% %.next% %.d% %.deep%' + '.b% %.next% %.d% %.deep') def test_media(self): fl = {'ws': ' ', 'nl': '\n'} sc = Scope() sc.push() - sc.current = Identifier( - ['@media', ' ', 'screen', ',', 'projection'], 0).parse(sc) + sc.current = Identifier(['@media', ' ', 'screen', ',', 'projection'], + 0).parse(sc) self.assertEqual(sc.current.fmt(fl), '@media screen,projection') for i in [ (['html'], 'html'), diff -Nru python-lesscpy-0.13.0+ds/test/test_issues.py python-lesscpy-0.15.0+ds/test/test_issues.py --- python-lesscpy-0.13.0+ds/test/test_issues.py 2017-06-06 16:56:43.000000000 +0000 +++ python-lesscpy-0.15.0+ds/test/test_issues.py 2019-10-08 18:40:38.000000000 +0000 @@ -10,7 +10,8 @@ pass -find_and_load_cases(IssuesTestCase, - less_dir='less/issues', - css_dir='css/issues', - css_minimized=False) +find_and_load_cases( + IssuesTestCase, + less_dir='less/issues', + css_dir='css/issues', + css_minimized=False) diff -Nru python-lesscpy-0.13.0+ds/test/test_less.py python-lesscpy-0.15.0+ds/test/test_less.py --- python-lesscpy-0.13.0+ds/test/test_less.py 2017-06-06 16:56:43.000000000 +0000 +++ python-lesscpy-0.15.0+ds/test/test_less.py 2019-10-08 18:40:38.000000000 +0000 @@ -10,6 +10,4 @@ pass -find_and_load_cases(LessTestCase, - less_dir='less', - css_dir='css') +find_and_load_cases(LessTestCase, less_dir='less', css_dir='css') diff -Nru python-lesscpy-0.13.0+ds/test/test_pycompile.py python-lesscpy-0.15.0+ds/test/test_pycompile.py --- python-lesscpy-0.13.0+ds/test/test_pycompile.py 2017-12-28 15:30:36.000000000 +0000 +++ python-lesscpy-0.15.0+ds/test/test_pycompile.py 2019-10-08 18:40:38.000000000 +0000 @@ -42,4 +42,5 @@ def fail_func(): compile(StringIO("a }"), minify=True) + self.assertRaises(CompilationError, fail_func) diff -Nru python-lesscpy-0.13.0+ds/test/test_utility.py python-lesscpy-0.15.0+ds/test/test_utility.py --- python-lesscpy-0.13.0+ds/test/test_utility.py 2017-06-06 16:56:43.000000000 +0000 +++ python-lesscpy-0.15.0+ds/test/test_utility.py 2019-10-08 18:40:38.000000000 +0000 @@ -88,7 +88,7 @@ self.assertEqual('0.6px', test(.6, 'px')) self.assertEqual('1', test(1)) self.assertEqual('1', test(1, None)) - self.assertEqual('1', test(1,)) + self.assertEqual('1', test(1, )) def test_convergent_round(self): test = utility.convergent_round diff -Nru python-lesscpy-0.13.0+ds/tox.ini python-lesscpy-0.15.0+ds/tox.ini --- python-lesscpy-0.13.0+ds/tox.ini 2017-12-28 15:36:34.000000000 +0000 +++ python-lesscpy-0.15.0+ds/tox.ini 2021-07-15 06:41:16.000000000 +0000 @@ -1,5 +1,6 @@ [tox] -envlist = py27,py33,p36 +envlist = py36,py37,py38,py39,pypy,pypy3 +skip_missing_interpreters = True [testenv] deps = -r{toxinidir}/test-requirements.txt