diff --git a/src/sage/categories/__init__.py b/src/sage/categories/__init__.py new file mode 100644 index 00000000000..3f293d43eac --- /dev/null +++ b/src/sage/categories/__init__.py @@ -0,0 +1 @@ +import sage.structure.element # resolve a cyclic import (categories.map > structure.element > ... > categories.map) diff --git a/src/sage/categories/all__sagemath_objects.py b/src/sage/categories/all__sagemath_objects.py index d87b4a1d20e..671fb0dfd16 100644 --- a/src/sage/categories/all__sagemath_objects.py +++ b/src/sage/categories/all__sagemath_objects.py @@ -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 diff --git a/src/sage/categories/category.py b/src/sage/categories/category.py index b71331c5ab5..8520225b2b4 100644 --- a/src/sage/categories/category.py +++ b/src/sage/categories/category.py @@ -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 @@ -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) @@ -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 @@ -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) diff --git a/src/sage/categories/category_singleton.pyx b/src/sage/categories/category_singleton.pyx index 543ce0375f7..2b63a5c7cf9 100644 --- a/src/sage/categories/category_singleton.pyx +++ b/src/sage/categories/category_singleton.pyx @@ -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 @@ -314,6 +313,8 @@ class Category_singleton(Category): ... AssertionError: is not a direct subclass of """ + 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 diff --git a/src/sage/categories/map.pyx b/src/sage/categories/map.pyx index 134b88ef1ba..78cdef54d5d 100644 --- a/src/sage/categories/map.pyx +++ b/src/sage/categories/map.pyx @@ -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 @@ -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) @@ -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()) @@ -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() @@ -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. @@ -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" diff --git a/src/sage/categories/morphism.pyx b/src/sage/categories/morphism.pyx index d4b412dd126..74362a2fa87 100644 --- a/src/sage/categories/morphism.pyx +++ b/src/sage/categories/morphism.pyx @@ -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 @@ -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" diff --git a/src/sage/misc/__init__.py b/src/sage/misc/__init__.py new file mode 100644 index 00000000000..f5961558d9f --- /dev/null +++ b/src/sage/misc/__init__.py @@ -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 diff --git a/src/sage/misc/all__sagemath_objects.py b/src/sage/misc/all__sagemath_objects.py index 30a76f38fab..ed0ff500949 100644 --- a/src/sage/misc/all__sagemath_objects.py +++ b/src/sage/misc/all__sagemath_objects.py @@ -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 diff --git a/src/sage/misc/c3_controlled.pyx b/src/sage/misc/c3_controlled.pyx index befaa7b5b32..0526e64764c 100644 --- a/src/sage/misc/c3_controlled.pyx +++ b/src/sage/misc/c3_controlled.pyx @@ -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 @@ -1349,6 +1348,8 @@ class HierarchyElement(object, metaclass=ClasscallMetaclass): sage: x.cls.mro() [, , , , , , , , <... '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,) diff --git a/src/sage/misc/fast_methods.pyx b/src/sage/misc/fast_methods.pyx index ce7f918cccd..522efc1e201 100644 --- a/src/sage/misc/fast_methods.pyx +++ b/src/sage/misc/fast_methods.pyx @@ -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 @@ -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) diff --git a/src/sage/rings/rational.pyx b/src/sage/rings/rational.pyx index 92fa6fd8fc3..5f94b8ade9b 100644 --- a/src/sage/rings/rational.pyx +++ b/src/sage/rings/rational.pyx @@ -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): @@ -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 @@ -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) diff --git a/src/sage/sets/pythonclass.pyx b/src/sage/sets/pythonclass.pyx index bfa7f3bc617..40ffbd55a89 100644 --- a/src/sage/sets/pythonclass.pyx +++ b/src/sage/sets/pythonclass.pyx @@ -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 = {} @@ -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()) diff --git a/src/sage/structure/__init__.py b/src/sage/structure/__init__.py index 8689eb1717f..e69de29bb2d 100644 --- a/src/sage/structure/__init__.py +++ b/src/sage/structure/__init__.py @@ -1,2 +0,0 @@ -# Resolve a cyclic import -import sage.structure.element diff --git a/src/sage/structure/category_object.pyx b/src/sage/structure/category_object.pyx index 48cee10c2bc..ea5aaa1393c 100644 --- a/src/sage/structure/category_object.pyx +++ b/src/sage/structure/category_object.pyx @@ -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 @@ -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)): diff --git a/src/sage/structure/factory.pyx b/src/sage/structure/factory.pyx index 75a043250c2..7474e310796 100644 --- a/src/sage/structure/factory.pyx +++ b/src/sage/structure/factory.pyx @@ -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