Skip to content

Commit

Permalink
sagemathgh-36403: Fix AttributeError doctests when output includes a …
Browse files Browse the repository at this point in the history
…suggestion (part of python 3.12 support)

    
In python 3.12, attribute errors add a suggestion at the end of the
usual error message ("Did you mean ...?").

We add ... at the end of these doctest outputs to fix it.

This PR is split in two commits:

 - The bulk of the changes, in the first commit, was obtained
automatically with:
    ```
    git grep -l "AttributeError:" src | xargs sed -ie \
        's/^ *\(AttributeError: .*\)\?has no attribute.*$/&.../'
    ```
 - The second commit includes 3 changes not catched by the sed pattern
above.

Since this changes a lot of files and is bound to get old, I'd
appreciate a quick review + merge to avoid trouble (the PR is long but
almost trivial and the review should be easy).

I'll soon make a separate PR (on top of this one) with the rest of the
support python 3.12 changes, which are maybe not so trivial but much
shorter than this one.

Related: sagemath#36181

@mkoeppe 🙏
    
URL: sagemath#36403
Reported by: Gonzalo Tornaría
Reviewer(s): Matthias Köppe
  • Loading branch information
Release Manager committed Oct 11, 2023
2 parents 293e4db + 5e34da9 commit e716501
Show file tree
Hide file tree
Showing 64 changed files with 116 additions and 116 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 @@ -1223,7 +1223,7 @@ However, only "elementary" construction functors have a rank::
sage: (Fract*Poly).rank
Traceback (most recent call last):
...
AttributeError: 'CompositeConstructionFunctor' object has no attribute 'rank'
AttributeError: 'CompositeConstructionFunctor' object has no attribute 'rank'...

.. end of output
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -318,15 +318,15 @@ http://docs.python.org/library/ for a complete list. ::
sage: e.__dict__
Traceback (most recent call last):
...
AttributeError: 'sage.rings.integer.Integer' object has no attribute '__dict__'
AttributeError: 'sage.rings.integer.Integer' object has no attribute '__dict__'...

sage: id4 = SymmetricGroup(4).one()
sage: type(id4)
<class 'sage.groups.perm_gps.permgroup_element.SymmetricGroupElement'>
sage: id4.__dict__
Traceback (most recent call last):
...
AttributeError: 'sage.groups.perm_gps.permgroup_element.SymmetricGroupElement' object has no attribute '__dict__'
AttributeError: 'sage.groups.perm_gps.permgroup_element.SymmetricGroupElement' object has no attribute '__dict__'...

.. note::

Expand Down
2 changes: 1 addition & 1 deletion src/sage/algebras/cluster_algebra.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@
sage: (t*s).g_vector()
Traceback (most recent call last):
...
AttributeError: 'ClusterAlgebra_with_category.element_class' object has no attribute 'g_vector'
AttributeError: 'ClusterAlgebra_with_category.element_class' object has no attribute 'g_vector'...
sage: A = ClusterAlgebra(['A', 2], principal_coefficients=True)
sage: A.explore_to_depth(infinity)
sage: s = A.cluster_variable((0, -1)); s
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ class WeylLieConformalAlgebra(LieConformalAlgebraWithStructureCoefficients):
sage: alpha0.degree()
Traceback (most recent call last):
...
AttributeError: 'WeylLieConformalAlgebra_with_category.element_class' object has no attribute 'degree'
AttributeError: 'WeylLieConformalAlgebra_with_category.element_class' object has no attribute 'degree'...
TESTS::
Expand Down
2 changes: 1 addition & 1 deletion src/sage/algebras/steenrod/steenrod_algebra.py
Original file line number Diff line number Diff line change
Expand Up @@ -1080,7 +1080,7 @@ def homogeneous_component(self, n):
sage: a.antipode() # not defined
Traceback (most recent call last):
...
AttributeError: 'CombinatorialFreeModule_with_category.element_class' object has no attribute 'antipode'
AttributeError: 'CombinatorialFreeModule_with_category.element_class' object has no attribute 'antipode'...
sage: A(a).antipode() # convert to elt of A, then compute antipode
Sq(2,1) + Sq(5)
Expand Down
2 changes: 1 addition & 1 deletion src/sage/categories/category.py
Original file line number Diff line number Diff line change
Expand Up @@ -2129,7 +2129,7 @@ def _with_axioms(self, axioms):
sage: Semigroups().Inverse()
Traceback (most recent call last):
...
AttributeError: 'Semigroups_with_category' object has no attribute 'Inverse'
AttributeError: 'Semigroups_with_category' object has no attribute 'Inverse'...
sage: Semigroups()._with_axioms(["Inverse"])
Category of semigroups
Expand Down
4 changes: 2 additions & 2 deletions src/sage/categories/category_with_axiom.py
Original file line number Diff line number Diff line change
Expand Up @@ -554,7 +554,7 @@ class from the base category class::
sage: Magmas.Unital.Associative
Traceback (most recent call last):
...
AttributeError: type object 'Magmas.Unital' has no attribute 'Associative'
AttributeError: type object 'Magmas.Unital' has no attribute 'Associative'...
The purpose of this section is to explain the design of the code
layout and the rationale for this mismatch.
Expand Down Expand Up @@ -769,7 +769,7 @@ def _(): return LazyImport('sage.categories.rngs', 'Rngs', at_startup=True)
sage: Semirings().NoZeroDivisors()
Traceback (most recent call last):
...
AttributeError: 'Semirings_with_category' object has no attribute 'NoZeroDivisors'
AttributeError: 'Semirings_with_category' object has no attribute 'NoZeroDivisors'...
Concretely, this is to be implemented by defining the new axiom in the
(``SubcategoryMethods`` nested class of the) appropriate category with
Expand Down
6 changes: 3 additions & 3 deletions src/sage/categories/enumerated_sets.py
Original file line number Diff line number Diff line change
Expand Up @@ -610,7 +610,7 @@ def _list_from_iterator(self):
sage: (QQ^2).list() # indirect test # needs sage.modules
Traceback (most recent call last):
...
AttributeError: 'FreeModule_ambient_field_with_category' object has no attribute 'list'
AttributeError: 'FreeModule_ambient_field_with_category' object has no attribute 'list'...
Here we test that for an object that does not know whether it
is finite or not. Calling ``x.list()`` simply tries to create
Expand All @@ -622,11 +622,11 @@ def _list_from_iterator(self):
sage: Q.is_finite()
Traceback (most recent call last):
...
AttributeError: 'QuotientRing_generic_with_category' object has no attribute 'is_finite'
AttributeError: 'QuotientRing_generic_with_category' object has no attribute 'is_finite'...
sage: Q.list() # indirect test
Traceback (most recent call last):
...
AttributeError: 'QuotientRing_generic_with_category' object has no attribute 'list'
AttributeError: 'QuotientRing_generic_with_category' object has no attribute 'list'...
Here is another example. We artificially create a version of
the ring of integers that does not know whether it is finite
Expand Down
2 changes: 1 addition & 1 deletion src/sage/categories/examples/sets_cat.py
Original file line number Diff line number Diff line change
Expand Up @@ -619,7 +619,7 @@ class PrimeNumbers_Facade(PrimeNumbers_Abstract):
sage: pf.next()
Traceback (most recent call last):
...
AttributeError: 'sage.rings.integer.Integer' object has no attribute 'next'
AttributeError: 'sage.rings.integer.Integer' object has no attribute 'next'...
unlike in the other implementations::
Expand Down
2 changes: 1 addition & 1 deletion src/sage/categories/homset.py
Original file line number Diff line number Diff line change
Expand Up @@ -632,7 +632,7 @@ def __init__(self, X, Y, category=None, base=None, check=True):
sage: H = MyHomset(X, Y, category=1, base = ZZ, check = False)
Traceback (most recent call last):
...
AttributeError: 'sage.rings.integer.Integer' object has no attribute 'Homsets'
AttributeError: 'sage.rings.integer.Integer' object has no attribute 'Homsets'...
sage: P.<t> = ZZ[]
sage: f = P.hom([1/2*t])
sage: f.parent().domain()
Expand Down
2 changes: 1 addition & 1 deletion src/sage/categories/modules_with_basis.py
Original file line number Diff line number Diff line change
Expand Up @@ -2456,7 +2456,7 @@ def apply_multilinear_morphism(self, f, codomain=None):
sage: tensor([a, b]).apply_multilinear_morphism(f) # needs sage.modules
Traceback (most recent call last):
...
AttributeError: 'int' object has no attribute 'parent'
AttributeError: 'int' object has no attribute 'parent'...
Here we consider an example where the codomain is a
module with basis with a different base ring::
Expand Down
2 changes: 1 addition & 1 deletion src/sage/categories/monoids.py
Original file line number Diff line number Diff line change
Expand Up @@ -556,7 +556,7 @@ def algebra_generators(self):
Traceback (most recent call last):
...
AttributeError: 'IntegerModMonoid_with_category' object
has no attribute 'monoid_generators'
has no attribute 'monoid_generators'...
sage: Z12.semigroup_generators()
Family (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)
sage: Z12.algebra(QQ).algebra_generators() # needs sage.modules
Expand Down
2 changes: 1 addition & 1 deletion src/sage/combinat/finite_state_machine.py
Original file line number Diff line number Diff line change
Expand Up @@ -1835,7 +1835,7 @@ def __getstate__(self):
sage: T1.transitions
Traceback (most recent call last):
...
AttributeError: 'FSMState' object has no attribute 'transitions'
AttributeError: 'FSMState' object has no attribute 'transitions'...
sage: A1 = loads(dumps(A))
sage: all(A.state(j) == A1.state(j) for j in [0, 1])
True
Expand Down
2 changes: 1 addition & 1 deletion src/sage/combinat/growth.py
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,7 @@
sage: GrowthDiagram(RulePascal(), [3,1,2])
Traceback (most recent call last):
...
AttributeError: 'RulePascal' object has no attribute 'forward_rule'
AttributeError: 'RulePascal' object has no attribute 'forward_rule'...
We now re-implement the rule where we provide the dual graded graphs::
Expand Down
2 changes: 1 addition & 1 deletion src/sage/combinat/integer_lists/lists.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ def __getattr__(self, name):
sage: L.foo
Traceback (most recent call last):
...
AttributeError: 'NoneType' object has no attribute 'foo'
AttributeError: 'NoneType' object has no attribute 'foo'...
"""
return getattr(self.backend, name)

Expand Down
2 changes: 1 addition & 1 deletion src/sage/combinat/posets/posets.py
Original file line number Diff line number Diff line change
Expand Up @@ -8825,7 +8825,7 @@ def is_induced_subposet(self, other):
sage: Poset().is_induced_subposet('junk')
Traceback (most recent call last):
...
AttributeError: 'str' object has no attribute 'subposet'
AttributeError: 'str' object has no attribute 'subposet'...
"""
if (not self._is_facade or (isinstance(other, FinitePoset) and
not other._is_facade)):
Expand Down
2 changes: 1 addition & 1 deletion src/sage/cpython/debug.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ def getattr_debug(obj, name, default=_no_default):
sage: _ = getattr_debug(1, "foo")
Traceback (most recent call last):
...
AttributeError: 'sage.rings.integer.Integer' object has no attribute 'foo'
AttributeError: 'sage.rings.integer.Integer' object has no attribute 'foo'...
sage: _ = getattr_debug(1, "foo", "xyz")
getattr_debug(obj=1, name='foo'):
type(obj) = <class 'sage.rings.integer.Integer'>
Expand Down
22 changes: 11 additions & 11 deletions src/sage/cpython/getattr.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,12 @@ cdef class AttributeErrorMessage:
sage: 1.bla #indirect doctest
Traceback (most recent call last):
...
AttributeError: 'sage.rings.integer.Integer' object has no attribute 'bla'
AttributeError: 'sage.rings.integer.Integer' object has no attribute 'bla'...
sage: x = polygen(ZZ, 'x')
sage: QQ[x].gen().bla # needs sage.libs.flint
Traceback (most recent call last):
...
AttributeError: 'sage.rings.polynomial.polynomial_rational_flint.Polynomial_rational_flint' object has no attribute 'bla'
AttributeError: 'sage.rings.polynomial.polynomial_rational_flint.Polynomial_rational_flint' object has no attribute 'bla'...
::
Expand Down Expand Up @@ -144,7 +144,7 @@ cpdef raw_getattr(obj, name):
sage: raw_getattr(X, "attr")
Traceback (most recent call last):
...
AttributeError: '...' object has no attribute 'attr'
AttributeError: '...' object has no attribute 'attr'...
sage: x = X()
sage: raw_getattr(x, "prop")
<property object at ...>
Expand Down Expand Up @@ -173,7 +173,7 @@ cpdef raw_getattr(obj, name):
sage: raw_getattr(Y, "attr")
Traceback (most recent call last):
...
AttributeError: '...' object has no attribute 'attr'
AttributeError: '...' object has no attribute 'attr'...
sage: y = Y()
sage: raw_getattr(y, "prop")
<property object at ...>
Expand Down Expand Up @@ -278,7 +278,7 @@ cpdef getattr_from_other_class(self, cls, name):
sage: getattr_from_other_class(1, A, "lazy_attribute")
Traceback (most recent call last):
...
AttributeError: 'sage.rings.integer.Integer' object has no attribute 'lazy_attribute'
AttributeError: 'sage.rings.integer.Integer' object has no attribute 'lazy_attribute'...
The integer ring is a parent, so, lazy attributes work::
Expand All @@ -289,7 +289,7 @@ cpdef getattr_from_other_class(self, cls, name):
sage: getattr_from_other_class(17, A, "lazy_attribute")
Traceback (most recent call last):
...
AttributeError: 'sage.rings.integer.Integer' object has no attribute 'lazy_attribute'
AttributeError: 'sage.rings.integer.Integer' object has no attribute 'lazy_attribute'...
In general, descriptors are not yet well supported, because they
often do not accept to be cheated with the type of their instance::
Expand All @@ -305,7 +305,7 @@ cpdef getattr_from_other_class(self, cls, name):
sage: getattr_from_other_class(1, A, "__weakref__")
Traceback (most recent call last):
...
AttributeError: 'sage.rings.integer.Integer' object has no attribute '__weakref__'
AttributeError: 'sage.rings.integer.Integer' object has no attribute '__weakref__'...
This was caught by :trac:`8296` for which we do a couple more tests::
Expand All @@ -314,7 +314,7 @@ cpdef getattr_from_other_class(self, cls, name):
sage: 1.__weakref__
Traceback (most recent call last):
...
AttributeError: 'sage.rings.integer.Integer' object has no attribute '__weakref__'
AttributeError: 'sage.rings.integer.Integer' object has no attribute '__weakref__'...
sage: n = 1
sage: ip = get_ipython() # not tested: only works in interactive shell
Expand All @@ -329,7 +329,7 @@ cpdef getattr_from_other_class(self, cls, name):
sage: getattr_from_other_class(1, A, "__call__")
Traceback (most recent call last):
...
AttributeError: 'sage.rings.integer.Integer' object has no attribute '__call__'
AttributeError: 'sage.rings.integer.Integer' object has no attribute '__call__'...
TESTS:
Expand All @@ -339,14 +339,14 @@ cpdef getattr_from_other_class(self, cls, name):
sage: getattr_from_other_class(1, type, "__name__")
Traceback (most recent call last):
...
AttributeError: 'sage.rings.integer.Integer' object has no attribute '__name__'
AttributeError: 'sage.rings.integer.Integer' object has no attribute '__name__'...
Non-strings as "name" are handled gracefully::
sage: getattr_from_other_class(1, type, None)
Traceback (most recent call last):
...
AttributeError: 'sage.rings.integer.Integer' object has no attribute None
AttributeError: 'sage.rings.integer.Integer' object has no attribute None...
"""
if not isinstance(cls, type):
raise TypeError(f"{cls!r} is not a type")
Expand Down
8 changes: 4 additions & 4 deletions src/sage/crypto/classical.py
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,7 @@ def rank_by_chi_square(self, C, pdict):
sage: A.rank_by_chi_square("", Plist)
Traceback (most recent call last):
...
AttributeError: 'str' object has no attribute 'parent'
AttributeError: 'str' object has no attribute 'parent'...
sage: A.rank_by_chi_square(A.encoding(""), Plist)
Traceback (most recent call last):
...
Expand Down Expand Up @@ -703,7 +703,7 @@ def rank_by_squared_differences(self, C, pdict):
sage: A.rank_by_squared_differences("", Plist)
Traceback (most recent call last):
...
AttributeError: 'str' object has no attribute 'parent'
AttributeError: 'str' object has no attribute 'parent'...
sage: A.rank_by_squared_differences(A.encoding(""), Plist)
Traceback (most recent call last):
...
Expand Down Expand Up @@ -2114,7 +2114,7 @@ def rank_by_chi_square(self, C, pdict):
sage: S.rank_by_chi_square("", Pdict)
Traceback (most recent call last):
...
AttributeError: 'str' object has no attribute 'parent'
AttributeError: 'str' object has no attribute 'parent'...
sage: S.rank_by_chi_square(S.encoding(""), Pdict)
Traceback (most recent call last):
...
Expand Down Expand Up @@ -2351,7 +2351,7 @@ def rank_by_squared_differences(self, C, pdict):
sage: S.rank_by_squared_differences("", Pdict)
Traceback (most recent call last):
...
AttributeError: 'str' object has no attribute 'parent'
AttributeError: 'str' object has no attribute 'parent'...
sage: S.rank_by_squared_differences(S.encoding(""), Pdict)
Traceback (most recent call last):
...
Expand Down
2 changes: 1 addition & 1 deletion src/sage/crypto/mq/mpolynomialsystemgenerator.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ def sbox(self):
sage: msg.sbox()
Traceback (most recent call last):
...
AttributeError: '<class 'sage.crypto.mq.mpolynomialsystemgenerator.MPolynomialSystemGenerator'>' object has no attribute '_sbox'
AttributeError: '<class 'sage.crypto.mq.mpolynomialsystemgenerator.MPolynomialSystemGenerator'>' object has no attribute '_sbox'...
"""
return self._sbox

Expand Down
8 changes: 4 additions & 4 deletions src/sage/data_structures/bitset.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -967,7 +967,7 @@ cdef class FrozenBitset:
sage: None | FrozenBitset('10101')
Traceback (most recent call last):
...
AttributeError: 'NoneType' object has no attribute '_union'
AttributeError: 'NoneType' object has no attribute '_union'...
"""
return self._union(other)

Expand Down Expand Up @@ -1037,7 +1037,7 @@ cdef class FrozenBitset:
sage: None & FrozenBitset("101011")
Traceback (most recent call last):
...
AttributeError: 'NoneType' object has no attribute 'intersection'
AttributeError: 'NoneType' object has no attribute 'intersection'...
"""
return self.intersection(other)

Expand Down Expand Up @@ -1106,7 +1106,7 @@ cdef class FrozenBitset:
sage: None - FrozenBitset('10101')
Traceback (most recent call last):
...
AttributeError: 'NoneType' object has no attribute 'difference'
AttributeError: 'NoneType' object has no attribute 'difference'...
"""
return self.difference(other)

Expand Down Expand Up @@ -1179,7 +1179,7 @@ cdef class FrozenBitset:
sage: None ^^ FrozenBitset('11111' * 10)
Traceback (most recent call last):
...
AttributeError: 'NoneType' object has no attribute 'symmetric_difference'
AttributeError: 'NoneType' object has no attribute 'symmetric_difference'...
"""
return self.symmetric_difference(other)

Expand Down
2 changes: 1 addition & 1 deletion src/sage/doctest/reporting.py
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ def report(self, source, timeout, return_code, results, output, pid=None):
sage: DTR.report(None, None, None, None, None)
Traceback (most recent call last):
...
AttributeError: 'NoneType' object has no attribute 'basename'
AttributeError: 'NoneType' object has no attribute 'basename'...
The only-errors mode does not output anything on success::
Expand Down
4 changes: 2 additions & 2 deletions src/sage/dynamics/finite_dynamical_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ class DiscreteDynamicalSystem(SageObject, metaclass=ClasscallMetaclass):
sage: D.inverse_evolution()(4)
Traceback (most recent call last):
...
AttributeError: 'DiscreteDynamicalSystem' object has no attribute 'inverse_evolution'
AttributeError: 'DiscreteDynamicalSystem' object has no attribute 'inverse_evolution'...
sage: D.orbit(3)
[3, 5, 1]
Expand All @@ -252,7 +252,7 @@ class DiscreteDynamicalSystem(SageObject, metaclass=ClasscallMetaclass):
sage: D.inverse_evolution()(4)
Traceback (most recent call last):
...
AttributeError: 'DiscreteDynamicalSystem' object has no attribute 'inverse_evolution'
AttributeError: 'DiscreteDynamicalSystem' object has no attribute 'inverse_evolution'...
sage: D.orbit(3)
[3, 5, 1]
Expand Down
2 changes: 1 addition & 1 deletion src/sage/geometry/cone.py
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ def Cone(rays, lattice=None, check=True, normalize=True):
sage: Cone([(1,0), (0,1)], check=False, normalize=False)
Traceback (most recent call last):
...
AttributeError: 'tuple' object has no attribute 'parent'
AttributeError: 'tuple' object has no attribute 'parent'...
You can construct different "not" cones: not full-dimensional, not
strictly convex, not containing any rays::
Expand Down
Loading

0 comments on commit e716501

Please sign in to comment.