Skip to content

Commit

Permalink
sagemathgh-36109: Prepare for updating Cython to 3.0.0
Browse files Browse the repository at this point in the history
    
<!-- ^^^^^
Please provide a concise, informative and self-explanatory title.
Don't put issue numbers in there, do this in the PR body below.
For example, instead of "Fixes sagemath#1234" use "Introduce new method to
calculate 1+1"
-->
<!-- Describe your changes here in detail -->

<!-- Why is this change required? What problem does it solve? -->
<!-- If this PR resolves an open issue, please link to it here. For
example "Fixes sagemath#12345". -->
<!-- If your change requires a documentation PR, please link it
appropriately. -->

Here are the changes needed to get Sage compiled with Cython 3. This PR
contains changes that do not break compatibility with old Cython, so
they can be merged without actually upgrading Cython.

Part of sagemath#29863.

### 📝 Checklist

<!-- Put an `x` in all the boxes that apply. -->
<!-- If your change requires a documentation PR, please link it
appropriately -->
<!-- If you're unsure about any of these, don't hesitate to ask. We're
here to help! -->
<!-- Feel free to remove irrelevant items. -->

- [x] The title is concise, informative, and self-explanatory.
- [x] The description explains in detail what this PR is about.
- [x] I have linked a relevant issue or discussion.

### ⌛ Dependencies

<!-- List all open PRs that this PR logically depends on
- sagemath#12345: short description why this is a dependency
- sagemath#34567: ...
-->

<!-- If you're unsure about any of these, don't hesitate to ask. We're
here to help! -->
    
URL: sagemath#36109
Reported by: Yutao Yuan
Reviewer(s): Gonzalo Tornaría, Yutao Yuan
  • Loading branch information
Release Manager committed Aug 31, 2023
2 parents 22446cb + 4b85613 commit f8b3a91
Show file tree
Hide file tree
Showing 127 changed files with 1,478 additions and 1,467 deletions.
2 changes: 1 addition & 1 deletion src/doc/en/thematic_tutorials/coercion_and_categories.rst
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,6 @@ 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',
'__ideal_monoid',
'__iter__',
'__len__',
'__rxor__',
Expand All @@ -119,6 +118,7 @@ This base class provides a lot more methods than a general parent::
'_default_category',
'_gens',
'_ideal_class_',
'_ideal_monoid',
'_latex_names',
'_list',
'_one_element',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ http://docs.python.org/library/ for a complete list. ::
sage: el
bla
sage: el.__dict__
{'__custom_name': 'bla', 'value': 42}
{'_SageObject__custom_name': 'bla', 'value': 42}

Lots of Sage objects are not Python objects but compiled Cython
objects. Python sees them as builtin objects and you do not have
Expand Down
5 changes: 2 additions & 3 deletions src/sage/algebras/letterplace/free_algebra_letterplace.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,15 @@ cdef class FreeAlgebra_letterplace_libsingular():
cdef ring* _lp_ring
cdef MPolynomialRing_libsingular _commutative_ring
cdef MPolynomialRing_libsingular _lp_ring_internal
cdef object __ngens
cdef object _ngens

cdef class FreeAlgebra_letterplace(Algebra):
cdef MPolynomialRing_libsingular _commutative_ring
cdef MPolynomialRing_libsingular _current_ring
cdef int _degbound
cdef int __ngens
cdef int _ngens
cdef int _nb_slackvars
cdef object __monoid
cdef public object __custom_name
cdef str exponents_to_string(self, E)
cdef str exponents_to_latex(self, E)
cdef tuple _degrees
34 changes: 17 additions & 17 deletions src/sage/algebras/letterplace/free_algebra_letterplace.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ cdef class FreeAlgebra_letterplace(Algebra):
"""
if not isinstance(R, MPolynomialRing_libsingular):
raise TypeError("a letterplace algebra must be provided by a polynomial ring of type %s" % MPolynomialRing_libsingular)
self.__ngens = R.ngens()
self._ngens = R.ngens()
if degrees is None:
varnames = R.variable_names()
self._nb_slackvars = 0
Expand All @@ -269,12 +269,12 @@ cdef class FreeAlgebra_letterplace(Algebra):
self._current_ring = make_letterplace_ring(R, 1)
self._degbound = 1
if degrees is None:
self._degrees = tuple([int(1)] * self.__ngens)
self._degrees = tuple([int(1)] * self._ngens)
else:
if (not isinstance(degrees, (tuple, list))) \
or len(degrees) != self.__ngens - self._nb_slackvars \
or len(degrees) != self._ngens - self._nb_slackvars \
or any(i <= 0 for i in degrees):
raise TypeError("the generator degrees must be given by a list or tuple of %d positive integers" % (self.__ngens - 1))
raise TypeError("the generator degrees must be given by a list or tuple of %d positive integers" % (self._ngens - 1))
self._degrees = tuple([int(i) for i in degrees])
self.set_degbound(max(self._degrees))
self._populate_coercion_lists_(coerce_list=[base_ring])
Expand Down Expand Up @@ -305,7 +305,7 @@ cdef class FreeAlgebra_letterplace(Algebra):
sage: F.ngens()
3
"""
return self.__ngens - self._nb_slackvars
return self._ngens - self._nb_slackvars

def gen(self, i):
"""
Expand All @@ -327,17 +327,17 @@ cdef class FreeAlgebra_letterplace(Algebra):
sage: F.gen(2)
c
"""
if i >= self.__ngens - self._nb_slackvars:
raise ValueError("this free algebra only has %d generators" % (self.__ngens - self._nb_slackvars))
if i >= self._ngens - self._nb_slackvars:
raise ValueError("this free algebra only has %d generators" % (self._ngens - self._nb_slackvars))
if self._gens is not None:
return self._gens[i]
deg = self._degrees[i]
# self.set_degbound(deg)
p = self._current_ring.gen(i)
cdef int n
cdef int j = self.__ngens - 1
cdef int j = self._ngens - 1
for n in range(1, deg):
j += self.__ngens
j += self._ngens
p *= self._current_ring.gen(j)
return FreeAlgebraElement_letterplace(self, p)

Expand Down Expand Up @@ -413,7 +413,7 @@ cdef class FreeAlgebra_letterplace(Algebra):
sage: FreeAlgebra(QQ, implementation='letterplace', names=['x']).is_commutative()
True
"""
return self.__ngens - self._nb_slackvars <= 1
return self._ngens - self._nb_slackvars <= 1

def is_field(self, proof=True):
"""
Expand All @@ -430,7 +430,7 @@ cdef class FreeAlgebra_letterplace(Algebra):
sage: F.is_field()
False
"""
return (not (self.__ngens - self._nb_slackvars)) and self._base.is_field(proof=proof)
return (not (self._ngens - self._nb_slackvars)) and self._base.is_field(proof=proof)

def _repr_(self):
"""
Expand All @@ -446,7 +446,7 @@ cdef class FreeAlgebra_letterplace(Algebra):
sage: F
Free Associative Unital Algebra on 3 generators (x, y, z) over Rational Field
"""
return "Free Associative Unital Algebra on %d generators %s over %s" % (self.__ngens - self._nb_slackvars, self.gens(), self._base)
return "Free Associative Unital Algebra on %d generators %s over %s" % (self._ngens - self._nb_slackvars, self.gens(), self._base)

def _latex_(self):
r"""
Expand Down Expand Up @@ -586,7 +586,7 @@ cdef class FreeAlgebra_letterplace(Algebra):
generated free abelian monoid.
In principle, this is correct, but it is not implemented, yet.>
"""
cdef int ngens = self.__ngens
cdef int ngens = self._ngens
cdef int nblocks = len(E) // ngens
cdef int i, j, base, exp, var_ind
cdef list out = []
Expand Down Expand Up @@ -618,7 +618,7 @@ cdef class FreeAlgebra_letterplace(Algebra):
sage: latex(-(a*b*(z+1)-c)^2) # indirect doctest
\left(2 z + 1\right) a b a b + \left(z + 1\right) a b c + \left(z + 1\right) c a b - c c
"""
cdef int ngens = self.__ngens
cdef int ngens = self._ngens
cdef int nblocks = len(E) // ngens
cdef int i, j, base, exp, var_ind
cdef list out = []
Expand Down Expand Up @@ -678,7 +678,7 @@ cdef class FreeAlgebra_letterplace(Algebra):
cdef list out = []
C = self.current_ring()
cdef FreeAlgebraElement_letterplace x
ngens = self.__ngens
ngens = self._ngens
cdef list G = [C(x._poly) for x in g]
from sage.groups.perm_gps.permgroup_named import CyclicPermutationGroup
CG = CyclicPermutationGroup(C.ngens())
Expand Down Expand Up @@ -811,7 +811,7 @@ cdef class FreeAlgebra_letterplace(Algebra):
l = len(e)
break
cdef dict out = {}
self.set_degbound(l // self.__ngens)
self.set_degbound(l // self._ngens)
cdef Py_ssize_t n = self._current_ring.ngens()
for e, c in D.iteritems():
out[tuple(e) + (0,) * (n - l)] = c
Expand Down Expand Up @@ -896,7 +896,7 @@ cdef class FreeAlgebra_letterplace_libsingular():
self._commutative_ring = commutative_ring

def __init__(self, commutative_ring, degbound):
self.__ngens = commutative_ring.ngens() * degbound
self._ngens = commutative_ring.ngens() * degbound

def __dealloc__(self):
r"""
Expand Down
32 changes: 16 additions & 16 deletions src/sage/algebras/quatalg/quaternion_algebra_element.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -1700,15 +1700,15 @@ cdef class QuaternionAlgebraElement_number_field(QuaternionAlgebraElement_abstra
x, y, z, w = v
cdef NumberFieldElement a = <NumberFieldElement>(parent._base(parent._a))
cdef NumberFieldElement b = <NumberFieldElement>(parent._base(parent._b))
fmpz_poly_set_ZZX(self.x, (<NumberFieldElement>x).__numerator)
fmpz_poly_set_ZZX(self.y, (<NumberFieldElement>y).__numerator)
fmpz_poly_set_ZZX(self.z, (<NumberFieldElement>z).__numerator)
fmpz_poly_set_ZZX(self.w, (<NumberFieldElement>w).__numerator)
fmpz_poly_set_ZZX(self.x, (<NumberFieldElement>x)._numerator)
fmpz_poly_set_ZZX(self.y, (<NumberFieldElement>y)._numerator)
fmpz_poly_set_ZZX(self.z, (<NumberFieldElement>z)._numerator)
fmpz_poly_set_ZZX(self.w, (<NumberFieldElement>w)._numerator)

ZZ_to_mpz(T1, &(<NumberFieldElement>x).__denominator)
ZZ_to_mpz(T2, &(<NumberFieldElement>y).__denominator)
ZZ_to_mpz(t3, &(<NumberFieldElement>z).__denominator)
ZZ_to_mpz(t4, &(<NumberFieldElement>w).__denominator)
ZZ_to_mpz(T1, &(<NumberFieldElement>x)._denominator)
ZZ_to_mpz(T2, &(<NumberFieldElement>y)._denominator)
ZZ_to_mpz(t3, &(<NumberFieldElement>z)._denominator)
ZZ_to_mpz(t4, &(<NumberFieldElement>w)._denominator)

mpz_lcm(self.d, T1, T2)
mpz_lcm(self.d, self.d, t3)
Expand All @@ -1724,10 +1724,10 @@ cdef class QuaternionAlgebraElement_number_field(QuaternionAlgebraElement_abstra
fmpz_poly_scalar_mul_mpz(self.z, self.z, t3)
fmpz_poly_scalar_mul_mpz(self.w, self.w, t4)

fmpz_poly_set_ZZX(self.a, a.__numerator) # we will assume that the denominator of a and b are 1
fmpz_poly_set_ZZX(self.b, b.__numerator)
fmpz_poly_set_ZZX(self.a, a._numerator) # we will assume that the denominator of a and b are 1
fmpz_poly_set_ZZX(self.b, b._numerator)

fmpz_poly_set_ZZX(self.modulus, (<NumberFieldElement>x).__fld_numerator.x) # and same for the modulus
fmpz_poly_set_ZZX(self.modulus, (<NumberFieldElement>x)._fld_numerator.x) # and same for the modulus

def __getitem__(self, int i):
"""
Expand Down Expand Up @@ -1756,17 +1756,17 @@ cdef class QuaternionAlgebraElement_number_field(QuaternionAlgebraElement_abstra
cdef NumberFieldElement item = el._new()

if i == 0:
fmpz_poly_get_ZZX(item.__numerator, self.x)
fmpz_poly_get_ZZX(item._numerator, self.x)
elif i == 1:
fmpz_poly_get_ZZX(item.__numerator, self.y)
fmpz_poly_get_ZZX(item._numerator, self.y)
elif i == 2:
fmpz_poly_get_ZZX(item.__numerator, self.z)
fmpz_poly_get_ZZX(item._numerator, self.z)
elif i == 3:
fmpz_poly_get_ZZX(item.__numerator, self.w)
fmpz_poly_get_ZZX(item._numerator, self.w)
else:
raise IndexError("quaternion element index out of range")

mpz_to_ZZ(&item.__denominator, self.d)
mpz_to_ZZ(&item._denominator, self.d)

return item

Expand Down
2 changes: 1 addition & 1 deletion src/sage/categories/hopf_algebras_with_basis.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class HopfAlgebrasWithBasis(CategoryWithAxiom_over_base_ring):
sage: A = C.example(); A # needs sage.groups
An example of Hopf algebra with basis: the group algebra of the
Dihedral group of order 6 as a permutation group over Rational Field
sage: A.__custom_name = "A" # needs sage.groups
sage: A.rename("A") # needs sage.groups
sage: A.category() # needs sage.groups
Category of finite dimensional hopf algebras with basis over Rational Field
Expand Down
4 changes: 2 additions & 2 deletions src/sage/categories/modules_with_basis.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ class ModulesWithBasis(CategoryWithAxiom_over_base_ring):
Let `X` and `Y` be two modules with basis. We can build `Hom(X,Y)`::
sage: X = CombinatorialFreeModule(QQ, [1,2]); X.__custom_name = "X" # needs sage.modules
sage: Y = CombinatorialFreeModule(QQ, [3,4]); Y.__custom_name = "Y" # needs sage.modules
sage: X = CombinatorialFreeModule(QQ, [1,2]); X.rename("X") # needs sage.modules
sage: Y = CombinatorialFreeModule(QQ, [3,4]); Y.rename("Y") # needs sage.modules
sage: H = Hom(X, Y); H # needs sage.modules
Set of Morphisms from X to Y
in Category of finite dimensional vector spaces with basis over Rational Field
Expand Down
9 changes: 4 additions & 5 deletions src/sage/combinat/cluster_complex.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,10 +222,6 @@ def __init__(self, W, k, coxeter_element, algorithm):
self._W = W
self._w0 = w
self._k = k
if k == 1:
self.__custom_name = 'Cluster complex'
else:
self.__custom_name = 'Multi-cluster complex'

self.set_immutable()

Expand Down Expand Up @@ -271,7 +267,10 @@ def _repr_(self):
sage: ClusterComplex(['A', 2])._repr_()
"Cluster complex of type ['A', 2] with 5 vertices and 5 facets"
"""
name = self.__custom_name
if self._k == 1:
name = 'Cluster complex'
else:
name = 'Multi-cluster complex'
name += (' of type %s with %s vertices and %s facets'
% (self.cartan_type(), len(self.vertices()),
len(self._facets)))
Expand Down
2 changes: 1 addition & 1 deletion src/sage/combinat/integer_lists/base.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ cdef class IntegerListsBackend():
cdef readonly min_part, max_part
cdef readonly min_slope, max_slope
cdef readonly Envelope floor, ceiling
cdef public dict __cached_methods # Support cached_method
cdef public dict _cached_methods # Support cached_method
1 change: 0 additions & 1 deletion src/sage/combinat/subword_complex.py
Original file line number Diff line number Diff line change
Expand Up @@ -1131,7 +1131,6 @@ def __init__(self, Q, w, algorithm="inductive"):
SimplicialComplex.__init__(self, maximal_faces=Fs,
maximality_check=False,
category=cat)
self.__custom_name = 'Subword complex'
self._W = W
try:
T = W.coxeter_matrix().coxeter_type()
Expand Down
10 changes: 10 additions & 0 deletions src/sage/cpython/cython_metaclass.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,16 @@ static CYTHON_INLINE int Sage_PyType_Ready(PyTypeObject* t)
if (r < 0)
return r;

#if PY_VERSION_HEX >= 0x03050000
// Cython 3 sets Py_TPFLAGS_HEAPTYPE before calling PyType_Ready,
// and resets just after the call. We need to reset it earlier,
// since otherwise the call to metaclass.__init__ below may have
// illegal memory accesses.
// See also:
// https://github.com/cython/cython/issues/3603
t->tp_flags &= ~Py_TPFLAGS_HEAPTYPE;
#endif

/* Set or get metaclass (the type of t) */
PyTypeObject* metaclass;

Expand Down
9 changes: 8 additions & 1 deletion src/sage/cpython/cython_metaclass.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,16 @@ file if you are using one).
In the extension type (a.k.a. ``cdef class``) for which you want to
define a metaclass, define a method ``__getmetaclass__`` with a single
unused argument. This method should return a type to be used as
unused argument, and turn off the Cython directive
``always_allow_keywords``. This method should return a type to be used as
metaclass:
.. code-block:: cython
cimport cython
cimport sage.cpython.cython_metaclass
cdef class MyCustomType():
@cython.always_allow_keywords(False)
def __getmetaclass__(_):
from foo import MyMetaclass
return MyMetaclass
Expand Down Expand Up @@ -63,8 +66,10 @@ EXAMPLES::
sage: cython( # needs sage.misc.cython
....: '''
....: cimport cython
....: cimport sage.cpython.cython_metaclass
....: cdef class MyCustomType():
....: @cython.always_allow_keywords(False)
....: def __getmetaclass__(_):
....: class MyMetaclass(type):
....: def __init__(*args):
Expand Down Expand Up @@ -101,8 +106,10 @@ returns a non-type::
sage: cython( # needs sage.misc.cython
....: '''
....: cimport cython
....: cimport sage.cpython.cython_metaclass
....: cdef class MyCustomType():
....: @cython.always_allow_keywords(False)
....: def __getmetaclass__(_):
....: return 2
....: ''')
Expand Down
2 changes: 1 addition & 1 deletion src/sage/cpython/getattr.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ cpdef getattr_from_other_class(self, cls, name):
Caveat: lazy attributes work with extension types only
if they allow attribute assignment or have a public attribute
``__cached_methods`` of type ``<dict>``. This condition
``_cached_methods`` of type ``<dict>``. This condition
is satisfied, e.g., by any class that is derived from
:class:`Parent`::
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ from .polyhedron_face_lattice cimport PolyhedronFaceLattice

@cython.final
cdef class CombinatorialPolyhedron(SageObject):
cdef public dict __cached_methods
cdef public dict _cached_methods

# Do not assume any of those attributes to be initialized, use the corresponding methods instead.
cdef tuple _Vrep # the names of VRep, if they exist
Expand Down
2 changes: 1 addition & 1 deletion src/sage/groups/perm_gps/permgroup_element.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement):
cpdef PermutationGroupElement _generate_new_GAP(self, old)
cpdef _gap_list(self)
cpdef domain(self)
cdef public __custom_name
cdef public _SageObject__custom_name
cpdef list _act_on_list_on_position(self, list x)
cpdef ClonableIntArray _act_on_array_on_position(self, ClonableIntArray x)
cpdef ETuple _act_on_etuple_on_position(self, ETuple x)
7 changes: 2 additions & 5 deletions src/sage/interfaces/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -1169,11 +1169,8 @@ def __repr__(self):
s = cr
else:
s = self._repr_()
if self._name in s:
try:
s = s.replace(self._name, getattr(self, '__custom_name'))
except AttributeError:
pass
if self._name in s and self.get_custom_name() is not None:
s = s.replace(self._name, self.get_custom_name())
if cr:
self._cached_repr = s
return s
Expand Down
4 changes: 2 additions & 2 deletions src/sage/interfaces/singular.py
Original file line number Diff line number Diff line change
Expand Up @@ -1400,8 +1400,8 @@ def _repr_(self):
"""
s = super(SingularElement, self)._repr_()
if self._name in s:
if (not hasattr(self, "__custom_name")) and self.type() == 'matrix':
s = self.parent().eval('pmat(%s,20)'%(self.name()))
if self.get_custom_name() is None and self.type() == 'matrix':
s = self.parent().eval('pmat(%s,20)' % (self.name()))
return s

def __copy__(self):
Expand Down
Loading

0 comments on commit f8b3a91

Please sign in to comment.