From e992427eff7da0f44844cd41d6a3ca2590663bd3 Mon Sep 17 00:00:00 2001
From: Martin <debacle@debian.org>
Date: Mon, 25 Apr 2022 19:59:23 +0000
Subject: [PATCH] New upstream version 1.4.0

---
 conftest.py                             | 10 ++++++++--
 scss/compiler.py                        |  4 ++--
 scss/extension/compass/gradients.py     |  2 +-
 scss/extension/compass/helpers.py       |  2 ++
 scss/namespace.py                       | 13 ++++++++++---
 scss/scss_meta.py                       |  6 +++---
 scss/selector.py                        |  2 +-
 scss/src/_speedups.c                    | 18 ++++++++++--------
 scss/src/hashtable.c                    |  2 +-
 scss/src/scanner.c                      |  7 ++++---
 scss/src/scanner.h                      |  9 ++++++---
 scss/tests/files/compass/gradients.css  |  4 ++++
 scss/tests/files/compass/gradients.scss |  5 +++++
 scss/types.py                           |  5 ++++-
 setup.py                                |  2 +-
 15 files changed, 62 insertions(+), 29 deletions(-)

diff --git a/conftest.py b/conftest.py
index 535bb681..86c213ac 100644
--- a/conftest.py
+++ b/conftest.py
@@ -58,7 +58,10 @@ def pytest_collect_file(path, parent):
         parts = str(path).split(path.sep)
         # -4 tests / -3 files / -2 directory / -1 file.scss
         if parts[-4:-2] == ['tests', 'files']:
-            return SassFile(path, parent)
+            if hasattr(SassFile, "from_parent"):
+                return SassFile.from_parent(parent, fspath=path)
+            else:
+                return SassFile(path, parent)
 
 
 class SassFile(pytest.File):
@@ -67,7 +70,10 @@ class SassFile(pytest.File):
         if not fontforge and parent_name == 'fonts':
             pytest.skip("font tests require fontforge")
 
-        yield SassItem(str(self.fspath), self)
+        if hasattr(SassItem, "from_parent"):
+            yield SassItem.from_parent(parent=self, name=str(self.fspath))
+        else:
+            yield SassItem(str(self.fspath), self)
 
 
 class SassItem(pytest.Item):
diff --git a/scss/compiler.py b/scss/compiler.py
index 7b8dbd16..2fb164bb 100644
--- a/scss/compiler.py
+++ b/scss/compiler.py
@@ -300,8 +300,8 @@ class Compilation(object):
         self.rules = self.apply_extends(self.rules)
 
         output, total_selectors = self.create_css(self.rules)
-        if total_selectors >= 4096:
-            log.error("Maximum number of supported selectors in Internet Explorer (4095) exceeded!")
+        if total_selectors > 65534:
+            log.warning("Maximum number of supported selectors in Internet Explorer (65534) exceeded!")
 
         return output
 
diff --git a/scss/extension/compass/gradients.py b/scss/extension/compass/gradients.py
index 031fba27..15e12001 100644
--- a/scss/extension/compass/gradients.py
+++ b/scss/extension/compass/gradients.py
@@ -59,7 +59,7 @@ def __color_stops(percentages, *args):
     if prev_color:
         stops.append(None)
     stops = stops[:len(colors)]
-    if stops[0] is None:
+    if stops[0] is None or stops[0] == Number(0):
         stops[0] = Number(0, '%')
     if stops[-1] is None:
         stops[-1] = Number(100, '%')
diff --git a/scss/extension/compass/helpers.py b/scss/extension/compass/helpers.py
index e7251b37..50c8d5e6 100644
--- a/scss/extension/compass/helpers.py
+++ b/scss/extension/compass/helpers.py
@@ -220,6 +220,8 @@ def dash_o(*args):
 # ------------------------------------------------------------------------------
 # Selector generation
 
+# selector-append is a Sass function
+@ns.declare_alias('selector-append')
 @ns.declare
 def append_selector(selector, to_append):
     if isinstance(selector, List):
diff --git a/scss/namespace.py b/scss/namespace.py
index 939cde52..dab3aea1 100644
--- a/scss/namespace.py
+++ b/scss/namespace.py
@@ -169,9 +169,16 @@ class Namespace(object):
 
     def _auto_register_function(self, function, name, ignore_args=0):
         name = name.replace('_', '-').rstrip('-')
-        argspec = inspect.getargspec(function)
-
-        if argspec.varargs or argspec.keywords:
+        try:
+            argspec = inspect.getfullargspec(function)
+            varkw = argspec.varkw
+        except AttributeError:
+            # In python 2.7, getfulargspec does not exist.
+            # Let's use getargspec as fallback.
+            argspec = inspect.getargspec(function)
+            varkw = argspec.keywords
+
+        if argspec.varargs or varkw:
             # Accepts some arbitrary number of arguments
             arities = [None]
         else:
diff --git a/scss/scss_meta.py b/scss/scss_meta.py
index 375aeda2..059eb78e 100644
--- a/scss/scss_meta.py
+++ b/scss/scss_meta.py
@@ -3,7 +3,7 @@
 pyScss, a Scss compiler for Python
 
 @author     German M. Bravo (Kronuz) <german.mb@gmail.com>
-@version    1.3.7
+@version    1.4.0
 @see        https://github.com/Kronuz/pyScss
 @copyright  (c) 2012-2013 German M. Bravo (Kronuz)
 @license    MIT License
@@ -46,8 +46,8 @@ from __future__ import unicode_literals
 
 import sys
 
-VERSION_INFO = (1, 3, 7)
-DATE_INFO = (2020, 3, 26)  # YEAR, MONTH, DAY
+VERSION_INFO = (1, 4, 0)
+DATE_INFO = (2022, 2, 23)  # YEAR, MONTH, DAY
 VERSION = '.'.join(str(i) for i in VERSION_INFO)
 REVISION = '%04d%02d%02d' % DATE_INFO
 BUILD_INFO = "pyScss v" + VERSION + " (" + REVISION + ")"
diff --git a/scss/selector.py b/scss/selector.py
index 8a6ecdf5..c187f01c 100644
--- a/scss/selector.py
+++ b/scss/selector.py
@@ -33,7 +33,7 @@ SELECTOR_TOKENIZER = re.compile(r'''
 
     # Square brackets are attribute tests
     # TODO: this doesn't handle ] within a string
-    | [[] .+? []]
+    | \[ .+? \]
 
     # Dot and pound start class/id selectors.  Percent starts a Sass
     # extend-target faux selector.
diff --git a/scss/src/_speedups.c b/scss/src/_speedups.c
index 1244b299..5c4ed930 100644
--- a/scss/src/_speedups.c
+++ b/scss/src/_speedups.c
@@ -8,6 +8,7 @@
 * MIT license (http://www.opensource.org/licenses/mit-license.php)
 * Copyright (c) 2011 German M. Bravo (Kronuz), All rights reserved.
 */
+#define PY_SSIZE_T_CLEAN
 #include <Python.h>
 #include "py3defs.h"
 #include "block_locator.h"
@@ -22,7 +23,7 @@ typedef struct {
 } scss_BlockLocator;
 
 static char*
-scss_pyunicode_to_utf8(PyObject* obj, int* len)
+scss_pyunicode_to_utf8(PyObject* obj, Py_ssize_t* len)
 {
 	char* internal_buffer;
 	char* ret;
@@ -188,7 +189,8 @@ scss_Scanner_token(scss_Scanner *self, PyObject *args)
 	PyObject *py_token;
 
 	char *tok;
-	int token_num, len;
+	int token_num;
+	Py_ssize_t len;
 	PyObject *restrictions = NULL;
 	Hashtable *_restrictions = NULL;
 
@@ -272,7 +274,7 @@ static PyObject *
 scss_Scanner_reset(scss_Scanner *self, PyObject *args, PyObject *kwds)
 {
 	char *input = NULL;
-	int input_sz = 0;
+	Py_ssize_t input_sz = 0;
 
 	if (self->scanner != NULL) {
 		if (PyArg_ParseTuple(args, "|z#", &input, &input_sz)) {
@@ -289,11 +291,11 @@ scss_Scanner_setup_patterns(PyObject *self, PyObject *patterns)
 {
 	PyObject *item, *item0, *item1;
 	int i, is_tuple, _is_tuple;
-	long size;
+	Py_ssize_t size;
 
 	Pattern *_patterns = NULL;
 	int patterns_sz = 0;
-	int len;
+	Py_ssize_t len;
 	if (!Scanner_initialized()) {
 		is_tuple = PyTuple_Check(patterns);
 		if (is_tuple || PyList_Check(patterns)) {
@@ -325,17 +327,17 @@ scss_Scanner_init(scss_Scanner *self, PyObject *args, PyObject *kwds)
 {
 	PyObject *item, *item0, *item1;
 	int i, is_tuple, _is_tuple;
-	long size;
+	Py_ssize_t size;
 
 	PyObject *patterns, *ignore;
 	Pattern *_patterns = NULL;
 	int patterns_sz = 0;
-	int len;
+	Py_ssize_t len;
 	Pattern *_ignore = NULL;
 	int ignore_sz = 0;
 	PyObject *py_input = NULL;
 	char *encoded_input = NULL;
-	int encoded_input_sz = 0;
+	Py_ssize_t encoded_input_sz = 0;
 
 	self->scanner = NULL;
 
diff --git a/scss/src/hashtable.c b/scss/src/hashtable.c
index 70f6cf1a..22e4cc69 100644
--- a/scss/src/hashtable.c
+++ b/scss/src/hashtable.c
@@ -43,7 +43,7 @@ murmurhash3(const void *key, const size_t len, const unsigned int seed) {
 		hash = ((hash << r2) | (hash >> (32 - r2))) * m + n;
 	}
 
-	tail = (const unsigned char *)(key + nblocks * 4);
+	tail = (const unsigned char *)(key) + nblocks * 4;
 
 	switch (len & 3) {
 		case 3:
diff --git a/scss/src/scanner.c b/scss/src/scanner.c
index a65ed373..40e53738 100644
--- a/scss/src/scanner.c
+++ b/scss/src/scanner.c
@@ -8,6 +8,7 @@
 * MIT license (http://www.opensource.org/licenses/mit-license.php)
 * Copyright (c) 2011 German M. Bravo (Kronuz), All rights reserved.
 */
+#define PY_SSIZE_T_CLEAN
 #include <Python.h>
 
 #include <stdio.h>
@@ -50,7 +51,7 @@ Pattern_regex(char *tok, char *expr) {
 }
 
 static int
-Pattern_match(Pattern *regex, char *string, int string_sz, int start_at, Token *p_token) {
+Pattern_match(Pattern *regex, char *string, Py_ssize_t string_sz, int start_at, Token *p_token) {
 	int options = PCRE_ANCHORED | PCRE_UTF8;
 	const char *errptr;
 	int ret, erroffset, ovector[3];
@@ -243,7 +244,7 @@ _Scanner_scan(Scanner *self, Hashtable *restrictions)
 /* Scanner public interface */
 
 void
-Scanner_reset(Scanner *self, char *input, int input_sz) {
+Scanner_reset(Scanner *self, char *input, Py_ssize_t input_sz) {
 	int i;
 
 	#ifdef DEBUG
@@ -290,7 +291,7 @@ Scanner_del(Scanner *self) {
 }
 
 Scanner*
-Scanner_new(Pattern patterns[], int patterns_sz, Pattern ignore[], int ignore_sz, char *input, int input_sz)
+Scanner_new(Pattern patterns[], int patterns_sz, Pattern ignore[], int ignore_sz, char *input, Py_ssize_t input_sz)
 {
 	int i;
 	size_t len;
diff --git a/scss/src/scanner.h b/scss/src/scanner.h
index ae63f5ce..9c60ae7e 100644
--- a/scss/src/scanner.h
+++ b/scss/src/scanner.h
@@ -11,6 +11,9 @@
 #ifndef SCANNER_H
 #define SCANNER_H
 
+#define PY_SSIZE_T_CLEAN
+#include <Python.h>
+
 #include "hashtable.h"
 
 #define PCRE_STATIC
@@ -50,7 +53,7 @@ typedef struct {
 	int tokens_bsz;
 	Token *tokens;
 	Restriction *restrictions;
-	int input_sz;
+	Py_ssize_t input_sz;
 	char *input;
 	int pos;
 } Scanner;
@@ -59,8 +62,8 @@ int Scanner_initialized(void);
 void Scanner_initialize(Pattern *, int);
 void Scanner_finalize(void);
 
-void Scanner_reset(Scanner *self, char *input, int input_sz);
-Scanner *Scanner_new(Pattern *, int, Pattern *, int, char *, int);
+void Scanner_reset(Scanner *self, char *input, Py_ssize_t input_sz);
+Scanner *Scanner_new(Pattern *, int, Pattern *, int, char *, Py_ssize_t);
 void Scanner_del(Scanner *);
 
 Token* Scanner_token(Scanner *, int, Hashtable *restrictions);
diff --git a/scss/tests/files/compass/gradients.css b/scss/tests/files/compass/gradients.css
index f26dc7f6..0dd99ee6 100644
--- a/scss/tests/files/compass/gradients.css
+++ b/scss/tests/files/compass/gradients.css
@@ -82,3 +82,7 @@
 .bg-linear-gradient-to {
   background: linear-gradient(to right, red, green);
 }
+
+.panel {
+  background-image: linear-gradient(to bottom, red, green);
+}
diff --git a/scss/tests/files/compass/gradients.scss b/scss/tests/files/compass/gradients.scss
index 1eba785f..05b2c70f 100644
--- a/scss/tests/files/compass/gradients.scss
+++ b/scss/tests/files/compass/gradients.scss
@@ -93,3 +93,8 @@
 .bg-linear-gradient-to {
   background: linear-gradient(to right, red 0%, green 100%);
 }
+
+// Issue #404
+.panel {
+	background-image: linear-gradient(to bottom, red 0, green 100%);
+}
diff --git a/scss/types.py b/scss/types.py
index c35905a3..acaf72c0 100644
--- a/scss/types.py
+++ b/scss/types.py
@@ -3,7 +3,10 @@ from __future__ import division
 from __future__ import print_function
 from __future__ import unicode_literals
 
-from collections import Iterable
+try:
+    from collections.abc import Iterable
+except ImportError:
+    from collections import Iterable
 import colorsys
 from fractions import Fraction
 import operator
diff --git a/setup.py b/setup.py
index fb5fede8..f159453f 100644
--- a/setup.py
+++ b/setup.py
@@ -17,7 +17,7 @@ with open('scss/scss_meta.py', 'rb') as f:
 install_requires = ['six']
 if sys.version_info < (3, 4):
     install_requires.append('enum34')
-    install_requires.append('pathlib')
+    install_requires.append('pathlib2')
 if sys.version_info < (2, 7):
     install_requires.append('ordereddict')
 
-- 
GitLab