From abb5607710a2a5cc5415423489fa452965cbef68 Mon Sep 17 00:00:00 2001 From: "E. Madison Bray" Date: Fri, 17 Jan 2020 16:59:59 +0000 Subject: [PATCH] Allow Sage to work with a system Python 3.6. Currently sage-the-distribution is tested against a minimum of Python 3.7, but we can support more system Pythons by supporting down to 3.6 with some minimal fixes to tests. --- build/bin/sage-spkg | 4 +++- build/pkgs/python3/spkg-configure.m4 | 8 ++++---- src/sage/all.py | 2 +- src/sage/combinat/subset.py | 17 ++++++++++++++++- src/sage/graphs/views.pyx | 1 + src/sage/misc/sagedoc.py | 2 +- src/sage/misc/sageinspect.py | 6 ++---- src/sage/symbolic/expression.pyx | 8 ++------ 8 files changed, 30 insertions(+), 18 deletions(-) diff --git a/build/bin/sage-spkg b/build/bin/sage-spkg index 6129555958a..bafc41cbbd5 100755 --- a/build/bin/sage-spkg +++ b/build/bin/sage-spkg @@ -68,7 +68,9 @@ #***************************************************************************** # Avoid surprises with character ranges [a-z] in regular expressions -export LC_ALL=C +# See Trac #15791; some locales can produce different results for +# character ranges (use C.UTF-8 to ensure UTF-8 default encoding in Python) +export LC_ALL=C.UTF-8 usage() { diff --git a/build/pkgs/python3/spkg-configure.m4 b/build/pkgs/python3/spkg-configure.m4 index 6e576be828f..2989803eba9 100644 --- a/build/pkgs/python3/spkg-configure.m4 +++ b/build/pkgs/python3/spkg-configure.m4 @@ -10,14 +10,14 @@ SAGE_SPKG_CONFIGURE([python3], [ dnl Using Python 3 for Sage. Check if we can do venv with a system python3 dnl instead of building our own copy. check_modules="sqlite3, ctypes, math, hashlib, crypt, readline, socket, zlib, distutils.core" - AC_CACHE_CHECK([for python3 >= 3.7.3, < 3.8 with modules $check_modules], [ac_cv_path_PYTHON3], [ + AC_CACHE_CHECK([for python3 >= 3.6, < 3.8 with modules $check_modules], [ac_cv_path_PYTHON3], [ AC_MSG_RESULT([]) - AC_PATH_PROGS_FEATURE_CHECK([PYTHON3], [python3.7 python3], [ + AC_PATH_PROGS_FEATURE_CHECK([PYTHON3], [python3.7 python3.6 python3], [ AC_MSG_CHECKING([... whether $ac_path_PYTHON3 is good]) python3_version=`"$ac_path_PYTHON3" --version 2>&1 \ | $SED -n -e 's/\([[0-9]]*\.[[0-9]]*\.[[0-9]]*\).*/\1/p'` AS_IF([test -n "$python3_version"], [ - AX_COMPARE_VERSION([$python3_version], [ge], [3.7.3], [ + AX_COMPARE_VERSION([$python3_version], [ge], [3.6.0], [ AX_COMPARE_VERSION([$python3_version], [lt], [3.8.0], [ dnl Because the system python is not used directly but rather in a venv without site-packages, dnl we test whether the module will be available in a venv. @@ -118,7 +118,7 @@ EOF ac_path_PYTHON3_found=: AC_MSG_RESULT([yes]) dnl introduction for AC_MSG_RESULT printed by AC_CACHE_CHECK - AC_MSG_CHECKING([for python3 >= 3.7.3, < 3.8 with modules $check_modules]) + AC_MSG_CHECKING([for python3 >= 3.6, < 3.8 with modules $check_modules]) ], [ AC_MSG_RESULT([no, the version is in the supported range, and the modules can be imported, but distutils cannot build a C++ 11 extension]) ]) diff --git a/src/sage/all.py b/src/sage/all.py index 94337b48d5f..4fd711965d6 100644 --- a/src/sage/all.py +++ b/src/sage/all.py @@ -22,7 +22,7 @@ ....: 'IPython', 'prompt_toolkit', 'jedi', # sage dependencies ....: 'threading', 'multiprocessing', # doctest dependencies ....: '__main__', 'sage.doctest', # doctesting - ....: 'signal', 'enum', # may appear in Python 3 + ....: 'signal', 'enum', 'types' # may appear in Python 3 ....: ] sage: def is_not_allowed(frame): ....: module = inspect.getmodule(frame) diff --git a/src/sage/combinat/subset.py b/src/sage/combinat/subset.py index a81e7cffd11..9ef2781d7ea 100644 --- a/src/sage/combinat/subset.py +++ b/src/sage/combinat/subset.py @@ -357,7 +357,22 @@ def cardinality(self): """ return Integer(1) << self._s.cardinality() - __len__ = cardinality + def __len__(self): + r""" + Equivalent to ``self.cardinality()``. + + TESTS:: + + ``__len__`` should return a Python int; in Python 3.7+ this happens + automatically, but not on Python 3.6. + + sage: S = Subsets(Set([1,2,3])) + sage: len(S) + 8 + sage: type(len(S)) is int + True + """ + return int(self.cardinality()) def first(self): """ diff --git a/src/sage/graphs/views.pyx b/src/sage/graphs/views.pyx index b1ac7a27c4a..3c28b0de50e 100644 --- a/src/sage/graphs/views.pyx +++ b/src/sage/graphs/views.pyx @@ -611,6 +611,7 @@ cdef class EdgesView: elif i < 0: return list(self)[i] else: + i = int(i) # For Python < 3.7 where islice doesn't support non-int try: return next(islice(self, i, i + 1, 1)) except StopIteration: diff --git a/src/sage/misc/sagedoc.py b/src/sage/misc/sagedoc.py index 61d7a4c812d..5a3c06d3fd6 100644 --- a/src/sage/misc/sagedoc.py +++ b/src/sage/misc/sagedoc.py @@ -1064,7 +1064,7 @@ def search_src(string, extra1='', extra2='', extra3='', extra4='', sage: print(search_src(" fetch(", "def", interact=False)) # py3 Traceback (most recent call last): ... - re.error: missing ), unterminated subpattern at position 6 + error: missing ), unterminated subpattern at position 6 To fix this, *escape* the parenthesis with a backslash:: diff --git a/src/sage/misc/sageinspect.py b/src/sage/misc/sageinspect.py index 6251ec5742c..46d7cb9100b 100644 --- a/src/sage/misc/sageinspect.py +++ b/src/sage/misc/sageinspect.py @@ -1724,10 +1724,8 @@ def sage_formatargspec(args, varargs=None, varkw=None, defaults=None, sage: defaults = [3] sage: sage_formatargspec(args, defaults=defaults) '(a, b, c=3)' - sage: formatargspec(args, defaults=defaults) == sage_formatargspec(args, defaults=defaults) # py2 - True - sage: formatargspec(args, defaults=defaults) == sage_formatargspec(args, defaults=defaults) # py3 - doctest:...: DeprecationWarning: `formatargspec` is deprecated since Python 3.5. Use `signature` and the `Signature` object directly + sage: import warnings; warnings.simplefilter('ignore') # py3: ignore DeprecationWarning + sage: formatargspec(args, defaults=defaults) == sage_formatargspec(args, defaults=defaults) True """ def formatargandannotation(arg): diff --git a/src/sage/symbolic/expression.pyx b/src/sage/symbolic/expression.pyx index 19da8508d27..b258064fcc8 100644 --- a/src/sage/symbolic/expression.pyx +++ b/src/sage/symbolic/expression.pyx @@ -5869,14 +5869,10 @@ cdef class Expression(CommutativeRingElement): Indexing directly with ``t[1]`` causes problems with numpy types. - sage: t[1] # py2 + sage: t[1] Traceback (most recent call last): ... - TypeError: 'sage.symbolic.expression.Expression' object does not support indexing - sage: t[1] # py3 - Traceback (most recent call last): - ... - TypeError: 'sage.symbolic.expression.Expression' object is not subscriptable + TypeError: 'sage.symbolic.expression.Expression' object ... """ if (is_a_symbol(self._gobj) or is_a_constant(self._gobj) or is_a_numeric(self._gobj)):