Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions src/sage/categories/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import sage.structure.element # resolve a cyclic import (categories.map > structure.element > ... > categories.map)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cannot add an init file. sage.categories is a PEP-420 namespace package.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Happy to hear your alternative solution.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll be happy to walk you through #35095

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, maybe later, for now it would be enough if you tell me how you broke this particular cyclic import.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mkoeppe can you please explain why adding the init file here is not okay but the one you add in #37185 is okay? In both cases the package seems to be shipped by only a single distribution and doesn't need PEP-420.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the package seems to be shipped by only a single distribution

No, that's not true for sage.categories. How did you get this impression?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which other distribution is shipping parts of categories?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are asking for info that you know how to obtain.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't find another one, that's why I am asking...

Copy link
Contributor

@mkoeppe mkoeppe Feb 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's very strange that you should claim you didn't find another one.

It's public knowledge that you know at least 1 way how to look for them, namely by looking for files src/sage/categories/all_*.py:

5 changes: 0 additions & 5 deletions src/sage/categories/all__sagemath_objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,10 @@

from sage.misc.lazy_import import lazy_import

# Resolve a circular import so that "import sage.categories.all" can succeed
# in initializing the category system.
import sage.structure.category_object # imports sage.categories.category

# Small part of "from sage.categories.basic import *":
from sage.categories.objects import Objects
from sage.categories.sets_cat import Sets, EmptySetError


from sage.categories.category import Category

from sage.categories.category_types import Elements
Expand Down
7 changes: 6 additions & 1 deletion src/sage/categories/category.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,6 @@
from sage.misc.cachefunc import cached_method, cached_function
from sage.misc.c3_controlled import _cmp_key, _cmp_key_named, C3_sorted_merge
from sage.misc.lazy_attribute import lazy_attribute
from sage.misc.unknown import Unknown
from sage.misc.weak_dict import WeakValueDictionary

from sage.structure.sage_object import SageObject
Expand Down Expand Up @@ -1802,6 +1801,8 @@ def is_subcategory(self, c):
sage: PoV3.is_subcategory(PoA3)
False
"""
from sage.misc.unknown import Unknown

if c is self:
return True
subcat_hook = c._subcategory_hook_(self)
Expand Down Expand Up @@ -2888,6 +2889,8 @@ def _subcategory_hook_(self, C):
sage: Bimodules(QQ,QQ)._subcategory_hook_(Rings())
False
"""
from sage.misc.unknown import Unknown

if not issubclass(C.parent_class, self.parent_class):
return False
return Unknown
Expand Down Expand Up @@ -3053,6 +3056,8 @@ def is_subcategory(self, C):
sage: Category.join([Rings(),Modules(QQ)]).is_subcategory(Category.join([Rngs(),Bimodules(QQ,QQ)]))
True
"""
from sage.misc.unknown import Unknown

if C is self:
return True
hook = C._subcategory_hook_(self)
Expand Down
3 changes: 2 additions & 1 deletion src/sage/categories/category_singleton.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ Singleton categories
# https://www.gnu.org/licenses/
# *****************************************************************************

from sage.misc.constant_function import ConstantFunction
from sage.misc.lazy_attribute import lazy_class_attribute
from sage.categories.category import Category
from sage.structure.category_object cimport CategoryObject
Expand Down Expand Up @@ -314,6 +313,8 @@ class Category_singleton(Category):
...
AssertionError: <class '__main__.MySubStuff'> is not a direct subclass of <class 'sage.categories.category_singleton.Category_singleton'>
"""
from sage.misc.constant_function import ConstantFunction

if isinstance(cls, DynamicMetaclass): # cls is something like Rings_with_category
cls = cls.__base__
# TODO: find a better way to check that cls is an abstract class
Expand Down
11 changes: 10 additions & 1 deletion src/sage/categories/map.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import weakref
from sage.ext.stdsage cimport HAS_DICTIONARY
from sage.arith.power cimport generic_power
from sage.sets.pythonclass cimport Set_PythonType
from sage.misc.constant_function import ConstantFunction
from sage.structure.element cimport parent
from cpython.object cimport PyObject_RichCompare

Expand Down Expand Up @@ -120,6 +119,8 @@ cdef class Map(Element):
From: Univariate Polynomial Ring in x over Rational Field
To: Symmetric group of order 6! as a permutation group
"""
from sage.misc.constant_function import ConstantFunction

if codomain is not None:
if isinstance(parent, type):
parent = Set_PythonType(parent)
Expand Down Expand Up @@ -304,6 +305,8 @@ cdef class Map(Element):
sage: phi
Defunct map
"""
from sage.misc.constant_function import ConstantFunction

if not isinstance(self.domain, ConstantFunction):
return
self.domain = weakref.ref(self.domain())
Expand Down Expand Up @@ -380,6 +383,8 @@ cdef class Map(Element):
...
ValueError: This map is in an invalid state, the domain has been garbage collected
"""
from sage.misc.constant_function import ConstantFunction

if isinstance(self.domain, ConstantFunction):
return
D = self.domain()
Expand Down Expand Up @@ -418,6 +423,8 @@ cdef class Map(Element):
sage: f._repr_type_str
'bla'
"""
from sage.misc.constant_function import ConstantFunction

# todo: the following can break during unpickling of complex
# objects with circular references! In that case, _slots might
# contain incomplete objects.
Expand Down Expand Up @@ -584,6 +591,8 @@ cdef class Map(Element):
sage: phi
Defunct map
"""
from sage.misc.constant_function import ConstantFunction

D = self.domain()
if D is None:
return "Defunct map"
Expand Down
4 changes: 2 additions & 2 deletions src/sage/categories/morphism.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@ AUTHORS:

from cpython.object cimport *

from sage.misc.constant_function import ConstantFunction

from sage.structure.element cimport Element, ModuleElement
from sage.structure.richcmp cimport richcmp_not_equal, rich_to_bool
from sage.structure.parent cimport Parent
Expand Down Expand Up @@ -90,6 +88,8 @@ cdef class Morphism(Map):
sage: phi
Defunct morphism
"""
from sage.misc.constant_function import ConstantFunction

D = self.domain()
if D is None:
return "Defunct morphism"
Expand Down
5 changes: 5 additions & 0 deletions src/sage/misc/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
try:
import sage.structure.element # to break a cyclic import (misc.constant_function > structure.element > ... > misc.constant_function)
except ModuleNotFoundError:
# Ignore, the import above may fail while collecting metadata info (at which point sage.structure is not yet installed)
pass
2 changes: 0 additions & 2 deletions src/sage/misc/all__sagemath_objects.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# Subset of sage.misc.all that is made available by the sage-objects distribution

import sage.structure.all # to break a cyclic import

from sage.misc.lazy_attribute import lazy_attribute, lazy_class_attribute
from sage.misc.lazy_import import lazy_import

Expand Down
3 changes: 2 additions & 1 deletion src/sage/misc/c3_controlled.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,6 @@ AUTHOR:
from sage.misc.classcall_metaclass import ClasscallMetaclass, typecall
from sage.misc.cachefunc import cached_function, cached_method
from sage.misc.lazy_attribute import lazy_attribute
from sage.structure.dynamic_class import dynamic_class

##############################################################################
# Implementation of the total order between categories
Expand Down Expand Up @@ -1349,6 +1348,8 @@ class HierarchyElement(object, metaclass=ClasscallMetaclass):
sage: x.cls.mro()
[<class '30.cls'>, <class '15.cls'>, <class '10.cls'>, <class '6.cls'>, <class '5.cls'>, <class '3.cls'>, <class '2.cls'>, <class '1.cls'>, <... 'object'>]
"""
from sage.structure.dynamic_class import dynamic_class

super_classes = tuple(self._from_value(base).cls for base in self._bases_controlled)
if not super_classes:
super_classes = (object,)
Expand Down
3 changes: 2 additions & 1 deletion src/sage/misc/fast_methods.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ AUTHOR:
#*****************************************************************************

from sage.misc.classcall_metaclass import ClasscallMetaclass, typecall
from sage.misc.constant_function import ConstantFunction

from cpython.object cimport Py_EQ, Py_NE

Expand Down Expand Up @@ -296,6 +295,8 @@ class Singleton(WithEqualityById, metaclass=ClasscallMetaclass):
sage: loads(dumps(c)) is copy(c) is C() # indirect doctest
True
"""
from sage.misc.constant_function import ConstantFunction

assert cls.mro()[1] == Singleton, "{} is not a direct subclass of {}".format(cls, Singleton)
res = typecall(cls)
cf = ConstantFunction(res)
Expand Down
3 changes: 2 additions & 1 deletion src/sage/rings/rational.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ from sage.structure.element cimport Element
from sage.structure.parent cimport Parent
from sage.structure.richcmp cimport rich_to_bool_sgn


RealNumber_classes = ()

def _register_real_number_class(cls):
Expand Down Expand Up @@ -2088,6 +2087,7 @@ cdef class Rational(sage.structure.element.FieldElement):
...
ValueError: cannot take even root of negative number
"""
from sage.rings.integer_ring import ZZ
# TODO -- this could be quicker, by using GMP directly.
cdef integer.Integer num
cdef integer.Integer den
Expand Down Expand Up @@ -3196,6 +3196,7 @@ cdef class Rational(sage.structure.element.FieldElement):
sage: (-1/2).log(3) # needs sage.symbolic
(I*pi + log(1/2))/log(3)
"""
from sage.rings.integer_ring import ZZ
cdef int self_sgn
if self.denom().is_one():
return ZZ(self.numer()).log(m, prec)
Expand Down
3 changes: 2 additions & 1 deletion src/sage/sets/pythonclass.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ Set of all objects of a given Python class

from cpython.object cimport Py_EQ, Py_NE
from sage.structure.richcmp cimport rich_to_bool
from sage.categories.sets_cat import Sets


cdef dict _type_set_cache = {}
Expand Down Expand Up @@ -83,6 +82,8 @@ cdef class Set_PythonType_class(Set_generic):
sage: Set_PythonType(float).category()
Category of sets
"""
from sage.categories.sets_cat import Sets

if not isinstance(typ, type):
raise TypeError(f"must be initialized with a class, not {typ!r}")
super().__init__(category=Sets())
Expand Down
2 changes: 0 additions & 2 deletions src/sage/structure/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +0,0 @@
# Resolve a cyclic import
import sage.structure.element
3 changes: 2 additions & 1 deletion src/sage/structure/category_object.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ This example illustrates generators for a free module over `\ZZ`.

from sage.cpython.getattr import dir_with_other_class
from sage.cpython.getattr cimport getattr_from_other_class
from sage.categories.category import Category
from sage.misc.cachefunc import cached_method
from sage.structure.dynamic_class import DynamicMetaclass

Expand Down Expand Up @@ -145,6 +144,8 @@ cdef class CategoryObject(SageObject):
...
TypeError: CategoryObject of type CategoryObject requires a Category, list or tuple, not NoneType
"""
from sage.categories.category import Category

if isinstance(category, Category):
self._category = category
elif isinstance(category, (list, tuple)):
Expand Down
4 changes: 0 additions & 4 deletions src/sage/structure/factory.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -768,7 +768,3 @@ def lookup_global(name):
else:
import sage.all as all
return getattr(all, name)


# Old imports required for unpickling old pickles
from sage.structure.test_factory import test_factory
Loading