From 326f36e8c21ce9bb07c119d00904c6cdc7103c76 Mon Sep 17 00:00:00 2001 From: Yutao Yuan Date: Mon, 7 Aug 2023 23:47:47 +0800 Subject: [PATCH 01/93] fix PY_NEW signature --- src/sage/ext/stdsage.pxd | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/ext/stdsage.pxd b/src/sage/ext/stdsage.pxd index 15abe13b7cd..e2bf7434f35 100644 --- a/src/sage/ext/stdsage.pxd +++ b/src/sage/ext/stdsage.pxd @@ -10,7 +10,7 @@ Standard C helper code for Cython modules # http://www.gnu.org/licenses/ #***************************************************************************** -from cpython.object cimport Py_TYPE, PyTypeObject +from cpython.object cimport Py_TYPE, PyTypeObject, PyObject cdef inline PY_NEW(type t): @@ -19,7 +19,7 @@ cdef inline PY_NEW(type t): :class:`Integer` where we change ``tp_new`` at runtime (Cython optimizations assume that ``tp_new`` doesn't change). """ - return (t).tp_new(t, NULL, NULL) + return (t).tp_new(t, NULL, NULL) cdef inline void PY_SET_TP_NEW(type dst, type src): From cba7b31edda2c2512001af01b0005a483bbab90e Mon Sep 17 00:00:00 2001 From: Yutao Yuan Date: Sun, 20 Aug 2023 04:49:57 +0800 Subject: [PATCH 02/93] update doctests for cython 3 --- src/doc/en/thematic_tutorials/coercion_and_categories.rst | 2 +- src/sage/arith/srange.pyx | 2 +- src/sage/combinat/sloane_functions.py | 2 +- src/sage/misc/cachefunc.pyx | 7 ++++--- src/sage/misc/lazy_import.pyx | 2 +- src/sage/misc/lazy_list.pyx | 2 +- src/sage/misc/sageinspect.py | 4 ++-- src/sage/modules/free_module_element.pyx | 2 +- src/sage/rings/finite_rings/finite_field_base.pyx | 2 +- src/sage/rings/polynomial/skew_polynomial_finite_field.pyx | 6 +++--- src/sage/structure/coerce_dict.pyx | 4 ++-- src/sage/tests/cmdline.py | 3 +-- 12 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/doc/en/thematic_tutorials/coercion_and_categories.rst b/src/doc/en/thematic_tutorials/coercion_and_categories.rst index de2349a9a3f..bb23331c151 100644 --- a/src/doc/en/thematic_tutorials/coercion_and_categories.rst +++ b/src/doc/en/thematic_tutorials/coercion_and_categories.rst @@ -105,7 +105,7 @@ it makes sense to build on top of the base class This base class provides a lot more methods than a general parent:: sage: [p for p in dir(Field) if p not in dir(Parent)] - ['__fraction_field', + ['_CommutativeRing__fraction_field', '__iter__', '__len__', '__rxor__', diff --git a/src/sage/arith/srange.pyx b/src/sage/arith/srange.pyx index 156e548a11a..132cf93d085 100644 --- a/src/sage/arith/srange.pyx +++ b/src/sage/arith/srange.pyx @@ -84,7 +84,7 @@ def xsrange(start, end=None, step=1, universe=None, *, coerce=True, bint include EXAMPLES:: sage: xsrange(10) - + <...generator object at 0x...> sage: for i in xsrange(1,5): ....: print(i) 1 diff --git a/src/sage/combinat/sloane_functions.py b/src/sage/combinat/sloane_functions.py index c3cf9299093..e5c99b71fe7 100644 --- a/src/sage/combinat/sloane_functions.py +++ b/src/sage/combinat/sloane_functions.py @@ -9169,7 +9169,7 @@ def __getattribute__(self, name): :: sage: sloane.__repr__ - + sage: sloane.__name__ Traceback (most recent call last): ... diff --git a/src/sage/misc/cachefunc.pyx b/src/sage/misc/cachefunc.pyx index 8aa30a85272..2b1d38c12b9 100644 --- a/src/sage/misc/cachefunc.pyx +++ b/src/sage/misc/cachefunc.pyx @@ -50,7 +50,7 @@ be used:: sage: cython('''cpdef test_funct(x): return -x''') sage: wrapped_funct = cached_function(test_funct, name='wrapped_funct') sage: wrapped_funct - Cached version of + Cached version of sage: wrapped_funct.__name__ 'wrapped_funct' sage: wrapped_funct(5) @@ -82,9 +82,9 @@ approach is still needed for cpdef methods:: sage: cython(os.linesep.join(cython_code)) sage: O = MyClass() sage: O.direct_method - Cached version of + Cached version of sage: O.wrapped_method - Cached version of + Cached version of sage: O.wrapped_method.__name__ 'wrapped_method' sage: O.wrapped_method(5) @@ -270,6 +270,7 @@ Introspection works:: "some doc for a wrapped cython method" return -x sage: print(sage_getsource(O.direct_method)) + @cached_method def direct_method(self, x): "Some doc for direct method" return 2*x diff --git a/src/sage/misc/lazy_import.pyx b/src/sage/misc/lazy_import.pyx index c33a1e74efd..7fc73407ace 100644 --- a/src/sage/misc/lazy_import.pyx +++ b/src/sage/misc/lazy_import.pyx @@ -1095,7 +1095,7 @@ def lazy_import(module, names, as_=None, *, sage: lazy_import('ppl', 'equation', ....: feature=PythonModule('ppl', spkg='pplpy', type='standard')) sage: equation # needs pplpy - + sage: lazy_import('PyNormaliz', 'NmzListConeProperties', feature=PythonModule('PyNormaliz', spkg='pynormaliz')) # optional - pynormaliz sage: NmzListConeProperties # optional - pynormaliz diff --git a/src/sage/misc/lazy_list.pyx b/src/sage/misc/lazy_list.pyx index ba62c446b69..cd750933860 100644 --- a/src/sage/misc/lazy_list.pyx +++ b/src/sage/misc/lazy_list.pyx @@ -678,7 +678,7 @@ cdef class lazy_list_generic(): sage: from itertools import count sage: from sage.misc.lazy_list import lazy_list sage: iter(lazy_list(count())) - + <...generator object at 0x...> :: diff --git a/src/sage/misc/sageinspect.py b/src/sage/misc/sageinspect.py index ce5e9987027..df8e6bf89ac 100644 --- a/src/sage/misc/sageinspect.py +++ b/src/sage/misc/sageinspect.py @@ -76,8 +76,8 @@ sage: sage_getdoc(sage.rings.rational.make_rational).lstrip() 'Make a rational number ...' - sage: sage_getsource(sage.rings.rational.make_rational)[4:] - 'make_rational(s):...' + sage: sage_getsource(sage.rings.rational.make_rational) + '@cython.binding(True)\ndef make_rational(s):...' Python functions:: diff --git a/src/sage/modules/free_module_element.pyx b/src/sage/modules/free_module_element.pyx index d5e8256b68c..c9af9bcbdf7 100644 --- a/src/sage/modules/free_module_element.pyx +++ b/src/sage/modules/free_module_element.pyx @@ -1634,7 +1634,7 @@ cdef class FreeModuleElement(Vector): # abstract base class sage: v = vector([1,2/3,pi]) # needs sage.symbolic sage: v.items() # needs sage.symbolic - + <...generator object at ...> sage: list(v.items()) # needs sage.symbolic [(0, 1), (1, 2/3), (2, pi)] diff --git a/src/sage/rings/finite_rings/finite_field_base.pyx b/src/sage/rings/finite_rings/finite_field_base.pyx index 7e2eed91153..3a6db8995c6 100644 --- a/src/sage/rings/finite_rings/finite_field_base.pyx +++ b/src/sage/rings/finite_rings/finite_field_base.pyx @@ -328,7 +328,7 @@ cdef class FiniteField(Field): sage: p = next_prime(2^64) sage: k. = FiniteField(p^2, impl="pari") sage: it = iter(k); it - + <...generator object at ...> sage: [next(it) for i in range(10)] [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] diff --git a/src/sage/rings/polynomial/skew_polynomial_finite_field.pyx b/src/sage/rings/polynomial/skew_polynomial_finite_field.pyx index 41951687939..c6b67cba5fb 100644 --- a/src/sage/rings/polynomial/skew_polynomial_finite_field.pyx +++ b/src/sage/rings/polynomial/skew_polynomial_finite_field.pyx @@ -629,7 +629,7 @@ cdef class SkewPolynomial_finite_field_dense(SkewPolynomial_finite_order_dense): sage: S. = k['x',Frob] sage: a = x^4 + 2*t*x^3 + 3*t^2*x^2 + (t^2 + t + 1)*x + 4*t + 3 sage: iter = a.right_irreducible_divisors(); iter - + <...generator object at 0x...> sage: next(iter) # random x + 2*t^2 + 4*t + 4 sage: next(iter) # random @@ -664,7 +664,7 @@ cdef class SkewPolynomial_finite_field_dense(SkewPolynomial_finite_order_dense): sage: S. = k['x',Frob] sage: a = x^4 + 2*t*x^3 + 3*t^2*x^2 + (t^2 + t + 1)*x + 4*t + 3 sage: iter = a.left_irreducible_divisors(); iter - + <...generator object at 0x...> sage: next(iter) # random x + 3*t + 3 sage: next(iter) # random @@ -1052,7 +1052,7 @@ cdef class SkewPolynomial_finite_field_dense(SkewPolynomial_finite_order_dense): sage: S. = k['x',Frob] sage: a = x^3 + (t^2 + 1)*x^2 + (2*t + 3)*x + t^2 + t + 2 sage: iter = a.factorizations(); iter - + <...generator object at 0x...> sage: next(iter) # random (x + 3*t^2 + 4*t) * (x + 2*t^2) * (x + 4*t^2 + 4*t + 2) sage: next(iter) # random diff --git a/src/sage/structure/coerce_dict.pyx b/src/sage/structure/coerce_dict.pyx index a2e8443084c..ef86c6af35c 100644 --- a/src/sage/structure/coerce_dict.pyx +++ b/src/sage/structure/coerce_dict.pyx @@ -777,7 +777,7 @@ cdef class MonoDict: sage: L[1] = None sage: L[2] = True sage: L.items() - + <...generator object at ...> sage: sorted(L.items()) [(1, None), (2, True)] """ @@ -1452,7 +1452,7 @@ cdef class TripleDict: sage: L = TripleDict() sage: L[1,2,3] = None sage: L.items() - + <...generator object at ...> sage: list(L.items()) [((1, 2, 3), None)] """ diff --git a/src/sage/tests/cmdline.py b/src/sage/tests/cmdline.py index ad0c44aa274..f14cd2db768 100644 --- a/src/sage/tests/cmdline.py +++ b/src/sage/tests/cmdline.py @@ -491,9 +491,8 @@ def test_executable(args, input="", timeout=100.0, pydebug_ignore_warnings=False sage: (out, err, ret) = test_executable(["sage", "--cython"]) sage: print(err) - Cython (http://cython.org) is a compiler for code written in the - Cython language. Cython is based on Pyrex by Greg Ewing. ... + cython: error: cython: Need at least one source file sage: def has_tty(): ....: try: From 703ec1b0e24037dcceba2a5c044c6ea3b1b4596c Mon Sep 17 00:00:00 2001 From: Yutao Yuan Date: Tue, 8 Aug 2023 00:21:52 +0800 Subject: [PATCH 03/93] update cython to 3.0.2 --- build/pkgs/cython/checksums.ini | 6 +- build/pkgs/cython/install-requires.txt | 2 +- build/pkgs/cython/package-version.txt | 2 +- ...directive-to-enable-the-Python-trash.patch | 355 ------------------ .../cython/patches/0001-rebased-PR2946.patch | 193 ---------- 5 files changed, 5 insertions(+), 553 deletions(-) delete mode 100644 build/pkgs/cython/patches/0001-cython.trashcan-directive-to-enable-the-Python-trash.patch delete mode 100644 build/pkgs/cython/patches/0001-rebased-PR2946.patch diff --git a/build/pkgs/cython/checksums.ini b/build/pkgs/cython/checksums.ini index 175914867ed..5d0bc66c242 100644 --- a/build/pkgs/cython/checksums.ini +++ b/build/pkgs/cython/checksums.ini @@ -1,5 +1,5 @@ tarball=Cython-VERSION.tar.gz -sha1=762987c737acfe7532cb3da38b450fb6e0cf1d7b -md5=a4d0f9fbc9c137f1a88937cd40e8c5ee -cksum=2260471737 +sha1=08eb99f7c95b7ca667b1547575e7369d8064b4b3 +md5=00def3f2b96c393098e01eb2f1f169ad +cksum=2321746451 upstream_url=https://pypi.io/packages/source/C/Cython/Cython-VERSION.tar.gz diff --git a/build/pkgs/cython/install-requires.txt b/build/pkgs/cython/install-requires.txt index b8a968fa247..3693d637891 100644 --- a/build/pkgs/cython/install-requires.txt +++ b/build/pkgs/cython/install-requires.txt @@ -1 +1 @@ -cython >=0.29.21, <1.0 +cython >=3.0, <4.0 diff --git a/build/pkgs/cython/package-version.txt b/build/pkgs/cython/package-version.txt index 5232b0aaea8..b5021469305 100644 --- a/build/pkgs/cython/package-version.txt +++ b/build/pkgs/cython/package-version.txt @@ -1 +1 @@ -0.29.36 +3.0.2 diff --git a/build/pkgs/cython/patches/0001-cython.trashcan-directive-to-enable-the-Python-trash.patch b/build/pkgs/cython/patches/0001-cython.trashcan-directive-to-enable-the-Python-trash.patch deleted file mode 100644 index 0cd3f35df32..00000000000 --- a/build/pkgs/cython/patches/0001-cython.trashcan-directive-to-enable-the-Python-trash.patch +++ /dev/null @@ -1,355 +0,0 @@ -See https://github.com/cython/cython/pull/2842 - -and https://github.com/cython/cython/pull/4475 - -commit c47c4ef735c4b7f1863b21bbe6f112b06c4aad05 -Author: Jeroen Demeyer -Date: Thu Feb 14 10:02:41 2019 +0100 - - @cython.trashcan directive to enable the Python trashcan for deallocations - -diff --git a/Cython/Compiler/ModuleNode.py b/Cython/Compiler/ModuleNode.py -index 56845330d..3a3e8a956 100644 ---- a/Cython/Compiler/ModuleNode.py -+++ b/Cython/Compiler/ModuleNode.py -@@ -1443,6 +1443,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): - - is_final_type = scope.parent_type.is_final_type - needs_gc = scope.needs_gc() -+ needs_trashcan = scope.needs_trashcan() - - weakref_slot = scope.lookup_here("__weakref__") if not scope.is_closure_class_scope else None - if weakref_slot not in scope.var_entries: -@@ -1481,6 +1482,11 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): - # running this destructor. - code.putln("PyObject_GC_UnTrack(o);") - -+ if needs_trashcan: -+ code.globalstate.use_utility_code( -+ UtilityCode.load_cached("PyTrashcan", "ExtensionTypes.c")) -+ code.putln("__Pyx_TRASHCAN_BEGIN(o, %s)" % slot_func_cname) -+ - # call the user's __dealloc__ - self.generate_usr_dealloc_call(scope, code) - -@@ -1554,6 +1560,10 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): - code.putln("(*Py_TYPE(o)->tp_free)(o);") - if freelist_size: - code.putln("}") -+ -+ if needs_trashcan: -+ code.putln("__Pyx_TRASHCAN_END") -+ - code.putln( - "}") - -diff --git a/Cython/Compiler/Options.py b/Cython/Compiler/Options.py -index d03119fca..539629926 100644 ---- a/Cython/Compiler/Options.py -+++ b/Cython/Compiler/Options.py -@@ -319,7 +319,8 @@ directive_types = { - 'freelist': int, - 'c_string_type': one_of('bytes', 'bytearray', 'str', 'unicode'), - 'c_string_encoding': normalise_encoding_name, -- 'cpow': bool -+ 'cpow': bool, -+ 'trashcan': bool, - } - - for key, val in _directive_defaults.items(): -@@ -362,6 +363,7 @@ directive_scopes = { # defaults to available everywhere - 'np_pythran': ('module',), - 'fast_gil': ('module',), - 'iterable_coroutine': ('module', 'function'), -+ 'trashcan' : ('cclass',), - } - - -diff --git a/Cython/Compiler/PyrexTypes.py b/Cython/Compiler/PyrexTypes.py -index c309bd04b..9231130b5 100644 ---- a/Cython/Compiler/PyrexTypes.py -+++ b/Cython/Compiler/PyrexTypes.py -@@ -1129,6 +1129,7 @@ class PyObjectType(PyrexType): - is_extern = False - is_subclassed = False - is_gc_simple = False -+ builtin_trashcan = False # builtin type using trashcan - - def __str__(self): - return "Python object" -@@ -1183,10 +1184,14 @@ class PyObjectType(PyrexType): - - - builtin_types_that_cannot_create_refcycles = set([ -- 'bool', 'int', 'long', 'float', 'complex', -+ 'object', 'bool', 'int', 'long', 'float', 'complex', - 'bytearray', 'bytes', 'unicode', 'str', 'basestring' - ]) - -+builtin_types_with_trashcan = set([ -+ 'dict', 'list', 'set', 'frozenset', 'tuple', 'type', -+]) -+ - - class BuiltinObjectType(PyObjectType): - # objstruct_cname string Name of PyObject struct -@@ -1211,6 +1216,7 @@ class BuiltinObjectType(PyObjectType): - self.typeptr_cname = "(&%s)" % cname - self.objstruct_cname = objstruct_cname - self.is_gc_simple = name in builtin_types_that_cannot_create_refcycles -+ self.builtin_trashcan = name in builtin_types_with_trashcan - if name == 'type': - # Special case the type type, as many C API calls (and other - # libraries) actually expect a PyTypeObject* for type arguments. -diff --git a/Cython/Compiler/Symtab.py b/Cython/Compiler/Symtab.py -index 7361a55ae..f0c311ba6 100644 ---- a/Cython/Compiler/Symtab.py -+++ b/Cython/Compiler/Symtab.py -@@ -2043,7 +2043,7 @@ class PyClassScope(ClassScope): - class CClassScope(ClassScope): - # Namespace of an extension type. - # -- # parent_type CClassType -+ # parent_type PyExtensionType - # #typeobj_cname string or None - # #objstruct_cname string - # method_table_cname string -@@ -2087,6 +2087,22 @@ class CClassScope(ClassScope): - return not self.parent_type.is_gc_simple - return False - -+ def needs_trashcan(self): -+ # If the trashcan directive is explicitly set to False, -+ # unconditionally disable the trashcan. -+ directive = self.directives.get('trashcan') -+ if directive is False: -+ return False -+ # If the directive is set to True and the class has Python-valued -+ # C attributes, then it should use the trashcan in tp_dealloc. -+ if directive and self.has_cyclic_pyobject_attrs: -+ return True -+ # Use the trashcan if the base class uses it -+ base_type = self.parent_type.base_type -+ if base_type and base_type.scope is not None: -+ return base_type.scope.needs_trashcan() -+ return self.parent_type.builtin_trashcan -+ - def needs_tp_clear(self): - """ - Do we need to generate an implementation for the tp_clear slot? Can -diff --git a/Cython/Utility/ExtensionTypes.c b/Cython/Utility/ExtensionTypes.c -index dc187ab49..f359165df 100644 ---- a/Cython/Utility/ExtensionTypes.c -+++ b/Cython/Utility/ExtensionTypes.c -@@ -119,6 +119,54 @@ static int __Pyx_PyType_Ready(PyTypeObject *t) { - return r; - } - -+/////////////// PyTrashcan.proto /////////////// -+ -+// These macros are taken from https://github.com/python/cpython/pull/11841 -+// Unlike the Py_TRASHCAN_SAFE_BEGIN/Py_TRASHCAN_SAFE_END macros, they -+// allow dealing correctly with subclasses. -+ -+// This requires CPython version >= 2.7.4 -+// (or >= 3.2.4 but we don't support such old Python 3 versions anyway) -+#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x03080000 -+// https://github.com/python/cpython/pull/11841 merged so Cython reimplementation -+// is no longer necessary -+#define __Pyx_TRASHCAN_BEGIN Py_TRASHCAN_BEGIN -+#define __Pyx_TRASHCAN_END Py_TRASHCAN_END -+#elif CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x02070400 -+#define __Pyx_TRASHCAN_BEGIN_CONDITION(op, cond) \ -+ do { \ -+ PyThreadState *_tstate = NULL; \ -+ // If "cond" is false, then _tstate remains NULL and the deallocator -+ // is run normally without involving the trashcan -+ if (cond) { \ -+ _tstate = PyThreadState_GET(); \ -+ if (_tstate->trash_delete_nesting >= PyTrash_UNWIND_LEVEL) { \ -+ // Store the object (to be deallocated later) and jump past -+ // Py_TRASHCAN_END, skipping the body of the deallocator -+ _PyTrash_thread_deposit_object((PyObject*)(op)); \ -+ break; \ -+ } \ -+ ++_tstate->trash_delete_nesting; \ -+ } -+ // The body of the deallocator is here. -+#define __Pyx_TRASHCAN_END \ -+ if (_tstate) { \ -+ --_tstate->trash_delete_nesting; \ -+ if (_tstate->trash_delete_later && _tstate->trash_delete_nesting <= 0) \ -+ _PyTrash_thread_destroy_chain(); \ -+ } \ -+ } while (0); -+ -+#define __Pyx_TRASHCAN_BEGIN(op, dealloc) __Pyx_TRASHCAN_BEGIN_CONDITION(op, \ -+ Py_TYPE(op)->tp_dealloc == (destructor)(dealloc)) -+ -+#else -+// The trashcan is a no-op on other Python implementations -+// or old CPython versions -+#define __Pyx_TRASHCAN_BEGIN(op, dealloc) -+#define __Pyx_TRASHCAN_END -+#endif -+ - /////////////// CallNextTpDealloc.proto /////////////// - - static void __Pyx_call_next_tp_dealloc(PyObject* obj, destructor current_tp_dealloc); -diff --git a/tests/run/trashcan.pyx b/tests/run/trashcan.pyx -new file mode 100644 -index 000000000..93a501ff8 ---- /dev/null -+++ b/tests/run/trashcan.pyx -@@ -0,0 +1,148 @@ -+# mode: run -+ -+cimport cython -+ -+ -+# Count number of times an object was deallocated twice. This should remain 0. -+cdef int double_deallocations = 0 -+def assert_no_double_deallocations(): -+ global double_deallocations -+ err = double_deallocations -+ double_deallocations = 0 -+ assert not err -+ -+ -+# Compute x = f(f(f(...(None)...))) nested n times and throw away the result. -+# The real test happens when exiting this function: then a big recursive -+# deallocation of x happens. We are testing two things in the tests below: -+# that Python does not crash and that no double deallocation happens. -+# See also https://github.com/python/cpython/pull/11841 -+def recursion_test(f, int n=2**20): -+ x = None -+ cdef int i -+ for i in range(n): -+ x = f(x) -+ -+ -+@cython.trashcan(True) -+cdef class Recurse: -+ """ -+ >>> recursion_test(Recurse) -+ >>> assert_no_double_deallocations() -+ """ -+ cdef public attr -+ cdef int deallocated -+ -+ def __init__(self, x): -+ self.attr = x -+ -+ def __dealloc__(self): -+ # Check that we're not being deallocated twice -+ global double_deallocations -+ double_deallocations += self.deallocated -+ self.deallocated = 1 -+ -+ -+cdef class RecurseSub(Recurse): -+ """ -+ >>> recursion_test(RecurseSub) -+ >>> assert_no_double_deallocations() -+ """ -+ cdef int subdeallocated -+ -+ def __dealloc__(self): -+ # Check that we're not being deallocated twice -+ global double_deallocations -+ double_deallocations += self.subdeallocated -+ self.subdeallocated = 1 -+ -+ -+@cython.freelist(4) -+@cython.trashcan(True) -+cdef class RecurseFreelist: -+ """ -+ >>> recursion_test(RecurseFreelist) -+ >>> recursion_test(RecurseFreelist, 1000) -+ >>> assert_no_double_deallocations() -+ """ -+ cdef public attr -+ cdef int deallocated -+ -+ def __init__(self, x): -+ self.attr = x -+ -+ def __dealloc__(self): -+ # Check that we're not being deallocated twice -+ global double_deallocations -+ double_deallocations += self.deallocated -+ self.deallocated = 1 -+ -+ -+# Subclass of list => uses trashcan by default -+# As long as https://github.com/python/cpython/pull/11841 is not fixed, -+# this does lead to double deallocations, so we skip that check. -+cdef class RecurseList(list): -+ """ -+ >>> RecurseList(42) -+ [42] -+ >>> recursion_test(RecurseList) -+ """ -+ def __init__(self, x): -+ super().__init__((x,)) -+ -+ -+# Some tests where the trashcan is NOT used. When the trashcan is not used -+# in a big recursive deallocation, the __dealloc__s of the base classs are -+# only run after the __dealloc__s of the subclasses. -+# We use this to detect trashcan usage. -+cdef int base_deallocated = 0 -+cdef int trashcan_used = 0 -+def assert_no_trashcan_used(): -+ global base_deallocated, trashcan_used -+ err = trashcan_used -+ trashcan_used = base_deallocated = 0 -+ assert not err -+ -+ -+cdef class Base: -+ def __dealloc__(self): -+ global base_deallocated -+ base_deallocated = 1 -+ -+ -+# Trashcan disabled by default -+cdef class Sub1(Base): -+ """ -+ >>> recursion_test(Sub1, 100) -+ >>> assert_no_trashcan_used() -+ """ -+ cdef public attr -+ -+ def __init__(self, x): -+ self.attr = x -+ -+ def __dealloc__(self): -+ global base_deallocated, trashcan_used -+ trashcan_used += base_deallocated -+ -+ -+@cython.trashcan(True) -+cdef class Middle(Base): -+ cdef public foo -+ -+ -+# Trashcan disabled explicitly -+@cython.trashcan(False) -+cdef class Sub2(Middle): -+ """ -+ >>> recursion_test(Sub2, 1000) -+ >>> assert_no_trashcan_used() -+ """ -+ cdef public attr -+ -+ def __init__(self, x): -+ self.attr = x -+ -+ def __dealloc__(self): -+ global base_deallocated, trashcan_used -+ trashcan_used += base_deallocated --- -2.37.1 (Apple Git-137.1) - diff --git a/build/pkgs/cython/patches/0001-rebased-PR2946.patch b/build/pkgs/cython/patches/0001-rebased-PR2946.patch deleted file mode 100644 index 36764e7291e..00000000000 --- a/build/pkgs/cython/patches/0001-rebased-PR2946.patch +++ /dev/null @@ -1,193 +0,0 @@ -From 0b69e95aa702fb9f52b285360d5c5ae5e7fbb745 Mon Sep 17 00:00:00 2001 -From: Dima Pasechnik -Date: Thu, 16 Mar 2023 22:35:09 +0000 -Subject: [PATCH] rebased PR2946 - ---- - Cython/Compiler/Main.py | 44 +++++++++++++++---- - Cython/Utils.py | 22 +++++++--- - runtests.py | 1 + - .../build/cythonize_pep420_namespace.srctree | 44 +++++++++++++++++++ - 4 files changed, 96 insertions(+), 15 deletions(-) - create mode 100644 tests/build/cythonize_pep420_namespace.srctree - -diff --git a/Cython/Compiler/Main.py b/Cython/Compiler/Main.py -index 9c57452ba..1143ecf03 100644 ---- a/Cython/Compiler/Main.py -+++ b/Cython/Compiler/Main.py -@@ -809,32 +809,58 @@ def search_include_directories(dirs, qualified_name, suffix, pos, include=False) - else: - dirs = (Utils.find_root_package_dir(file_desc.filename),) + dirs - -+ # search for dotted filename e.g. /foo.bar.pxd - dotted_filename = qualified_name - if suffix: - dotted_filename += suffix - -+ for dirname in dirs: -+ path = os.path.join(dirname, dotted_filename) -+ if os.path.exists(path): -+ return path -+ -+ # search for filename in package structure e.g. /foo/bar.pxd or /foo/bar/__init__.pxd - if not include: -+ - names = qualified_name.split('.') - package_names = tuple(names[:-1]) - module_name = names[-1] - module_filename = module_name + suffix - package_filename = "__init__" + suffix - -- for dirname in dirs: -- path = os.path.join(dirname, dotted_filename) -- if os.path.exists(path): -- return path -- -- if not include: -- package_dir = Utils.check_package_dir(dirname, package_names) -+ # search for standard packages first - PEP420 -+ namespace_dirs = [] -+ for dirname in dirs: -+ package_dir, is_namespace = Utils.check_package_dir(dirname, package_names) - if package_dir is not None: -+ -+ if is_namespace: -+ namespace_dirs.append(package_dir) -+ continue -+ -+ # matches modules of the form: /foo/bar.pxd - path = os.path.join(package_dir, module_filename) - if os.path.exists(path): - return path -- path = os.path.join(package_dir, module_name, -- package_filename) -+ -+ # matches modules of the form: /foo/bar/__init__.pxd -+ path = os.path.join(package_dir, module_name, package_filename) - if os.path.exists(path): - return path -+ -+ # search for namespaces second - PEP420 -+ for package_dir in namespace_dirs: -+ -+ # matches modules of the form: /foo/bar.pxd -+ path = os.path.join(package_dir, module_filename) -+ if os.path.exists(path): -+ return path -+ -+ # matches modules of the form: /foo/bar/__init__.pxd -+ path = os.path.join(package_dir, module_name, package_filename) -+ if os.path.exists(path): -+ return path -+ - return None - - -diff --git a/Cython/Utils.py b/Cython/Utils.py -index 69563794c..77a48fbd7 100644 ---- a/Cython/Utils.py -+++ b/Cython/Utils.py -@@ -135,15 +135,19 @@ def find_root_package_dir(file_path): - return dir - - @cached_function --def check_package_dir(dir, package_names): -+def check_package_dir(dir_path, package_names): -+ namespace = True - for dirname in package_names: -- dir = os.path.join(dir, dirname) -- if not is_package_dir(dir): -- return None -- return dir -+ dir_path = os.path.join(dir_path, dirname) -+ has_init = contains_init(dir_path) -+ if not namespace and not has_init: -+ return None, False -+ elif has_init: -+ namespace = False -+ return dir_path, namespace - - @cached_function --def is_package_dir(dir_path): -+def contains_init(dir_path): - for filename in ("__init__.py", - "__init__.pyc", - "__init__.pyx", -@@ -152,6 +156,12 @@ def is_package_dir(dir_path): - if path_exists(path): - return 1 - -+ -+def is_package_dir(dir_path): -+ if contains_init(dir_path): -+ return 1 -+ -+ - @cached_function - def path_exists(path): - # try on the filesystem first -diff --git a/runtests.py b/runtests.py -index 91a0dd257..7d0446384 100755 ---- a/runtests.py -+++ b/runtests.py -@@ -415,6 +415,7 @@ VER_DEP_MODULES = { - 'run.special_methods_T561_py2' - ]), - (3,3) : (operator.lt, lambda x: x in ['build.package_compilation', -+ 'build.cythonize_pep420_namespace', - 'run.yield_from_py33', - 'pyximport.pyximport_namespace', - ]), -diff --git a/tests/build/cythonize_pep420_namespace.srctree b/tests/build/cythonize_pep420_namespace.srctree -new file mode 100644 -index 000000000..6a031e417 ---- /dev/null -+++ b/tests/build/cythonize_pep420_namespace.srctree -@@ -0,0 +1,44 @@ -+PYTHON setup.py build_ext --inplace -+PYTHON -c "import runner" -+ -+######## setup.py ######## -+ -+from Cython.Build.Dependencies import cythonize -+ -+from distutils.core import setup, Extension -+ -+setup( -+ ext_modules=cythonize([ -+ Extension("nsp.m1.a", ["nsp/m1/a.pyx"]), -+ Extension("nsp.m2.b", ["nsp/m2/b.pyx"]) -+ ]), -+) -+ -+######## nsp/m1/__init__.py ######## -+ -+######## nsp/m1/a.pyx ######## -+ -+cdef class A: -+ pass -+ -+######## nsp/m1/a.pxd ######## -+ -+cdef class A: -+ pass -+ -+######## nsp/m2/__init__.py ######## -+ -+######## nsp/m2/b.pyx ######## -+ -+from nsp.m1.a cimport A -+ -+cdef class B(A): -+ pass -+ -+######## runner.py ######## -+ -+from nsp.m1.a import A -+from nsp.m2.b import B -+ -+a = A() -+b = B() --- -2.37.1 (Apple Git-137.1) - From ad75f666bd777dca0628492819f99c998742f1bc Mon Sep 17 00:00:00 2001 From: Yutao Yuan Date: Tue, 8 Aug 2023 11:30:45 +0800 Subject: [PATCH 04/93] use cython legacy directives for sage --- src/sage_setup/cython_options.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/sage_setup/cython_options.py b/src/sage_setup/cython_options.py index 086aa070ca9..9725ce0e1af 100644 --- a/src/sage_setup/cython_options.py +++ b/src/sage_setup/cython_options.py @@ -10,13 +10,17 @@ def compiler_directives(profile: bool): auto_pickle=False, # Do not create __test__ dictionary automatically from docstrings autotestdict=False, + binding=False, + c_api_binop_methods=True, # Do not check for division by 0 (this is about 35% quicker than with check) cdivision=True, + cpow=True, # Embed a textual copy of the call signature in the docstring (to support tools like IPython) embedsignature=True, fast_getattr=True, # Use Python 3 (including source code semantics) for module compilation language_level="3", + legacy_implicit_noexcept=True, # Enable support for late includes (make declarations in Cython code available to C include files) preliminary_late_includes_cy28=True, # Add hooks for Python profilers into the compiled C code From 0044e67c50b53b2f75703375260f4dbe46309e6d Mon Sep 17 00:00:00 2001 From: Yutao Yuan Date: Tue, 8 Aug 2023 00:54:01 +0800 Subject: [PATCH 05/93] add cython3 patches for cysignals, cypari2, fpylll, and pplpy --- .../pkgs/cypari/patches/cython3-legacy.patch | 32 ++++++++++++++++ .../patches/cython3-fix-warning.patch | 13 +++++++ .../cysignals/patches/cython3-legacy.patch | 30 +++++++++++++++ .../pkgs/fpylll/patches/cython3-legacy.patch | 37 +++++++++++++++++++ build/pkgs/pplpy/patches/cython3-legacy.patch | 22 +++++++++++ .../pkgs/pplpy/patches/relative-import.patch | 21 +++++++++++ 6 files changed, 155 insertions(+) create mode 100644 build/pkgs/cypari/patches/cython3-legacy.patch create mode 100644 build/pkgs/cysignals/patches/cython3-fix-warning.patch create mode 100644 build/pkgs/cysignals/patches/cython3-legacy.patch create mode 100644 build/pkgs/fpylll/patches/cython3-legacy.patch create mode 100644 build/pkgs/pplpy/patches/cython3-legacy.patch create mode 100644 build/pkgs/pplpy/patches/relative-import.patch diff --git a/build/pkgs/cypari/patches/cython3-legacy.patch b/build/pkgs/cypari/patches/cython3-legacy.patch new file mode 100644 index 00000000000..41392fe80d7 --- /dev/null +++ b/build/pkgs/cypari/patches/cython3-legacy.patch @@ -0,0 +1,32 @@ +commit 8ef356a4eb936c37f55a5c501f3a955e6740c0c5 +Author: Gonzalo Tornaría +Date: Wed Jul 19 19:45:23 2023 -0300 + + cython3 support using legacy directives + +diff --git a/cypari2/gen.pyx b/cypari2/gen.pyx +index 247b1ad..75050a0 100644 +--- a/cypari2/gen.pyx ++++ b/cypari2/gen.pyx +@@ -329,7 +329,7 @@ cdef class Gen(Gen_base): + >>> pari = Pari() + >>> L = pari("vector(10,i,i^2)") + >>> L.__iter__() +- ++ <...generator object at ...> + >>> [x for x in L] + [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] + >>> list(L) +diff --git a/setup.py b/setup.py +index 2188711..455337f 100755 +--- a/setup.py ++++ b/setup.py +@@ -36,6 +36,8 @@ class build_ext(_build_ext): + "binding": True, + "cdivision": True, + "language_level": 2, ++ "legacy_implicit_noexcept": True, ++ "c_api_binop_methods": True, + } + + _build_ext.finalize_options(self) diff --git a/build/pkgs/cysignals/patches/cython3-fix-warning.patch b/build/pkgs/cysignals/patches/cython3-fix-warning.patch new file mode 100644 index 00000000000..98cad9625e4 --- /dev/null +++ b/build/pkgs/cysignals/patches/cython3-fix-warning.patch @@ -0,0 +1,13 @@ +diff --git a/src/cysignals/signals.pxd.in b/src/cysignals/signals.pxd.in +index c86e085..a98c8d1 100644 +--- a/src/cysignals/signals.pxd.in ++++ b/src/cysignals/signals.pxd.in +@@ -54,7 +54,7 @@ cdef extern from "macros.h" nogil: + # can be used to make Cython check whether there is a pending exception + # (PyErr_Occurred() is non-NULL). To Cython, it will look like + # cython_check_exception() actually raised the exception. +-cdef inline void cython_check_exception() nogil except *: ++cdef inline void cython_check_exception() except * nogil: + pass + + diff --git a/build/pkgs/cysignals/patches/cython3-legacy.patch b/build/pkgs/cysignals/patches/cython3-legacy.patch new file mode 100644 index 00000000000..274575d5d35 --- /dev/null +++ b/build/pkgs/cysignals/patches/cython3-legacy.patch @@ -0,0 +1,30 @@ +commit 9996a4028ddc7f9a5ffda3df65d5b7d3b7df8aa5 +Author: Gonzalo Tornaría +Date: Wed Jul 19 18:34:57 2023 -0300 + + cython3 support using legacy directives + +diff --git a/setup.py b/setup.py +index 37acdfc..f68270b 100755 +--- a/setup.py ++++ b/setup.py +@@ -157,13 +157,17 @@ class build_ext(_build_ext): + # Run Cython with -Werror on continuous integration services + # with Python 3.6 or later + from Cython.Compiler import Options +- Options.warning_errors = True ++ Options.warning_errors = False + + from Cython.Build.Dependencies import cythonize + return cythonize(extensions, + build_dir=cythonize_dir, + include_path=["src", os.path.join(cythonize_dir, "src")], +- compiler_directives=dict(binding=True, language_level=2)) ++ compiler_directives=dict( ++ binding=True, ++ language_level=2, ++ legacy_implicit_noexcept=True, ++ )) + + + class build_py(_build_py): diff --git a/build/pkgs/fpylll/patches/cython3-legacy.patch b/build/pkgs/fpylll/patches/cython3-legacy.patch new file mode 100644 index 00000000000..808c14e9c1b --- /dev/null +++ b/build/pkgs/fpylll/patches/cython3-legacy.patch @@ -0,0 +1,37 @@ +commit b6e12c2b0648e84b26dcf0aac507a5b4d9dde301 +Author: Gonzalo Tornaría +Date: Wed Jul 19 20:38:01 2023 -0300 + + cython3 support using legacy directives + +diff --git a/setup.py b/setup.py +index 274836f..8fc5af5 100755 +--- a/setup.py ++++ b/setup.py +@@ -123,7 +123,12 @@ class build_ext(_build_ext, object): + self.extensions, + include_path=["src"], + build_dir=self.cythonize_dir, +- compiler_directives={"binding": True, "embedsignature": True, "language_level": 2}, ++ compiler_directives={ ++ "binding": True, ++ "embedsignature": True, ++ "language_level": 2, ++ "legacy_implicit_noexcept": True, ++ }, + ) + super(build_ext, self).run() + +diff --git a/src/fpylll/fplll/enumeration_callback_helper.h b/src/fpylll/fplll/enumeration_callback_helper.h +index c099430..706162f 100644 +--- a/src/fpylll/fplll/enumeration_callback_helper.h ++++ b/src/fpylll/fplll/enumeration_callback_helper.h +@@ -5,7 +5,7 @@ + #include + #include + +-extern "C" { ++extern "C++" { + bool evaluator_callback_call_obj(PyObject *obj, int n, double *new_sol_coord); + } + diff --git a/build/pkgs/pplpy/patches/cython3-legacy.patch b/build/pkgs/pplpy/patches/cython3-legacy.patch new file mode 100644 index 00000000000..a038da16d6b --- /dev/null +++ b/build/pkgs/pplpy/patches/cython3-legacy.patch @@ -0,0 +1,22 @@ +commit e6f3e66154138ce3e31e803e74b8c71787c70acc +Author: Gonzalo Tornaría +Date: Wed Jul 19 20:47:52 2023 -0300 + + cython3 support using legacy directives + +diff --git a/setup.py b/setup.py +index 13d543b..55dcd34 100755 +--- a/setup.py ++++ b/setup.py +@@ -38,7 +38,11 @@ class build_ext(_build_ext): + self.extensions[:] = cythonize( + self.extensions, + include_path=sys.path, +- compiler_directives={'embedsignature': True}) ++ compiler_directives={ ++ 'embedsignature': True, ++ 'legacy_implicit_noexcept': True, ++ 'c_api_binop_methods': True, ++ }) + + _build_ext.run(self) diff --git a/build/pkgs/pplpy/patches/relative-import.patch b/build/pkgs/pplpy/patches/relative-import.patch new file mode 100644 index 00000000000..3c011203367 --- /dev/null +++ b/build/pkgs/pplpy/patches/relative-import.patch @@ -0,0 +1,21 @@ +From aaa28537fa7ea061ebb8d5131b1e23673eaf741d Mon Sep 17 00:00:00 2001 +From: Matthias Koeppe +Date: Sun, 31 Jul 2022 12:39:34 -0700 +Subject: [PATCH] ppl/bit_arrays.pxd: Use relative cimport + +--- + ppl/bit_arrays.pxd | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ppl/bit_arrays.pxd b/ppl/bit_arrays.pxd +index eb57434..145a978 100644 +--- a/ppl/bit_arrays.pxd ++++ b/ppl/bit_arrays.pxd +@@ -1,4 +1,4 @@ +-from ppl_decl cimport * ++from .ppl_decl cimport * + + cdef class Bit_Row(object): + cdef PPL_Bit_Row *thisptr +-- +GitLab From bbe813486fd6777c2b7401aebbfa1602dbc285b6 Mon Sep 17 00:00:00 2001 From: Yutao Yuan Date: Tue, 8 Aug 2023 11:29:28 +0800 Subject: [PATCH 06/93] add cython3 patch for scipy --- build/pkgs/scipy/patches/cython3-legacy.patch | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 build/pkgs/scipy/patches/cython3-legacy.patch diff --git a/build/pkgs/scipy/patches/cython3-legacy.patch b/build/pkgs/scipy/patches/cython3-legacy.patch new file mode 100644 index 00000000000..9abf0c02154 --- /dev/null +++ b/build/pkgs/scipy/patches/cython3-legacy.patch @@ -0,0 +1,91 @@ +diff --git a/scipy/linalg.pxd b/scipy/linalg.pxd +index 1f656b87..c7c49f9a 100644 +--- a/scipy/linalg.pxd ++++ b/scipy/linalg.pxd +@@ -1 +1 @@ +-from .linalg cimport cython_blas, cython_lapack ++from scipy.linalg cimport cython_blas, cython_lapack +diff --git a/scipy/meson.build b/scipy/meson.build +index 21ea04d5..71d54804 100644 +--- a/scipy/meson.build ++++ b/scipy/meson.build +@@ -197,7 +197,7 @@ _cython_tree = [ + fs.copyfile('special.pxd'), + ] + +-cython_args = ['-3', '--fast-fail', '--output-file', '@OUTPUT@', '--include-dir', '@BUILD_ROOT@', '@INPUT@'] ++cython_args = ['-3', '--fast-fail', '--directive', 'legacy_implicit_noexcept=True', '--output-file', '@OUTPUT@', '--include-dir', '@BUILD_ROOT@', '@INPUT@'] + cython_cplus_args = ['--cplus'] + cython_args + + cython_gen = generator(cython, +diff --git a/scipy/optimize/cython_optimize.pxd b/scipy/optimize/cython_optimize.pxd +index d5a0bdd7..d35f8da6 100644 +--- a/scipy/optimize/cython_optimize.pxd ++++ b/scipy/optimize/cython_optimize.pxd +@@ -7,5 +7,5 @@ + # support. Changing it causes an ABI forward-compatibility break + # (gh-11793), so we currently leave it as is (no further cimport + # statements should be used in this file). +-from .cython_optimize._zeros cimport ( ++from scipy.optimize.cython_optimize._zeros cimport ( + brentq, brenth, ridder, bisect, zeros_full_output) +diff --git a/scipy/optimize/meson.build b/scipy/optimize/meson.build +index 05db6a68..07d46fb9 100644 +--- a/scipy/optimize/meson.build ++++ b/scipy/optimize/meson.build +@@ -231,6 +231,10 @@ endif + + _dummy_init_optimize = fs.copyfile('__init__.py') + ++_cython_tree = [ ++ fs.copyfile('cython_optimize.pxd'), ++] ++ + opt_gen = generator(cython, + arguments : cython_args, + output : '@BASENAME@.c', +diff --git a/scipy/special.pxd b/scipy/special.pxd +index 62cb8280..1daa9fb3 100644 +--- a/scipy/special.pxd ++++ b/scipy/special.pxd +@@ -1 +1 @@ +-from .special cimport cython_special ++from scipy.special cimport cython_special +diff --git a/scipy/special/meson.build b/scipy/special/meson.build +index f92183f5..09ad0a4f 100644 +--- a/scipy/special/meson.build ++++ b/scipy/special/meson.build +@@ -362,7 +362,7 @@ py3.extension_module('_ufuncs_cxx', + [ufuncs_cxx_sources, + uf_cython_gen_cpp.process(cython_special[2]), # _ufuncs_cxx.pyx + ], +- cpp_args: cython_cpp_args, ++ cpp_args: [cython_cpp_args, '-DCYTHON_EXTERN_C=extern "C"'], + include_directories: [inc_np, '../_lib/boost', '../_lib', + '../_build_utils/src'], + link_args: version_link_args, +diff --git a/scipy/special/setup.py b/scipy/special/setup.py +index 7e8c9608..b38a6ec2 100644 +--- a/scipy/special/setup.py ++++ b/scipy/special/setup.py +@@ -103,7 +103,7 @@ def configuration(parent_package='',top_path=None): + sources=ufuncs_cxx_src, + depends=ufuncs_cxx_dep, + include_dirs=[curdir] + inc_dirs, +- define_macros=define_macros, ++ define_macros=define_macros + [('CYTHON_EXTERN_C', 'extern "C"')], + extra_info=get_info("npymath")) + ufuncs_cxx_ext._pre_build_hook = set_cxx_flags_hook + +diff --git a/tools/cythonize.py b/tools/cythonize.py +index 402824cb..7ad778da 100755 +--- a/tools/cythonize.py ++++ b/tools/cythonize.py +@@ -94,6 +94,7 @@ def process_pyx(fromfile, tofile, cwd): + flags = ['--fast-fail', '-3'] + if tofile.endswith('.cxx'): + flags += ['--cplus'] ++ flags += ['--directive', 'legacy_implicit_noexcept=true'] + + try: + try: From 543917591850414cb3b874353cbebd2c6b717e52 Mon Sep 17 00:00:00 2001 From: Yutao Yuan Date: Mon, 21 Aug 2023 11:06:20 +0800 Subject: [PATCH 07/93] add cython3 patch for numpy --- build/pkgs/numpy/patches/cython3-legacy.patch | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 build/pkgs/numpy/patches/cython3-legacy.patch diff --git a/build/pkgs/numpy/patches/cython3-legacy.patch b/build/pkgs/numpy/patches/cython3-legacy.patch new file mode 100644 index 00000000000..dfcb9c4a69c --- /dev/null +++ b/build/pkgs/numpy/patches/cython3-legacy.patch @@ -0,0 +1,12 @@ +diff --git a/tools/cythonize.py b/tools/cythonize.py +index 002b2fa..c04422e 100755 +--- a/tools/cythonize.py ++++ b/tools/cythonize.py +@@ -47,6 +47,7 @@ def process_pyx(fromfile, tofile): + flags = ['-3', '--fast-fail'] + if tofile.endswith('.cxx'): + flags.append('--cplus') ++ flags += ['--directive', 'legacy_implicit_noexcept=true'] + + subprocess.check_call( + [sys.executable, '-m', 'cython'] + flags + ["-o", tofile, fromfile]) From 4d5f7bf0c7344caaa8fcf939e993d1c7925e8fbf Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Wed, 12 Apr 2023 17:23:13 +0900 Subject: [PATCH 08/93] Adding a new comparison mode to lazy series and added a check for undefined series. --- .../combinat/species/recursive_species.py | 9 + src/sage/data_structures/stream.py | 53 ++++ src/sage/rings/lazy_series.py | 245 ++++++++++++++---- src/sage/rings/lazy_series_ring.py | 117 +++++++-- 4 files changed, 359 insertions(+), 65 deletions(-) diff --git a/src/sage/combinat/species/recursive_species.py b/src/sage/combinat/species/recursive_species.py index a361bdfad20..8fd01494c1a 100644 --- a/src/sage/combinat/species/recursive_species.py +++ b/src/sage/combinat/species/recursive_species.py @@ -401,6 +401,15 @@ def define(self, x): [1, 2, 3, 5, 8, 13, 21, 34, 55, 89] sage: F.isotype_generating_series()[0:10] [1, 2, 3, 5, 8, 13, 21, 34, 55, 89] + + Check that :issue:`35071` is fixed:: + + sage: X = species.SingletonSpecies() + sage: E = species.SetSpecies(max=3) + sage: B = species.CombinatorialSpecies(min=1) + sage: B.define(X*E(B)) + sage: B.generating_series() + z + z^2 + 3/2*z^3 + 5/2*z^4 + 9/2*z^5 + 17/2*z^6 + 133/8*z^7 + O(z^8) """ if not isinstance(x, GenericCombinatorialSpecies): raise TypeError("x must be a combinatorial species") diff --git a/src/sage/data_structures/stream.py b/src/sage/data_structures/stream.py index 87b5b1e7ecb..735398cbcca 100644 --- a/src/sage/data_structures/stream.py +++ b/src/sage/data_structures/stream.py @@ -199,6 +199,12 @@ def is_nonzero(self): """ return False + def is_undefined(self): + """ + Return ``True`` if ``self`` is an undefined stream. + """ + return False + class Stream_inexact(Stream): """ @@ -1042,6 +1048,12 @@ def iterate_coefficients(self): yield self._target[n] n += 1 + def is_undefined(self): + """ + Return ``True`` if ``self`` is an undefined stream. + """ + return self._target is None + class Stream_unary(Stream_inexact): r""" @@ -1118,6 +1130,12 @@ def __eq__(self, other): """ return isinstance(other, type(self)) and self._series == other._series + def is_undefined(self): + """ + Return ``True`` if ``self`` is an undefined stream. + """ + return self._series.is_undefined() + class Stream_binary(Stream_inexact): """ @@ -1206,6 +1224,12 @@ def __eq__(self, other): return False return self._left == other._left and self._right == other._right + def is_undefined(self): + """ + Return ``True`` if ``self`` is an undefined stream. + """ + return self._left.is_undefined() or self._right.is_undefined() + class Stream_binaryCommutative(Stream_binary): r""" @@ -2316,6 +2340,12 @@ def is_nonzero(self): """ return self._series.is_nonzero() + def is_undefined(self): + """ + Return ``True`` if ``self`` is an undefined stream. + """ + return self._series.is_undefined() + class Stream_rmul(Stream_scalar): """ @@ -2748,6 +2778,12 @@ def __eq__(self, other): return (isinstance(other, type(self)) and self._series == other._series and self._function == other._function) + def is_undefined(self): + """ + Return ``True`` if ``self`` is an undefined stream. + """ + return self._series.is_undefined() + class Stream_shift(Stream): """ @@ -2881,6 +2917,11 @@ def is_nonzero(self): """ return self._series.is_nonzero() + def is_undefined(self): + """ + Return ``True`` if ``self`` is an undefined stream. + """ + return self._series.is_undefined() class Stream_truncated(Stream_inexact): """ @@ -3130,6 +3171,12 @@ def is_nonzero(self): start = self._approximate_order - offset return any(self._cache[start:]) + def is_undefined(self): + """ + Return ``True`` if ``self`` is an undefined stream. + """ + return self._series.is_undefined() + class Stream_derivative(Stream_inexact): """ @@ -3258,3 +3305,9 @@ def is_nonzero(self): True """ return self._series.is_nonzero() + + def is_undefined(self): + """ + Return ``True`` if ``self`` is an undefined stream. + """ + return self._series.is_undefined() diff --git a/src/sage/rings/lazy_series.py b/src/sage/rings/lazy_series.py index 3278c8eed7c..a43e9697332 100644 --- a/src/sage/rings/lazy_series.py +++ b/src/sage/rings/lazy_series.py @@ -246,6 +246,7 @@ Stream_dirichlet_invert, Stream_plethysm ) +from sage.misc.unknown import Unknown, UnknownError class LazyModuleElement(Element): @@ -938,13 +939,31 @@ def _richcmp_(self, other, op): sage: fz = L(lambda n: 0, valuation=0) sage: L.zero() == fz - Traceback (most recent call last): - ... - ValueError: undecidable + False sage: fz == L.zero() - Traceback (most recent call last): - ... - ValueError: undecidable + False + + With using :class:`Unknown`:: + + sage: L.options.use_unknown = True + sage: fz = L(lambda n: 0, valuation=0) + sage: L.zero() == fz + Unknown + sage: fz == L.zero() + Unknown + sage: fz != L.zero() + Unknown + + With using finite halting precision:: + + sage: L.options.halting_precision = 40 + sage: fz = L(lambda n: 0, valuation=0) + sage: L.zero() == fz + True + sage: fz == L.zero() + True + + sage: L.options._reset() TESTS:: @@ -953,24 +972,27 @@ def _richcmp_(self, other, op): sage: g = L([0,0,1,0,1,0,0], degree=7, constant=1) sage: f == g True - """ if op is op_EQ: + if (not self.parent().options['use_unknown'] + and self.parent().options['halting_precision'] is None): + return self._coeff_stream == other._coeff_stream + if isinstance(self._coeff_stream, Stream_zero): if isinstance(other._coeff_stream, Stream_zero): return True - if other._coeff_stream.is_nonzero(): + if other._coeff_stream.is_undefined() or other._coeff_stream.is_nonzero(): return False elif isinstance(other._coeff_stream, Stream_zero): - if self._coeff_stream.is_nonzero(): + if self._coeff_stream.is_undefined() or self._coeff_stream.is_nonzero(): return False elif isinstance(self._coeff_stream, Stream_exact): if isinstance(other._coeff_stream, Stream_exact): return self._coeff_stream == other._coeff_stream - if self._coeff_stream != other._coeff_stream: + if self._coeff_stream != other._coeff_stream or other._coeff_stream.is_undefined(): return False elif isinstance(other._coeff_stream, Stream_exact): - if other._coeff_stream != self._coeff_stream: + if other._coeff_stream != self._coeff_stream or self._coeff_stream.is_undefined(): return False else: # both streams are inexact, perhaps they are equal by @@ -980,19 +1002,26 @@ def _richcmp_(self, other, op): # perhaps their caches are different if self._coeff_stream != other._coeff_stream: return False + if self._coeff_stream.is_undefined() or other._coeff_stream.is_undefined(): + return False # undecidable otherwise prec = self.parent().options['halting_precision'] if prec is None: - raise ValueError("undecidable") + return Unknown + # raise UnknownError("undecidable") # at least one of the approximate orders is not infinity m = min(self._coeff_stream._approximate_order, other._coeff_stream._approximate_order) return all(self[i] == other[i] for i in range(m, m + prec)) if op is op_NE: - return not (self == other) + ret = (self == other) + if ret is Unknown: + return ret + return not ret + # FIXME: This should check for equality in <= and >= and other return NotImplemented return False def __hash__(self): @@ -1015,9 +1044,8 @@ def __bool__(self): """ Test whether ``self`` is not zero. - An uninitialized series returns ``True`` as it is considered - as a formal variable, such as a generator of a polynomial - ring. + When the halting precision is infinite, then any series that is + not known to be zero will be ``True``. TESTS:: @@ -1033,11 +1061,9 @@ def __bool__(self): False sage: M = L(lambda n: 2*n if n < 10 else 1, valuation=0); M # optional - sage.rings.finite_rings O(z^7) - sage: bool(M) # optional - sage.rings.finite_rings - Traceback (most recent call last): - ... - ValueError: undecidable as lazy Laurent series - sage: M[15] # optional - sage.rings.finite_rings + sage: bool(M) + True + sage: M[15] 1 sage: bool(M) # optional - sage.rings.finite_rings True @@ -1045,11 +1071,9 @@ def __bool__(self): sage: L. = LazyLaurentSeriesRing(GF(2), sparse=True) # optional - sage.rings.finite_rings sage: M = L(lambda n: 2*n if n < 10 else 1, valuation=0); M # optional - sage.rings.finite_rings O(z^7) - sage: bool(M) # optional - sage.rings.finite_rings - Traceback (most recent call last): - ... - ValueError: undecidable as lazy Laurent series - sage: M[15] # optional - sage.rings.finite_rings + sage: bool(M) + True + sage: M[15] 1 sage: bool(M) # optional - sage.rings.finite_rings True @@ -1076,18 +1100,52 @@ def __bool__(self): sage: g.define(1 + z*g) # optional - sage.rings.finite_rings sage: bool(g) # optional - sage.rings.finite_rings True + + Comparison with finite halting precision:: + + sage: M = L(lambda n: 2*n if n < 10 else 0, valuation=0) + sage: bool(M) + True + sage: M.is_zero() + False + + sage: L.options.halting_precision = 20 + sage: bool(M) + False + sage: M.is_zero() + True + + + With finite halting precision, it can be considered to + be indistinguishable from zero until possibly enough + coefficients are computed:: + + sage: L. = LazyLaurentSeriesRing(GF(2)) + sage: L.options.halting_precision = 20 + sage: f = L(lambda n: 0, valuation=0) + sage: f.is_zero() + True + + sage: g = L(lambda n: 0 if n < 50 else 1, valuation=2) + sage: bool(g) # checks up to degree 22 = 2 + 20 + False + sage: bool(g) # checks up to degree 42 = 22 + 20 + False + sage: bool(g) # checks up to degree 62 = 42 + 20 + True + sage: L.options._reset() """ if isinstance(self._coeff_stream, Stream_zero): return False + + prec = self.parent().options['halting_precision'] + if prec is None and not self.parent().options['use_unknown']: + return True + if isinstance(self._coeff_stream, Stream_exact): return True - if isinstance(self._coeff_stream, Stream_uninitialized): - if self._coeff_stream._target is None: - return True - if isinstance(self._coeff_stream._target, Stream_zero): - return False - if isinstance(self._coeff_stream._target, Stream_exact): - return True + if self._coeff_stream.is_undefined(): + return True if self._coeff_stream._is_sparse: cache = self._coeff_stream._cache if any(cache[a] for a in cache): @@ -1096,15 +1154,57 @@ def __bool__(self): if any(self._coeff_stream._cache): return True - v = self._coeff_stream._approximate_order - if self[v]: - return True - - prec = self.parent().options['halting_precision'] if prec is None: - raise ValueError("undecidable as lazy Laurent series") + raise UnknownError("undecidable") + v = self._coeff_stream._approximate_order return any(self[i] for i in range(v, v + prec)) + def is_nonzero(self): + """ + Return ``True`` if ``self`` is known to be nonzero. + + EXAMPLES: + + A series that it not known to be nonzero with no halting precision:: + + sage: L. = LazyLaurentSeriesRing(GF(2)) + sage: f = L(lambda n: 0, valuation=0) + sage: f.is_nonzero() + False + sage: bool(f) + True + sage: g = L(lambda n: 0 if n < 50 else 1, valuation=2) + sage: g.is_nonzero() + False + sage: g[60] + 1 + sage: g.is_nonzero() + True + + With finite halting precision, it can be considered to + be indistinguishable from zero until possibly enough + coefficients are computed:: + + sage: L.options.halting_precision = 20 + sage: f = L(lambda n: 0, valuation=0) + sage: f.is_zero() + True + + sage: g = L(lambda n: 0 if n < 50 else 1, valuation=2) + sage: g.is_nonzero() # checks up to degree 22 = 2 + 20 + False + sage: g.is_nonzero() # checks up to degree 42 = 22 + 20 + False + sage: g.is_nonzero() # checks up to degree 62 = 42 + 20 + True + sage: L.options._reset() + """ + if self._coeff_stream.is_nonzero(): + return True + if self.parent().options['halting_precision'] is not None: + return bool(self) + return False + def define(self, s): r""" Define an equation by ``self = s``. @@ -1350,6 +1450,24 @@ def define(self, s): sage: (f*s[1]).revert() + 1 - f # optional - sage.combinat O^7 + Undefined series inside of another series (see :issue:`35071`):: + + sage: L. = LazyPowerSeriesRing(QQ) + sage: f = z^2 + sage: b = L.undefined(valuation=1) + sage: b.define(z*f(f(b))) + sage: b + O(z^8) + + sage: L. = LazyPowerSeriesRing(ZZ) + sage: f = L.undefined() + sage: f.define(L(lambda n: 0 if not n else sigma(f[n-1]+1))) + sage: f + x + 3*x^2 + 7*x^3 + 15*x^4 + 31*x^5 + 63*x^6 + O(x^7) + sage: f = L.undefined() + sage: f.define((1/(1-L(lambda n: 0 if not n else sigma(f[n-1]+1))))) + sage: f + 1 + 3*x + 16*x^2 + 87*x^3 + 607*x^4 + 4518*x^5 + 30549*x^6 + O(x^7) """ if not isinstance(self._coeff_stream, Stream_uninitialized) or self._coeff_stream._target is not None: raise ValueError("series already defined") @@ -1396,7 +1514,9 @@ def _repr_(self): sage: L(lambda x: x if x > 0 else 0, valuation=-10) O(z^-3) - sage: L.undefined(valuation=0) + sage: s = L.undefined(valuation=0); s + Uninitialized Lazy Laurent Series + sage: (s + s^2).map_coefficients(lambda f: f % 3) Uninitialized Lazy Laurent Series sage: L(0) 0 @@ -1410,7 +1530,7 @@ def _repr_(self): """ if isinstance(self._coeff_stream, Stream_zero): return '0' - if isinstance(self._coeff_stream, Stream_uninitialized) and self._coeff_stream._target is None: + if self._coeff_stream.is_undefined(): return 'Uninitialized Lazy Laurent Series' return self._format_series(repr) @@ -1443,7 +1563,10 @@ def _latex_(self): sage: latex(L(lambda x: x if x > 0 else 0, valuation=-10)) O(\frac{1}{z^{3}}) - sage: latex(L.undefined(valuation=0)) + sage: s = L.undefined(valuation=0) + sage: latex(s) + \text{\texttt{Undef}} + sage: latex((s + s^2).map_coefficients(lambda f: f % 3)) \text{\texttt{Undef}} sage: latex(L(0)) 0 @@ -1460,7 +1583,7 @@ def _latex_(self): from sage.misc.latex import latex if isinstance(self._coeff_stream, Stream_zero): return latex('0') - if isinstance(self._coeff_stream, Stream_uninitialized) and self._coeff_stream._target is None: + if self._coeff_stream.is_undefined(): return latex("Undef") return self._format_series(latex) @@ -1784,9 +1907,17 @@ def _acted_upon_(self, scalar, self_on_left): Different scalars potentially give different series:: sage: 2 * M == 3 * M - Traceback (most recent call last): - ... - ValueError: undecidable + False + + sage: L.options.use_unknown = True + sage: 2 * M == 3 * M + Unknown + + sage: L.options.halting_precision = 30 + sage: 2 * M == 3 * M + False + + sage: L.options._reset() Sparse series can be multiplied with a scalar:: @@ -3196,8 +3327,28 @@ def _div_(self, other): sage: f / f s[] + Dividing when the coefficient ring is a lazy Dirichlet ring:: + + sage: D = LazyDirichletSeriesRing(QQ, "s") + sage: zeta = D(constant=1) + sage: L. = LazyLaurentSeriesRing(D) + sage: 1 / (1 - t*zeta) + (1 + O(1/(8^s))) + + (1 + 1/(2^s) + 1/(3^s) + 1/(4^s) + 1/(5^s) + 1/(6^s) + 1/(7^s) + O(1/(8^s)))*t + + ... + O(t^7) + + Check for dividing by other type of `0` series:: + + sage: L. = LazyPowerSeriesRing(QQ) + sage: f = L(lambda n: 0, valuation=0) + sage: L.options.halting_precision = 20 + sage: 1 / f + Traceback (most recent call last): + ... + ZeroDivisionError: cannot divide by 0 + sage: L.options._reset() """ - if isinstance(other._coeff_stream, Stream_zero): + if not other: raise ZeroDivisionError("cannot divide by 0") P = self.parent() diff --git a/src/sage/rings/lazy_series_ring.py b/src/sage/rings/lazy_series_ring.py index 32545f65574..6804ccb211e 100644 --- a/src/sage/rings/lazy_series_ring.py +++ b/src/sage/rings/lazy_series_ring.py @@ -19,6 +19,21 @@ :class:`sage.rings.padics.generic_nodes.pAdicRelaxedGeneric`, :func:`sage.rings.padics.factory.ZpER` +.. WARNING:: + + When the halting precision is infinite, the default for ``bool(f)`` + is ``True`` for any lazy series ``f`` that is not known to be zero. + This could end up resulting in infinite loops:: + + sage: L. = LazyPowerSeriesRing(ZZ) + sage: f = L(lambda n: 0, valuation=0) + sage: 1 / f # not tested - infinite loop + +.. SEEALSO:: + + The examples of :class:`LazyLaurentSeriesRing` contain a discussion + about the different methods of comparisons the lazy series can use. + AUTHORS: - Kwankyu Lee (2019-02-24): initial version @@ -488,7 +503,7 @@ def _element_constructor_(self, x=None, valuation=None, degree=None, constant=No if valuation is None: raise ValueError("you must specify the degree for the polynomial 0") degree = valuation - if x == R.zero(): + if not x: coeff_stream = Stream_exact([], order=degree, constant=constant) return self.element_class(self, coeff_stream) initial_coefficients = [x[i] for i in range(x.valuation(), x.degree() + 1)] @@ -661,6 +676,7 @@ class options(GlobalOptions): - constant_length: 3 - display_length: 7 - halting_precision: None + - use_unknown: False sage: LLS.options.display_length 7 @@ -694,8 +710,11 @@ class options(GlobalOptions): description='the number of coefficients to display for nonzero constant series', checker=lambda x: x in ZZ and x > 0) halting_precision = dict(default=None, - description='the number of coefficients, beginning with the approximate valuation, to check in equality tests', - checker=lambda x: x is None or x in ZZ and x > 0) + description='the number of coefficients, beginning with the approximate valuation, to check in equality tests', + checker=lambda x: x is None or x in ZZ and x > 0) + use_unknown = dict(default=False, + description='whether to raise an error when a comparison is unknown', + checker=lambda x: x is True or x is False) @cached_method def one(self): @@ -1139,36 +1158,98 @@ class LazyLaurentSeriesRing(LazySeriesRing): sage: s 1 + z + 2*z^2 + 5*z^3 + 14*z^4 + 42*z^5 + 132*z^6 + O(z^7) - If the series is not specified by a finite number of initial - coefficients and a constant for the remaining coefficients, then - equality checking will depend on the coefficients which have - already been computed. If this information is not enough to - check that two series are different we raise an error:: + By default, any two series ``f`` and ``g`` that are not known to + be equal are considered to be different:: + + sage: f = L(lambda n: 0, valuation=0) + sage: f == 0 + False + + .. WARNING:: + + We have imposed that ``(f == g) == not (f != g)``, and so + ``f != g`` returning ``True`` might not mean that the two + series are actually different:: + + sage: g = L.zero() + sage: f != g + True + + This can be verified by :meth:`~sage.rings.lazy_series.is_nonzero()`, + which only returns ``True`` if the series is known to be nonzero:: + + sage: (f - g).is_nonzero() + False + + The implementation of the ring can be either be a sparse or a dense one. + The default is a sparse implementation:: + sage: L. = LazyLaurentSeriesRing(ZZ) + sage: L.is_sparse() + True + sage: L. = LazyLaurentSeriesRing(ZZ, sparse=False) + sage: L.is_sparse() + False + + We additionally provide two other methods of performing comparisons. + The first is returning an :class:`Unknown` and the second uses a check + up to a (user set) finite precision. These behaviors are set using the + options ``use_unknown`` and ``halting_precision``. In particular, + this applies to series that are not specified by a finite number + of initial coefficients and a constant for the remaining coefficients. + Equality checking will depend on the coefficients which have + already been computed. If this information is not enough to + check that two series are different, then if ``L.options.use_unknown`` + is set to ``True``, then we return an :class:`Unknown`:: + + sage: L.options.use_unknown = True sage: f = 1 / (z + z^2); f z^-1 - 1 + z - z^2 + z^3 - z^4 + z^5 + O(z^6) sage: f2 = f * 2 # currently no coefficients computed sage: f3 = f * 3 # currently no coefficients computed sage: f2 == f3 - Traceback (most recent call last): - ... - ValueError: undecidable + Unknown sage: f2 # computes some of the coefficients of f2 2*z^-1 - 2 + 2*z - 2*z^2 + 2*z^3 - 2*z^4 + 2*z^5 + O(z^6) sage: f3 # computes some of the coefficients of f3 3*z^-1 - 3 + 3*z - 3*z^2 + 3*z^3 - 3*z^4 + 3*z^5 + O(z^6) sage: f2 == f3 False + sage: f2a = f + f + sage: f2 == f2a + Unknown + sage: zf = L(lambda n: 0, valuation=0) + sage: zf == 0 + Unknown - The implementation of the ring can be either be a sparse or a dense one. - The default is a sparse implementation:: + For boolean checks, an error is raised when it is not known to be nonzero:: - sage: L. = LazyLaurentSeriesRing(ZZ) - sage: L.is_sparse() - True - sage: L. = LazyLaurentSeriesRing(ZZ, sparse=False) - sage: L.is_sparse() + sage: bool(zf) + Traceback (most recent call last): + ... + UnknownError: undecidable + + If the halting precision is set to a finite number `p` (for unlimited + precision, it is set to ``None``), then it will check up to `p` values + from the current position:: + + sage: L.options.halting_precision = 20 + sage: f2 = f * 2 # currently no coefficients computed + sage: f3 = f * 3 # currently no coefficients computed + sage: f2 == f3 False + sage: f2a = f + f + sage: f2 == f2a + True + sage: zf = L(lambda n: 0, valuation=0) + sage: zf == 0 + True + + TESTS: + + We reset the options:: + + sage: L.options._reset() """ Element = LazyLaurentSeries From 534ba6086c613253a03ea5c741ce982eb479ddb1 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Wed, 12 Apr 2023 17:48:42 +0900 Subject: [PATCH 09/93] Alternative proposal returning None for unknown comparisons. --- src/sage/data_structures/stream.py | 2 +- src/sage/rings/lazy_series.py | 36 ++++++++++++++++-------------- src/sage/rings/lazy_series_ring.py | 26 ++++++++++----------- 3 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/sage/data_structures/stream.py b/src/sage/data_structures/stream.py index 735398cbcca..b35c865d060 100644 --- a/src/sage/data_structures/stream.py +++ b/src/sage/data_structures/stream.py @@ -665,7 +665,7 @@ def __init__(self, initial_coefficients, constant=None, degree=None, order=None) if order + len(initial_coefficients) == self._degree: # Strip off the constant values at the end for w in reversed(initial_coefficients): - if w != self._constant: + if not (w == self._constant): break initial_coefficients.pop() self._degree -= 1 diff --git a/src/sage/rings/lazy_series.py b/src/sage/rings/lazy_series.py index a43e9697332..f5f526dbb06 100644 --- a/src/sage/rings/lazy_series.py +++ b/src/sage/rings/lazy_series.py @@ -938,21 +938,21 @@ def _richcmp_(self, other, op): False sage: fz = L(lambda n: 0, valuation=0) - sage: L.zero() == fz - False - sage: fz == L.zero() - False + sage: (L.zero() == fz) is None + True + sage: (fz == L.zero()) is None + True With using :class:`Unknown`:: sage: L.options.use_unknown = True sage: fz = L(lambda n: 0, valuation=0) - sage: L.zero() == fz - Unknown - sage: fz == L.zero() - Unknown - sage: fz != L.zero() - Unknown + sage: (L.zero() == fz) is None + True + sage: (fz == L.zero()) is None + True + sage: (fz != L.zero()) is None + True With using finite halting precision:: @@ -1008,7 +1008,8 @@ def _richcmp_(self, other, op): # undecidable otherwise prec = self.parent().options['halting_precision'] if prec is None: - return Unknown + return None + #return Unknown # raise UnknownError("undecidable") # at least one of the approximate orders is not infinity m = min(self._coeff_stream._approximate_order, @@ -1017,7 +1018,7 @@ def _richcmp_(self, other, op): if op is op_NE: ret = (self == other) - if ret is Unknown: + if ret is None: return ret return not ret @@ -1155,7 +1156,8 @@ def __bool__(self): return True if prec is None: - raise UnknownError("undecidable") + return True + #raise UnknownError("undecidable") v = self._coeff_stream._approximate_order return any(self[i] for i in range(v, v + prec)) @@ -1906,12 +1908,12 @@ def _acted_upon_(self, scalar, self_on_left): Different scalars potentially give different series:: - sage: 2 * M == 3 * M - False + sage: (2 * M == 3 * M) is None + True sage: L.options.use_unknown = True - sage: 2 * M == 3 * M - Unknown + sage: (2 * M == 3 * M) is None + True sage: L.options.halting_precision = 30 sage: 2 * M == 3 * M diff --git a/src/sage/rings/lazy_series_ring.py b/src/sage/rings/lazy_series_ring.py index 6804ccb211e..c5350cde77e 100644 --- a/src/sage/rings/lazy_series_ring.py +++ b/src/sage/rings/lazy_series_ring.py @@ -676,7 +676,7 @@ class options(GlobalOptions): - constant_length: 3 - display_length: 7 - halting_precision: None - - use_unknown: False + - use_unknown: True sage: LLS.options.display_length 7 @@ -712,7 +712,7 @@ class options(GlobalOptions): halting_precision = dict(default=None, description='the number of coefficients, beginning with the approximate valuation, to check in equality tests', checker=lambda x: x is None or x in ZZ and x > 0) - use_unknown = dict(default=False, + use_unknown = dict(default=True, description='whether to raise an error when a comparison is unknown', checker=lambda x: x is True or x is False) @@ -1162,8 +1162,8 @@ class LazyLaurentSeriesRing(LazySeriesRing): be equal are considered to be different:: sage: f = L(lambda n: 0, valuation=0) - sage: f == 0 - False + sage: (f == 0) is None + True .. WARNING:: @@ -1172,7 +1172,7 @@ class LazyLaurentSeriesRing(LazySeriesRing): series are actually different:: sage: g = L.zero() - sage: f != g + sage: (f != g) is None True This can be verified by :meth:`~sage.rings.lazy_series.is_nonzero()`, @@ -1207,8 +1207,8 @@ class LazyLaurentSeriesRing(LazySeriesRing): z^-1 - 1 + z - z^2 + z^3 - z^4 + z^5 + O(z^6) sage: f2 = f * 2 # currently no coefficients computed sage: f3 = f * 3 # currently no coefficients computed - sage: f2 == f3 - Unknown + sage: (f2 == f3) is None + True sage: f2 # computes some of the coefficients of f2 2*z^-1 - 2 + 2*z - 2*z^2 + 2*z^3 - 2*z^4 + 2*z^5 + O(z^6) sage: f3 # computes some of the coefficients of f3 @@ -1216,18 +1216,16 @@ class LazyLaurentSeriesRing(LazySeriesRing): sage: f2 == f3 False sage: f2a = f + f - sage: f2 == f2a - Unknown + sage: (f2 == f2a) is None + True sage: zf = L(lambda n: 0, valuation=0) - sage: zf == 0 - Unknown + sage: (zf == 0) is None + True For boolean checks, an error is raised when it is not known to be nonzero:: sage: bool(zf) - Traceback (most recent call last): - ... - UnknownError: undecidable + True If the halting precision is set to a finite number `p` (for unlimited precision, it is set to ``None``), then it will check up to `p` values From e985124a38bdff7d0dd464f9699369235e9e264e Mon Sep 17 00:00:00 2001 From: Martin Rubey Date: Sun, 20 Aug 2023 17:50:22 +0200 Subject: [PATCH 10/93] unify docstrings and uncontroversial doctests from #35480 and #35485 --- src/sage/data_structures/stream.py | 65 ++++++++++++++++----------- src/sage/rings/lazy_series.py | 71 ++++++++++++++++++++++++------ src/sage/rings/lazy_series_ring.py | 6 +-- 3 files changed, 99 insertions(+), 43 deletions(-) diff --git a/src/sage/data_structures/stream.py b/src/sage/data_structures/stream.py index b35c865d060..641f330a5ba 100644 --- a/src/sage/data_structures/stream.py +++ b/src/sage/data_structures/stream.py @@ -186,7 +186,7 @@ def __ne__(self, other): def is_nonzero(self): r""" Return ``True`` if and only if this stream is known - to be nonzero. + to be non-zero. The default implementation is ``False``. @@ -243,7 +243,7 @@ def __init__(self, is_sparse, true_order): def is_nonzero(self): r""" - Return ``True`` if and only if the cache contains a nonzero element. + Return ``True`` if and only if the cache contains a non-zero element. EXAMPLES:: @@ -332,7 +332,7 @@ def __setstate__(self, d): def __getitem__(self, n): """ - Return the `n`-th coefficient of ``self``. + Return the ``n``-th coefficient of ``self``. INPUT: @@ -433,7 +433,7 @@ def iterate_coefficients(self): def order(self): r""" Return the order of ``self``, which is the minimum index ``n`` such - that ``self[n]`` is nonzero. + that ``self[n]`` is non-zero. EXAMPLES:: @@ -659,7 +659,7 @@ def __init__(self, initial_coefficients, constant=None, degree=None, order=None) # complicated otherwise for i, v in enumerate(initial_coefficients): if v: - # We have found the first nonzero coefficient + # We have found the first non-zero coefficient order += i initial_coefficients = initial_coefficients[i:] if order + len(initial_coefficients) == self._degree: @@ -738,7 +738,7 @@ def __getitem__(self, n): def order(self): r""" Return the order of ``self``, which is the minimum index - ``n`` such that ``self[n]`` is nonzero. + ``n`` such that ``self[n]`` is non-zero. EXAMPLES:: @@ -869,9 +869,9 @@ def __ne__(self, other): def is_nonzero(self): r""" Return ``True`` if and only if this stream is known - to be nonzero. + to be non-zero. - An assumption of this class is that it is nonzero. + An assumption of this class is that it is non-zero. EXAMPLES:: @@ -1578,7 +1578,7 @@ def get_coefficient(self, n): def is_nonzero(self): r""" Return ``True`` if and only if this stream is known - to be nonzero. + to be non-zero. EXAMPLES:: @@ -1596,6 +1596,14 @@ def is_nonzero(self): return self._left.is_nonzero() and self._right.is_nonzero() +class Stream_cauchy_mul_commutative(Stream_cauchy_mul, Stream_binaryCommutative): + """ + Operator for multiplication of two coefficient streams using the + Cauchy product for commutative multiplication of coefficients. + """ + pass + + class Stream_dirichlet_convolve(Stream_binary): r""" Operator for the Dirichlet convolution of two streams. @@ -1644,7 +1652,7 @@ def _approximate_order(self): or self._right._approximate_order <= 0): raise ValueError("Dirichlet convolution is only defined for " "coefficient streams with minimal index of " - "nonzero coefficient at least 1") + "non-zero coefficient at least 1") return self._left._approximate_order * self._right._approximate_order def get_coefficient(self, n): @@ -2236,6 +2244,11 @@ class Stream_scalar(Stream_inexact): Base class for operators multiplying a coefficient stream by a scalar. + INPUT: + + - ``series`` -- a :class:`Stream` + - ``scalar`` -- a non-zero, non-one scalar + .. TODO:: This does not inherit from :class:`Stream_unary`, because of @@ -2322,7 +2335,7 @@ def __eq__(self, other): def is_nonzero(self): r""" Return ``True`` if and only if this stream is known - to be nonzero. + to be non-zero. EXAMPLES:: @@ -2355,7 +2368,7 @@ class Stream_rmul(Stream_scalar): INPUT: - ``series`` -- a :class:`Stream` - - ``scalar`` -- a non-zero scalar + - ``scalar`` -- a non-zero, non-one scalar EXAMPLES:: @@ -2397,7 +2410,7 @@ class Stream_lmul(Stream_scalar): INPUT: - ``series`` -- a :class:`Stream` - - ``scalar`` -- a non-zero scalar + - ``scalar`` -- a non-zero, non-one scalar EXAMPLES:: @@ -2504,7 +2517,7 @@ def get_coefficient(self, n): def is_nonzero(self): r""" Return ``True`` if and only if this stream is known - to be nonzero. + to be non-zero. EXAMPLES:: @@ -2643,9 +2656,9 @@ def iterate_coefficients(self): def is_nonzero(self): r""" Return ``True`` if and only if this stream is known - to be nonzero. + to be non-zero. - An assumption of this class is that it is nonzero. + An assumption of this class is that it is non-zero. EXAMPLES:: @@ -2660,7 +2673,7 @@ def is_nonzero(self): class Stream_map_coefficients(Stream_inexact): r""" - The stream with ``function`` applied to each nonzero coefficient + The stream with ``function`` applied to each non-zero coefficient of ``series``. INPUT: @@ -2787,7 +2800,7 @@ def is_undefined(self): class Stream_shift(Stream): """ - Operator for shifting a nonzero, nonexact stream. + Operator for shifting a non-zero, non-exact stream. Instances of this class share the cache with its input stream. @@ -2833,7 +2846,7 @@ def _approximate_order(self): def order(self): r""" Return the order of ``self``, which is the minimum index - ``n`` such that ``self[n]`` is nonzero. + ``n`` such that ``self[n]`` is non-zero. EXAMPLES:: @@ -2903,9 +2916,9 @@ def __eq__(self, other): def is_nonzero(self): r""" Return ``True`` if and only if this stream is known - to be nonzero. + to be non-zero. - An assumption of this class is that it is nonzero. + An assumption of this class is that it is non-zero. EXAMPLES:: @@ -2925,7 +2938,7 @@ def is_undefined(self): class Stream_truncated(Stream_inexact): """ - Operator for shifting a nonzero, nonexact stream that has + Operator for shifting a non-zero, non-exact stream that has been shifted below its minimal valuation. Instances of this class share the cache with its input stream. @@ -3086,7 +3099,7 @@ def __eq__(self, other): def order(self): """ Return the order of ``self``, which is the minimum index ``n`` such - that ``self[n]`` is nonzero. + that ``self[n]`` is non-zero. EXAMPLES:: @@ -3132,7 +3145,7 @@ def order(self): def is_nonzero(self): r""" Return ``True`` if and only if this stream is known - to be nonzero. + to be non-zero. EXAMPLES:: @@ -3180,7 +3193,7 @@ def is_undefined(self): class Stream_derivative(Stream_inexact): """ - Operator for taking derivatives of a stream. + Operator for taking derivatives of a non-exact stream. INPUT: @@ -3293,7 +3306,7 @@ def __eq__(self, other): def is_nonzero(self): r""" Return ``True`` if and only if this stream is known - to be nonzero. + to be non-zero. EXAMPLES:: diff --git a/src/sage/rings/lazy_series.py b/src/sage/rings/lazy_series.py index f5f526dbb06..130de96db03 100644 --- a/src/sage/rings/lazy_series.py +++ b/src/sage/rings/lazy_series.py @@ -196,6 +196,19 @@ sage: L = LazySymmetricFunctions(s) # optional - sage.combinat sage.rings.finite_rings sage: check(L, lambda n: sum(k*s(la) for k, la in enumerate(Partitions(n))), # optional - sage.combinat sage.rings.finite_rings ....: valuation=0) + +Check that we can invert matrices:: + + sage: L. = LazyLaurentSeriesRing(QQ) + sage: a11 = 1 + L(lambda n: 1 if not n else 0, valuation=0) + sage: a12 = 1 + L(lambda n: 1 if n == 1 else 0, valuation=0) + sage: a21 = 1 + L(lambda n: 1 if n == 2 else 0, valuation=0) + sage: a22 = 1 + L(lambda n: 1 if n == 3 else 0, valuation=0) + sage: m = matrix([[a11, a12], [a21, a22]]) + sage: m.inverse() + [ 1 + z + 2*z^2 + 3*z^3 + 4*z^4 + 5*z^5 + 6*z^6 + O(z^7) -1 - 2*z - 3*z^2 - 4*z^3 - 5*z^4 - 6*z^5 - 7*z^6 + O(z^7)] + [ -1 - z - 3*z^2 - 3*z^3 - 5*z^4 - 5*z^5 - 7*z^6 + O(z^7) 2 + 2*z + 4*z^2 + 4*z^3 + 6*z^4 + 6*z^5 + 8*z^6 + O(z^7)] + """ # **************************************************************************** @@ -219,6 +232,7 @@ from sage.combinat.partition import Partition, Partitions from sage.misc.derivative import derivative_parse from sage.categories.integral_domains import IntegralDomains +from sage.categories.rings import Rings from sage.rings.infinity import infinity from sage.rings.integer_ring import ZZ from sage.rings.rational_field import QQ @@ -228,6 +242,7 @@ from sage.data_structures.stream import ( Stream_add, Stream_cauchy_mul, + Stream_cauchy_mul_commutative, Stream_sub, Stream_cauchy_compose, Stream_lmul, @@ -1062,9 +1077,9 @@ def __bool__(self): False sage: M = L(lambda n: 2*n if n < 10 else 1, valuation=0); M # optional - sage.rings.finite_rings O(z^7) - sage: bool(M) + sage: bool(M) # optional - sage.rings.finite_rings True - sage: M[15] + sage: M[15] # optional - sage.rings.finite_rings 1 sage: bool(M) # optional - sage.rings.finite_rings True @@ -1072,9 +1087,9 @@ def __bool__(self): sage: L. = LazyLaurentSeriesRing(GF(2), sparse=True) # optional - sage.rings.finite_rings sage: M = L(lambda n: 2*n if n < 10 else 1, valuation=0); M # optional - sage.rings.finite_rings O(z^7) - sage: bool(M) + sage: bool(M) # optional - sage.rings.finite_rings True - sage: M[15] + sage: M[15] # optional - sage.rings.finite_rings 1 sage: bool(M) # optional - sage.rings.finite_rings True @@ -1227,7 +1242,7 @@ def define(self, s): sage: binomial(2000, 1000) / C[1000] 1001 - The Catalan numbers but with a valuation 1:: + The Catalan numbers but with a valuation `1`:: sage: B = L.undefined(valuation=1) sage: B.define(z + B^2) @@ -1990,6 +2005,19 @@ def _acted_upon_(self, scalar, self_on_left): sage: f = L(constant=2) sage: 2*f 0 + + Check that non-commutativity is taken into account:: + + sage: M = MatrixSpace(ZZ, 2) + sage: L. = LazyPowerSeriesRing(M) + sage: f = L(lambda n: matrix([[1,n],[0,1]])) + sage: m = matrix([[1,0],[1,1]]) + sage: (m * f - f * m)[1] + [-1 0] + [ 0 1] + sage: m * f[1] - f[1] * m + [-1 0] + [ 0 1] """ # With the current design, the coercion model does not have # enough information to detect a priori that this method only @@ -2030,7 +2058,7 @@ def _acted_upon_(self, scalar, self_on_left): order=v, constant=c, degree=coeff_stream._degree)) - if self_on_left or R.is_commutative(): + if self_on_left or R in Rings().Commutative(): return P.element_class(P, Stream_lmul(coeff_stream, scalar, P.is_sparse())) return P.element_class(P, Stream_rmul(coeff_stream, scalar, @@ -2996,6 +3024,9 @@ def _mul_(self, other): and right.order() == 0 and not right._constant): return self # right == 1 + if ((isinstance(left, Stream_cauchy_invert) and left._series == right) + or (isinstance(right, Stream_cauchy_invert) and right._series == left)): + return P.one() # The product is exact if and only if both factors are exact # and one of the factors has eventually 0 coefficients: # (p + a x^d/(1-x))(q + b x^e/(1-x)) @@ -3043,7 +3074,11 @@ def _mul_(self, other): constant=c) return P.element_class(P, coeff_stream) - return P.element_class(P, Stream_cauchy_mul(left, right, P.is_sparse())) + if P in Rings().Commutative(): + coeff_stream = Stream_cauchy_mul_commutative(left, right, P.is_sparse()) + else: + coeff_stream = Stream_cauchy_mul(left, right, P.is_sparse()) + return P.element_class(P, coeff_stream) def __pow__(self, n): r""" @@ -3185,7 +3220,7 @@ def __invert__(self): sage: g = L([2], valuation=-1, constant=1); g 2*x^-1 + 1 + x + x^2 + O(x^3) sage: g * g^-1 - 1 + O(x^7) + 1 sage: L. = LazyPowerSeriesRing(QQ) sage: ~(x + x^2) @@ -3368,7 +3403,7 @@ def _div_(self, other): return self # self is right - if left is right: + if left == right: return P.one() if (P._minimal_valuation is not None @@ -3443,7 +3478,11 @@ def _div_(self, other): # P._minimal_valuation is zero, because we allow division by # series of positive valuation right_inverse = Stream_cauchy_invert(right) - return P.element_class(P, Stream_cauchy_mul(left, right_inverse, P.is_sparse())) + if P in Rings().Commutative(): + coeff_stream = Stream_cauchy_mul_commutative(left, right_inverse, P.is_sparse()) + else: + coeff_stream = Stream_cauchy_mul(left, right_inverse, P.is_sparse()) + return P.element_class(P, coeff_stream) def _floordiv_(self, other): r""" @@ -3534,7 +3573,9 @@ def exp(self): d_self = Stream_function(lambda n: (n + 1) * coeff_stream[n + 1], False, 0) f = P.undefined(valuation=0) - d_self_f = Stream_cauchy_mul(d_self, f._coeff_stream, False) + # d_self and f._coeff_stream always commute, the coefficients + # of the product are of the form sum_{k=1}^n a_k a_{n+1-k}. + d_self_f = Stream_cauchy_mul_commutative(d_self, f._coeff_stream, False) int_d_self_f = Stream_function(lambda n: d_self_f[n-1] / R(n) if n else R.one(), False, 0) f._coeff_stream._target = int_d_self_f @@ -3583,9 +3624,11 @@ def log(self): # multivariate power series d_self = Stream_function(lambda n: (n + 1) * coeff_stream[n + 1], P.is_sparse(), 0) - d_self_quo_self = Stream_cauchy_mul(d_self, - Stream_cauchy_invert(coeff_stream), - P.is_sparse()) + coeff_stream_inverse = Stream_cauchy_invert(coeff_stream) + # d_self and coeff_stream_inverse always commute + d_self_quo_self = Stream_cauchy_mul_commutative(d_self, + coeff_stream_inverse, + P.is_sparse()) int_d_self_quo_self = Stream_function(lambda n: d_self_quo_self[n-1] / R(n), P.is_sparse(), 1) return P.element_class(P, int_d_self_quo_self) diff --git a/src/sage/rings/lazy_series_ring.py b/src/sage/rings/lazy_series_ring.py index c5350cde77e..aebe887ae58 100644 --- a/src/sage/rings/lazy_series_ring.py +++ b/src/sage/rings/lazy_series_ring.py @@ -2398,10 +2398,10 @@ def __init__(self, basis, sparse=True, category=None): if basis not in GradedAlgebrasWithBasis: raise ValueError("basis should be in GradedAlgebrasWithBasis") self._arity = 1 - category = Algebras(base_ring.category()) - if base_ring in IntegralDomains(): + category = Algebras(basis.category()) + if basis in IntegralDomains(): category &= IntegralDomains() - elif base_ring in Rings().Commutative(): + elif basis in Rings().Commutative(): category = category.Commutative() if base_ring.is_zero(): From c65b3e35a96042f9ce6e9167852e88d2d71aedf0 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 2 Sep 2023 21:38:04 -0700 Subject: [PATCH 11/93] build/pkgs/scipy/patches/cython3-legacy.patch: Remove --- build/pkgs/scipy/patches/cython3-legacy.patch | 91 ------------------- 1 file changed, 91 deletions(-) delete mode 100644 build/pkgs/scipy/patches/cython3-legacy.patch diff --git a/build/pkgs/scipy/patches/cython3-legacy.patch b/build/pkgs/scipy/patches/cython3-legacy.patch deleted file mode 100644 index 9abf0c02154..00000000000 --- a/build/pkgs/scipy/patches/cython3-legacy.patch +++ /dev/null @@ -1,91 +0,0 @@ -diff --git a/scipy/linalg.pxd b/scipy/linalg.pxd -index 1f656b87..c7c49f9a 100644 ---- a/scipy/linalg.pxd -+++ b/scipy/linalg.pxd -@@ -1 +1 @@ --from .linalg cimport cython_blas, cython_lapack -+from scipy.linalg cimport cython_blas, cython_lapack -diff --git a/scipy/meson.build b/scipy/meson.build -index 21ea04d5..71d54804 100644 ---- a/scipy/meson.build -+++ b/scipy/meson.build -@@ -197,7 +197,7 @@ _cython_tree = [ - fs.copyfile('special.pxd'), - ] - --cython_args = ['-3', '--fast-fail', '--output-file', '@OUTPUT@', '--include-dir', '@BUILD_ROOT@', '@INPUT@'] -+cython_args = ['-3', '--fast-fail', '--directive', 'legacy_implicit_noexcept=True', '--output-file', '@OUTPUT@', '--include-dir', '@BUILD_ROOT@', '@INPUT@'] - cython_cplus_args = ['--cplus'] + cython_args - - cython_gen = generator(cython, -diff --git a/scipy/optimize/cython_optimize.pxd b/scipy/optimize/cython_optimize.pxd -index d5a0bdd7..d35f8da6 100644 ---- a/scipy/optimize/cython_optimize.pxd -+++ b/scipy/optimize/cython_optimize.pxd -@@ -7,5 +7,5 @@ - # support. Changing it causes an ABI forward-compatibility break - # (gh-11793), so we currently leave it as is (no further cimport - # statements should be used in this file). --from .cython_optimize._zeros cimport ( -+from scipy.optimize.cython_optimize._zeros cimport ( - brentq, brenth, ridder, bisect, zeros_full_output) -diff --git a/scipy/optimize/meson.build b/scipy/optimize/meson.build -index 05db6a68..07d46fb9 100644 ---- a/scipy/optimize/meson.build -+++ b/scipy/optimize/meson.build -@@ -231,6 +231,10 @@ endif - - _dummy_init_optimize = fs.copyfile('__init__.py') - -+_cython_tree = [ -+ fs.copyfile('cython_optimize.pxd'), -+] -+ - opt_gen = generator(cython, - arguments : cython_args, - output : '@BASENAME@.c', -diff --git a/scipy/special.pxd b/scipy/special.pxd -index 62cb8280..1daa9fb3 100644 ---- a/scipy/special.pxd -+++ b/scipy/special.pxd -@@ -1 +1 @@ --from .special cimport cython_special -+from scipy.special cimport cython_special -diff --git a/scipy/special/meson.build b/scipy/special/meson.build -index f92183f5..09ad0a4f 100644 ---- a/scipy/special/meson.build -+++ b/scipy/special/meson.build -@@ -362,7 +362,7 @@ py3.extension_module('_ufuncs_cxx', - [ufuncs_cxx_sources, - uf_cython_gen_cpp.process(cython_special[2]), # _ufuncs_cxx.pyx - ], -- cpp_args: cython_cpp_args, -+ cpp_args: [cython_cpp_args, '-DCYTHON_EXTERN_C=extern "C"'], - include_directories: [inc_np, '../_lib/boost', '../_lib', - '../_build_utils/src'], - link_args: version_link_args, -diff --git a/scipy/special/setup.py b/scipy/special/setup.py -index 7e8c9608..b38a6ec2 100644 ---- a/scipy/special/setup.py -+++ b/scipy/special/setup.py -@@ -103,7 +103,7 @@ def configuration(parent_package='',top_path=None): - sources=ufuncs_cxx_src, - depends=ufuncs_cxx_dep, - include_dirs=[curdir] + inc_dirs, -- define_macros=define_macros, -+ define_macros=define_macros + [('CYTHON_EXTERN_C', 'extern "C"')], - extra_info=get_info("npymath")) - ufuncs_cxx_ext._pre_build_hook = set_cxx_flags_hook - -diff --git a/tools/cythonize.py b/tools/cythonize.py -index 402824cb..7ad778da 100755 ---- a/tools/cythonize.py -+++ b/tools/cythonize.py -@@ -94,6 +94,7 @@ def process_pyx(fromfile, tofile, cwd): - flags = ['--fast-fail', '-3'] - if tofile.endswith('.cxx'): - flags += ['--cplus'] -+ flags += ['--directive', 'legacy_implicit_noexcept=true'] - - try: - try: From 84ad1a944b36173f050b6a3dd46c84269c31ed82 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 6 Sep 2023 16:04:37 -0700 Subject: [PATCH 12/93] build/pkgs/cython/dependencies: Add pythran as an order-only dep --- build/pkgs/cython/dependencies | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/pkgs/cython/dependencies b/build/pkgs/cython/dependencies index 0738c2d7777..bda9b4d2579 100644 --- a/build/pkgs/cython/dependencies +++ b/build/pkgs/cython/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) +$(PYTHON) | $(PYTHON_TOOLCHAIN) pythran ---------- All lines of this file are ignored except the first. From 789f23f445a14f1b0927b0d41f68d20720cfd398 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Wed, 12 Apr 2023 17:23:13 +0900 Subject: [PATCH 13/93] Removing redundant comparisons, renaming error comparisons (following padics), adding is_unitialized() doctests. --- src/sage/data_structures/stream.py | 172 ++++++++++++++++++++++----- src/sage/rings/lazy_series.py | 182 +++++++++++++++++------------ src/sage/rings/lazy_series_ring.py | 54 ++++++--- 3 files changed, 282 insertions(+), 126 deletions(-) diff --git a/src/sage/data_structures/stream.py b/src/sage/data_structures/stream.py index 641f330a5ba..7038ce2149c 100644 --- a/src/sage/data_structures/stream.py +++ b/src/sage/data_structures/stream.py @@ -199,9 +199,21 @@ def is_nonzero(self): """ return False - def is_undefined(self): + def is_trivially_ne(self, other): """ - Return ``True`` if ``self`` is an undefined stream. + Return if ``self`` is trivially not equal to ``other``. + + The default implementation is ``False``. + + .. NOTE:: + + This does not check that the streams are equal. + """ + return False + + def is_uninitialized(self): + """ + Return ``True`` if ``self`` is an uninitialized stream. """ return False @@ -542,7 +554,10 @@ def __ne__(self, other): # TODO: more cases, in particular mixed implementations, # could be detected if not isinstance(other, Stream_inexact): - return False + return (other != self) + + if self.is_uninitialized() != other.is_uninitialized(): + return True if self._is_sparse and other._is_sparse: for i in self._cache: @@ -746,7 +761,6 @@ def order(self): sage: s = Stream_exact([1]) sage: s.order() 0 - """ return self._approximate_order @@ -843,13 +857,17 @@ def __ne__(self, other): [0, 0, 0, 2, 1, 1, 1, 1] sage: [f[i] for i in range(-3, 5)] [0, 0, 0, 2, 1, 1, 1, 1] - """ if isinstance(other, type(self)): return (self._degree != other._degree or self._approximate_order != other._approximate_order or self._initial_coefficients != other._initial_coefficients or self._constant != other._constant) + if other.is_uninitialized(): + return True + if isinstance(other, Stream_zero): + # We are assumed to be nonzero + return True # if other is not exact, we can at least compare with the # elements in its cache if other._is_sparse: @@ -1009,7 +1027,6 @@ class Stream_uninitialized(Stream_inexact): sage: C._target = one sage: C[4] 0 - """ def __init__(self, approximate_order, true_order=False): """ @@ -1048,9 +1065,16 @@ def iterate_coefficients(self): yield self._target[n] n += 1 - def is_undefined(self): + def is_uninitialized(self): """ - Return ``True`` if ``self`` is an undefined stream. + Return ``True`` if ``self`` is an uninitialized stream. + + EXAMPLES:: + + sage: from sage.data_structures.stream import Stream_uninitialized + sage: C = Stream_uninitialized(0) + sage: C.is_uninitialized() + True """ return self._target is None @@ -1074,7 +1098,6 @@ class Stream_unary(Stream_inexact): sage: [g[i] for i in range(10)] [0, 4, 8, 12, 16, 20, 24, 28, 32, 36] """ - def __init__(self, series, is_sparse): """ Initialize ``self``. @@ -1130,11 +1153,19 @@ def __eq__(self, other): """ return isinstance(other, type(self)) and self._series == other._series - def is_undefined(self): + def is_uninitialized(self): """ - Return ``True`` if ``self`` is an undefined stream. + Return ``True`` if ``self`` is an uninitialized stream. + + EXAMPLES:: + + sage: from sage.data_structures.stream import Stream_uninitialized, Stream_unary + sage: C = Stream_uninitialized(0) + sage: M = Stream_unary(C, True) + sage: M.is_uninitialized() + True """ - return self._series.is_undefined() + return self._series.is_uninitialized() class Stream_binary(Stream_inexact): @@ -1224,11 +1255,23 @@ def __eq__(self, other): return False return self._left == other._left and self._right == other._right - def is_undefined(self): + def is_uninitialized(self): """ - Return ``True`` if ``self`` is an undefined stream. + Return ``True`` if ``self`` is an uninitialized stream. + + EXAMPLES:: + + sage: from sage.data_structures.stream import Stream_uninitialized, Stream_sub, Stream_function + sage: C = Stream_uninitialized(0) + sage: F = Stream_function(lambda n: n, True, 0) + sage: B = Stream_sub(F, C, True) + sage: B.is_uninitialized() + True + sage: Bp = Stream_sub(F, F, True) + sage: Bp.is_uninitialized() + False """ - return self._left.is_undefined() or self._right.is_undefined() + return self._left.is_uninitialized() or self._right.is_uninitialized() class Stream_binaryCommutative(Stream_binary): @@ -1370,6 +1413,33 @@ def __eq__(self, other): """ return self is other or isinstance(other, Stream_zero) + def __ne__(self, other): + """ + Return whether ``self`` and ``other`` are known to be not equal. + + INPUT: + + - ``other`` -- a stream + + EXAMPLES:: + + sage: from sage.data_structures.stream import Stream_zero, Stream_function + sage: Stream_zero() != Stream_zero() + False + sage: f = Stream_function(lambda n: 2*n, True, 0) + sage: Stream_zero() != f + False + sage: f[0] + 0 + sage: Stream_zero() != f + False + sage: f[1] + 2 + sage: Stream_zero() != f + True + """ + return self is not other and not isinstance(other, Stream_zero) and other.is_nonzero() + def __hash__(self): """ Return the hash of ``self``. @@ -2353,11 +2423,19 @@ def is_nonzero(self): """ return self._series.is_nonzero() - def is_undefined(self): + def is_uninitialized(self): """ - Return ``True`` if ``self`` is an undefined stream. + Return ``True`` if ``self`` is an uninitialized stream. + + EXAMPLES:: + + sage: from sage.data_structures.stream import Stream_uninitialized, Stream_lmul, Stream_function + sage: C = Stream_uninitialized(0) + sage: B = Stream_lmul(C, 2, True) + sage: B.is_uninitialized() + True """ - return self._series.is_undefined() + return self._series.is_uninitialized() class Stream_rmul(Stream_scalar): @@ -2791,11 +2869,19 @@ def __eq__(self, other): return (isinstance(other, type(self)) and self._series == other._series and self._function == other._function) - def is_undefined(self): + def is_uninitialized(self): """ - Return ``True`` if ``self`` is an undefined stream. + Return ``True`` if ``self`` is an uninitialized stream. + + EXAMPLES:: + + sage: from sage.data_structures.stream import Stream_uninitialized, Stream_map_coefficients + sage: C = Stream_uninitialized(0) + sage: M = Stream_map_coefficients(C, lambda n: -n, True) + sage: M.is_uninitialized() + True """ - return self._series.is_undefined() + return self._series.is_uninitialized() class Stream_shift(Stream): @@ -2930,11 +3016,20 @@ def is_nonzero(self): """ return self._series.is_nonzero() - def is_undefined(self): + def is_uninitialized(self): """ - Return ``True`` if ``self`` is an undefined stream. + Return ``True`` if ``self`` is an uninitialized stream. + + EXAMPLES:: + + sage: from sage.data_structures.stream import Stream_uninitialized, Stream_shift + sage: C = Stream_uninitialized(0) + sage: S = Stream_shift(C, 5) + sage: S.is_uninitialized() + True """ - return self._series.is_undefined() + return self._series.is_uninitialized() + class Stream_truncated(Stream_inexact): """ @@ -3184,11 +3279,19 @@ def is_nonzero(self): start = self._approximate_order - offset return any(self._cache[start:]) - def is_undefined(self): + def is_uninitialized(self): """ - Return ``True`` if ``self`` is an undefined stream. + Return ``True`` if ``self`` is an uninitialized stream. + + EXAMPLES:: + + sage: from sage.data_structures.stream import Stream_uninitialized, Stream_truncated + sage: C = Stream_uninitialized(0) + sage: S = Stream_truncated(C, -5, 3) + sage: S.is_uninitialized() + True """ - return self._series.is_undefined() + return self._series.is_uninitialized() class Stream_derivative(Stream_inexact): @@ -3275,7 +3378,6 @@ def __hash__(self): True sage: hash(f) == hash(g) False - """ return hash((type(self), self._series, self._shift)) @@ -3319,8 +3421,16 @@ def is_nonzero(self): """ return self._series.is_nonzero() - def is_undefined(self): + def is_uninitialized(self): """ - Return ``True`` if ``self`` is an undefined stream. + Return ``True`` if ``self`` is an uninitialized stream. + + EXAMPLES:: + + sage: from sage.data_structures.stream import Stream_uninitialized, Stream_derivative + sage: C = Stream_uninitialized(0) + sage: D = Stream_derivative(C, 1, True) + sage: D.is_uninitialized() + True """ - return self._series.is_undefined() + return self._series.is_uninitialized() diff --git a/src/sage/rings/lazy_series.py b/src/sage/rings/lazy_series.py index 130de96db03..50f4e7c5c45 100644 --- a/src/sage/rings/lazy_series.py +++ b/src/sage/rings/lazy_series.py @@ -261,7 +261,6 @@ Stream_dirichlet_invert, Stream_plethysm ) -from sage.misc.unknown import Unknown, UnknownError class LazyModuleElement(Element): @@ -953,23 +952,30 @@ def _richcmp_(self, other, op): False sage: fz = L(lambda n: 0, valuation=0) - sage: (L.zero() == fz) is None - True - sage: (fz == L.zero()) is None - True + sage: L.zero() == fz + False + sage: fz == L.zero() + False - With using :class:`Unknown`:: + With using secure computations:: - sage: L.options.use_unknown = True + sage: L.options.secure = True sage: fz = L(lambda n: 0, valuation=0) - sage: (L.zero() == fz) is None - True - sage: (fz == L.zero()) is None - True - sage: (fz != L.zero()) is None - True + sage: L.zero() == fz + Traceback (most recent call last): + ... + ValueError: undecidable + sage: fz == L.zero() + Traceback (most recent call last): + ... + ValueError: undecidable + sage: fz != L.zero() + Traceback (most recent call last): + ... + ValueError: undecidable - With using finite halting precision:: + With using finite halting precision (which ignores + the ``secure`` option):: sage: L.options.halting_precision = 40 sage: fz = L(lambda n: 0, valuation=0) @@ -989,43 +995,20 @@ def _richcmp_(self, other, op): True """ if op is op_EQ: - if (not self.parent().options['use_unknown'] + if self._coeff_stream == other._coeff_stream: + return True + + if (not self.parent().options['secure'] and self.parent().options['halting_precision'] is None): - return self._coeff_stream == other._coeff_stream - - if isinstance(self._coeff_stream, Stream_zero): - if isinstance(other._coeff_stream, Stream_zero): - return True - if other._coeff_stream.is_undefined() or other._coeff_stream.is_nonzero(): - return False - elif isinstance(other._coeff_stream, Stream_zero): - if self._coeff_stream.is_undefined() or self._coeff_stream.is_nonzero(): - return False - elif isinstance(self._coeff_stream, Stream_exact): - if isinstance(other._coeff_stream, Stream_exact): - return self._coeff_stream == other._coeff_stream - if self._coeff_stream != other._coeff_stream or other._coeff_stream.is_undefined(): - return False - elif isinstance(other._coeff_stream, Stream_exact): - if other._coeff_stream != self._coeff_stream or self._coeff_stream.is_undefined(): - return False - else: - # both streams are inexact, perhaps they are equal by - # construction - if self._coeff_stream == other._coeff_stream: - return True - # perhaps their caches are different - if self._coeff_stream != other._coeff_stream: - return False - if self._coeff_stream.is_undefined() or other._coeff_stream.is_undefined(): - return False + return False + + if self._coeff_stream != other._coeff_stream: + return False # undecidable otherwise prec = self.parent().options['halting_precision'] if prec is None: - return None - #return Unknown - # raise UnknownError("undecidable") + raise ValueError("undecidable") # at least one of the approximate orders is not infinity m = min(self._coeff_stream._approximate_order, other._coeff_stream._approximate_order) @@ -1068,7 +1051,7 @@ def __bool__(self): sage: L. = LazyLaurentSeriesRing(GF(2)) # optional - sage.rings.finite_rings sage: bool(z - z) # optional - sage.rings.finite_rings False - sage: f = 1/(1 - z) # optional - sage.rings.finite_rings + sage: f = 1 / (1 - z) # optional - sage.rings.finite_rings sage: bool(f) # optional - sage.rings.finite_rings True sage: M = L(lambda n: n, valuation=0); M # optional - sage.rings.finite_rings @@ -1131,7 +1114,6 @@ def __bool__(self): sage: M.is_zero() True - With finite halting precision, it can be considered to be indistinguishable from zero until possibly enough coefficients are computed:: @@ -1155,30 +1137,24 @@ def __bool__(self): return False prec = self.parent().options['halting_precision'] - if prec is None and not self.parent().options['use_unknown']: + if prec is None and not self.parent().options['secure']: return True if isinstance(self._coeff_stream, Stream_exact): return True - if self._coeff_stream.is_undefined(): + if self._coeff_stream.is_uninitialized(): + return True + if self._coeff_stream.is_nonzero(): return True - if self._coeff_stream._is_sparse: - cache = self._coeff_stream._cache - if any(cache[a] for a in cache): - return True - else: - if any(self._coeff_stream._cache): - return True if prec is None: - return True - #raise UnknownError("undecidable") + raise ValueError("undecidable") v = self._coeff_stream._approximate_order return any(self[i] for i in range(v, v + prec)) def is_nonzero(self): - """ - Return ``True`` if ``self`` is known to be nonzero. + r""" + Return ``True`` if ``self`` is *known* to be nonzero. EXAMPLES: @@ -1222,6 +1198,52 @@ def is_nonzero(self): return bool(self) return False + def prove_nonzero(self): + r""" + Generate coefficients until the result is shown to be nonzero + and returns the degree with the first nonzero coefficient. + + .. WARNING:: + + If the stream is exactly zero, this will run forever. + + EXAMPLES:: + + sage: L. = LazyLaurentSeriesRing(GF(5)) + sage: g = L(lambda n: 0 if n < 50 else 1, valuation=2) + sage: g.prove_nonzero() + 50 + + sage: L.zero().prove_nonzero() + Traceback (most recent call last): + ... + ValueError: trivially zero + """ + if isinstance(self._coeff_stream, Stream_zero): + raise ValueError("trivially zero") + + i = self._coeff_stream._approximate_order + while True: + if self[i]: + return i + i += 1 + + def is_trivial_zero(self): + r""" + Return whether ``self`` is known to be trivially zero. + + EXAMPLES:: + + sage: L. = LazyLaurentSeriesRing(ZZ) + sage: f = L(lambda n: 0, valuation=2) + sage: f.is_trivial_zero() + False + + sage: L.zero().is_trivial_zero() + True + """ + return isinstance(self._coeff_stream, Stream_zero) + def define(self, s): r""" Define an equation by ``self = s``. @@ -1532,9 +1554,9 @@ def _repr_(self): O(z^-3) sage: s = L.undefined(valuation=0); s - Uninitialized Lazy Laurent Series + Uninitialized Lazy Series sage: (s + s^2).map_coefficients(lambda f: f % 3) - Uninitialized Lazy Laurent Series + Uninitialized Lazy Series sage: L(0) 0 @@ -1547,8 +1569,8 @@ def _repr_(self): """ if isinstance(self._coeff_stream, Stream_zero): return '0' - if self._coeff_stream.is_undefined(): - return 'Uninitialized Lazy Laurent Series' + if self._coeff_stream.is_uninitialized(): + return 'Uninitialized Lazy Series' return self._format_series(repr) def _latex_(self): @@ -1600,7 +1622,7 @@ def _latex_(self): from sage.misc.latex import latex if isinstance(self._coeff_stream, Stream_zero): return latex('0') - if self._coeff_stream.is_undefined(): + if self._coeff_stream.is_uninitialized(): return latex("Undef") return self._format_series(latex) @@ -1614,14 +1636,17 @@ def _ascii_art_(self): sage: L. = LazyLaurentSeriesRing(e) # optional - sage.combinat sage: L.options.display_length = 3 # optional - sage.combinat sage: ascii_art(1 / (1 - e[1]*z)) # optional - sage.combinat - e[] + e[1]*z + e[1, 1]*z^2 + O(e[]*z^3) + e[] + e[1]*z + e[1, 1]*z^2 + O(e[]*z^3 + sage: x = L.undefined(valuation=0) # optional - sage.combinat + sage: ascii_art(x + x^2 - 5) # optional - sage.combinat + Uninitialized Lazy Series sage: L.options._reset() # optional - sage.combinat """ from sage.typeset.ascii_art import ascii_art, AsciiArt if isinstance(self._coeff_stream, Stream_zero): return AsciiArt('0') - if isinstance(self._coeff_stream, Stream_uninitialized) and self._coeff_stream._target is None: - return AsciiArt('Uninitialized Lazy Laurent Series') + if self._coeff_stream.is_uninitialized(): + return AsciiArt('Uninitialized Lazy Series') return self._format_series(ascii_art, True) def _unicode_art_(self): @@ -1635,13 +1660,16 @@ def _unicode_art_(self): sage: L.options.display_length = 3 # optional - sage.combinat sage: unicode_art(1 / (1 - e[1]*z)) # optional - sage.combinat e[] + e[1]*z + e[1, 1]*z^2 + O(e[]*z^3) + sage: x = L.undefined(valuation=0) # optional - sage.combinat + sage: ascii_art(x + x^2 - 5) # optional - sage.combinat + Uninitialized Lazy Series sage: L.options._reset() # optional - sage.combinat """ from sage.typeset.unicode_art import unicode_art, UnicodeArt if isinstance(self._coeff_stream, Stream_zero): return UnicodeArt('0') - if isinstance(self._coeff_stream, Stream_uninitialized) and self._coeff_stream._target is None: - return UnicodeArt('Uninitialized Lazy Laurent Series') + if self._coeff_stream.is_uninitialized(): + return UnicodeArt('Uninitialized Lazy Series') return self._format_series(unicode_art, True) def change_ring(self, ring): @@ -1923,12 +1951,14 @@ def _acted_upon_(self, scalar, self_on_left): Different scalars potentially give different series:: - sage: (2 * M == 3 * M) is None - True + sage: 2 * M == 3 * M + False - sage: L.options.use_unknown = True - sage: (2 * M == 3 * M) is None - True + sage: L.options.secure = True + sage: 2 * M == 3 * M + Traceback (most recent call last): + ... + ValueError: undecidable sage: L.options.halting_precision = 30 sage: 2 * M == 3 * M diff --git a/src/sage/rings/lazy_series_ring.py b/src/sage/rings/lazy_series_ring.py index aebe887ae58..9d743164745 100644 --- a/src/sage/rings/lazy_series_ring.py +++ b/src/sage/rings/lazy_series_ring.py @@ -676,7 +676,7 @@ class options(GlobalOptions): - constant_length: 3 - display_length: 7 - halting_precision: None - - use_unknown: True + - secure: False sage: LLS.options.display_length 7 @@ -712,9 +712,9 @@ class options(GlobalOptions): halting_precision = dict(default=None, description='the number of coefficients, beginning with the approximate valuation, to check in equality tests', checker=lambda x: x is None or x in ZZ and x > 0) - use_unknown = dict(default=True, - description='whether to raise an error when a comparison is unknown', - checker=lambda x: x is True or x is False) + secure = dict(default=False, + description='whether to raise an error when a comparison is unknown', + checker=lambda x: x is True or x is False) @cached_method def one(self): @@ -1162,8 +1162,15 @@ class LazyLaurentSeriesRing(LazySeriesRing): be equal are considered to be different:: sage: f = L(lambda n: 0, valuation=0) - sage: (f == 0) is None - True + sage: f == 0 + False + + sage: f = L(constant=1, valuation=0).derivative(); f + 1 + 2*z + 3*z^2 + 4*z^3 + 5*z^4 + 6*z^5 + 7*z^6 + O(z^7) + sage: g = L(lambda n: (n+1), valuation=0); g + 1 + 2*z + 3*z^2 + 4*z^3 + 5*z^4 + 6*z^5 + 7*z^6 + O(z^7) + sage: f == g + False .. WARNING:: @@ -1171,8 +1178,9 @@ class LazyLaurentSeriesRing(LazySeriesRing): ``f != g`` returning ``True`` might not mean that the two series are actually different:: + sage: f = L(lambda n: 0, valuation=0) sage: g = L.zero() - sage: (f != g) is None + sage: f != g True This can be verified by :meth:`~sage.rings.lazy_series.is_nonzero()`, @@ -1192,23 +1200,25 @@ class LazyLaurentSeriesRing(LazySeriesRing): False We additionally provide two other methods of performing comparisons. - The first is returning an :class:`Unknown` and the second uses a check + The first is raising a ``ValueError`` and the second uses a check up to a (user set) finite precision. These behaviors are set using the - options ``use_unknown`` and ``halting_precision``. In particular, + options ``secure`` and ``halting_precision``. In particular, this applies to series that are not specified by a finite number of initial coefficients and a constant for the remaining coefficients. Equality checking will depend on the coefficients which have already been computed. If this information is not enough to - check that two series are different, then if ``L.options.use_unknown`` - is set to ``True``, then we return an :class:`Unknown`:: + check that two series are different, then if ``L.options.secure`` + is set to ``True``, then we raise a ``ValueError``:: - sage: L.options.use_unknown = True + sage: L.options.secure = True sage: f = 1 / (z + z^2); f z^-1 - 1 + z - z^2 + z^3 - z^4 + z^5 + O(z^6) sage: f2 = f * 2 # currently no coefficients computed sage: f3 = f * 3 # currently no coefficients computed - sage: (f2 == f3) is None - True + sage: f2 == f3 + Traceback (most recent call last): + ... + ValueError: undecidable sage: f2 # computes some of the coefficients of f2 2*z^-1 - 2 + 2*z - 2*z^2 + 2*z^3 - 2*z^4 + 2*z^5 + O(z^6) sage: f3 # computes some of the coefficients of f3 @@ -1216,16 +1226,22 @@ class LazyLaurentSeriesRing(LazySeriesRing): sage: f2 == f3 False sage: f2a = f + f - sage: (f2 == f2a) is None - True + sage: f2 == f2a + Traceback (most recent call last): + ... + ValueError: undecidable sage: zf = L(lambda n: 0, valuation=0) - sage: (zf == 0) is None - True + sage: zf == 0 + Traceback (most recent call last): + ... + ValueError: undecidable For boolean checks, an error is raised when it is not known to be nonzero:: sage: bool(zf) - True + Traceback (most recent call last): + ... + ValueError: undecidable If the halting precision is set to a finite number `p` (for unlimited precision, it is set to ``None``), then it will check up to `p` values From 6789a2cd29a69a29c40e9b85e270ebfef7610647 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Sat, 9 Sep 2023 14:23:13 +0900 Subject: [PATCH 14/93] More Stream_unary inheritance, some missing details, and other polishing. --- src/sage/data_structures/stream.py | 167 +++++++++++++---------------- src/sage/rings/lazy_series.py | 69 ++++++------ 2 files changed, 107 insertions(+), 129 deletions(-) diff --git a/src/sage/data_structures/stream.py b/src/sage/data_structures/stream.py index 7038ce2149c..0d400d58fd2 100644 --- a/src/sage/data_structures/stream.py +++ b/src/sage/data_structures/stream.py @@ -179,7 +179,6 @@ def __ne__(self, other): False sage: CS != Stream(-2) False - """ return False @@ -199,21 +198,18 @@ def is_nonzero(self): """ return False - def is_trivially_ne(self, other): - """ - Return if ``self`` is trivially not equal to ``other``. + def is_uninitialized(self): + r""" + Return ``True`` if ``self`` is an uninitialized stream. The default implementation is ``False``. - .. NOTE:: - - This does not check that the streams are equal. - """ - return False + EXAMPLES:: - def is_uninitialized(self): - """ - Return ``True`` if ``self`` is an uninitialized stream. + sage: from sage.data_structures.stream import Stream_zero + sage: zero = Stream_zero() + sage: zero.is_uninitialized() + False """ return False @@ -939,7 +935,6 @@ class Stream_iterator(Stream_inexact): sage: f = Stream_iterator(iter(NonNegativeIntegers()), 1) sage: [f[i] for i in range(10)] [0, 0, 1, 2, 3, 4, 5, 6, 7, 8] - """ def __init__(self, iter, approximate_order, true_order=False): """ @@ -968,6 +963,11 @@ class Stream_function(Stream_inexact): - ``approximate_order`` -- integer; a lower bound for the order of the stream + .. NOTE:: + + We assume for equality that ``function`` is a function in the + mathematical sense. + EXAMPLES:: sage: from sage.data_structures.stream import Stream_function @@ -1000,6 +1000,43 @@ def __init__(self, function, is_sparse, approximate_order, true_order=False): super().__init__(is_sparse, true_order) self._approximate_order = approximate_order + def __hash__(self): + """ + Return the hash of ``self``. + + EXAMPLES:: + + sage: from sage.data_structures.stream import Stream_function + sage: f = Stream_function(lambda n: n, True, 0) + sage: g = Stream_function(lambda n: 1, False, 1) + sage: hash(f) == hash(g) + True + """ + # We don't hash the function as it might not be hashable. + return hash(type(self)) + + def __eq__(self, other): + r""" + Return whether ``self`` and ``other`` are known to be equal. + + INPUT: + + - ``other`` -- a stream + + EXAMPLES:: + + sage: from sage.data_structures.stream import Stream_function + sage: fun = lambda n: n + sage: f = Stream_function(fun, True, 0) + sage: g = Stream_function(fun, False, 0) + sage: h = Stream_function(lambda n: n, False, 0) + sage: f == g + True + sage: f == h + False + """ + return isinstance(other, type(self)) and self.get_coefficient == other.get_coefficient + class Stream_uninitialized(Stream_inexact): r""" @@ -1086,6 +1123,9 @@ class Stream_unary(Stream_inexact): INPUT: - ``series`` -- :class:`Stream` the operator acts on + - ``is_sparse`` -- boolean + - ``true_order`` -- boolean (default: ``False``) if the approximate order + is the actual order EXAMPLES:: @@ -1098,7 +1138,7 @@ class Stream_unary(Stream_inexact): sage: [g[i] for i in range(10)] [0, 4, 8, 12, 16, 20, 24, 28, 32, 36] """ - def __init__(self, series, is_sparse): + def __init__(self, series, is_sparse, true_order=False): """ Initialize ``self``. @@ -1113,7 +1153,7 @@ def __init__(self, series, is_sparse): sage: TestSuite(g).run() """ self._series = series - super().__init__(is_sparse, False) + super().__init__(is_sparse, true_order) def __hash__(self): """ @@ -1350,7 +1390,6 @@ class Stream_zero(Stream): sage: s[5] 0 """ - def __init__(self): """ Initialize ``self``. @@ -1360,7 +1399,6 @@ def __init__(self): sage: from sage.data_structures.stream import Stream_zero sage: s = Stream_zero() sage: TestSuite(s).run() - """ super().__init__(True) self._approximate_order = infinity @@ -1415,7 +1453,7 @@ def __eq__(self, other): def __ne__(self, other): """ - Return whether ``self`` and ``other`` are known to be not equal. + Return whether ``self`` and ``other`` are known to be different. INPUT: @@ -1749,6 +1787,7 @@ def get_coefficient(self, n): and n // k >= self._right._approximate_order and (l := self._left[k]))) + class Stream_dirichlet_invert(Stream_unary): r""" Operator for inverse with respect to Dirichlet convolution of the stream. @@ -2309,7 +2348,7 @@ def stretched_power_restrict_degree(self, i, m, d): ##################################################################### # Unary operations -class Stream_scalar(Stream_inexact): +class Stream_scalar(Stream_unary): """ Base class for operators multiplying a coefficient stream by a scalar. @@ -2318,14 +2357,7 @@ class Stream_scalar(Stream_inexact): - ``series`` -- a :class:`Stream` - ``scalar`` -- a non-zero, non-one scalar - - .. TODO:: - - This does not inherit from :class:`Stream_unary`, because of - the extra argument ``scalar``. However, we could also - override :meth:`Stream_unary.hash`, - :meth:`Stream_unary.__eq__`. Would this be any better? - + - ``is_sparse`` -- boolean """ def __init__(self, series, scalar, is_sparse): """ @@ -2337,10 +2369,10 @@ def __init__(self, series, scalar, is_sparse): sage: f = Stream_function(lambda n: -1, True, 0) sage: g = Stream_rmul(f, 3, True) """ - self._series = series self._scalar = scalar assert scalar, "the scalar must not be equal to 0" - super().__init__(is_sparse, series._true_order) + assert scalar != 1, "the scalar must not be equal to 1" + super().__init__(series, is_sparse, series._true_order) @lazy_attribute def _approximate_order(self): @@ -2423,20 +2455,6 @@ def is_nonzero(self): """ return self._series.is_nonzero() - def is_uninitialized(self): - """ - Return ``True`` if ``self`` is an uninitialized stream. - - EXAMPLES:: - - sage: from sage.data_structures.stream import Stream_uninitialized, Stream_lmul, Stream_function - sage: C = Stream_uninitialized(0) - sage: B = Stream_lmul(C, 2, True) - sage: B.is_uninitialized() - True - """ - return self._series.is_uninitialized() - class Stream_rmul(Stream_scalar): """ @@ -2749,7 +2767,7 @@ def is_nonzero(self): return True -class Stream_map_coefficients(Stream_inexact): +class Stream_map_coefficients(Stream_unary): r""" The stream with ``function`` applied to each non-zero coefficient of ``series``. @@ -2759,6 +2777,11 @@ class Stream_map_coefficients(Stream_inexact): - ``series`` -- a :class:`Stream` - ``function`` -- a function that modifies the elements of the stream + .. NOTE:: + + We assume for equality that ``function`` is a function in the + mathematical sense. + EXAMPLES:: sage: from sage.data_structures.stream import (Stream_map_coefficients, Stream_function) @@ -2780,8 +2803,7 @@ def __init__(self, series, function, is_sparse, approximate_order=None, true_ord sage: TestSuite(g).run(skip="_test_pickling") """ self._function = function - self._series = series - super().__init__(is_sparse, true_order) + super().__init__(series, is_sparse, true_order) if approximate_order is not None: self._approximate_order = approximate_order @@ -2869,20 +2891,6 @@ def __eq__(self, other): return (isinstance(other, type(self)) and self._series == other._series and self._function == other._function) - def is_uninitialized(self): - """ - Return ``True`` if ``self`` is an uninitialized stream. - - EXAMPLES:: - - sage: from sage.data_structures.stream import Stream_uninitialized, Stream_map_coefficients - sage: C = Stream_uninitialized(0) - sage: M = Stream_map_coefficients(C, lambda n: -n, True) - sage: M.is_uninitialized() - True - """ - return self._series.is_uninitialized() - class Stream_shift(Stream): """ @@ -3031,7 +3039,7 @@ def is_uninitialized(self): return self._series.is_uninitialized() -class Stream_truncated(Stream_inexact): +class Stream_truncated(Stream_unary): """ Operator for shifting a non-zero, non-exact stream that has been shifted below its minimal valuation. @@ -3081,9 +3089,8 @@ def __init__(self, series, shift, minimal_valuation): sage: s._approximate_order 3 """ - super().__init__(series._is_sparse, False) + super().__init__(series, series._is_sparse, False) assert isinstance(series, Stream_inexact) - self._series = series # We share self._series._cache but not self._series._approximate order # self._approximate_order cannot be updated by self._series.__getitem__ self._cache = series._cache @@ -3279,22 +3286,8 @@ def is_nonzero(self): start = self._approximate_order - offset return any(self._cache[start:]) - def is_uninitialized(self): - """ - Return ``True`` if ``self`` is an uninitialized stream. - - EXAMPLES:: - - sage: from sage.data_structures.stream import Stream_uninitialized, Stream_truncated - sage: C = Stream_uninitialized(0) - sage: S = Stream_truncated(C, -5, 3) - sage: S.is_uninitialized() - True - """ - return self._series.is_uninitialized() - -class Stream_derivative(Stream_inexact): +class Stream_derivative(Stream_unary): """ Operator for taking derivatives of a non-exact stream. @@ -3302,6 +3295,7 @@ class Stream_derivative(Stream_inexact): - ``series`` -- a :class:`Stream` - ``shift`` -- a positive integer + - ``is_sparse`` -- boolean """ def __init__(self, series, shift, is_sparse): """ @@ -3314,9 +3308,8 @@ def __init__(self, series, shift, is_sparse): sage: f2 = Stream_derivative(f, 2, True) sage: TestSuite(f2).run() """ - self._series = series self._shift = shift - super().__init__(is_sparse, False) + super().__init__(series, is_sparse, False) @lazy_attribute def _approximate_order(self): @@ -3420,17 +3413,3 @@ def is_nonzero(self): True """ return self._series.is_nonzero() - - def is_uninitialized(self): - """ - Return ``True`` if ``self`` is an uninitialized stream. - - EXAMPLES:: - - sage: from sage.data_structures.stream import Stream_uninitialized, Stream_derivative - sage: C = Stream_uninitialized(0) - sage: D = Stream_derivative(C, 1, True) - sage: D.is_uninitialized() - True - """ - return self._series.is_uninitialized() diff --git a/src/sage/rings/lazy_series.py b/src/sage/rings/lazy_series.py index 50f4e7c5c45..bf68569a90f 100644 --- a/src/sage/rings/lazy_series.py +++ b/src/sage/rings/lazy_series.py @@ -1152,10 +1152,19 @@ def __bool__(self): v = self._coeff_stream._approximate_order return any(self[i] for i in range(v, v + prec)) - def is_nonzero(self): + def is_nonzero(self, proof=False): r""" Return ``True`` if ``self`` is *known* to be nonzero. + INPUT: + + - ``proof`` -- (default: ``False``) if ``True``, this will also return + an index such that ``self`` has a nonzero coefficient + + .. WARNING:: + + If the stream is exactly zero, this will run forever. + EXAMPLES: A series that it not known to be nonzero with no halting precision:: @@ -1191,42 +1200,32 @@ def is_nonzero(self): sage: g.is_nonzero() # checks up to degree 62 = 42 + 20 True sage: L.options._reset() - """ - if self._coeff_stream.is_nonzero(): - return True - if self.parent().options['halting_precision'] is not None: - return bool(self) - return False - - def prove_nonzero(self): - r""" - Generate coefficients until the result is shown to be nonzero - and returns the degree with the first nonzero coefficient. - - .. WARNING:: - - If the stream is exactly zero, this will run forever. - EXAMPLES:: + With a proof:: sage: L. = LazyLaurentSeriesRing(GF(5)) - sage: g = L(lambda n: 0 if n < 50 else 1, valuation=2) - sage: g.prove_nonzero() - 50 + sage: g = L(lambda n: 5 if n < 50 else 1, valuation=2) + sage: g.is_nonzero(proof=True) + (True, 50) - sage: L.zero().prove_nonzero() - Traceback (most recent call last): - ... - ValueError: trivially zero + sage: L.zero().is_nonzero(proof=True) + (False, None) """ - if isinstance(self._coeff_stream, Stream_zero): - raise ValueError("trivially zero") + if proof: + if isinstance(self._coeff_stream, Stream_zero): + return (False, None) - i = self._coeff_stream._approximate_order - while True: - if self[i]: - return i - i += 1 + i = self._coeff_stream._approximate_order + while True: + if self[i]: + return (True, i) + i += 1 + + if self._coeff_stream.is_nonzero(): + return True + if self.parent().options['halting_precision'] is not None: + return bool(self) + return False def is_trivial_zero(self): r""" @@ -1636,7 +1635,7 @@ def _ascii_art_(self): sage: L. = LazyLaurentSeriesRing(e) # optional - sage.combinat sage: L.options.display_length = 3 # optional - sage.combinat sage: ascii_art(1 / (1 - e[1]*z)) # optional - sage.combinat - e[] + e[1]*z + e[1, 1]*z^2 + O(e[]*z^3 + e[] + e[1]*z + e[1, 1]*z^2 + O(e[]*z^3) sage: x = L.undefined(valuation=0) # optional - sage.combinat sage: ascii_art(x + x^2 - 5) # optional - sage.combinat Uninitialized Lazy Series @@ -1646,7 +1645,7 @@ def _ascii_art_(self): if isinstance(self._coeff_stream, Stream_zero): return AsciiArt('0') if self._coeff_stream.is_uninitialized(): - return AsciiArt('Uninitialized Lazy Series') + return AsciiArt(['Uninitialized Lazy Series']) return self._format_series(ascii_art, True) def _unicode_art_(self): @@ -1661,7 +1660,7 @@ def _unicode_art_(self): sage: unicode_art(1 / (1 - e[1]*z)) # optional - sage.combinat e[] + e[1]*z + e[1, 1]*z^2 + O(e[]*z^3) sage: x = L.undefined(valuation=0) # optional - sage.combinat - sage: ascii_art(x + x^2 - 5) # optional - sage.combinat + sage: unicode_art(x + x^2 - 5) # optional - sage.combinat Uninitialized Lazy Series sage: L.options._reset() # optional - sage.combinat """ @@ -1669,7 +1668,7 @@ def _unicode_art_(self): if isinstance(self._coeff_stream, Stream_zero): return UnicodeArt('0') if self._coeff_stream.is_uninitialized(): - return UnicodeArt('Uninitialized Lazy Series') + return UnicodeArt(['Uninitialized Lazy Series']) return self._format_series(unicode_art, True) def change_ring(self, ring): From 9db4d0f4a86a195e66d207d4742825a53bf9eb80 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Sat, 9 Sep 2023 14:24:18 +0900 Subject: [PATCH 15/93] Moving Stream_dirichlet_invert to the unary section. --- src/sage/data_structures/stream.py | 214 ++++++++++++++--------------- 1 file changed, 107 insertions(+), 107 deletions(-) diff --git a/src/sage/data_structures/stream.py b/src/sage/data_structures/stream.py index 0d400d58fd2..8ec1b74c1f2 100644 --- a/src/sage/data_structures/stream.py +++ b/src/sage/data_structures/stream.py @@ -1788,113 +1788,6 @@ def get_coefficient(self, n): and (l := self._left[k]))) -class Stream_dirichlet_invert(Stream_unary): - r""" - Operator for inverse with respect to Dirichlet convolution of the stream. - - INPUT: - - - ``series`` -- a :class:`Stream` - - EXAMPLES:: - - sage: from sage.data_structures.stream import (Stream_dirichlet_invert, Stream_function) - sage: f = Stream_function(lambda n: 1, True, 1) - sage: g = Stream_dirichlet_invert(f, True) - sage: [g[i] for i in range(10)] - [0, 1, -1, -1, 0, -1, 1, -1, 0, 0] - sage: [moebius(i) for i in range(10)] # needs sage.libs.pari - [0, 1, -1, -1, 0, -1, 1, -1, 0, 0] - """ - def __init__(self, series, is_sparse): - """ - Initialize. - - TESTS:: - - sage: from sage.data_structures.stream import (Stream_exact, Stream_dirichlet_invert) - sage: f = Stream_exact([0, 0], constant=1) - sage: g = Stream_dirichlet_invert(f, True) - sage: g[1] - Traceback (most recent call last): - ... - ZeroDivisionError: the Dirichlet inverse only exists if the coefficient with index 1 is non-zero - """ - super().__init__(series, is_sparse) - self._zero = ZZ.zero() - - @lazy_attribute - def _approximate_order(self): - """ - Compute and return the approximate order of ``self``. - - EXAMPLES:: - - sage: from sage.data_structures.stream import Stream_function, Stream_dirichlet_invert - sage: f = Stream_function(lambda n: n, True, 1) - sage: h = Stream_dirichlet_invert(f, True) - sage: h._approximate_order - 1 - sage: [h[i] for i in range(5)] - [0, -2, -8, -12, -48] - """ - # this is the true order, but we want to check first - if self._series._approximate_order > 1: - raise ZeroDivisionError("the Dirichlet inverse only exists if the " - "coefficient with index 1 is non-zero") - self._true_order = True - return 1 - - @lazy_attribute - def _ainv(self): - """ - The inverse of the leading coefficient. - - EXAMPLES:: - - sage: from sage.data_structures.stream import (Stream_exact, Stream_dirichlet_invert) - sage: f = Stream_exact([0, 3], constant=2) - sage: g = Stream_dirichlet_invert(f, True) - sage: g._ainv - 1/3 - - sage: f = Stream_exact([Zmod(6)(5)], constant=2, order=1) - sage: g = Stream_dirichlet_invert(f, True) - sage: g._ainv - 5 - """ - try: - return ~self._series[1] - except TypeError: - return self._series[1].inverse_of_unit() - - def get_coefficient(self, n): - """ - Return the ``n``-th coefficient of ``self``. - - INPUT: - - - ``n`` -- integer; the degree for the coefficient - - EXAMPLES:: - - sage: from sage.data_structures.stream import (Stream_exact, Stream_dirichlet_invert) - sage: f = Stream_exact([0, 3], constant=2) - sage: g = Stream_dirichlet_invert(f, True) - sage: g.get_coefficient(6) - 2/27 - sage: [g[i] for i in range(8)] - [0, 1/3, -2/9, -2/9, -2/27, -2/9, 2/27, -2/9] - """ - if n == 1: - return self._ainv - # TODO: isn't self[k] * l and l * self[k] the same here? - c = sum(self[k] * l for k in divisors(n) - if (k < n - and (l := self._series[n // k]))) - return -c * self._ainv - - class Stream_cauchy_compose(Stream_binary): r""" Return ``f`` composed by ``g``. @@ -2767,6 +2660,113 @@ def is_nonzero(self): return True +class Stream_dirichlet_invert(Stream_unary): + r""" + Operator for inverse with respect to Dirichlet convolution of the stream. + + INPUT: + + - ``series`` -- a :class:`Stream` + + EXAMPLES:: + + sage: from sage.data_structures.stream import (Stream_dirichlet_invert, Stream_function) + sage: f = Stream_function(lambda n: 1, True, 1) + sage: g = Stream_dirichlet_invert(f, True) + sage: [g[i] for i in range(10)] + [0, 1, -1, -1, 0, -1, 1, -1, 0, 0] + sage: [moebius(i) for i in range(10)] # needs sage.libs.pari + [0, 1, -1, -1, 0, -1, 1, -1, 0, 0] + """ + def __init__(self, series, is_sparse): + """ + Initialize. + + TESTS:: + + sage: from sage.data_structures.stream import (Stream_exact, Stream_dirichlet_invert) + sage: f = Stream_exact([0, 0], constant=1) + sage: g = Stream_dirichlet_invert(f, True) + sage: g[1] + Traceback (most recent call last): + ... + ZeroDivisionError: the Dirichlet inverse only exists if the coefficient with index 1 is non-zero + """ + super().__init__(series, is_sparse) + self._zero = ZZ.zero() + + @lazy_attribute + def _approximate_order(self): + """ + Compute and return the approximate order of ``self``. + + EXAMPLES:: + + sage: from sage.data_structures.stream import Stream_function, Stream_dirichlet_invert + sage: f = Stream_function(lambda n: n, True, 1) + sage: h = Stream_dirichlet_invert(f, True) + sage: h._approximate_order + 1 + sage: [h[i] for i in range(5)] + [0, -2, -8, -12, -48] + """ + # this is the true order, but we want to check first + if self._series._approximate_order > 1: + raise ZeroDivisionError("the Dirichlet inverse only exists if the " + "coefficient with index 1 is non-zero") + self._true_order = True + return 1 + + @lazy_attribute + def _ainv(self): + """ + The inverse of the leading coefficient. + + EXAMPLES:: + + sage: from sage.data_structures.stream import (Stream_exact, Stream_dirichlet_invert) + sage: f = Stream_exact([0, 3], constant=2) + sage: g = Stream_dirichlet_invert(f, True) + sage: g._ainv + 1/3 + + sage: f = Stream_exact([Zmod(6)(5)], constant=2, order=1) + sage: g = Stream_dirichlet_invert(f, True) + sage: g._ainv + 5 + """ + try: + return ~self._series[1] + except TypeError: + return self._series[1].inverse_of_unit() + + def get_coefficient(self, n): + """ + Return the ``n``-th coefficient of ``self``. + + INPUT: + + - ``n`` -- integer; the degree for the coefficient + + EXAMPLES:: + + sage: from sage.data_structures.stream import (Stream_exact, Stream_dirichlet_invert) + sage: f = Stream_exact([0, 3], constant=2) + sage: g = Stream_dirichlet_invert(f, True) + sage: g.get_coefficient(6) + 2/27 + sage: [g[i] for i in range(8)] + [0, 1/3, -2/9, -2/9, -2/27, -2/9, 2/27, -2/9] + """ + if n == 1: + return self._ainv + # TODO: isn't self[k] * l and l * self[k] the same here? + c = sum(self[k] * l for k in divisors(n) + if (k < n + and (l := self._series[n // k]))) + return -c * self._ainv + + class Stream_map_coefficients(Stream_unary): r""" The stream with ``function`` applied to each non-zero coefficient From cfd2dfe2cdb6cbe97e28937d2ca2d215b31d4f3e Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Sun, 10 Sep 2023 13:45:19 +0900 Subject: [PATCH 16/93] Better uninitialized checking; fixing doctests. --- src/sage/combinat/species/recursive_species.py | 6 +++--- src/sage/data_structures/stream.py | 11 ++++++++++- src/sage/rings/lazy_series.py | 8 +++++--- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/sage/combinat/species/recursive_species.py b/src/sage/combinat/species/recursive_species.py index 8fd01494c1a..3cd073f9f9c 100644 --- a/src/sage/combinat/species/recursive_species.py +++ b/src/sage/combinat/species/recursive_species.py @@ -230,7 +230,7 @@ def _gs(self, series_ring, base_ring): sage: F = CombinatorialSpecies() sage: F.generating_series() - Uninitialized Lazy Laurent Series + Uninitialized Lazy Series """ if base_ring not in self._generating_series: self._generating_series[base_ring] = series_ring.undefined(valuation=(0 if self._min is None else self._min)) @@ -247,7 +247,7 @@ def _itgs(self, series_ring, base_ring): sage: F = CombinatorialSpecies() sage: F.isotype_generating_series() - Uninitialized Lazy Laurent Series + Uninitialized Lazy Series """ if base_ring not in self._isotype_generating_series: self._isotype_generating_series[base_ring] = series_ring.undefined(valuation=(0 if self._min is None else self._min)) @@ -264,7 +264,7 @@ def _cis(self, series_ring, base_ring): sage: F = CombinatorialSpecies() sage: F.cycle_index_series() - Uninitialized Lazy Laurent Series + Uninitialized Lazy Series """ if base_ring not in self._cycle_index_series: self._cycle_index_series[base_ring] = series_ring.undefined(valuation=(0 if self._min is None else self._min)) diff --git a/src/sage/data_structures/stream.py b/src/sage/data_structures/stream.py index 8ec1b74c1f2..d7f1f939bb7 100644 --- a/src/sage/data_structures/stream.py +++ b/src/sage/data_structures/stream.py @@ -1080,6 +1080,7 @@ def __init__(self, approximate_order, true_order=False): raise ValueError("the valuation must be specified for undefined series") super().__init__(False, true_order) self._approximate_order = approximate_order + self._initializing = False def iterate_coefficients(self): """ @@ -1113,7 +1114,15 @@ def is_uninitialized(self): sage: C.is_uninitialized() True """ - return self._target is None + if self._target is None: + return True + if self._initializing: + return False + # We implement semaphore-like behavior for coupled (undefined) series + self._initializing = True + result = self._target.is_uninitialized() + self._initializing = False + return result class Stream_unary(Stream_inexact): diff --git a/src/sage/rings/lazy_series.py b/src/sage/rings/lazy_series.py index bf68569a90f..230c70dafa2 100644 --- a/src/sage/rings/lazy_series.py +++ b/src/sage/rings/lazy_series.py @@ -3594,7 +3594,8 @@ def exp(self): coeff_stream = self._coeff_stream # TODO: coefficients should not be checked here, it prevents # us from using self.define in some cases! - if any(coeff_stream[i] for i in range(coeff_stream._approximate_order, 1)): + if ((not coeff_stream.is_uninitialized()) + and any(coeff_stream[i] for i in range(coeff_stream._approximate_order, 1))): raise ValueError("can only compose with a positive valuation series") # WARNING: d_self need not be a proper element of P, e.g. for # multivariate power series @@ -3646,8 +3647,9 @@ def log(self): coeff_stream = self._coeff_stream # TODO: coefficients should not be checked here, it prevents # us from using self.define in some cases! - if (any(coeff_stream[i] for i in range(coeff_stream._approximate_order, 0)) - or coeff_stream[0] != R.one()): + if ((not coeff_stream.is_uninitialized()) + and (any(coeff_stream[i] for i in range(coeff_stream._approximate_order, 0)) + or coeff_stream[0] != R.one())): raise ValueError("can only compose with a positive valuation series") # WARNING: d_self need not be a proper element of P, e.g. for # multivariate power series From 72e15b65cdc24b1fdf54ef7caad1304c14897806 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Sun, 10 Sep 2023 13:58:51 +0900 Subject: [PATCH 17/93] Adding a test for the improved uninitialized series. --- src/sage/data_structures/stream.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/sage/data_structures/stream.py b/src/sage/data_structures/stream.py index d7f1f939bb7..c24f2c547df 100644 --- a/src/sage/data_structures/stream.py +++ b/src/sage/data_structures/stream.py @@ -1113,6 +1113,15 @@ def is_uninitialized(self): sage: C = Stream_uninitialized(0) sage: C.is_uninitialized() True + + A more subtle uninitialized series:: + + sage: L. = LazyPowerSeriesRing(QQ) + sage: T = L.undefined(1) + sage: D = L.undefined(0) + sage: T.define(z * exp(T) * D) + sage: T._coeff_stream.is_uninitialized() + True """ if self._target is None: return True From 0eec13deb03de81b262198c22d4b03e024e99ac1 Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Sun, 10 Sep 2023 09:07:20 -0400 Subject: [PATCH 18/93] build/pkgs/patchelf: add Gentoo package information --- build/pkgs/patchelf/distros/gentoo.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 build/pkgs/patchelf/distros/gentoo.txt diff --git a/build/pkgs/patchelf/distros/gentoo.txt b/build/pkgs/patchelf/distros/gentoo.txt new file mode 100644 index 00000000000..5a8e4027272 --- /dev/null +++ b/build/pkgs/patchelf/distros/gentoo.txt @@ -0,0 +1 @@ +dev-util/patchelf From 27100436661dcf5068fda8391896d8f7dc59855a Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Sun, 10 Sep 2023 09:10:17 -0400 Subject: [PATCH 19/93] build/pkgs/patchelf: add spkg-configure.m4 If "patchelf" is in the user's $PATH, we can use it. --- build/pkgs/patchelf/spkg-configure.m4 | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 build/pkgs/patchelf/spkg-configure.m4 diff --git a/build/pkgs/patchelf/spkg-configure.m4 b/build/pkgs/patchelf/spkg-configure.m4 new file mode 100644 index 00000000000..599c23e3f8b --- /dev/null +++ b/build/pkgs/patchelf/spkg-configure.m4 @@ -0,0 +1,4 @@ +SAGE_SPKG_CONFIGURE([patchelf],[ + AC_PATH_PROG(PATCHELF, patchelf) + AS_IF([test -z "${PATCHELF}"], [sage_spkg_install_patchelf=yes]) +]) From d97caa613c751be4498eede257df2be0db1bef9c Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 10 Sep 2023 14:56:21 -0700 Subject: [PATCH 20/93] Revert "build/pkgs/cython/dependencies: Add pythran as an order-only dep" This reverts commit 84ad1a944b36173f050b6a3dd46c84269c31ed82. --- build/pkgs/cython/dependencies | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/pkgs/cython/dependencies b/build/pkgs/cython/dependencies index bda9b4d2579..0738c2d7777 100644 --- a/build/pkgs/cython/dependencies +++ b/build/pkgs/cython/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) pythran +$(PYTHON) | $(PYTHON_TOOLCHAIN) ---------- All lines of this file are ignored except the first. From 587b220d2383c61f0633bd8ddcf958d8017e853d Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 10 Sep 2023 14:56:53 -0700 Subject: [PATCH 21/93] build/pkgs/pythran: Update to 0.14.0 --- build/pkgs/pythran/checksums.ini | 6 +++--- build/pkgs/pythran/package-version.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/pkgs/pythran/checksums.ini b/build/pkgs/pythran/checksums.ini index dc9beccf6b6..2a926b36347 100644 --- a/build/pkgs/pythran/checksums.ini +++ b/build/pkgs/pythran/checksums.ini @@ -1,5 +1,5 @@ tarball=pythran-VERSION.tar.gz -sha1=dd675e9ccc93379b529687328ca558d5617eb1c6 -md5=3090288af50566af75cb058d1878aaad -cksum=3968085663 +sha1=8f997393d123a6185dbf2be0ead588df004c6c4c +md5=2885a2974b9b523439761bfd8bc54f03 +cksum=1307669216 upstream_url=https://pypi.io/packages/source/p/pythran/pythran-VERSION.tar.gz diff --git a/build/pkgs/pythran/package-version.txt b/build/pkgs/pythran/package-version.txt index c317a91891f..a803cc227fe 100644 --- a/build/pkgs/pythran/package-version.txt +++ b/build/pkgs/pythran/package-version.txt @@ -1 +1 @@ -0.13.1 +0.14.0 From e4749c0b24b9e4e17820b8b80fe40db42a3116d6 Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Sun, 10 Sep 2023 18:02:23 -0400 Subject: [PATCH 22/93] build/pkgs/patchelf/distros: add remaining All sourced from, https://repology.org/project/patchelf/versions --- build/pkgs/patchelf/distros/conda.txt | 1 + build/pkgs/patchelf/distros/debian.txt | 1 + build/pkgs/patchelf/distros/fedora.txt | 1 + build/pkgs/patchelf/distros/freebsd.txt | 1 + build/pkgs/patchelf/distros/homebrew.txt | 1 + build/pkgs/patchelf/distros/macports.txt | 1 + build/pkgs/patchelf/distros/nix.txt | 1 + build/pkgs/patchelf/distros/opensuse.txt | 1 + build/pkgs/patchelf/distros/repology.txt | 1 + build/pkgs/patchelf/distros/void.txt | 1 + 10 files changed, 10 insertions(+) create mode 100644 build/pkgs/patchelf/distros/conda.txt create mode 100644 build/pkgs/patchelf/distros/debian.txt create mode 100644 build/pkgs/patchelf/distros/fedora.txt create mode 100644 build/pkgs/patchelf/distros/freebsd.txt create mode 100644 build/pkgs/patchelf/distros/homebrew.txt create mode 100644 build/pkgs/patchelf/distros/macports.txt create mode 100644 build/pkgs/patchelf/distros/nix.txt create mode 100644 build/pkgs/patchelf/distros/opensuse.txt create mode 100644 build/pkgs/patchelf/distros/repology.txt create mode 100644 build/pkgs/patchelf/distros/void.txt diff --git a/build/pkgs/patchelf/distros/conda.txt b/build/pkgs/patchelf/distros/conda.txt new file mode 100644 index 00000000000..fca4680084f --- /dev/null +++ b/build/pkgs/patchelf/distros/conda.txt @@ -0,0 +1 @@ +patchelf diff --git a/build/pkgs/patchelf/distros/debian.txt b/build/pkgs/patchelf/distros/debian.txt new file mode 100644 index 00000000000..fca4680084f --- /dev/null +++ b/build/pkgs/patchelf/distros/debian.txt @@ -0,0 +1 @@ +patchelf diff --git a/build/pkgs/patchelf/distros/fedora.txt b/build/pkgs/patchelf/distros/fedora.txt new file mode 100644 index 00000000000..fca4680084f --- /dev/null +++ b/build/pkgs/patchelf/distros/fedora.txt @@ -0,0 +1 @@ +patchelf diff --git a/build/pkgs/patchelf/distros/freebsd.txt b/build/pkgs/patchelf/distros/freebsd.txt new file mode 100644 index 00000000000..b45345ef8e7 --- /dev/null +++ b/build/pkgs/patchelf/distros/freebsd.txt @@ -0,0 +1 @@ +sysutils/patchelf diff --git a/build/pkgs/patchelf/distros/homebrew.txt b/build/pkgs/patchelf/distros/homebrew.txt new file mode 100644 index 00000000000..fca4680084f --- /dev/null +++ b/build/pkgs/patchelf/distros/homebrew.txt @@ -0,0 +1 @@ +patchelf diff --git a/build/pkgs/patchelf/distros/macports.txt b/build/pkgs/patchelf/distros/macports.txt new file mode 100644 index 00000000000..fca4680084f --- /dev/null +++ b/build/pkgs/patchelf/distros/macports.txt @@ -0,0 +1 @@ +patchelf diff --git a/build/pkgs/patchelf/distros/nix.txt b/build/pkgs/patchelf/distros/nix.txt new file mode 100644 index 00000000000..fca4680084f --- /dev/null +++ b/build/pkgs/patchelf/distros/nix.txt @@ -0,0 +1 @@ +patchelf diff --git a/build/pkgs/patchelf/distros/opensuse.txt b/build/pkgs/patchelf/distros/opensuse.txt new file mode 100644 index 00000000000..fca4680084f --- /dev/null +++ b/build/pkgs/patchelf/distros/opensuse.txt @@ -0,0 +1 @@ +patchelf diff --git a/build/pkgs/patchelf/distros/repology.txt b/build/pkgs/patchelf/distros/repology.txt new file mode 100644 index 00000000000..fca4680084f --- /dev/null +++ b/build/pkgs/patchelf/distros/repology.txt @@ -0,0 +1 @@ +patchelf diff --git a/build/pkgs/patchelf/distros/void.txt b/build/pkgs/patchelf/distros/void.txt new file mode 100644 index 00000000000..fca4680084f --- /dev/null +++ b/build/pkgs/patchelf/distros/void.txt @@ -0,0 +1 @@ +patchelf From d92ae7ccc6622fa7742671d6713dcf0e997dda5d Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 10 Sep 2023 15:13:58 -0700 Subject: [PATCH 23/93] build/pkgs/pythran/dependencies: Remove numpy --- build/pkgs/pythran/dependencies | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/pkgs/pythran/dependencies b/build/pkgs/pythran/dependencies index 8a64589c0bc..b661bb4d3e4 100644 --- a/build/pkgs/pythran/dependencies +++ b/build/pkgs/pythran/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) beniget gast ply numpy | $(PYTHON_TOOLCHAIN) +$(PYTHON) beniget gast ply | $(PYTHON_TOOLCHAIN) ---------- All lines of this file are ignored except the first. From fcc71993653ce62c705b9fd5fc3d793d3ae64163 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 10 Sep 2023 15:14:40 -0700 Subject: [PATCH 24/93] Revert "Revert "build/pkgs/cython/dependencies: Add pythran as an order-only dep"" This reverts commit d97caa613c751be4498eede257df2be0db1bef9c. --- build/pkgs/cython/dependencies | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/pkgs/cython/dependencies b/build/pkgs/cython/dependencies index 0738c2d7777..bda9b4d2579 100644 --- a/build/pkgs/cython/dependencies +++ b/build/pkgs/cython/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) +$(PYTHON) | $(PYTHON_TOOLCHAIN) pythran ---------- All lines of this file are ignored except the first. From 691e23735d2d0e53f411957bf1cd8a08cf3d0136 Mon Sep 17 00:00:00 2001 From: Martin Rubey Date: Tue, 12 Sep 2023 07:48:11 +0200 Subject: [PATCH 25/93] improve check for __invert__ and _div_ --- src/sage/rings/lazy_series.py | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/sage/rings/lazy_series.py b/src/sage/rings/lazy_series.py index 230c70dafa2..2817948dcf2 100644 --- a/src/sage/rings/lazy_series.py +++ b/src/sage/rings/lazy_series.py @@ -57,7 +57,7 @@ sage: f 1 + z + 2*z^2 + 3*z^3 + 5*z^4 + 8*z^5 + 13*z^6 + O(z^7) sage: f^-1 - 1 - z - z^2 + O(z^7) + 1 - z - z^2 sage: f + f^-1 2 + z^2 + 3*z^3 + 5*z^4 + 8*z^5 + 13*z^6 + O(z^7) sage: g = (f + f^-1)*(f - f^-1); g @@ -3256,10 +3256,20 @@ def __invert__(self): Traceback (most recent call last): ... ZeroDivisionError: cannot divide by a series of positive valuation + + Check that :issue:`36253` is fixed:: + + sage: f = L(lambda n: n) + sage: ~f + Traceback (most recent call last): + ... + ZeroDivisionError: cannot divide by a series of positive valuation """ P = self.parent() coeff_stream = self._coeff_stream - if P._minimal_valuation is not None and coeff_stream._approximate_order > 0: + if (P._minimal_valuation is not None + and (coeff_stream._approximate_order > 0 + or not coeff_stream.is_uninitialized() and not coeff_stream[0])): raise ZeroDivisionError("cannot divide by a series of positive valuation") # the inverse is exact if and only if coeff_stream corresponds to one of @@ -3411,9 +3421,11 @@ def _div_(self, other): sage: 1 / f Traceback (most recent call last): ... - ZeroDivisionError: cannot divide by 0 + ZeroDivisionError: cannot divide by a series of positive valuation sage: L.options._reset() """ + if self.is_one(): + return ~other if not other: raise ZeroDivisionError("cannot divide by 0") @@ -4351,6 +4363,7 @@ def revert(self): R = P.base_ring() # we cannot assume that the last initial coefficient # and the constant differ, see stream.Stream_exact + # TODO: provide example or remove this claim if (coeff_stream._degree == 1 + len(coeff_stream._initial_coefficients) and coeff_stream._constant == -R.one() and all(c == -R.one() for c in coeff_stream._initial_coefficients)): From 1ee53b602a7eb27b368a47912f140e50c399787a Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Sun, 10 Sep 2023 19:27:15 -0400 Subject: [PATCH 26/93] build/pkgs/poetry_core: add Gentoo package information --- build/pkgs/poetry_core/distros/gentoo.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 build/pkgs/poetry_core/distros/gentoo.txt diff --git a/build/pkgs/poetry_core/distros/gentoo.txt b/build/pkgs/poetry_core/distros/gentoo.txt new file mode 100644 index 00000000000..758fd6e9e01 --- /dev/null +++ b/build/pkgs/poetry_core/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/poetry-core From 6462f07fc6a9a86d19e3a0819c65cdca587db2e0 Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Sun, 10 Sep 2023 19:28:33 -0400 Subject: [PATCH 27/93] build/pkgs/poetry_core: add standard python spkg-configure.m4 --- build/pkgs/poetry_core/spkg-configure.m4 | 1 + 1 file changed, 1 insertion(+) create mode 100644 build/pkgs/poetry_core/spkg-configure.m4 diff --git a/build/pkgs/poetry_core/spkg-configure.m4 b/build/pkgs/poetry_core/spkg-configure.m4 new file mode 100644 index 00000000000..ae5337520e7 --- /dev/null +++ b/build/pkgs/poetry_core/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([poetry_core], [SAGE_PYTHON_PACKAGE_CHECK([poetry-core])]) From ccd562928e5f767c170c3d657a2c2c2717173dc5 Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Sun, 10 Sep 2023 19:32:02 -0400 Subject: [PATCH 28/93] build/pkgs/asttokens: add Gentoo package information --- build/pkgs/asttokens/distros/gentoo.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 build/pkgs/asttokens/distros/gentoo.txt diff --git a/build/pkgs/asttokens/distros/gentoo.txt b/build/pkgs/asttokens/distros/gentoo.txt new file mode 100644 index 00000000000..4aae3fb6cb4 --- /dev/null +++ b/build/pkgs/asttokens/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/asttokens From 5e0f99762f71dd70a58311d5cb986ba6a64b9050 Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Sun, 10 Sep 2023 19:32:50 -0400 Subject: [PATCH 29/93] build/pkgs/asttokens: add standard python spkg-configure.m4 --- build/pkgs/asttokens/spkg-configure.m4 | 1 + 1 file changed, 1 insertion(+) create mode 100644 build/pkgs/asttokens/spkg-configure.m4 diff --git a/build/pkgs/asttokens/spkg-configure.m4 b/build/pkgs/asttokens/spkg-configure.m4 new file mode 100644 index 00000000000..2221fabfb2b --- /dev/null +++ b/build/pkgs/asttokens/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([asttokens], [SAGE_PYTHON_PACKAGE_CHECK([asttokens])]) From 31725f0b36fe3fd43c2bad66ad2fa2aa7476e0f5 Mon Sep 17 00:00:00 2001 From: Martin Rubey Date: Tue, 12 Sep 2023 16:59:51 +0200 Subject: [PATCH 30/93] replace optional keyword parameter check with checking for uninitialized series --- src/sage/rings/lazy_series.py | 70 ++++++++++++++++------------------- 1 file changed, 31 insertions(+), 39 deletions(-) diff --git a/src/sage/rings/lazy_series.py b/src/sage/rings/lazy_series.py index ee14fd25a3e..a2376550bc1 100644 --- a/src/sage/rings/lazy_series.py +++ b/src/sage/rings/lazy_series.py @@ -1381,7 +1381,7 @@ def define(self, s): sage: E = L(lambda n: s[n], valuation=0) sage: X = L(s[1]) sage: A = L.undefined() - sage: A.define(X*E(A, check=False)) + sage: A.define(X*E(A)) sage: A[:6] [m[1], 2*m[1, 1] + m[2], @@ -3632,7 +3632,7 @@ def exp(self): P = self.parent() R = self.base_ring() coeff_stream = self._coeff_stream - # TODO: coefficients should not be checked here, it prevents + # coefficients must not be checked here, it prevents # us from using self.define in some cases! if ((not coeff_stream.is_uninitialized()) and any(coeff_stream[i] for i in range(coeff_stream._approximate_order, 1))): @@ -3685,7 +3685,7 @@ def log(self): P = self.parent() R = self.base_ring() coeff_stream = self._coeff_stream - # TODO: coefficients should not be checked here, it prevents + # coefficients must not be checked here, it prevents # us from using self.define in some cases! if ((not coeff_stream.is_uninitialized()) and (any(coeff_stream[i] for i in range(coeff_stream._approximate_order, 0)) @@ -3827,7 +3827,7 @@ def _im_gens_(self, codomain, im_gens, base_map=None): return codomain(self.map_coefficients(base_map)(im_gens[0])) - def __call__(self, g, *, check=True): + def __call__(self, g): r""" Return the composition of ``self`` with ``g``. @@ -4221,18 +4221,18 @@ def __call__(self, g, *, check=True): raise NotImplementedError("can only compose with a lazy series") # Perhaps we just don't yet know if the valuation is positive - if check: - if g._coeff_stream._approximate_order <= 0: - if any(g._coeff_stream[i] for i in range(g._coeff_stream._approximate_order, 1)): - raise ValueError("can only compose with a positive valuation series") - g._coeff_stream._approximate_order = 1 + if g._coeff_stream._approximate_order <= 0: + if (not g._coeff_stream.is_uninitialized() + and any(g._coeff_stream[i] for i in range(g._coeff_stream._approximate_order, 1))): + raise ValueError("can only compose with a positive valuation series") + g._coeff_stream._approximate_order = 1 if isinstance(g, LazyDirichletSeries): - if check: - if g._coeff_stream._approximate_order == 1: - if g._coeff_stream[1] != 0: - raise ValueError("can only compose with a positive valuation series") - g._coeff_stream._approximate_order = 2 + if g._coeff_stream._approximate_order == 1: + if (not g._coeff_stream.is_uninitialized() + and g._coeff_stream[1] != 0): + raise ValueError("can only compose with a positive valuation series") + g._coeff_stream._approximate_order = 2 # we assume that the valuation of self[i](g) is at least i def coefficient(n): @@ -4815,7 +4815,7 @@ def _im_gens_(self, codomain, im_gens, base_map=None): return codomain(self.map_coefficients(base_map)(*im_gens)) - def __call__(self, *g, check=True): + def __call__(self, *g): r""" Return the composition of ``self`` with ``g``. @@ -5068,18 +5068,17 @@ def __call__(self, *g, check=True): g = [P(h) for h in g] R = P._internal_poly_ring.base_ring() - if check: - for h in g: - if h._coeff_stream._approximate_order == 0: - if h[0]: - raise ValueError("can only compose with a positive valuation series") - h._coeff_stream._approximate_order = 1 + for h in g: + if h._coeff_stream._approximate_order == 0: + if not h._coeff_stream.is_uninitialized() and h[0]: + raise ValueError("can only compose with a positive valuation series") + h._coeff_stream._approximate_order = 1 - if isinstance(h, LazyDirichletSeries): - if h._coeff_stream._approximate_order == 1: - if h._coeff_stream[1] != 0: - raise ValueError("can only compose with a positive valuation series") - h._coeff_stream._approximate_order = 2 + if isinstance(h, LazyDirichletSeries): + if h._coeff_stream._approximate_order == 1: + if not h._coeff_stream.is_uninitialized() and h._coeff_stream[1] != 0: + raise ValueError("can only compose with a positive valuation series") + h._coeff_stream._approximate_order = 2 # We now have that every element of g has a _coeff_stream sorder = self._coeff_stream._approximate_order @@ -5812,7 +5811,7 @@ def is_unit(self): return False return self[0].is_unit() - def __call__(self, *args, check=True): + def __call__(self, *args): r""" Return the composition of ``self`` with ``g``. @@ -5998,10 +5997,10 @@ def __call__(self, *args, check=True): P = LazySymmetricFunctions(R) g = P(g) - if check and not (isinstance(self._coeff_stream, Stream_exact) - and not self._coeff_stream._constant): + if not (isinstance(self._coeff_stream, Stream_exact) + and not self._coeff_stream._constant): if g._coeff_stream._approximate_order == 0: - if g[0]: + if not g._coeff_stream.is_uninitialized() and g[0]: raise ValueError("can only compose with a positive valuation series") g._coeff_stream._approximate_order = 1 @@ -6401,7 +6400,7 @@ def coefficient(n): else: raise NotImplementedError("only implemented for arity 1") - def arithmetic_product(self, *args, check=True): + def arithmetic_product(self, *args): r""" Return the arithmetic product of ``self`` with ``g``. @@ -6450,9 +6449,6 @@ def arithmetic_product(self, *args, check=True): - ``g`` -- a cycle index series having the same parent as ``self`` - - ``check`` -- (default: ``True``) a Boolean which, when set - to ``False``, will cause input checks to be skipped - OUTPUT: The arithmetic product of ``self`` with ``g``. @@ -6596,15 +6592,11 @@ def arithmetic_product(self, *args, check=True): and not g._coeff_stream._constant): gs = g.symmetric_function() c += self[0].arithmetic_product(gs) - elif check: - raise ValueError("can only take the arithmetic product with a positive valuation series") if g[0]: if (isinstance(self._coeff_stream, Stream_exact) and not self._coeff_stream._constant): fs = self.symmetric_function() c += fs.arithmetic_product(g[0]) - elif check: - raise ValueError("can only take the arithmetic product with a positive valuation series") p = R.realization_of().p() # TODO: does the following introduce a memory leak? @@ -6879,7 +6871,7 @@ def __invert__(self): return P.element_class(P, Stream_dirichlet_invert(self._coeff_stream, P.is_sparse())) - def __call__(self, p, *, check=True): + def __call__(self, p): r""" Return the composition of ``self`` with a linear polynomial ``p``. From 59ef72e4cd65ea1175d43cdd026110d68792c7ac Mon Sep 17 00:00:00 2001 From: dcoudert Date: Sat, 16 Sep 2023 12:58:41 +0200 Subject: [PATCH 31/93] some care with return...else statements --- src/sage/graphs/generic_graph.py | 408 ++++++++++++++----------------- 1 file changed, 185 insertions(+), 223 deletions(-) diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index 1a205d6de34..71a187f6bc4 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -1709,9 +1709,20 @@ def igraph_graph(self, vertex_list=None, vertex_attrs={}, edge_attrs={}): True sage: G.edges(sort=True) == H.edges(sort=True) # optional - python_igraph False + + Check input parameter ``vertex_list``:: + + sage: G = Graph(3) + sage: G.igraph_graph(vertex_list=[]) # optional - python_igraph + Traceback (most recent call last): + ... + ValueError: ``vertex_list`` must be a permutation of the vertices """ if vertex_list is None: - vertex_list = self.vertices(sort=False) + vertex_list = self + elif (len(vertex_list) != self.order() or + set(vertex_list) != set(self)): + raise ValueError("``vertex_list`` must be a permutation of the vertices") v_to_int = {v: i for i, v in enumerate(vertex_list)} edges = [(v_to_int[v], v_to_int[w]) for v, w in self.edge_iterator(labels=False)] @@ -3225,8 +3236,7 @@ def loop_edges(self, labels=True): return [(v, v) for v in self.loop_vertices() for l in self.edge_label(v, v)] elif labels: return [(v, v, self.edge_label(v, v)) for v in self.loop_vertices()] - else: - return [(v, v) for v in self.loop_vertices()] + return [(v, v) for v in self.loop_vertices()] # As discussed in trac 22911, we make method loops an alias for loop_edges loops = loop_edges @@ -3267,8 +3277,7 @@ def loop_vertices(self): """ if self.allows_loops(): return [v for v in self if self.has_edge(v, v)] - else: - return [] + return [] def has_multiple_edges(self, to_undirected=False): """ @@ -4037,8 +4046,7 @@ def antisymmetric(self): g = self.transitive_closure() g.allow_loops(False) return g.is_directed_acyclic() - else: - return self.is_directed_acyclic() + return self.is_directed_acyclic() def density(self): """ @@ -4074,15 +4082,13 @@ def density(self): return Rational(0) if self._directed: return Rational(self.size()) / Rational(n ** 2) - else: - return Rational(self.size()) / Rational((n ** 2 + n) / 2) + return Rational(self.size()) / Rational((n ** 2 + n) / 2) else: if n < 2: return Rational(0) if self._directed: return Rational(self.size()) / Rational((n ** 2 - n)) - else: - return Rational(self.size()) / Rational((n ** 2 - n) / 2) + return Rational(self.size()) / Rational((n ** 2 - n) / 2) def is_bipartite(self, certificate=False): r""" @@ -4143,8 +4149,7 @@ def is_bipartite(self, certificate=False): if self.has_edge(u, u): if certificate: return (False, [u]) - else: - return False + return False color = {} # inheritance of colors along the DFS to recover an odd @@ -4195,8 +4200,7 @@ def is_bipartite(self, certificate=False): return False, cycle - else: - return False + return False # We color a new vertex else: @@ -4206,8 +4210,7 @@ def is_bipartite(self, certificate=False): if certificate: return True, color - else: - return True + return True def is_eulerian(self, path=False): r""" @@ -4616,8 +4619,7 @@ def eulerian_circuit(self, return_vertices=False, labels=True, path=False): if return_vertices: return edges, vertices - else: - return edges + return edges def min_spanning_tree(self, weight_function=None, @@ -4950,8 +4952,7 @@ def cmp_fun(x): E = networkx.minimum_spanning_edges(G, data=False) return [(u, v, self.edge_label(u, v)) if hash(u) < hash(v) else (v, u, self.edge_label(u, v)) for u, v in E] - else: - raise NotImplementedError("minimum spanning tree algorithm '%s' is not implemented" % algorithm) + raise NotImplementedError("minimum spanning tree algorithm '%s' is not implemented" % algorithm) def spanning_trees_count(self, root_vertex=None): r""" @@ -5028,18 +5029,18 @@ def spanning_trees_count(self, root_vertex=None): M.subdivide(1, 1) M2 = M.subdivision(1, 1) return M2.determinant() + + if root_vertex is None: + root_vertex = vertices[0] + index = 0 + elif root_vertex not in vertices: + raise ValueError("vertex (%s) not in the graph" % root_vertex) else: - if root_vertex is None: - root_vertex = vertices[0] - index = 0 - elif root_vertex not in vertices: - raise ValueError("vertex (%s) not in the graph" % root_vertex) - else: - index = vertices.index(root_vertex) + index = vertices.index(root_vertex) - M = self.kirchhoff_matrix(vertices=vertices) - M[index, index] += 1 - return abs(M.determinant()) + M = self.kirchhoff_matrix(vertices=vertices) + M[index, index] += 1 + return abs(M.determinant()) def cycle_basis(self, output='vertex'): r""" @@ -5301,8 +5302,7 @@ def minimum_cycle_basis(self, algorithm=None, weight_function=None, by_weight=Fa basis.append(min_cycle_basis(comp, weight_function=weight_function, by_weight=by_weight)) return sum(basis, []) - else: - raise NotImplementedError("only 'NetworkX' and Cython implementation is supported") + raise NotImplementedError("only 'NetworkX' and Cython implementation is supported") # Planarity @@ -6294,8 +6294,7 @@ def genus(self, set_embedding=True, on_embedding=None, minimal=True, maximal=Fal H = G.subgraph(block) g += genus.simple_connected_graph_genus(H, set_embedding=False, check=False, minimal=True) return g - else: - return genus.simple_connected_graph_genus(G, set_embedding=False, check=False, minimal=minimal) + return genus.simple_connected_graph_genus(G, set_embedding=False, check=False, minimal=minimal) def crossing_number(self): r""" @@ -7808,22 +7807,22 @@ def good_edge(e): if value_only: return obj - else: - edges = [(u, v, l) for u, v, l in g.edge_iterator() if in_cut[good_edge((u, v))]] - val = [obj, edges] - if vertices: - in_set = p.get_values(in_set, convert=bool, tolerance=integrality_tolerance) - a = [] - b = [] - for v in g: - if in_set[0, v]: - a.append(v) - else: - b.append(v) - val.append([a, b]) + edges = [(u, v, l) for u, v, l in g.edge_iterator() if in_cut[good_edge((u, v))]] + val = [obj, edges] + + if vertices: + in_set = p.get_values(in_set, convert=bool, tolerance=integrality_tolerance) + a = [] + b = [] + for v in g: + if in_set[0, v]: + a.append(v) + else: + b.append(v) + val.append([a, b]) - return val + return val def longest_path(self, s=None, t=None, use_edge_labels=False, algorithm="MILP", solver=None, verbose=0, *, integrality_tolerance=1e-3): @@ -8017,12 +8016,12 @@ def longest_path(self, s=None, t=None, use_edge_labels=False, algorithm="MILP", algorithm=algorithm) for g in self.connected_components_subgraphs()), key=lambda x: x[0]) - else: - return max((g.longest_path(s=s, t=t, - use_edge_labels=use_edge_labels, - algorithm=algorithm) - for g in self.connected_components_subgraphs()), - key=lambda x: x.order()) + + return max((g.longest_path(s=s, t=t, + use_edge_labels=use_edge_labels, + algorithm=algorithm) + for g in self.connected_components_subgraphs()), + key=lambda x: x.order()) # Stupid cases # - Graph having <= 1 vertex. @@ -8196,8 +8195,7 @@ def weight(x): if edge_used[frozenset((u, v))])) if use_edge_labels: return sum(map(weight, g.edge_labels())), g - else: - return g + return g def hamiltonian_path(self, s=None, t=None, use_edge_labels=False, maximize=False, algorithm='MILP', solver=None, verbose=0, @@ -9101,8 +9099,7 @@ def hamiltonian_cycle(self, algorithm='tsp', solver=None, constraint_generation= from sage.graphs.generic_graph_pyx import find_hamiltonian as fh return fh(self) - else: - raise ValueError("algorithm (%s) should be 'tsp' or 'backtrack'." % (algorithm)) + raise ValueError("algorithm (%s) should be 'tsp' or 'backtrack'." % (algorithm)) def feedback_vertex_set(self, value_only=False, solver=None, verbose=0, constraint_generation=True, *, integrality_tolerance=1e-3): @@ -9292,8 +9289,7 @@ def feedback_vertex_set(self, value_only=False, solver=None, verbose=0, if isok: if value_only: return Integer(self.order() - h.order()) - else: - return [v for v in self if b_val[v]] + return [v for v in self if b_val[v]] # There is a circuit left. Let's add the corresponding # constraint ! @@ -9335,8 +9331,7 @@ def feedback_vertex_set(self, value_only=False, solver=None, verbose=0, b_sol = p.get_values(b, convert=bool, tolerance=integrality_tolerance) if value_only: return Integer(sum(1 for v in self if b_sol[v])) - else: - return [v for v in self if b_sol[v]] + return [v for v in self if b_sol[v]] def flow(self, x, y, value_only=True, integer=False, use_edge_labels=True, vertex_bound=False, algorithm=None, solver=None, verbose=0, @@ -10688,8 +10683,8 @@ def pagerank(self, alpha=0.85, personalization=None, by_weight=False, I = self.igraph_graph() page_rank = I.pagerank(damping=alpha, weights=weight) return {v: page_rank[i] for i, v in enumerate(self)} - else: - raise NotImplementedError("only 'NetworkX', 'Scipy', and 'igraph' are supported") + + raise NotImplementedError("only 'NetworkX', 'Scipy', and 'igraph' are supported") # Vertex handlers @@ -12804,8 +12799,7 @@ def edge_iterator(self, vertices=None, labels=True, ignore_direction=False, sort return self._backend.iterator_out_edges(vertices, labels) elif not sort_vertices: return self._backend.iterator_unsorted_edges(vertices, labels) - else: - return self._backend.iterator_edges(vertices, labels) + return self._backend.iterator_edges(vertices, labels) def edges_incident(self, vertices=None, labels=True, sort=False): r""" @@ -13095,8 +13089,7 @@ def degree(self, vertices=None, labels=False): return dict(self.degree_iterator(vertices, labels)) elif vertices in self and not labels: return next(self.degree_iterator(vertices, labels)) - else: - return list(self.degree_iterator(vertices, labels)) + return list(self.degree_iterator(vertices, labels)) def average_degree(self): r""" @@ -13490,10 +13483,9 @@ def subgraph(self, vertices=None, edges=None, inplace=False, inplace=inplace, edge_property=edge_property, immutable=immutable) - else: - return self._subgraph_by_adding(vertices=vertices, edges=edges, - edge_property=edge_property, - immutable=immutable) + return self._subgraph_by_adding(vertices=vertices, edges=edges, + edge_property=edge_property, + immutable=immutable) def _subgraph_by_adding(self, vertices=None, edges=None, edge_property=None, immutable=None): r""" @@ -14542,9 +14534,7 @@ def is_chordal(self, certificate=False, algorithm="B"): # 2- The graph is chordal if certificate: return True, peo - - else: - return True + return True def is_circulant(self, certificate=False): r""" @@ -14623,8 +14613,7 @@ def is_circulant(self, certificate=False): if self.order() <= 1: if certificate: return (True, (self.order(), [0] if self.size() else [])) - else: - return True + return True certif_list = [] @@ -14663,11 +14652,9 @@ def is_circulant(self, certificate=False): if not certificate: return False - else: - if certif_list: - return (True, certif_list) - else: - return (False, None) + if certif_list: + return (True, certif_list) + return (False, None) def is_interval(self, certificate=False): r""" @@ -15027,12 +15014,10 @@ def R(u, v): # we only need to check that we have the right set of edges. return len(edges) >= M - else: - # The graph is simple - if G.allows_loops() and not induced and not loops: - return G.size() - len(loop_edges) == M - - return G.size() == M + # The graph is simple + if G.allows_loops() and not induced and not loops: + return G.size() - len(loop_edges) == M + return G.size() == M def is_cycle(self, directed_cycle=True): r""" @@ -15103,11 +15088,11 @@ def is_cycle(self, directed_cycle=True): if g._directed: if directed_cycle: return g.order() == g.size() and g.is_strongly_connected() - else: - # We make a copy of self ignoring the direction of edges - from sage.graphs.graph import Graph - g = Graph(multiedges=True, loops=True) - g.add_edges(self.edge_iterator(labels=False)) + + # We make a copy of self ignoring the direction of edges + from sage.graphs.graph import Graph + g = Graph(multiedges=True, loops=True) + g.add_edges(self.edge_iterator(labels=False)) return g.is_regular(k=2) and g.is_connected() @@ -15251,8 +15236,7 @@ def is_subgraph(self, other, induced=True, up_to_isomorphism=False): # and whether the induced subgraph of ``other`` is contained in ``self``. return (self._backend.is_subgraph(other._backend, self) and other._backend.is_subgraph(self._backend, self)) - else: - return self._backend.is_subgraph(other._backend, self) + return self._backend.is_subgraph(other._backend, self) # Cluster @@ -15401,9 +15385,8 @@ def clustering_average(self, implementation=None): elif implementation == 'networkx': import networkx return networkx.average_clustering(self.networkx_graph()) - else: - coeffs = self.clustering_coeff(implementation=implementation) - return sum(coeffs.values()) / len(coeffs) + coeffs = self.clustering_coeff(implementation=implementation) + return sum(coeffs.values()) / len(coeffs) def clustering_coeff(self, nodes=None, @@ -16026,8 +16009,7 @@ def _girth_bfs(self, odd=False, certificate=False): cycles[x].append(y) u, v = ends return (best, list(reversed(cycles[u])) + cycles[v]) - else: - return best + return best # Centrality @@ -16133,8 +16115,7 @@ def centrality_betweenness(self, k=None, normalized=True, weight=None, weight=weight, endpoints=endpoints, seed=seed) - else: - raise ValueError("'algorithm' can be \"NetworkX\", \"Sage\" or None") + raise ValueError("'algorithm' can be \"NetworkX\", \"Sage\" or None") def centrality_closeness(self, vert=None, by_weight=False, algorithm=None, weight_function=None, check_weight=True): @@ -16389,42 +16370,39 @@ def centrality_closeness(self, vert=None, by_weight=False, algorithm=None, closeness[x] = networkx.closeness_centrality(G, x, distance='weight' if by_weight else None) if onlyone: return closeness.get(vert, None) - else: - return closeness + return closeness elif algorithm == "Johnson_Boost": from sage.graphs.base.boost_graph import johnson_closeness_centrality self.weighted(by_weight) closeness = johnson_closeness_centrality(self, weight_function) if onlyone: return closeness.get(vert, None) + return {v: closeness[v] for v in v_iter if v in closeness} + + closeness = dict() + distances = None + if algorithm in ["Floyd-Warshall-Cython", + "Floyd-Warshall-Python"]: + distances = self.shortest_path_all_pairs(algorithm=algorithm, + by_weight=by_weight, + weight_function=weight_function, + check_weight=False)[0] + + for v in v_iter: + if distances is None: + distv = self.shortest_path_lengths(v, algorithm=algorithm, + by_weight=by_weight, + weight_function=weight_function, + check_weight=False) else: - return {v: closeness[v] for v in v_iter if v in closeness} - else: - closeness = dict() - distances = None - if algorithm in ["Floyd-Warshall-Cython", - "Floyd-Warshall-Python"]: - distances = self.shortest_path_all_pairs(algorithm=algorithm, - by_weight=by_weight, - weight_function=weight_function, - check_weight=False)[0] - - for v in v_iter: - if distances is None: - distv = self.shortest_path_lengths(v, algorithm=algorithm, - by_weight=by_weight, - weight_function=weight_function, - check_weight=False) - else: - distv = distances[v] - try: - closeness[v] = float(len(distv) - 1) * (len(distv) - 1) / (float(sum(distv.values())) * (self.num_verts() - 1)) - except ZeroDivisionError: - pass - if onlyone: - return closeness.get(vert, None) - else: - return closeness + distv = distances[v] + try: + closeness[v] = float(len(distv) - 1) * (len(distv) - 1) / (float(sum(distv.values())) * (self.num_verts() - 1)) + except ZeroDivisionError: + pass + if onlyone: + return closeness.get(vert, None) + return closeness def triangles_count(self, algorithm=None): r""" @@ -16517,30 +16495,28 @@ def triangles_count(self, algorithm=None): from sage.graphs.digraph_generators import digraphs return self.subgraph_search_count(digraphs.Circuit(3)) // 3 - else: - self._scream_if_not_simple() - if algorithm is None: - from sage.graphs.base.dense_graph import DenseGraphBackend - algorithm = ('dense_copy' if isinstance(self._backend, DenseGraphBackend) else - 'sparse_copy') + self._scream_if_not_simple() + if algorithm is None: + from sage.graphs.base.dense_graph import DenseGraphBackend + algorithm = ('dense_copy' if isinstance(self._backend, DenseGraphBackend) else + 'sparse_copy') - if algorithm == 'iter': - tr = 0 - for u in self: - Nu = set(self.neighbors(u)) - for v in Nu: - tr += len(Nu.intersection(self.neighbors(v))) - return Integer(tr // 6) - elif algorithm == "sparse_copy": - from sage.graphs.base.static_sparse_graph import triangles_count - return sum(triangles_count(self).values()) // 3 - elif algorithm == "dense_copy": - from sage.graphs.base.static_dense_graph import triangles_count - return sum(triangles_count(self).values()) // 3 - elif algorithm == 'matrix': - return (self.adjacency_matrix(vertices=list(self))**3).trace() // 6 - else: - raise ValueError('unknown algorithm "{}"'.format(algorithm)) + if algorithm == 'iter': + tr = 0 + for u in self: + Nu = set(self.neighbors(u)) + for v in Nu: + tr += len(Nu.intersection(self.neighbors(v))) + return Integer(tr // 6) + elif algorithm == "sparse_copy": + from sage.graphs.base.static_sparse_graph import triangles_count + return sum(triangles_count(self).values()) // 3 + elif algorithm == "dense_copy": + from sage.graphs.base.static_dense_graph import triangles_count + return sum(triangles_count(self).values()) // 3 + elif algorithm == 'matrix': + return (self.adjacency_matrix(vertices=list(self))**3).trace() // 6 + raise ValueError('unknown algorithm "{}"'.format(algorithm)) def shortest_path(self, u, v, by_weight=False, algorithm=None, weight_function=None, check_weight=True): @@ -16722,8 +16698,7 @@ def shortest_path(self, u, v, by_weight=False, algorithm=None, return [] elif algorithm == "BFS_Bid": return self._backend.shortest_path(u, v) - else: - raise ValueError('unknown algorithm "{}"'.format(algorithm)) + raise ValueError('unknown algorithm "{}"'.format(algorithm)) def shortest_path_length(self, u, v, by_weight=False, algorithm=None, weight_function=None, check_weight=True): @@ -16909,8 +16884,7 @@ def shortest_path_length(self, u, v, by_weight=False, algorithm=None, return Infinity elif algorithm == "BFS_Bid": return self._backend.shortest_path(u, v, distance_flag=True) - else: - raise ValueError('unknown algorithm "{}"'.format(algorithm)) + raise ValueError('unknown algorithm "{}"'.format(algorithm)) def _check_weight_function(self, weight_function=None): r""" @@ -17243,8 +17217,7 @@ def shortest_paths(self, u, by_weight=False, algorithm=None, paths[v] = path return paths - else: - raise ValueError('unknown algorithm "{}"'.format(algorithm)) + raise ValueError('unknown algorithm "{}"'.format(algorithm)) def _path_length(self, path, by_weight=False, weight_function=None): r""" @@ -17310,8 +17283,7 @@ def _path_length(self, path, by_weight=False, weight_function=None): check_weight=False) return sum(weight_function((u, v, self.edge_label(u, v))) for u, v in zip(path[:-1], path[1:])) - else: - return len(path) - 1 + return len(path) - 1 def shortest_path_lengths(self, u, by_weight=False, algorithm=None, weight_function=None, check_weight=True): @@ -17449,8 +17421,7 @@ def shortest_path_lengths(self, u, by_weight=False, algorithm=None, from sage.graphs.base.boost_graph import shortest_paths return shortest_paths(self, u, weight_function, algorithm)[0] - else: - raise ValueError('unknown algorithm "{}"'.format(algorithm)) + raise ValueError('unknown algorithm "{}"'.format(algorithm)) def shortest_path_all_pairs(self, by_weight=False, algorithm=None, weight_function=None, check_weight=True): @@ -19464,19 +19435,17 @@ def transitive_reduction(self): G.add_edge(e) return G - else: - # The transitive reduction of each connected component of an - # undirected graph is a spanning tree - from sage.graphs.graph import Graph - if self.is_connected(): - return Graph(self.min_spanning_tree(weight_function=lambda e: 1)) - else: - G = Graph(list(self)) - for cc in self.connected_components(sort=False): - if len(cc) > 1: - edges = self.subgraph(cc).min_spanning_tree(weight_function=lambda e: 1) - G.add_edges(edges) - return G + # The transitive reduction of each connected component of an + # undirected graph is a spanning tree + from sage.graphs.graph import Graph + if self.is_connected(): + return Graph(self.min_spanning_tree(weight_function=lambda e: 1)) + G = Graph(list(self)) + for cc in self.connected_components(sort=False): + if len(cc) > 1: + edges = self.subgraph(cc).min_spanning_tree(weight_function=lambda e: 1) + G.add_edges(edges) + return G def is_transitively_reduced(self): r""" @@ -20082,13 +20051,12 @@ def layout_forest(self, tree_orientation="down", forest_roots=None, """ if not self: return dict() - else: - # Compute the layout component by component - return layout_split(self.__class__.layout_tree, - self, - tree_orientation=tree_orientation, - forest_roots=forest_roots, - **options) + # Compute the layout component by component + return layout_split(self.__class__.layout_tree, + self, + tree_orientation=tree_orientation, + forest_roots=forest_roots, + **options) def layout_tree(self, tree_orientation="down", tree_root=None, dim=2, **options): @@ -21318,8 +21286,7 @@ def plot3d(self, bgcolor=(1, 1, 1), return TT - else: - raise TypeError("rendering engine (%s) not implemented" % engine) + raise TypeError("rendering engine (%s) not implemented" % engine) def show3d(self, bgcolor=(1, 1, 1), vertex_colors=None, vertex_size=0.06, edge_colors=None, edge_size=0.02, edge_size2=0.0325, @@ -22266,8 +22233,7 @@ def characteristic_polynomial(self, var='x', laplacian=False): """ if laplacian: return self.kirchhoff_matrix(vertices=list(self)).charpoly(var=var) - else: - return self.adjacency_matrix(vertices=list(self)).charpoly(var=var) + return self.adjacency_matrix(vertices=list(self)).charpoly(var=var) # alias, consistent with linear algebra code charpoly = characteristic_polynomial @@ -22850,9 +22816,9 @@ def degree_to_cell(self, vertex, cell): in_neighbors_in_cell = set([a for a, _, _ in self.incoming_edges(vertex)]) & set(cell) out_neighbors_in_cell = set([a for _, a, _ in self.outgoing_edges(vertex)]) & set(cell) return (len(in_neighbors_in_cell), len(out_neighbors_in_cell)) - else: - neighbors_in_cell = set(self.neighbors(vertex)) & set(cell) - return len(neighbors_in_cell) + + neighbors_in_cell = set(self.neighbors(vertex)) & set(cell) + return len(neighbors_in_cell) def is_equitable(self, partition, quotient_matrix=False): """ @@ -22929,13 +22895,13 @@ def is_equitable(self, partition, quotient_matrix=False): else: M[i, j] = degrees[0] return M - else: - for cell1 in partition: - for cell2 in partition: - degrees = [self.degree_to_cell(u, cell2) for u in cell1] - if len(set(degrees)) > 1: - return False - return True + + for cell1 in partition: + for cell2 in partition: + degrees = [self.degree_to_cell(u, cell2) for u in cell1] + if len(set(degrees)) > 1: + return False + return True def coarsest_equitable_refinement(self, partition, sparse=True): r""" @@ -23843,18 +23809,17 @@ def multilabel(e): return False elif not certificate: return True + isom_trans = {} + if edge_labels or self.has_multiple_edges(): + relabeling2_inv = {} + for x in relabeling2: + relabeling2_inv[relabeling2[x]] = x + for v in self: + isom_trans[v] = relabeling2_inv[other_vertices[isom[G_to[relabeling[v]]]]] else: - isom_trans = {} - if edge_labels or self.has_multiple_edges(): - relabeling2_inv = {} - for x in relabeling2: - relabeling2_inv[relabeling2[x]] = x - for v in self: - isom_trans[v] = relabeling2_inv[other_vertices[isom[G_to[relabeling[v]]]]] - else: - for v in self: - isom_trans[v] = other_vertices[isom[G_to[v]]] - return True, isom_trans + for v in self: + isom_trans[v] = other_vertices[isom[G_to[v]]] + return True, isom_trans def canonical_label(self, partition=None, certificate=False, edge_labels=False, algorithm=None, return_graph=True): @@ -24107,8 +24072,7 @@ class by some canonization function `c`. If `G` and `H` are graphs, H.relabel(c_new) if certificate: return H, c_new - else: - return H + return H def is_cayley(self, return_group=False, mapping=False, generators=False, allow_disconnected=False): @@ -24279,8 +24243,7 @@ def is_cayley(self, return_group=False, mapping=False, if generators: out.append(genset) return tuple(out) - else: - return c + return c def is_self_complementary(self): r""" @@ -24529,8 +24492,7 @@ def katz_matrix(self, alpha, nonedgesonly=False, vertices=None): onesmat = matrix(QQ, n, n, lambda i, j: 1) Missing = onesmat - A - In return K.elementwise_product(Missing) - else: - return K + return K def katz_centrality(self, alpha, u=None): r""" @@ -24624,13 +24586,13 @@ def katz_centrality(self, alpha, u=None): verts = list(self) M = self.katz_matrix(alpha, nonedgesonly=False, vertices=verts) return {u: sum(M[i]) for i, u in enumerate(verts)} - else: - K = {} - for g in self.connected_components_subgraphs(): - verts = list(g) - M = g.katz_matrix(alpha, nonedgesonly=False, vertices=verts) - K.update({u: sum(M[i]) for i, u in enumerate(verts)}) - return K + + K = {} + for g in self.connected_components_subgraphs(): + verts = list(g) + M = g.katz_matrix(alpha, nonedgesonly=False, vertices=verts) + K.update({u: sum(M[i]) for i, u in enumerate(verts)}) + return K def edge_polytope(self, backend=None): r""" From 28cf8d90f00b6e18f8e426699d857eeccd0b2aa7 Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Fri, 15 Sep 2023 22:03:15 +0100 Subject: [PATCH 32/93] more spkg-configure.m4 for python packages --- build/pkgs/beautifulsoup4/spkg-configure.m4 | 1 + build/pkgs/jupyter_jsmol/spkg-configure.m4 | 3 +++ build/pkgs/jupyter_packaging/spkg-configure.m4 | 3 +++ build/pkgs/jupyter_sphinx/spkg-configure.m4 | 3 +++ build/pkgs/jupyterlab_widgets/spkg-configure.m4 | 3 +++ build/pkgs/sphinx/spkg-configure.m4 | 3 +++ build/pkgs/sphinx_basic_ng/spkg-configure.m4 | 3 +++ build/pkgs/sphinx_copybutton/spkg-configure.m4 | 3 +++ build/pkgs/sphinxcontrib_websupport/spkg-configure.m4 | 3 +++ build/pkgs/tinycss2/spkg-configure.m4 | 3 +++ 10 files changed, 28 insertions(+) create mode 100644 build/pkgs/beautifulsoup4/spkg-configure.m4 create mode 100644 build/pkgs/jupyter_jsmol/spkg-configure.m4 create mode 100644 build/pkgs/jupyter_packaging/spkg-configure.m4 create mode 100644 build/pkgs/jupyter_sphinx/spkg-configure.m4 create mode 100644 build/pkgs/jupyterlab_widgets/spkg-configure.m4 create mode 100644 build/pkgs/sphinx/spkg-configure.m4 create mode 100644 build/pkgs/sphinx_basic_ng/spkg-configure.m4 create mode 100644 build/pkgs/sphinx_copybutton/spkg-configure.m4 create mode 100644 build/pkgs/sphinxcontrib_websupport/spkg-configure.m4 create mode 100644 build/pkgs/tinycss2/spkg-configure.m4 diff --git a/build/pkgs/beautifulsoup4/spkg-configure.m4 b/build/pkgs/beautifulsoup4/spkg-configure.m4 new file mode 100644 index 00000000000..e9298f00ba4 --- /dev/null +++ b/build/pkgs/beautifulsoup4/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([beautifulsoup4], [SAGE_PYTHON_PACKAGE_CHECK([beautifulsoup4])]) diff --git a/build/pkgs/jupyter_jsmol/spkg-configure.m4 b/build/pkgs/jupyter_jsmol/spkg-configure.m4 new file mode 100644 index 00000000000..202fe5fff31 --- /dev/null +++ b/build/pkgs/jupyter_jsmol/spkg-configure.m4 @@ -0,0 +1,3 @@ +SAGE_SPKG_CONFIGURE([jupyter_jsmol], [ + SAGE_PYTHON_PACKAGE_CHECK([jupyter_jsmol]) +]) diff --git a/build/pkgs/jupyter_packaging/spkg-configure.m4 b/build/pkgs/jupyter_packaging/spkg-configure.m4 new file mode 100644 index 00000000000..2d3ee6280dd --- /dev/null +++ b/build/pkgs/jupyter_packaging/spkg-configure.m4 @@ -0,0 +1,3 @@ +SAGE_SPKG_CONFIGURE([jupyter_packaging], [ + SAGE_PYTHON_PACKAGE_CHECK([jupyter_packaging]) +]) diff --git a/build/pkgs/jupyter_sphinx/spkg-configure.m4 b/build/pkgs/jupyter_sphinx/spkg-configure.m4 new file mode 100644 index 00000000000..e9650c888f8 --- /dev/null +++ b/build/pkgs/jupyter_sphinx/spkg-configure.m4 @@ -0,0 +1,3 @@ +SAGE_SPKG_CONFIGURE([jupyter_sphinx], [ + SAGE_PYTHON_PACKAGE_CHECK([jupyter_sphinx]) +]) diff --git a/build/pkgs/jupyterlab_widgets/spkg-configure.m4 b/build/pkgs/jupyterlab_widgets/spkg-configure.m4 new file mode 100644 index 00000000000..dfea30713eb --- /dev/null +++ b/build/pkgs/jupyterlab_widgets/spkg-configure.m4 @@ -0,0 +1,3 @@ +SAGE_SPKG_CONFIGURE([jupyterlab_widgets], [ + SAGE_PYTHON_PACKAGE_CHECK([jupyterlab_widgets]) +]) diff --git a/build/pkgs/sphinx/spkg-configure.m4 b/build/pkgs/sphinx/spkg-configure.m4 new file mode 100644 index 00000000000..6376e00a02d --- /dev/null +++ b/build/pkgs/sphinx/spkg-configure.m4 @@ -0,0 +1,3 @@ +SAGE_SPKG_CONFIGURE([sphinx], [ + SAGE_PYTHON_PACKAGE_CHECK([sphinx]) +]) diff --git a/build/pkgs/sphinx_basic_ng/spkg-configure.m4 b/build/pkgs/sphinx_basic_ng/spkg-configure.m4 new file mode 100644 index 00000000000..9400cc485e1 --- /dev/null +++ b/build/pkgs/sphinx_basic_ng/spkg-configure.m4 @@ -0,0 +1,3 @@ +SAGE_SPKG_CONFIGURE([sphinx_basic_ng], [ + SAGE_PYTHON_PACKAGE_CHECK([sphinx_basic_ng]) +]) diff --git a/build/pkgs/sphinx_copybutton/spkg-configure.m4 b/build/pkgs/sphinx_copybutton/spkg-configure.m4 new file mode 100644 index 00000000000..8a0d5c983af --- /dev/null +++ b/build/pkgs/sphinx_copybutton/spkg-configure.m4 @@ -0,0 +1,3 @@ +SAGE_SPKG_CONFIGURE([sphinx_copybutton], [ + SAGE_PYTHON_PACKAGE_CHECK([sphinx_copybutton]) +]) diff --git a/build/pkgs/sphinxcontrib_websupport/spkg-configure.m4 b/build/pkgs/sphinxcontrib_websupport/spkg-configure.m4 new file mode 100644 index 00000000000..2a27c8f5802 --- /dev/null +++ b/build/pkgs/sphinxcontrib_websupport/spkg-configure.m4 @@ -0,0 +1,3 @@ +SAGE_SPKG_CONFIGURE([sphinxcontrib_websupport], [ + SAGE_PYTHON_PACKAGE_CHECK([sphinxcontrib_websupport]) +]) diff --git a/build/pkgs/tinycss2/spkg-configure.m4 b/build/pkgs/tinycss2/spkg-configure.m4 new file mode 100644 index 00000000000..a27e98eaa2a --- /dev/null +++ b/build/pkgs/tinycss2/spkg-configure.m4 @@ -0,0 +1,3 @@ +SAGE_SPKG_CONFIGURE([tinycss2], [ + SAGE_PYTHON_PACKAGE_CHECK([tinycss2]) +]) From 264085e6efb6ad98912024654d7428ae27e10b38 Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Sat, 16 Sep 2023 12:48:57 +0100 Subject: [PATCH 33/93] 7.1+ does not work with Sage, cf sagemath/sage/pull/35658 see https://github.com/sagemath/sage/pull/35658, in particular https://github.com/sagemath/sage/pull/35658#issuecomment-1722179207 and later --- build/pkgs/sphinx/install-requires.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/pkgs/sphinx/install-requires.txt b/build/pkgs/sphinx/install-requires.txt index 9003fdec2f8..1ad0ea81a41 100644 --- a/build/pkgs/sphinx/install-requires.txt +++ b/build/pkgs/sphinx/install-requires.txt @@ -1 +1 @@ -sphinx >=5.2, <8 +sphinx >=5.2, <7.1 From 3ad8227315938d59ce1129d4f34094747c6aba79 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 25 Aug 2023 14:34:51 -0700 Subject: [PATCH 34/93] build/pkgs/ipympl: Switch to wheel package --- build/pkgs/ipympl/checksums.ini | 5 +++++ build/pkgs/ipympl/dependencies | 4 +--- build/pkgs/ipympl/package-version.txt | 1 + build/pkgs/ipympl/requirements.txt | 1 - 4 files changed, 7 insertions(+), 4 deletions(-) create mode 100644 build/pkgs/ipympl/checksums.ini create mode 100644 build/pkgs/ipympl/package-version.txt delete mode 100644 build/pkgs/ipympl/requirements.txt diff --git a/build/pkgs/ipympl/checksums.ini b/build/pkgs/ipympl/checksums.ini new file mode 100644 index 00000000000..2c724147c64 --- /dev/null +++ b/build/pkgs/ipympl/checksums.ini @@ -0,0 +1,5 @@ +tarball=ipympl-VERSION-py2.py3-none-any.whl +sha1=9848409026669d9edd83074730d7e2456ae8a187 +md5=e08ec29d29955174178b7230d41a7ff7 +cksum=490103438 +upstream_url=https://pypi.io/packages/py2.py3/i/ipympl/ipympl-VERSION-py2.py3-none-any.whl diff --git a/build/pkgs/ipympl/dependencies b/build/pkgs/ipympl/dependencies index 90b85bcfdbc..b9a86422e74 100644 --- a/build/pkgs/ipympl/dependencies +++ b/build/pkgs/ipympl/dependencies @@ -1,6 +1,4 @@ - ipywidgets matplotlib ipykernel | $(PYTHON_TOOLCHAIN) jupyter_packaging $(PYTHON) +ipython numpy ipython_genutils pillow traitlets ipywidgets matplotlib | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. - -jupyterlab is listed as a "build-system requires", but the package installs correctly without it. diff --git a/build/pkgs/ipympl/package-version.txt b/build/pkgs/ipympl/package-version.txt new file mode 100644 index 00000000000..965065db5b8 --- /dev/null +++ b/build/pkgs/ipympl/package-version.txt @@ -0,0 +1 @@ +0.9.3 diff --git a/build/pkgs/ipympl/requirements.txt b/build/pkgs/ipympl/requirements.txt deleted file mode 100644 index d715db054cd..00000000000 --- a/build/pkgs/ipympl/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -ipympl From a1b6e72ba3e3b4c172afe9783b27606119f6ba9a Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 2 Sep 2023 18:36:50 -0700 Subject: [PATCH 35/93] build/pkgs/pkgconfig: Update to 1.5.5, change to wheel package --- build/pkgs/pkgconfig/SPKG.rst | 13 ++++++------- build/pkgs/pkgconfig/checksums.ini | 10 +++++----- build/pkgs/pkgconfig/dependencies | 2 +- build/pkgs/pkgconfig/install-requires.txt | 2 +- build/pkgs/pkgconfig/spkg-install.in | 8 -------- 5 files changed, 13 insertions(+), 22 deletions(-) delete mode 100644 build/pkgs/pkgconfig/spkg-install.in diff --git a/build/pkgs/pkgconfig/SPKG.rst b/build/pkgs/pkgconfig/SPKG.rst index 3c5d61a167a..9566fb4e409 100644 --- a/build/pkgs/pkgconfig/SPKG.rst +++ b/build/pkgs/pkgconfig/SPKG.rst @@ -1,19 +1,18 @@ -pkgconfig: Python interface to pkg-config -========================================= +pkgconfig: Interface Python with pkg-config +=========================================== Description ----------- -Pkgconfig is a Python module to interface with the pkg-config command -line tool. +Interface Python with pkg-config License ------- -MIT License - +MIT Upstream Contact ---------------- -https://github.com/matze/pkgconfig +https://pypi.org/project/pkgconfig/ + diff --git a/build/pkgs/pkgconfig/checksums.ini b/build/pkgs/pkgconfig/checksums.ini index d3cc48bde60..80d5aac1b27 100644 --- a/build/pkgs/pkgconfig/checksums.ini +++ b/build/pkgs/pkgconfig/checksums.ini @@ -1,5 +1,5 @@ -tarball=pkgconfig-VERSION.tar.gz -sha1=32af6abc220c64b36f745a208b950542b1ab3456 -md5=12523e11b91b050ca49975cc033689a4 -cksum=1707388199 -upstream_url=https://pypi.io/packages/source/p/pkgconfig/pkgconfig-VERSION.tar.gz +tarball=pkgconfig-VERSION-py3-none-any.whl +sha1=bca14b2806a8e8afb0bd04f8e3675550b286dda8 +md5=80f1e06563f3af0f090694db58736455 +cksum=15738577 +upstream_url=https://pypi.io/packages/py3/p/pkgconfig/pkgconfig-VERSION-py3-none-any.whl diff --git a/build/pkgs/pkgconfig/dependencies b/build/pkgs/pkgconfig/dependencies index b52668ccb01..07274d4d9a5 100644 --- a/build/pkgs/pkgconfig/dependencies +++ b/build/pkgs/pkgconfig/dependencies @@ -1,4 +1,4 @@ - | $(PYTHON_TOOLCHAIN) pkgconf poetry_core $(PYTHON) + | pkgconf $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/pkgconfig/install-requires.txt b/build/pkgs/pkgconfig/install-requires.txt index afa452604e3..549fd1bf164 100644 --- a/build/pkgs/pkgconfig/install-requires.txt +++ b/build/pkgs/pkgconfig/install-requires.txt @@ -1 +1 @@ -pkgconfig >=1.5.1 +pkgconfig diff --git a/build/pkgs/pkgconfig/spkg-install.in b/build/pkgs/pkgconfig/spkg-install.in deleted file mode 100644 index d14edc90bcd..00000000000 --- a/build/pkgs/pkgconfig/spkg-install.in +++ /dev/null @@ -1,8 +0,0 @@ -cd src - -sdh_pip_install . - -if [ $? -ne 0 ]; then - echo >&2 "Error installing pkgconfig." - exit 1 -fi From 01ff39e38fffed8797565e17f35d0eb4d1af69aa Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 24 Aug 2023 11:56:07 -0700 Subject: [PATCH 36/93] build/pkgs/widgetsnbextension: Update to 4.0.8 --- build/pkgs/widgetsnbextension/checksums.ini | 6 +++--- build/pkgs/widgetsnbextension/package-version.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/pkgs/widgetsnbextension/checksums.ini b/build/pkgs/widgetsnbextension/checksums.ini index 2b335f09484..725cff285f7 100644 --- a/build/pkgs/widgetsnbextension/checksums.ini +++ b/build/pkgs/widgetsnbextension/checksums.ini @@ -1,5 +1,5 @@ tarball=widgetsnbextension-VERSION.tar.gz -sha1=21f8dc7732adad09921bf590fa0eb0d4c3dd7f48 -md5=2d44896382b3a587823e08df6d2f3165 -cksum=209268639 +sha1=b5d01e48dbf258264abef72e34c83a12da938842 +md5=06421deddf129f9dc26d4458b6a6381e +cksum=2456830638 upstream_url=https://pypi.io/packages/source/w/widgetsnbextension/widgetsnbextension-VERSION.tar.gz diff --git a/build/pkgs/widgetsnbextension/package-version.txt b/build/pkgs/widgetsnbextension/package-version.txt index c4e41f94594..a2cec7aff41 100644 --- a/build/pkgs/widgetsnbextension/package-version.txt +++ b/build/pkgs/widgetsnbextension/package-version.txt @@ -1 +1 @@ -4.0.3 +4.0.8 From 7fda18ce02f94127d337eafbd3c1db853916aae1 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 25 Aug 2023 14:43:33 -0700 Subject: [PATCH 37/93] build/pkgs/widgetsnbextension: Change to wheel package --- build/pkgs/widgetsnbextension/SPKG.rst | 17 ++++++++++++++--- build/pkgs/widgetsnbextension/checksums.ini | 10 +++++----- build/pkgs/widgetsnbextension/dependencies | 2 +- .../widgetsnbextension/install-requires.txt | 2 +- build/pkgs/widgetsnbextension/spkg-install.in | 1 - 5 files changed, 21 insertions(+), 11 deletions(-) delete mode 100644 build/pkgs/widgetsnbextension/spkg-install.in diff --git a/build/pkgs/widgetsnbextension/SPKG.rst b/build/pkgs/widgetsnbextension/SPKG.rst index 8ebc9468f32..8788fa7c034 100644 --- a/build/pkgs/widgetsnbextension/SPKG.rst +++ b/build/pkgs/widgetsnbextension/SPKG.rst @@ -1,7 +1,18 @@ -widgetsnbextension: Jupyter notebook extension for interactive HTML widgets -=========================================================================== +widgetsnbextension: Jupyter interactive widgets for Jupyter Notebook +==================================================================== Description ----------- -Interactive HTML widgets for Jupyter notebooks. +Jupyter interactive widgets for Jupyter Notebook + +License +------- + +BSD 3-Clause License + +Upstream Contact +---------------- + +https://pypi.org/project/widgetsnbextension/ + diff --git a/build/pkgs/widgetsnbextension/checksums.ini b/build/pkgs/widgetsnbextension/checksums.ini index 725cff285f7..30e08312a8f 100644 --- a/build/pkgs/widgetsnbextension/checksums.ini +++ b/build/pkgs/widgetsnbextension/checksums.ini @@ -1,5 +1,5 @@ -tarball=widgetsnbextension-VERSION.tar.gz -sha1=b5d01e48dbf258264abef72e34c83a12da938842 -md5=06421deddf129f9dc26d4458b6a6381e -cksum=2456830638 -upstream_url=https://pypi.io/packages/source/w/widgetsnbextension/widgetsnbextension-VERSION.tar.gz +tarball=widgetsnbextension-VERSION-py3-none-any.whl +sha1=1ffb84b17fca00a6e4bbad41f395ed6f37e1c6b9 +md5=38786a4166938b1b4165a76c244c3fc9 +cksum=2255132975 +upstream_url=https://pypi.io/packages/py3/w/widgetsnbextension/widgetsnbextension-VERSION-py3-none-any.whl diff --git a/build/pkgs/widgetsnbextension/dependencies b/build/pkgs/widgetsnbextension/dependencies index 301cefdea49..b5af54575fc 100644 --- a/build/pkgs/widgetsnbextension/dependencies +++ b/build/pkgs/widgetsnbextension/dependencies @@ -1,4 +1,4 @@ - jupyter_packaging | $(PYTHON_TOOLCHAIN) jupyter_core $(PYTHON) +jupyter_core | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/widgetsnbextension/install-requires.txt b/build/pkgs/widgetsnbextension/install-requires.txt index 1b446d635a2..c6d44d55e1f 100644 --- a/build/pkgs/widgetsnbextension/install-requires.txt +++ b/build/pkgs/widgetsnbextension/install-requires.txt @@ -1 +1 @@ -widgetsnbextension >=3.5.1 +widgetsnbextension diff --git a/build/pkgs/widgetsnbextension/spkg-install.in b/build/pkgs/widgetsnbextension/spkg-install.in deleted file mode 100644 index deba1bb42bb..00000000000 --- a/build/pkgs/widgetsnbextension/spkg-install.in +++ /dev/null @@ -1 +0,0 @@ -cd src && sdh_pip_install . From 4ece267acadb446bae5ff8b616f2bb574f593ba3 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 14 Sep 2023 11:07:58 -0700 Subject: [PATCH 38/93] build/pkgs/poetry_core: Remove --- build/pkgs/poetry_core/SPKG.rst | 18 ------------------ build/pkgs/poetry_core/checksums.ini | 5 ----- build/pkgs/poetry_core/dependencies | 4 ---- build/pkgs/poetry_core/distros/conda.txt | 1 - build/pkgs/poetry_core/install-requires.txt | 1 - build/pkgs/poetry_core/package-version.txt | 1 - build/pkgs/poetry_core/patches/5547.diff_bin | 12 ------------ build/pkgs/poetry_core/spkg-install.in | 4 ---- build/pkgs/poetry_core/type | 1 - 9 files changed, 47 deletions(-) delete mode 100644 build/pkgs/poetry_core/SPKG.rst delete mode 100644 build/pkgs/poetry_core/checksums.ini delete mode 100644 build/pkgs/poetry_core/dependencies delete mode 100644 build/pkgs/poetry_core/distros/conda.txt delete mode 100644 build/pkgs/poetry_core/install-requires.txt delete mode 100644 build/pkgs/poetry_core/package-version.txt delete mode 100644 build/pkgs/poetry_core/patches/5547.diff_bin delete mode 100644 build/pkgs/poetry_core/spkg-install.in delete mode 100644 build/pkgs/poetry_core/type diff --git a/build/pkgs/poetry_core/SPKG.rst b/build/pkgs/poetry_core/SPKG.rst deleted file mode 100644 index 6a65756f4ec..00000000000 --- a/build/pkgs/poetry_core/SPKG.rst +++ /dev/null @@ -1,18 +0,0 @@ -poetry_core: Poetry PEP 517 Build Backend -========================================= - -Description ------------ - -Poetry PEP 517 Build Backend - -License -------- - -MIT - -Upstream Contact ----------------- - -https://pypi.org/project/poetry-core/ - diff --git a/build/pkgs/poetry_core/checksums.ini b/build/pkgs/poetry_core/checksums.ini deleted file mode 100644 index bef11e2f92c..00000000000 --- a/build/pkgs/poetry_core/checksums.ini +++ /dev/null @@ -1,5 +0,0 @@ -tarball=poetry-core-VERSION.tar.gz -sha1=67c8e65065f751c87cadf973a0a2d7b2cfad3bfa -md5=8cc4e6bf435733d91bb1b2fd7ec85749 -cksum=2571863917 -upstream_url=https://pypi.io/packages/source/p/poetry_core/poetry-core-VERSION.tar.gz diff --git a/build/pkgs/poetry_core/dependencies b/build/pkgs/poetry_core/dependencies deleted file mode 100644 index 47296a7bace..00000000000 --- a/build/pkgs/poetry_core/dependencies +++ /dev/null @@ -1,4 +0,0 @@ - | $(PYTHON_TOOLCHAIN) $(PYTHON) - ----------- -All lines of this file are ignored except the first. diff --git a/build/pkgs/poetry_core/distros/conda.txt b/build/pkgs/poetry_core/distros/conda.txt deleted file mode 100644 index 9b1f9e3fa7d..00000000000 --- a/build/pkgs/poetry_core/distros/conda.txt +++ /dev/null @@ -1 +0,0 @@ -poetry-core diff --git a/build/pkgs/poetry_core/install-requires.txt b/build/pkgs/poetry_core/install-requires.txt deleted file mode 100644 index 9b1f9e3fa7d..00000000000 --- a/build/pkgs/poetry_core/install-requires.txt +++ /dev/null @@ -1 +0,0 @@ -poetry-core diff --git a/build/pkgs/poetry_core/package-version.txt b/build/pkgs/poetry_core/package-version.txt deleted file mode 100644 index b0f3d96f877..00000000000 --- a/build/pkgs/poetry_core/package-version.txt +++ /dev/null @@ -1 +0,0 @@ -1.0.8 diff --git a/build/pkgs/poetry_core/patches/5547.diff_bin b/build/pkgs/poetry_core/patches/5547.diff_bin deleted file mode 100644 index f4f5f4c83b8..00000000000 --- a/build/pkgs/poetry_core/patches/5547.diff_bin +++ /dev/null @@ -1,12 +0,0 @@ -diff -urB a/poetry/core/vcs/__init__.py b/poetry/core/vcs/__init__.py ---- a/poetry/core/vcs/__init__.py 2022-02-27 20:15:29.000000000 -0800 -+++ b/poetry/core/vcs/__init__.py 2022-05-05 10:26:37.248645073 -0700 -@@ -20,7 +20,7 @@ - ) - ).strip() - -- vcs = Git(Path(git_dir)) -+ vcs = Git(Path(git_dir)) if git_dir.startswith(str(directory.resolve())) else None - - except (subprocess.CalledProcessError, OSError, RuntimeError): - vcs = None diff --git a/build/pkgs/poetry_core/spkg-install.in b/build/pkgs/poetry_core/spkg-install.in deleted file mode 100644 index 4dc571e2c62..00000000000 --- a/build/pkgs/poetry_core/spkg-install.in +++ /dev/null @@ -1,4 +0,0 @@ -cd src -# Work around https://github.com/python-poetry/poetry/issues/5547 -patch -p1 --posix --binary < "../patches/5547.diff_bin" || sdh_die -sdh_pip_install . diff --git a/build/pkgs/poetry_core/type b/build/pkgs/poetry_core/type deleted file mode 100644 index a6a7b9cd726..00000000000 --- a/build/pkgs/poetry_core/type +++ /dev/null @@ -1 +0,0 @@ -standard From 1571d287448cb70b01f83b3453317abafa93b12f Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 25 Aug 2023 14:45:37 -0700 Subject: [PATCH 39/93] build/pkgs/jupyter_packaging: Remove --- build/pkgs/jupyter_packaging/SPKG.rst | 18 ------------------ build/pkgs/jupyter_packaging/checksums.ini | 5 ----- build/pkgs/jupyter_packaging/dependencies | 4 ---- build/pkgs/jupyter_packaging/distros/conda.txt | 1 - .../jupyter_packaging/install-requires.txt | 1 - .../pkgs/jupyter_packaging/package-version.txt | 1 - build/pkgs/jupyter_packaging/spkg-install.in | 2 -- build/pkgs/jupyter_packaging/type | 1 - 8 files changed, 33 deletions(-) delete mode 100644 build/pkgs/jupyter_packaging/SPKG.rst delete mode 100644 build/pkgs/jupyter_packaging/checksums.ini delete mode 100644 build/pkgs/jupyter_packaging/dependencies delete mode 100644 build/pkgs/jupyter_packaging/distros/conda.txt delete mode 100644 build/pkgs/jupyter_packaging/install-requires.txt delete mode 100644 build/pkgs/jupyter_packaging/package-version.txt delete mode 100644 build/pkgs/jupyter_packaging/spkg-install.in delete mode 100644 build/pkgs/jupyter_packaging/type diff --git a/build/pkgs/jupyter_packaging/SPKG.rst b/build/pkgs/jupyter_packaging/SPKG.rst deleted file mode 100644 index 7e6a0bcfd8a..00000000000 --- a/build/pkgs/jupyter_packaging/SPKG.rst +++ /dev/null @@ -1,18 +0,0 @@ -jupyter_packaging: Jupyter Packaging Utilities -============================================== - -Description ------------ - -Jupyter Packaging Utilities - -License -------- - -BSD - -Upstream Contact ----------------- - -https://pypi.org/project/jupyter-packaging/ - diff --git a/build/pkgs/jupyter_packaging/checksums.ini b/build/pkgs/jupyter_packaging/checksums.ini deleted file mode 100644 index 65b3bd148f6..00000000000 --- a/build/pkgs/jupyter_packaging/checksums.ini +++ /dev/null @@ -1,5 +0,0 @@ -tarball=jupyter_packaging-VERSION.tar.gz -sha1=092d249360aa56838a188decc4bcd09647fda4d9 -md5=9c6834023bd699bda5365ab7ed18bde2 -cksum=3308833189 -upstream_url=https://pypi.io/packages/source/j/jupyter_packaging/jupyter_packaging-VERSION.tar.gz diff --git a/build/pkgs/jupyter_packaging/dependencies b/build/pkgs/jupyter_packaging/dependencies deleted file mode 100644 index 11e420a0a7b..00000000000 --- a/build/pkgs/jupyter_packaging/dependencies +++ /dev/null @@ -1,4 +0,0 @@ - packaging deprecation tomlkit | $(PYTHON_TOOLCHAIN) hatchling $(PYTHON) - ----------- -All lines of this file are ignored except the first. diff --git a/build/pkgs/jupyter_packaging/distros/conda.txt b/build/pkgs/jupyter_packaging/distros/conda.txt deleted file mode 100644 index 9cefa40dbb7..00000000000 --- a/build/pkgs/jupyter_packaging/distros/conda.txt +++ /dev/null @@ -1 +0,0 @@ -# jupyter-packaging # only a build dependency, not needed at runtime; conda package does not support Python 3.11 as of 2023-05 diff --git a/build/pkgs/jupyter_packaging/install-requires.txt b/build/pkgs/jupyter_packaging/install-requires.txt deleted file mode 100644 index b5ec61b7d14..00000000000 --- a/build/pkgs/jupyter_packaging/install-requires.txt +++ /dev/null @@ -1 +0,0 @@ -jupyter-packaging diff --git a/build/pkgs/jupyter_packaging/package-version.txt b/build/pkgs/jupyter_packaging/package-version.txt deleted file mode 100644 index aa22d3ce39b..00000000000 --- a/build/pkgs/jupyter_packaging/package-version.txt +++ /dev/null @@ -1 +0,0 @@ -0.12.3 diff --git a/build/pkgs/jupyter_packaging/spkg-install.in b/build/pkgs/jupyter_packaging/spkg-install.in deleted file mode 100644 index 37ac1a53437..00000000000 --- a/build/pkgs/jupyter_packaging/spkg-install.in +++ /dev/null @@ -1,2 +0,0 @@ -cd src -sdh_pip_install . diff --git a/build/pkgs/jupyter_packaging/type b/build/pkgs/jupyter_packaging/type deleted file mode 100644 index a6a7b9cd726..00000000000 --- a/build/pkgs/jupyter_packaging/type +++ /dev/null @@ -1 +0,0 @@ -standard From 68dc2d830529119fac797c68cd344ae406aaf1d8 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 25 Aug 2023 14:48:24 -0700 Subject: [PATCH 40/93] build/pkgs/tomlkit: Remove --- build/pkgs/tomlkit/SPKG.rst | 18 ------------------ build/pkgs/tomlkit/checksums.ini | 5 ----- build/pkgs/tomlkit/dependencies | 4 ---- build/pkgs/tomlkit/distros/conda.txt | 1 - build/pkgs/tomlkit/install-requires.txt | 1 - build/pkgs/tomlkit/package-version.txt | 1 - build/pkgs/tomlkit/spkg-install.in | 2 -- build/pkgs/tomlkit/type | 1 - 8 files changed, 33 deletions(-) delete mode 100644 build/pkgs/tomlkit/SPKG.rst delete mode 100644 build/pkgs/tomlkit/checksums.ini delete mode 100644 build/pkgs/tomlkit/dependencies delete mode 100644 build/pkgs/tomlkit/distros/conda.txt delete mode 100644 build/pkgs/tomlkit/install-requires.txt delete mode 100644 build/pkgs/tomlkit/package-version.txt delete mode 100644 build/pkgs/tomlkit/spkg-install.in delete mode 100644 build/pkgs/tomlkit/type diff --git a/build/pkgs/tomlkit/SPKG.rst b/build/pkgs/tomlkit/SPKG.rst deleted file mode 100644 index ebb77909ba7..00000000000 --- a/build/pkgs/tomlkit/SPKG.rst +++ /dev/null @@ -1,18 +0,0 @@ -tomlkit: Style preserving TOML library -====================================== - -Description ------------ - -Style preserving TOML library - -License -------- - -MIT - -Upstream Contact ----------------- - -https://pypi.org/project/tomlkit/ - diff --git a/build/pkgs/tomlkit/checksums.ini b/build/pkgs/tomlkit/checksums.ini deleted file mode 100644 index 545bb2bc02b..00000000000 --- a/build/pkgs/tomlkit/checksums.ini +++ /dev/null @@ -1,5 +0,0 @@ -tarball=tomlkit-VERSION.tar.gz -sha1=b097f71385b3b693a41a23ecd551959faae73e0d -md5=ac33a015aa5f3f8e8e0667081b388bb7 -cksum=785586052 -upstream_url=https://pypi.io/packages/source/t/tomlkit/tomlkit-VERSION.tar.gz diff --git a/build/pkgs/tomlkit/dependencies b/build/pkgs/tomlkit/dependencies deleted file mode 100644 index e67b4c08948..00000000000 --- a/build/pkgs/tomlkit/dependencies +++ /dev/null @@ -1,4 +0,0 @@ - | $(PYTHON_TOOLCHAIN) poetry_core $(PYTHON) - ----------- -All lines of this file are ignored except the first. diff --git a/build/pkgs/tomlkit/distros/conda.txt b/build/pkgs/tomlkit/distros/conda.txt deleted file mode 100644 index 8141b831035..00000000000 --- a/build/pkgs/tomlkit/distros/conda.txt +++ /dev/null @@ -1 +0,0 @@ -tomlkit diff --git a/build/pkgs/tomlkit/install-requires.txt b/build/pkgs/tomlkit/install-requires.txt deleted file mode 100644 index 8141b831035..00000000000 --- a/build/pkgs/tomlkit/install-requires.txt +++ /dev/null @@ -1 +0,0 @@ -tomlkit diff --git a/build/pkgs/tomlkit/package-version.txt b/build/pkgs/tomlkit/package-version.txt deleted file mode 100644 index e5cbde33e62..00000000000 --- a/build/pkgs/tomlkit/package-version.txt +++ /dev/null @@ -1 +0,0 @@ -0.11.6 diff --git a/build/pkgs/tomlkit/spkg-install.in b/build/pkgs/tomlkit/spkg-install.in deleted file mode 100644 index 37ac1a53437..00000000000 --- a/build/pkgs/tomlkit/spkg-install.in +++ /dev/null @@ -1,2 +0,0 @@ -cd src -sdh_pip_install . diff --git a/build/pkgs/tomlkit/type b/build/pkgs/tomlkit/type deleted file mode 100644 index a6a7b9cd726..00000000000 --- a/build/pkgs/tomlkit/type +++ /dev/null @@ -1 +0,0 @@ -standard From 94b3aeca2f145d34c04decf42eead578d57b3ff5 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 14 Sep 2023 11:39:03 -0700 Subject: [PATCH 41/93] build/pkgs/pkgconfig/SPKG.rst: Restore hand-edited version --- build/pkgs/pkgconfig/SPKG.rst | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/build/pkgs/pkgconfig/SPKG.rst b/build/pkgs/pkgconfig/SPKG.rst index 9566fb4e409..3c5d61a167a 100644 --- a/build/pkgs/pkgconfig/SPKG.rst +++ b/build/pkgs/pkgconfig/SPKG.rst @@ -1,18 +1,19 @@ -pkgconfig: Interface Python with pkg-config -=========================================== +pkgconfig: Python interface to pkg-config +========================================= Description ----------- -Interface Python with pkg-config +Pkgconfig is a Python module to interface with the pkg-config command +line tool. License ------- -MIT +MIT License + Upstream Contact ---------------- -https://pypi.org/project/pkgconfig/ - +https://github.com/matze/pkgconfig From 77aa9f1f2f87fa8daa28f27c2d167c14b6ef27e8 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 14 Sep 2023 14:40:14 -0700 Subject: [PATCH 42/93] configure --disable-notebook: Disable ipympl --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 532da2165e8..0f2bf7f3cf5 100644 --- a/configure.ac +++ b/configure.ac @@ -507,7 +507,7 @@ AC_ARG_ENABLE([cvxopt], AC_ARG_ENABLE([notebook], AS_HELP_STRING([--disable-notebook], [disable build of the Jupyter notebook and related packages]), [ - for pkg in notebook nbconvert beautifulsoup4 sagenb_export nbformat nbclient terminado send2trash prometheus_client mistune pandocfilters bleach defusedxml jsonschema jupyter_jsmol argon2_cffi webencodings tinycss2; do + for pkg in notebook nbconvert beautifulsoup4 sagenb_export nbformat nbclient terminado send2trash prometheus_client mistune pandocfilters bleach defusedxml jsonschema jupyter_jsmol argon2_cffi webencodings tinycss2 ipympl; do AS_VAR_SET([SAGE_ENABLE_$pkg], [$enableval]) done ]) From 5875178fe908144f82d5474164daf334a0ad6258 Mon Sep 17 00:00:00 2001 From: dcoudert Date: Sun, 17 Sep 2023 12:09:46 +0200 Subject: [PATCH 43/93] PR #36275: remove rst syntax from error messages --- src/sage/graphs/generic_graph.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index 00d0225fd4c..3974716e4ff 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -1716,13 +1716,13 @@ def igraph_graph(self, vertex_list=None, vertex_attrs={}, edge_attrs={}): sage: G.igraph_graph(vertex_list=[]) # optional - python_igraph Traceback (most recent call last): ... - ValueError: ``vertex_list`` must be a permutation of the vertices + ValueError: parameter vertex_list must be a permutation of the vertices """ if vertex_list is None: vertex_list = self elif (len(vertex_list) != self.order() or set(vertex_list) != set(self)): - raise ValueError("``vertex_list`` must be a permutation of the vertices") + raise ValueError("parameter vertex_list must be a permutation of the vertices") v_to_int = {v: i for i, v in enumerate(vertex_list)} edges = [(v_to_int[v], v_to_int[w]) for v, w in self.edge_iterator(labels=False)] @@ -2031,11 +2031,11 @@ def adjacency_matrix(self, sparse=None, vertices=None, *, base_ring=None, **kwds sage: graphs.PathGraph(5).adjacency_matrix(vertices=[0,0,0,0,0]) # needs sage.modules Traceback (most recent call last): ... - ValueError: ``vertices`` must be a permutation of the vertices + ValueError: parameter vertices must be a permutation of the vertices sage: graphs.PathGraph(5).adjacency_matrix(vertices=[1,2,3]) # needs sage.modules Traceback (most recent call last): ... - ValueError: ``vertices`` must be a permutation of the vertices + ValueError: parameter vertices must be a permutation of the vertices sage: Graph ([[0, 42, 'John'], [(42, 'John')]]).adjacency_matrix() Traceback (most recent call last): ... @@ -2060,7 +2060,7 @@ def adjacency_matrix(self, sparse=None, vertices=None, *, base_ring=None, **kwds "``vertices``") elif (len(vertices) != n or set(vertices) != set(self.vertex_iterator())): - raise ValueError("``vertices`` must be a permutation of the vertices") + raise ValueError("parameter vertices must be a permutation of the vertices") new_indices = {v: i for i, v in enumerate(vertices)} D = {} @@ -2258,11 +2258,11 @@ def incidence_matrix(self, oriented=None, sparse=True, vertices=None, edges=None sage: P5.incidence_matrix(vertices=[1] * P5.order()) # needs sage.modules Traceback (most recent call last): ... - ValueError: ``vertices`` must be a permutation of the vertices + ValueError: parameter vertices must be a permutation of the vertices sage: P5.incidence_matrix(edges=[(0, 1)] * P5.size()) # needs sage.modules Traceback (most recent call last): ... - ValueError: ``edges`` must be a permutation of the edges + ValueError: parameter edges must be a permutation of the edges sage: P5.incidence_matrix(edges=P5.edges(sort=False, labels=True)) # needs sage.modules [1 0 0 0] [1 1 0 0] @@ -2277,13 +2277,13 @@ def incidence_matrix(self, oriented=None, sparse=True, vertices=None, edges=None vertices = self.vertices(sort=False) elif (len(vertices) != self.num_verts() or set(vertices) != set(self.vertex_iterator())): - raise ValueError("``vertices`` must be a permutation of the vertices") + raise ValueError("parameter vertices must be a permutation of the vertices") verts = {v: i for i, v in enumerate(vertices)} if edges is None: edges = self.edge_iterator(labels=False) elif len(edges) != self.size(): - raise ValueError("``edges`` must be a permutation of the edges") + raise ValueError("parameter edges must be a permutation of the edges") else: # We check that we have the same set of unlabeled edges if oriented: @@ -2295,7 +2295,7 @@ def reorder(u, v): i_edges = [reorder(verts[e[0]], verts[e[1]]) for e in edges] s_edges = [reorder(verts[u], verts[v]) for u, v in self.edge_iterator(labels=False)] if sorted(i_edges) != sorted(s_edges): - raise ValueError("``edges`` must be a permutation of the edges") + raise ValueError("parameter edges must be a permutation of the edges") from sage.matrix.constructor import matrix if base_ring is None: @@ -2425,7 +2425,7 @@ def distance_matrix(self, vertices=None, *, base_ring=None, **kwds): vertices = self.vertices(sort=True) elif (len(vertices) != self.order() or set(vertices) != set(self.vertex_iterator())): - raise ValueError("``vertices`` must be a permutation of the vertices") + raise ValueError("parameter vertices must be a permutation of the vertices") # We extract from **kwds the arguments for distance_all_pairs keys = ['by_weight', 'algorithm', 'weight_function', 'check_weight'] @@ -2559,7 +2559,7 @@ def weighted_adjacency_matrix(self, sparse=True, vertices=None, vertices = self.vertices(sort=True) elif (len(vertices) != self.num_verts() or set(vertices) != set(self.vertex_iterator())): - raise ValueError("``vertices`` must be a permutation of the vertices") + raise ValueError("parameter vertices must be a permutation of the vertices") # Method for checking edge weights and setting default weight if default_weight is None: @@ -24501,7 +24501,7 @@ def katz_matrix(self, alpha, nonedgesonly=False, vertices=None): vertices = self.vertices(sort=True) elif (len(vertices) != n or set(vertices) != set(self)): - raise ValueError("``vertices`` must be a permutation of the vertices") + raise ValueError("parameter vertices must be a permutation of the vertices") A = self.adjacency_matrix(vertices=vertices) From a3cade03fa90e1410fb2990f52c6facabd767ec2 Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Sat, 16 Sep 2023 14:23:40 +0100 Subject: [PATCH 44/93] more spkg_configure.m4 for Python packages --- build/pkgs/beautifulsoup4/spkg-configure.m4 | 1 + build/pkgs/jupyter_jsmol/spkg-configure.m4 | 3 +++ build/pkgs/jupyter_packaging/spkg-configure.m4 | 3 +++ build/pkgs/jupyter_sphinx/spkg-configure.m4 | 3 +++ build/pkgs/jupyterlab_widgets/spkg-configure.m4 | 3 +++ build/pkgs/setuptools_scm_git_archive/spkg-configure.m4 | 1 + build/pkgs/setuptools_wheel/spkg-configure.m4 | 1 + build/pkgs/sphinx/spkg-configure.m4 | 3 +++ build/pkgs/sphinx_basic_ng/spkg-configure.m4 | 3 +++ build/pkgs/sphinx_copybutton/spkg-configure.m4 | 3 +++ build/pkgs/sphinxcontrib_websupport/spkg-configure.m4 | 3 +++ build/pkgs/tinycss2/spkg-configure.m4 | 3 +++ 12 files changed, 30 insertions(+) create mode 100644 build/pkgs/beautifulsoup4/spkg-configure.m4 create mode 100644 build/pkgs/jupyter_jsmol/spkg-configure.m4 create mode 100644 build/pkgs/jupyter_packaging/spkg-configure.m4 create mode 100644 build/pkgs/jupyter_sphinx/spkg-configure.m4 create mode 100644 build/pkgs/jupyterlab_widgets/spkg-configure.m4 create mode 100644 build/pkgs/setuptools_scm_git_archive/spkg-configure.m4 create mode 100644 build/pkgs/setuptools_wheel/spkg-configure.m4 create mode 100644 build/pkgs/sphinx/spkg-configure.m4 create mode 100644 build/pkgs/sphinx_basic_ng/spkg-configure.m4 create mode 100644 build/pkgs/sphinx_copybutton/spkg-configure.m4 create mode 100644 build/pkgs/sphinxcontrib_websupport/spkg-configure.m4 create mode 100644 build/pkgs/tinycss2/spkg-configure.m4 diff --git a/build/pkgs/beautifulsoup4/spkg-configure.m4 b/build/pkgs/beautifulsoup4/spkg-configure.m4 new file mode 100644 index 00000000000..e9298f00ba4 --- /dev/null +++ b/build/pkgs/beautifulsoup4/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([beautifulsoup4], [SAGE_PYTHON_PACKAGE_CHECK([beautifulsoup4])]) diff --git a/build/pkgs/jupyter_jsmol/spkg-configure.m4 b/build/pkgs/jupyter_jsmol/spkg-configure.m4 new file mode 100644 index 00000000000..202fe5fff31 --- /dev/null +++ b/build/pkgs/jupyter_jsmol/spkg-configure.m4 @@ -0,0 +1,3 @@ +SAGE_SPKG_CONFIGURE([jupyter_jsmol], [ + SAGE_PYTHON_PACKAGE_CHECK([jupyter_jsmol]) +]) diff --git a/build/pkgs/jupyter_packaging/spkg-configure.m4 b/build/pkgs/jupyter_packaging/spkg-configure.m4 new file mode 100644 index 00000000000..2d3ee6280dd --- /dev/null +++ b/build/pkgs/jupyter_packaging/spkg-configure.m4 @@ -0,0 +1,3 @@ +SAGE_SPKG_CONFIGURE([jupyter_packaging], [ + SAGE_PYTHON_PACKAGE_CHECK([jupyter_packaging]) +]) diff --git a/build/pkgs/jupyter_sphinx/spkg-configure.m4 b/build/pkgs/jupyter_sphinx/spkg-configure.m4 new file mode 100644 index 00000000000..e9650c888f8 --- /dev/null +++ b/build/pkgs/jupyter_sphinx/spkg-configure.m4 @@ -0,0 +1,3 @@ +SAGE_SPKG_CONFIGURE([jupyter_sphinx], [ + SAGE_PYTHON_PACKAGE_CHECK([jupyter_sphinx]) +]) diff --git a/build/pkgs/jupyterlab_widgets/spkg-configure.m4 b/build/pkgs/jupyterlab_widgets/spkg-configure.m4 new file mode 100644 index 00000000000..dfea30713eb --- /dev/null +++ b/build/pkgs/jupyterlab_widgets/spkg-configure.m4 @@ -0,0 +1,3 @@ +SAGE_SPKG_CONFIGURE([jupyterlab_widgets], [ + SAGE_PYTHON_PACKAGE_CHECK([jupyterlab_widgets]) +]) diff --git a/build/pkgs/setuptools_scm_git_archive/spkg-configure.m4 b/build/pkgs/setuptools_scm_git_archive/spkg-configure.m4 new file mode 100644 index 00000000000..0da3db40d22 --- /dev/null +++ b/build/pkgs/setuptools_scm_git_archive/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([setuptools_scm_git_archive], [SAGE_PYTHON_PACKAGE_CHECK([setuptools_scm_git_archive])]) diff --git a/build/pkgs/setuptools_wheel/spkg-configure.m4 b/build/pkgs/setuptools_wheel/spkg-configure.m4 new file mode 100644 index 00000000000..db71392a8b0 --- /dev/null +++ b/build/pkgs/setuptools_wheel/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([setuptools_wheel], [SAGE_PYTHON_PACKAGE_CHECK([setuptools_wheel])]) diff --git a/build/pkgs/sphinx/spkg-configure.m4 b/build/pkgs/sphinx/spkg-configure.m4 new file mode 100644 index 00000000000..6376e00a02d --- /dev/null +++ b/build/pkgs/sphinx/spkg-configure.m4 @@ -0,0 +1,3 @@ +SAGE_SPKG_CONFIGURE([sphinx], [ + SAGE_PYTHON_PACKAGE_CHECK([sphinx]) +]) diff --git a/build/pkgs/sphinx_basic_ng/spkg-configure.m4 b/build/pkgs/sphinx_basic_ng/spkg-configure.m4 new file mode 100644 index 00000000000..9400cc485e1 --- /dev/null +++ b/build/pkgs/sphinx_basic_ng/spkg-configure.m4 @@ -0,0 +1,3 @@ +SAGE_SPKG_CONFIGURE([sphinx_basic_ng], [ + SAGE_PYTHON_PACKAGE_CHECK([sphinx_basic_ng]) +]) diff --git a/build/pkgs/sphinx_copybutton/spkg-configure.m4 b/build/pkgs/sphinx_copybutton/spkg-configure.m4 new file mode 100644 index 00000000000..8a0d5c983af --- /dev/null +++ b/build/pkgs/sphinx_copybutton/spkg-configure.m4 @@ -0,0 +1,3 @@ +SAGE_SPKG_CONFIGURE([sphinx_copybutton], [ + SAGE_PYTHON_PACKAGE_CHECK([sphinx_copybutton]) +]) diff --git a/build/pkgs/sphinxcontrib_websupport/spkg-configure.m4 b/build/pkgs/sphinxcontrib_websupport/spkg-configure.m4 new file mode 100644 index 00000000000..2a27c8f5802 --- /dev/null +++ b/build/pkgs/sphinxcontrib_websupport/spkg-configure.m4 @@ -0,0 +1,3 @@ +SAGE_SPKG_CONFIGURE([sphinxcontrib_websupport], [ + SAGE_PYTHON_PACKAGE_CHECK([sphinxcontrib_websupport]) +]) diff --git a/build/pkgs/tinycss2/spkg-configure.m4 b/build/pkgs/tinycss2/spkg-configure.m4 new file mode 100644 index 00000000000..a27e98eaa2a --- /dev/null +++ b/build/pkgs/tinycss2/spkg-configure.m4 @@ -0,0 +1,3 @@ +SAGE_SPKG_CONFIGURE([tinycss2], [ + SAGE_PYTHON_PACKAGE_CHECK([tinycss2]) +]) From fe68ca240c309d33644673b16ece4690fd0b4386 Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Mon, 18 Sep 2023 13:07:01 +0100 Subject: [PATCH 45/93] correct the name of meson_python in m4 macro call --- build/pkgs/meson_python/spkg-configure.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/pkgs/meson_python/spkg-configure.m4 b/build/pkgs/meson_python/spkg-configure.m4 index 267e6ad801c..69a5eb89a85 100644 --- a/build/pkgs/meson_python/spkg-configure.m4 +++ b/build/pkgs/meson_python/spkg-configure.m4 @@ -1,3 +1,3 @@ SAGE_SPKG_CONFIGURE([meson_python], [ - SAGE_PYTHON_PACKAGE_CHECK([meson-python]) + SAGE_PYTHON_PACKAGE_CHECK([meson_python]) ]) From 1a187e08af2ffe8db36f4ef49712519a4a8b9db5 Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Mon, 18 Sep 2023 12:50:19 +0100 Subject: [PATCH 46/93] remove duplicate args in @options() in region_plot This is needed for Sphinx 7.1+ --- src/sage/plot/contour_plot.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/sage/plot/contour_plot.py b/src/sage/plot/contour_plot.py index 7a8be38979b..fee6e36401d 100644 --- a/src/sage/plot/contour_plot.py +++ b/src/sage/plot/contour_plot.py @@ -1391,11 +1391,9 @@ def f(x,y): raise ValueError("fill=%s is not supported" % options['fill']) -@options(plot_points=100, incol='blue', outcol=None, bordercol=None, - borderstyle=None, borderwidth=None, frame=False, axes=True, - legend_label=None, aspect_ratio=1, alpha=1) -def region_plot(f, xrange, yrange, plot_points, incol, outcol, bordercol, - borderstyle, borderwidth, alpha, **options): +@options(frame=False, axes=True, legend_label=None, aspect_ratio=1) +def region_plot(f, xrange, yrange, plot_points=100, incol='blue', outcol=None, bordercol=None, + borderstyle=None, borderwidth=None, alpha=1, **options): r""" ``region_plot`` takes a boolean function of two variables, `f(x, y)` and plots the region where f is True over the specified From 4df7474c004ab84db3158cfdb4d8a7de2797cb13 Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Mon, 18 Sep 2023 15:43:59 +0100 Subject: [PATCH 47/93] added spkg-configure for ipympl --- build/pkgs/ipympl/spkg-configure.m4 | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 build/pkgs/ipympl/spkg-configure.m4 diff --git a/build/pkgs/ipympl/spkg-configure.m4 b/build/pkgs/ipympl/spkg-configure.m4 new file mode 100644 index 00000000000..d6ccf959ec7 --- /dev/null +++ b/build/pkgs/ipympl/spkg-configure.m4 @@ -0,0 +1,3 @@ +SAGE_SPKG_CONFIGURE([ipympl], [ + SAGE_PYTHON_PACKAGE_CHECK([ipympl]) +]) From c7931be2165620bbe7fc45c20141ab0818a65cd8 Mon Sep 17 00:00:00 2001 From: Miguel Marco Date: Mon, 18 Sep 2023 18:35:15 +0200 Subject: [PATCH 48/93] Generic implementation of fitting ideal, and specific _fitting_ideal for MPolynomialRing --- src/sage/matrix/matrix2.pyx | 132 +++++++++++++++++++ src/sage/matrix/matrix_mpolynomial_dense.pyx | 66 +++++++++- 2 files changed, 197 insertions(+), 1 deletion(-) diff --git a/src/sage/matrix/matrix2.pyx b/src/sage/matrix/matrix2.pyx index 32c9b2eea38..5e986ade8fd 100644 --- a/src/sage/matrix/matrix2.pyx +++ b/src/sage/matrix/matrix2.pyx @@ -89,6 +89,7 @@ from sage.structure.element cimport have_same_parent from sage.misc.verbose import verbose from sage.categories.fields import Fields from sage.categories.integral_domains import IntegralDomains +from sage.categories.principal_ideal_domains import PrincipalIdealDomains from sage.rings.ring import is_Ring from sage.rings.number_field.number_field_base import NumberField from sage.rings.integer_ring import ZZ, is_IntegerRing @@ -102,6 +103,8 @@ from . import berlekamp_massey from sage.modules.free_module_element import is_FreeModuleElement from sage.matrix.matrix_misc import permanental_minor_polynomial +from sage.misc.misc_c import prod + # used to deprecate only adjoint method from sage.misc.superseded import deprecated_function_alias @@ -15902,6 +15905,135 @@ cdef class Matrix(Matrix1): else: return dp + def fitting_ideal(self, i): + r""" + Return the `i`-th Fitting ideal of the matrix. This is the ideal generated + by the `n - i` minors, where `n` is the number of columns. + + INPUT: + + ``i`` -- an integer + + OUTPUT: + + An ideal on the base ring. + + EXAMPLES:: + + sage: R. = QQ[] + sage: M = matrix(R, [[2*x-z, 0, y-z^2, 1], [0, z - y, z - x, 0],[z - y, x^2 - y, 0, 0]]) + sage: M + [ 2*x - z 0 -z^2 + y 1] + [ 0 -y + z -x + z 0] + [ -y + z x^2 - y 0 0] + sage: [R.ideal(M.minors(i)) == M.fitting_ideal(4-i) for i in range(5)] + [True, True, True, True, True] + sage: M.fitting_ideal(0) + Ideal (0) of Multivariate Polynomial Ring in x, y, z over Rational Field + sage: M.fitting_ideal(1) + Ideal (2*x^4 - 3*x^3*z + x^2*z^2 + y^2*z^2 - 2*y*z^3 + z^4 - 2*x^2*y - y^3 + 3*x*y*z + 2*y^2*z - 2*y*z^2, -x^3 + x^2*z + x*y - y*z, y^2 - 2*y*z + z^2, x*y - x*z - y*z + z^2) of Multivariate Polynomial Ring in x, y, z over Rational Field + sage: M.fitting_ideal(3) + Ideal (2*x - z, -z^2 + y, 1, -y + z, -x + z, -y + z, x^2 - y) of Multivariate Polynomial Ring in x, y, z over Rational Field + sage: M.fitting_ideal(4) + Ideal (1) of Multivariate Polynomial Ring in x, y, z over Rational Field + + + If the base ring is a field, the Fitting ideals are zero under the corank:: + + sage: M = matrix(QQ, [[2,1,3,5],[4,2,6,6],[0,3,2,0]]) + sage: M + [2 1 3 5] + [4 2 6 6] + [0 3 2 0] + sage: M.fitting_ideal(0) + Principal ideal (0) of Rational Field + sage: M.fitting_ideal(1) + Principal ideal (1) of Rational Field + sage: M.fitting_ideal(2) + Principal ideal (1) of Rational Field + sage: M.fitting_ideal(3) + Principal ideal (1) of Rational Field + sage: M.fitting_ideal(4) + Principal ideal (1) of Rational Field + + + In the case of principal ideal domains, it is given by the elementary + divisors:: + + sage: M = matrix([[2,1,3,5],[4,2,6,6],[0,3,2,0]]) + sage: M + [2 1 3 5] + [4 2 6 6] + [0 3 2 0] + sage: M.fitting_ideal(0) + Principal ideal (0) of Integer Ring + sage: M.fitting_ideal(1) + Principal ideal (4) of Integer Ring + sage: M.fitting_ideal(2) + Principal ideal (1) of Integer Ring + sage: M.fitting_ideal(3) + Principal ideal (1) of Integer Ring + sage: M.fitting_ideal(4) + Principal ideal (1) of Integer Ring + sage: M.elementary_divisors() + [1, 1, 4] + + """ + R = self.base_ring() + if not R.is_exact(): + raise NotImplementedError("Fitting ideals over non-exact rings not implemented at present") + n = self.ncols() + rank = n - i + if rank > self.nrows(): + return R.ideal([R.zero()]) + elif rank <= 0: + return R.ideal([R.one()]) + elif rank == 1: + return R.ideal(self.coefficients()) + if R in _Fields: + if self.rank() >= rank: + return R.ideal([1]) + else: + return R.ideal([0]) + try: + elemdiv = self.elementary_divisors() + if rank > len(elemdiv): + return R.ideal([0]) + return R.ideal(prod(elemdiv[:rank])) + except (TypeError, NotImplementedError, ArithmeticError): + pass + for (nr,r) in enumerate(self.rows()): + nz = [e for e in enumerate(r) if e[1]] + if len(nz) == 0: + N = self.delete_rows([nr]) + return N.fitting_ideal(i) + elif len(nz) == 1: + N = self.delete_rows([nr]) + F1 = N.fitting_ideal(i) + N = N.delete_columns([nz[0][0]]) + F2 = N.fitting_ideal(i) + return F1 + nz[0][1]*F2 + for (nc,c) in enumerate(self.columns()): + nz = [e for e in enumerate(c) if e[1]] + if len(nz) == 0: + N = self.delete_columns([nc]) + return N._fitting_ideal(i - 1) + elif len(nz) == 1: + N = self.delete_columns([nc]) + F1 = N.fitting_ideal(i-1) + N = N.delete_rows([nz[0][0]]) + F2 = N.fitting_ideal(i) + return F1 + nz[0][1]*F2 + if hasattr(self, '_fitting_ideal'): + try: + return self._fitting_ideal(i) + except NotImplementedError: + pass + else: + return R.ideal(self.minors(rank)) + + + def _hermite_form_euclidean(self, transformation=False, normalization=None): """ Transform the matrix in place to hermite normal form and optionally diff --git a/src/sage/matrix/matrix_mpolynomial_dense.pyx b/src/sage/matrix/matrix_mpolynomial_dense.pyx index d8819bdc7cc..e3de9bbdb57 100644 --- a/src/sage/matrix/matrix_mpolynomial_dense.pyx +++ b/src/sage/matrix/matrix_mpolynomial_dense.pyx @@ -23,7 +23,9 @@ from sage.matrix.matrix2 cimport Matrix from sage.rings.polynomial.multi_polynomial_libsingular cimport MPolynomialRing_libsingular from sage.rings.polynomial.polynomial_singular_interface import can_convert_to_singular -from sage.libs.singular.function import singular_function +from sage.libs.singular.function import singular_function, lib + +from cysignals.signals cimport sig_on, sig_off cdef class Matrix_mpolynomial_dense(Matrix_generic_dense): @@ -451,6 +453,68 @@ cdef class Matrix_mpolynomial_dense(Matrix_generic_dense): """ return self.fetch('swapped_columns') + def _fitting_ideal(self, i): + r""" + Return the `i`-th Fitting ideal of the matrix. This is the ideal generated + by the `n - i` minors, where `n` is the number of columns. + + INPUT: + + ``i`` -- an integer + + OUTPUT: + + An ideal on the base ring. + + EXAMPLES:: + + sage: R. = QQ[] + sage: M = matrix(R, [[2*x-z, 0, y-z^2, 0], [0, z - y, z - x, 0],[z - y, x^2 - y, 0, z]]) + sage: M + [ 2*x - z 0 -z^2 + y 0] + [ 0 -y + z -x + z 0] + [ -y + z x^2 - y 0 z] + sage: M.fitting_ideal(0) + Ideal (0) of Multivariate Polynomial Ring in x, y, z over Rational Field + sage: M.fitting_ideal(1) + Ideal (2*x^4 - 3*x^3*z + x^2*z^2 + y^2*z^2 - 2*y*z^3 + z^4 - 2*x^2*y - y^3 + 3*x*y*z + 2*y^2*z - 2*y*z^2, y*z^3 - z^4 - y^2*z + y*z^2, -2*x*y*z + 2*x*z^2 + y*z^2 - z^3, -2*x^2*z + 3*x*z^2 - z^3) of Multivariate Polynomial Ring in x, y, z over Rational Field + sage: M.fitting_ideal(2) + Ideal (-x^3 + x^2*z + x*y - y*z, -y^2 + 2*y*z - z^2, -x^2*z^2 + x^2*y + y*z^2 - y^2, 2*x^3 - x^2*z - 2*x*y + y*z, -x*y + x*z + y*z - z^2, -y*z^2 + z^3 + y^2 - y*z, -2*x*y + 2*x*z + y*z - z^2, y*z^2 - z^3 - y^2 + y*z, 2*x^2 - 3*x*z + z^2, 2*x*z - z^2, -z^3 + y*z, -y*z + z^2, -x*z + z^2) of Multivariate Polynomial Ring in x, y, z over Rational Field + sage: M.fitting_ideal(3) + Ideal (2*x - z, -z^2 + y, -y + z, -x + z, -y + z, x^2 - y, z) of Multivariate Polynomial Ring in x, y, z over Rational Field + sage: M.fitting_ideal(4) + Ideal (1) of Multivariate Polynomial Ring in x, y, z over Rational Field + sage: [R.ideal(M.minors(i)) == M._fitting_ideal(4 - i) for i in range(5)] + [True, True, True, True, True] + + """ + minor = singular_function("minor") + R = self.base_ring() + for (nrow, row) in enumerate(self.rows()): + if not row: + N = self.delete_rows([nrow]) + return N._fitting_ideal(i) + for (ncoef, coef) in enumerate(row): + if all(coef.divides(f) for f in row): + N = self.__copy__() + for j in range(self.ncols()): + if j != ncoef: + N.add_multiple_of_column(j, ncoef, -R(self[nrow,j] / coef)) + return N.fitting_ideal(i) + for (ncolumn, column) in enumerate(self.columns()): + if not column: + N = self.delete_columns([ncolumn]) + return N._fitting_ideal(i-1) + for (ncoef, coef) in enumerate(column): + if all(coef.divides(f) for f in column): + N = self.__copy__() + for j in range(self.nrows()): + if j != ncoef: + N.add_multiple_of_row(j, ncoef, -R(self[j, ncolumn] / coef)) + return N.fitting_ideal(i) + rank = self.ncols() - i + return R.ideal(minor(self, rank)) + def determinant(self, algorithm=None): """ Return the determinant of this matrix From f32bfebdb8325dc456508a21a466aafbf6660399 Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Mon, 18 Sep 2023 22:36:18 +0100 Subject: [PATCH 49/93] distros info --- build/pkgs/beautifulsoup4/distros/alpine.txt | 1 + build/pkgs/beautifulsoup4/distros/arch.txt | 1 + build/pkgs/beautifulsoup4/distros/debian.txt | 1 + build/pkgs/beautifulsoup4/distros/fedora.txt | 1 + build/pkgs/beautifulsoup4/distros/gentoo.txt | 1 + build/pkgs/beautifulsoup4/distros/opensuse.txt | 1 + build/pkgs/ipympl/distros/arch.txt | 1 + build/pkgs/ipympl/distros/freebsd.txt | 1 + build/pkgs/ipympl/distros/macports.txt | 1 + build/pkgs/ipympl/distros/repology.txt | 1 + build/pkgs/jupyter_jsmol/distros/arch.txt | 1 + build/pkgs/jupyter_jsmol/distros/freebsd.txt | 1 + build/pkgs/jupyter_sphinx/distros/arch.txt | 1 + build/pkgs/jupyter_sphinx/distros/fedora.txt | 1 + build/pkgs/jupyter_sphinx/distros/freebsd.txt | 1 + build/pkgs/jupyter_sphinx/distros/macports.txt | 1 + build/pkgs/jupyter_sphinx/distros/opensuse.txt | 1 + build/pkgs/meson_python/distros/alpine.txt | 1 + build/pkgs/meson_python/distros/arch.txt | 1 + build/pkgs/meson_python/distros/debian.txt | 1 + build/pkgs/meson_python/distros/fedora.txt | 1 + build/pkgs/meson_python/distros/freebsd.txt | 1 + build/pkgs/meson_python/distros/opensuse.txt | 1 + build/pkgs/meson_python/distros/void.txt | 1 + build/pkgs/setuptools_scm_git_archive/distros/alpine.txt | 1 + build/pkgs/setuptools_scm_git_archive/distros/arch.txt | 1 + build/pkgs/setuptools_scm_git_archive/distros/debian.txt | 1 + build/pkgs/setuptools_scm_git_archive/distros/fedora.txt | 1 + build/pkgs/setuptools_scm_git_archive/distros/freebsd.txt | 1 + build/pkgs/setuptools_scm_git_archive/distros/gentoo.txt | 1 + build/pkgs/sphinx_basic_ng/distros/arch.txt | 1 + build/pkgs/sphinx_basic_ng/distros/debian.txt | 1 + build/pkgs/sphinx_basic_ng/distros/fedora.txt | 1 + build/pkgs/sphinx_basic_ng/distros/freebsd.txt | 1 + build/pkgs/sphinx_basic_ng/distros/gentoo.txt | 1 + build/pkgs/sphinx_copybutton/distros/alpine.txt | 1 + build/pkgs/sphinx_copybutton/distros/arch.txt | 1 + build/pkgs/sphinx_copybutton/distros/fedora.txt | 1 + build/pkgs/sphinx_copybutton/distros/freebsd.txt | 1 + build/pkgs/sphinx_copybutton/distros/gentoo.txt | 1 + build/pkgs/sphinx_copybutton/distros/void.txt | 1 + build/pkgs/sphinxcontrib_websupport/distros/alpine.txt | 1 + build/pkgs/sphinxcontrib_websupport/distros/debian.txt | 1 + build/pkgs/sphinxcontrib_websupport/distros/gentoo.txt | 1 + build/pkgs/tinycss2/distros/alpine.txt | 1 + build/pkgs/tinycss2/distros/arch.txt | 1 + build/pkgs/tinycss2/distros/debian.txt | 1 + build/pkgs/tinycss2/distros/fedora.txt | 1 + build/pkgs/tinycss2/distros/freebsd.txt | 1 + build/pkgs/tinycss2/distros/gentoo.txt | 1 + build/pkgs/tinycss2/distros/macports.txt | 1 + build/pkgs/tinycss2/distros/opensuse.txt | 1 + build/pkgs/tinycss2/distros/void.txt | 1 + 53 files changed, 53 insertions(+) create mode 100644 build/pkgs/beautifulsoup4/distros/alpine.txt create mode 100644 build/pkgs/beautifulsoup4/distros/arch.txt create mode 100644 build/pkgs/beautifulsoup4/distros/debian.txt create mode 100644 build/pkgs/beautifulsoup4/distros/fedora.txt create mode 100644 build/pkgs/beautifulsoup4/distros/gentoo.txt create mode 100644 build/pkgs/beautifulsoup4/distros/opensuse.txt create mode 100644 build/pkgs/ipympl/distros/arch.txt create mode 100644 build/pkgs/ipympl/distros/freebsd.txt create mode 100644 build/pkgs/ipympl/distros/macports.txt create mode 100644 build/pkgs/ipympl/distros/repology.txt create mode 100644 build/pkgs/jupyter_jsmol/distros/arch.txt create mode 100644 build/pkgs/jupyter_jsmol/distros/freebsd.txt create mode 100644 build/pkgs/jupyter_sphinx/distros/arch.txt create mode 100644 build/pkgs/jupyter_sphinx/distros/fedora.txt create mode 100644 build/pkgs/jupyter_sphinx/distros/freebsd.txt create mode 100644 build/pkgs/jupyter_sphinx/distros/macports.txt create mode 100644 build/pkgs/jupyter_sphinx/distros/opensuse.txt create mode 100644 build/pkgs/meson_python/distros/alpine.txt create mode 100644 build/pkgs/meson_python/distros/arch.txt create mode 100644 build/pkgs/meson_python/distros/debian.txt create mode 100644 build/pkgs/meson_python/distros/fedora.txt create mode 100644 build/pkgs/meson_python/distros/freebsd.txt create mode 100644 build/pkgs/meson_python/distros/opensuse.txt create mode 100644 build/pkgs/meson_python/distros/void.txt create mode 100644 build/pkgs/setuptools_scm_git_archive/distros/alpine.txt create mode 100644 build/pkgs/setuptools_scm_git_archive/distros/arch.txt create mode 100644 build/pkgs/setuptools_scm_git_archive/distros/debian.txt create mode 100644 build/pkgs/setuptools_scm_git_archive/distros/fedora.txt create mode 100644 build/pkgs/setuptools_scm_git_archive/distros/freebsd.txt create mode 100644 build/pkgs/setuptools_scm_git_archive/distros/gentoo.txt create mode 100644 build/pkgs/sphinx_basic_ng/distros/arch.txt create mode 100644 build/pkgs/sphinx_basic_ng/distros/debian.txt create mode 100644 build/pkgs/sphinx_basic_ng/distros/fedora.txt create mode 100644 build/pkgs/sphinx_basic_ng/distros/freebsd.txt create mode 100644 build/pkgs/sphinx_basic_ng/distros/gentoo.txt create mode 100644 build/pkgs/sphinx_copybutton/distros/alpine.txt create mode 100644 build/pkgs/sphinx_copybutton/distros/arch.txt create mode 100644 build/pkgs/sphinx_copybutton/distros/fedora.txt create mode 100644 build/pkgs/sphinx_copybutton/distros/freebsd.txt create mode 100644 build/pkgs/sphinx_copybutton/distros/gentoo.txt create mode 100644 build/pkgs/sphinx_copybutton/distros/void.txt create mode 100644 build/pkgs/sphinxcontrib_websupport/distros/alpine.txt create mode 100644 build/pkgs/sphinxcontrib_websupport/distros/debian.txt create mode 100644 build/pkgs/sphinxcontrib_websupport/distros/gentoo.txt create mode 100644 build/pkgs/tinycss2/distros/alpine.txt create mode 100644 build/pkgs/tinycss2/distros/arch.txt create mode 100644 build/pkgs/tinycss2/distros/debian.txt create mode 100644 build/pkgs/tinycss2/distros/fedora.txt create mode 100644 build/pkgs/tinycss2/distros/freebsd.txt create mode 100644 build/pkgs/tinycss2/distros/gentoo.txt create mode 100644 build/pkgs/tinycss2/distros/macports.txt create mode 100644 build/pkgs/tinycss2/distros/opensuse.txt create mode 100644 build/pkgs/tinycss2/distros/void.txt diff --git a/build/pkgs/beautifulsoup4/distros/alpine.txt b/build/pkgs/beautifulsoup4/distros/alpine.txt new file mode 100644 index 00000000000..63787cb8abf --- /dev/null +++ b/build/pkgs/beautifulsoup4/distros/alpine.txt @@ -0,0 +1 @@ +py3-beautifulsoup4 diff --git a/build/pkgs/beautifulsoup4/distros/arch.txt b/build/pkgs/beautifulsoup4/distros/arch.txt new file mode 100644 index 00000000000..2e8f9a66b24 --- /dev/null +++ b/build/pkgs/beautifulsoup4/distros/arch.txt @@ -0,0 +1 @@ +python-beautifulsoup4 diff --git a/build/pkgs/beautifulsoup4/distros/debian.txt b/build/pkgs/beautifulsoup4/distros/debian.txt new file mode 100644 index 00000000000..c1f5f713cda --- /dev/null +++ b/build/pkgs/beautifulsoup4/distros/debian.txt @@ -0,0 +1 @@ +beautifulsoup4 diff --git a/build/pkgs/beautifulsoup4/distros/fedora.txt b/build/pkgs/beautifulsoup4/distros/fedora.txt new file mode 100644 index 00000000000..2e8f9a66b24 --- /dev/null +++ b/build/pkgs/beautifulsoup4/distros/fedora.txt @@ -0,0 +1 @@ +python-beautifulsoup4 diff --git a/build/pkgs/beautifulsoup4/distros/gentoo.txt b/build/pkgs/beautifulsoup4/distros/gentoo.txt new file mode 100644 index 00000000000..5bdeb6522ec --- /dev/null +++ b/build/pkgs/beautifulsoup4/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/beautifulsoup4 diff --git a/build/pkgs/beautifulsoup4/distros/opensuse.txt b/build/pkgs/beautifulsoup4/distros/opensuse.txt new file mode 100644 index 00000000000..2e8f9a66b24 --- /dev/null +++ b/build/pkgs/beautifulsoup4/distros/opensuse.txt @@ -0,0 +1 @@ +python-beautifulsoup4 diff --git a/build/pkgs/ipympl/distros/arch.txt b/build/pkgs/ipympl/distros/arch.txt new file mode 100644 index 00000000000..85cef6a0662 --- /dev/null +++ b/build/pkgs/ipympl/distros/arch.txt @@ -0,0 +1 @@ +python-ipympl diff --git a/build/pkgs/ipympl/distros/freebsd.txt b/build/pkgs/ipympl/distros/freebsd.txt new file mode 100644 index 00000000000..12b982ba727 --- /dev/null +++ b/build/pkgs/ipympl/distros/freebsd.txt @@ -0,0 +1 @@ +devel/py-ipympl diff --git a/build/pkgs/ipympl/distros/macports.txt b/build/pkgs/ipympl/distros/macports.txt new file mode 100644 index 00000000000..3102367bb00 --- /dev/null +++ b/build/pkgs/ipympl/distros/macports.txt @@ -0,0 +1 @@ +py-ipympl diff --git a/build/pkgs/ipympl/distros/repology.txt b/build/pkgs/ipympl/distros/repology.txt new file mode 100644 index 00000000000..68e8e609e7f --- /dev/null +++ b/build/pkgs/ipympl/distros/repology.txt @@ -0,0 +1 @@ +python:ipympl diff --git a/build/pkgs/jupyter_jsmol/distros/arch.txt b/build/pkgs/jupyter_jsmol/distros/arch.txt new file mode 100644 index 00000000000..9465bfb8e0c --- /dev/null +++ b/build/pkgs/jupyter_jsmol/distros/arch.txt @@ -0,0 +1 @@ +jupyter-jsmol diff --git a/build/pkgs/jupyter_jsmol/distros/freebsd.txt b/build/pkgs/jupyter_jsmol/distros/freebsd.txt new file mode 100644 index 00000000000..5954a774e80 --- /dev/null +++ b/build/pkgs/jupyter_jsmol/distros/freebsd.txt @@ -0,0 +1 @@ +science/py-jupyter_jsmol diff --git a/build/pkgs/jupyter_sphinx/distros/arch.txt b/build/pkgs/jupyter_sphinx/distros/arch.txt new file mode 100644 index 00000000000..95d44e5858f --- /dev/null +++ b/build/pkgs/jupyter_sphinx/distros/arch.txt @@ -0,0 +1 @@ +python-jupyter-sphinx diff --git a/build/pkgs/jupyter_sphinx/distros/fedora.txt b/build/pkgs/jupyter_sphinx/distros/fedora.txt new file mode 100644 index 00000000000..95d44e5858f --- /dev/null +++ b/build/pkgs/jupyter_sphinx/distros/fedora.txt @@ -0,0 +1 @@ +python-jupyter-sphinx diff --git a/build/pkgs/jupyter_sphinx/distros/freebsd.txt b/build/pkgs/jupyter_sphinx/distros/freebsd.txt new file mode 100644 index 00000000000..7e84cc729e6 --- /dev/null +++ b/build/pkgs/jupyter_sphinx/distros/freebsd.txt @@ -0,0 +1 @@ +textproc/py-jupyter_sphinx diff --git a/build/pkgs/jupyter_sphinx/distros/macports.txt b/build/pkgs/jupyter_sphinx/distros/macports.txt new file mode 100644 index 00000000000..9ad2b36d1ba --- /dev/null +++ b/build/pkgs/jupyter_sphinx/distros/macports.txt @@ -0,0 +1 @@ +py-jupyter_sphinx diff --git a/build/pkgs/jupyter_sphinx/distros/opensuse.txt b/build/pkgs/jupyter_sphinx/distros/opensuse.txt new file mode 100644 index 00000000000..95d44e5858f --- /dev/null +++ b/build/pkgs/jupyter_sphinx/distros/opensuse.txt @@ -0,0 +1 @@ +python-jupyter-sphinx diff --git a/build/pkgs/meson_python/distros/alpine.txt b/build/pkgs/meson_python/distros/alpine.txt new file mode 100644 index 00000000000..248216b1fdc --- /dev/null +++ b/build/pkgs/meson_python/distros/alpine.txt @@ -0,0 +1 @@ +py3-meson-python diff --git a/build/pkgs/meson_python/distros/arch.txt b/build/pkgs/meson_python/distros/arch.txt new file mode 100644 index 00000000000..9705cab644e --- /dev/null +++ b/build/pkgs/meson_python/distros/arch.txt @@ -0,0 +1 @@ +meson-python diff --git a/build/pkgs/meson_python/distros/debian.txt b/build/pkgs/meson_python/distros/debian.txt new file mode 100644 index 00000000000..9705cab644e --- /dev/null +++ b/build/pkgs/meson_python/distros/debian.txt @@ -0,0 +1 @@ +meson-python diff --git a/build/pkgs/meson_python/distros/fedora.txt b/build/pkgs/meson_python/distros/fedora.txt new file mode 100644 index 00000000000..17b4e0c04c5 --- /dev/null +++ b/build/pkgs/meson_python/distros/fedora.txt @@ -0,0 +1 @@ +python-meson-python diff --git a/build/pkgs/meson_python/distros/freebsd.txt b/build/pkgs/meson_python/distros/freebsd.txt new file mode 100644 index 00000000000..5609e7545cf --- /dev/null +++ b/build/pkgs/meson_python/distros/freebsd.txt @@ -0,0 +1 @@ +devel/meson-python diff --git a/build/pkgs/meson_python/distros/opensuse.txt b/build/pkgs/meson_python/distros/opensuse.txt new file mode 100644 index 00000000000..17b4e0c04c5 --- /dev/null +++ b/build/pkgs/meson_python/distros/opensuse.txt @@ -0,0 +1 @@ +python-meson-python diff --git a/build/pkgs/meson_python/distros/void.txt b/build/pkgs/meson_python/distros/void.txt new file mode 100644 index 00000000000..93dae9570a4 --- /dev/null +++ b/build/pkgs/meson_python/distros/void.txt @@ -0,0 +1 @@ +python3-meson-python diff --git a/build/pkgs/setuptools_scm_git_archive/distros/alpine.txt b/build/pkgs/setuptools_scm_git_archive/distros/alpine.txt new file mode 100644 index 00000000000..c08bc88e16c --- /dev/null +++ b/build/pkgs/setuptools_scm_git_archive/distros/alpine.txt @@ -0,0 +1 @@ +py3-setuptools-scm-git-archive diff --git a/build/pkgs/setuptools_scm_git_archive/distros/arch.txt b/build/pkgs/setuptools_scm_git_archive/distros/arch.txt new file mode 100644 index 00000000000..bc2a39f97a3 --- /dev/null +++ b/build/pkgs/setuptools_scm_git_archive/distros/arch.txt @@ -0,0 +1 @@ +python-setuptools-scm-git-archive diff --git a/build/pkgs/setuptools_scm_git_archive/distros/debian.txt b/build/pkgs/setuptools_scm_git_archive/distros/debian.txt new file mode 100644 index 00000000000..538474ff946 --- /dev/null +++ b/build/pkgs/setuptools_scm_git_archive/distros/debian.txt @@ -0,0 +1 @@ +setuptools-scm-git-archive diff --git a/build/pkgs/setuptools_scm_git_archive/distros/fedora.txt b/build/pkgs/setuptools_scm_git_archive/distros/fedora.txt new file mode 100644 index 00000000000..ada37357769 --- /dev/null +++ b/build/pkgs/setuptools_scm_git_archive/distros/fedora.txt @@ -0,0 +1 @@ +python-setuptools_scm_git_archive diff --git a/build/pkgs/setuptools_scm_git_archive/distros/freebsd.txt b/build/pkgs/setuptools_scm_git_archive/distros/freebsd.txt new file mode 100644 index 00000000000..2ace76a2af0 --- /dev/null +++ b/build/pkgs/setuptools_scm_git_archive/distros/freebsd.txt @@ -0,0 +1 @@ +devel/py-setuptools_scm_git_archive diff --git a/build/pkgs/setuptools_scm_git_archive/distros/gentoo.txt b/build/pkgs/setuptools_scm_git_archive/distros/gentoo.txt new file mode 100644 index 00000000000..fb7388e3dd7 --- /dev/null +++ b/build/pkgs/setuptools_scm_git_archive/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/setuptools_scm_git_archive diff --git a/build/pkgs/sphinx_basic_ng/distros/arch.txt b/build/pkgs/sphinx_basic_ng/distros/arch.txt new file mode 100644 index 00000000000..de43e3bfd58 --- /dev/null +++ b/build/pkgs/sphinx_basic_ng/distros/arch.txt @@ -0,0 +1 @@ +python-sphinx-basic-ng diff --git a/build/pkgs/sphinx_basic_ng/distros/debian.txt b/build/pkgs/sphinx_basic_ng/distros/debian.txt new file mode 100644 index 00000000000..c11d80ea377 --- /dev/null +++ b/build/pkgs/sphinx_basic_ng/distros/debian.txt @@ -0,0 +1 @@ +sphinx-basic-ng diff --git a/build/pkgs/sphinx_basic_ng/distros/fedora.txt b/build/pkgs/sphinx_basic_ng/distros/fedora.txt new file mode 100644 index 00000000000..de43e3bfd58 --- /dev/null +++ b/build/pkgs/sphinx_basic_ng/distros/fedora.txt @@ -0,0 +1 @@ +python-sphinx-basic-ng diff --git a/build/pkgs/sphinx_basic_ng/distros/freebsd.txt b/build/pkgs/sphinx_basic_ng/distros/freebsd.txt new file mode 100644 index 00000000000..1d0b5ec22b4 --- /dev/null +++ b/build/pkgs/sphinx_basic_ng/distros/freebsd.txt @@ -0,0 +1 @@ +textproc/py-sphinx-basic-ng diff --git a/build/pkgs/sphinx_basic_ng/distros/gentoo.txt b/build/pkgs/sphinx_basic_ng/distros/gentoo.txt new file mode 100644 index 00000000000..8b7a20a21ea --- /dev/null +++ b/build/pkgs/sphinx_basic_ng/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/sphinx-basic-ng diff --git a/build/pkgs/sphinx_copybutton/distros/alpine.txt b/build/pkgs/sphinx_copybutton/distros/alpine.txt new file mode 100644 index 00000000000..85cc9c14557 --- /dev/null +++ b/build/pkgs/sphinx_copybutton/distros/alpine.txt @@ -0,0 +1 @@ +py3-sphinx-copybutton diff --git a/build/pkgs/sphinx_copybutton/distros/arch.txt b/build/pkgs/sphinx_copybutton/distros/arch.txt new file mode 100644 index 00000000000..2a99b129e49 --- /dev/null +++ b/build/pkgs/sphinx_copybutton/distros/arch.txt @@ -0,0 +1 @@ +python-sphinx-copybutton diff --git a/build/pkgs/sphinx_copybutton/distros/fedora.txt b/build/pkgs/sphinx_copybutton/distros/fedora.txt new file mode 100644 index 00000000000..2a99b129e49 --- /dev/null +++ b/build/pkgs/sphinx_copybutton/distros/fedora.txt @@ -0,0 +1 @@ +python-sphinx-copybutton diff --git a/build/pkgs/sphinx_copybutton/distros/freebsd.txt b/build/pkgs/sphinx_copybutton/distros/freebsd.txt new file mode 100644 index 00000000000..96e72696cff --- /dev/null +++ b/build/pkgs/sphinx_copybutton/distros/freebsd.txt @@ -0,0 +1 @@ +textproc/py-sphinx-copybutton diff --git a/build/pkgs/sphinx_copybutton/distros/gentoo.txt b/build/pkgs/sphinx_copybutton/distros/gentoo.txt new file mode 100644 index 00000000000..e9d93b941e9 --- /dev/null +++ b/build/pkgs/sphinx_copybutton/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/sphinx-copybutton diff --git a/build/pkgs/sphinx_copybutton/distros/void.txt b/build/pkgs/sphinx_copybutton/distros/void.txt new file mode 100644 index 00000000000..576663b4a9d --- /dev/null +++ b/build/pkgs/sphinx_copybutton/distros/void.txt @@ -0,0 +1 @@ +python3-sphinx-copybutton diff --git a/build/pkgs/sphinxcontrib_websupport/distros/alpine.txt b/build/pkgs/sphinxcontrib_websupport/distros/alpine.txt new file mode 100644 index 00000000000..521405d79ba --- /dev/null +++ b/build/pkgs/sphinxcontrib_websupport/distros/alpine.txt @@ -0,0 +1 @@ +py3-sphinxcontrib-websupport diff --git a/build/pkgs/sphinxcontrib_websupport/distros/debian.txt b/build/pkgs/sphinxcontrib_websupport/distros/debian.txt new file mode 100644 index 00000000000..141994ece36 --- /dev/null +++ b/build/pkgs/sphinxcontrib_websupport/distros/debian.txt @@ -0,0 +1 @@ +sphinxcontrib-websupport diff --git a/build/pkgs/sphinxcontrib_websupport/distros/gentoo.txt b/build/pkgs/sphinxcontrib_websupport/distros/gentoo.txt new file mode 100644 index 00000000000..8f21bafa771 --- /dev/null +++ b/build/pkgs/sphinxcontrib_websupport/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/sphinxcontrib-websupport diff --git a/build/pkgs/tinycss2/distros/alpine.txt b/build/pkgs/tinycss2/distros/alpine.txt new file mode 100644 index 00000000000..5e465b22439 --- /dev/null +++ b/build/pkgs/tinycss2/distros/alpine.txt @@ -0,0 +1 @@ +py3-tinycss2 diff --git a/build/pkgs/tinycss2/distros/arch.txt b/build/pkgs/tinycss2/distros/arch.txt new file mode 100644 index 00000000000..cb5becfe9eb --- /dev/null +++ b/build/pkgs/tinycss2/distros/arch.txt @@ -0,0 +1 @@ +python-tinycss2 diff --git a/build/pkgs/tinycss2/distros/debian.txt b/build/pkgs/tinycss2/distros/debian.txt new file mode 100644 index 00000000000..cb5becfe9eb --- /dev/null +++ b/build/pkgs/tinycss2/distros/debian.txt @@ -0,0 +1 @@ +python-tinycss2 diff --git a/build/pkgs/tinycss2/distros/fedora.txt b/build/pkgs/tinycss2/distros/fedora.txt new file mode 100644 index 00000000000..cb5becfe9eb --- /dev/null +++ b/build/pkgs/tinycss2/distros/fedora.txt @@ -0,0 +1 @@ +python-tinycss2 diff --git a/build/pkgs/tinycss2/distros/freebsd.txt b/build/pkgs/tinycss2/distros/freebsd.txt new file mode 100644 index 00000000000..048731bb153 --- /dev/null +++ b/build/pkgs/tinycss2/distros/freebsd.txt @@ -0,0 +1 @@ +textproc/py-tinycss2 diff --git a/build/pkgs/tinycss2/distros/gentoo.txt b/build/pkgs/tinycss2/distros/gentoo.txt new file mode 100644 index 00000000000..dcfa0d16aed --- /dev/null +++ b/build/pkgs/tinycss2/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/tinycss2 diff --git a/build/pkgs/tinycss2/distros/macports.txt b/build/pkgs/tinycss2/distros/macports.txt new file mode 100644 index 00000000000..2d8350494f2 --- /dev/null +++ b/build/pkgs/tinycss2/distros/macports.txt @@ -0,0 +1 @@ +py-tinycss2 diff --git a/build/pkgs/tinycss2/distros/opensuse.txt b/build/pkgs/tinycss2/distros/opensuse.txt new file mode 100644 index 00000000000..cb5becfe9eb --- /dev/null +++ b/build/pkgs/tinycss2/distros/opensuse.txt @@ -0,0 +1 @@ +python-tinycss2 diff --git a/build/pkgs/tinycss2/distros/void.txt b/build/pkgs/tinycss2/distros/void.txt new file mode 100644 index 00000000000..a2c2cb2f4ab --- /dev/null +++ b/build/pkgs/tinycss2/distros/void.txt @@ -0,0 +1 @@ +python3-tinycss2 From 64a4510546e8d19157122b22a780763691b49381 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 18 Sep 2023 14:35:59 -0700 Subject: [PATCH 50/93] src/sage/misc/cython.py: Hide Cython 3 warning with unpatched cysignals --- src/sage/misc/cython.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/sage/misc/cython.py b/src/sage/misc/cython.py index 5f83f585c3a..347b2e896d8 100644 --- a/src/sage/misc/cython.py +++ b/src/sage/misc/cython.py @@ -21,6 +21,7 @@ import builtins import os +import re import sys import shutil @@ -396,6 +397,12 @@ def cython(filename, verbose=0, compile_message=False, raise RuntimeError(cython_messages.strip()) if verbose >= 0: + # triggered by Cython 3 with unpatched cysignals 1.11.2 + cython_messages = re.sub( + "^.*The keyword 'nogil' should appear at the end of the function signature line. " + "Placing it before 'except' or 'noexcept' will be disallowed in a future version of Cython.\n", + "", cython_messages, 0, re.MULTILINE) + sys.stderr.write(cython_messages) sys.stderr.flush() From c5747b9c4f333695b62f9da6a091ceb022ac034f Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 18 Sep 2023 15:21:02 -0700 Subject: [PATCH 51/93] .github/workflows/ci-linux-incremental.yml: Test standard-sitepackages --- .github/workflows/ci-linux-incremental.yml | 38 +++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci-linux-incremental.yml b/.github/workflows/ci-linux-incremental.yml index c3de6545efb..a4aa9ae99c7 100644 --- a/.github/workflows/ci-linux-incremental.yml +++ b/.github/workflows/ci-linux-incremental.yml @@ -60,7 +60,8 @@ jobs: echo "uninstall_targets=$(echo $(for a in '' ${{ steps.changed-packages.outputs.configures_all_changed_files }}; do echo $a | sed -E 's,build/pkgs/([_.a-z0-9]*)/spkg-configure[.]m4 *,\1-uninstall,'; done | sort -u))" >> $GITHUB_OUTPUT echo "build_targets=$(echo $(for a in '' ${{ steps.changed-packages.outputs.pkgs_all_changed_files }}; do echo $a | sed -E 's,-,_,g;s,(build/)?pkgs/([-_.a-z0-9]*)/[^ ]* *,\2-ensure,;'; done | sort -u))" >> $GITHUB_OUTPUT cat $GITHUB_OUTPUT - minimal: + + test: needs: [changed_files] if: | github.event_name != 'pull_request' || @@ -94,3 +95,38 @@ jobs: ["standard", "minimal"] docker_push_repository: ghcr.io/${{ github.repository }}/ + + site: + needs: [changed_files] + if: | + github.event_name != 'pull_request' || + ((github.event.action != 'labeled' && + (contains(github.event.pull_request.labels.*.name, 'c: packages: standard') || + contains(github.event.pull_request.labels.*.name, 'c: packages: optional'))) || + (github.event.action == 'labeled' && + (github.event.label.name == 'c: packages: optional' || + github.event.label.name == 'c: packages: standard'))) + uses: ./.github/workflows/docker.yml + with: + # Build incrementally from published Docker image + incremental: true + free_disk_space: true + from_docker_repository: ghcr.io/sagemath/sage/ + from_docker_target: "with-targets" + from_docker_tag: "dev" + docker_targets: "with-targets" + targets: "${{needs.changed_files.outputs.uninstall_targets}} ${{needs.changed_files.outputs.build_targets}} build doc-html ptest" + # Only test systems with a usable system python (>= 3.9) + tox_system_factors: >- + ["ubuntu-jammy", + "ubuntu-mantic", + "debian-bullseye", + "debian-bookworm", + "fedora-33", + "fedora-38", + "gentoo-python3.11", + "archlinux", + "debian-bullseye-i386"] + tox_packages_factors: >- + ["standard-sitepackages"] + docker_push_repository: ghcr.io/${{ github.repository }}/ From 0df84e10656d3a57375127b5e7a89ee7c5ea1fc7 Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Tue, 19 Sep 2023 11:02:33 +0100 Subject: [PATCH 52/93] gentoo has py, too --- build/pkgs/py/distros/gentoo.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 build/pkgs/py/distros/gentoo.txt diff --git a/build/pkgs/py/distros/gentoo.txt b/build/pkgs/py/distros/gentoo.txt new file mode 100644 index 00000000000..d4894e50cf7 --- /dev/null +++ b/build/pkgs/py/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/py From f0e6420f8e0a45784df1aec9e4a7155d74fcb5a0 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 19 Sep 2023 09:26:22 -0700 Subject: [PATCH 53/93] build/pkgs/toml: Remove --- build/pkgs/toml/distros/arch.txt | 1 - build/pkgs/toml/distros/debian.txt | 1 - build/pkgs/toml/distros/fedora.txt | 1 - build/pkgs/toml/distros/gentoo.txt | 1 - build/pkgs/toml/distros/opensuse.txt | 1 - 5 files changed, 5 deletions(-) delete mode 100644 build/pkgs/toml/distros/arch.txt delete mode 100644 build/pkgs/toml/distros/debian.txt delete mode 100644 build/pkgs/toml/distros/fedora.txt delete mode 100644 build/pkgs/toml/distros/gentoo.txt delete mode 100644 build/pkgs/toml/distros/opensuse.txt diff --git a/build/pkgs/toml/distros/arch.txt b/build/pkgs/toml/distros/arch.txt deleted file mode 100644 index 821ee775ac7..00000000000 --- a/build/pkgs/toml/distros/arch.txt +++ /dev/null @@ -1 +0,0 @@ -python-toml diff --git a/build/pkgs/toml/distros/debian.txt b/build/pkgs/toml/distros/debian.txt deleted file mode 100644 index 543e89d2a6f..00000000000 --- a/build/pkgs/toml/distros/debian.txt +++ /dev/null @@ -1 +0,0 @@ -python3-toml diff --git a/build/pkgs/toml/distros/fedora.txt b/build/pkgs/toml/distros/fedora.txt deleted file mode 100644 index 821ee775ac7..00000000000 --- a/build/pkgs/toml/distros/fedora.txt +++ /dev/null @@ -1 +0,0 @@ -python-toml diff --git a/build/pkgs/toml/distros/gentoo.txt b/build/pkgs/toml/distros/gentoo.txt deleted file mode 100644 index 64fcea3559f..00000000000 --- a/build/pkgs/toml/distros/gentoo.txt +++ /dev/null @@ -1 +0,0 @@ -dev-python/toml diff --git a/build/pkgs/toml/distros/opensuse.txt b/build/pkgs/toml/distros/opensuse.txt deleted file mode 100644 index fbc340aee15..00000000000 --- a/build/pkgs/toml/distros/opensuse.txt +++ /dev/null @@ -1 +0,0 @@ -python3${PYTHON_MINOR}-toml From d002b3fa88f0684ef7e725174589bb475821254f Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 19 Sep 2023 10:17:53 -0700 Subject: [PATCH 54/93] build/pkgs/poetry_core: Remove (again) --- build/pkgs/poetry_core/distros/gentoo.txt | 1 - build/pkgs/poetry_core/spkg-configure.m4 | 1 - 2 files changed, 2 deletions(-) delete mode 100644 build/pkgs/poetry_core/distros/gentoo.txt delete mode 100644 build/pkgs/poetry_core/spkg-configure.m4 diff --git a/build/pkgs/poetry_core/distros/gentoo.txt b/build/pkgs/poetry_core/distros/gentoo.txt deleted file mode 100644 index 758fd6e9e01..00000000000 --- a/build/pkgs/poetry_core/distros/gentoo.txt +++ /dev/null @@ -1 +0,0 @@ -dev-python/poetry-core diff --git a/build/pkgs/poetry_core/spkg-configure.m4 b/build/pkgs/poetry_core/spkg-configure.m4 deleted file mode 100644 index ae5337520e7..00000000000 --- a/build/pkgs/poetry_core/spkg-configure.m4 +++ /dev/null @@ -1 +0,0 @@ -SAGE_SPKG_CONFIGURE([poetry_core], [SAGE_PYTHON_PACKAGE_CHECK([poetry-core])]) From fb2752aefb5db809e18529cd0a00abac12ad4701 Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Wed, 20 Sep 2023 12:57:11 +0100 Subject: [PATCH 55/93] add systems info for furo --- build/pkgs/furo/distros/arch.txt | 1 + build/pkgs/furo/distros/debian.txt | 1 + build/pkgs/furo/distros/fedora.txt | 1 + build/pkgs/furo/distros/freebsd.txt | 1 + build/pkgs/furo/distros/gentoo.txt | 1 + build/pkgs/furo/spkg-configure.m4 | 3 +++ 6 files changed, 8 insertions(+) create mode 100644 build/pkgs/furo/distros/arch.txt create mode 100644 build/pkgs/furo/distros/debian.txt create mode 100644 build/pkgs/furo/distros/fedora.txt create mode 100644 build/pkgs/furo/distros/freebsd.txt create mode 100644 build/pkgs/furo/distros/gentoo.txt create mode 100644 build/pkgs/furo/spkg-configure.m4 diff --git a/build/pkgs/furo/distros/arch.txt b/build/pkgs/furo/distros/arch.txt new file mode 100644 index 00000000000..8cd8d580864 --- /dev/null +++ b/build/pkgs/furo/distros/arch.txt @@ -0,0 +1 @@ +python-sphinx-furo diff --git a/build/pkgs/furo/distros/debian.txt b/build/pkgs/furo/distros/debian.txt new file mode 100644 index 00000000000..a95ae18b4f9 --- /dev/null +++ b/build/pkgs/furo/distros/debian.txt @@ -0,0 +1 @@ +furo diff --git a/build/pkgs/furo/distros/fedora.txt b/build/pkgs/furo/distros/fedora.txt new file mode 100644 index 00000000000..d274c983622 --- /dev/null +++ b/build/pkgs/furo/distros/fedora.txt @@ -0,0 +1 @@ +python-furo diff --git a/build/pkgs/furo/distros/freebsd.txt b/build/pkgs/furo/distros/freebsd.txt new file mode 100644 index 00000000000..389d717bad0 --- /dev/null +++ b/build/pkgs/furo/distros/freebsd.txt @@ -0,0 +1 @@ +textproc/py-furo diff --git a/build/pkgs/furo/distros/gentoo.txt b/build/pkgs/furo/distros/gentoo.txt new file mode 100644 index 00000000000..e823e710d71 --- /dev/null +++ b/build/pkgs/furo/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/furo diff --git a/build/pkgs/furo/spkg-configure.m4 b/build/pkgs/furo/spkg-configure.m4 new file mode 100644 index 00000000000..b1a92a7a70e --- /dev/null +++ b/build/pkgs/furo/spkg-configure.m4 @@ -0,0 +1,3 @@ +SAGE_SPKG_CONFIGURE([furo], [ + SAGE_PYTHON_PACKAGE_CHECK([furo]) +]) From cb78fd95b03678f821bc575c683feb74f860105c Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 20 Sep 2023 19:46:44 -0700 Subject: [PATCH 56/93] src/sage/matrix/matrix_gfpn_dense.pyx: Replace relative cimport --- src/sage/matrix/matrix_gfpn_dense.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/matrix/matrix_gfpn_dense.pyx b/src/sage/matrix/matrix_gfpn_dense.pyx index 49a556ba7d4..4cccf473de1 100644 --- a/src/sage/matrix/matrix_gfpn_dense.pyx +++ b/src/sage/matrix/matrix_gfpn_dense.pyx @@ -55,7 +55,7 @@ from sage.misc.randstate import current_randstate from sage.misc.randstate cimport randstate from sage.structure.element cimport Element, Matrix from sage.structure.richcmp import rich_to_bool -from .args cimport MatrixArgs_init +from sage.matrix.args cimport MatrixArgs_init from libc.string cimport memset, memcpy From 7d4345bad41642dce0642b3178298fb6c85499e0 Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Thu, 21 Sep 2023 18:06:30 +0100 Subject: [PATCH 57/93] sphinx 7.x is OK --- build/pkgs/sphinx/install-requires.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/pkgs/sphinx/install-requires.txt b/build/pkgs/sphinx/install-requires.txt index 1ad0ea81a41..9003fdec2f8 100644 --- a/build/pkgs/sphinx/install-requires.txt +++ b/build/pkgs/sphinx/install-requires.txt @@ -1 +1 @@ -sphinx >=5.2, <7.1 +sphinx >=5.2, <8 From 180e8147aee0ff0af46f2d383f9d6920216875aa Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 21 Sep 2023 12:31:34 -0700 Subject: [PATCH 58/93] build/pkgs/jupyter_packaging: Remove (again) --- build/pkgs/jupyter_packaging/spkg-configure.m4 | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 build/pkgs/jupyter_packaging/spkg-configure.m4 diff --git a/build/pkgs/jupyter_packaging/spkg-configure.m4 b/build/pkgs/jupyter_packaging/spkg-configure.m4 deleted file mode 100644 index 2d3ee6280dd..00000000000 --- a/build/pkgs/jupyter_packaging/spkg-configure.m4 +++ /dev/null @@ -1,3 +0,0 @@ -SAGE_SPKG_CONFIGURE([jupyter_packaging], [ - SAGE_PYTHON_PACKAGE_CHECK([jupyter_packaging]) -]) From db87da77f8c17a79908e1ac83ad30433b8b60b54 Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Fri, 22 Sep 2023 23:16:24 -0400 Subject: [PATCH 59/93] build/pkgs/lrcalc_python: add standard python spkg-configure.m4 --- build/pkgs/lrcalc_python/spkg-configure.m4 | 1 + 1 file changed, 1 insertion(+) create mode 100644 build/pkgs/lrcalc_python/spkg-configure.m4 diff --git a/build/pkgs/lrcalc_python/spkg-configure.m4 b/build/pkgs/lrcalc_python/spkg-configure.m4 new file mode 100644 index 00000000000..c29476b742b --- /dev/null +++ b/build/pkgs/lrcalc_python/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([lrcalc_python], [SAGE_PYTHON_PACKAGE_CHECK([lrcalc_python])]) From e00736fabd1927973f11715f35c61ab072c37fee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Fri, 15 Sep 2023 21:16:40 +0200 Subject: [PATCH 60/93] full pep8 for modular/hecke --- src/sage/modular/hecke/algebra.py | 11 +++--- src/sage/modular/hecke/ambient_module.py | 4 +-- src/sage/modular/hecke/degenmap.py | 13 ++++--- src/sage/modular/hecke/element.py | 46 +++++++++++++----------- src/sage/modular/hecke/hecke_operator.py | 36 ++++++++++--------- src/sage/modular/hecke/homspace.py | 9 +++-- src/sage/modular/hecke/morphism.py | 17 +++++---- src/sage/modular/hecke/submodule.py | 19 +++++----- 8 files changed, 83 insertions(+), 72 deletions(-) diff --git a/src/sage/modular/hecke/algebra.py b/src/sage/modular/hecke/algebra.py index 3699d2cb98e..0f6f5536a70 100644 --- a/src/sage/modular/hecke/algebra.py +++ b/src/sage/modular/hecke/algebra.py @@ -43,7 +43,7 @@ def is_HeckeAlgebra(x): r""" - Return True if x is of type HeckeAlgebra. + Return ``True`` if x is of type HeckeAlgebra. EXAMPLES:: @@ -210,7 +210,7 @@ def __call__(self, x, check=True): In the last case, the parameter ``check`` controls whether or not to check that this element really does lie in the appropriate algebra. At present, setting ``check=True`` raises - a NotImplementedError unless x is a scalar (or a diagonal + a :class:`NotImplementedError` unless x is a scalar (or a diagonal matrix). EXAMPLES:: @@ -320,7 +320,7 @@ def ngens(self): def is_noetherian(self): """ - Return True if this Hecke algebra is Noetherian as a ring. This is true + Return ``True`` if this Hecke algebra is Noetherian as a ring. This is true if and only if the base ring is Noetherian. EXAMPLES:: @@ -649,7 +649,6 @@ def __richcmp__(self, other, op): False sage: A == A True - """ if not isinstance(other, HeckeAlgebra_anemic): return NotImplemented @@ -675,9 +674,9 @@ def hecke_operator(self, n): raise IndexError("Hecke operator T_%s not defined in the anemic Hecke algebra" % n) return self.module()._hecke_operator_class()(self, n) - def is_anemic(self): + def is_anemic(self) -> bool: """ - Return True, since this is the anemic Hecke algebra. + Return ``True``, since this is the anemic Hecke algebra. EXAMPLES:: diff --git a/src/sage/modular/hecke/ambient_module.py b/src/sage/modular/hecke/ambient_module.py index 6b03862d6dd..e5ed6158cb5 100644 --- a/src/sage/modular/hecke/ambient_module.py +++ b/src/sage/modular/hecke/ambient_module.py @@ -388,12 +388,12 @@ def degeneracy_map(self, codomain, t=1): err = True if err: raise ValueError(("the level of self (=%s) must be a divisor or multiple of " - "level (=%s) and t (=%s) must be a divisor of the quotient") % (self.level(), level, t)) + "level (=%s) and t (=%s) must be a divisor of the quotient") % (self.level(), level, t)) eps = self.character() if not (eps is None) and level % eps.conductor() != 0: raise ArithmeticError("the conductor of the character of this space " - "(=%s) must be divisible by the level (=%s)" % (eps.conductor(), level)) + "(=%s) must be divisible by the level (=%s)" % (eps.conductor(), level)) if M is None: M = self.hecke_module_of_level(level) diff --git a/src/sage/modular/hecke/degenmap.py b/src/sage/modular/hecke/degenmap.py index 7475244b569..fad128c0c3c 100644 --- a/src/sage/modular/hecke/degenmap.py +++ b/src/sage/modular/hecke/degenmap.py @@ -2,7 +2,7 @@ Degeneracy maps """ -#***************************************************************************** +# **************************************************************************** # Sage: Open Source Mathematical Software # # Copyright (C) 2005 William Stein @@ -16,12 +16,11 @@ # # The full text of the GPL is available at: # -# http://www.gnu.org/licenses/ -#***************************************************************************** - - +# https://www.gnu.org/licenses/ +# **************************************************************************** from . import morphism + class DegeneracyMap(morphism.HeckeModuleMorphism_matrix): """ A degeneracy map between Hecke modules of different levels. @@ -93,8 +92,8 @@ def __init__(self, matrix, domain, codomain, t): if t == 1: pow = "" else: - pow = "^%s"%t - name = "degeneracy map corresponding to f(q) |--> f(q%s)"%(pow) + pow = "^%s" % t + name = "degeneracy map corresponding to f(q) |--> f(q%s)" % (pow) morphism.HeckeModuleMorphism_matrix.__init__(self, H, matrix, name) def t(self): diff --git a/src/sage/modular/hecke/element.py b/src/sage/modular/hecke/element.py index fb8d267cf98..b91d33b6b8d 100644 --- a/src/sage/modular/hecke/element.py +++ b/src/sage/modular/hecke/element.py @@ -6,7 +6,7 @@ - William Stein """ -#***************************************************************************** +# **************************************************************************** # Sage: Open Source Mathematical Software # # Copyright (C) 2005 William Stein @@ -20,15 +20,16 @@ # # The full text of the GPL is available at: # -# http://www.gnu.org/licenses/ -#***************************************************************************** +# https://www.gnu.org/licenses/ +# **************************************************************************** from sage.structure.richcmp import richcmp, op_NE from sage.structure.element import ModuleElement + def is_HeckeModuleElement(x): """ - Return True if x is a Hecke module element, i.e., of type HeckeModuleElement. + Return ``True`` if x is a Hecke module element, i.e., of type HeckeModuleElement. EXAMPLES:: @@ -39,6 +40,7 @@ def is_HeckeModuleElement(x): """ return isinstance(x, HeckeModuleElement) + class HeckeModuleElement(ModuleElement): """ Element of a Hecke module. @@ -180,7 +182,7 @@ def _lmul_(self, x): sage: BrandtModule(37)([0,1,-1])._lmul_(3) (0, 3, -3) """ - return self.parent()(self.element()*x) + return self.parent()(self.element() * x) def _rmul_(self, x): """ @@ -218,9 +220,9 @@ def _sub_(self, right): """ return self.parent()(self.element() - right.element()) - def is_cuspidal(self): + def is_cuspidal(self) -> bool: r""" - Return True if this element is cuspidal. + Return ``True`` if this element is cuspidal. EXAMPLES:: @@ -247,14 +249,14 @@ def is_cuspidal(self): sage: N = next(S for S in M.decomposition(anemic=False) if S.hecke_matrix(3).trace()==-128844) sage: [g.is_cuspidal() for g in N.gens()] [True, True] - """ - return (self in self.parent().ambient().cuspidal_submodule()) + return self in self.parent().ambient().cuspidal_submodule() - def is_eisenstein(self): + def is_eisenstein(self) -> bool: r""" - Return True if this element is Eisenstein. This makes sense for both - modular forms and modular symbols. + Return ``True`` if this element is Eisenstein. + + This makes sense for both modular forms and modular symbols. EXAMPLES:: @@ -269,12 +271,13 @@ def is_eisenstein(self): sage: EllipticCurve('37a1').newform().element().is_eisenstein() False """ - return (self in self.parent().ambient().eisenstein_submodule()) + return self in self.parent().ambient().eisenstein_submodule() - def is_new(self, p=None): + def is_new(self, p=None) -> bool: r""" - Return True if this element is p-new. If p is None, return True if the - element is new. + Return ``True`` if this element is p-new. + + If p is ``None``, return ``True`` if the element is new. EXAMPLES:: @@ -285,12 +288,13 @@ def is_new(self, p=None): sage: CuspForms(22, 2).0.is_new() False """ - return (self in self.parent().new_submodule(p)) + return self in self.parent().new_submodule(p) - def is_old(self, p=None): + def is_old(self, p=None) -> bool: r""" - Return True if this element is p-old. If p is None, return True if the - element is old. + Return ``True`` if this element is p-old. + + If p is ``None``, return ``True`` if the element is old. EXAMPLES:: @@ -305,4 +309,4 @@ def is_old(self, p=None): sage: EisensteinForms(144, 2).1.is_old(2) # not implemented False """ - return (self in self.parent().old_submodule(p)) + return self in self.parent().old_submodule(p) diff --git a/src/sage/modular/hecke/hecke_operator.py b/src/sage/modular/hecke/hecke_operator.py index df65f1b526d..e0401936daa 100644 --- a/src/sage/modular/hecke/hecke_operator.py +++ b/src/sage/modular/hecke/hecke_operator.py @@ -27,7 +27,7 @@ def is_HeckeOperator(x): r""" - Return True if x is of type HeckeOperator. + Return ``True`` if x is of type HeckeOperator. EXAMPLES:: @@ -40,9 +40,10 @@ def is_HeckeOperator(x): """ return isinstance(x, HeckeOperator) + def is_HeckeAlgebraElement(x): r""" - Return True if x is of type HeckeAlgebraElement. + Return ``True`` if x is of type HeckeAlgebraElement. EXAMPLES:: @@ -55,6 +56,7 @@ def is_HeckeAlgebraElement(x): """ return isinstance(x, HeckeAlgebraElement) + class HeckeAlgebraElement(AlgebraElement): r""" Base class for elements of Hecke algebras. @@ -70,7 +72,7 @@ def __init__(self, parent): Generic element of a structure """ if not algebra.is_HeckeAlgebra(parent): - raise TypeError("parent (=%s) must be a Hecke algebra"%parent) + raise TypeError("parent (=%s) must be a Hecke algebra" % parent) AlgebraElement.__init__(self, parent) def domain(self): @@ -138,7 +140,7 @@ def hecke_module_morphism(self): M = self.domain() H = End(M) if isinstance(self, HeckeOperator): - name = "T_%s"%self.index() + name = "T_%s" % self.index() else: name = "" self.__hecke_module_morphism = morphism.HeckeModuleMorphism_matrix(H, T, name) @@ -244,7 +246,7 @@ def apply_sparse(self, x): 24*(1,0) - 5*(1,9) """ if x not in self.domain(): - raise TypeError("x (=%s) must be in %s"%(x, self.domain())) + raise TypeError("x (=%s) must be in %s" % (x, self.domain())) # Generic implementation which doesn't actually do anything # special regarding sparseness. Override this for speed. T = self.hecke_module_morphism() @@ -300,7 +302,7 @@ def decomposition(self): except AttributeError: pass if isinstance(self, HeckeOperator) and \ - arith.gcd(self.index(), self.domain().level()) == 1: + arith.gcd(self.index(), self.domain().level()) == 1: D = self.hecke_module_morphism().decomposition(is_diagonalizable=True) else: # TODO: There are other weaker hypotheses that imply diagonalizability. @@ -463,7 +465,7 @@ def _richcmp_(self, other, op): if isinstance(other, HeckeOperator): return richcmp(self, other.matrix_form(), op) else: - raise RuntimeError("Bug in coercion code") # can't get here + raise RuntimeError("Bug in coercion code") # can't get here return richcmp(self.__matrix, other.__matrix, op) @@ -636,7 +638,7 @@ def _richcmp_(self, other, op): if isinstance(other, HeckeAlgebraElement_matrix): return richcmp(self.matrix_form(), other, op) else: - raise RuntimeError("Bug in coercion code") # can't get here + raise RuntimeError("Bug in coercion code") # can't get here if self.__n == other.__n: return rich_to_bool(op, 0) @@ -651,7 +653,7 @@ def _repr_(self): sage: ModularSymbols(Gamma0(7), 4).hecke_operator(6)._repr_() 'Hecke operator T_6 on Modular Symbols space of dimension 4 for Gamma_0(7) of weight 4 with sign 0 over Rational Field' """ - return "Hecke operator T_%s on %s"%(self.__n, self.domain()) + return "Hecke operator T_%s on %s" % (self.__n, self.domain()) def _latex_(self): r""" @@ -662,15 +664,17 @@ def _latex_(self): sage: ModularSymbols(Gamma0(7), 4).hecke_operator(6)._latex_() 'T_{6}' """ - return "T_{%s}"%self.__n + return "T_{%s}" % self.__n def _mul_(self, other): - """ - Multiply this Hecke operator by another element of the same algebra. If - the other element is of the form `T_m` for some m, we check whether the - product is equal to `T_{mn}` and return that; if the product is not - (easily seen to be) of the form `T_{mn}`, then we calculate the product - of the two matrices and return a Hecke algebra element defined by that. + r""" + Multiply this Hecke operator by another element of the same algebra. + + If the other element is of the form `T_m` for some m, we check + whether the product is equal to `T_{mn}` and return that; if + the product is not (easily seen to be) of the form `T_{mn}`, + then we calculate the product of the two matrices and return a + Hecke algebra element defined by that. EXAMPLES: We create the space of modular symbols of level `11` and weight `2`, then compute `T_2` diff --git a/src/sage/modular/hecke/homspace.py b/src/sage/modular/hecke/homspace.py index a42e40e3584..2245067bf99 100644 --- a/src/sage/modular/hecke/homspace.py +++ b/src/sage/modular/hecke/homspace.py @@ -1,7 +1,7 @@ r""" Hom spaces between Hecke modules """ -#***************************************************************************** +# **************************************************************************** # Copyright (C) 2005 William Stein # # Distributed under the terms of the GNU General Public License (GPL) @@ -13,9 +13,8 @@ # See the GNU General Public License for more details; the full text # is available at: # -# http://www.gnu.org/licenses/ -#***************************************************************************** - +# https://www.gnu.org/licenses/ +# **************************************************************************** from sage.matrix.constructor import matrix from sage.matrix.matrix_space import MatrixSpace from sage.categories.homset import HomsetWithBase @@ -25,7 +24,7 @@ def is_HeckeModuleHomspace(x): r""" - Return True if x is a space of homomorphisms in the category of Hecke modules. + Return ``True`` if x is a space of homomorphisms in the category of Hecke modules. EXAMPLES:: diff --git a/src/sage/modular/hecke/morphism.py b/src/sage/modular/hecke/morphism.py index 92df8ca77dc..373d2b67298 100644 --- a/src/sage/modular/hecke/morphism.py +++ b/src/sage/modular/hecke/morphism.py @@ -6,7 +6,7 @@ - William Stein """ -#***************************************************************************** +# **************************************************************************** # Sage: Open Source Mathematical Software # # Copyright (C) 2005 William Stein @@ -20,8 +20,8 @@ # # The full text of the GPL is available at: # -# http://www.gnu.org/licenses/ -#***************************************************************************** +# https://www.gnu.org/licenses/ +# **************************************************************************** import sage.misc.misc as misc @@ -33,9 +33,10 @@ # modular abelian varieties (which are specified by matrices, but on # integral homology). All morphisms derive from HeckeModuleMorphism. + def is_HeckeModuleMorphism(x): r""" - Return True if x is of type HeckeModuleMorphism. + Return ``True`` if x is of type HeckeModuleMorphism. EXAMPLES:: @@ -44,6 +45,7 @@ def is_HeckeModuleMorphism(x): """ return isinstance(x, HeckeModuleMorphism) + def is_HeckeModuleMorphism_matrix(x): """ @@ -54,12 +56,14 @@ def is_HeckeModuleMorphism_matrix(x): """ return isinstance(x, HeckeModuleMorphism_matrix) + class HeckeModuleMorphism(Morphism): r""" Abstract base class for morphisms of Hecke modules. """ pass + class HeckeModuleMorphism_matrix(MatrixMorphism, HeckeModuleMorphism): """ Morphisms of Hecke modules when the morphism is given by a matrix. @@ -146,9 +150,8 @@ def _repr_(self): 'Hecke module morphism spam defined by the matrix\n[0 1 2]\n[3 4 5]\n[6 7 8]\nDomain: Modular Symbols space of dimension 3 for Gamma_0(6) of weight ...\nCodomain: Modular Symbols space of dimension 3 for Gamma_0(6) of weight ...' """ name = self.__name - if name != '': + if name: name += ' ' - return "Hecke module morphism %sdefined by the matrix\n%r\nDomain: %s\nCodomain: %s"%( - name, self.matrix(), misc.strunc(self.domain()), misc.strunc(self.codomain())) + return "Hecke module morphism %sdefined by the matrix\n%r\nDomain: %s\nCodomain: %s" % (name, self.matrix(), misc.strunc(self.domain()), misc.strunc(self.codomain())) # __mul__ method removed by David Loeffler 2009-04-14 as it is an exact duplicate of sage.modules.matrix_morphism.__mul__ diff --git a/src/sage/modular/hecke/submodule.py b/src/sage/modular/hecke/submodule.py index e50b9d723e8..c1112d685b6 100644 --- a/src/sage/modular/hecke/submodule.py +++ b/src/sage/modular/hecke/submodule.py @@ -29,7 +29,7 @@ def is_HeckeSubmodule(x): r""" - Return True if x is of type HeckeSubmodule. + Return ``True`` if x is of type HeckeSubmodule. EXAMPLES:: @@ -91,8 +91,9 @@ def __init__(self, ambient, submodule, dual_free_module=None, check=True): self.__ambient = ambient self.__submodule = submodule - module.HeckeModule_free_module.__init__(self, - ambient.base_ring(), ambient.level(), ambient.weight()) + module.HeckeModule_free_module.__init__(self, ambient.base_ring(), + ambient.level(), + ambient.weight()) if not (dual_free_module is None): if not is_FreeModule(dual_free_module): raise TypeError("dual_free_module must be a free module") @@ -446,10 +447,12 @@ def degeneracy_map(self, level, t=1): @cached_method def dual_free_module(self, bound=None, anemic=True, use_star=True): r""" - Compute embedded dual free module if possible. In general this won't be - possible, e.g., if this space is not Hecke equivariant, possibly if it - is not cuspidal, or if the characteristic is not 0. In all these cases - we raise a RuntimeError exception. + Compute embedded dual free module if possible. + + In general this will not be possible, e.g., if this space is + not Hecke equivariant, possibly if it is not cuspidal, or if + the characteristic is not 0. In all these cases we raise a + :class:`RuntimeError` exception. If use_star is True (which is the default), we also use the +/- eigenspaces for the star operator to find the dual free module of self. @@ -587,7 +590,7 @@ def dual_free_module(self, bound=None, anemic=True, use_star=True): return V2 raise RuntimeError("Computation of embedded dual vector space failed " - "(cut down to rank %s, but should have cut down to rank %s)." % (V.rank(), self.rank())) + "(cut down to rank %s, but should have cut down to rank %s)." % (V.rank(), self.rank())) def free_module(self): """ From b801ebbfb3fa77e96172aa7a6b317fb096bb420f Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 23 Sep 2023 09:03:30 -0700 Subject: [PATCH 61/93] build/pkgs/setuptools_scm_git_archive: Remove (obsolete) --- build/pkgs/matplotlib/dependencies | 2 +- build/pkgs/setuptools_scm_git_archive/SPKG.rst | 18 ------------------ .../setuptools_scm_git_archive/checksums.ini | 5 ----- .../setuptools_scm_git_archive/dependencies | 4 ---- .../install-requires.txt | 1 - .../package-version.txt | 1 - .../setuptools_scm_git_archive/spkg-install.in | 2 -- build/pkgs/setuptools_scm_git_archive/type | 1 - 8 files changed, 1 insertion(+), 33 deletions(-) delete mode 100644 build/pkgs/setuptools_scm_git_archive/SPKG.rst delete mode 100644 build/pkgs/setuptools_scm_git_archive/checksums.ini delete mode 100644 build/pkgs/setuptools_scm_git_archive/dependencies delete mode 100644 build/pkgs/setuptools_scm_git_archive/install-requires.txt delete mode 100644 build/pkgs/setuptools_scm_git_archive/package-version.txt delete mode 100644 build/pkgs/setuptools_scm_git_archive/spkg-install.in delete mode 100644 build/pkgs/setuptools_scm_git_archive/type diff --git a/build/pkgs/matplotlib/dependencies b/build/pkgs/matplotlib/dependencies index f2968081f9c..8abcba00ee8 100644 --- a/build/pkgs/matplotlib/dependencies +++ b/build/pkgs/matplotlib/dependencies @@ -1,4 +1,4 @@ - numpy freetype pillow dateutil pyparsing tornado cycler qhull fonttools contourpy | $(PYTHON_TOOLCHAIN) kiwisolver certifi setuptools_scm_git_archive $(PYTHON) + numpy freetype pillow dateutil pyparsing tornado cycler qhull fonttools contourpy | $(PYTHON_TOOLCHAIN) kiwisolver certifi setuptools_scm $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/setuptools_scm_git_archive/SPKG.rst b/build/pkgs/setuptools_scm_git_archive/SPKG.rst deleted file mode 100644 index 540e0c2d923..00000000000 --- a/build/pkgs/setuptools_scm_git_archive/SPKG.rst +++ /dev/null @@ -1,18 +0,0 @@ -setuptools_scm_git_archive: setuptools_scm plugin for git archives -================================================================== - -Description ------------ - -setuptools_scm plugin for git archives - -License -------- - -MIT - -Upstream Contact ----------------- - -https://pypi.org/project/setuptools-scm-git-archive/ - diff --git a/build/pkgs/setuptools_scm_git_archive/checksums.ini b/build/pkgs/setuptools_scm_git_archive/checksums.ini deleted file mode 100644 index ed010b0f53e..00000000000 --- a/build/pkgs/setuptools_scm_git_archive/checksums.ini +++ /dev/null @@ -1,5 +0,0 @@ -tarball=setuptools_scm_git_archive-VERSION.tar.gz -sha1=5e893fcb35f9633ea1431138c1d90a5f2687b36d -md5=df3933d33c49c5d9aca06715b4c65370 -cksum=2554004806 -upstream_url=https://pypi.io/packages/source/s/setuptools_scm_git_archive/setuptools_scm_git_archive-VERSION.tar.gz diff --git a/build/pkgs/setuptools_scm_git_archive/dependencies b/build/pkgs/setuptools_scm_git_archive/dependencies deleted file mode 100644 index 47296a7bace..00000000000 --- a/build/pkgs/setuptools_scm_git_archive/dependencies +++ /dev/null @@ -1,4 +0,0 @@ - | $(PYTHON_TOOLCHAIN) $(PYTHON) - ----------- -All lines of this file are ignored except the first. diff --git a/build/pkgs/setuptools_scm_git_archive/install-requires.txt b/build/pkgs/setuptools_scm_git_archive/install-requires.txt deleted file mode 100644 index 538474ff946..00000000000 --- a/build/pkgs/setuptools_scm_git_archive/install-requires.txt +++ /dev/null @@ -1 +0,0 @@ -setuptools-scm-git-archive diff --git a/build/pkgs/setuptools_scm_git_archive/package-version.txt b/build/pkgs/setuptools_scm_git_archive/package-version.txt deleted file mode 100644 index c068b2447cc..00000000000 --- a/build/pkgs/setuptools_scm_git_archive/package-version.txt +++ /dev/null @@ -1 +0,0 @@ -1.4 diff --git a/build/pkgs/setuptools_scm_git_archive/spkg-install.in b/build/pkgs/setuptools_scm_git_archive/spkg-install.in deleted file mode 100644 index 37ac1a53437..00000000000 --- a/build/pkgs/setuptools_scm_git_archive/spkg-install.in +++ /dev/null @@ -1,2 +0,0 @@ -cd src -sdh_pip_install . diff --git a/build/pkgs/setuptools_scm_git_archive/type b/build/pkgs/setuptools_scm_git_archive/type deleted file mode 100644 index a6a7b9cd726..00000000000 --- a/build/pkgs/setuptools_scm_git_archive/type +++ /dev/null @@ -1 +0,0 @@ -standard From 722bc8490bf45cece4adb25a501b6fc1e7061918 Mon Sep 17 00:00:00 2001 From: Luze Xu Date: Thu, 13 Apr 2023 21:58:21 -0700 Subject: [PATCH 62/93] Docstring reformatting --- src/sage/categories/crystals.py | 56 +++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 24 deletions(-) diff --git a/src/sage/categories/crystals.py b/src/sage/categories/crystals.py index edeb6fb9b35..74a8319da29 100644 --- a/src/sage/categories/crystals.py +++ b/src/sage/categories/crystals.py @@ -919,7 +919,7 @@ def digraph(self, subset=None, index_set=None): def latex_file(self, filename): r""" - Export a file, suitable for pdflatex, to 'filename'. + Export a file, suitable for pdflatex, to ``filename``. This requires a proper installation of ``dot2tex`` in sage-python. For more @@ -954,7 +954,7 @@ def latex_file(self, filename): def _latex_(self, **options): r""" Returns the crystal graph as a latex string. This can be exported - to a file with self.latex_file('filename'). + to a file with ``self.latex_file('filename')``. EXAMPLES:: @@ -977,15 +977,9 @@ def _latex_(self, **options): def metapost(self, filename, thicklines=False, labels=True, scaling_factor=1.0, tallness=1.0): r""" - Use C.metapost("filename.mp",[options]), where options can be: + Export a file, suitable for MetaPost, to ``filename``. - thicklines = True (for thicker edges) labels = False (to suppress - labeling of the vertices) scaling_factor=value, where value is a - floating point number, 1.0 by default. Increasing or decreasing the - scaling factor changes the size of the image. tallness=1.0. - Increasing makes the image taller without increasing the width. - - Root operators e(1) or f(1) move along red lines, e(2) or f(2) + Root operators `e(1)` or `f(1)` move along red lines, `e(2)` or `f(2)` along green. The highest weight is in the lower left. Vertices with the same weight are kept close together. The concise labels on the nodes are strings introduced by Berenstein and Zelevinsky and @@ -994,20 +988,34 @@ def metapost(self, filename, thicklines=False, labels=True, scaling_factor=1.0, For Cartan types B2 or C2, the pattern has the form - a2 a3 a4 a1 + `a_2 a_3 a_4 a_1` - where c\*a2 = a3 = 2\*a4 =0 and a1=0, with c=2 for B2, c=1 for C2. - Applying e(2) a1 times, e(1) a2 times, e(2) a3 times, e(1) a4 times + where `c*a_2 = a_3 = 2*a_4 = 0` and `a_1=0`, with `c=2` for B2, `c=1` for C2. + Applying `e(2)` `a_1` times, `e(1)` `a_2` times, `e(2)` `a_3` times, `e(1)` `a_4` times returns to the highest weight. (Observe that Littelmann writes the - roots in opposite of the usual order, so our e(1) is his e(2) for + roots in opposite of the usual order, so our `e(1)` is his `e(2)` for these Cartan types.) For type A2, the pattern has the form - a3 a2 a1 + `a_3 a_2 a_1` - where applying e(1) a1 times, e(2) a2 times then e(3) a1 times + where applying `e(1)` `a_3` times, `e(2)` `a_2` times then `e(1)` `a_1` times returns to the highest weight. These data determine the vertex and may be translated into a Gelfand-Tsetlin pattern or tableau. + INPUT: + + - ``filename`` -- name of the output file, e.g., ``'filename.mp'`` + + - ``thicklines`` -- (default: ``True``) for thicker edges + + - ``labels`` -- (default: False) to suppress labeling of the vertices + + - ``scaling_factor`` -- (default: ``1.0``) Increasing or decreasing the + scaling factor changes the size of the image + + - ``tallness`` -- (default: ``1.0``) Increasing makes the image taller + without increasing the width + EXAMPLES:: sage: C = crystals.Letters(['A', 2]) @@ -1450,7 +1458,7 @@ def Phi(self): def f_string(self, list): r""" - Applies `f_{i_r} \cdots f_{i_1}` to self for ``list`` as + Applies `f_{i_r} \cdots f_{i_1}` to ``self`` for ``list`` as `[i_1, ..., i_r]` EXAMPLES:: @@ -1470,7 +1478,7 @@ def f_string(self, list): def e_string(self, list): r""" - Applies `e_{i_r} \cdots e_{i_1}` to self for ``list`` as + Applies `e_{i_r} \cdots e_{i_1}` to ``self`` for ``list`` as `[i_1, ..., i_r]` EXAMPLES:: @@ -1562,11 +1570,11 @@ def is_lowest_weight(self, index_set=None): def to_highest_weight(self, index_set=None): r""" Return the highest weight element `u` and a list `[i_1,...,i_k]` - such that `self = f_{i_1} ... f_{i_k} u`, where `i_1,...,i_k` are + such that ``self`` `= f_{i_1} ... f_{i_k} u`, where `i_1,...,i_k` are elements in ``index_set``. - By default the index set is assumed to be - the full index set of self. + By default the ``index_set`` is assumed to be + the full index set of ``self``. EXAMPLES:: @@ -1603,11 +1611,11 @@ def to_highest_weight(self, index_set=None): def to_lowest_weight(self, index_set=None): r""" Return the lowest weight element `u` and a list `[i_1,...,i_k]` - such that `self = e_{i_1} ... e_{i_k} u`, where `i_1,...,i_k` are + such that ``self`` `= e_{i_1} ... e_{i_k} u`, where `i_1,...,i_k` are elements in ``index_set``. - By default the index set is assumed to be the full index - set of self. + By default the ``index_set`` is assumed to be the full index + set of ``self``. EXAMPLES:: From e25aa2535c28c503c4aed82462647eb96f6a140f Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Fri, 22 Sep 2023 17:51:21 -0400 Subject: [PATCH 63/93] src/sage/combinat/words/words.py: replace tmp_dir() Standard tempfile.TemporaryDirectory() replacement. Issue: https://github.com/sagemath/sage/issues/36322 --- src/sage/combinat/words/words.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/sage/combinat/words/words.py b/src/sage/combinat/words/words.py index 50cb3db11e8..900ab9c8508 100644 --- a/src/sage/combinat/words/words.py +++ b/src/sage/combinat/words/words.py @@ -1635,11 +1635,12 @@ def __setstate__(self, state): r""" TESTS:: - sage: import os + sage: import os, tempfile sage: W = Words('ab') - sage: filename = os.path.join(tmp_dir(), 'test.sobj') - sage: W.save(filename) - sage: load(filename) + sage: with tempfile.TemporaryDirectory() as d: + ....: filename = os.path.join(d, 'test.sobj') + ....: W.save(filename) + ....: load(filename) Finite and infinite words over {'a', 'b'} """ # add a default to support old pickles from #19619 @@ -2100,11 +2101,12 @@ def __setstate__(self, state): r""" TESTS:: - sage: import os + sage: import os, tempfile sage: W = Words('ab', 10) - sage: filename = os.path.join(tmp_dir(), 'test.sobj') - sage: W.save(filename) - sage: load(filename) + sage: with tempfile.TemporaryDirectory() as d: + ....: filename = os.path.join(d, 'test.sobj') + ....: W.save(filename) + ....: load(filename) Words of length 10 over {'a', 'b'} """ # add a default to support old pickles from #19619 From e05f75f166d0b15146fb05b2187cf5484c7d8112 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Mon, 25 Sep 2023 08:53:23 +0200 Subject: [PATCH 64/93] more fixes for E228 and E225 in combinat and some other folders --- src/sage/combinat/affine_permutation.py | 62 +++++----- src/sage/combinat/integer_vector.py | 10 +- .../combinat/integer_vectors_mod_permgroup.py | 10 +- src/sage/combinat/k_tableau.py | 84 +++++++------- .../multiset_partition_into_sets_ordered.py | 18 +-- src/sage/combinat/partition.py | 78 ++++++------- src/sage/combinat/partition_kleshchev.py | 8 +- src/sage/combinat/partition_tuple.py | 104 ++++++++--------- src/sage/combinat/permutation.py | 36 +++--- src/sage/combinat/tableau.py | 4 +- src/sage/combinat/tableau_tuple.py | 12 +- src/sage/combinat/vector_partition.py | 10 +- src/sage/knots/knotinfo.py | 22 ++-- src/sage/knots/link.py | 10 +- src/sage/misc/inline_fortran.py | 4 +- src/sage/misc/sageinspect.py | 24 ++-- src/sage/misc/superseded.py | 2 +- src/sage/misc/temporary_file.py | 2 +- src/sage/monoids/free_abelian_monoid.py | 2 +- src/sage/monoids/free_monoid_element.py | 4 +- src/sage/monoids/hecke_monoid.py | 2 +- src/sage/monoids/string_monoid.py | 2 +- src/sage/quadratic_forms/ternary_qf.py | 26 ++--- src/sage/sandpiles/examples.py | 6 +- src/sage/sandpiles/sandpile.py | 106 +++++++++--------- src/sage/structure/formal_sum.py | 4 +- src/sage/structure/gens_py.py | 4 +- src/sage/structure/sequence.py | 4 +- 28 files changed, 330 insertions(+), 330 deletions(-) diff --git a/src/sage/combinat/affine_permutation.py b/src/sage/combinat/affine_permutation.py index 13144414cb9..17279fee0e8 100644 --- a/src/sage/combinat/affine_permutation.py +++ b/src/sage/combinat/affine_permutation.py @@ -394,7 +394,7 @@ def grassmannian_quotient(self, i=0, side='right'): while not (D == [i] or D == []): m = D[0] if m == i: - m=D[1] + m = D[1] if side == 'right': fin = fin.apply_simple_reflection(m, side='left') gr = gr.apply_simple_reflection(m, side='right') @@ -470,7 +470,7 @@ def value(self, i, base_window=False): if base_window: self[i-1] window = (i-1) // (self.k+1) - return self[(i-1)%(self.k+1)] + window*(self.k+1) + return self[(i-1) % (self.k+1)] + window*(self.k+1) def position(self, i): r""" @@ -518,7 +518,7 @@ def apply_simple_reflection_right(self, i): if j == 0: a = l[0] l[0] = l[-1] - (self.k+1) - l[-1] = a +(self.k+1) + l[-1] = a + (self.k+1) else: a = l[j-1] l[j-1] = l[j] @@ -589,7 +589,7 @@ def has_right_descent(self, i) -> bool: sage: p.has_right_descent(0) False """ - return self.value(i)>self.value(i+1) + return self.value(i) > self.value(i+1) def has_left_descent(self, i) -> bool: r""" @@ -708,20 +708,20 @@ def maximal_cyclic_factor(self, typ='decreasing', side='right', verbose=False): j = i for _ in range(1, self.k): if (typ[0],side[0]) == ('d', 'r'): - j=(j+1)%(k+1) + j = (j+1) % (k+1) if (typ[0],side[0]) == ('i', 'r'): - j=(j-1)%(k+1) + j = (j-1) % (k+1) if (typ[0],side[0]) == ('d', 'l'): - j=(j-1)%(k+1) + j = (j-1) % (k+1) if (typ[0],side[0]) == ('i', 'l'): - j=(j+1)%(k+1) + j = (j+1) % (k+1) if y.has_descent(j, side): - y=y.apply_simple_reflection(j,side) - T.append(j%(k+1)) + y = y.apply_simple_reflection(j,side) + T.append(j % (k+1)) if verbose: print(i, T) if len(T) > len(best_T): - best_T=T + best_T = T #if (typ[0],side[0])==('i','r'): best_T.reverse() #if (typ[0],side[0])==('d','l'): best_T.reverse() #if typ[0]=='d': best_T.reverse() @@ -791,7 +791,7 @@ def maximal_cyclic_decomposition(self, typ='decreasing', side='right', verbose=F y = y.apply_simple_reflection_left(i) if verbose: print(S, y.length()) - if side[0]=='r': + if side[0] == 'r': listy.reverse() return listy @@ -848,13 +848,13 @@ def to_lehmer_code(self, typ='decreasing', side='right'): #value than the number in position i. Then cyclically shift #the resulting vector. for i in range(self.k+1): - a=self(i) + a = self(i) for j in range(i-self.k, i): - b=self(j) + b = self(j) # A small rotation is necessary for the reduced word from # the Lehmer code to match the element. if a < b: - code[i-1]+=((b-a)//(self.k+1)+1) + code[i-1] += ((b-a)//(self.k+1)+1) elif typ[0] == 'i' and side[0] == 'l': #Find number of positions to the right of i smaller than i, then #cyclically shift the resulting vector. @@ -866,7 +866,7 @@ def to_lehmer_code(self, typ='decreasing', side='right'): #the lehmer code to match the element. if b < i: code[i-1] += (i-b) // (self.k+1) + 1 - elif typ[0] == 'd' and side[0]=='l': + elif typ[0] == 'd' and side[0] == 'l': #Find number of positions to the left of i larger than i. for i in range(self.k+1): pos = self.position(i) @@ -1029,7 +1029,7 @@ def tableau_of_word(self, w, typ='decreasing', side='right', alpha=None): if x0.length() != len(w): raise ValueError("word was not reduced") if alpha is None: - alpha=Composition([1 for i in w]) + alpha = Composition([1 for i in w]) else: if sum(alpha) != len(w): raise ValueError("size of alpha must match length of w") @@ -1647,7 +1647,7 @@ def check(self): if not len(self) == 6: raise ValueError("length of list must be 6") #Check that we have an even number of 'big' elements left of the 7th entry. - s = sum(i//6 - (i%6 == 0) for i in self if i > 6) + s = sum(i//6 - (i % 6 == 0) for i in self if i > 6) if s % 2: raise ValueError("type G affine permutations have an even number of" " entries greater than 6 to the left of the 7th position") @@ -1678,7 +1678,7 @@ def value(self, i, base_window=False): if base_window: self[i-1] window = (i-1) // N - return self[(i-1)%N] + window*(N) + return self[(i-1) % N] + window*(N) def position(self, i): r""" @@ -1758,28 +1758,28 @@ def apply_simple_reflection_left(self, i): l = [] if i == 1: for m in range(6): - res=self[m]%6 - if res==1 or res==3 or res==5: + res = self[m] % 6 + if res == 1 or res == 3 or res == 5: l.append(self[m]+1) - elif res==2 or res==4 or res==0: + elif res == 2 or res == 4 or res == 0: l.append(self[m]-1) else: l.append(self[m]) elif i == 2: for m in range(6): - res=self[m]%6 - if res==2 or res==4: + res = self[m] % 6 + if res == 2 or res == 4: l.append(self[m]+1) - elif res==3 or res==5: + elif res == 3 or res == 5: l.append(self[m]-1) else: l.append(self[m]) elif i == 0: for m in range(6): - res=self[m]%6 - if res==1 or res==2: + res = self[m] % 6 + if res == 1 or res == 2: l.append(self[m]-2) - elif res==5 or res==0: + elif res == 5 or res == 0: l.append(self[m]+2) else: l.append(self[m]) @@ -1983,9 +1983,9 @@ def AffinePermutationGroup(cartan_type): Type G affine permutation with window [0, 4, -1, 8, 3, 7] """ ct = CartanType(cartan_type) - if ct.letter=='A': + if ct.letter == 'A': return AffinePermutationGroupTypeA(ct) - if ct.letter=='B': + if ct.letter == 'B': return AffinePermutationGroupTypeB(ct) if ct.letter == 'C': return AffinePermutationGroupTypeC(ct) @@ -2140,7 +2140,7 @@ def index_set(self): """ return self.cartan_type().index_set() - _index_set=index_set + _index_set = index_set def reflection_index_set(self): r""" diff --git a/src/sage/combinat/integer_vector.py b/src/sage/combinat/integer_vector.py index 5cd4911e4e0..65eb4dfc4e9 100644 --- a/src/sage/combinat/integer_vector.py +++ b/src/sage/combinat/integer_vector.py @@ -111,8 +111,8 @@ def is_gale_ryser(r,s): # builds the corresponding partitions, i.e. # removes the 0 and sorts the sequences from sage.combinat.partition import Partition - r2 = Partition(sorted([x for x in r if x>0], reverse=True)) - s2 = Partition(sorted([x for x in s if x>0], reverse=True)) + r2 = Partition(sorted([x for x in r if x > 0], reverse=True)) + s2 = Partition(sorted([x for x in s if x > 0], reverse=True)) # If the two sequences only contained zeroes if len(r2) == 0 and len(s2) == 0: @@ -361,13 +361,13 @@ def gale_ryser_theorem(p1, p2, algorithm="gale", elif algorithm == "gale": from sage.numerical.mip import MixedIntegerLinearProgram - k1, k2=len(p1), len(p2) + k1, k2 = len(p1), len(p2) p = MixedIntegerLinearProgram(solver=solver) b = p.new_variable(binary=True) for (i,c) in enumerate(p1): - p.add_constraint(p.sum([b[i,j] for j in range(k2)]) ==c) + p.add_constraint(p.sum([b[i,j] for j in range(k2)]) == c) for (i,c) in enumerate(p2): - p.add_constraint(p.sum([b[j,i] for j in range(k1)]) ==c) + p.add_constraint(p.sum([b[j,i] for j in range(k1)]) == c) p.set_objective(None) p.solve() b = p.get_values(b, convert=ZZ, tolerance=integrality_tolerance) diff --git a/src/sage/combinat/integer_vectors_mod_permgroup.py b/src/sage/combinat/integer_vectors_mod_permgroup.py index 46365a26eeb..8503bd978c5 100644 --- a/src/sage/combinat/integer_vectors_mod_permgroup.py +++ b/src/sage/combinat/integer_vectors_mod_permgroup.py @@ -431,8 +431,8 @@ def is_canonical(self, v, check=True): False """ if check: - assert isinstance(v, (ClonableIntArray, list)), '%s should be a list or a integer vector'%v - assert (self.n == len(v)), '%s should be of length %s'%(v, self.n) + assert isinstance(v, (ClonableIntArray, list)), '%s should be a list or a integer vector' % v + assert (self.n == len(v)), '%s should be of length %s' % (v, self.n) for p in v: assert (p == NN(p)), 'Elements of %s should be integers' % v return is_canonical(self._sgs, self.element_class(self, list(v), check=False)) @@ -473,7 +473,7 @@ def __call__(self, v, check=True): if v.parent() is self: return v else: - raise ValueError('%s should be a Python list of integer'%(v)) + raise ValueError('%s should be a Python list of integer' % (v)) except Exception: return self.element_class(self, list(v), check=check) @@ -499,7 +499,7 @@ def orbit(self, v): sage: I.orbit([1,1,1,1]) {[1, 1, 1, 1]} """ - assert isinstance(v, (list, ClonableIntArray)), '%s should be a Python list or an element of %s'%(v, self) + assert isinstance(v, (list, ClonableIntArray)), '%s should be a Python list or an element of %s' % (v, self) try: if v.parent() is self: return orbit(self._sgs, v) @@ -720,7 +720,7 @@ def __call__(self, v, check=True): if v.parent() is self: return v else: - raise ValueError('%s should be a Python list of integer'%(v)) + raise ValueError('%s should be a Python list of integer' % (v)) except Exception: return self.element_class(self, list(v), check=check) diff --git a/src/sage/combinat/k_tableau.py b/src/sage/combinat/k_tableau.py index 77264231908..3aeeb543567 100644 --- a/src/sage/combinat/k_tableau.py +++ b/src/sage/combinat/k_tableau.py @@ -469,7 +469,7 @@ def chi(x): return "" if x in ZZ: return x - return "%s"%x + return "%s" % x if self.parent()._representation in ['core', 'bounded']: t = [[chi(x) for x in row] for row in self] from .output import tex_from_array @@ -960,8 +960,8 @@ def dictionary_of_coordinates_at_residues(self, v): d[r] = [] for i in range(len(self)): for j in range(len(self[i])): - if self[i][j]==v and (j - i)%(self.k+1) == r: - d[r]+=[(i,j)] + if self[i][j] == v and (j - i) % (self.k+1) == r: + d[r] += [(i,j)] return d def list_of_standard_cells(self): @@ -1027,7 +1027,7 @@ def list_of_standard_cells(self): D = self.dictionary_of_coordinates_at_residues(v+1) new_D = {a: b for (a, b) in D.items() if all(x not in already_used for x in b)} - r = (r - min([self.k+1 - (x-r)%(self.k+1) for x in new_D]))%(self.k+1) + r = (r - min([self.k+1 - (x-r) % (self.k+1) for x in new_D])) % (self.k+1) standard_cells.append(new_D[r][-1]) already_used += new_D[r] out.append(standard_cells) @@ -1165,8 +1165,8 @@ def k_charge_J(self): Ji = 0 for i in range(len(sw)-1): c = (self._height_of_restricted_subword(sw,i+2)+1,0) - cdi = self.parent().circular_distance((-c[0])%(self.k+1),(sw[i][1]-sw[i][0])%(self.k+1)) - cdi1 = self.parent().circular_distance((-c[0])%(self.k+1),(sw[i+1][1]-sw[i+1][0])%(self.k+1)) + cdi = self.parent().circular_distance((-c[0]) % (self.k+1),(sw[i][1]-sw[i][0]) % (self.k+1)) + cdi1 = self.parent().circular_distance((-c[0]) % (self.k+1),(sw[i+1][1]-sw[i+1][0]) % (self.k+1)) if (cdi > cdi1): Ji += 1 kch += Ji + self.parent().diag(sw[i+1],c) @@ -1365,7 +1365,7 @@ def circular_distance(self, cr, r): sage: T.circular_distance(8, 9) 10 """ - return self.k - ((r+self.k-cr)%(self.k+1)) + return self.k - ((r+self.k-cr) % (self.k+1)) Element = WeakTableau_core @@ -1407,7 +1407,7 @@ def __classcall_private__(cls, t, k): inner = tab.inner_shape() weight = tuple(tab.weight()) if outer.conjugate().length() > k: - raise ValueError("The shape of %s is not %s-bounded"%(t, k)) + raise ValueError("The shape of %s is not %s-bounded" % (t, k)) return WeakTableaux_bounded(k, [outer, inner], weight)(t) def __init__(self, parent, t): @@ -1450,7 +1450,7 @@ def __init__(self, parent, t): k = parent.k self.k = k if parent._outer_shape.conjugate().length() > k: - raise ValueError("%s is not a %s-bounded tableau"%(t, k)) + raise ValueError("%s is not a %s-bounded tableau" % (t, k)) ClonableList.__init__(self, parent, [list(r) for r in t]) def _repr_diagram(self): @@ -2389,8 +2389,8 @@ def __classcall_private__(cls, T, k, weight=None): if weight is not None and tuple(weight) != count_marks: raise ValueError("Weight = %s and tableau = %s do not agree" % (weight, T)) tijseq = StrongTableaux.marked_CST_to_transposition_sequence(T, k) - if tijseq is None or len(tijseq)=abs(v)]) + return sgn(v)*min([i for i in range(len(self.weight())+1) if sum(self.weight()[:i]) >= abs(v)]) return [[f(v) for v in row] for row in self.to_standard_list()] def to_unmarked_list( self ): @@ -3628,11 +3628,11 @@ def chi(x): if x is None: return "" if x in ZZ: - s = "%s"%abs(x) - if x<0: + s = "%s" % abs(x) + if x < 0: s += "^\\ast" return s - return "%s"%x + return "%s" % x T = [[chi(x) for x in row] for row in self.to_list()] from .output import tex_from_array return tex_from_array(T) @@ -3674,7 +3674,7 @@ def restrict( self, r ): [] """ rr = sum(self.weight()[:r]) - rest_tab = [y for y in ([x for x in row if x is None or abs(x)<=rr] for row in self.to_standard_list()) if y] + rest_tab = [y for y in ([x for x in row if x is None or abs(x) <= rr] for row in self.to_standard_list()) if y] new_parent = StrongTableaux( self.k, (Core([len(x) for x in rest_tab], self.k+1), self.inner_shape()), self.weight()[:r] ) return new_parent(rest_tab) @@ -3710,7 +3710,7 @@ def set_weight( self, mu ): sage: StrongTableau([],4).set_weight([]) [] """ - if sum(mu)!=self.size() or self.is_column_strict_with_weight( mu ): + if sum(mu) != self.size() or self.is_column_strict_with_weight( mu ): return StrongTableaux.__classcall__(StrongTableaux, self.k, (self.outer_shape(), self.inner_shape()), tuple(mu))(self.to_standard_list()) else: raise ValueError("%s is not a semistandard strong tableau with respect to the partition %s" % (self, mu)) @@ -3957,9 +3957,9 @@ def __classcall_private__(cls, k, shape, weight=None): sage: ST3 = StrongTableaux(3, [2,2], weight=[1,1,1,1]) sage: TestSuite(ST3).run() """ - if k<=0: + if k <= 0: raise ValueError("The input k has to be a positive integer") - if shape==[] or shape[0] in ZZ: + if shape == [] or shape[0] in ZZ: outer_shape = Core(shape,k+1) inner_shape = Core([],k+1) else: @@ -3984,13 +3984,13 @@ def _repr_( self ): sage: StrongTableaux(3, [[],[]], weight=[]) Set of strong 3-tableaux of shape [] and of weight () """ - if self._inner_shape==Core([],self.k+1): + if self._inner_shape == Core([],self.k+1): s = "Set of strong %s-tableaux" % self.k - s +=" of shape %s" % self._outer_shape + s += " of shape %s" % self._outer_shape else: s = "Set of strong %s-tableaux" % self.k - s +=" of shape [%s, %s]" % (self._outer_shape, self._inner_shape) - s +="%sand of weight %s" % (" ",self._weight) + s += " of shape [%s, %s]" % (self._outer_shape, self._inner_shape) + s += "%sand of weight %s" % (" ",self._weight) return s options = Tableaux.options @@ -4099,7 +4099,7 @@ def __iter__(self): [[]] """ size = sum(self._weight) - if size==0: + if size == 0: yield self([[None]*(row) for row in self._inner_shape]) else: for unT in StrongTableaux.standard_unmarked_iterator( self.k, size, self._outer_shape, self._inner_shape ): @@ -4153,7 +4153,7 @@ def standard_unmarked_iterator( cls, k, size, outer_shape=None, inner_shape=[] ) sage: list(StrongTableaux.standard_unmarked_iterator(4,0, outer_shape=[])) [[]] """ - if size==0: + if size == 0: if outer_shape is None or Core(outer_shape,k+1).contains(inner_shape): yield [[None]*(inner_shape[i]) for i in range(len(inner_shape))] else: @@ -4216,7 +4216,7 @@ def marked_given_unmarked_and_weight_iterator(cls, unmarkedT, k, weight): import itertools dsc = Composition(weight).descents() for m in itertools.product(*[td[key] for key in sorted(td)]): - if all(((m[i][1]-m[i][0]=len(Tlist): + while c[0] >= len(Tlist): Tlist.append([]) Tlist[c[0]].append( v ) - if len(Tlist[c[0]])-c[0]==tij[1]: + if len(Tlist[c[0]])-c[0] == tij[1]: Tlist[c[0]][-1] = -Tlist[c[0]][-1] #mark the cell that is on the j-1 diagonal return Tlist else: - raise ValueError("%s is not a single step up in the strong lattice"%tij) + raise ValueError("%s is not a single step up in the strong lattice" % tij) @classmethod def follows_tableau_unsigned_standard( cls, Tlist, k ): @@ -4514,7 +4514,7 @@ def marked_CST_to_transposition_sequence(self, T, k): LL = list(T) if not LL or all(v is None for v in sum(LL,[])): return [] - marks = [v for row in T for v in row if v is not None and v<0] + [0] + marks = [v for row in T for v in row if v is not None and v < 0] + [0] m = -min(marks) # the largest marked cell transeq = [] # start with the empty list and append on the right sh = Core([len(r) for r in T], k + 1) diff --git a/src/sage/combinat/multiset_partition_into_sets_ordered.py b/src/sage/combinat/multiset_partition_into_sets_ordered.py index 7775f33ad93..6f0b07de541 100755 --- a/src/sage/combinat/multiset_partition_into_sets_ordered.py +++ b/src/sage/combinat/multiset_partition_into_sets_ordered.py @@ -803,7 +803,7 @@ def fatten(self, grouping): str_rep = '[' for i in range(len(grouping)): st = ",".join(str(k) for k in result[i]) - str_rep += "{" + st+ "}" + str_rep += "{" + st + "}" str_rep = str_rep.replace("}{", "}, {") + "]" raise ValueError("%s is not a valid ordered multiset partition into sets" % (str_rep)) else: @@ -1554,7 +1554,7 @@ def __init__(self, is_finite=None, **constraints): constraints.pop("max_order", None) min_ord = constraints.get("min_order", 0) max_ord = constraints.get("max_order", infinity) - assert min_ord <= max_ord, "min_order=%s <= max_order=%s"%(min_ord, max_ord) + assert min_ord <= max_ord, "min_order=%s <= max_order=%s" % (min_ord, max_ord) if min_ord == max_ord: constraints["order"] = constraints.pop("min_order", constraints.pop("max_order")) @@ -2226,7 +2226,7 @@ def _repr_(self): 'Ordered Multiset Partitions into Sets of multiset {{1, 1, 4}}' """ ms_rep = "{{" + ", ".join(map(str, self._Xtup)) + "}}" - return "Ordered Multiset Partitions into Sets" + " of multiset %s"%ms_rep + return "Ordered Multiset Partitions into Sets" + " of multiset %s" % ms_rep def __contains__(self, x): """ @@ -2396,7 +2396,7 @@ def _repr_(self): cdict = dict(self.constraints) cdict.pop("weight", None) ms_rep = "{{" + ", ".join(map(str, self._Xtup)) + "}}" - base_repr = "Ordered Multiset Partitions into Sets" + " of multiset %s"%ms_rep + base_repr = "Ordered Multiset Partitions into Sets" + " of multiset %s" % ms_rep return base_repr + self._constraint_repr_(cdict) ############### @@ -2441,7 +2441,7 @@ def _repr_(self): 'Ordered Multiset Partitions into Sets of order 2 over alphabet {1, 3}' """ A_rep = "Ordered Multiset Partitions into Sets of order " + str(self._order) - A_rep += " over alphabet {%s}"%(", ".join(map(str, sorted(self._alphabet)))) + A_rep += " over alphabet {%s}" % (", ".join(map(str, sorted(self._alphabet)))) return A_rep def _an_element_(self): @@ -2583,7 +2583,7 @@ def _repr_(self): cdict.pop("alphabet", None) cdict.pop("order", None) base_repr = "Ordered Multiset Partitions into Sets of order " + str(self._order) - base_repr += " over alphabet {%s}"%(", ".join(map(str, sorted(self._alphabet)))) + base_repr += " over alphabet {%s}" % (", ".join(map(str, sorted(self._alphabet)))) return base_repr + self._constraint_repr_(cdict) ############### @@ -3236,9 +3236,9 @@ def __init__(self, n, ell, k): self.ell = ell self.k = k if not all([n in ZZ, ell in ZZ, k in ZZ]): - raise TypeError("n (=%s), ell (=%s), and k (=%s) must all be positive integers"%(n, ell, k)) + raise TypeError("n (=%s), ell (=%s), and k (=%s) must all be positive integers" % (n, ell, k)) if not all([n > 0, ell >= k, k > 0]): - raise ValueError("n (=%s), ell (=%s), and k (=%s) must all be positive integers"%(n, ell, k)) + raise ValueError("n (=%s), ell (=%s), and k (=%s) must all be positive integers" % (n, ell, k)) self._cartan_type = CartanType(['A',n-1]) B = Letters(['A', n-1]) T = tensor([B]*ell) @@ -3316,7 +3316,7 @@ def _element_constructor_(self, x): B,T = self._BT return self.element_class(self, (T(*[B(a) for a in _concatenate(t)]), breaks)) else: - raise ValueError("cannot convert %s into an element of %s"%(x, self)) + raise ValueError("cannot convert %s into an element of %s" % (x, self)) def __contains__(self, x): """ diff --git a/src/sage/combinat/partition.py b/src/sage/combinat/partition.py index 742f9a93917..3c5535c88c1 100644 --- a/src/sage/combinat/partition.py +++ b/src/sage/combinat/partition.py @@ -714,7 +714,7 @@ def _repr_exp_low(self): if not self._list: return '-' exp = self.to_exp() - return '%s' % ', '.join('%s%s' % (m+1, '' if e==1 else '^%s'%e) + return '%s' % ', '.join('%s%s' % (m+1, '' if e == 1 else '^%s' % e) for (m,e) in enumerate(exp) if e > 0) def _repr_exp_high(self): @@ -752,7 +752,7 @@ def _repr_compact_low(self): if not self._list: return '-' exp = self.to_exp() - return '%s' % ','.join('%s%s' % (m+1, '' if e==1 else '^%s'%e) + return '%s' % ','.join('%s%s' % (m+1, '' if e == 1 else '^%s' % e) for (m,e) in enumerate(exp) if e > 0) def _repr_compact_high(self): @@ -770,9 +770,9 @@ def _repr_compact_high(self): if not self._list: return '-' exp = self.to_exp()[::-1] # reversed list of exponents - M=max(self) - return '%s' % ','.join('%s%s' % (M-m, '' if e==1 else '^%s'%e) - for (m,e) in enumerate(exp) if e>0) + M = max(self) + return '%s' % ','.join('%s%s' % (M-m, '' if e == 1 else '^%s' % e) + for (m,e) in enumerate(exp) if e > 0) def _repr_diagram(self): r""" @@ -946,7 +946,7 @@ def _latex_exp_low(self): if not self._list: return "{\\emptyset}" exp = self.to_exp() - return '%s' % ','.join('%s%s' % (m+1, '' if e==1 else '^{%s}'%e) + return '%s' % ','.join('%s%s' % (m+1, '' if e == 1 else '^{%s}' % e) for (m,e) in enumerate(exp) if e > 0) def _latex_exp_high(self): @@ -964,8 +964,8 @@ def _latex_exp_high(self): return "{\\emptyset}" exp = self.to_exp()[::-1] # reversed list of exponents M = max(self) - return '%s' % ','.join('%s%s' % (M-m, '' if e==1 else '^{%s}'%e) - for (m,e) in enumerate(exp) if e>0) + return '%s' % ','.join('%s%s' % (M-m, '' if e == 1 else '^{%s}' % e) + for (m,e) in enumerate(exp) if e > 0) def ferrers_diagram(self): r""" @@ -2068,11 +2068,11 @@ def frobenius_coordinates(self): mu = self muconj = mu.conjugate() # Naive implementation if len(mu) <= len(muconj): - a = [x for x in (val-i-1 for i, val in enumerate(mu)) if x>=0] - b = [x for x in (muconj[i]-i-1 for i in range(len(a))) if x>=0] + a = [x for x in (val-i-1 for i, val in enumerate(mu)) if x >= 0] + b = [x for x in (muconj[i]-i-1 for i in range(len(a))) if x >= 0] else: - b = [x for x in (val-i-1 for i, val in enumerate(muconj)) if x>=0] - a = [x for x in (mu[i]-i-1 for i in range(len(b))) if x>=0] + b = [x for x in (val-i-1 for i, val in enumerate(muconj)) if x >= 0] + a = [x for x in (mu[i]-i-1 for i in range(len(b))) if x >= 0] return (a,b) def frobenius_rank(self): @@ -2742,11 +2742,11 @@ def garnir_tableau(self, *cell): if row + 1 >= len(self) or col >= self[row+1]: raise ValueError('(row+1, col) must be inside the diagram') - g=self.initial_tableau().to_list() - a=g[row][col] + g = self.initial_tableau().to_list() + a = g[row][col] g[row][col:] = list(range(a+col+1,g[row+1][col]+1)) g[row+1][:col+1] = list(range(a,a+col+1)) - g=tableau.Tableau(g) + g = tableau.Tableau(g) g._garnir_cell = (row, col) return g @@ -2808,26 +2808,26 @@ def top_garnir_tableau(self,e,cell): - [KMR2012]_ """ - (row,col)=cell - if row+1>=len(self) or col>=self[row+1]: - raise ValueError('(%s,%s)=(row+1,col) must be inside the diagram' %(row+1,col)) + (row,col) = cell + if row+1 >= len(self) or col >= self[row+1]: + raise ValueError('(%s,%s)=(row+1,col) must be inside the diagram' % (row+1,col)) - g=self.garnir_tableau(cell) # start with the Garnir tableau and modify + g = self.garnir_tableau(cell) # start with the Garnir tableau and modify - if e==0: + if e == 0: return g # no more dominant tableau of the same residue - a=e*int((self[row]-col)/e) # number of cells in the e-bricks in row `row` - b=e*int((col+1)/e) # number of cells in the e-bricks in row `row+1` + a = e*int((self[row]-col)/e) # number of cells in the e-bricks in row `row` + b = e*int((col+1)/e) # number of cells in the e-bricks in row `row+1` - if a==0 or b==0: + if a == 0 or b == 0: return g - t=g.to_list() - m=g[row+1][0] # smallest number in 0-Garnir belt + t = g.to_list() + m = g[row+1][0] # smallest number in 0-Garnir belt # now we will put the number m,m+1,...,t[row+1][col] in order into t - t[row][col:a+col]=[m+col-b+1+i for i in range(a)] - t[row+1][col-b+1:col+1]=[m+a+col-b+1+i for i in range(b)] + t[row][col:a+col] = [m+col-b+1+i for i in range(a)] + t[row+1][col-b+1:col+1] = [m+a+col-b+1+i for i in range(b)] return tableau.StandardTableau(t) @cached_method @@ -2855,11 +2855,11 @@ def young_subgroup(self): sage: Partition([4,2]).young_subgroup() # optional - sage.groups Permutation Group with generators [(), (5,6), (3,4), (2,3), (1,2)] """ - gens=[] - m=0 + gens = [] + m = 0 for row in self: gens.extend([ (c,c+1) for c in range(m+1,m+row)]) - m+=row + m += row gens.append(list(range(1,self.size() + 1))) # to ensure we get a subgroup of Sym_n return PermutationGroup( gens ) @@ -4604,9 +4604,9 @@ def from_kbounded_to_reduced_word(self, k): result = [] while not p.is_empty(): corners = p.corners() - c = p.content(corners[0][0],corners[0][1])%(k+1) + c = p.content(corners[0][0],corners[0][1]) % (k+1) result.append(Integer(c)) - list = [x for x in corners if p.content(x[0],x[1])%(k+1) ==c] + list = [x for x in corners if p.content(x[0],x[1]) % (k+1) == c] for x in list: p = p.remove_cell(x[0]) return result @@ -5333,7 +5333,7 @@ def outline(self, variable=None): outside_contents = [self.content(*c) for c in self.outside_corners()] inside_contents = [self.content(*c) for c in self.corners()] return sum(abs(variable+c) for c in outside_contents)\ - -sum(abs(variable+c) for c in inside_contents) + - sum(abs(variable+c) for c in inside_contents) def dual_equivalence_graph(self, directed=False, coloring=None): r""" @@ -5873,7 +5873,7 @@ def __classcall_private__(cls, n=None, **kwargs): ('parts_in' in kwargs or 'starting' in kwargs or 'ending' in kwargs)): - raise ValueError("the parameters 'parts_in', 'starting' and "+ + raise ValueError("the parameters 'parts_in', 'starting' and " + "'ending' cannot be combined with anything else") if 'parts_in' in kwargs: @@ -5888,7 +5888,7 @@ def __classcall_private__(cls, n=None, **kwargs): return RestrictedPartitions_n(n, kwargs['restricted']) # FIXME: should inherit from IntegerListLex, and implement repr, or _name as a lazy attribute - kwargs['name'] = "Partitions of the integer %s satisfying constraints %s"%(n, ", ".join( ["%s=%s"%(key, kwargs[key]) for key in sorted(kwargs)] )) + kwargs['name'] = "Partitions of the integer %s satisfying constraints %s" % (n, ", ".join( ["%s=%s" % (key, kwargs[key]) for key in sorted(kwargs)] )) # min_part is at least 1, and it is 1 by default kwargs['min_part'] = max(1, kwargs.get('min_part', 1)) @@ -6329,7 +6329,7 @@ def from_beta_numbers(self, beta): beta.sort() # put them into increasing order just in case offset = 0 while offset < len(beta)-1 and beta[offset] == offset: - offset+=1 + offset += 1 beta = beta[offset:] mu = [beta[i]-offset-i for i in range(len(beta))] return self.element_class(self, list(reversed(mu))) @@ -6432,7 +6432,7 @@ def from_core_and_quotient(self, core, quotient): """ from .partition_tuple import PartitionTuple, PartitionTuples if quotient not in PartitionTuples(): - raise ValueError('the quotient %s must be a tuple of partitions'%quotient) + raise ValueError('the quotient %s must be a tuple of partitions' % quotient) components = PartitionTuple(quotient).components() length = len(components) k = length*max(len(q) for q in components) + len(core) @@ -6762,7 +6762,7 @@ def random_element_uniform(self): rand -= d * cached_number_of_partitions(r) if rand < 0: break - d +=1 + d += 1 r -= j else: continue @@ -7754,7 +7754,7 @@ def list(self): new_list += add(element) l = new_list - return [self.element_class(self, [x for x in p if x!=0]) for p in l] + return [self.element_class(self, [x for x in p if x != 0]) for p in l] def cardinality(self): """ diff --git a/src/sage/combinat/partition_kleshchev.py b/src/sage/combinat/partition_kleshchev.py index 18db4ff3424..06781aa96ed 100644 --- a/src/sage/combinat/partition_kleshchev.py +++ b/src/sage/combinat/partition_kleshchev.py @@ -1286,11 +1286,11 @@ def _element_constructor_(self, mu): return mu if KPmu._level != self._level or KPmu._e != self._e: - raise ValueError('%s is not an element of %s'%(mu, self)) + raise ValueError('%s is not an element of %s' % (mu, self)) if KPmu._convention[1] != self._convention[1]: mu = [nu.conjugate() for nu in mu] - if self._level>1 and KPmu._convention[0] == self._convention[0]: + if self._level > 1 and KPmu._convention[0] == self._convention[0]: mu = mu[::-1] return super()._element_constructor_(mu) @@ -1483,7 +1483,7 @@ def _repr_(self): return 'Kleshchev partitions with e=%s' % (self._e) return 'Kleshchev partitions with e=%s and multicharge=(%s)' % ( - self._e,','.join('%s'%m for m in self._multicharge)) + self._e,','.join('%s' % m for m in self._multicharge)) def __contains__(self, mu): """ @@ -1707,7 +1707,7 @@ def _repr_(self): return 'Kleshchev partitions with e=%s and size %s' % (self._e, self._size) return 'Kleshchev partitions with e=%s and multicharge=(%s) and size %s' % ( - self._e,','.join('%s'%m for m in self._multicharge), self._size + self._e,','.join('%s' % m for m in self._multicharge), self._size ) def __contains__(self, mu): diff --git a/src/sage/combinat/partition_tuple.py b/src/sage/combinat/partition_tuple.py index 4fbf6b91723..5766027efbc 100644 --- a/src/sage/combinat/partition_tuple.py +++ b/src/sage/combinat/partition_tuple.py @@ -794,9 +794,9 @@ def diagram(self): # There should be a fancier list compression for this but I couldn't get # one to work in the cases where a component was the empty partition diag = [] - diag_str=PartitionTuples.options('diagram_str') + diag_str = PartitionTuples.options('diagram_str') for row in range(row_max): - line='' + line = '' for c in range(len(self)): if row == 0 and self[c] == []: line += ' -' @@ -880,8 +880,8 @@ def up(self): """ for c in range(len(self)): for nu in self[c].up(): - up=[tau for tau in self] - up[c]=nu + up = [tau for tau in self] + up[c] = nu yield PartitionTuple(up) def up_list(self): @@ -914,8 +914,8 @@ def down(self): """ for c in range(len(self)): for nu in self[c].down(): - down=[tau for tau in self] - down[c]=nu + down = [tau for tau in self] + down[c] = nu yield PartitionTuple(down) def down_list(self): @@ -1054,7 +1054,7 @@ def dominates(self, mu): True """ try: - mu=PartitionTuple(mu) + mu = PartitionTuple(mu) except ValueError: raise ValueError('%s must be a PartitionTuple' % mu) @@ -1063,21 +1063,21 @@ def dominates(self, mu): level = 0 ssum = 0 # sum of successive rows in self musum = 0 # sum of successive rows in self - while levelssum: + while level < self.level() and level < mu.level(): + row = 0 + while row < len(self[level]) and row < len(mu[level]): + ssum += self[level][row] + musum += mu[level][row] + if musum > ssum: return False - row+=1 - if rowssum: + row += 1 + if row < len(self[level]): + ssum += sum(self[level][row:]) + elif row < len(mu[level]): + musum += sum(mu[level][row:]) + if musum > ssum: return False - level+=1 + level += 1 return True @cached_method @@ -1177,11 +1177,11 @@ def garnir_tableau(self, *cell): - :meth:`top_garnir_tableau` """ try: - (comp, row,col)=cell + (comp, row,col) = cell except ValueError: - (comp, row,col)=cell[0] + (comp, row,col) = cell[0] - if comp>=len(self) or row+1>=len(self[comp]) or col>=self[comp][row+1]: + if comp >= len(self) or row+1 >= len(self[comp]) or col >= self[comp][row+1]: raise ValueError('(comp, row+1, col) must be inside the diagram') g = self.initial_tableau().to_list() a = g[comp][row][col] @@ -1246,26 +1246,26 @@ def top_garnir_tableau(self,e,cell): - :meth:`~sage.combinat.partition.Partition_tuple.garnir_tableau` """ - (comp,row,col)=cell - if comp>=len(self) or row+1>=len(self[comp]) or col>=self[comp][row+1]: + (comp,row,col) = cell + if comp >= len(self) or row+1 >= len(self[comp]) or col >= self[comp][row+1]: raise ValueError('(comp, row+1, col) must be inside the diagram') - g=self.garnir_tableau(cell) + g = self.garnir_tableau(cell) - if e==0: + if e == 0: return # no more dominant tableau of the same residue - a=e*int((self[comp][row]-col)/e) # number of cells in the e-bricks in row `row` - b=e*int((col+1)/e) # number of cells in the e-bricks in row `row+1` + a = e*int((self[comp][row]-col)/e) # number of cells in the e-bricks in row `row` + b = e*int((col+1)/e) # number of cells in the e-bricks in row `row+1` - if a==0 or b==0: + if a == 0 or b == 0: return self.garnir_tableau(cell) - t=g.to_list() - m=t[comp][row+1][0] # smallest number of 0-Garnir belt + t = g.to_list() + m = t[comp][row+1][0] # smallest number of 0-Garnir belt # now we will put the number m,m+1,...,t[row+1][col] in order into t - t[comp][row][col:a+col]=[m+col-b+1+i for i in range(a)] - t[comp][row+1][col-b+1:col+1]=[m+a+col-b+1+i for i in range(b)] + t[comp][row][col:a+col] = [m+col-b+1+i for i in range(a)] + t[comp][row+1][col-b+1:col+1] = [m+a+col-b+1+i for i in range(b)] from .tableau_tuple import StandardTableauTuple return StandardTableauTuple(t) @@ -1299,7 +1299,7 @@ def arm_length(self, k,r,c): try: return self[k][r]-(c+1) except IndexError: - raise ValueError("The cell %s is not in the diagram" %((k,r,c),)) + raise ValueError("The cell %s is not in the diagram" % ((k,r,c),)) def leg_length(self, k,r,c): """ @@ -1346,7 +1346,7 @@ def contains(self, mu): sage: PartitionTuple([[1,1],[2],[2,1]]).contains( PartitionTuple([[1,1],[2],[2,1]]) ) True """ - return mu.level()<=self.level() and all(self[c].contains(mu[c]) for c in range(len(mu))) + return mu.level() <= self.level() and all(self[c].contains(mu[c]) for c in range(len(mu))) def hook_length(self, k,r,c): r""" @@ -1597,7 +1597,7 @@ def degree(self, e): for some integer `N`. Compare with :meth:`prime_degree`. """ - multicharge=tuple([i*self.size() for i in range(self.size())]) + multicharge = tuple([i*self.size() for i in range(self.size())]) return sum(t.degree(e, multicharge) for t in self.standard_tableaux()) def prime_degree(self, p): @@ -1648,7 +1648,7 @@ def prime_degree(self, p): while ps[-1]*p < self.size(): ps.append(ps[-1] * p) - multicharge=tuple([i*self.size() for i in range(self.size())]) + multicharge = tuple([i*self.size() for i in range(self.size())]) return sum(t.degree(pk, multicharge) for pk in ps for t in self.standard_tableaux()) @cached_method @@ -2005,23 +2005,23 @@ def __getitem__(self, r): if isinstance(r,(int,Integer)): return self.unrank(r) elif isinstance(r,slice): - start=0 if r.start is None else r.start - stop=r.stop + start = 0 if r.start is None else r.start + stop = r.stop if stop is None and not self.is_finite(): raise ValueError('infinite set') else: raise ValueError('r must be an integer or a slice') - count=0 - parts=[] + count = 0 + parts = [] for t in self: - if count==stop: + if count == stop: break - if count>=start: + if count >= start: parts.append(t) - count+=1 + count += 1 # this is to cope with empty slice endpoints like [6:] or [:] - if count==stop or stop is None: + if count == stop or stop is None: return parts raise IndexError('value out of range') @@ -2449,10 +2449,10 @@ def _an_element_(self): mu = [[] for _ in itertools.repeat(None, self._level)] if self._size > 0: if self._level == 1: - mu=[self._size-1,1] + mu = [self._size-1,1] else: - mu[0]=[1] - mu[-1]=[self._size-1] + mu[0] = [1] + mu[-1] = [self._size-1] return self.element_class(self, mu) def cardinality(self): @@ -2501,9 +2501,9 @@ def __setstate__(self, state): Partition tuples of level 7 and size 3 """ if isinstance(state, dict): # for old pickles from Tableau_class - parts=PartitionTuples(state['k'], state['n']) - self.__class__=parts.__class__ - self.__dict__=parts.__dict__ + parts = PartitionTuples(state['k'], state['n']) + self.__class__ = parts.__class__ + self.__dict__ = parts.__dict__ else: super().__setstate__(state) diff --git a/src/sage/combinat/permutation.py b/src/sage/combinat/permutation.py index 459364f6121..5cf89374de9 100644 --- a/src/sage/combinat/permutation.py +++ b/src/sage/combinat/permutation.py @@ -487,7 +487,7 @@ def __classcall_private__(cls, l, check=True): elif len(l) <= 1: return Permutations()([]) else: - raise ValueError("cannot convert l (= %s) to a Permutation"%l) + raise ValueError("cannot convert l (= %s) to a Permutation" % l) # otherwise, it gets processed by CombinatorialElement's __init__. return Permutations()(l, check=check) @@ -548,10 +548,10 @@ def __init__(self, parent, l, check=True): # Is the maximum element of the permutation the length of input, # or is some integer missing ? if int(lst[-1]) != len(lst): - raise ValueError("The permutation has length "+str(len(lst))+ - " but its maximal element is "+ - str(int(lst[-1]))+". Some element "+ - "may be repeated, or an element is missing"+ + raise ValueError("The permutation has length "+str(len(lst)) + + " but its maximal element is " + + str(int(lst[-1]))+". Some element " + + "may be repeated, or an element is missing" + ", but there is something wrong with its length.") # Do the elements appear only once ? @@ -1517,8 +1517,8 @@ def _to_inversion_vector_orig(self): iv = [0]*len(p) for i in range(len(p)): for pj in p: - if pj>i+1: - iv[i]+=1 + if pj > i+1: + iv[i] += 1 elif pj == i+1: break return iv @@ -1631,7 +1631,7 @@ def inversions(self) -> list: p = self[:] n = len(p) return [tuple([i+1,j+1]) for i in range(n-1) for j in range(i+1,n) - if p[i]>p[j]] + if p[i] > p[j]] def stack_sort(self) -> Permutation: """ @@ -1756,7 +1756,7 @@ def show(self, representation="cycles", orientation="landscape", **args): elif orientation == "portrait": r = lambda x,y : (-y,x) else: - raise ValueError("The value of 'orientation' must be either "+ + raise ValueError("The value of 'orientation' must be either " + "'landscape' or 'portrait'.") p = self[:] @@ -1769,7 +1769,7 @@ def show(self, representation="cycles", orientation="landscape", **args): return L.show(axes=False, **args) else: - raise ValueError("The value of 'representation' must be equal to "+ + raise ValueError("The value of 'representation' must be equal to " + "'cycles', 'chord-diagram' or 'braid'") def number_of_inversions(self) -> Integer: @@ -2086,7 +2086,7 @@ def iswitch(self, i): [1, 2, 3] """ if i not in range(2, len(self)): - raise ValueError("i (= %s) must between 2 and n-1"%i) + raise ValueError("i (= %s) must between 2 and n-1" % i) state = self._icondition(i) if state[0] is None: @@ -2833,7 +2833,7 @@ def to_lehmer_code(self) -> list: """ l = len(self._list) # choose the best implementations - if l<577: + if l < 577: return self._to_lehmer_code_small() else: return self.inverse().to_inversion_vector() @@ -5600,7 +5600,7 @@ def __classcall_private__(cls, n=None, k=None, **kwargs): #Make sure that exactly one keyword was passed for key in kwargs: if key not in valid_args: - raise ValueError("unknown keyword argument: %s"%key) + raise ValueError("unknown keyword argument: %s" % key) if key not in [ 'avoiding' ]: number_of_arguments += 1 @@ -5649,7 +5649,7 @@ def __classcall_private__(cls, n=None, k=None, **kwargs): a = tuple(map(Permutation, a)) return StandardPermutations_avoiding_generic(n, a) else: - raise ValueError("do not know how to avoid %s"%a) + raise ValueError("do not know how to avoid %s" % a) else: return StandardPermutations_n(n) else: @@ -6004,7 +6004,7 @@ def _repr_(self) -> str: sage: Permutations(['c','a','c']) Permutations of the multi-set ['c', 'a', 'c'] """ - return "Permutations of the multi-set %s"%list(self.mset) + return "Permutations of the multi-set %s" % list(self.mset) def __iter__(self): r""" @@ -6344,7 +6344,7 @@ def _repr_(self) -> str: sage: Permutations(['c','a','t']) Permutations of the set ['c', 'a', 't'] """ - return "Permutations of the set %s"%list(self._set) + return "Permutations of the set %s" % list(self._set) class Element(ClonableArray): """ @@ -7574,7 +7574,7 @@ def from_permutation_group_element(pge, parent=None): [2, 1, 4, 3] """ if not isinstance(pge, PermutationGroupElement): - raise TypeError("pge (= %s) must be a PermutationGroupElement"%pge) + raise TypeError("pge (= %s) must be a PermutationGroupElement" % pge) if parent is None: parent = Permutations( len(pge.domain()) ) @@ -8827,7 +8827,7 @@ def _repr_(self): sage: CyclicPermutations(range(4)) Cyclic permutations of [0, 1, 2, 3] """ - return "Cyclic permutations of %s"%list(self.mset) + return "Cyclic permutations of %s" % list(self.mset) def __iter__(self, distinct=False): """ diff --git a/src/sage/combinat/tableau.py b/src/sage/combinat/tableau.py index cdfaf7a2b5b..cd3c902e1c9 100644 --- a/src/sage/combinat/tableau.py +++ b/src/sage/combinat/tableau.py @@ -6475,7 +6475,7 @@ def __contains__(self, x): sage: 1 in SST False """ - return SemistandardTableaux.__contains__(self, x) and [len(_) for _ in x]==self.shape + return SemistandardTableaux.__contains__(self, x) and [len(_) for _ in x] == self.shape def _repr_(self): """ @@ -6587,7 +6587,7 @@ def __contains__(self, x): sage: 1 in SST False """ - if self.size==0: + if self.size == 0: return x == [] return (SemistandardTableaux.__contains__(self, x) diff --git a/src/sage/combinat/tableau_tuple.py b/src/sage/combinat/tableau_tuple.py index fb99c185e8e..889f5ee9bc4 100644 --- a/src/sage/combinat/tableau_tuple.py +++ b/src/sage/combinat/tableau_tuple.py @@ -4126,12 +4126,12 @@ def __classcall_private__(cls, *args, **kwargs): raise ValueError('the shape must be a partition tuple') if level is None: - level=shape.level() - elif level!=shape.level(): + level = shape.level() + elif level != shape.level(): raise ValueError('the shape and level must agree') if size is None: - size=shape.size() - elif size!=shape.size(): + size = shape.size() + elif size != shape.size(): raise ValueError('the shape and size must agree') # now that the inputs appear to make sense, return the appropriate class @@ -4235,8 +4235,8 @@ def __contains__(self, t): if all(s in Tableaux() for s in t): flatt = sorted(sum((list(row) for s in t for row in s), [])) return flatt == list(range(1, len(flatt)+1)) and all(len(x) == 0 or - (all(row[i] c)) for x in t) else: return t in StandardTableaux() diff --git a/src/sage/combinat/vector_partition.py b/src/sage/combinat/vector_partition.py index b9a6882d207..2bd89dbb244 100644 --- a/src/sage/combinat/vector_partition.py +++ b/src/sage/combinat/vector_partition.py @@ -52,11 +52,11 @@ def find_min(vect): [0, 1, 0] """ i = len(vect) - while vect[i-1]==0 and i>0: - i=i-1 + while vect[i-1] == 0 and i > 0: + i = i-1 min = [0]*len(vect) - if i>0: - min[i-1]=1 + if i > 0: + min[i-1] = 1 return min @@ -315,7 +315,7 @@ def __iter__(self): for part in self._parts: # choose the first part if tuple(part) == self._vec: yield self.element_class(self, [list(part)]) - elif any(part[i]>self._vec[i] for i in range(len(self._vec))): + elif any(part[i] > self._vec[i] for i in range(len(self._vec))): pass else:# recursively find all possibilities for the rest of the vector partition new_vec = tuple(self._vec[i]-part[i] for i in range(len(self._vec))) diff --git a/src/sage/knots/knotinfo.py b/src/sage/knots/knotinfo.py index 6adbe4df4b2..0e1e45d2cbe 100644 --- a/src/sage/knots/knotinfo.py +++ b/src/sage/knots/knotinfo.py @@ -1488,15 +1488,15 @@ def jones_polynomial(self, variab=None, skein_normalization=False, puiseux=False if skein_normalization: if not variab: - variab='A' + variab = 'A' from sage.rings.polynomial.laurent_polynomial_ring import LaurentPolynomialRing R = LaurentPolynomialRing(ZZ, variab) else: if not variab: if use_sqrt or self.is_knot() or puiseux: - variab='t' + variab = 't' else: - variab='x' + variab = 'x' if puiseux: from sage.rings.puiseux_series_ring import PuiseuxSeriesRing # since PuiseuxPolynomial is not available, so far R = PuiseuxSeriesRing(ZZ, variab) @@ -2008,7 +2008,7 @@ def link(self, use_item=db.columns().pd_notation, snappy=False): s^-5 """ if not isinstance(use_item, KnotInfoColumns): - raise TypeError('%s must be an instance of %s' %(use_item, KnotInfoColumns)) + raise TypeError('%s must be an instance of %s' % (use_item, KnotInfoColumns)) if snappy: try: @@ -2036,7 +2036,7 @@ def link(self, use_item=db.columns().pd_notation, snappy=False): elif use_item == self.items.gauss_notation: return Knots().from_gauss_code(self.gauss_notation()) - raise ValueError('Link construction using %s not possible' %use_item) + raise ValueError('Link construction using %s not possible' % use_item) @cached_method def is_unique(self): @@ -2496,9 +2496,9 @@ def __repr__(self): 'Series of knots K6' """ if self._is_knot: - return 'Series of knots %s' %(self._name()) + return 'Series of knots %s' % (self._name()) else: - return 'Series of links %s' %(self._name()) + return 'Series of links %s' % (self._name()) def __getitem__(self, item): r""" @@ -2587,13 +2587,13 @@ def _name(self): if is_knot: if cross_nr > 10: - res = 'K%s%s' %(cross_nr, alt) + res = 'K%s%s' % (cross_nr, alt) else: - res = 'K%s' %(cross_nr) + res = 'K%s' % (cross_nr) elif n_unori: - res = '%s' %(n_unori) + res = '%s' % (n_unori) else: - res = 'L%s%s' %(cross_nr, alt) + res = 'L%s%s' % (cross_nr, alt) return res def is_recoverable(self, unique=True, max_samples=8): diff --git a/src/sage/knots/link.py b/src/sage/knots/link.py index a832f695eb1..a5ecdb5490c 100644 --- a/src/sage/knots/link.py +++ b/src/sage/knots/link.py @@ -726,7 +726,7 @@ def braid(self): C1[C1.index(-a)] = newedge + 1 C2 = newPD[newPD.index(tails[-b])] C2[C2.index(-b)] = newedge + 2 - newPD.append([newedge + 2, newedge +1, newedge + 3, newedge]) # D + newPD.append([newedge + 2, newedge + 1, newedge + 3, newedge]) # D newPD.append([newedge + 3, -a, -b, newedge]) # E self._braid = Link(newPD).braid() return self._braid @@ -2054,7 +2054,7 @@ def khovanov_polynomial(self, var1='q', var2='t', base_ring=ZZ): gens = [g for g in H.gens() if g.order() == infinity or ch.divides(g.order())] l = len(gens) if l: - coeff[(h,d)]=l + coeff[(h,d)] = l return L(coeff) def determinant(self): @@ -4051,7 +4051,7 @@ def answer(L): achp = L.is_amphicheiral(positive=True) if ach is None and achp is None: if unique: - raise NotImplementedError('this link cannot be uniquely determined (unknown chirality)%s' %non_unique_hint) + raise NotImplementedError('this link cannot be uniquely determined (unknown chirality)%s' % non_unique_hint) elif L.is_amphicheiral() or L.is_amphicheiral(positive=True): chiral = False @@ -4068,7 +4068,7 @@ def answer(L): # polynomial does not distinguish mirror images (see the above # example ``k11m``). if unique: - raise NotImplementedError('mirror type of this link cannot be uniquely determined%s' %non_unique_hint) + raise NotImplementedError('mirror type of this link cannot be uniquely determined%s' % non_unique_hint) mirrored = '?' elif L in lm: mirrored = True @@ -4117,7 +4117,7 @@ def answer_list(l): if set(list(S)) == set(l): return answer_unori(S) - raise NotImplementedError('this link cannot be uniquely determined%s' %non_unique_hint) + raise NotImplementedError('this link cannot be uniquely determined%s' % non_unique_hint) self_m = self.mirror_image() ls, proved_s = self._knotinfo_matching_list() diff --git a/src/sage/misc/inline_fortran.py b/src/sage/misc/inline_fortran.py index 0ace070510b..5d4fc7831bb 100644 --- a/src/sage/misc/inline_fortran.py +++ b/src/sage/misc/inline_fortran.py @@ -65,8 +65,8 @@ class InlineFortran: def __init__(self, globals=None): # globals=None means: use user globals from REPL self.globs = globals - self.library_paths=[] - self.libraries=[] + self.library_paths = [] + self.libraries = [] self.verbose = False def __repr__(self): diff --git a/src/sage/misc/sageinspect.py b/src/sage/misc/sageinspect.py index 88ac75ea843..708e33d4fb6 100644 --- a/src/sage/misc/sageinspect.py +++ b/src/sage/misc/sageinspect.py @@ -1086,12 +1086,12 @@ def split_string(s, quot): tmp_group, s = _split_syntactical_unit(s) out.append(tmp_group) s = s.strip() - if tmp_group==stop: + if tmp_group == stop: return ''.join(out), s elif s.startswith(stop): out.append(stop) return ''.join(out), s[1:].strip() - raise SyntaxError("Syntactical group starting with %s did not end with %s"%(repr(start),repr(stop))) + raise SyntaxError("Syntactical group starting with %s did not end with %s" % (repr(start),repr(stop))) def _sage_getargspec_from_ast(source): @@ -1263,7 +1263,7 @@ def _sage_getargspec_cython(source): nb_stars = 0 varargs = None keywords = None - while (i> 1 if not padic: bits.reverse() diff --git a/src/sage/quadratic_forms/ternary_qf.py b/src/sage/quadratic_forms/ternary_qf.py index 119e8dfdc24..6a08d00f26c 100644 --- a/src/sage/quadratic_forms/ternary_qf.py +++ b/src/sage/quadratic_forms/ternary_qf.py @@ -153,7 +153,7 @@ def polynomial(self, names='x,y,z'): Multivariate Polynomial Ring in x, y, z over Integer Ring """ (x,y,z) = polygens(ZZ,names) - return self._a * x**2 + self._b* y**2 + self._c * z**2 + self._t * x*y + self._s * x*z + self._r * y*z + return self._a * x**2 + self._b * y**2 + self._c * z**2 + self._t * x*y + self._s * x*z + self._r * y*z def _repr_(self): r""" @@ -172,8 +172,8 @@ def _repr_(self): [0 0 0] """ rep = 'Ternary quadratic form with integer coefficients:\n' - rep+= '[' + str(self._a) + ' ' + str(self._b) + ' ' + str(self._c) + ']\n' - rep+= '[' + str(self._r) + ' ' + str(self._s) + ' ' + str(self._t) + ']' + rep += '[' + str(self._a) + ' ' + str(self._b) + ' ' + str(self._c) + ']\n' + rep += '[' + str(self._r) + ' ' + str(self._s) + ' ' + str(self._t) + ']' return rep def __call__(self, v): @@ -721,7 +721,7 @@ def is_eisenstein_reduced(self) -> bool: sage: Q.is_eisenstein_reduced() False """ - [a,b,c,r,s,t]=[self._a,self._b,self._c,self._r,self._s,self._t] + [a,b,c,r,s,t] = [self._a,self._b,self._c,self._r,self._s,self._t] # cond 2 if not (r > 0 and t > 0 and s > 0): @@ -746,7 +746,7 @@ def is_eisenstein_reduced(self) -> bool: # cond 6 # r, s, t <= 0 - if r<=0: + if r <= 0: if a == -t and s != 0: return False if a == -s and t != 0: @@ -824,17 +824,17 @@ def pseudorandom_primitive_zero_mod_p(self, p): [a,b,c,r,s,t] = self.coefficients() while True: - r1=randint(0,p-1) - r2=randint(0,p-1) - alpha=(b*r1**2+t*r1+a) % p + r1 = randint(0,p-1) + r2 = randint(0,p-1) + alpha = (b*r1**2+t*r1+a) % p if alpha != 0: - beta=(2*b*r1*r2+t*r2+r*r1+s) % p - gamma=(b*r2**2+r*r2+c) % p - disc=beta**2-4*alpha*gamma + beta = (2*b*r1*r2+t*r2+r*r1+s) % p + gamma = (b*r2**2+r*r2+c) % p + disc = beta**2-4*alpha*gamma if mod(disc, p).is_square(): - z=(-beta+mod(disc,p).sqrt().lift())*(2*alpha).inverse_mod(p) + z = (-beta+mod(disc,p).sqrt().lift())*(2*alpha).inverse_mod(p) # return vector((z,r1*z+r2,1))%p return z % p, (r1*z+r2) % p, 1 @@ -858,7 +858,7 @@ def find_zeros_mod_p(self, p): [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] """ - if p==2: + if p == 2: return _find_zeros_mod_p_2(self._a, self._b, self._c, self._r, self._s, self._t) diff --git a/src/sage/sandpiles/examples.py b/src/sage/sandpiles/examples.py index a902a156318..6507992cc3c 100644 --- a/src/sage/sandpiles/examples.py +++ b/src/sage/sandpiles/examples.py @@ -163,15 +163,15 @@ def Fan(self, n, deg_three_verts=False): True """ f = graphs.WheelGraph(n) - if n>2: + if n > 2: f.delete_edge(1,n-1) if deg_three_verts: f.allow_multiple_edges(True) f.add_edges([(0,1),(0,n-1)]) return Sandpile(f,0) - elif n==1: + elif n == 1: return Sandpile(f,0) - elif n==2: + elif n == 2: if deg_three_verts: return Sandpile({0:{1:3}, 1:{0:3}}) else: diff --git a/src/sage/sandpiles/sandpile.py b/src/sage/sandpiles/sandpile.py index c8e15e06f05..eca2303fc9f 100644 --- a/src/sage/sandpiles/sandpile.py +++ b/src/sage/sandpiles/sandpile.py @@ -2256,14 +2256,14 @@ def markov_chain(self,state, distrib=None): while True: i = X.get_random_element() if V[i] != self.sink(): - st[V[i]]+=1 + st[V[i]] += 1 st = st.stabilize() yield st elif isinstance(st,SandpileDivisor): alive = st.is_alive() while True: i = X.get_random_element() - st[V[i]]+=1 + st[V[i]] += 1 if alive: yield st else: @@ -2965,7 +2965,7 @@ def __init__(self, S, c): c.reverse() config = {} for v in S.vertices(sort=True): - if v!=S.sink(): + if v != S.sink(): config[v] = c.pop() dict.__init__(self,config) else: @@ -3045,22 +3045,22 @@ def __getattr__(self, name): 3 """ if name not in self.__dict__: - if name=='_deg': + if name == '_deg': self._set_deg() return self.__dict__[name] - if name=='_stabilize': + if name == '_stabilize': self._set_stabilize() return self.__dict__[name] - if name=='_equivalent_recurrent': + if name == '_equivalent_recurrent': self._set_equivalent_recurrent() return self.__dict__[name] - if name=='_is_recurrent': + if name == '_is_recurrent': self._set_is_recurrent() return self.__dict__[name] - if name=='_equivalent_superstable': + if name == '_equivalent_superstable': self._set_equivalent_superstable() return self.__dict__[name] - if name=='_is_superstable': + if name == '_is_superstable': self._set_is_superstable() return self.__dict__[name] else: @@ -3323,7 +3323,7 @@ def __lt__(self, other): sage: d < c False """ - return self<=other and self!=other + return self <= other and self != other def __ge__(self, other): r""" @@ -3382,7 +3382,7 @@ def __gt__(self, other): sage: c > d False """ - return self>=other and self!=other + return self >= other and self != other # recurrent power def __pow__(self, k): @@ -3419,7 +3419,7 @@ def __pow__(self, k): if k == 0: return self._sandpile.identity() else: - if k<0: + if k < 0: k = -k for i in range(k): result -= self @@ -3599,7 +3599,7 @@ def unstable(self): [2, 3] """ return [v for v in self._vertices if - self[v]>=self._sandpile.out_degree(v)] + self[v] >= self._sandpile.out_degree(v)] def fire_unstable(self): r""" @@ -3647,7 +3647,7 @@ def _set_stabilize(self): firing_vector[v] += dm[0] for e in s.outgoing_edge_iterator(v): if e[1] != s.sink(): - c[e[1]] += dm[0]* e[2] + c[e[1]] += dm[0] * e[2] unstable = c.unstable() self._stabilize = [c, firing_vector] @@ -3721,7 +3721,7 @@ def support(self): sage: c.support() [1, 2] """ - return [i for i in self if self[i] !=0] + return [i for i in self if self[i] != 0] def add_random(self, distrib=None): r""" @@ -3797,7 +3797,7 @@ def add_random(self, distrib=None): X = GeneralDiscreteDistribution(distrib) V = self._sandpile.vertices(sort=True) i = X.get_random_element() - if i!=self._sandpile._sink_ind: # not the sink + if i != self._sandpile._sink_ind: # not the sink c[V[i]] += 1 return c @@ -4117,7 +4117,7 @@ def burst_size(self, v): - [Lev2014]_ """ - if v==self.sandpile().sink(): + if v == self.sandpile().sink(): return 1 else: w = deepcopy(self) @@ -4367,43 +4367,43 @@ def __getattr__(self, name): 6 """ if name not in self.__dict__: - if name=='_deg': + if name == '_deg': self._set_deg() return self.__dict__[name] - if name=='_q_reduced': + if name == '_q_reduced': self._set_q_reduced() return self.__dict__[name] - if name=='_linear_system': + if name == '_linear_system': self._set_linear_system() return self.__dict__[name] - if name=='_effective_div': + if name == '_effective_div': self._set_effective_div() return self.__dict__[name] - if name=='_polytope': + if name == '_polytope': self._set_polytope() return self.__dict__[name] - if name=='_polytope_integer_pts': + if name == '_polytope_integer_pts': self._set_polytope_integer_pts() return self.__dict__[name] - if name=='_rank': + if name == '_rank': self._set_rank() return self.__dict__[name] - if name=='_rank_witness': + if name == '_rank_witness': self._set_rank(True) return self.__dict__[name] - if name=='_r_of_D': + if name == '_r_of_D': self._set_r_of_D() return self.__dict__[name] - if name=='_Dcomplex': + if name == '_Dcomplex': self._set_Dcomplex() return self.__dict__[name] - if name=='_life': + if name == '_life': self._set_life() return self.__dict__[name] - if name=='_stabilize': + if name == '_stabilize': self._set_stabilize() return self.__dict__[name] - if name=='_weierstrass_pts': + if name == '_weierstrass_pts': self._set_weierstrass_pts() return self.__dict__[name] else: @@ -4869,7 +4869,7 @@ def unstable(self): [1, 2] """ return [v for v in self._vertices if - self[v]>=self._sandpile.out_degree(v)] + self[v] >= self._sandpile.out_degree(v)] def fire_unstable(self): r""" @@ -5120,9 +5120,9 @@ def _set_linear_system(self): lin_sys_mat = lin_sys + '.mat' lin_sys_rel = lin_sys + '.rel' lin_sys_rhs = lin_sys + '.rhs' - lin_sys_sign= lin_sys + '.sign' - lin_sys_zhom= lin_sys + '.zhom' - lin_sys_zinhom= lin_sys + '.zinhom' + lin_sys_sign = lin_sys + '.sign' + lin_sys_zhom = lin_sys + '.zhom' + lin_sys_zinhom = lin_sys + '.zinhom' lin_sys_log = lin_sys + '.log' with open(lin_sys_mat, 'w') as mat_file: @@ -5423,11 +5423,11 @@ def _set_rank(self, set_witness=False): while k >= 0: rk += 1 try: - d = next(i for i,j in enumerate(c) if i==j and i!=0) + d = next(i for i,j in enumerate(c) if i == j and i != 0) except Exception: d = n - 1 k = k - d - if k >=0: + if k >= 0: c[0] = n - 1 - d b1 = [c[i] + n - d for i in range(1,d)] b2 = [c[i] - d for i in range(d,n-1)] @@ -5577,7 +5577,7 @@ def weierstrass_rank_seq(self, v='sink'): [(1, 0, -1), (1, 0, -1), (1, 0, -1), (1, 0, -1), (1, 0, 0, -1)] """ s = self.sandpile() - if v=='sink': + if v == 'sink': v = s.sink() try: seq = self._weierstrass_rank_seq[v] @@ -5585,11 +5585,11 @@ def weierstrass_rank_seq(self, v='sink'): D = deepcopy(self) verts = s.vertices(sort=True) Ei = s.zero_div() - Ei[verts.index(v)]=1 + Ei[verts.index(v)] = 1 Ei = SandpileDivisor(s,Ei) r = D.rank() seq = [r] - while r !=-1: + while r != -1: D = D - Ei r = D.rank() seq.append(r) @@ -5776,7 +5776,7 @@ def support(self): sage: S.vertices(sort=True) [0, 1, 2, 3] """ - return [i for i in self if self[i] !=0] + return [i for i in self if self[i] != 0] def _set_Dcomplex(self): r""" @@ -6001,7 +6001,7 @@ def _set_stabilize(self): firing_vector = self._sandpile.zero_div() E = deepcopy(self) unstable = E.unstable() - while unstable!=[]: + while unstable != []: E = E.fire_unstable() for v in unstable: firing_vector[v] += 1 @@ -6174,23 +6174,23 @@ def triangle_sandpile(n): for i in range(n): for j in range(n-i): T[(i,j)] = {} - if i0: + if i > 0: T[(i,j)][(i-1,j+1)] = 1 T[(i,j)][(i-1,j)] = 1 - if j>0: + if j > 0: T[(i,j)][(i,j-1)] = 1 T[(i,j)][(i+1,j-1)] = 1 d = len(T[(i,j)]) - if d<6: + if d < 6: T[(i,j)][(-1, -1)] = 6-d T = Sandpile(T, (-1, -1)) pos = {} for x in T.nonsink_vertices(): coords = list(x) - coords[0]+=QQ(1)/2*coords[1] + coords[0] += QQ(1)/2*coords[1] pos[x] = coords pos[(-1, -1)] = (-1,-1) T.set_pos(pos) @@ -6368,11 +6368,11 @@ def firing_graph(S, eff): g.add_vertices(range(len(eff))) for i in g.vertices(sort=True): for v in eff[i]: - if eff[i][v]>=S.out_degree(v): + if eff[i][v] >= S.out_degree(v): new_div = deepcopy(eff[i]) new_div[v] -= S.out_degree(v) for oe in S.outgoing_edges(v): - new_div[oe[1]]+=oe[2] + new_div[oe[1]] += oe[2] if new_div in eff: g.add_edge((i,eff.index(new_div))) return g @@ -6406,11 +6406,11 @@ def parallel_firing_graph(S, eff): new_edge = False new_div = deepcopy(eff[i]) for v in eff[i]: - if eff[i][v]>=S.out_degree(v): + if eff[i][v] >= S.out_degree(v): new_edge = True new_div[v] -= S.out_degree(v) for oe in S.outgoing_edges(v): - new_div[oe[1]]+=oe[2] + new_div[oe[1]] += oe[2] if new_edge and (new_div in eff): g.add_edge((i,eff.index(new_div))) return g @@ -6586,16 +6586,16 @@ def wilmes_algorithm(M): U = identity_matrix(ZZ,k).block_sum(smith) L = U*L L[k] = -L[k] - if L[-1][-2]>0: + if L[-1][-2] > 0: L[-1] = -L[-1] for k in range(M.nrows()-2,-1,-1): for i in range(k+2,M.nrows()): - while L[k][i-1]>0: + while L[k][i-1] > 0: L[k] = L[k] + L[i] v = -L[k+1] for i in range(k+2,M.nrows()): v = abs(L[i,i-1])*v + v[i-1]*L[i] - while L[k,k]<=0 or L[k,-1]>0: + while L[k,k] <= 0 or L[k,-1] > 0: L[k] = L[k] + v return L else: diff --git a/src/sage/structure/formal_sum.py b/src/sage/structure/formal_sum.py index 223ef23ce16..7d8d5274144 100644 --- a/src/sage/structure/formal_sum.py +++ b/src/sage/structure/formal_sum.py @@ -140,7 +140,7 @@ def __init__(self, x, parent=None, check=True, reduce=True): try: self._data = [(k(t[0]), t[1]) for t in self._data] except (IndexError, KeyError) as msg: - raise TypeError("%s\nInvalid formal sum"%msg) + raise TypeError("%s\nInvalid formal sum" % msg) def __iter__(self): """ @@ -348,7 +348,7 @@ def _repr_(self): sage: FormalSums(GF(7))._repr_() 'Abelian Group of all Formal Finite Sums over Finite Field of size 7' """ - return "Abelian Group of all Formal Finite Sums over %s"%self.base_ring() + return "Abelian Group of all Formal Finite Sums over %s" % self.base_ring() def _element_constructor_(self, x, check=True, reduce=True): """ diff --git a/src/sage/structure/gens_py.py b/src/sage/structure/gens_py.py index c5a4bca56ec..22555a74c92 100644 --- a/src/sage/structure/gens_py.py +++ b/src/sage/structure/gens_py.py @@ -28,7 +28,7 @@ def multiplicative_iterator(M): stop = [g.multiplicative_order() for g in G] for i in range(len(stop)): if stop[i] is infinity: - raise ArithmeticError("%s is not finite."%M) + raise ArithmeticError("%s is not finite." % M) stop[i] = stop[i] - 1 z = M(1) yield z @@ -55,7 +55,7 @@ def abelian_iterator(M): stop = [g.additive_order() for g in G] for i in range(len(stop)): if stop[i] is infinity: - raise ArithmeticError("%s is not finite."%M) + raise ArithmeticError("%s is not finite." % M) stop[i] = stop[i] - 1 z = M(0) yield z diff --git a/src/sage/structure/sequence.py b/src/sage/structure/sequence.py index 00ee377ac82..0c700c1fb81 100644 --- a/src/sage/structure/sequence.py +++ b/src/sage/structure/sequence.py @@ -500,7 +500,7 @@ def __setitem__(self, n, value): else: y = self.__universe(value) list.__setitem__(self, n, y) - self.__hash=None + self.__hash = None def __getitem__(self, n): """ @@ -888,7 +888,7 @@ def __getattr__(self, name): self.__hash = self._Sequence__hash return self.__hash else: - raise AttributeError("'Sequence_generic' object has no attribute '%s'"%name) + raise AttributeError("'Sequence_generic' object has no attribute '%s'" % name) seq = Sequence From e4e3f36b0d84ceb6168bd147ed2eb1796abe708d Mon Sep 17 00:00:00 2001 From: Miguel Marco Date: Mon, 25 Sep 2023 10:38:15 +0200 Subject: [PATCH 65/93] Address reviewer's comments. --- src/sage/matrix/matrix2.pyx | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/src/sage/matrix/matrix2.pyx b/src/sage/matrix/matrix2.pyx index 5e986ade8fd..949be0f3fa9 100644 --- a/src/sage/matrix/matrix2.pyx +++ b/src/sage/matrix/matrix2.pyx @@ -15978,28 +15978,42 @@ cdef class Matrix(Matrix1): sage: M.elementary_divisors() [1, 1, 4] + This is also true for univariate polynomials over a field:: + + sage: R. = QQ[] + sage: M = matrix(R,[[x^2-2*x+1, x-1,x^2-1],[0,x+1,1]]) + sage: M.fitting_ideal(0) + Principal ideal (0) of Univariate Polynomial Ring in x over Rational Field + sage: M.fitting_ideal(1) + Principal ideal (x - 1) of Univariate Polynomial Ring in x over Rational Field + sage: M.fitting_ideal(2) + Principal ideal (1) of Univariate Polynomial Ring in x over Rational Field + sage: M.smith_form()[0] + [ 1 0 0] + [ 0 x - 1 0] + """ R = self.base_ring() if not R.is_exact(): raise NotImplementedError("Fitting ideals over non-exact rings not implemented at present") n = self.ncols() - rank = n - i - if rank > self.nrows(): + rank_minors = n - i + if rank_minors > self.nrows(): return R.ideal([R.zero()]) - elif rank <= 0: + elif rank_minors <= 0: return R.ideal([R.one()]) - elif rank == 1: + elif rank_minors == 1: return R.ideal(self.coefficients()) if R in _Fields: - if self.rank() >= rank: + if self.rank() >= rank_minors: return R.ideal([1]) else: return R.ideal([0]) try: elemdiv = self.elementary_divisors() - if rank > len(elemdiv): + if rank_minors > len(elemdiv): return R.ideal([0]) - return R.ideal(prod(elemdiv[:rank])) + return R.ideal(prod(elemdiv[:rank_minors])) except (TypeError, NotImplementedError, ArithmeticError): pass for (nr,r) in enumerate(self.rows()): @@ -16017,7 +16031,7 @@ cdef class Matrix(Matrix1): nz = [e for e in enumerate(c) if e[1]] if len(nz) == 0: N = self.delete_columns([nc]) - return N._fitting_ideal(i - 1) + return N.fitting_ideal(i - 1) elif len(nz) == 1: N = self.delete_columns([nc]) F1 = N.fitting_ideal(i-1) @@ -16029,8 +16043,7 @@ cdef class Matrix(Matrix1): return self._fitting_ideal(i) except NotImplementedError: pass - else: - return R.ideal(self.minors(rank)) + return R.ideal(self.minors(rank_minors)) From d11230ad420c93ef061811b73c17d43048cebcb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Mon, 25 Sep 2023 10:53:31 +0200 Subject: [PATCH 66/93] fix the linter once more --- src/sage/coding/all.py | 2 +- src/sage/coding/source_coding/huffman.py | 1 + src/sage/crypto/sbox.pyx | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/sage/coding/all.py b/src/sage/coding/all.py index 89778395ff3..e5ff88308b7 100644 --- a/src/sage/coding/all.py +++ b/src/sage/coding/all.py @@ -2,7 +2,7 @@ from sage.misc.lazy_import import lazy_import as _lazy_import _lazy_import("sage.coding.code_constructions", ["permutation_action", - "walsh_matrix"]) + "walsh_matrix"]) _lazy_import("sage.coding.linear_code", "LinearCode") diff --git a/src/sage/coding/source_coding/huffman.py b/src/sage/coding/source_coding/huffman.py index eb138738f2f..6c08a4d885a 100644 --- a/src/sage/coding/source_coding/huffman.py +++ b/src/sage/coding/source_coding/huffman.py @@ -32,6 +32,7 @@ from sage.structure.sage_object import SageObject + ########################################################################### # # Helper functions diff --git a/src/sage/crypto/sbox.pyx b/src/sage/crypto/sbox.pyx index dfd3bd58a22..b72f13e30a8 100644 --- a/src/sage/crypto/sbox.pyx +++ b/src/sage/crypto/sbox.pyx @@ -649,7 +649,7 @@ cdef class SBox(SageObject): TESTS:: Testing square SBoxes:: - + sage: from sage.crypto.sbox import SBox sage: S = SBox(7,6,0,4,2,5,1,3) sage: S.difference_distribution_table() From 1c6cd5d2c44691bcfe1c152937702db577c04bb0 Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Sat, 23 Sep 2023 16:20:56 -0400 Subject: [PATCH 67/93] src/sage/repl/load.py: replace tmp_dir() Standard tempfile.TemporaryDirectory() replacement. Issue: https://github.com/sagemath/sage/issues/36322 --- src/sage/repl/load.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/sage/repl/load.py b/src/sage/repl/load.py index 64329bfab11..4b82e3d021e 100644 --- a/src/sage/repl/load.py +++ b/src/sage/repl/load.py @@ -177,16 +177,17 @@ def load(filename, globals, attach=False): current working directory, i.e., ``'.'``. But you can modify the path with :func:`load_attach_path`:: + sage: import tempfile sage: sage.repl.attach.reset(); reset_load_attach_path() sage: load_attach_path() ['.'] - sage: t_dir = tmp_dir() - sage: fname = 'test.py' - sage: fullpath = os.path.join(t_dir, fname) - sage: with open(fullpath, 'w') as f: - ....: _ = f.write("print(37 * 3)") - sage: load_attach_path(t_dir, replace=True) - sage: attach(fname) + sage: with tempfile.TemporaryDirectory() as t_dir: + ....: fname = 'test.py' + ....: fullpath = os.path.join(t_dir, fname) + ....: with open(fullpath, 'w') as f: + ....: _ = f.write("print(37 * 3)") + ....: load_attach_path(t_dir, replace=True) + ....: attach(fname) 111 sage: sage.repl.attach.reset(); reset_load_attach_path() # clean up From 7bd6a9fae66a7edd0130a953c40e43c14fd60c50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Mon, 25 Sep 2023 20:14:36 +0200 Subject: [PATCH 68/93] using more itertools.product --- .../multiset_partition_into_sets_ordered.py | 33 +++++++++---------- src/sage/combinat/set_partition_ordered.py | 13 ++++---- src/sage/graphs/path_enumeration.pyx | 8 ++--- src/sage/modules/filtered_vector_space.py | 6 ++-- src/sage/modules/tensor_operations.py | 17 +++------- 5 files changed, 34 insertions(+), 43 deletions(-) diff --git a/src/sage/combinat/multiset_partition_into_sets_ordered.py b/src/sage/combinat/multiset_partition_into_sets_ordered.py index 7775f33ad93..f366014c742 100755 --- a/src/sage/combinat/multiset_partition_into_sets_ordered.py +++ b/src/sage/combinat/multiset_partition_into_sets_ordered.py @@ -52,22 +52,19 @@ ((1,), (1, 2, 3)), ((1, 2), (2, 3)), ((1, 2, 3), (3,))] """ -#***************************************************************************** +# **************************************************************************** # Copyright (C) 2018 Aaron Lauve # # Distributed under the terms of the GNU General Public License (GPL) # as published by the Free Software Foundation; either version 2 of # the License, or (at your option) any later version. -# http://www.gnu.org/licenses/ +# https://www.gnu.org/licenses/ # **************************************************************************** - - from functools import reduce -from itertools import chain +from itertools import chain, product from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets -from sage.categories.cartesian_product import cartesian_product from sage.categories.classical_crystals import ClassicalCrystals from sage.categories.tensor import tensor from sage.structure.unique_representation import UniqueRepresentation @@ -672,7 +669,7 @@ def split_blocks(self, k=2): return {tuple([self]*k): 1} out = {} - for t in cartesian_product([_split_block(block, k) for block in self]): + for t in product(*[_split_block(block, k) for block in self]): tt = tuple([P([l for l in c if l]) for c in zip(*t)]) out[tt] = out.get(tt, 0) + 1 return out @@ -711,8 +708,8 @@ def finer(self, strong=False): if not self: return set([self]) - CP = cartesian_product([_refine_block(block, strong) for block in self]) - return set(P(_concatenate(map(list,c))) for c in CP) + CP = product(*[_refine_block(block, strong) for block in self]) + return set(P(_concatenate(map(list, c))) for c in CP) def is_finer(self, co): """ @@ -2892,16 +2889,16 @@ def _iterator_size(size, length=None, alphabet=None): max_p = max(alphabet) for alpha in IntegerListsLex(size, length=length, min_part=1, max_part=min(size, sum(alphabet))): - for p in cartesian_product([IntegerListsLex(a, min_slope=1, - min_part=min_p, - max_part=min(a, max_p)) - for a in alpha]): + for p in product(*[IntegerListsLex(a, min_slope=1, + min_part=min_p, + max_part=min(a, max_p)) + for a in alpha]): if frozenset(_concatenate(p)).issubset(frozenset(alphabet)): yield tuple(frozenset(k) for k in p) else: for alpha in IntegerListsLex(size, length=length, min_part=1, max_part=size): - for p in cartesian_product([IntegerListsLex(a, min_slope=1, - min_part=1) for a in alpha]): + for p in product(*[IntegerListsLex(a, min_slope=1, + min_part=1) for a in alpha]): yield tuple(frozenset(k) for k in p) @@ -2967,11 +2964,11 @@ def _iterator_order(A, d, lengths=None): yield () else: for alpha in IntegerListsLex(d, length=k, min_part=1, max_part=n): - for co in cartesian_product([Subsets_sk(A, a) for a in alpha]): + for co in product(*[Subsets_sk(A, a) for a in alpha]): yield tuple(frozenset(X) for X in co) -def _descents(w): +def _descents(w) -> list: r""" Return descent positions in the word ``w``. @@ -2983,7 +2980,7 @@ def _descents(w): sage: _descents([]) [] """ - return [j for j in range(len(w)-1) if w[j] > w[j+1]] + return [j for j in range(len(w) - 1) if w[j] > w[j + 1]] def _break_at_descents(alpha, weak=True): diff --git a/src/sage/combinat/set_partition_ordered.py b/src/sage/combinat/set_partition_ordered.py index d5dae5ba617..186835f7129 100644 --- a/src/sage/combinat/set_partition_ordered.py +++ b/src/sage/combinat/set_partition_ordered.py @@ -24,8 +24,9 @@ # # https://www.gnu.org/licenses/ # **************************************************************************** +from itertools import product + from sage.arith.misc import factorial, multinomial -from sage.categories.cartesian_product import cartesian_product from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets from sage.combinat.combinat import stirling_number2 @@ -452,7 +453,7 @@ def finer(self): if not self: return FiniteEnumeratedSet([self]) return FiniteEnumeratedSet([par(sum((list(i) for i in C), [])) - for C in cartesian_product([OrderedSetPartitions(X) for X in self])]) + for C in product(*[OrderedSetPartitions(X) for X in self])]) def is_finer(self, co2): """ @@ -548,7 +549,7 @@ def fatten(self, grouping): result = [None] * len(grouping) j = 0 for i in range(len(grouping)): - result[i] = set().union(*self[j:j+grouping[i]]) + result[i] = set().union(*self[j:j + grouping[i]]) j += grouping[i] return parent(self)(result) @@ -636,7 +637,7 @@ def bottom_up_osp(X, comp): result = [None] * len(comp) j = 0 for i in range(len(comp)): - result[i] = set(xs[j:j+comp[i]]) + result[i] = set(xs[j:j + comp[i]]) j += comp[i] return OrderedSetPartitions(X)(result) @@ -671,7 +672,7 @@ def strongly_finer(self): return FiniteEnumeratedSet([self]) buo = OrderedSetPartition.bottom_up_osp return FiniteEnumeratedSet([par(sum((list(P) for P in C), [])) - for C in cartesian_product([[buo(X, comp) for comp in Compositions(len(X))] for X in self])]) + for C in product(*[[buo(X, comp) for comp in Compositions(len(X))] for X in self])]) def is_strongly_finer(self, co2): r""" @@ -779,7 +780,7 @@ def strongly_fatter(self): # arbitrarily, and then concatenate the results. fattenings = [list(subcomp.fatter()) for subcomp in subcomps] return FiniteEnumeratedSet([OrderedSetPartition(sum([list(gg) for gg in fattening], [])) - for fattening in cartesian_product(fattenings)]) + for fattening in product(*fattenings)]) @combinatorial_map(name='to packed word') def to_packed_word(self): diff --git a/src/sage/graphs/path_enumeration.pyx b/src/sage/graphs/path_enumeration.pyx index 0e5304bcae4..6ef3e79143e 100644 --- a/src/sage/graphs/path_enumeration.pyx +++ b/src/sage/graphs/path_enumeration.pyx @@ -31,8 +31,8 @@ Functions # (at your option) any later version. # https://www.gnu.org/licenses/ # **************************************************************************** +from itertools import product -from sage.categories.cartesian_product import cartesian_product from sage.misc.misc_c import prod from libcpp.queue cimport priority_queue from libcpp.pair cimport pair @@ -263,7 +263,7 @@ def all_paths(G, start, end, use_multiedges=False, report_edges=False, labels=Fa if report_edges and labels: path_with_labels = [] for p in all_paths: - path_with_labels.extend(cartesian_product([edge_labels[e] for e in zip(p[:-1], p[1:])])) + path_with_labels.extend(product(*[edge_labels[e] for e in zip(p[:-1], p[1:])])) return path_with_labels elif use_multiedges and G.has_multiple_edges(): multiple_all_paths = [] @@ -1586,7 +1586,7 @@ def _all_paths_iterator(self, vertex, ending_vertices=None, neighbor in ending_vertices): newpath = path + [neighbor] if report_edges and labels: - for p in cartesian_product([my_dict[e] for e in zip(newpath[:-1], newpath[1:])]): + for p in product(*[my_dict[e] for e in zip(newpath[:-1], newpath[1:])]): yield list(p) elif use_multiedges and self.has_multiple_edges(): m = prod(edge_multiplicity[e] for e in zip(newpath[:-1], newpath[1:])) @@ -1610,7 +1610,7 @@ def _all_paths_iterator(self, vertex, ending_vertices=None, if path[-1] in ending_vertices: # yield good path if report_edges and labels: - for p in cartesian_product([my_dict[e] for e in zip(path[:-1], path[1:])]): + for p in product(*[my_dict[e] for e in zip(path[:-1], path[1:])]): yield list(p) elif use_multiedges and self.has_multiple_edges(): m = prod(edge_multiplicity[e] for e in zip(path[:-1], path[1:])) diff --git a/src/sage/modules/filtered_vector_space.py b/src/sage/modules/filtered_vector_space.py index 8bd7e986ced..f34c0abfe71 100644 --- a/src/sage/modules/filtered_vector_space.py +++ b/src/sage/modules/filtered_vector_space.py @@ -107,6 +107,7 @@ # the License, or (at your option) any later version. # https://www.gnu.org/licenses/ # *************************************************************************** +from itertools import product from sage.rings.rational_field import QQ from sage.rings.integer_ring import ZZ @@ -1122,11 +1123,10 @@ def _power_operation(self, n, operation): iters = [self.support()] * n filtration = {} - from sage.categories.cartesian_product import cartesian_product - for degrees in cartesian_product(iters): + for degrees in product(*iters): deg = sum(degrees) filt_deg = filtration.get(deg, set()) - for i in cartesian_product([indices.get(d) for d in degrees]): + for i in product(*[indices.get(d) for d in degrees]): pow_i = T.index_map(*i) if pow_i is not None: filt_deg.add(pow_i) diff --git a/src/sage/modules/tensor_operations.py b/src/sage/modules/tensor_operations.py index 41743870ca7..91ec0d83e07 100644 --- a/src/sage/modules/tensor_operations.py +++ b/src/sage/modules/tensor_operations.py @@ -60,7 +60,7 @@ # the License, or (at your option) any later version. # https://www.gnu.org/licenses/ # **************************************************************************** - +from itertools import product from collections import defaultdict from sage.modules.free_module import FreeModule_ambient_field @@ -90,12 +90,11 @@ def symmetrized_coordinate_sums(dim, n): ((0, 0), (0, 1) + (1, 0), (1, 1)) """ from sage.structure.formal_sum import FormalSum - from sage.categories.cartesian_product import cartesian_product coordinates = [list(range(dim)) for i in range(n)] table = defaultdict(list) - for i in cartesian_product(coordinates): + for i in product(*coordinates): sort_i = tuple(sorted(i)) table[sort_i].append([1, tuple(i)]) @@ -344,11 +343,7 @@ def _init_product_vectors(self, i): """ # Pick out the i[j]-th vector rays = [list(self._V[j].vectors()[k]) for j, k in enumerate(i)] - v = [] - # Note: convert to list, as cartesian_product of vectors is unrelated - from sage.categories.cartesian_product import cartesian_product - for r in cartesian_product(rays): - v.append(prod(r)) # build up the tensor product + v = [prod(r) for r in product(*rays)] # build up the tensor product v = tuple(v) # Use index of pre-existing tensor product vector if there is one try: @@ -415,8 +410,7 @@ def _init_product(self): [((0, 0), 0), ((0, 1), 1), ((1, 0), 2), ((1, 1), 3), ((2, 0), 3), ((2, 1), 2)] """ V_list_indices = [list(range(V.n_vectors())) for V in self._V] - from sage.categories.cartesian_product import cartesian_product - for i in cartesian_product(V_list_indices): + for i in product(*V_list_indices): self._index_map[tuple(i)] = self._init_product_vectors(i) self._symmetrize_indices = False @@ -433,12 +427,11 @@ def _init_symmetric(self): sage: sorted(Sym2_R._index_map.items()) [((0, 0), 0), ((0, 1), 1), ((0, 2), 2), ((1, 1), 3), ((1, 2), 4), ((2, 2), 3)] """ - from sage.categories.cartesian_product import cartesian_product V_list_indices = [list(range(V.n_vectors())) for V in self._V] Sym = symmetrized_coordinate_sums(self._V[0].dimension(), len(self._V)) N = len(V_list_indices) - for i in cartesian_product(V_list_indices): + for i in product(*V_list_indices): if any(i[j - 1] > i[j] for j in range(1, N)): continue self._index_map[tuple(i)] = self._init_power_operation_vectors(i, Sym) From 93e54a5b1fce802f42c9c1e454dfa5cc84b90c02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Mon, 25 Sep 2023 20:40:21 +0200 Subject: [PATCH 69/93] add some class roles for linking Errors in doc --- src/sage/databases/conway.py | 2 +- src/sage/graphs/generic_graph.py | 3 ++- src/sage/interfaces/singular.py | 2 +- src/sage/matrix/matrix_cyclo_dense.pyx | 5 +++-- src/sage/matrix/matrix_space.py | 4 ++-- src/sage/modular/abvar/abvar.py | 22 +++++++++++-------- src/sage/modular/overconvergent/genus0.py | 7 +++--- src/sage/modular/pollack_stevens/dist.pyx | 2 +- src/sage/modules/vector_space_homspace.py | 2 +- src/sage/numerical/gauss_legendre.pyx | 2 +- src/sage/rings/morphism.pyx | 2 +- src/sage/rings/polynomial/polynomial_ring.py | 2 +- src/sage/schemes/affine/affine_space.py | 4 ++-- src/sage/schemes/elliptic_curves/heegner.py | 6 ++--- src/sage/schemes/product_projective/space.py | 6 ++--- .../schemes/projective/projective_space.py | 4 ++-- src/sage/structure/element.pyx | 2 +- src/sage/structure/parent.pyx | 3 ++- src/sage/structure/parent_gens.pyx | 8 ++++--- src/sage/structure/parent_old.pyx | 7 +++--- 20 files changed, 53 insertions(+), 42 deletions(-) diff --git a/src/sage/databases/conway.py b/src/sage/databases/conway.py index d5d83431ea3..600c5a7c1ff 100644 --- a/src/sage/databases/conway.py +++ b/src/sage/databases/conway.py @@ -179,7 +179,7 @@ def __iter__(self): def polynomial(self, p, n): """ Return the Conway polynomial of degree ``n`` over ``GF(p)``, - or raise a RuntimeError if this polynomial is not in the + or raise a :class:`RuntimeError` if this polynomial is not in the database. .. NOTE:: diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index 19cc35bfb0b..840868b5528 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -1900,7 +1900,8 @@ def adjacency_matrix(self, sparse=None, vertices=None, *, base_ring=None, **kwds matrix. By default, the ordering given by :meth:`GenericGraph.vertices` with ``sort=True`` is used. If the vertices are not comparable, the keyword ``vertices`` must be - used to specify an ordering, or a TypeError exception will be raised. + used to specify an ordering, or a :class:`TypeError` exception will + be raised. - ``base_ring`` -- a ring (default: ``ZZ``); the base ring of the matrix space to use. diff --git a/src/sage/interfaces/singular.py b/src/sage/interfaces/singular.py index c4fb1261288..f4e5c6a9158 100644 --- a/src/sage/interfaces/singular.py +++ b/src/sage/interfaces/singular.py @@ -584,7 +584,7 @@ def eval(self, x, allow_semicolon=True, strip=True, **kwds): - ``x`` - string (of code) - ``allow_semicolon`` - default: False; if False then - raise a TypeError if the input line contains a semicolon. + raise a :class:`TypeError` if the input line contains a semicolon. - ``strip`` - ignored diff --git a/src/sage/matrix/matrix_cyclo_dense.pyx b/src/sage/matrix/matrix_cyclo_dense.pyx index 93f1f21a4f8..f54f3423ded 100644 --- a/src/sage/matrix/matrix_cyclo_dense.pyx +++ b/src/sage/matrix/matrix_cyclo_dense.pyx @@ -680,8 +680,9 @@ cdef class Matrix_cyclo_dense(Matrix_dense): cdef long _hash_(self) except -1: """ - Return hash of an immutable matrix. Raise a TypeError if input - matrix is mutable. + Return hash of an immutable matrix. + + This raises a :class:`TypeError` if input matrix is mutable. EXAMPLES: diff --git a/src/sage/matrix/matrix_space.py b/src/sage/matrix/matrix_space.py index 1ea8c0bca9f..6aab58352be 100644 --- a/src/sage/matrix/matrix_space.py +++ b/src/sage/matrix/matrix_space.py @@ -1343,8 +1343,8 @@ def _latex_(self): def __len__(self): """ Return number of elements of this matrix space if it fits in - an int; raise a TypeError if there are infinitely many - elements, and raise an OverflowError if there are finitely + an int; raise a :class:`TypeError` if there are infinitely many + elements, and raise an :class:`OverflowError` if there are finitely many but more than the size of an int. EXAMPLES:: diff --git a/src/sage/modular/abvar/abvar.py b/src/sage/modular/abvar/abvar.py index 7f59627139a..54ef9cc41c5 100644 --- a/src/sage/modular/abvar/abvar.py +++ b/src/sage/modular/abvar/abvar.py @@ -611,16 +611,19 @@ def newform_label(self): def elliptic_curve(self): """ - Return an elliptic curve isogenous to self. If self is not dimension 1 - with rational base ring, raise a ValueError. + Return an elliptic curve isogenous to ``self``. - The elliptic curve is found by looking it up in the CremonaDatabase. - The CremonaDatabase contains all curves up to some large conductor. If - a curve is not found in the CremonaDatabase, a RuntimeError will be - raised. In practice, only the most committed users will see this - RuntimeError. + If ``self`` is not dimension 1 + with rational base ring, this raises a :class:`ValueError`. - OUTPUT: an elliptic curve isogenous to self. + The elliptic curve is found by looking it up in the + CremonaDatabase. The CremonaDatabase contains all curves up + to some large conductor. If a curve is not found in the + CremonaDatabase, a :class:`RuntimeError` will be raised. In + practice, only the most committed users will see this + :class:`RuntimeError`. + + OUTPUT: an elliptic curve isogenous to ``self``. EXAMPLES:: @@ -4183,7 +4186,8 @@ def modular_symbols(self, sign=0): """ Return space of modular symbols (with given sign) associated to this modular abelian variety, if it can be found by cutting down - using Hecke operators. Otherwise raise a RuntimeError exception. + using Hecke operators. Otherwise raise a :class:`RuntimeError` + exception. EXAMPLES:: diff --git a/src/sage/modular/overconvergent/genus0.py b/src/sage/modular/overconvergent/genus0.py index 30e52f242e6..04e86a0732e 100644 --- a/src/sage/modular/overconvergent/genus0.py +++ b/src/sage/modular/overconvergent/genus0.py @@ -422,9 +422,10 @@ def change_ring(self, ring): def base_extend(self, ring): r""" - Return the base extension of self to the given base ring. There must be - a canonical map to this ring from the current base ring, otherwise a - TypeError will be raised. + Return the base extension of ``self`` to the given base ring. + + There must be a canonical map to this ring from the current + base ring, otherwise a :class:`TypeError` will be raised. EXAMPLES:: diff --git a/src/sage/modular/pollack_stevens/dist.pyx b/src/sage/modular/pollack_stevens/dist.pyx index eeb93f5f8e7..7a869a1c05a 100644 --- a/src/sage/modular/pollack_stevens/dist.pyx +++ b/src/sage/modular/pollack_stevens/dist.pyx @@ -853,7 +853,7 @@ cdef class Dist_vector(Dist): sage: QQ(d) 4/3 - We get a TypeError if there is more than 1 moment:: + We get a :class:`TypeError` if there is more than 1 moment:: sage: D = Symk(1); d = D([1,2]); d (1, 2) diff --git a/src/sage/modules/vector_space_homspace.py b/src/sage/modules/vector_space_homspace.py index c15f0f59285..b815051171a 100644 --- a/src/sage/modules/vector_space_homspace.py +++ b/src/sage/modules/vector_space_homspace.py @@ -365,7 +365,7 @@ def __call__(self, A, check=True, **kwds): sage: H.zero().is_zero() True - Previously the above code resulted in a TypeError because the + Previously the above code resulted in a :class:`TypeError` because the dimensions of the matrix were incorrect. """ from .vector_space_morphism import is_VectorSpaceMorphism, VectorSpaceMorphism diff --git a/src/sage/numerical/gauss_legendre.pyx b/src/sage/numerical/gauss_legendre.pyx index 96708c5b1ac..269727c1fdd 100644 --- a/src/sage/numerical/gauss_legendre.pyx +++ b/src/sage/numerical/gauss_legendre.pyx @@ -304,7 +304,7 @@ def integrate_vector_N(f, prec, N=3): The nodes and weights are calculated in the real field with ``prec`` bits of precision. If the vector space in which ``f`` takes values is over a field which is incompatible with this field (e.g. a finite - field) then a TypeError occurs. + field) then a :class:`TypeError` occurs. """ # We use nodes_uncached, because caching takes up memory, and numerics in # Bruin-DisneyHogg-Gao suggest that caching provides little benefit in the diff --git a/src/sage/rings/morphism.pyx b/src/sage/rings/morphism.pyx index 184efab78a5..5f7dc12cdb1 100644 --- a/src/sage/rings/morphism.pyx +++ b/src/sage/rings/morphism.pyx @@ -2492,7 +2492,7 @@ cdef class RingHomomorphism_cover(RingHomomorphism): We verify that calling directly raises the expected error (just coercing into the codomain), but calling with __call__ - (the second call below) gives a TypeError since 1/2 can't be + (the second call below) gives a :class:`TypeError` since 1/2 cannot be coerced into the domain. :: sage: f._call_(1/2) diff --git a/src/sage/rings/polynomial/polynomial_ring.py b/src/sage/rings/polynomial/polynomial_ring.py index af37b6d9fd7..0b2daea1e0b 100644 --- a/src/sage/rings/polynomial/polynomial_ring.py +++ b/src/sage/rings/polynomial/polynomial_ring.py @@ -388,7 +388,7 @@ def _element_constructor_(self, x=None, check=True, is_gen=False, sage: S(x) x - Throw a TypeError if any of the coefficients cannot be coerced + Throw a :class:`TypeError` if any of the coefficients cannot be coerced into the base ring (:trac:`6777`):: sage: RealField(300)['x']( [ 1, ComplexField(300).gen(), 0 ]) # needs sage.rings.real_mpfr diff --git a/src/sage/schemes/affine/affine_space.py b/src/sage/schemes/affine/affine_space.py index 181221488b2..42de0a0ec16 100644 --- a/src/sage/schemes/affine/affine_space.py +++ b/src/sage/schemes/affine/affine_space.py @@ -481,8 +481,8 @@ def _latex_generic_point(self, v=None): def _check_satisfies_equations(self, v): """ - Return True if ``v`` defines a point on the scheme self; raise a - TypeError otherwise. + Return ``True`` if ``v`` defines a point on the scheme ``self``; raise a + :class:`TypeError` otherwise. EXAMPLES:: diff --git a/src/sage/schemes/elliptic_curves/heegner.py b/src/sage/schemes/elliptic_curves/heegner.py index c021dc616e3..058b2f84669 100644 --- a/src/sage/schemes/elliptic_curves/heegner.py +++ b/src/sage/schemes/elliptic_curves/heegner.py @@ -569,7 +569,7 @@ def galois_group(self, base=QQ): def is_subfield(self, M): """ Return ``True`` if this ring class field is a subfield of the ring class field `M`. - If `M` is not a ring class field, then a TypeError is raised. + If `M` is not a ring class field, then a :class:`TypeError` is raised. EXAMPLES:: @@ -725,7 +725,7 @@ def __call__(self, x): sage: G(alpha) Class field automorphism defined by 14*x^2 - 10*x*y + 25*y^2 - A TypeError is raised when the coercion is not possible:: + A :class:`TypeError` is raised when the coercion is not possible:: sage: G(0) Traceback (most recent call last): @@ -4341,7 +4341,7 @@ def _trace_exact_conductor_1(self, prec=53): the case of conductor 1, computed using prec bits of precision, then approximated using some algorithm (e.g., continued fractions). If the precision is not enough to - determine a point on the curve, then a RuntimeError is raised. + determine a point on the curve, then a :class:`RuntimeError` is raised. Even if the precision determines a point, there is no guarantee that it is correct. diff --git a/src/sage/schemes/product_projective/space.py b/src/sage/schemes/product_projective/space.py index 16d6cfb38c0..0293e666cd6 100644 --- a/src/sage/schemes/product_projective/space.py +++ b/src/sage/schemes/product_projective/space.py @@ -739,13 +739,13 @@ def _validate(self, polynomials): except TypeError: raise TypeError("polynomials (=%s) must be elements of %s" % (polynomials,source_ring)) for f in polynomials: - self._degree(f) #raises a ValueError if not multi-homogeneous + self._degree(f) # raises a ValueError if not multi-homogeneous return polynomials def _check_satisfies_equations(self, v): """ - Return True if ``v`` defines a point on the scheme this space; raise a - TypeError otherwise. + Return ``True`` if ``v`` defines a point on the scheme this space; + raise a :class:`TypeError` otherwise. EXAMPLES:: diff --git a/src/sage/schemes/projective/projective_space.py b/src/sage/schemes/projective/projective_space.py index 7a06401f39f..622f9ef911c 100644 --- a/src/sage/schemes/projective/projective_space.py +++ b/src/sage/schemes/projective/projective_space.py @@ -359,8 +359,8 @@ def ngens(self): def _check_satisfies_equations(self, v): """ - Return True if ``v`` defines a point on the scheme; raise a - TypeError otherwise. + Return ``True`` if ``v`` defines a point on the scheme; raise a + :class:`TypeError` otherwise. EXAMPLES:: diff --git a/src/sage/structure/element.pyx b/src/sage/structure/element.pyx index 36da1c0cc12..caae7e40ffc 100644 --- a/src/sage/structure/element.pyx +++ b/src/sage/structure/element.pyx @@ -2706,7 +2706,7 @@ cdef class RingElement(ModuleElement): sage: 2r^(1/2) # needs sage.symbolic sqrt(2) - Exponent overflow should throw an OverflowError (:trac:`2956`):: + Exponent overflow should throw an :class:`OverflowError` (:trac:`2956`):: sage: K. = AA[] # needs sage.rings.number_field sage: x^(2^64 + 12345) # needs sage.rings.number_field diff --git a/src/sage/structure/parent.pyx b/src/sage/structure/parent.pyx index 895f7ae386b..6548d8a3656 100644 --- a/src/sage/structure/parent.pyx +++ b/src/sage/structure/parent.pyx @@ -1344,7 +1344,8 @@ cdef class Parent(sage.structure.category_object.CategoryObject): r""" Return the unique homomorphism from self to codomain that sends ``self.gens()`` to the entries of ``im_gens``. - Raises a TypeError if there is no such homomorphism. + + This raises a :class:`TypeError` if there is no such homomorphism. INPUT: diff --git a/src/sage/structure/parent_gens.pyx b/src/sage/structure/parent_gens.pyx index cc6ffaace21..3f69b9daee4 100644 --- a/src/sage/structure/parent_gens.pyx +++ b/src/sage/structure/parent_gens.pyx @@ -199,10 +199,11 @@ cdef class ParentWithGens(ParentWithBase): def hom(self, im_gens, codomain=None, base_map=None, category=None, check=True): r""" - Return the unique homomorphism from self to codomain that + Return the unique homomorphism from ``self`` to codomain that sends ``self.gens()`` to the entries of ``im_gens`` and induces the map ``base_map`` on the base ring. - Raises a TypeError if there is no such homomorphism. + + This raises a :class:`TypeError` if there is no such homomorphism. INPUT: @@ -272,7 +273,8 @@ cdef class ParentWithGens(ParentWithBase): From: Integer Ring To: Finite Field of size 5 - There might not be a natural morphism, in which case a TypeError exception is raised. + There might not be a natural morphism, in which case a + :class:`TypeError` exception is raised. :: diff --git a/src/sage/structure/parent_old.pyx b/src/sage/structure/parent_old.pyx index 549afae6242..77a7888d3b8 100644 --- a/src/sage/structure/parent_old.pyx +++ b/src/sage/structure/parent_old.pyx @@ -221,11 +221,12 @@ cdef class Parent(parent.Parent): Given a list v of rings, try to coerce x canonically into each one in turn. Return the __call__ coercion of the result into self of the first canonical coercion that succeeds. Raise a - TypeError if none of them succeed. + :class:`TypeError` if none of them succeed. INPUT: - x -- Python object - v -- parent object or list (iterator) of parent objects + + - x -- Python object + - v -- parent object or list (iterator) of parent objects """ deprecation(33464, "usage of _coerce_try is deprecated") check_old_coerce(self) From 52508f65a2c4858484875f22fcff05c1f482daa7 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 25 Sep 2023 16:22:46 -0700 Subject: [PATCH 70/93] build/pkgs/sagemath_{coxeter3,mcqd,meataxe,tdlib}: Remove bad conda.txt --- build/pkgs/sagemath_coxeter3/distros/conda.txt | 1 - build/pkgs/sagemath_mcqd/distros/conda.txt | 1 - build/pkgs/sagemath_meataxe/distros/conda.txt | 1 - build/pkgs/sagemath_tdlib/distros/conda.txt | 1 - 4 files changed, 4 deletions(-) delete mode 100644 build/pkgs/sagemath_coxeter3/distros/conda.txt delete mode 100644 build/pkgs/sagemath_mcqd/distros/conda.txt delete mode 100644 build/pkgs/sagemath_meataxe/distros/conda.txt delete mode 100644 build/pkgs/sagemath_tdlib/distros/conda.txt diff --git a/build/pkgs/sagemath_coxeter3/distros/conda.txt b/build/pkgs/sagemath_coxeter3/distros/conda.txt deleted file mode 100644 index 3ffe2eb8bfc..00000000000 --- a/build/pkgs/sagemath_coxeter3/distros/conda.txt +++ /dev/null @@ -1 +0,0 @@ -sagemath-coxeter3 diff --git a/build/pkgs/sagemath_mcqd/distros/conda.txt b/build/pkgs/sagemath_mcqd/distros/conda.txt deleted file mode 100644 index 9504f7f4c76..00000000000 --- a/build/pkgs/sagemath_mcqd/distros/conda.txt +++ /dev/null @@ -1 +0,0 @@ -sagemath-mcqd diff --git a/build/pkgs/sagemath_meataxe/distros/conda.txt b/build/pkgs/sagemath_meataxe/distros/conda.txt deleted file mode 100644 index b3abc7692fe..00000000000 --- a/build/pkgs/sagemath_meataxe/distros/conda.txt +++ /dev/null @@ -1 +0,0 @@ -sagemath-meataxe diff --git a/build/pkgs/sagemath_tdlib/distros/conda.txt b/build/pkgs/sagemath_tdlib/distros/conda.txt deleted file mode 100644 index f890d1c9084..00000000000 --- a/build/pkgs/sagemath_tdlib/distros/conda.txt +++ /dev/null @@ -1 +0,0 @@ -sagemath-tdlib From 0a27b65d1a6231575de96a945ec14b585e38ec3a Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 25 Sep 2023 16:23:43 -0700 Subject: [PATCH 71/93] tox.ini (debian-trixie): Use IGNORE_MISSING_SYSTEM_PACKAGES=yes --- tox.ini | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tox.ini b/tox.ini index 84bb05c351c..6ea933fd89d 100644 --- a/tox.ini +++ b/tox.ini @@ -227,6 +227,7 @@ setenv = # # https://hub.docker.com/_/debian # debian-bullseye does not have libgiac-dev + # debian-trixie does not have libbrial-dev # debian: SYSTEM=debian debian: BASE_IMAGE=debian @@ -239,6 +240,7 @@ setenv = debian-bullseye: IGNORE_MISSING_SYSTEM_PACKAGES=yes debian-bookworm: BASE_TAG=bookworm debian-trixie: BASE_TAG=trixie + debian-trixie: IGNORE_MISSING_SYSTEM_PACKAGES=yes debian-sid: BASE_TAG=sid # # https://hub.docker.com/u/linuxmintd From 4ba2b6a59b7a249b368f0d23979c7bc8277de6fc Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 25 Sep 2023 16:25:17 -0700 Subject: [PATCH 72/93] .github/workflows/ci-macos.yml: Refactor through new reusable workflow macos.yml, update macOS, Xcode versions --- .github/workflows/ci-macos.yml | 115 +++++++----------------- .github/workflows/macos.yml | 159 +++++++++++++++++++++++++++++++++ tox.ini | 25 ++++++ 3 files changed, 217 insertions(+), 82 deletions(-) create mode 100644 .github/workflows/macos.yml diff --git a/.github/workflows/ci-macos.yml b/.github/workflows/ci-macos.yml index 3f49b4f8d96..9482eb9632b 100644 --- a/.github/workflows/ci-macos.yml +++ b/.github/workflows/ci-macos.yml @@ -30,89 +30,40 @@ env: TARGETS_OPTIONAL: ptest jobs: - local-macos: + stage-1: + uses: ./.github/workflows/macos.yml + with: + stage: "1" - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - stage: ["1", "2", "2-optional-0-o", "2-optional-p-z", "2-experimental-0-o", "2-experimental-p-z"] - # python3_xcode is only accepted if enough packages are available from the system - # --> to test "minimal", we would need https://github.com/sagemath/sage/issues/30949 - tox_env: [homebrew-macos-usrlocal-minimal, homebrew-macos-usrlocal-standard, homebrew-macos-usrlocal-maximal, homebrew-macos-usrlocal-python3_xcode-standard, conda-forge-macos-minimal, conda-forge-macos-standard, conda-forge-macos-maximal] - xcode_version_factor: [default] - os: [ macos-11, macos-12 ] - env: - TOX_ENV: local-${{ matrix.tox_env }} - LOCAL_ARTIFACT_NAME: sage-local-commit-${{ github.sha }}-tox-local-${{ matrix.tox_env }}-${{ matrix.os }}-xcode_${{ matrix.xcode_version_factor }} - LOGS_ARTIFACT_NAME: logs-commit-${{ github.sha }}-tox-local-${{ matrix.tox_env }}--${{ matrix.os }}-xcode_${{ matrix.xcode_version_factor }} - steps: - - uses: actions/checkout@v4 - - name: Select Xcode version - run: | - if [ ${{ matrix.xcode_version_factor }} != default ]; then sudo xcode-select -s /Applications/Xcode_${{ matrix.xcode_version_factor }}.app; fi - - name: Install test prerequisites - run: | - brew install tox - - uses: actions/download-artifact@v3 - with: - path: sage-local-artifact - name: ${{ env.LOCAL_ARTIFACT_NAME }} - if: contains(matrix.stage, '2') - - name: Extract sage-local artifact - # This is macOS tar -- cannot use --listed-incremental - run: | - export SAGE_LOCAL=$(pwd)/.tox/$TOX_ENV/local - .github/workflows/extract-sage-local.sh sage-local-artifact/sage-local-*.tar - if: contains(matrix.stage, '2') - - name: Build and test with tox - # We use a high parallelization on purpose in order to catch possible parallelization bugs in the build scripts. - # For doctesting, we use a lower parallelization to avoid timeouts. - run: | - case "${{ matrix.stage }}" in - 1) export TARGETS_PRE="all-sage-local" TARGETS="all-sage-local" TARGETS_OPTIONAL="build/make/Makefile" - ;; - 2) export TARGETS_PRE="all-sage-local" TARGETS="build doc-html" TARGETS_OPTIONAL="ptest" - ;; - 2-optional*) export TARGETS_PRE="build/make/Makefile" TARGETS="build/make/Makefile" - targets_pattern="${{ matrix.stage }}" - targets_pattern="${targets_pattern#2-optional-}" - export TARGETS_OPTIONAL=$( echo $(export PATH=build/bin:$PATH && sage-package list :optional: --has-file 'spkg-install.in|spkg-install|requirements.txt' --no-file huge|has_nonfree_dependencies | grep -v sagemath_doc | grep "^[$targets_pattern]" ) ) - ;; - 2-experimental*) export TARGETS_PRE="build/make/Makefile" TARGETS="build/make/Makefile" - targets_pattern="${{ matrix.stage }}" - targets_pattern="${targets_pattern#2-experimental-}" - export TARGETS_OPTIONAL=$( echo $(export PATH=build/bin:$PATH && sage-package list :experimental: --has-file 'spkg-install.in|spkg-install|requirements.txt' --no-file huge|has_nonfree_dependencies | grep -v sagemath_doc | grep "^[$targets_pattern]" ) ) - ;; - esac - MAKE="make -j12" tox -e $TOX_ENV -- SAGE_NUM_THREADS=4 $TARGETS - - name: Prepare logs artifact - run: | - mkdir -p "artifacts/$LOGS_ARTIFACT_NAME"; cp -r .tox/*/log "artifacts/$LOGS_ARTIFACT_NAME" - if: always() - - uses: actions/upload-artifact@v3 - with: - path: artifacts - name: ${{ env.LOGS_ARTIFACT_NAME }} - if: always() - - name: Print out logs for immediate inspection - # and markup the output with GitHub Actions logging commands - run: | - .github/workflows/scan-logs.sh "artifacts/$LOGS_ARTIFACT_NAME" - if: always() - - name: Prepare sage-local artifact - # This also includes the copies of homebrew or conda installed in the tox environment. - # We use absolute pathnames in the tar file. - # This is macOS tar -- cannot use --remove-files. - # We remove the $SAGE_LOCAL/lib64 link, which will be recreated by the next stage. - run: | - mkdir -p sage-local-artifact && (cd .tox/$TOX_ENV && rm -f "local/lib64" && tar -cf - $(pwd)) > sage-local-artifact/sage-${{ env.TOX_ENV }}-${{ matrix.stage }}.tar - if: contains(matrix.stage, '1') - - uses: actions/upload-artifact@v3 - with: - path: sage-local-artifact/sage-${{ env.TOX_ENV }}-${{ matrix.stage }}.tar - name: ${{ env.LOCAL_ARTIFACT_NAME }} - if: always() + stage-2: + uses: ./.github/workflows/macos.yml + with: + stage: "2" + needs: [stage-1] + + stage-2-optional-0-o: + uses: ./.github/workflows/macos.yml + with: + stage: "2-optional-0-o" + needs: [stage-2] + + stage-2-optional-p-z: + uses: ./.github/workflows/macos.yml + with: + stage: "2-optional-p-z" + needs: [stage-2-optional-0-o] + + stage-2-experimental-0-o: + uses: ./.github/workflows/macos.yml + with: + stage: "2-optional-0-o" + needs: [stage-2-optional-p-z] + + stage-2-experimental-p-z: + uses: ./.github/workflows/macos.yml + with: + stage: "2-experimental-p-z" + needs: [stage-2-experimental-0-o] dist: diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml new file mode 100644 index 00000000000..dd5e6bec8eb --- /dev/null +++ b/.github/workflows/macos.yml @@ -0,0 +1,159 @@ +name: Reusable workflow for macOS portability CI + +on: + workflow_call: + inputs: + # Either specify a stage + stage: + required: false + type: string + # Or specify targets + targets_pre: + default: build/make/Makefile + type: string + targets: + default: build/make/Makefile + type: string + targets_optional: + default: build/make/Makefile + type: string + # System configuration + osversion_xcodeversion_toxenv_tuples: + description: 'Stringified JSON object' + default: >- + [["latest", "", "homebrew-macos-usrlocal-minimal"], + ["latest", "", "homebrew-macos-usrlocal-standard"], + ["11", "xcode_11.7", "homebrew-macos-usrlocal-standard"], + ["12", "", "homebrew-macos-usrlocal-standard"], + ["13", "xcode_15.0", "homebrew-macos-usrlocal-standard"], + ["latest", "", "homebrew-macos-usrlocal-maximal"], + ["latest", "", "homebrew-macos-usrlocal-python3_xcode-standard"], + ["latest", "", "conda-forge-macos-minimal"], + ["latest", "", "conda-forge-macos-standard"], + ["latest", "", "conda-forge-macos-maximal"]] + type: string + extra_sage_packages: + description: 'Extra Sage packages to install as system packages' + type: string + default: "" + max_parallel: + type: number + default: 10 + free_disk_space: + default: false + type: boolean + # + # For use in upstream CIs. + # + upstream_artifact: + required: false + type: string + sage_repo: + required: false + type: string + sage_ref: + required: false + type: string + +jobs: + local-macos: + + runs-on: macos-${{ matrix.osversion_xcodeversion_toxenv[0] }} + strategy: + fail-fast: false + max-parallel: ${{ inputs.max_parallel }} + matrix: + osversion_xcodeversion_toxenv: ${{ fromJson(inputs.osversion_xcodeversion_toxenv_tuples) }} + env: + TOX_ENV: local-${{ matrix.osversion_xcodeversion_toxenv[2] }}${{ matrix.osversion_xcodeversion_toxenv[1] && format('-{0}', matrix.osversion_xcodeversion_toxenv[1]) }} + LOCAL_ARTIFACT_NAME: sage-local-commit-${{ github.sha }}-tox-local-${{ matrix.osversion_xcodeversion_toxenv[2] }}-macos-${{ matrix.osversion_xcodeversion_toxenv[0] }}${{ matrix.osversion_xcodeversion_toxenv[1] && format('-{0}', matrix.osversion_xcodeversion_toxenv[1]) }} + LOGS_ARTIFACT_NAME: logs-commit-${{ github.sha }}-tox-local-${{ matrix.osversion_xcodeversion_toxenv[2] }}-macos-${{ matrix.osversion_xcodeversion_toxenv[0] }}${{ matrix.osversion_xcodeversion_toxenv[1] && format('-{0}', matrix.osversion_xcodeversion_toxenv[1]) }} + steps: + - name: Check out SageMath + uses: actions/checkout@v4 + with: + repository: ${{ inputs.sage_repo }} + ref: ${{ inputs.sage_ref }} + fetch-depth: 10000 + + - name: Install test prerequisites + run: | + brew install tox + - name: Download upstream artifact + uses: actions/download-artifact@v3 + with: + path: upstream + name: ${{ inputs.upstream_artifact }} + if: inputs.upstream_artifact + - name: Update Sage packages from upstream artifact + run: | + (export PATH=$(pwd)/build/bin:$PATH; (cd upstream && bash -x update-pkgs.sh) && sed -i.bak '/upstream/d' .dockerignore && echo "/:toolchain:/i ADD upstream upstream" | sed -i.bak -f - build/bin/write-dockerfile.sh && git diff) + if: inputs.upstream_artifact + + - name: Merge CI fixes from sagemath/sage + run: | + .ci/merge-fixes.sh + env: + GH_TOKEN: ${{ github.token }} + + - uses: actions/download-artifact@v3 + with: + path: sage-local-artifact + name: ${{ env.LOCAL_ARTIFACT_NAME }} + if: contains(inputs.stage, '2') + - name: Extract sage-local artifact + # This is macOS tar -- cannot use --listed-incremental + run: | + export SAGE_LOCAL=$(pwd)/.tox/$TOX_ENV/local + .github/workflows/extract-sage-local.sh sage-local-artifact/sage-local-*.tar + if: contains(inputs.stage, '2') + - name: Build and test with tox + # We use a high parallelization on purpose in order to catch possible parallelization bugs in the build scripts. + # For doctesting, we use a lower parallelization to avoid timeouts. + run: | + case "${{ inputs.stage }}" in + 1) export TARGETS_PRE="all-sage-local" TARGETS="all-sage-local" TARGETS_OPTIONAL="build/make/Makefile" + ;; + 2) export TARGETS_PRE="all-sage-local" TARGETS="build doc-html" TARGETS_OPTIONAL="ptest" + ;; + 2-optional*) export TARGETS_PRE="build/make/Makefile" TARGETS="build/make/Makefile" + targets_pattern="${{ inputs.stage }}" + targets_pattern="${targets_pattern#2-optional-}" + export TARGETS_OPTIONAL=$( echo $(export PATH=build/bin:$PATH && sage-package list :optional: --has-file 'spkg-install.in|spkg-install|requirements.txt' --no-file huge|has_nonfree_dependencies | grep -v sagemath_doc | grep "^[$targets_pattern]" ) ) + ;; + 2-experimental*) export TARGETS_PRE="build/make/Makefile" TARGETS="build/make/Makefile" + targets_pattern="${{ inputs.stage }}" + targets_pattern="${targets_pattern#2-experimental-}" + export TARGETS_OPTIONAL=$( echo $(export PATH=build/bin:$PATH && sage-package list :experimental: --has-file 'spkg-install.in|spkg-install|requirements.txt' --no-file huge|has_nonfree_dependencies | grep -v sagemath_doc | grep "^[$targets_pattern]" ) ) + ;; + *) export TARGETS_PRE="${{ inputs.targets_pre }}" TARGETS="${{ inputs.targets }} TARGETS_OPTIONAL="${{ inputs.targets_optional }} + ;; + esac + MAKE="make -j12" tox -e $TOX_ENV -- SAGE_NUM_THREADS=4 $TARGETS + - name: Prepare logs artifact + run: | + mkdir -p "artifacts/$LOGS_ARTIFACT_NAME"; cp -r .tox/*/log "artifacts/$LOGS_ARTIFACT_NAME" + if: always() + - uses: actions/upload-artifact@v3 + with: + path: artifacts + name: ${{ env.LOGS_ARTIFACT_NAME }} + if: always() + - name: Print out logs for immediate inspection + # and markup the output with GitHub Actions logging commands + run: | + .github/workflows/scan-logs.sh "artifacts/$LOGS_ARTIFACT_NAME" + if: always() + - name: Prepare sage-local artifact + # This also includes the copies of homebrew or conda installed in the tox environment. + # We use absolute pathnames in the tar file. + # This is macOS tar -- cannot use --remove-files. + # We remove the $SAGE_LOCAL/lib64 link, which will be recreated by the next stage. + run: | + mkdir -p sage-local-artifact && (cd .tox/$TOX_ENV && rm -f "local/lib64" && tar -cf - $(pwd)) > sage-local-artifact/sage-${{ env.TOX_ENV }}-${{ inputs.stage }}.tar + if: contains(inputs.stage, '1') + - uses: actions/upload-artifact@v3 + with: + path: sage-local-artifact/sage-${{ env.TOX_ENV }}-${{ inputs.stage }}.tar + name: ${{ env.LOCAL_ARTIFACT_NAME }} + if: always() diff --git a/tox.ini b/tox.ini index 6ea933fd89d..39a087c1062 100644 --- a/tox.ini +++ b/tox.ini @@ -601,6 +601,27 @@ setenv = macos-12.3: MACOSX_DEPLOYMENT_TARGET=12.3 macos-13.3: MACOS_SDK=/Library/Developer/CommandLineTools/SDKs/MacOSX13.3.sdk macos-13.3: MACOSX_DEPLOYMENT_TARGET=13.3 + macos-14.0: MACOS_SDK=/Library/Developer/CommandLineTools/SDKs/MacOSX14.0.sdk + macos-14.0: MACOSX_DEPLOYMENT_TARGET=14.0 + # XCode versions, as installed on GH Actions runners + # only in https://github.com/actions/runner-images/blob/main/images/macos/macos-11-Readme.md#xcode + xcode_11.7: XCODE_VERSION=11.7 + xcode_12.4: XCODE_VERSION=12.4 + xcode_12.5.1: XCODE_VERSION=12.5.1 + xcode_13.0: XCODE_VERSION=13.0 + # in above and also in https://github.com/actions/runner-images/blob/main/images/macos/macos-12-Readme.md#xcode + xcode_13.1: XCODE_VERSION=13.1 + xcode_13.2.1: XCODE_VERSION=13.2.1 + # only in https://github.com/actions/runner-images/blob/main/images/macos/macos-12-Readme.md#xcode + xcode_13.3.1: XCODE_VERSION=13.3.1 + xcode_13.4.1: XCODE_VERSION=13.4.1 + xcode_14.0.1: XCODE_VERSION=14.0.1 + # in avove and also in https://github.com/actions/runner-images/blob/main/images/macos/macos-13-Readme.md#xcode + xcode_14.1: XCODE_VERSION=14.1 + xcode_14.2: XCODE_VERSION=14.2 + # only in https://github.com/actions/runner-images/blob/main/images/macos/macos-13-Readme.md#xcode + xcode_14.3.1: XCODE_VERSION=14.3.1 + xcode_15.0: XCODE_VERSION=15.0 # # Resulting full configuration args, including EXTRA_CONFIGURE_ARGS from the user environment # @@ -629,6 +650,10 @@ commands = # local: bash -c 'if [ ! -d {env:HOME}/Library/Caches ]; then mkdir -p {env:SHARED_CACHE_DIR} && mkdir -p {env:HOME}/Library && ln -sf {toxworkdir}/Caches {env:HOME}/Library/; fi' # + # local-macos + # + local-macos: bash -c 'if [ -n "{env:XCODE_VERSION:}" ]; then sudo xcode-select -s /Applications/Xcode_{env:XCODE_VERSION:}.app; fi;' + # # local-homebrew # # https://docs.brew.sh/Installation From 9cff8ff051106d689f36e0625da97f6b8e0ed3d7 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 25 Sep 2023 16:25:40 -0700 Subject: [PATCH 73/93] .ci/merge-fixes.sh: New --- .ci/merge-fixes.sh | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100755 .ci/merge-fixes.sh diff --git a/.ci/merge-fixes.sh b/.ci/merge-fixes.sh new file mode 100755 index 00000000000..19b76f536be --- /dev/null +++ b/.ci/merge-fixes.sh @@ -0,0 +1,28 @@ +#!/bin/sh +# Merge open PRs from sagemath/sage labeled "blocker". +GH="gh -R sagemath/sage" +PRs="$($GH pr list --label "p: blocker / 1" --json number --jq '.[].number')" +if [ -z "$PRs" ]; then + echo 'Nothing to do: Found no open PRs with "blocker" status.' +else + echo "Found PRs: " $PRs + export GIT_AUTHOR_NAME="ci-sage workflow" + export GIT_AUTHOR_EMAIL="ci-sage@example.com" + export GIT_COMMITTER_NAME="$GIT_AUTHOR_NAME" + export GIT_COMMITTER_EMAIL="$GIT_AUTHOR_EMAIL" + git commit -q -m "Uncommitted changes" --no-allow-empty -a + git tag -f test_head + for a in $PRs; do + echo "::group::Merging PR #$a" + $GH pr checkout $a + git checkout -q test_head + if git merge --no-edit -q FETCH_HEAD; then + echo "::endgroup::" + echo "Merged #$a" + else + echo "::endgroup::" + echo "Failure merging #$a, resetting" + git reset --hard + fi + done +fi From a9d84a8efddc28fdbdbb87d6dd73672cdffceb2c Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 25 Sep 2023 16:32:28 -0700 Subject: [PATCH 74/93] Use .ci/merge-fixes.sh in all workflows --- .github/workflows/build.yml | 6 ++++++ .github/workflows/ci-conda.yml | 6 ++++++ .github/workflows/doc-build-pdf.yml | 6 ++++++ .github/workflows/doc-build.yml | 6 ++++++ .github/workflows/docker.yml | 6 ++++++ .github/workflows/lint.yml | 15 +++++++++++++++ 6 files changed, 45 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 547ba7f90fe..545eb4e064b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -32,6 +32,12 @@ jobs: id: checkout uses: actions/checkout@v4 + - name: Merge CI fixes from sagemath/sage + run: | + .ci/merge-fixes.sh + env: + GH_TOKEN: ${{ github.token }} + - name: Update system packages id: prepare run: | diff --git a/.github/workflows/ci-conda.yml b/.github/workflows/ci-conda.yml index 14d38feff96..b0a95754cab 100644 --- a/.github/workflows/ci-conda.yml +++ b/.github/workflows/ci-conda.yml @@ -51,6 +51,12 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Merge CI fixes from sagemath/sage + run: | + .ci/merge-fixes.sh + env: + GH_TOKEN: ${{ github.token }} + - name: Check for Miniconda id: check_conda run: echo ::set-output name=installed::$CONDA diff --git a/.github/workflows/doc-build-pdf.yml b/.github/workflows/doc-build-pdf.yml index 6728b140c8b..6eacba7fe52 100644 --- a/.github/workflows/doc-build-pdf.yml +++ b/.github/workflows/doc-build-pdf.yml @@ -21,6 +21,12 @@ jobs: - name: Checkout uses: actions/checkout@v4 + - name: Merge CI fixes from sagemath/sage + run: | + .ci/merge-fixes.sh + env: + GH_TOKEN: ${{ github.token }} + - name: Prepare run: | apt-get update && apt-get install -y zip diff --git a/.github/workflows/doc-build.yml b/.github/workflows/doc-build.yml index 3c7cd9a7091..75214db8314 100644 --- a/.github/workflows/doc-build.yml +++ b/.github/workflows/doc-build.yml @@ -19,6 +19,12 @@ jobs: - name: Checkout uses: actions/checkout@v4 + - name: Merge CI fixes from sagemath/sage + run: | + .ci/merge-fixes.sh + env: + GH_TOKEN: ${{ github.token }} + - name: Update system packages run: | apt-get update && apt-get install -y git zip diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 12fac573272..db4896bbd12 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -179,6 +179,12 @@ jobs: (export PATH=$(pwd)/build/bin:$PATH; (cd upstream && bash -x update-pkgs.sh) && sed -i.bak '/upstream/d' .dockerignore && echo "/:toolchain:/i ADD upstream upstream" | sed -i.bak -f - build/bin/write-dockerfile.sh && git diff) if: inputs.upstream_artifact + - name: Merge CI fixes from sagemath/sage + run: | + .ci/merge-fixes.sh + env: + GH_TOKEN: ${{ github.token }} + - name: Try to login to ghcr.io if: inputs.docker_push_repository != '' # https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-environment-variable diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index c63f371b268..b4eebb4ac9e 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -14,6 +14,11 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 + - name: Merge CI fixes from sagemath/sage + run: | + .ci/merge-fixes.sh + env: + GH_TOKEN: ${{ github.token }} - name: Set up Python uses: actions/setup-python@v4 with: @@ -28,6 +33,11 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 + - name: Merge CI fixes from sagemath/sage + run: | + .ci/merge-fixes.sh + env: + GH_TOKEN: ${{ github.token }} - name: Set up Python uses: actions/setup-python@v4 with: @@ -42,6 +52,11 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 + - name: Merge CI fixes from sagemath/sage + run: | + .ci/merge-fixes.sh + env: + GH_TOKEN: ${{ github.token }} - name: Set up Python uses: actions/setup-python@v4 with: From e4025c15586ddced6211eaff95f7901b077320a7 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 25 Sep 2023 16:52:35 -0700 Subject: [PATCH 75/93] .ci/merge-fixes.sh: Unshallow for merge --- .ci/merge-fixes.sh | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/.ci/merge-fixes.sh b/.ci/merge-fixes.sh index 19b76f536be..735fa8a609a 100755 --- a/.ci/merge-fixes.sh +++ b/.ci/merge-fixes.sh @@ -1,6 +1,7 @@ #!/bin/sh # Merge open PRs from sagemath/sage labeled "blocker". -GH="gh -R sagemath/sage" +REPO="sagemath/sage" +GH="gh -R $REPO" PRs="$($GH pr list --label "p: blocker / 1" --json number --jq '.[].number')" if [ -z "$PRs" ]; then echo 'Nothing to do: Found no open PRs with "blocker" status.' @@ -11,12 +12,13 @@ else export GIT_COMMITTER_NAME="$GIT_AUTHOR_NAME" export GIT_COMMITTER_EMAIL="$GIT_AUTHOR_EMAIL" git commit -q -m "Uncommitted changes" --no-allow-empty -a - git tag -f test_head for a in $PRs; do - echo "::group::Merging PR #$a" - $GH pr checkout $a + echo "::group::Merging PR https://github.com/$REPO/pull/$a" + git tag -f test_head + $GH pr checkout -b pr-$a $a + git fetch --unshallow --all git checkout -q test_head - if git merge --no-edit -q FETCH_HEAD; then + if git merge --no-edit -q pr-$a; then echo "::endgroup::" echo "Merged #$a" else @@ -25,4 +27,5 @@ else git reset --hard fi done + git log test_head..HEAD fi From 3949cc71907129fc8fe3bb2e1c6f7f7c484748ad Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 25 Sep 2023 18:43:17 -0700 Subject: [PATCH 76/93] build.yml, doc-build.yml: First create CI fixes as an artifact, so gh is not needed in the container --- .ci/merge-fixes.sh | 6 ++++-- .github/workflows/build.yml | 36 ++++++++++++++++++++++++++++++--- .github/workflows/doc-build.yml | 36 ++++++++++++++++++++++++++++++--- 3 files changed, 70 insertions(+), 8 deletions(-) diff --git a/.ci/merge-fixes.sh b/.ci/merge-fixes.sh index 735fa8a609a..2c8d6e8503f 100755 --- a/.ci/merge-fixes.sh +++ b/.ci/merge-fixes.sh @@ -11,6 +11,7 @@ else export GIT_AUTHOR_EMAIL="ci-sage@example.com" export GIT_COMMITTER_NAME="$GIT_AUTHOR_NAME" export GIT_COMMITTER_EMAIL="$GIT_AUTHOR_EMAIL" + git tag -f test_base git commit -q -m "Uncommitted changes" --no-allow-empty -a for a in $PRs; do echo "::group::Merging PR https://github.com/$REPO/pull/$a" @@ -18,8 +19,9 @@ else $GH pr checkout -b pr-$a $a git fetch --unshallow --all git checkout -q test_head - if git merge --no-edit -q pr-$a; then + if git merge --no-edit --squash -q pr-$a; then echo "::endgroup::" + git commit -q -m "Merge https://github.com/$REPO/pull/$a" -a --allow-empty echo "Merged #$a" else echo "::endgroup::" @@ -27,5 +29,5 @@ else git reset --hard fi done - git log test_head..HEAD + git log test_base..HEAD fi diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 545eb4e064b..25434d9c9c3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -24,19 +24,34 @@ concurrency: cancel-in-progress: true jobs: - build: + get_ci_fixes: runs-on: ubuntu-latest - container: ghcr.io/sagemath/sage/sage-${{ github.event.inputs.platform || 'ubuntu-focal-standard' }}-with-targets:${{ github.event.inputs.docker_tag || 'dev'}} steps: - name: Checkout id: checkout uses: actions/checkout@v4 - - name: Merge CI fixes from sagemath/sage run: | .ci/merge-fixes.sh env: GH_TOKEN: ${{ github.token }} + - name: Store CI fixes in upstream artifact + run: | + mkdir -p upstream + git format-patch --stdout test_base > upstream/ci_fixes.patch + - uses: actions/upload-artifact@v2 + with: + path: upstream + name: upstream + + build: + runs-on: ubuntu-latest + container: ghcr.io/sagemath/sage/sage-${{ github.event.inputs.platform || 'ubuntu-focal-standard' }}-with-targets:${{ github.event.inputs.docker_tag || 'dev'}} + needs: [get_ci_fixes] + steps: + - name: Checkout + id: checkout + uses: actions/checkout@v4 - name: Update system packages id: prepare @@ -74,6 +89,21 @@ jobs: if [ ! -f worktree-image/.gitignore ]; then cp .gitignore worktree-image/; fi (cd worktree-image && git add -A && git commit --quiet --allow-empty -m "old" -a && git tag -f old && git reset --hard new && git reset --quiet old && git add -N . && git status) + - name: Download upstream artifact + uses: actions/download-artifact@v3 + with: + path: upstream + name: upstream + + - name: Apply CI fixes from sagemath/sage + # After applying the fixes, make sure all changes are marked as uncommitted changes. + run: | + if [ -r upstream/ci_fixes.patch ]; then + (cd worktree-image && git commit --quiet -m "current changes" --allow-empty -a && git am) < upstream/ci_fixes.patch + git reset --quiet old + git add -N . + fi + - name: Incremental build, test changed files (sage -t --new) id: incremental run: | diff --git a/.github/workflows/doc-build.yml b/.github/workflows/doc-build.yml index 75214db8314..1837b838a87 100644 --- a/.github/workflows/doc-build.yml +++ b/.github/workflows/doc-build.yml @@ -12,18 +12,33 @@ concurrency: cancel-in-progress: true jobs: - build-docs: + get_ci_fixes: runs-on: ubuntu-latest - container: ghcr.io/sagemath/sage/sage-ubuntu-focal-standard-with-targets:dev steps: - name: Checkout + id: checkout uses: actions/checkout@v4 - - name: Merge CI fixes from sagemath/sage run: | .ci/merge-fixes.sh env: GH_TOKEN: ${{ github.token }} + - name: Store CI fixes in upstream artifact + run: | + mkdir -p upstream + git format-patch --stdout test_base > upstream/ci_fixes.patch + - uses: actions/upload-artifact@v2 + with: + path: upstream + name: upstream + + build-docs: + runs-on: ubuntu-latest + container: ghcr.io/sagemath/sage/sage-ubuntu-focal-standard-with-targets:dev + needs: [get_ci_fixes] + steps: + - name: Checkout + uses: actions/checkout@v4 - name: Update system packages run: | @@ -60,6 +75,21 @@ jobs: # Keep track of changes to built HTML new_version=$(cat src/VERSION.txt); (cd /sage/local/share/doc/sage/html/en && find . -name "*.html" | xargs sed -i '/class="sidebar-brand-text"/s/Sage [0-9a-z.]* /Sage '$new_version' /'; git init && (echo "*.svg binary"; echo "*.pdf binary") >> .gitattributes && (echo ".buildinfo"; echo '*.inv'; echo '.git*'; echo '*.svg'; echo '*.pdf'; echo '*.png'; echo 'searchindex.js') > .gitignore; git add -A && git commit --quiet -m "old") + - name: Download upstream artifact + uses: actions/download-artifact@v3 + with: + path: upstream + name: upstream + + - name: Apply CI fixes from sagemath/sage + # After applying the fixes, make sure all changes are marked as uncommitted changes. + run: | + if [ -r upstream/ci_fixes.patch ]; then + (cd worktree-image && git commit -m "current changes" --allow-empty -a && git am) < upstream/ci_fixes.patch + git reset --quiet old + git add -N . + fi + - name: Incremental build id: incremental run: | From e129160c968afeaa2c913da8fcb29991010fd4d0 Mon Sep 17 00:00:00 2001 From: OP5642 Date: Sat, 9 Sep 2023 23:59:23 +0200 Subject: [PATCH 77/93] Initial additions --- src/sage/topology/simplicial_complex.py | 71 ++++++++++++++++++++++--- 1 file changed, 64 insertions(+), 7 deletions(-) diff --git a/src/sage/topology/simplicial_complex.py b/src/sage/topology/simplicial_complex.py index d8a6aaf696e..7706970e797 100644 --- a/src/sage/topology/simplicial_complex.py +++ b/src/sage/topology/simplicial_complex.py @@ -4845,11 +4845,19 @@ def intersection(self, other): F = F + [s for s in self.faces()[k] if s in other.faces()[k]] return SimplicialComplex(F) - def bigraded_betti_numbers(self, base_ring=ZZ): + def bigraded_betti_numbers(self, base_ring=ZZ, verbose=False): r""" Return a dictionary of the bigraded Betti numbers of ``self``, with keys `(-a, 2b)`. + INPUT: + + - ``base_ring`` -- (optional, default ``ZZ``) the base ring used + when computing homology + - ``verbose`` -- (optional, default ``False``) if ``True``, print + messages during the computation, which indicate in which subcomplexes + non-trivial homologies appear + .. SEEALSO:: See :meth:`bigraded_betti_number` for more information. @@ -4862,8 +4870,38 @@ def bigraded_betti_numbers(self, base_ring=ZZ): [((0, 0), 1), ((-1, 6), 1), ((-1, 4), 2), ((-2, 8), 1), ((-2, 6), 1)] sage: sorted(Y.bigraded_betti_numbers(base_ring=QQ).items(), reverse=True) # needs sage.modules [((0, 0), 1), ((-1, 4), 3), ((-2, 8), 2), ((-2, 6), 1), ((-3, 10), 1)] - """ - if base_ring in self._bbn_all_computed: + + If we wish to view them in a form of a table, it is + simple enough to create a function as such:: + + sage: def print_table(bbns): + ....: max_a = max(-p[0] for p in bbns) + ....: max_b = max(p[1] for p in bbns) + ....: bbn_table = [[bbns.get((-a,b), 0) for a in range(max_a+1)] + ....: for b in range(max_b+1)] + ....: width = len(str(max(bbns.values()))) + 1 + ....: print(' '*width, end=' ') + ....: for i in range(max_a+1): + ....: print(f'{-i:{width}}', end=' ') + ....: print() + ....: for j in range(len(bbn_table)): + ....: print(f'{j:{width}}', end=' ') + ....: for r in bbn_table[j]: + ....: print(f'{r:{width}}', end=' ') + ....: print() + sage: print_table(X.bigraded_betti_numbers()) + 0 -1 -2 + 0 1 0 0 + 1 0 0 0 + 2 0 0 0 + 3 0 0 0 + 4 0 2 0 + 5 0 0 0 + 6 0 1 1 + 7 0 0 0 + 8 0 0 1 + """ + if base_ring in self._bbn_all_computed and not verbose: return self._bbn[base_ring] from sage.homology.homology_group import HomologyGroup @@ -4884,18 +4922,29 @@ def bigraded_betti_numbers(self, base_ring=ZZ): if ind not in B: B[ind] = ZZ.zero() B[ind] += len(H[j-k-1].gens()) + if verbose: + print("Non-trivial homology {} in dimension {} of the full subcomplex generated by a set of vertices {}".format(H[j-k-1], j-k-1, x)) self._bbn[base_ring] = B self._bbn_all_computed.add(base_ring) return B - def bigraded_betti_number(self, a, b, base_ring=ZZ): + def bigraded_betti_number(self, a, b, base_ring=ZZ, verbose=False): r""" Return the bigraded Betti number indexed in the form `(-a, 2b)`. - Bigraded Betti number with indices `(-a, 2b)` is defined as a sum of ranks - of `(b-a-1)`-th (co)homologies of full subcomplexes with exactly `b` vertices. + Bigraded Betti number with indices `(-a, 2b)` is defined as a + sum of ranks of `(b-a-1)`-th (co)homologies of full subcomplexes + with exactly `b` vertices. + + INPUT: + + - ``base_ring`` -- (optional, default ``ZZ``) the base ring used + when computing homology + - ``verbose`` -- (optional, default ``False``) if ``True``, print + messages during the computation, which indicate in which subcomplexes + non-trivial homologies appear EXAMPLES:: @@ -4915,12 +4964,18 @@ def bigraded_betti_number(self, a, b, base_ring=ZZ): 2 sage: X.bigraded_betti_number(-1, 8) 0 + sage: Y = SimplicialComplex([[1,2,3],[1,2,4],[3,5],[4,5]]) + sage: Y.bigraded_betti_number(-1, 4, verbose=True) + Non-trivial homology Z in dimension 0 of the full subcomplex generated by a set of vertices (1, 5) + Non-trivial homology Z in dimension 0 of the full subcomplex generated by a set of vertices (2, 5) + Non-trivial homology Z in dimension 0 of the full subcomplex generated by a set of vertices (3, 4) + 3 """ if b % 2: return ZZ.zero() if a == 0 and b == 0: return ZZ.one() - if base_ring in self._bbn: + if base_ring in self._bbn and not verbose: if base_ring in self._bbn_all_computed: return self._bbn[base_ring].get((a, b), ZZ.zero()) elif (a, b) in self._bbn[base_ring]: @@ -4939,6 +4994,8 @@ def bigraded_betti_number(self, a, b, base_ring=ZZ): H = S.homology(base_ring=base_ring) if b+a-1 in H and H[b+a-1] != H0: B += len(H[b+a-1].gens()) + if verbose: + print("Non-trivial homology {} in dimension {} of the full subcomplex generated by a set of vertices {}".format(H[b+a-1], b+a-1, x)) B = ZZ(B) From bb4121697ed8d4ed74a7aee96cb0fff7ceefc04f Mon Sep 17 00:00:00 2001 From: OP5642 Date: Sun, 17 Sep 2023 16:44:52 +0200 Subject: [PATCH 78/93] Added suggestions from code review --- src/sage/topology/simplicial_complex.py | 33 ++++++++++++++++--------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/src/sage/topology/simplicial_complex.py b/src/sage/topology/simplicial_complex.py index 7706970e797..167b5be74c0 100644 --- a/src/sage/topology/simplicial_complex.py +++ b/src/sage/topology/simplicial_complex.py @@ -4852,11 +4852,15 @@ def bigraded_betti_numbers(self, base_ring=ZZ, verbose=False): INPUT: - - ``base_ring`` -- (optional, default ``ZZ``) the base ring used + - ``base_ring`` -- (default: ``ZZ``) the base ring used when computing homology - - ``verbose`` -- (optional, default ``False``) if ``True``, print - messages during the computation, which indicate in which subcomplexes - non-trivial homologies appear + - ``verbose`` -- (default: ``False``) if ``True``, print + messages during the computation, which indicate in which + subcomplexes non-trivial homologies appear + + .. NOTE:: + + If ``verbose`` is ``True``, then caching is avoided. .. SEEALSO:: @@ -4940,11 +4944,15 @@ def bigraded_betti_number(self, a, b, base_ring=ZZ, verbose=False): INPUT: - - ``base_ring`` -- (optional, default ``ZZ``) the base ring used + - ``base_ring`` -- (default: ``ZZ``) the base ring used when computing homology - - ``verbose`` -- (optional, default ``False``) if ``True``, print - messages during the computation, which indicate in which subcomplexes - non-trivial homologies appear + - ``verbose`` -- (default: ``False``) if ``True``, print + messages during the computation, which indicate in which + subcomplexes non-trivial homologies appear + + .. NOTE:: + + If ``verbose`` is ``True``, then caching is avoided. EXAMPLES:: @@ -4966,9 +4974,12 @@ def bigraded_betti_number(self, a, b, base_ring=ZZ, verbose=False): 0 sage: Y = SimplicialComplex([[1,2,3],[1,2,4],[3,5],[4,5]]) sage: Y.bigraded_betti_number(-1, 4, verbose=True) - Non-trivial homology Z in dimension 0 of the full subcomplex generated by a set of vertices (1, 5) - Non-trivial homology Z in dimension 0 of the full subcomplex generated by a set of vertices (2, 5) - Non-trivial homology Z in dimension 0 of the full subcomplex generated by a set of vertices (3, 4) + Non-trivial homology Z in dimension 0 of the full subcomplex + generated by a set of vertices (1, 5) + Non-trivial homology Z in dimension 0 of the full subcomplex + generated by a set of vertices (2, 5) + Non-trivial homology Z in dimension 0 of the full subcomplex + generated by a set of vertices (3, 4) 3 """ if b % 2: From 037b616e39b65fb8a36a6560af9a3b069d9f4c7a Mon Sep 17 00:00:00 2001 From: OP5642 Date: Sun, 17 Sep 2023 23:37:36 +0200 Subject: [PATCH 79/93] Improved ``verbose`` option for ``bigraded_betti_numbers()`` method --- src/sage/topology/simplicial_complex.py | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/sage/topology/simplicial_complex.py b/src/sage/topology/simplicial_complex.py index 167b5be74c0..1d00dd50a4d 100644 --- a/src/sage/topology/simplicial_complex.py +++ b/src/sage/topology/simplicial_complex.py @@ -4870,9 +4870,23 @@ def bigraded_betti_numbers(self, base_ring=ZZ, verbose=False): sage: X = SimplicialComplex([[0,1],[1,2],[1,3],[2,3]]) sage: Y = SimplicialComplex([[1,2,3],[1,2,4],[3,5],[4,5]]) - sage: sorted(X.bigraded_betti_numbers().items(), reverse=True) # needs sage.modules + sage: sorted(X.bigraded_betti_numbers(base_ring=QQ).items(), reverse=True) [((0, 0), 1), ((-1, 6), 1), ((-1, 4), 2), ((-2, 8), 1), ((-2, 6), 1)] - sage: sorted(Y.bigraded_betti_numbers(base_ring=QQ).items(), reverse=True) # needs sage.modules + sage: sorted(Y.bigraded_betti_numbers(verbose=True).items(), reverse=True) + (-1, 4): Non-trivial homology Z in dimension 0 of the full + subcomplex generated by a set of vertices (1, 5) + (-1, 4): Non-trivial homology Z in dimension 0 of the full + subcomplex generated by a set of vertices (2, 5) + (-1, 4): Non-trivial homology Z in dimension 0 of the full + subcomplex generated by a set of vertices (3, 4) + (-2, 6): Non-trivial homology Z in dimension 0 of the full + subcomplex generated by a set of vertices (1, 2, 5) + (-2, 8): Non-trivial homology Z in dimension 1 of the full + subcomplex generated by a set of vertices (1, 3, 4, 5) + (-2, 8): Non-trivial homology Z in dimension 1 of the full + subcomplex generated by a set of vertices (2, 3, 4, 5) + (-3, 10): Non-trivial homology Z in dimension 1 of the full + subcomplex generated by a set of vertices (1, 2, 3, 4, 5) [((0, 0), 1), ((-1, 4), 3), ((-2, 8), 2), ((-2, 6), 1), ((-3, 10), 1)] If we wish to view them in a form of a table, it is @@ -4927,7 +4941,7 @@ def bigraded_betti_numbers(self, base_ring=ZZ, verbose=False): B[ind] = ZZ.zero() B[ind] += len(H[j-k-1].gens()) if verbose: - print("Non-trivial homology {} in dimension {} of the full subcomplex generated by a set of vertices {}".format(H[j-k-1], j-k-1, x)) + print("{}: Non-trivial homology {} in dimension {} of the full subcomplex generated by a set of vertices {}".format(ind, H[j-k-1], j-k-1, x)) self._bbn[base_ring] = B self._bbn_all_computed.add(base_ring) From 5c971eef7a9fe04badbe49284154465be42c20f4 Mon Sep 17 00:00:00 2001 From: Martin Rubey Date: Tue, 26 Sep 2023 15:15:26 +0200 Subject: [PATCH 80/93] revert treating 1 / f and ~f the same --- src/sage/rings/lazy_series.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/sage/rings/lazy_series.py b/src/sage/rings/lazy_series.py index 339256bda07..8086e15f9ef 100644 --- a/src/sage/rings/lazy_series.py +++ b/src/sage/rings/lazy_series.py @@ -57,7 +57,7 @@ sage: f 1 + z + 2*z^2 + 3*z^3 + 5*z^4 + 8*z^5 + 13*z^6 + O(z^7) sage: f^-1 - 1 - z - z^2 + 1 - z - z^2 + O(z^7) sage: f + f^-1 2 + z^2 + 3*z^3 + 5*z^4 + 8*z^5 + 13*z^6 + O(z^7) sage: g = (f + f^-1)*(f - f^-1); g @@ -3448,11 +3448,12 @@ def _div_(self, other): sage: 1 / f Traceback (most recent call last): ... - ZeroDivisionError: cannot divide by a series of positive valuation + ZeroDivisionError: cannot divide by 0 sage: L.options._reset() """ - if self.is_one(): - return ~other + # currently __invert__ and _div_ behave differently with + # respect to division by lazy power series of positive + # valuation, so we cannot call ~other if self.is_one() if not other: raise ZeroDivisionError("cannot divide by 0") From d4cc09d5c37139ab03646e22d62124c70abf2714 Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Tue, 26 Sep 2023 18:54:33 +0100 Subject: [PATCH 81/93] fix expect interface for newer ptyprocess See https://github.com/sagemath/sage/issues/32147 for details --- build/pkgs/ptyprocess/checksums.ini | 6 +++--- build/pkgs/ptyprocess/install-requires.txt | 4 +--- build/pkgs/ptyprocess/package-version.txt | 2 +- src/sage/interfaces/expect.py | 2 +- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/build/pkgs/ptyprocess/checksums.ini b/build/pkgs/ptyprocess/checksums.ini index 7c8cf7bd652..d55046be142 100644 --- a/build/pkgs/ptyprocess/checksums.ini +++ b/build/pkgs/ptyprocess/checksums.ini @@ -1,5 +1,5 @@ tarball=ptyprocess-VERSION.tar.gz -sha1=3290062d67ef8a2f136bff9c2cd106673ff21316 -md5=94e537122914cc9ec9c1eadcd36e73a1 -cksum=1748633415 +sha1=2d8830d1025c8e33149c7723c2f283122f9488c1 +md5=9da200c397cb1752209a6b718b6cfc68 +cksum=2094263560 upstream_url=https://pypi.io/packages/source/p/ptyprocess/ptyprocess-VERSION.tar.gz diff --git a/build/pkgs/ptyprocess/install-requires.txt b/build/pkgs/ptyprocess/install-requires.txt index a89be777b4a..4527bfdd3d1 100644 --- a/build/pkgs/ptyprocess/install-requires.txt +++ b/build/pkgs/ptyprocess/install-requires.txt @@ -1,3 +1 @@ -ptyprocess ==0.5.1 -# https://github.com/sagemath/sage/issues/31280#comment:42 and following -# sagelib is not compatible with ptyprocess 0.5.2, 0.6, and 0.7 +ptyprocess > 0.5 diff --git a/build/pkgs/ptyprocess/package-version.txt b/build/pkgs/ptyprocess/package-version.txt index dfd7f4b3ab3..faef31a4357 100644 --- a/build/pkgs/ptyprocess/package-version.txt +++ b/build/pkgs/ptyprocess/package-version.txt @@ -1 +1 @@ -0.5.1.p0 +0.7.0 diff --git a/src/sage/interfaces/expect.py b/src/sage/interfaces/expect.py index 84adf0341b5..30d3843852e 100644 --- a/src/sage/interfaces/expect.py +++ b/src/sage/interfaces/expect.py @@ -561,7 +561,7 @@ def _close(self, force=True): try: if self._expect is not None: self._expect.close(force=force) - except ExceptionPexpect: + except (ExceptionPexpect, OSError): self._expect.ptyproc.fd = -1 self._expect.ptyproc.closed = True self._expect.child_fd = -1 From 8d1b661e8a51595cc5b0981148321d484ac0b4d5 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 26 Sep 2023 11:10:11 -0700 Subject: [PATCH 82/93] .github/workflows/macos.yml: Remove Docker-specific upstream artifact handling --- .github/workflows/macos.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index dd5e6bec8eb..5b448cec1bb 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -87,7 +87,7 @@ jobs: if: inputs.upstream_artifact - name: Update Sage packages from upstream artifact run: | - (export PATH=$(pwd)/build/bin:$PATH; (cd upstream && bash -x update-pkgs.sh) && sed -i.bak '/upstream/d' .dockerignore && echo "/:toolchain:/i ADD upstream upstream" | sed -i.bak -f - build/bin/write-dockerfile.sh && git diff) + (export PATH=$(pwd)/build/bin:$PATH; (cd upstream && bash -x update-pkgs.sh) && git diff) if: inputs.upstream_artifact - name: Merge CI fixes from sagemath/sage From 21fc2b3c5a7558b8047454b17aac4cb2c7962f14 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 26 Sep 2023 11:10:34 -0700 Subject: [PATCH 83/93] .github/workflows/build.yml: More quiet in the new git acrobatics --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 25434d9c9c3..feffa45c00d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -101,7 +101,7 @@ jobs: if [ -r upstream/ci_fixes.patch ]; then (cd worktree-image && git commit --quiet -m "current changes" --allow-empty -a && git am) < upstream/ci_fixes.patch git reset --quiet old - git add -N . + git add --quiet -N . fi - name: Incremental build, test changed files (sage -t --new) From b92d9f42fe0c88e71fba61c5f36326ded19d454d Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 26 Sep 2023 13:08:35 -0700 Subject: [PATCH 84/93] Do not make empty commits --- .ci/merge-fixes.sh | 7 +++++-- .github/workflows/build.yml | 4 +--- .github/workflows/doc-build.yml | 4 +--- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/.ci/merge-fixes.sh b/.ci/merge-fixes.sh index 2c8d6e8503f..1fb8267df0e 100755 --- a/.ci/merge-fixes.sh +++ b/.ci/merge-fixes.sh @@ -21,8 +21,11 @@ else git checkout -q test_head if git merge --no-edit --squash -q pr-$a; then echo "::endgroup::" - git commit -q -m "Merge https://github.com/$REPO/pull/$a" -a --allow-empty - echo "Merged #$a" + if git commit -q -m "Merge https://github.com/$REPO/pull/$a" -a --no-allow-empty; then + echo "Merged #$a" + else + echo "Empty, skipped" + fi else echo "::endgroup::" echo "Failure merging #$a, resetting" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index feffa45c00d..b8dafe9a398 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -99,9 +99,7 @@ jobs: # After applying the fixes, make sure all changes are marked as uncommitted changes. run: | if [ -r upstream/ci_fixes.patch ]; then - (cd worktree-image && git commit --quiet -m "current changes" --allow-empty -a && git am) < upstream/ci_fixes.patch - git reset --quiet old - git add --quiet -N . + (cd worktree-image && git commit -q -m "current changes" --allow-empty -a && git am; git reset --quiet old; git add -N .) < upstream/ci_fixes.patch fi - name: Incremental build, test changed files (sage -t --new) diff --git a/.github/workflows/doc-build.yml b/.github/workflows/doc-build.yml index 1837b838a87..ab4530a964a 100644 --- a/.github/workflows/doc-build.yml +++ b/.github/workflows/doc-build.yml @@ -85,9 +85,7 @@ jobs: # After applying the fixes, make sure all changes are marked as uncommitted changes. run: | if [ -r upstream/ci_fixes.patch ]; then - (cd worktree-image && git commit -m "current changes" --allow-empty -a && git am) < upstream/ci_fixes.patch - git reset --quiet old - git add -N . + (cd worktree-image && git commit -q -m "current changes" --allow-empty -a && git am; git reset --quiet old; git add -N .) < upstream/ci_fixes.patch fi - name: Incremental build From b14ef26c12163e1767d9904f2e34883ad0dafb47 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 26 Sep 2023 15:10:00 -0700 Subject: [PATCH 85/93] .github/workflows/{build,doc-build}.yml: Use actions/upload-artifact@v3 --- .github/workflows/build.yml | 2 +- .github/workflows/doc-build.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b8dafe9a398..bbb3e687540 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -39,7 +39,7 @@ jobs: run: | mkdir -p upstream git format-patch --stdout test_base > upstream/ci_fixes.patch - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 with: path: upstream name: upstream diff --git a/.github/workflows/doc-build.yml b/.github/workflows/doc-build.yml index ab4530a964a..6f8cb348d55 100644 --- a/.github/workflows/doc-build.yml +++ b/.github/workflows/doc-build.yml @@ -27,7 +27,7 @@ jobs: run: | mkdir -p upstream git format-patch --stdout test_base > upstream/ci_fixes.patch - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 with: path: upstream name: upstream From c22131f74897c05f625c91008973df8be124ebed Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 26 Sep 2023 18:19:08 -0700 Subject: [PATCH 86/93] build/pkgs/ecm/spkg-install.in: Work around build failure with Xcode 15, https://github.com/sagemath/sage/issues/36342 --- build/pkgs/ecm/spkg-install.in | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/build/pkgs/ecm/spkg-install.in b/build/pkgs/ecm/spkg-install.in index b60230f368a..ce58949c8ee 100644 --- a/build/pkgs/ecm/spkg-install.in +++ b/build/pkgs/ecm/spkg-install.in @@ -189,6 +189,12 @@ export CFLAGS # Not exported by 'sage-env'. LDFLAGS are exported above if # necessary. We currently don't set (or modify) any other # environment variables, so don't have to export them here. +# Workaround for build failure with Xcode 15, https://github.com/sagemath/sage/issues/36342 +case "$UNAME" in + Darwin*) + export gmp_cv_asm_underscore=yes + ;; +esac ############################################################################### # Now configure ECM: From df89444b783f0b6d7b3f0e80bb0b4a723add3766 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Wed, 27 Sep 2023 11:02:13 +0800 Subject: [PATCH 87/93] Remove obsolete workaround from conda --- .github/workflows/ci-conda.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/ci-conda.yml b/.github/workflows/ci-conda.yml index 14d38feff96..90d3756dba7 100644 --- a/.github/workflows/ci-conda.yml +++ b/.github/workflows/ci-conda.yml @@ -99,9 +99,6 @@ jobs: echo "::remove-matcher owner=configure-system-package-warning::" echo "::remove-matcher owner=configure-system-package-error::" - # Manually install ptyprocess for now, until https://github.com/sagemath/sage/issues/32147 is fixed - pip install --no-build-isolation -v -v ptyprocess==0.5.1 - - name: Build shell: bash -l {0} run: | From 35f816af2ea09e8969bd21c3f2ebd1a7e973653f Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 17 Jun 2023 11:36:39 -0700 Subject: [PATCH 88/93] build/bin/sage-logger [GITHUB_ACTIONS]: Emit ::group:: ... ::endgroup:: for prefixed logs --- build/bin/sage-logger | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/build/bin/sage-logger b/build/bin/sage-logger index 1682ccbc079..47220c27a39 100755 --- a/build/bin/sage-logger +++ b/build/bin/sage-logger @@ -89,11 +89,16 @@ else # Redirect stdout and stderr to a subprocess running tee. # We trap SIGINT such that SIGINT interrupts the main process being # run, not the logging. + + if [ -n "$$(GITHUB_ACTIONS)" ]; then echo "::group::${logname}"; fi + ( exec 2>&1; eval "$cmd" ) | \ ( trap '' SIGINT; tee -a "$logfile" | $SED ) pipestatus=(${PIPESTATUS[*]}) + if [ -n "$$(GITHUB_ACTIONS)" ]; then echo "::endgroup::"; fi + if [ ${pipestatus[1]} -ne 0 ]; then exit ${pipestatus[1]} else From c7e3f32b135afa09af5da31eb17f01a6ac5ae43f Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 30 Jun 2023 00:44:18 -0700 Subject: [PATCH 89/93] build.yml: Use 'make --output-sync=recurse' --- .github/workflows/build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 547ba7f90fe..f1cfd787887 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -76,7 +76,7 @@ jobs: ./bootstrap && make build && ./sage -t --new -p2 working-directory: ./worktree-image env: - MAKE: make -j2 + MAKE: make -j2 --output-sync=recurse SAGE_NUM_THREADS: 2 - name: Build and test modularized distributions @@ -84,7 +84,7 @@ jobs: run: make V=0 tox && make pypi-wheels working-directory: ./worktree-image env: - MAKE: make -j2 + MAKE: make -j2 --output-sync=recurse SAGE_NUM_THREADS: 2 - name: Set up node to install pyright @@ -123,7 +123,7 @@ jobs: make build working-directory: ./worktree-image env: - MAKE: make -j2 + MAKE: make -j2 --output-sync=recurse SAGE_NUM_THREADS: 2 - name: Pytest From 29984a4cdade66e480553dded337bb595f4be896 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 30 Jun 2023 07:36:40 -0700 Subject: [PATCH 90/93] doc-build.yml: Use 'make --output-sync=recurse --- .github/workflows/doc-build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/doc-build.yml b/.github/workflows/doc-build.yml index 3c7cd9a7091..5e2c36f16c6 100644 --- a/.github/workflows/doc-build.yml +++ b/.github/workflows/doc-build.yml @@ -61,7 +61,7 @@ jobs: ./bootstrap && make build working-directory: ./worktree-image env: - MAKE: make -j2 + MAKE: make -j2 --output-sync=recurse SAGE_NUM_THREADS: 2 - name: Build (fallback to non-incremental) @@ -72,7 +72,7 @@ jobs: make doc-clean doc-uninstall sagelib-clean && git clean -fx src/sage && ./config.status && make build working-directory: ./worktree-image env: - MAKE: make -j2 + MAKE: make -j2 --output-sync=recurse SAGE_NUM_THREADS: 2 - name: Build docs @@ -89,7 +89,7 @@ jobs: ./config.status && make doc-html working-directory: ./worktree-image env: - MAKE: make -j2 + MAKE: make -j2 --output-sync=recurse SAGE_NUM_THREADS: 2 - name: Copy docs From c021b0a2428e3117c388cb6721b49bc048f17286 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 30 Jun 2023 07:53:16 -0700 Subject: [PATCH 91/93] build/bin/sage-logger [GITHUB_ACTIONS]: Put ::group::, ::endgroup:: in the 'sed' subshell --- build/bin/sage-logger | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/build/bin/sage-logger b/build/bin/sage-logger index 47220c27a39..219626b315d 100755 --- a/build/bin/sage-logger +++ b/build/bin/sage-logger @@ -90,15 +90,13 @@ else # We trap SIGINT such that SIGINT interrupts the main process being # run, not the logging. - if [ -n "$$(GITHUB_ACTIONS)" ]; then echo "::group::${logname}"; fi + ( exec 2>&1; eval "$cmd" ) | \ - ( trap '' SIGINT; tee -a "$logfile" | $SED ) + ( trap '' SIGINT; if [ -n "$$(GITHUB_ACTIONS)" ]; then echo "::group::${logname}"; fi; tee -a "$logfile" | $SED; if [ -n "$$(GITHUB_ACTIONS)" ]; then echo "::endgroup::"; fi ) pipestatus=(${PIPESTATUS[*]}) - if [ -n "$$(GITHUB_ACTIONS)" ]; then echo "::endgroup::"; fi - if [ ${pipestatus[1]} -ne 0 ]; then exit ${pipestatus[1]} else From fd6b0306afbf768a8b931623237ff841adfa674e Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 30 Jun 2023 08:07:05 -0700 Subject: [PATCH 92/93] build/bin/sage-logger [GITHUB_ACTIONS]: Fix env syntax, run only in prefixed logs --- build/bin/sage-logger | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/build/bin/sage-logger b/build/bin/sage-logger index 219626b315d..1d8d92c0c75 100755 --- a/build/bin/sage-logger +++ b/build/bin/sage-logger @@ -90,10 +90,8 @@ else # We trap SIGINT such that SIGINT interrupts the main process being # run, not the logging. - - ( exec 2>&1; eval "$cmd" ) | \ - ( trap '' SIGINT; if [ -n "$$(GITHUB_ACTIONS)" ]; then echo "::group::${logname}"; fi; tee -a "$logfile" | $SED; if [ -n "$$(GITHUB_ACTIONS)" ]; then echo "::endgroup::"; fi ) + ( trap '' SIGINT; if [ -n "$GITHUB_ACTIONS" -a -n "$prefix" ]; then echo "::group::${logname}"; fi; tee -a "$logfile" | $SED; if [ -n "$GITHUB_ACTIONS" -a -n "$prefix" ]; then echo "::endgroup::"; fi ) pipestatus=(${PIPESTATUS[*]}) From 1cf0c13e5271b13f0db4364a39d8bd80e13f66cc Mon Sep 17 00:00:00 2001 From: Release Manager Date: Thu, 28 Sep 2023 00:06:42 +0200 Subject: [PATCH 93/93] Updated SageMath version to 10.2.beta5 --- CITATION.cff | 4 ++-- VERSION.txt | 2 +- build/pkgs/configure/checksums.ini | 6 +++--- build/pkgs/configure/package-version.txt | 2 +- build/pkgs/sage_conf/install-requires.txt | 2 +- build/pkgs/sage_docbuild/install-requires.txt | 2 +- build/pkgs/sage_setup/install-requires.txt | 2 +- build/pkgs/sage_sws2rst/install-requires.txt | 2 +- build/pkgs/sagelib/install-requires.txt | 2 +- build/pkgs/sagemath_bliss/install-requires.txt | 2 +- build/pkgs/sagemath_categories/install-requires.txt | 2 +- build/pkgs/sagemath_coxeter3/install-requires.txt | 2 +- build/pkgs/sagemath_environment/install-requires.txt | 2 +- build/pkgs/sagemath_mcqd/install-requires.txt | 2 +- build/pkgs/sagemath_meataxe/install-requires.txt | 2 +- build/pkgs/sagemath_objects/install-requires.txt | 2 +- build/pkgs/sagemath_repl/install-requires.txt | 2 +- build/pkgs/sagemath_sirocco/install-requires.txt | 2 +- build/pkgs/sagemath_tdlib/install-requires.txt | 2 +- pkgs/sage-conf/VERSION.txt | 2 +- pkgs/sage-conf_pypi/VERSION.txt | 2 +- pkgs/sage-docbuild/VERSION.txt | 2 +- pkgs/sage-setup/VERSION.txt | 2 +- pkgs/sage-sws2rst/VERSION.txt | 2 +- pkgs/sagemath-bliss/VERSION.txt | 2 +- pkgs/sagemath-categories/VERSION.txt | 2 +- pkgs/sagemath-coxeter3/VERSION.txt | 2 +- pkgs/sagemath-environment/VERSION.txt | 2 +- pkgs/sagemath-mcqd/VERSION.txt | 2 +- pkgs/sagemath-meataxe/VERSION.txt | 2 +- pkgs/sagemath-objects/VERSION.txt | 2 +- pkgs/sagemath-repl/VERSION.txt | 2 +- pkgs/sagemath-sirocco/VERSION.txt | 2 +- pkgs/sagemath-tdlib/VERSION.txt | 2 +- src/VERSION.txt | 2 +- src/bin/sage-version.sh | 6 +++--- src/sage/version.py | 6 +++--- 37 files changed, 44 insertions(+), 44 deletions(-) diff --git a/CITATION.cff b/CITATION.cff index 270a3771e13..7c31fd13f05 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -4,8 +4,8 @@ title: SageMath abstract: SageMath is a free open-source mathematics software system. authors: - name: "The SageMath Developers" -version: 10.2.beta4 +version: 10.2.beta5 doi: 10.5281/zenodo.593563 -date-released: 2023-09-24 +date-released: 2023-09-27 repository-code: "https://github.com/sagemath/sage" url: "https://www.sagemath.org/" diff --git a/VERSION.txt b/VERSION.txt index 81e115aa077..3b70b866392 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -SageMath version 10.2.beta4, Release Date: 2023-09-24 +SageMath version 10.2.beta5, Release Date: 2023-09-27 diff --git a/build/pkgs/configure/checksums.ini b/build/pkgs/configure/checksums.ini index 4b63f77b720..f6feef844de 100644 --- a/build/pkgs/configure/checksums.ini +++ b/build/pkgs/configure/checksums.ini @@ -1,4 +1,4 @@ tarball=configure-VERSION.tar.gz -sha1=c6efbc310523cfc3c1f2fa3f86a0761311de6003 -md5=670d28340bbdd4cabaeb3e76a2004dbe -cksum=2059970385 +sha1=96468a2d2ec8ee319095f3d2abd73e5f1ec7829d +md5=87391217b5c82275e1cb581721877eec +cksum=370856230 diff --git a/build/pkgs/configure/package-version.txt b/build/pkgs/configure/package-version.txt index 03261de9a5c..886c67921da 100644 --- a/build/pkgs/configure/package-version.txt +++ b/build/pkgs/configure/package-version.txt @@ -1 +1 @@ -8cf728dfa04520d04e7eac3f8e6751eab0c3dde5 +b01856309bcb0d25e9cf830da19fa1cdd24df2bf diff --git a/build/pkgs/sage_conf/install-requires.txt b/build/pkgs/sage_conf/install-requires.txt index 2e27a902192..f38cdee4efc 100644 --- a/build/pkgs/sage_conf/install-requires.txt +++ b/build/pkgs/sage_conf/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sage-conf ~= 10.2b4 +sage-conf ~= 10.2b5 diff --git a/build/pkgs/sage_docbuild/install-requires.txt b/build/pkgs/sage_docbuild/install-requires.txt index b8bf809524d..62965fd0775 100644 --- a/build/pkgs/sage_docbuild/install-requires.txt +++ b/build/pkgs/sage_docbuild/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sage-docbuild ~= 10.2b4 +sage-docbuild ~= 10.2b5 diff --git a/build/pkgs/sage_setup/install-requires.txt b/build/pkgs/sage_setup/install-requires.txt index 47b2c4f5114..42ef7aa07f9 100644 --- a/build/pkgs/sage_setup/install-requires.txt +++ b/build/pkgs/sage_setup/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sage-setup ~= 10.2b4 +sage-setup ~= 10.2b5 diff --git a/build/pkgs/sage_sws2rst/install-requires.txt b/build/pkgs/sage_sws2rst/install-requires.txt index 24c91a42bc8..8c3cca6a40a 100644 --- a/build/pkgs/sage_sws2rst/install-requires.txt +++ b/build/pkgs/sage_sws2rst/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sage-sws2rst ~= 10.2b4 +sage-sws2rst ~= 10.2b5 diff --git a/build/pkgs/sagelib/install-requires.txt b/build/pkgs/sagelib/install-requires.txt index c9421c52882..981188d32ca 100644 --- a/build/pkgs/sagelib/install-requires.txt +++ b/build/pkgs/sagelib/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-standard ~= 10.2b4 +sagemath-standard ~= 10.2b5 diff --git a/build/pkgs/sagemath_bliss/install-requires.txt b/build/pkgs/sagemath_bliss/install-requires.txt index aa08f5ad67b..eaf783b463d 100644 --- a/build/pkgs/sagemath_bliss/install-requires.txt +++ b/build/pkgs/sagemath_bliss/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-bliss ~= 10.2b4 +sagemath-bliss ~= 10.2b5 diff --git a/build/pkgs/sagemath_categories/install-requires.txt b/build/pkgs/sagemath_categories/install-requires.txt index 44e7a2644ea..6f9c7bce7d6 100644 --- a/build/pkgs/sagemath_categories/install-requires.txt +++ b/build/pkgs/sagemath_categories/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-categories ~= 10.2b4 +sagemath-categories ~= 10.2b5 diff --git a/build/pkgs/sagemath_coxeter3/install-requires.txt b/build/pkgs/sagemath_coxeter3/install-requires.txt index d4445a7d2cc..79e17497045 100644 --- a/build/pkgs/sagemath_coxeter3/install-requires.txt +++ b/build/pkgs/sagemath_coxeter3/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-coxeter3 ~= 10.2b4 +sagemath-coxeter3 ~= 10.2b5 diff --git a/build/pkgs/sagemath_environment/install-requires.txt b/build/pkgs/sagemath_environment/install-requires.txt index ad55353e259..5e7993d773b 100644 --- a/build/pkgs/sagemath_environment/install-requires.txt +++ b/build/pkgs/sagemath_environment/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-environment ~= 10.2b4 +sagemath-environment ~= 10.2b5 diff --git a/build/pkgs/sagemath_mcqd/install-requires.txt b/build/pkgs/sagemath_mcqd/install-requires.txt index 9c355b8fdda..cf817314c08 100644 --- a/build/pkgs/sagemath_mcqd/install-requires.txt +++ b/build/pkgs/sagemath_mcqd/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-mcqd ~= 10.2b4 +sagemath-mcqd ~= 10.2b5 diff --git a/build/pkgs/sagemath_meataxe/install-requires.txt b/build/pkgs/sagemath_meataxe/install-requires.txt index 812b0cbc6b6..97b6bb48c9c 100644 --- a/build/pkgs/sagemath_meataxe/install-requires.txt +++ b/build/pkgs/sagemath_meataxe/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-meataxe ~= 10.2b4 +sagemath-meataxe ~= 10.2b5 diff --git a/build/pkgs/sagemath_objects/install-requires.txt b/build/pkgs/sagemath_objects/install-requires.txt index c2307b7b379..99b0309ee9e 100644 --- a/build/pkgs/sagemath_objects/install-requires.txt +++ b/build/pkgs/sagemath_objects/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-objects ~= 10.2b4 +sagemath-objects ~= 10.2b5 diff --git a/build/pkgs/sagemath_repl/install-requires.txt b/build/pkgs/sagemath_repl/install-requires.txt index 5eb4dbf6a98..9dab260bb52 100644 --- a/build/pkgs/sagemath_repl/install-requires.txt +++ b/build/pkgs/sagemath_repl/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-repl ~= 10.2b4 +sagemath-repl ~= 10.2b5 diff --git a/build/pkgs/sagemath_sirocco/install-requires.txt b/build/pkgs/sagemath_sirocco/install-requires.txt index 145cd4dff71..7b67a383e35 100644 --- a/build/pkgs/sagemath_sirocco/install-requires.txt +++ b/build/pkgs/sagemath_sirocco/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-sirocco ~= 10.2b4 +sagemath-sirocco ~= 10.2b5 diff --git a/build/pkgs/sagemath_tdlib/install-requires.txt b/build/pkgs/sagemath_tdlib/install-requires.txt index c8f62a5455b..a5f0a2240a4 100644 --- a/build/pkgs/sagemath_tdlib/install-requires.txt +++ b/build/pkgs/sagemath_tdlib/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-tdlib ~= 10.2b4 +sagemath-tdlib ~= 10.2b5 diff --git a/pkgs/sage-conf/VERSION.txt b/pkgs/sage-conf/VERSION.txt index 90b7024a582..7786f0e63e4 100644 --- a/pkgs/sage-conf/VERSION.txt +++ b/pkgs/sage-conf/VERSION.txt @@ -1 +1 @@ -10.2.beta4 +10.2.beta5 diff --git a/pkgs/sage-conf_pypi/VERSION.txt b/pkgs/sage-conf_pypi/VERSION.txt index 90b7024a582..7786f0e63e4 100644 --- a/pkgs/sage-conf_pypi/VERSION.txt +++ b/pkgs/sage-conf_pypi/VERSION.txt @@ -1 +1 @@ -10.2.beta4 +10.2.beta5 diff --git a/pkgs/sage-docbuild/VERSION.txt b/pkgs/sage-docbuild/VERSION.txt index 90b7024a582..7786f0e63e4 100644 --- a/pkgs/sage-docbuild/VERSION.txt +++ b/pkgs/sage-docbuild/VERSION.txt @@ -1 +1 @@ -10.2.beta4 +10.2.beta5 diff --git a/pkgs/sage-setup/VERSION.txt b/pkgs/sage-setup/VERSION.txt index 90b7024a582..7786f0e63e4 100644 --- a/pkgs/sage-setup/VERSION.txt +++ b/pkgs/sage-setup/VERSION.txt @@ -1 +1 @@ -10.2.beta4 +10.2.beta5 diff --git a/pkgs/sage-sws2rst/VERSION.txt b/pkgs/sage-sws2rst/VERSION.txt index 90b7024a582..7786f0e63e4 100644 --- a/pkgs/sage-sws2rst/VERSION.txt +++ b/pkgs/sage-sws2rst/VERSION.txt @@ -1 +1 @@ -10.2.beta4 +10.2.beta5 diff --git a/pkgs/sagemath-bliss/VERSION.txt b/pkgs/sagemath-bliss/VERSION.txt index 90b7024a582..7786f0e63e4 100644 --- a/pkgs/sagemath-bliss/VERSION.txt +++ b/pkgs/sagemath-bliss/VERSION.txt @@ -1 +1 @@ -10.2.beta4 +10.2.beta5 diff --git a/pkgs/sagemath-categories/VERSION.txt b/pkgs/sagemath-categories/VERSION.txt index 90b7024a582..7786f0e63e4 100644 --- a/pkgs/sagemath-categories/VERSION.txt +++ b/pkgs/sagemath-categories/VERSION.txt @@ -1 +1 @@ -10.2.beta4 +10.2.beta5 diff --git a/pkgs/sagemath-coxeter3/VERSION.txt b/pkgs/sagemath-coxeter3/VERSION.txt index 90b7024a582..7786f0e63e4 100644 --- a/pkgs/sagemath-coxeter3/VERSION.txt +++ b/pkgs/sagemath-coxeter3/VERSION.txt @@ -1 +1 @@ -10.2.beta4 +10.2.beta5 diff --git a/pkgs/sagemath-environment/VERSION.txt b/pkgs/sagemath-environment/VERSION.txt index 90b7024a582..7786f0e63e4 100644 --- a/pkgs/sagemath-environment/VERSION.txt +++ b/pkgs/sagemath-environment/VERSION.txt @@ -1 +1 @@ -10.2.beta4 +10.2.beta5 diff --git a/pkgs/sagemath-mcqd/VERSION.txt b/pkgs/sagemath-mcqd/VERSION.txt index 90b7024a582..7786f0e63e4 100644 --- a/pkgs/sagemath-mcqd/VERSION.txt +++ b/pkgs/sagemath-mcqd/VERSION.txt @@ -1 +1 @@ -10.2.beta4 +10.2.beta5 diff --git a/pkgs/sagemath-meataxe/VERSION.txt b/pkgs/sagemath-meataxe/VERSION.txt index 90b7024a582..7786f0e63e4 100644 --- a/pkgs/sagemath-meataxe/VERSION.txt +++ b/pkgs/sagemath-meataxe/VERSION.txt @@ -1 +1 @@ -10.2.beta4 +10.2.beta5 diff --git a/pkgs/sagemath-objects/VERSION.txt b/pkgs/sagemath-objects/VERSION.txt index 90b7024a582..7786f0e63e4 100644 --- a/pkgs/sagemath-objects/VERSION.txt +++ b/pkgs/sagemath-objects/VERSION.txt @@ -1 +1 @@ -10.2.beta4 +10.2.beta5 diff --git a/pkgs/sagemath-repl/VERSION.txt b/pkgs/sagemath-repl/VERSION.txt index 90b7024a582..7786f0e63e4 100644 --- a/pkgs/sagemath-repl/VERSION.txt +++ b/pkgs/sagemath-repl/VERSION.txt @@ -1 +1 @@ -10.2.beta4 +10.2.beta5 diff --git a/pkgs/sagemath-sirocco/VERSION.txt b/pkgs/sagemath-sirocco/VERSION.txt index 90b7024a582..7786f0e63e4 100644 --- a/pkgs/sagemath-sirocco/VERSION.txt +++ b/pkgs/sagemath-sirocco/VERSION.txt @@ -1 +1 @@ -10.2.beta4 +10.2.beta5 diff --git a/pkgs/sagemath-tdlib/VERSION.txt b/pkgs/sagemath-tdlib/VERSION.txt index 90b7024a582..7786f0e63e4 100644 --- a/pkgs/sagemath-tdlib/VERSION.txt +++ b/pkgs/sagemath-tdlib/VERSION.txt @@ -1 +1 @@ -10.2.beta4 +10.2.beta5 diff --git a/src/VERSION.txt b/src/VERSION.txt index 90b7024a582..7786f0e63e4 100644 --- a/src/VERSION.txt +++ b/src/VERSION.txt @@ -1 +1 @@ -10.2.beta4 +10.2.beta5 diff --git a/src/bin/sage-version.sh b/src/bin/sage-version.sh index dda770f38b1..3bc82696a62 100644 --- a/src/bin/sage-version.sh +++ b/src/bin/sage-version.sh @@ -4,6 +4,6 @@ # which stops "setup.py develop" from rewriting it as a Python file. : # This file is auto-generated by the sage-update-version script, do not edit! -SAGE_VERSION='10.2.beta4' -SAGE_RELEASE_DATE='2023-09-24' -SAGE_VERSION_BANNER='SageMath version 10.2.beta4, Release Date: 2023-09-24' +SAGE_VERSION='10.2.beta5' +SAGE_RELEASE_DATE='2023-09-27' +SAGE_VERSION_BANNER='SageMath version 10.2.beta5, Release Date: 2023-09-27' diff --git a/src/sage/version.py b/src/sage/version.py index 6aec9425110..659a7932e4e 100644 --- a/src/sage/version.py +++ b/src/sage/version.py @@ -1,5 +1,5 @@ # Sage version information for Python scripts # This file is auto-generated by the sage-update-version script, do not edit! -version = '10.2.beta4' -date = '2023-09-24' -banner = 'SageMath version 10.2.beta4, Release Date: 2023-09-24' +version = '10.2.beta5' +date = '2023-09-27' +banner = 'SageMath version 10.2.beta5, Release Date: 2023-09-27'