Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add debug option to check category MRO #39170

Draft
wants to merge 29 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
df6293f
Add _make_named_class_key for FilteredModulesCategory
user202729 Dec 18, 2024
c6b3b55
Fix a few things
user202729 Dec 19, 2024
c14e958
Fix tests
user202729 Dec 19, 2024
8511d7e
Add debug option to check category MRO
user202729 Dec 19, 2024
449e97c
More debug checking
user202729 Dec 19, 2024
2c64aee
Harmless refactors
user202729 Dec 20, 2024
d240553
Better printing of debug.test_category_graph failure
user202729 Dec 20, 2024
a611e34
Hope it works
user202729 Dec 20, 2024
cd602d2
Unrelated bugfix
user202729 Dec 20, 2024
131714e
Too many cached function with no argument returning None, cannot rais…
user202729 Dec 20, 2024
a4f9de6
Band-aid
user202729 Dec 20, 2024
67c2486
Fix tests
user202729 Dec 20, 2024
ff90f0c
Remove debug feature and loosen up the check
user202729 Dec 20, 2024
6f35e05
Unbreak string representation of category_with_axiom
user202729 Dec 20, 2024
1b4dbca
Revert a test, revert default category of SR to CommutativeRings()
user202729 Dec 20, 2024
2f49994
Remove debug.test_nonrecursive_cachefunc
user202729 Dec 21, 2024
6419749
Consistently use getattr([category], name) for _make_named_class_key
user202729 Dec 21, 2024
ba7d5d9
Add back the docstring
user202729 Dec 21, 2024
84bda72
Mark a test as long time
user202729 Dec 21, 2024
5933e47
Move make_named_class_key back to filteredmodules
user202729 Dec 21, 2024
939d609
Fix tests accordingly
user202729 Dec 21, 2024
182f33f
Oops, forget one check (cause all the trouble?)
user202729 Dec 21, 2024
eee57f2
Revert "Remove debug.test_nonrecursive_cachefunc"
user202729 Dec 21, 2024
3781c65
Give up
user202729 Dec 21, 2024
79fe1f3
Merge remote-tracking branch 'upstream/develop' into category-mro-test
user202729 Dec 23, 2024
fbaa1a7
Try again?
user202729 Dec 23, 2024
97229b1
Re-enable a test
user202729 Dec 23, 2024
8a2e17f
Merge remote-tracking branch 'upstream/develop' into category-mro-test
user202729 Jan 5, 2025
9013cd7
Merge remote-tracking branch 'upstream/develop' into category-mro-test
user202729 Jan 22, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 10 additions & 21 deletions src/sage/categories/bimodules.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@

EXAMPLES::

sage: Bimodules(QQ, ZZ)

Check failure on line 35 in src/sage/categories/bimodules.py

View workflow job for this annotation

GitHub Actions / test-new

Failed example:

Failed example:: Exception raised: Traceback (most recent call last): File "sage/misc/cachefunc.pyx", line 1005, in sage.misc.cachefunc.CachedFunction.__call__ return self.cache[k] File "sage/misc/weak_dict.pyx", line 709, in sage.misc.weak_dict.WeakValueDictionary.__getitem__ raise KeyError(k) KeyError: ((<class 'sage.categories.bimodules.Bimodules'>, Rational Field, Integer Ring), ()) During handling of the above exception, another exception occurred: Traceback (most recent call last): File "sage/misc/cachefunc.pyx", line 1005, in sage.misc.cachefunc.CachedFunction.__call__ return self.cache[k] File "sage/misc/weak_dict.pyx", line 709, in sage.misc.weak_dict.WeakValueDictionary.__getitem__ raise KeyError(k) KeyError: ((<class 'sage.categories.left_modules.LeftModules'>, Rational Field), ()) During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/sage/src/sage/doctest/forker.py", line 728, in _run self.compile_and_execute(example, compiler, test.globs) File "/sage/src/sage/doctest/forker.py", line 1152, in compile_and_execute exec(compiled, globs) File "<doctest sage.categories.bimodules.Bimodules[0]>", line 1, in <module> Bimodules(QQ, ZZ) File "sage/misc/classcall_metaclass.pyx", line 321, in sage.misc.classcall_metaclass.ClasscallMetaclass.__call__ return cls.classcall(cls, *args, **kwds) File "/sage/src/sage/categories/category.py", line 456, in __classcall__ return super().__classcall__(cls, *args, **options) File "sage/misc/cachefunc.pyx", line 1010, in sage.misc.cachefunc.CachedFunction.__call__ w = self.f(*args, **kwds) File "/sage/src/sage/structure/unique_representation.py", line 1113, in __classcall__ return super().__classcall__(cls, *args, **options) File "/sage/src/sage/structure/unique_representation.py", line 597, in __classcall__ instance = typecall(cls, *args, **options) File "sage/misc/classcall_metaclass.pyx", line 472, in sage.misc.classcall_metaclass.typecall return (<PyTypeObject*>type).tp_call(cls, args, kwds) File "/sage/src/sage/categories/bimodules.py", line 60, in __init__ Category.__init__(self) File "/sage/src/sage/categories/category.py", line 483, in __init__ (self.__class__, self.subcategory_class, ), File "sage/misc/lazy_attribute.pyx", line 126, in sage.misc.lazy_attribute._lazy_attribute.__get__ result = self.f(a) File "/sage/src/sage/categories/category.py", line 1640, in subcategory_class _ = self._all_super_categories File "sage/misc/lazy_attribute.pyx", line 126, in sage.misc.lazy_attribute._lazy_attribute.__get__ result = self.f(a) File "/sage/src/sage/categories/category.py", line 861, in _all_super_categories for cat in self._super_categories] + File "sage/misc/lazy_attribute.pyx", line 126, in sage.misc.lazy_attribute._lazy_attribute.__get__ result = self.f(a) File "/sage/src/sage/categories/category.py", line 1016, in _super_categories return sorted(_flatten_categories(self.super_categories(), JoinCategory), key=category_sort_key, reverse=True) File "/sage/src/sage/categories/bimodules.py", line 168, in super_categories return [LeftModules(R), RightModules(S)] File "sage/misc/classcall_metaclass.pyx", line 321, in sage.misc.classcall_metaclass.ClasscallMetaclass.__call__ return cls.classcall(cls, *args, **kwds) File "/sage/src/sage/categories/category.py", line 456, in __classcall__ return super().__classcall__(cls, *args, **options) File "sage/misc/cachefunc.pyx", line 1010, in sage.misc.cachefunc.CachedFunction.__call__ w = self.f(*args, **kwds) File "/sage/src/sage/structure/unique_representation.py", line 1113, in __classcall__ return super().__classcall__(cls, *args, **options) File "/sage/src/sage/structure/unique_representation.py", line 597, in __classcall__ instance = typecall(cls, *args, **options) File "sage/misc/classcall_metaclass.pyx", line 472, in sage.misc.classcall_metaclass.typecall return (<PyTypeObject*>type).tp_call(cls, args, kwds)
Category of bimodules over Rational Field on the left and Integer Ring on the right
sage: Bimodules(QQ, ZZ).super_categories()

Check failure on line 37 in src/sage/categories/bimodules.py

View workflow job for this annotation

GitHub Actions / test-new

Failed example:

Failed example:: Exception raised: Traceback (most recent call last): File "sage/misc/cachefunc.pyx", line 1005, in sage.misc.cachefunc.CachedFunction.__call__ return self.cache[k] File "sage/misc/weak_dict.pyx", line 709, in sage.misc.weak_dict.WeakValueDictionary.__getitem__ raise KeyError(k) KeyError: ((<class 'sage.categories.bimodules.Bimodules'>, Rational Field, Integer Ring), ()) During handling of the above exception, another exception occurred: Traceback (most recent call last): File "sage/misc/cachefunc.pyx", line 1005, in sage.misc.cachefunc.CachedFunction.__call__ return self.cache[k] File "sage/misc/weak_dict.pyx", line 709, in sage.misc.weak_dict.WeakValueDictionary.__getitem__ raise KeyError(k) KeyError: ((<class 'sage.categories.left_modules.LeftModules'>, Rational Field), ()) During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/sage/src/sage/doctest/forker.py", line 728, in _run self.compile_and_execute(example, compiler, test.globs) File "/sage/src/sage/doctest/forker.py", line 1152, in compile_and_execute exec(compiled, globs) File "<doctest sage.categories.bimodules.Bimodules[1]>", line 1, in <module> Bimodules(QQ, ZZ).super_categories() File "sage/misc/classcall_metaclass.pyx", line 321, in sage.misc.classcall_metaclass.ClasscallMetaclass.__call__ return cls.classcall(cls, *args, **kwds) File "/sage/src/sage/categories/category.py", line 456, in __classcall__ return super().__classcall__(cls, *args, **options) File "sage/misc/cachefunc.pyx", line 1010, in sage.misc.cachefunc.CachedFunction.__call__ w = self.f(*args, **kwds) File "/sage/src/sage/structure/unique_representation.py", line 1113, in __classcall__ return super().__classcall__(cls, *args, **options) File "/sage/src/sage/structure/unique_representation.py", line 597, in __classcall__ instance = typecall(cls, *args, **options) File "sage/misc/classcall_metaclass.pyx", line 472, in sage.misc.classcall_metaclass.typecall return (<PyTypeObject*>type).tp_call(cls, args, kwds) File "/sage/src/sage/categories/bimodules.py", line 60, in __init__ Category.__init__(self) File "/sage/src/sage/categories/category.py", line 483, in __init__ (self.__class__, self.subcategory_class, ), File "sage/misc/lazy_attribute.pyx", line 126, in sage.misc.lazy_attribute._lazy_attribute.__get__ result = self.f(a) File "/sage/src/sage/categories/category.py", line 1640, in subcategory_class _ = self._all_super_categories File "sage/misc/lazy_attribute.pyx", line 126, in sage.misc.lazy_attribute._lazy_attribute.__get__ result = self.f(a) File "/sage/src/sage/categories/category.py", line 861, in _all_super_categories for cat in self._super_categories] + File "sage/misc/lazy_attribute.pyx", line 126, in sage.misc.lazy_attribute._lazy_attribute.__get__ result = self.f(a) File "/sage/src/sage/categories/category.py", line 1016, in _super_categories return sorted(_flatten_categories(self.super_categories(), JoinCategory), key=category_sort_key, reverse=True) File "/sage/src/sage/categories/bimodules.py", line 168, in super_categories return [LeftModules(R), RightModules(S)] File "sage/misc/classcall_metaclass.pyx", line 321, in sage.misc.classcall_metaclass.ClasscallMetaclass.__call__ return cls.classcall(cls, *args, **kwds) File "/sage/src/sage/categories/category.py", line 456, in __classcall__ return super().__classcall__(cls, *args, **options) File "sage/misc/cachefunc.pyx", line 1010, in sage.misc.cachefunc.CachedFunction.__call__ w = self.f(*args, **kwds) File "/sage/src/sage/structure/unique_representation.py", line 1113, in __classcall__ return super().__classcall__(cls, *args, **options) File "/sage/src/sage/structure/unique_representation.py", line 597, in __classcall__ instance = typecall(cls, *args, **options) File "sage/misc/classcall_metaclass.pyx", line 472, in sage.misc.classcall_metaclass.typecall return (<PyTypeObject*>type).tp_cal
[Category of left modules over Rational Field, Category of right modules over Integer Ring]
"""

Expand All @@ -44,8 +44,8 @@

EXAMPLES::

sage: C = Bimodules(QQ, ZZ)

Check failure on line 47 in src/sage/categories/bimodules.py

View workflow job for this annotation

GitHub Actions / test-new

Failed example:

Failed example:: Exception raised: Traceback (most recent call last): File "sage/misc/cachefunc.pyx", line 1005, in sage.misc.cachefunc.CachedFunction.__call__ return self.cache[k] File "sage/misc/weak_dict.pyx", line 709, in sage.misc.weak_dict.WeakValueDictionary.__getitem__ raise KeyError(k) KeyError: ((<class 'sage.categories.bimodules.Bimodules'>, Rational Field, Integer Ring), ()) During handling of the above exception, another exception occurred: Traceback (most recent call last): File "sage/misc/cachefunc.pyx", line 1005, in sage.misc.cachefunc.CachedFunction.__call__ return self.cache[k] File "sage/misc/weak_dict.pyx", line 709, in sage.misc.weak_dict.WeakValueDictionary.__getitem__ raise KeyError(k) KeyError: ((<class 'sage.categories.left_modules.LeftModules'>, Rational Field), ()) During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/sage/src/sage/doctest/forker.py", line 728, in _run self.compile_and_execute(example, compiler, test.globs) File "/sage/src/sage/doctest/forker.py", line 1152, in compile_and_execute exec(compiled, globs) File "<doctest sage.categories.bimodules.Bimodules.__init__[0]>", line 1, in <module> C = Bimodules(QQ, ZZ) File "sage/misc/classcall_metaclass.pyx", line 321, in sage.misc.classcall_metaclass.ClasscallMetaclass.__call__ return cls.classcall(cls, *args, **kwds) File "/sage/src/sage/categories/category.py", line 456, in __classcall__ return super().__classcall__(cls, *args, **options) File "sage/misc/cachefunc.pyx", line 1010, in sage.misc.cachefunc.CachedFunction.__call__ w = self.f(*args, **kwds) File "/sage/src/sage/structure/unique_representation.py", line 1113, in __classcall__ return super().__classcall__(cls, *args, **options) File "/sage/src/sage/structure/unique_representation.py", line 597, in __classcall__ instance = typecall(cls, *args, **options) File "sage/misc/classcall_metaclass.pyx", line 472, in sage.misc.classcall_metaclass.typecall return (<PyTypeObject*>type).tp_call(cls, args, kwds) File "/sage/src/sage/categories/bimodules.py", line 60, in __init__ Category.__init__(self) File "/sage/src/sage/categories/category.py", line 483, in __init__ (self.__class__, self.subcategory_class, ), File "sage/misc/lazy_attribute.pyx", line 126, in sage.misc.lazy_attribute._lazy_attribute.__get__ result = self.f(a) File "/sage/src/sage/categories/category.py", line 1640, in subcategory_class _ = self._all_super_categories File "sage/misc/lazy_attribute.pyx", line 126, in sage.misc.lazy_attribute._lazy_attribute.__get__ result = self.f(a) File "/sage/src/sage/categories/category.py", line 861, in _all_super_categories for cat in self._super_categories] + File "sage/misc/lazy_attribute.pyx", line 126, in sage.misc.lazy_attribute._lazy_attribute.__get__ result = self.f(a) File "/sage/src/sage/categories/category.py", line 1016, in _super_categories return sorted(_flatten_categories(self.super_categories(), JoinCategory), key=category_sort_key, reverse=True) File "/sage/src/sage/categories/bimodules.py", line 168, in super_categories return [LeftModules(R), RightModules(S)] File "sage/misc/classcall_metaclass.pyx", line 321, in sage.misc.classcall_metaclass.ClasscallMetaclass.__call__ return cls.classcall(cls, *args, **kwds) File "/sage/src/sage/categories/category.py", line 456, in __classcall__ return super().__classcall__(cls, *args, **options) File "sage/misc/cachefunc.pyx", line 1010, in sage.misc.cachefunc.CachedFunction.__call__ w = self.f(*args, **kwds) File "/sage/src/sage/structure/unique_representation.py", line 1113, in __classcall__ return super().__classcall__(cls, *args, **options) File "/sage/src/sage/structure/unique_representation.py", line 597, in __classcall__ instance = typecall(cls, *args, **options) File "sage/misc/classcall_metaclass.pyx", line 472, in sage.misc.classcall_metaclass.typecall return (<PyTypeObject*>type).tp_call(cls,
sage: TestSuite(C).run()

Check failure on line 48 in src/sage/categories/bimodules.py

View workflow job for this annotation

GitHub Actions / test-new

Failed example:

Failed example:: Exception raised: Traceback (most recent call last): File "/sage/src/sage/doctest/forker.py", line 728, in _run self.compile_and_execute(example, compiler, test.globs) File "/sage/src/sage/doctest/forker.py", line 1152, in compile_and_execute exec(compiled, globs) File "<doctest sage.categories.bimodules.Bimodules.__init__[1]>", line 1, in <module> TestSuite(C).run() NameError: name 'C' is not defined
"""
if not (left_base in Rings() or
(isinstance(left_base, Category)
Expand Down Expand Up @@ -74,36 +74,25 @@

EXAMPLES::

sage: Bimodules(QQ,ZZ)._make_named_class_key('parent_class')

Check failure on line 77 in src/sage/categories/bimodules.py

View workflow job for this annotation

GitHub Actions / test-new

Failed example:

Failed example:: Exception raised: Traceback (most recent call last): File "sage/misc/cachefunc.pyx", line 1005, in sage.misc.cachefunc.CachedFunction.__call__ return self.cache[k] File "sage/misc/weak_dict.pyx", line 709, in sage.misc.weak_dict.WeakValueDictionary.__getitem__ raise KeyError(k) KeyError: ((<class 'sage.categories.bimodules.Bimodules'>, Rational Field, Integer Ring), ()) During handling of the above exception, another exception occurred: Traceback (most recent call last): File "sage/misc/cachefunc.pyx", line 1005, in sage.misc.cachefunc.CachedFunction.__call__ return self.cache[k] File "sage/misc/weak_dict.pyx", line 709, in sage.misc.weak_dict.WeakValueDictionary.__getitem__ raise KeyError(k) KeyError: ((<class 'sage.categories.left_modules.LeftModules'>, Rational Field), ()) During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/sage/src/sage/doctest/forker.py", line 728, in _run self.compile_and_execute(example, compiler, test.globs) File "/sage/src/sage/doctest/forker.py", line 1152, in compile_and_execute exec(compiled, globs) File "<doctest sage.categories.bimodules.Bimodules._make_named_class_key[0]>", line 1, in <module> Bimodules(QQ,ZZ)._make_named_class_key('parent_class') File "sage/misc/classcall_metaclass.pyx", line 321, in sage.misc.classcall_metaclass.ClasscallMetaclass.__call__ return cls.classcall(cls, *args, **kwds) File "/sage/src/sage/categories/category.py", line 456, in __classcall__ return super().__classcall__(cls, *args, **options) File "sage/misc/cachefunc.pyx", line 1010, in sage.misc.cachefunc.CachedFunction.__call__ w = self.f(*args, **kwds) File "/sage/src/sage/structure/unique_representation.py", line 1113, in __classcall__ return super().__classcall__(cls, *args, **options) File "/sage/src/sage/structure/unique_representation.py", line 597, in __classcall__ instance = typecall(cls, *args, **options) File "sage/misc/classcall_metaclass.pyx", line 472, in sage.misc.classcall_metaclass.typecall return (<PyTypeObject*>type).tp_call(cls, args, kwds) File "/sage/src/sage/categories/bimodules.py", line 60, in __init__ Category.__init__(self) File "/sage/src/sage/categories/category.py", line 483, in __init__ (self.__class__, self.subcategory_class, ), File "sage/misc/lazy_attribute.pyx", line 126, in sage.misc.lazy_attribute._lazy_attribute.__get__ result = self.f(a) File "/sage/src/sage/categories/category.py", line 1640, in subcategory_class _ = self._all_super_categories File "sage/misc/lazy_attribute.pyx", line 126, in sage.misc.lazy_attribute._lazy_attribute.__get__ result = self.f(a) File "/sage/src/sage/categories/category.py", line 861, in _all_super_categories for cat in self._super_categories] + File "sage/misc/lazy_attribute.pyx", line 126, in sage.misc.lazy_attribute._lazy_attribute.__get__ result = self.f(a) File "/sage/src/sage/categories/category.py", line 1016, in _super_categories return sorted(_flatten_categories(self.super_categories(), JoinCategory), key=category_sort_key, reverse=True) File "/sage/src/sage/categories/bimodules.py", line 168, in super_categories return [LeftModules(R), RightModules(S)] File "sage/misc/classcall_metaclass.pyx", line 321, in sage.misc.classcall_metaclass.ClasscallMetaclass.__call__ return cls.classcall(cls, *args, **kwds) File "/sage/src/sage/categories/category.py", line 456, in __classcall__ return super().__classcall__(cls, *args, **options) File "sage/misc/cachefunc.pyx", line 1010, in sage.misc.cachefunc.CachedFunction.__call__ w = self.f(*args, **kwds) File "/sage/src/sage/structure/unique_representation.py", line 1113, in __classcall__ return super().__classcall__(cls, *args, **options) File "/sage/src/sage/structure/unique_representation.py", line 597, in __classcall__ instance = typecall(cls, *args, **options) File "sage/misc/classcall_metaclass.pyx", line 472, in sage.misc.classcall_metaclass.typecall
(Join of Category of number fields
and Category of quotient fields
and Category of metric spaces,
Join of Category of Dedekind domains
and Category of euclidean domains
and Category of noetherian rings
and Category of infinite enumerated sets
and Category of metric spaces)
(<class 'sage.categories.category.JoinCategory.parent_class'>,
<class 'sage.categories.category.JoinCategory.parent_class'>)


sage: Bimodules(Fields(), ZZ)._make_named_class_key('element_class')

Check failure on line 82 in src/sage/categories/bimodules.py

View workflow job for this annotation

GitHub Actions / test-new

Failed example:

Failed example:: Exception raised: Traceback (most recent call last): File "sage/misc/cachefunc.pyx", line 1005, in sage.misc.cachefunc.CachedFunction.__call__ return self.cache[k] File "sage/misc/weak_dict.pyx", line 709, in sage.misc.weak_dict.WeakValueDictionary.__getitem__ raise KeyError(k) KeyError: ((<class 'sage.categories.bimodules.Bimodules'>, Category of fields, Integer Ring), ()) During handling of the above exception, another exception occurred: Traceback (most recent call last): File "sage/misc/cachefunc.pyx", line 1005, in sage.misc.cachefunc.CachedFunction.__call__ return self.cache[k] File "sage/misc/weak_dict.pyx", line 709, in sage.misc.weak_dict.WeakValueDictionary.__getitem__ raise KeyError(k) KeyError: ((<class 'sage.categories.right_modules.RightModules'>, Integer Ring), ()) During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/sage/src/sage/doctest/forker.py", line 728, in _run self.compile_and_execute(example, compiler, test.globs) File "/sage/src/sage/doctest/forker.py", line 1152, in compile_and_execute exec(compiled, globs) File "<doctest sage.categories.bimodules.Bimodules._make_named_class_key[1]>", line 1, in <module> Bimodules(Fields(), ZZ)._make_named_class_key('element_class') File "sage/misc/classcall_metaclass.pyx", line 321, in sage.misc.classcall_metaclass.ClasscallMetaclass.__call__ return cls.classcall(cls, *args, **kwds) File "/sage/src/sage/categories/category.py", line 456, in __classcall__ return super().__classcall__(cls, *args, **options) File "sage/misc/cachefunc.pyx", line 1010, in sage.misc.cachefunc.CachedFunction.__call__ w = self.f(*args, **kwds) File "/sage/src/sage/structure/unique_representation.py", line 1113, in __classcall__ return super().__classcall__(cls, *args, **options) File "/sage/src/sage/structure/unique_representation.py", line 597, in __classcall__ instance = typecall(cls, *args, **options) File "sage/misc/classcall_metaclass.pyx", line 472, in sage.misc.classcall_metaclass.typecall return (<PyTypeObject*>type).tp_call(cls, args, kwds) File "/sage/src/sage/categories/bimodules.py", line 60, in __init__ Category.__init__(self) File "/sage/src/sage/categories/category.py", line 483, in __init__ (self.__class__, self.subcategory_class, ), File "sage/misc/lazy_attribute.pyx", line 126, in sage.misc.lazy_attribute._lazy_attribute.__get__ result = self.f(a) File "/sage/src/sage/categories/category.py", line 1640, in subcategory_class _ = self._all_super_categories File "sage/misc/lazy_attribute.pyx", line 126, in sage.misc.lazy_attribute._lazy_attribute.__get__ result = self.f(a) File "/sage/src/sage/categories/category.py", line 861, in _all_super_categories for cat in self._super_categories] + File "sage/misc/lazy_attribute.pyx", line 126, in sage.misc.lazy_attribute._lazy_attribute.__get__ result = self.f(a) File "/sage/src/sage/categories/category.py", line 1016, in _super_categories return sorted(_flatten_categories(self.super_categories(), JoinCategory), key=category_sort_key, reverse=True) File "/sage/src/sage/categories/bimodules.py", line 168, in super_categories return [LeftModules(R), RightModules(S)] File "sage/misc/classcall_metaclass.pyx", line 321, in sage.misc.classcall_metaclass.ClasscallMetaclass.__call__ return cls.classcall(cls, *args, **kwds) File "/sage/src/sage/categories/category.py", line 456, in __classcall__ return super().__classcall__(cls, *args, **options) File "sage/misc/cachefunc.pyx", line 1010, in sage.misc.cachefunc.CachedFunction.__call__ w = self.f(*args, **kwds) File "/sage/src/sage/structure/unique_representation.py", line 1113, in __classcall__ return super().__classcall__(cls, *args, **options) File "/sage/src/sage/structure/unique_representation.py", line 597, in __classcall__ instance = typecall(cls, *args, **options) File "sage/misc/classcall_metaclass.pyx", line 472, in sage.misc.classcall_metacl
(Category of fields,
Join of Category of Dedekind domains
and Category of euclidean domains
and Category of noetherian rings
and Category of infinite enumerated sets
and Category of metric spaces)
(<class 'sage.categories.fields.Fields.element_class'>,
<class 'sage.categories.category.JoinCategory.element_class'>)

sage: Bimodules(QQ, Rings())._make_named_class_key('element_class')

Check failure on line 86 in src/sage/categories/bimodules.py

View workflow job for this annotation

GitHub Actions / test-new

Failed example:

Failed example:: Exception raised: Traceback (most recent call last): File "sage/misc/cachefunc.pyx", line 1005, in sage.misc.cachefunc.CachedFunction.__call__ return self.cache[k] File "sage/misc/weak_dict.pyx", line 709, in sage.misc.weak_dict.WeakValueDictionary.__getitem__ raise KeyError(k) KeyError: ((<class 'sage.categories.bimodules.Bimodules'>, Rational Field, Category of rings), ()) During handling of the above exception, another exception occurred: Traceback (most recent call last): File "sage/misc/cachefunc.pyx", line 1005, in sage.misc.cachefunc.CachedFunction.__call__ return self.cache[k] File "sage/misc/weak_dict.pyx", line 709, in sage.misc.weak_dict.WeakValueDictionary.__getitem__ raise KeyError(k) KeyError: ((<class 'sage.categories.left_modules.LeftModules'>, Rational Field), ()) During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/sage/src/sage/doctest/forker.py", line 728, in _run self.compile_and_execute(example, compiler, test.globs) File "/sage/src/sage/doctest/forker.py", line 1152, in compile_and_execute exec(compiled, globs) File "<doctest sage.categories.bimodules.Bimodules._make_named_class_key[2]>", line 1, in <module> Bimodules(QQ, Rings())._make_named_class_key('element_class') File "sage/misc/classcall_metaclass.pyx", line 321, in sage.misc.classcall_metaclass.ClasscallMetaclass.__call__ return cls.classcall(cls, *args, **kwds) File "/sage/src/sage/categories/category.py", line 456, in __classcall__ return super().__classcall__(cls, *args, **options) File "sage/misc/cachefunc.pyx", line 1010, in sage.misc.cachefunc.CachedFunction.__call__ w = self.f(*args, **kwds) File "/sage/src/sage/structure/unique_representation.py", line 1113, in __classcall__ return super().__classcall__(cls, *args, **options) File "/sage/src/sage/structure/unique_representation.py", line 597, in __classcall__ instance = typecall(cls, *args, **options) File "sage/misc/classcall_metaclass.pyx", line 472, in sage.misc.classcall_metaclass.typecall return (<PyTypeObject*>type).tp_call(cls, args, kwds) File "/sage/src/sage/categories/bimodules.py", line 60, in __init__ Category.__init__(self) File "/sage/src/sage/categories/category.py", line 483, in __init__ (self.__class__, self.subcategory_class, ), File "sage/misc/lazy_attribute.pyx", line 126, in sage.misc.lazy_attribute._lazy_attribute.__get__ result = self.f(a) File "/sage/src/sage/categories/category.py", line 1640, in subcategory_class _ = self._all_super_categories File "sage/misc/lazy_attribute.pyx", line 126, in sage.misc.lazy_attribute._lazy_attribute.__get__ result = self.f(a) File "/sage/src/sage/categories/category.py", line 861, in _all_super_categories for cat in self._super_categories] + File "sage/misc/lazy_attribute.pyx", line 126, in sage.misc.lazy_attribute._lazy_attribute.__get__ result = self.f(a) File "/sage/src/sage/categories/category.py", line 1016, in _super_categories return sorted(_flatten_categories(self.super_categories(), JoinCategory), key=category_sort_key, reverse=True) File "/sage/src/sage/categories/bimodules.py", line 168, in super_categories return [LeftModules(R), RightModules(S)] File "sage/misc/classcall_metaclass.pyx", line 321, in sage.misc.classcall_metaclass.ClasscallMetaclass.__call__ return cls.classcall(cls, *args, **kwds) File "/sage/src/sage/categories/category.py", line 456, in __classcall__ return super().__classcall__(cls, *args, **options) File "sage/misc/cachefunc.pyx", line 1010, in sage.misc.cachefunc.CachedFunction.__call__ w = self.f(*args, **kwds) File "/sage/src/sage/structure/unique_representation.py", line 1113, in __classcall__ return super().__classcall__(cls, *args, **options) File "/sage/src/sage/structure/unique_representation.py", line 597, in __classcall__ instance = typecall(cls, *args, **options) File "sage/misc/classcall_metaclass.pyx", line 472, in sage.misc.classcall_metacl
(Join of Category of number fields
and Category of quotient fields
and Category of metric spaces,
Category of rings)
(<class 'sage.categories.category.JoinCategory.element_class'>,
<class 'sage.categories.rings.Rings.element_class'>)

sage: Bimodules(Fields(), Rings())._make_named_class_key('element_class')
(Category of fields, Category of rings)
(<class 'sage.categories.fields.Fields.element_class'>,
<class 'sage.categories.rings.Rings.element_class'>)
"""
return (self._left_base_ring if isinstance(self._left_base_ring, Category) else self._left_base_ring.category(),
self._right_base_ring if isinstance(self._right_base_ring, Category) else self._right_base_ring.category())
return (getattr(self._left_base_ring if isinstance(self._left_base_ring, Category) else self._left_base_ring.category(), name),
getattr(self._right_base_ring if isinstance(self._right_base_ring, Category) else self._right_base_ring.category(), name))

@classmethod
def an_instance(cls):
Expand All @@ -112,7 +101,7 @@

EXAMPLES::

sage: Bimodules.an_instance() # needs sage.rings.real_mpfr

Check failure on line 104 in src/sage/categories/bimodules.py

View workflow job for this annotation

GitHub Actions / test-new

Failed example:

Failed example:: Exception raised: Traceback (most recent call last): File "sage/misc/cachefunc.pyx", line 1005, in sage.misc.cachefunc.CachedFunction.__call__ return self.cache[k] File "sage/misc/weak_dict.pyx", line 709, in sage.misc.weak_dict.WeakValueDictionary.__getitem__ raise KeyError(k) KeyError: ((<class 'sage.categories.bimodules.Bimodules'>, Rational Field, Real Field with 53 bits of precision), ()) During handling of the above exception, another exception occurred: Traceback (most recent call last): File "sage/misc/cachefunc.pyx", line 1005, in sage.misc.cachefunc.CachedFunction.__call__ return self.cache[k] File "sage/misc/weak_dict.pyx", line 709, in sage.misc.weak_dict.WeakValueDictionary.__getitem__ raise KeyError(k) KeyError: ((<class 'sage.categories.left_modules.LeftModules'>, Rational Field), ()) During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/sage/src/sage/doctest/forker.py", line 728, in _run self.compile_and_execute(example, compiler, test.globs) File "/sage/src/sage/doctest/forker.py", line 1152, in compile_and_execute exec(compiled, globs) File "<doctest sage.categories.bimodules.Bimodules.an_instance[0]>", line 1, in <module> Bimodules.an_instance() # needs sage.rings.real_mpfr File "/sage/src/sage/categories/bimodules.py", line 109, in an_instance return cls(QQ, RR) File "sage/misc/classcall_metaclass.pyx", line 321, in sage.misc.classcall_metaclass.ClasscallMetaclass.__call__ return cls.classcall(cls, *args, **kwds) File "/sage/src/sage/categories/category.py", line 456, in __classcall__ return super().__classcall__(cls, *args, **options) File "sage/misc/cachefunc.pyx", line 1010, in sage.misc.cachefunc.CachedFunction.__call__ w = self.f(*args, **kwds) File "/sage/src/sage/structure/unique_representation.py", line 1113, in __classcall__ return super().__classcall__(cls, *args, **options) File "/sage/src/sage/structure/unique_representation.py", line 597, in __classcall__ instance = typecall(cls, *args, **options) File "sage/misc/classcall_metaclass.pyx", line 472, in sage.misc.classcall_metaclass.typecall return (<PyTypeObject*>type).tp_call(cls, args, kwds) File "/sage/src/sage/categories/bimodules.py", line 60, in __init__ Category.__init__(self) File "/sage/src/sage/categories/category.py", line 483, in __init__ (self.__class__, self.subcategory_class, ), File "sage/misc/lazy_attribute.pyx", line 126, in sage.misc.lazy_attribute._lazy_attribute.__get__ result = self.f(a) File "/sage/src/sage/categories/category.py", line 1640, in subcategory_class _ = self._all_super_categories File "sage/misc/lazy_attribute.pyx", line 126, in sage.misc.lazy_attribute._lazy_attribute.__get__ result = self.f(a) File "/sage/src/sage/categories/category.py", line 861, in _all_super_categories for cat in self._super_categories] + File "sage/misc/lazy_attribute.pyx", line 126, in sage.misc.lazy_attribute._lazy_attribute.__get__ result = self.f(a) File "/sage/src/sage/categories/category.py", line 1016, in _super_categories return sorted(_flatten_categories(self.super_categories(), JoinCategory), key=category_sort_key, reverse=True) File "/sage/src/sage/categories/bimodules.py", line 168, in super_categories return [LeftModules(R), RightModules(S)] File "sage/misc/classcall_metaclass.pyx", line 321, in sage.misc.classcall_metaclass.ClasscallMetaclass.__call__ return cls.classcall(cls, *args, **kwds) File "/sage/src/sage/categories/category.py", line 456, in __classcall__ return super().__classcall__(cls, *args, **options) File "sage/misc/cachefunc.pyx", line 1010, in sage.misc.cachefunc.CachedFunction.__call__ w = self.f(*args, **kwds) File "/sage/src/sage/structure/unique_representation.py", line 1113, in __classcall__ return super().__classcall__(cls, *args, **options) File "/sage/src/sage/structure/unique_representation.py", line 597, in _
Category of bimodules over Rational Field on the left and Real Field with 53 bits of precision on the right
"""
from sage.rings.rational_field import QQ
Expand All @@ -123,7 +112,7 @@
"""
EXAMPLES::

sage: Bimodules(QQ, ZZ) # indirect doctest

Check failure on line 115 in src/sage/categories/bimodules.py

View workflow job for this annotation

GitHub Actions / test-new

Failed example:

Failed example:: Exception raised: Traceback (most recent call last): File "sage/misc/cachefunc.pyx", line 1005, in sage.misc.cachefunc.CachedFunction.__call__ return self.cache[k] File "sage/misc/weak_dict.pyx", line 709, in sage.misc.weak_dict.WeakValueDictionary.__getitem__ raise KeyError(k) KeyError: ((<class 'sage.categories.bimodules.Bimodules'>, Rational Field, Integer Ring), ()) During handling of the above exception, another exception occurred: Traceback (most recent call last): File "sage/misc/cachefunc.pyx", line 1005, in sage.misc.cachefunc.CachedFunction.__call__ return self.cache[k] File "sage/misc/weak_dict.pyx", line 709, in sage.misc.weak_dict.WeakValueDictionary.__getitem__ raise KeyError(k) KeyError: ((<class 'sage.categories.left_modules.LeftModules'>, Rational Field), ()) During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/sage/src/sage/doctest/forker.py", line 728, in _run self.compile_and_execute(example, compiler, test.globs) File "/sage/src/sage/doctest/forker.py", line 1152, in compile_and_execute exec(compiled, globs) File "<doctest sage.categories.bimodules.Bimodules._repr_object_names[0]>", line 1, in <module> Bimodules(QQ, ZZ) # indirect doctest File "sage/misc/classcall_metaclass.pyx", line 321, in sage.misc.classcall_metaclass.ClasscallMetaclass.__call__ return cls.classcall(cls, *args, **kwds) File "/sage/src/sage/categories/category.py", line 456, in __classcall__ return super().__classcall__(cls, *args, **options) File "sage/misc/cachefunc.pyx", line 1010, in sage.misc.cachefunc.CachedFunction.__call__ w = self.f(*args, **kwds) File "/sage/src/sage/structure/unique_representation.py", line 1113, in __classcall__ return super().__classcall__(cls, *args, **options) File "/sage/src/sage/structure/unique_representation.py", line 597, in __classcall__ instance = typecall(cls, *args, **options) File "sage/misc/classcall_metaclass.pyx", line 472, in sage.misc.classcall_metaclass.typecall return (<PyTypeObject*>type).tp_call(cls, args, kwds) File "/sage/src/sage/categories/bimodules.py", line 60, in __init__ Category.__init__(self) File "/sage/src/sage/categories/category.py", line 483, in __init__ (self.__class__, self.subcategory_class, ), File "sage/misc/lazy_attribute.pyx", line 126, in sage.misc.lazy_attribute._lazy_attribute.__get__ result = self.f(a) File "/sage/src/sage/categories/category.py", line 1640, in subcategory_class _ = self._all_super_categories File "sage/misc/lazy_attribute.pyx", line 126, in sage.misc.lazy_attribute._lazy_attribute.__get__ result = self.f(a) File "/sage/src/sage/categories/category.py", line 861, in _all_super_categories for cat in self._super_categories] + File "sage/misc/lazy_attribute.pyx", line 126, in sage.misc.lazy_attribute._lazy_attribute.__get__ result = self.f(a) File "/sage/src/sage/categories/category.py", line 1016, in _super_categories return sorted(_flatten_categories(self.super_categories(), JoinCategory), key=category_sort_key, reverse=True) File "/sage/src/sage/categories/bimodules.py", line 168, in super_categories return [LeftModules(R), RightModules(S)] File "sage/misc/classcall_metaclass.pyx", line 321, in sage.misc.classcall_metaclass.ClasscallMetaclass.__call__ return cls.classcall(cls, *args, **kwds) File "/sage/src/sage/categories/category.py", line 456, in __classcall__ return super().__classcall__(cls, *args, **options) File "sage/misc/cachefunc.pyx", line 1010, in sage.misc.cachefunc.CachedFunction.__call__ w = self.f(*args, **kwds) File "/sage/src/sage/structure/unique_representation.py", line 1113, in __classcall__ return super().__classcall__(cls, *args, **options) File "/sage/src/sage/structure/unique_representation.py", line 597, in __classcall__ instance = typecall(cls, *args, **options) File "sage/misc/classcall_metaclass.pyx", line 472, in sage.misc.classcall_metaclass.typecall return (<PyTypeO
Category of bimodules over Rational Field on the left and Integer Ring on the right
"""
return "bimodules over %s on the left and %s on the right" \
Expand All @@ -136,7 +125,7 @@

EXAMPLES::

sage: Bimodules(QQ, ZZ).left_base_ring()

Check failure on line 128 in src/sage/categories/bimodules.py

View workflow job for this annotation

GitHub Actions / test-new

Failed example:

Failed example:: Exception raised: Traceback (most recent call last): File "sage/misc/cachefunc.pyx", line 1005, in sage.misc.cachefunc.CachedFunction.__call__ return self.cache[k] File "sage/misc/weak_dict.pyx", line 709, in sage.misc.weak_dict.WeakValueDictionary.__getitem__ raise KeyError(k) KeyError: ((<class 'sage.categories.bimodules.Bimodules'>, Rational Field, Integer Ring), ()) During handling of the above exception, another exception occurred: Traceback (most recent call last): File "sage/misc/cachefunc.pyx", line 1005, in sage.misc.cachefunc.CachedFunction.__call__ return self.cache[k] File "sage/misc/weak_dict.pyx", line 709, in sage.misc.weak_dict.WeakValueDictionary.__getitem__ raise KeyError(k) KeyError: ((<class 'sage.categories.left_modules.LeftModules'>, Rational Field), ()) During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/sage/src/sage/doctest/forker.py", line 728, in _run self.compile_and_execute(example, compiler, test.globs) File "/sage/src/sage/doctest/forker.py", line 1152, in compile_and_execute exec(compiled, globs) File "<doctest sage.categories.bimodules.Bimodules.left_base_ring[0]>", line 1, in <module> Bimodules(QQ, ZZ).left_base_ring() File "sage/misc/classcall_metaclass.pyx", line 321, in sage.misc.classcall_metaclass.ClasscallMetaclass.__call__ return cls.classcall(cls, *args, **kwds) File "/sage/src/sage/categories/category.py", line 456, in __classcall__ return super().__classcall__(cls, *args, **options) File "sage/misc/cachefunc.pyx", line 1010, in sage.misc.cachefunc.CachedFunction.__call__ w = self.f(*args, **kwds) File "/sage/src/sage/structure/unique_representation.py", line 1113, in __classcall__ return super().__classcall__(cls, *args, **options) File "/sage/src/sage/structure/unique_representation.py", line 597, in __classcall__ instance = typecall(cls, *args, **options) File "sage/misc/classcall_metaclass.pyx", line 472, in sage.misc.classcall_metaclass.typecall return (<PyTypeObject*>type).tp_call(cls, args, kwds) File "/sage/src/sage/categories/bimodules.py", line 60, in __init__ Category.__init__(self) File "/sage/src/sage/categories/category.py", line 483, in __init__ (self.__class__, self.subcategory_class, ), File "sage/misc/lazy_attribute.pyx", line 126, in sage.misc.lazy_attribute._lazy_attribute.__get__ result = self.f(a) File "/sage/src/sage/categories/category.py", line 1640, in subcategory_class _ = self._all_super_categories File "sage/misc/lazy_attribute.pyx", line 126, in sage.misc.lazy_attribute._lazy_attribute.__get__ result = self.f(a) File "/sage/src/sage/categories/category.py", line 861, in _all_super_categories for cat in self._super_categories] + File "sage/misc/lazy_attribute.pyx", line 126, in sage.misc.lazy_attribute._lazy_attribute.__get__ result = self.f(a) File "/sage/src/sage/categories/category.py", line 1016, in _super_categories return sorted(_flatten_categories(self.super_categories(), JoinCategory), key=category_sort_key, reverse=True) File "/sage/src/sage/categories/bimodules.py", line 168, in super_categories return [LeftModules(R), RightModules(S)] File "sage/misc/classcall_metaclass.pyx", line 321, in sage.misc.classcall_metaclass.ClasscallMetaclass.__call__ return cls.classcall(cls, *args, **kwds) File "/sage/src/sage/categories/category.py", line 456, in __classcall__ return super().__classcall__(cls, *args, **options) File "sage/misc/cachefunc.pyx", line 1010, in sage.misc.cachefunc.CachedFunction.__call__ w = self.f(*args, **kwds) File "/sage/src/sage/structure/unique_representation.py", line 1113, in __classcall__ return super().__classcall__(cls, *args, **options) File "/sage/src/sage/structure/unique_representation.py", line 597, in __classcall__ instance = typecall(cls, *args, **options) File "sage/misc/classcall_metaclass.pyx", line 472, in sage.misc.classcall_metaclass.typecall return (<PyTypeObject*
Rational Field
"""
return self._left_base_ring
Expand Down
167 changes: 132 additions & 35 deletions src/sage/categories/category.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@

import inspect
from warnings import warn
from itertools import zip_longest
from sage.misc.abstract_method import abstract_method, abstract_methods_of_class
from sage.misc.cachefunc import cached_method, cached_function
from sage.misc.c3_controlled import _cmp_key, _cmp_key_named, C3_sorted_merge
Expand All @@ -113,6 +114,7 @@

from sage.structure.sage_object import SageObject
from sage.structure.unique_representation import UniqueRepresentation
from sage.structure.debug_options import debug
from sage.structure.dynamic_class import DynamicMetaclass, dynamic_class

from sage.categories.category_cy_helper import category_sort_key, _sort_uniq, _flatten_categories, join_as_tuple
Expand Down Expand Up @@ -943,6 +945,20 @@ def all_super_categories(self, proper=False):
appropriate. Simply because lazy attributes are much
faster than any method.

.. NOTE::

This is not the same as the concept of super category in mathematics.
In fact, this is not even the opposite relation of :meth:`is_subcategory`::

sage: A = VectorSpaces(QQ); A
Category of vector spaces over Rational Field
sage: B = VectorSpaces(QQ.category()); B
Category of vector spaces over (number fields and quotient fields and metric spaces)
sage: A.is_subcategory(B)
True
sage: B in A.all_super_categories()
False

EXAMPLES::

sage: C = Rings(); C
Expand Down Expand Up @@ -1379,8 +1395,6 @@ def _test_category_graph(self, **options):
method resolution order of the parent and element
classes. This method checks this.

.. TODO:: currently, this won't work for hom categories.

EXAMPLES::

sage: C = HopfAlgebrasWithBasis(QQ)
Expand Down Expand Up @@ -1622,8 +1636,25 @@ def subcategory_class(self):
sage: type(cls)
<class 'sage.structure.dynamic_class.DynamicMetaclass'>
"""
return self._make_named_class('subcategory_class', 'SubcategoryMethods',
cache=False, picklable=False)
if debug.test_category_graph:
_ = self._all_super_categories
subcategory_class = self._make_named_class('subcategory_class', 'SubcategoryMethods',
cache=False, picklable=False)
if debug.test_category_graph:
# see also _test_category_graph()
previous_all_super_categories = self.__dict__.get("_all_super_categories", None)
for C in self._all_super_categories_proper:
assert "subcategory_class" in C.__dict__ # avoid Heisenbug (relies on implementation detail of lazy_attribute)
mismatch = [(i, a, b)
for i, (a, b) in enumerate(zip_longest(
subcategory_class.mro()[1:],
[C.subcategory_class for C in self._all_super_categories_proper] + [object]
))
if a is None or b is None or a != b]
if mismatch:
print(f"Category graph does not match with Python MRO: {subcategory_class=} {subcategory_class.mro()=} {mismatch=}")
# we cannot even print self._all_super_categories here otherwise there's a risk of infinite recursion
return subcategory_class

@lazy_attribute
def parent_class(self):
Expand Down Expand Up @@ -1668,7 +1699,15 @@ def parent_class(self):
:class:`~sage.categories.category_types.Category_over_base` and
:class:`sage.categories.category.JoinCategory`.
"""
return self._make_named_class('parent_class', 'ParentMethods')
if debug.test_category_graph:
_ = self._all_super_categories
parent_class = self._make_named_class('parent_class', 'ParentMethods')
if debug.test_category_graph:
# see also _test_category_graph()
if parent_class.mro()[1:] != [C.parent_class for C in self._all_super_categories_proper] + [object]:
print(f"Category graph does not match with Python MRO: {parent_class=} {parent_class.mro()=} {self._all_super_categories=}")
return parent_class


@lazy_attribute
def element_class(self):
Expand Down Expand Up @@ -1714,7 +1753,15 @@ def element_class(self):

.. SEEALSO:: :meth:`parent_class`
"""
return self._make_named_class('element_class', 'ElementMethods')
if debug.test_category_graph:
_ = self._all_super_categories
element_class = self._make_named_class('element_class', 'ElementMethods')
if debug.test_category_graph:
# see also _test_category_graph()
assert self is self._all_super_categories[0]
if element_class.mro()[1:] != [C.element_class for C in self._all_super_categories_proper] + [object]:
print(f"Category graph does not match with Python MRO: {element_class=} {element_class.mro()=} {self._all_super_categories=}")
return element_class

@lazy_attribute
def morphism_class(self):
Expand Down Expand Up @@ -1757,7 +1804,7 @@ def required_methods(self):
# Operations on the lattice of categories
def is_subcategory(self, c):
"""
Return ``True`` if ``self`` is naturally embedded as a subcategory of `c`.
Return ``True`` if there is a natural forgetful functor from ``self`` to `c`.

EXAMPLES::

Expand Down Expand Up @@ -2046,13 +2093,18 @@ def _with_axiom(self, axiom):
Return the subcategory of the objects of ``self`` satisfying
the given ``axiom``.

Note that this is a private method thus should not be directly
used, see below.

INPUT:

- ``axiom`` -- string, the name of an axiom

EXAMPLES::

sage: Sets()._with_axiom("Finite")
sage: Sets()._with_axiom("Finite") # not idiomatic
Category of finite sets
sage: Sets().Finite() # recommended
Category of finite sets

sage: type(Magmas().Finite().Commutative())
Expand All @@ -2068,7 +2120,7 @@ def _with_axiom(self, axiom):
sage: Sets()._with_axiom("Associative")
Category of sets

.. WARNING:: This may be changed in the future to raising an error.
.. WARNING:: This may be changed in the future to raise an error.
"""
return Category.join(self._with_axiom_as_tuple(axiom))

Expand Down Expand Up @@ -2697,6 +2749,29 @@ class CategoryWithParameters(Category):
sage: C1.parent_class is C3.parent_class
False

.. NOTE::

If category ``A`` is a supercategory of category ``B``,
and category ``B`` uses the optimization, then so must ``A``.

For example, ``Modules(ZZ)`` is a supercategory of ``Algebras(ZZ)``,
and ``Algebras(ZZ)`` implements the optimization::

sage: isinstance(Algebras(ZZ), CategoryWithParameters)
True
sage: Algebras(ZZ).parent_class is Algebras(ZZ.category()).parent_class
True
sage: Modules(ZZ) in Algebras(ZZ).all_super_categories()
True

This forces ``Modules(ZZ)`` to also implement the optimization::

sage: Modules(ZZ).parent_class is Modules(ZZ.category()).parent_class
True

This is because the Python MRO must match the supercategory hierarchy.
See :meth:`Category._test_category_graph`.

.. automethod:: Category._make_named_class
"""

Expand Down Expand Up @@ -2803,14 +2878,49 @@ def _make_named_class(self, name, method_provider, cache=False, **options):
cls = self.__class__
if isinstance(cls, DynamicMetaclass):
cls = cls.__base__
if debug.test_category_graph and hasattr(self, "_Category_over_base__base"):
previous_base = self._Category_over_base__base
if hasattr(previous_base, "category"):
previous_base_category = previous_base.category()
key = (cls, name, self._make_named_class_key(name))
if debug.test_category_graph:
key2 = (cls, name, self._make_named_class_key(name))
assert key == key2
if debug.test_category_graph and key in self._make_named_class_cache:
old_cls = self._make_named_class_cache[key]
last_category = self._make_named_class_last_category_cache[key]
# new_cls = Category._make_named_class(self, name, method_provider, cache=cache, **options)
# if old_cls.mro()[1:] != new_cls.mro()[1:]:
# ^ cannot do the above because :meth:`_make_named_class` may refine the category of the ring thus modifies key
# mismatch = [(i, a, b)
# for i, (a, b) in enumerate(zip(self._all_super_categories[1:], last_category._all_super_categories[1:]))
# if getattr(a, name) != getattr(b, name)]
# ^ cannot do the above because :meth:`getattr(a, name)` may also refine the category (Heisenbug)
mismatch = [(i, a, b)
for i, (a, b) in enumerate(zip_longest(self._all_super_categories[1:], last_category._all_super_categories[1:]))
if a is None or b is None or (name in a.__dict__ and name in b.__dict__ and a.__dict__[name] != b.__dict__[name])]
if mismatch:
key3 = (cls, name, self._make_named_class_key(name))
print(f"Categories with same _make_named_class_key has different MRO: {self._all_super_categories=}",
f"{last_category=} {last_category._all_super_categories=} {mismatch=}" +
(" (probably Heisenbug)" if key3 != key else ""))
try:
return self._make_named_class_cache[key]
except KeyError:
pass
result = Category._make_named_class(self, name, method_provider,
cache=cache, **options)
# the object in the parameter may have had its category refined, which modifies the key, needs to recompute
# (problem with mutable objects)
if key != (cls, name, self._make_named_class_key(name)):
# throw result away and recompute
return self._make_named_class(name, method_provider, cache=cache, **options)
self._make_named_class_cache[key] = result
if debug.test_category_graph:
if not hasattr(CategoryWithParameters, '_make_named_class_last_category_cache'):
CategoryWithParameters._make_named_class_last_category_cache = {}
# if C._make_named_class(name) was called, then _make_named_class_last_category_cache[key] = C
self._make_named_class_last_category_cache[key] = self
return result

@abstract_method
Expand All @@ -2835,24 +2945,14 @@ def _make_named_class_key(self, name):
The parent class of an algebra depends only on the category of the base ring::

sage: Algebras(ZZ)._make_named_class_key("parent_class")
Join of Category of Dedekind domains
and Category of euclidean domains
and Category of noetherian rings
and Category of infinite enumerated sets
and Category of metric spaces
<class 'sage.categories.category.JoinCategory.parent_class'>

The morphism class of a bimodule depends only on the category
of the left and right base rings::

sage: Bimodules(QQ, ZZ)._make_named_class_key("morphism_class")
(Join of Category of number fields
and Category of quotient fields
and Category of metric spaces,
Join of Category of Dedekind domains
and Category of euclidean domains
and Category of noetherian rings
and Category of infinite enumerated sets
and Category of metric spaces)
(<class 'sage.categories.category.JoinCategory.morphism_class'>,
<class 'sage.categories.category.JoinCategory.morphism_class'>)

The element class of a join category depends only on the
element class of its super categories::
Expand Down Expand Up @@ -2976,21 +3076,13 @@ def _make_named_class_key(self, name):
EXAMPLES::

sage: Modules(ZZ)._make_named_class_key('element_class')
Join of Category of Dedekind domains
and Category of euclidean domains
and Category of noetherian rings
and Category of infinite enumerated sets
and Category of metric spaces
<class 'sage.categories.category.JoinCategory.element_class'>
sage: Modules(QQ)._make_named_class_key('parent_class')
Join of Category of number fields
and Category of quotient fields
and Category of metric spaces
<class 'sage.categories.category.JoinCategory.parent_class'>
sage: Schemes(Spec(ZZ))._make_named_class_key('parent_class')
Category of schemes
<class 'sage.categories.schemes.Schemes.parent_class'>
sage: ModularAbelianVarieties(QQ)._make_named_class_key('parent_class')
Join of Category of number fields
and Category of quotient fields
and Category of metric spaces
<class 'sage.categories.category.JoinCategory.parent_class'>
"""
return tuple(getattr(cat, name) for cat in self._super_categories)

Expand Down Expand Up @@ -3064,6 +3156,9 @@ def _with_axiom(self, axiom):
"""
Return the category obtained by adding an axiom to ``self``.

As with :meth:`Category._with_axiom`, using this method directly is
not idiomatic.

.. NOTE::

This is just an optimization of
Expand All @@ -3073,7 +3168,9 @@ def _with_axiom(self, axiom):
EXAMPLES::

sage: C = Category.join([Monoids(), Posets()])
sage: C._with_axioms(["Finite"])
sage: C._with_axioms(["Finite"]) # not idiomatic
Join of Category of finite monoids and Category of finite posets
sage: C.Finite() # recommended
Join of Category of finite monoids and Category of finite posets

TESTS:
Expand Down
22 changes: 6 additions & 16 deletions src/sage/categories/category_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,27 +229,17 @@ def _make_named_class_key(self, name):
EXAMPLES::

sage: Modules(ZZ)._make_named_class_key('element_class')
Join of Category of Dedekind domains
and Category of euclidean domains
and Category of noetherian rings
and Category of infinite enumerated sets
and Category of metric spaces
<class 'sage.categories.category.JoinCategory.element_class'>
sage: Modules(QQ)._make_named_class_key('parent_class')
Join of Category of number fields
and Category of quotient fields
and Category of metric spaces
<class 'sage.categories.category.JoinCategory.parent_class'>
sage: Schemes(Spec(ZZ))._make_named_class_key('parent_class')
Category of schemes
<class 'sage.categories.schemes.Schemes.parent_class'>
sage: ModularAbelianVarieties(QQ)._make_named_class_key('parent_class')
Join of Category of number fields
and Category of quotient fields
and Category of metric spaces
<class 'sage.categories.category.JoinCategory.parent_class'>
sage: Algebras(Fields())._make_named_class_key('morphism_class')
Category of fields
<class 'sage.categories.fields.Fields.morphism_class'>
"""
if isinstance(self.__base, Category):
return self.__base
return self.__base.category()
return getattr(self.__base if isinstance(self.__base, Category) else self.__base.category(), name)

@classmethod
def an_instance(cls):
Expand Down
Loading
Loading