passagemath-objects 10.6.41__cp314-cp314t-macosx_13_0_arm64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of passagemath-objects might be problematic. Click here for more details.

Files changed (280) hide show
  1. passagemath_objects/.dylibs/libgmp.10.dylib +0 -0
  2. passagemath_objects/__init__.py +3 -0
  3. passagemath_objects-10.6.41.dist-info/METADATA +115 -0
  4. passagemath_objects-10.6.41.dist-info/RECORD +280 -0
  5. passagemath_objects-10.6.41.dist-info/WHEEL +6 -0
  6. passagemath_objects-10.6.41.dist-info/top_level.txt +3 -0
  7. sage/all__sagemath_objects.py +37 -0
  8. sage/arith/all__sagemath_objects.py +5 -0
  9. sage/arith/long.pxd +411 -0
  10. sage/arith/numerical_approx.cpython-314t-darwin.so +0 -0
  11. sage/arith/numerical_approx.pxd +35 -0
  12. sage/arith/numerical_approx.pyx +75 -0
  13. sage/arith/power.cpython-314t-darwin.so +0 -0
  14. sage/arith/power.pxd +31 -0
  15. sage/arith/power.pyx +127 -0
  16. sage/categories/action.cpython-314t-darwin.so +0 -0
  17. sage/categories/action.pxd +29 -0
  18. sage/categories/action.pyx +641 -0
  19. sage/categories/algebra_functor.py +745 -0
  20. sage/categories/all__sagemath_objects.py +33 -0
  21. sage/categories/basic.py +62 -0
  22. sage/categories/cartesian_product.py +295 -0
  23. sage/categories/category.py +3401 -0
  24. sage/categories/category_cy_helper.cpython-314t-darwin.so +0 -0
  25. sage/categories/category_cy_helper.pxd +8 -0
  26. sage/categories/category_cy_helper.pyx +322 -0
  27. sage/categories/category_singleton.cpython-314t-darwin.so +0 -0
  28. sage/categories/category_singleton.pxd +3 -0
  29. sage/categories/category_singleton.pyx +342 -0
  30. sage/categories/category_types.py +637 -0
  31. sage/categories/category_with_axiom.py +2876 -0
  32. sage/categories/covariant_functorial_construction.py +703 -0
  33. sage/categories/facade_sets.py +228 -0
  34. sage/categories/functor.cpython-314t-darwin.so +0 -0
  35. sage/categories/functor.pxd +7 -0
  36. sage/categories/functor.pyx +691 -0
  37. sage/categories/homset.py +1338 -0
  38. sage/categories/homsets.py +364 -0
  39. sage/categories/isomorphic_objects.py +73 -0
  40. sage/categories/map.cpython-314t-darwin.so +0 -0
  41. sage/categories/map.pxd +34 -0
  42. sage/categories/map.pyx +2112 -0
  43. sage/categories/morphism.cpython-314t-darwin.so +0 -0
  44. sage/categories/morphism.pxd +14 -0
  45. sage/categories/morphism.pyx +895 -0
  46. sage/categories/objects.py +167 -0
  47. sage/categories/primer.py +1696 -0
  48. sage/categories/pushout.py +4834 -0
  49. sage/categories/quotients.py +64 -0
  50. sage/categories/realizations.py +200 -0
  51. sage/categories/sets_cat.py +3228 -0
  52. sage/categories/sets_with_partial_maps.py +52 -0
  53. sage/categories/subobjects.py +64 -0
  54. sage/categories/subquotients.py +21 -0
  55. sage/categories/with_realizations.py +311 -0
  56. sage/cpython/__init__.py +19 -0
  57. sage/cpython/_py2_random.py +619 -0
  58. sage/cpython/all.py +3 -0
  59. sage/cpython/atexit.cpython-314t-darwin.so +0 -0
  60. sage/cpython/atexit.pyx +269 -0
  61. sage/cpython/builtin_types.cpython-314t-darwin.so +0 -0
  62. sage/cpython/builtin_types.pyx +7 -0
  63. sage/cpython/cython_metaclass.cpython-314t-darwin.so +0 -0
  64. sage/cpython/cython_metaclass.h +117 -0
  65. sage/cpython/cython_metaclass.pxd +3 -0
  66. sage/cpython/cython_metaclass.pyx +130 -0
  67. sage/cpython/debug.cpython-314t-darwin.so +0 -0
  68. sage/cpython/debug.pyx +302 -0
  69. sage/cpython/dict_del_by_value.cpython-314t-darwin.so +0 -0
  70. sage/cpython/dict_del_by_value.pxd +9 -0
  71. sage/cpython/dict_del_by_value.pyx +191 -0
  72. sage/cpython/dict_internal.h +245 -0
  73. sage/cpython/getattr.cpython-314t-darwin.so +0 -0
  74. sage/cpython/getattr.pxd +9 -0
  75. sage/cpython/getattr.pyx +439 -0
  76. sage/cpython/pycore_long.h +97 -0
  77. sage/cpython/pycore_long.pxd +10 -0
  78. sage/cpython/python_debug.h +44 -0
  79. sage/cpython/python_debug.pxd +47 -0
  80. sage/cpython/pyx_visit.h +13 -0
  81. sage/cpython/string.cpython-314t-darwin.so +0 -0
  82. sage/cpython/string.pxd +76 -0
  83. sage/cpython/string.pyx +34 -0
  84. sage/cpython/string_impl.h +60 -0
  85. sage/cpython/type.cpython-314t-darwin.so +0 -0
  86. sage/cpython/type.pxd +2 -0
  87. sage/cpython/type.pyx +40 -0
  88. sage/cpython/wrapperdescr.pxd +67 -0
  89. sage/ext/all__sagemath_objects.py +3 -0
  90. sage/ext/ccobject.h +64 -0
  91. sage/ext/cplusplus.pxd +17 -0
  92. sage/ext/mod_int.h +30 -0
  93. sage/ext/mod_int.pxd +24 -0
  94. sage/ext/stdsage.pxd +39 -0
  95. sage/groups/all__sagemath_objects.py +1 -0
  96. sage/groups/group.cpython-314t-darwin.so +0 -0
  97. sage/groups/group.pxd +14 -0
  98. sage/groups/group.pyx +322 -0
  99. sage/groups/old.cpython-314t-darwin.so +0 -0
  100. sage/groups/old.pxd +14 -0
  101. sage/groups/old.pyx +219 -0
  102. sage/libs/all__sagemath_objects.py +3 -0
  103. sage/libs/gmp/__init__.py +1 -0
  104. sage/libs/gmp/all.pxd +6 -0
  105. sage/libs/gmp/binop.pxd +23 -0
  106. sage/libs/gmp/misc.pxd +8 -0
  107. sage/libs/gmp/mpf.pxd +88 -0
  108. sage/libs/gmp/mpn.pxd +57 -0
  109. sage/libs/gmp/mpq.pxd +57 -0
  110. sage/libs/gmp/mpz.pxd +202 -0
  111. sage/libs/gmp/pylong.cpython-314t-darwin.so +0 -0
  112. sage/libs/gmp/pylong.pxd +12 -0
  113. sage/libs/gmp/pylong.pyx +150 -0
  114. sage/libs/gmp/random.pxd +25 -0
  115. sage/libs/gmp/randomize.pxd +59 -0
  116. sage/libs/gmp/types.pxd +53 -0
  117. sage/libs/gmpxx.pxd +19 -0
  118. sage/misc/abstract_method.py +276 -0
  119. sage/misc/all__sagemath_objects.py +43 -0
  120. sage/misc/bindable_class.py +253 -0
  121. sage/misc/c3_controlled.cpython-314t-darwin.so +0 -0
  122. sage/misc/c3_controlled.pxd +2 -0
  123. sage/misc/c3_controlled.pyx +1402 -0
  124. sage/misc/cachefunc.cpython-314t-darwin.so +0 -0
  125. sage/misc/cachefunc.pxd +43 -0
  126. sage/misc/cachefunc.pyx +3781 -0
  127. sage/misc/call.py +188 -0
  128. sage/misc/classcall_metaclass.cpython-314t-darwin.so +0 -0
  129. sage/misc/classcall_metaclass.pxd +14 -0
  130. sage/misc/classcall_metaclass.pyx +599 -0
  131. sage/misc/constant_function.cpython-314t-darwin.so +0 -0
  132. sage/misc/constant_function.pyx +130 -0
  133. sage/misc/decorators.py +747 -0
  134. sage/misc/fast_methods.cpython-314t-darwin.so +0 -0
  135. sage/misc/fast_methods.pxd +20 -0
  136. sage/misc/fast_methods.pyx +351 -0
  137. sage/misc/flatten.py +90 -0
  138. sage/misc/fpickle.cpython-314t-darwin.so +0 -0
  139. sage/misc/fpickle.pyx +177 -0
  140. sage/misc/function_mangling.cpython-314t-darwin.so +0 -0
  141. sage/misc/function_mangling.pxd +11 -0
  142. sage/misc/function_mangling.pyx +308 -0
  143. sage/misc/inherit_comparison.cpython-314t-darwin.so +0 -0
  144. sage/misc/inherit_comparison.pxd +5 -0
  145. sage/misc/inherit_comparison.pyx +105 -0
  146. sage/misc/instancedoc.cpython-314t-darwin.so +0 -0
  147. sage/misc/instancedoc.pyx +331 -0
  148. sage/misc/lazy_attribute.cpython-314t-darwin.so +0 -0
  149. sage/misc/lazy_attribute.pyx +607 -0
  150. sage/misc/lazy_format.py +135 -0
  151. sage/misc/lazy_import.cpython-314t-darwin.so +0 -0
  152. sage/misc/lazy_import.pyx +1299 -0
  153. sage/misc/lazy_import_cache.py +36 -0
  154. sage/misc/lazy_list.cpython-314t-darwin.so +0 -0
  155. sage/misc/lazy_list.pxd +19 -0
  156. sage/misc/lazy_list.pyx +1187 -0
  157. sage/misc/lazy_string.cpython-314t-darwin.so +0 -0
  158. sage/misc/lazy_string.pxd +7 -0
  159. sage/misc/lazy_string.pyx +546 -0
  160. sage/misc/misc.py +1066 -0
  161. sage/misc/misc_c.cpython-314t-darwin.so +0 -0
  162. sage/misc/misc_c.pxd +3 -0
  163. sage/misc/misc_c.pyx +766 -0
  164. sage/misc/namespace_package.py +37 -0
  165. sage/misc/nested_class.cpython-314t-darwin.so +0 -0
  166. sage/misc/nested_class.pxd +3 -0
  167. sage/misc/nested_class.pyx +394 -0
  168. sage/misc/persist.cpython-314t-darwin.so +0 -0
  169. sage/misc/persist.pyx +1251 -0
  170. sage/misc/prandom.py +418 -0
  171. sage/misc/randstate.cpython-314t-darwin.so +0 -0
  172. sage/misc/randstate.pxd +30 -0
  173. sage/misc/randstate.pyx +1059 -0
  174. sage/misc/repr.py +203 -0
  175. sage/misc/reset.cpython-314t-darwin.so +0 -0
  176. sage/misc/reset.pyx +196 -0
  177. sage/misc/sage_ostools.cpython-314t-darwin.so +0 -0
  178. sage/misc/sage_ostools.pyx +323 -0
  179. sage/misc/sage_timeit.py +276 -0
  180. sage/misc/sage_timeit_class.cpython-314t-darwin.so +0 -0
  181. sage/misc/sage_timeit_class.pyx +120 -0
  182. sage/misc/sage_unittest.py +637 -0
  183. sage/misc/sageinspect.py +2768 -0
  184. sage/misc/session.cpython-314t-darwin.so +0 -0
  185. sage/misc/session.pyx +392 -0
  186. sage/misc/superseded.py +557 -0
  187. sage/misc/test_nested_class.py +228 -0
  188. sage/misc/timing.py +264 -0
  189. sage/misc/unknown.py +222 -0
  190. sage/misc/verbose.py +253 -0
  191. sage/misc/weak_dict.cpython-314t-darwin.so +0 -0
  192. sage/misc/weak_dict.pxd +15 -0
  193. sage/misc/weak_dict.pyx +1231 -0
  194. sage/modules/all__sagemath_objects.py +1 -0
  195. sage/modules/module.cpython-314t-darwin.so +0 -0
  196. sage/modules/module.pxd +5 -0
  197. sage/modules/module.pyx +329 -0
  198. sage/rings/all__sagemath_objects.py +3 -0
  199. sage/rings/integer_fake.h +22 -0
  200. sage/rings/integer_fake.pxd +55 -0
  201. sage/sets/all__sagemath_objects.py +3 -0
  202. sage/sets/pythonclass.cpython-314t-darwin.so +0 -0
  203. sage/sets/pythonclass.pxd +9 -0
  204. sage/sets/pythonclass.pyx +247 -0
  205. sage/structure/__init__.py +4 -0
  206. sage/structure/all.py +30 -0
  207. sage/structure/category_object.cpython-314t-darwin.so +0 -0
  208. sage/structure/category_object.pxd +28 -0
  209. sage/structure/category_object.pyx +1087 -0
  210. sage/structure/coerce.cpython-314t-darwin.so +0 -0
  211. sage/structure/coerce.pxd +44 -0
  212. sage/structure/coerce.pyx +2107 -0
  213. sage/structure/coerce_actions.cpython-314t-darwin.so +0 -0
  214. sage/structure/coerce_actions.pxd +27 -0
  215. sage/structure/coerce_actions.pyx +988 -0
  216. sage/structure/coerce_dict.cpython-314t-darwin.so +0 -0
  217. sage/structure/coerce_dict.pxd +51 -0
  218. sage/structure/coerce_dict.pyx +1557 -0
  219. sage/structure/coerce_exceptions.py +23 -0
  220. sage/structure/coerce_maps.cpython-314t-darwin.so +0 -0
  221. sage/structure/coerce_maps.pxd +28 -0
  222. sage/structure/coerce_maps.pyx +718 -0
  223. sage/structure/debug_options.cpython-314t-darwin.so +0 -0
  224. sage/structure/debug_options.pxd +6 -0
  225. sage/structure/debug_options.pyx +54 -0
  226. sage/structure/dynamic_class.py +541 -0
  227. sage/structure/element.cpython-314t-darwin.so +0 -0
  228. sage/structure/element.pxd +272 -0
  229. sage/structure/element.pyx +4772 -0
  230. sage/structure/element_wrapper.cpython-314t-darwin.so +0 -0
  231. sage/structure/element_wrapper.pxd +12 -0
  232. sage/structure/element_wrapper.pyx +582 -0
  233. sage/structure/factorization.py +1422 -0
  234. sage/structure/factorization_integer.py +105 -0
  235. sage/structure/factory.cpython-314t-darwin.so +0 -0
  236. sage/structure/factory.pyx +786 -0
  237. sage/structure/formal_sum.py +489 -0
  238. sage/structure/gens_py.py +73 -0
  239. sage/structure/global_options.py +1743 -0
  240. sage/structure/indexed_generators.py +863 -0
  241. sage/structure/list_clone.cpython-314t-darwin.so +0 -0
  242. sage/structure/list_clone.pxd +65 -0
  243. sage/structure/list_clone.pyx +1867 -0
  244. sage/structure/list_clone_demo.cpython-314t-darwin.so +0 -0
  245. sage/structure/list_clone_demo.pyx +248 -0
  246. sage/structure/list_clone_timings.py +179 -0
  247. sage/structure/list_clone_timings_cy.cpython-314t-darwin.so +0 -0
  248. sage/structure/list_clone_timings_cy.pyx +86 -0
  249. sage/structure/mutability.cpython-314t-darwin.so +0 -0
  250. sage/structure/mutability.pxd +21 -0
  251. sage/structure/mutability.pyx +348 -0
  252. sage/structure/nonexact.py +69 -0
  253. sage/structure/parent.cpython-314t-darwin.so +0 -0
  254. sage/structure/parent.pxd +112 -0
  255. sage/structure/parent.pyx +3093 -0
  256. sage/structure/parent_base.cpython-314t-darwin.so +0 -0
  257. sage/structure/parent_base.pxd +13 -0
  258. sage/structure/parent_base.pyx +44 -0
  259. sage/structure/parent_gens.cpython-314t-darwin.so +0 -0
  260. sage/structure/parent_gens.pxd +22 -0
  261. sage/structure/parent_gens.pyx +377 -0
  262. sage/structure/parent_old.cpython-314t-darwin.so +0 -0
  263. sage/structure/parent_old.pxd +25 -0
  264. sage/structure/parent_old.pyx +294 -0
  265. sage/structure/proof/__init__.py +1 -0
  266. sage/structure/proof/all.py +243 -0
  267. sage/structure/proof/proof.py +300 -0
  268. sage/structure/richcmp.cpython-314t-darwin.so +0 -0
  269. sage/structure/richcmp.pxd +213 -0
  270. sage/structure/richcmp.pyx +495 -0
  271. sage/structure/sage_object.cpython-314t-darwin.so +0 -0
  272. sage/structure/sage_object.pxd +3 -0
  273. sage/structure/sage_object.pyx +988 -0
  274. sage/structure/sage_object_test.py +19 -0
  275. sage/structure/sequence.py +937 -0
  276. sage/structure/set_factories.py +1178 -0
  277. sage/structure/set_factories_example.py +527 -0
  278. sage/structure/support_view.py +179 -0
  279. sage/structure/test_factory.py +56 -0
  280. sage/structure/unique_representation.py +1359 -0
@@ -0,0 +1,1299 @@
1
+ # sage_setup: distribution = sagemath-objects
2
+ r"""
3
+ Lazy imports
4
+
5
+ This module allows one to lazily import objects into a namespace,
6
+ where the actual import is delayed until the object is actually called
7
+ or inspected. This is useful for modules that are expensive to import
8
+ or may cause circular references, though there is some overhead in its
9
+ use.
10
+
11
+ EXAMPLES::
12
+
13
+ sage: lazy_import('sage.rings.integer_ring', 'ZZ')
14
+ sage: type(ZZ)
15
+ <class 'sage.misc.lazy_import.LazyImport'>
16
+ sage: ZZ(4.0)
17
+ 4
18
+
19
+ By default, a warning is issued if a lazy import module is resolved
20
+ during Sage's startup. In case a lazy import's sole purpose is to
21
+ break a circular reference and it is known to be resolved at startup
22
+ time, one can use the ``at_startup`` option::
23
+
24
+ sage: lazy_import('sage.rings.integer_ring', 'ZZ', at_startup=True)
25
+
26
+ This option can also be used as an intermediate step toward not
27
+ importing by default a module that is used in several places, some of
28
+ which can already afford to lazy import the module but not all.
29
+
30
+ A lazy import that is marked as "at_startup" will print a message if
31
+ it is actually resolved after the startup, so that the developer knows
32
+ that (s)he can remove the flag::
33
+
34
+ sage: ZZ # needs sage.all
35
+ doctest:warning...
36
+ UserWarning: Option ``at_startup=True`` for lazy import ZZ not needed anymore
37
+ Integer Ring
38
+
39
+ .. SEEALSO:: :func:`lazy_import`, :class:`LazyImport`
40
+
41
+ AUTHOR:
42
+
43
+ - Robert Bradshaw
44
+ """
45
+
46
+ # ****************************************************************************
47
+ # Copyright (C) 2009 Robert Bradshaw <robertwb@math.washington.edu>
48
+ #
49
+ # This program is free software: you can redistribute it and/or modify
50
+ # it under the terms of the GNU General Public License as published by
51
+ # the Free Software Foundation, either version 2 of the License, or
52
+ # (at your option) any later version.
53
+ # https://www.gnu.org/licenses/
54
+ # ****************************************************************************
55
+
56
+ # Keep OLD division semantics for Python 2 compatibility, such that
57
+ # lazy imports support old and true division.
58
+
59
+ cimport cython
60
+ from cpython.object cimport PyObject_RichCompare
61
+ from cpython.number cimport PyNumber_TrueDivide, PyNumber_Power, PyNumber_Index
62
+
63
+ cdef extern from *:
64
+ int likely(int) nogil # Defined by Cython
65
+
66
+ import os
67
+ import pickle
68
+ from warnings import warn
69
+ import inspect
70
+ from sage.misc import sageinspect
71
+
72
+
73
+ # LazyImport.__repr__ uses try... except FeatureNotPresentError.
74
+ # This is defined in sage.features, provided by the distribution sagemath-environment.
75
+ try:
76
+ from sage.features import FeatureNotPresentError
77
+ except ImportError:
78
+ # If sage.features cannot be imported, then FeatureNotPresentError cannot
79
+ # be raised. In this case, use the empty tuple as the exception specification.
80
+ FeatureNotPresentError = ()
81
+
82
+
83
+ cdef inline obj(x):
84
+ if type(x) is LazyImport:
85
+ return (<LazyImport>x).get_object()
86
+ else:
87
+ return x
88
+
89
+
90
+ # boolean to determine whether Sage is still starting up
91
+ cdef bint startup_guard = False
92
+
93
+ cdef bint finish_startup_called = False
94
+
95
+
96
+ cpdef finish_startup():
97
+ """
98
+ Finish the startup phase.
99
+
100
+ This function must be called exactly once at the end of the Sage
101
+ import process (:mod:`~sage.all`).
102
+
103
+ TESTS::
104
+
105
+ sage: from sage.misc.lazy_import import finish_startup
106
+ sage: finish_startup()
107
+ Traceback (most recent call last):
108
+ ...
109
+ AssertionError: finish_startup() must be called exactly once
110
+ """
111
+ global startup_guard, finish_startup_called
112
+ assert startup_guard, 'finish_startup() must be called exactly once'
113
+ startup_guard = False
114
+ finish_startup_called = True
115
+
116
+
117
+ cpdef commence_startup():
118
+ """
119
+ Begin the startup phase.
120
+
121
+ This should only be called once, and only during the monolithic startup (:mod:`~sage.all`).
122
+ """
123
+ global startup_guard
124
+ assert not startup_guard and not finish_startup_called, 'commence_startup() can only be called once, and not after finish_startup()'
125
+ startup_guard = True
126
+
127
+
128
+ cpdef ensure_startup_finished():
129
+ """
130
+ Make sure that the startup phase is finished.
131
+
132
+ In contrast to :func:`finish_startup`, this function can
133
+ be called repeatedly.
134
+
135
+ TESTS::
136
+
137
+ sage: from sage.misc.lazy_import import ensure_startup_finished
138
+ sage: ensure_startup_finished()
139
+ """
140
+ global startup_guard
141
+ startup_guard = False
142
+
143
+
144
+ cpdef bint is_during_startup() noexcept:
145
+ """
146
+ Return whether Sage is currently starting up.
147
+
148
+ OUTPUT: boolean
149
+
150
+ TESTS::
151
+
152
+ sage: from sage.misc.lazy_import import is_during_startup
153
+ sage: is_during_startup()
154
+ False
155
+ """
156
+ global startup_guard
157
+ return startup_guard
158
+
159
+
160
+ cpdef test_fake_startup():
161
+ """
162
+ For testing purposes only.
163
+
164
+ Switch the startup lazy import guard back on.
165
+
166
+ EXAMPLES::
167
+
168
+ sage: sage.misc.lazy_import.test_fake_startup()
169
+ sage: lazy_import('sage.rings.integer_ring', 'ZZ', 'my_ZZ')
170
+ sage: my_ZZ(123)
171
+ doctest:warning...
172
+ UserWarning: Resolving lazy import ZZ during startup
173
+ 123
174
+ sage: sage.misc.lazy_import.finish_startup()
175
+ """
176
+ global startup_guard, finish_startup_called
177
+ startup_guard = True
178
+ finish_startup_called = False
179
+
180
+
181
+ @cython.final
182
+ cdef class LazyImport():
183
+ """
184
+ EXAMPLES::
185
+
186
+ sage: from sage.misc.lazy_import import LazyImport
187
+ sage: my_integer = LazyImport('sage.rings.integer', 'Integer')
188
+ sage: my_integer(4)
189
+ 4
190
+ sage: my_integer('101', base=2)
191
+ 5
192
+ sage: my_integer(3/2)
193
+ Traceback (most recent call last):
194
+ ...
195
+ TypeError: no conversion of this rational to integer
196
+ """
197
+ cdef readonly _object # The actual object if imported, None otherwise
198
+ cdef _module
199
+ cdef _name
200
+ cdef _as_name
201
+ cdef _namespace
202
+ cdef bint _at_startup
203
+ cdef _deprecation
204
+ cdef _feature
205
+
206
+ def __init__(self, module, name, as_name=None, at_startup=False, namespace=None,
207
+ deprecation=None, feature=None):
208
+ """
209
+ EXAMPLES::
210
+
211
+ sage: from sage.misc.lazy_import import LazyImport
212
+ sage: lazy_ZZ = LazyImport('sage.rings.integer_ring', 'ZZ')
213
+ sage: type(lazy_ZZ)
214
+ <class 'sage.misc.lazy_import.LazyImport'>
215
+ sage: lazy_ZZ._get_object() is ZZ
216
+ True
217
+ sage: type(lazy_ZZ)
218
+ <class 'sage.misc.lazy_import.LazyImport'>
219
+ """
220
+ self._object = None
221
+ self._module = module
222
+ self._name = name
223
+ self._as_name = name if as_name is None else as_name
224
+ self._namespace = namespace
225
+ self._at_startup = at_startup
226
+ self._deprecation = deprecation
227
+ self._feature = feature
228
+
229
+ cdef inline get_object(self):
230
+ """
231
+ Faster, Cython-only partially-inlined version of ``_get_object``.
232
+ """
233
+ if likely(self._object is not None):
234
+ return self._object
235
+ return self._get_object()
236
+
237
+ cpdef _get_object(self):
238
+ """
239
+ Return the wrapped object, importing it if necessary.
240
+
241
+ OUTPUT: the wrapped object
242
+
243
+ EXAMPLES::
244
+
245
+ sage: from sage.misc.lazy_import import LazyImport
246
+ sage: my_integer_ring = LazyImport('sage.rings.integer_ring', 'ZZ')
247
+ sage: my_integer_ring._object is None
248
+ True
249
+ sage: my_integer_ring._get_object()
250
+ Integer Ring
251
+ sage: my_integer_ring._object is None
252
+ False
253
+ sage: my_rats = LazyImport('sage.rings.rational_field', 'QQ', at_startup=True)
254
+ sage: my_rats
255
+ doctest:warning...
256
+ UserWarning: Option ``at_startup=True`` for lazy import QQ not needed anymore
257
+ Rational Field
258
+ """
259
+ if self._object is not None:
260
+ return self._object
261
+
262
+ if startup_guard and not self._at_startup:
263
+ warn(f"Resolving lazy import {self._name} during startup")
264
+ elif self._at_startup and not startup_guard:
265
+ if finish_startup_called:
266
+ warn(f"Option ``at_startup=True`` for lazy import {self._name} not needed anymore")
267
+
268
+ feature = self._feature
269
+ try:
270
+ self._object = getattr(__import__(self._module, {}, {}, [self._name]), self._name)
271
+ except ImportError as e:
272
+ if feature:
273
+ # Avoid warnings from static type checkers by explicitly importing FeatureNotPresentError.
274
+ from sage.features import FeatureNotPresentError
275
+ raise FeatureNotPresentError(feature, reason=f'Importing {self._name} failed: {e}')
276
+ raise
277
+
278
+ if feature:
279
+ # for the case that the feature is hidden
280
+ feature.require()
281
+
282
+ if self._deprecation is not None:
283
+ from sage.misc.superseded import deprecation_cython as deprecation
284
+ try:
285
+ issue_number, message = self._deprecation
286
+ except TypeError:
287
+ issue_number = self._deprecation
288
+ import_command = f'from {self._module} import {self._name}'
289
+ if self._as_name != self._name:
290
+ import_command += f' as {self._as_name}'
291
+ message = f'\nImporting {self._as_name} from here is deprecated; please use "{import_command}" instead.'
292
+ deprecation(issue_number, message)
293
+ # Replace the lazy import in the namespace by the actual object
294
+ name = self._as_name
295
+ if self._namespace is not None:
296
+ if self._namespace.get(name) is self:
297
+ self._namespace[name] = self._object
298
+ return self._object
299
+
300
+ def _get_deprecation_issue(self):
301
+ """
302
+ Return the issue number of the deprecation, or 0 if this lazy
303
+ import is not deprecated.
304
+
305
+ EXAMPLES::
306
+
307
+ sage: from sage.misc.lazy_import import LazyImport
308
+ sage: H = LazyImport('sage.categories.homsets', 'Homsets')
309
+ sage: H._get_deprecation_issue()
310
+ 0
311
+ sage: H = LazyImport('sage.categories.homsets', 'Homsets', deprecation=10668)
312
+ sage: H._get_deprecation_issue()
313
+ 10668
314
+ sage: H = LazyImport('sage.categories.homsets', 'Homsets', deprecation=(10668, "this is deprecated"))
315
+ sage: H._get_deprecation_issue()
316
+ 10668
317
+ """
318
+ if self._deprecation is None:
319
+ return 0
320
+ try:
321
+ return self._deprecation[0]
322
+ except TypeError:
323
+ return self._deprecation
324
+
325
+ def _instancedoc_(self):
326
+ """
327
+ Return the docstring of the wrapped object for introspection.
328
+
329
+ EXAMPLES::
330
+
331
+ sage: from sage.misc.lazy_import import LazyImport
332
+ sage: my_isprime = LazyImport('sage.arith.misc', 'is_prime')
333
+ sage: my_isprime.__doc__ is is_prime.__doc__
334
+ True
335
+
336
+ TESTS:
337
+
338
+ Check that :issue:`19475` is fixed::
339
+
340
+ sage: 'A subset of the real line' in RealSet.__doc__
341
+ True
342
+ """
343
+ return sageinspect.sage_getdoc_original(self.get_object())
344
+
345
+ def _sage_src_(self):
346
+ """
347
+ Return the source of the wrapped object for introspection.
348
+
349
+ EXAMPLES::
350
+
351
+ sage: from sage.misc.lazy_import import LazyImport
352
+ sage: my_isprime = LazyImport('sage.arith.misc', 'is_prime')
353
+ sage: 'def is_prime(' in my_isprime._sage_src_()
354
+ True
355
+ """
356
+ return sageinspect.sage_getsource(self.get_object())
357
+
358
+ def _sage_argspec_(self):
359
+ """
360
+ Return the argspec of the wrapped object for introspection.
361
+
362
+ EXAMPLES::
363
+
364
+ sage: from sage.misc.lazy_import import LazyImport
365
+ sage: rm = LazyImport('sage.matrix.special', 'random_matrix')
366
+ sage: rm._sage_argspec_() # needs sage.modules
367
+ FullArgSpec(args=['ring', 'nrows', 'ncols', 'algorithm', 'implementation'],
368
+ varargs='args', varkw='kwds', defaults=(None, 'randomize', None),
369
+ kwonlyargs=[], kwonlydefaults=None, annotations={})
370
+ """
371
+ return sageinspect.sage_getargspec(self.get_object())
372
+
373
+ def __getattr__(self, attr):
374
+ """
375
+ Attribute lookup on ``self`` defers to attribute lookup on the
376
+ wrapped object.
377
+
378
+ EXAMPLES::
379
+
380
+ sage: from sage.misc.lazy_import import LazyImport
381
+ sage: my_integer = LazyImport('sage.rings.integer', 'Integer')
382
+ sage: my_integer.sqrt is Integer.sqrt
383
+ True
384
+ """
385
+ return getattr(self.get_object(), attr)
386
+
387
+ # We need to wrap all the slot methods, as they are not forwarded
388
+ # via getattr.
389
+
390
+ def __dir__(self):
391
+ """
392
+ Tab completion on ``self`` defers to completion on the wrapped
393
+ object.
394
+
395
+ EXAMPLES::
396
+
397
+ sage: from sage.misc.lazy_import import LazyImport
398
+ sage: lazy_ZZ = LazyImport('sage.rings.integer_ring', 'ZZ')
399
+ sage: dir(lazy_ZZ) == dir(ZZ)
400
+ True
401
+ """
402
+ return dir(self.get_object())
403
+
404
+ def __call__(self, *args, **kwds):
405
+ """
406
+ Calling ``self`` calls the wrapped object.
407
+
408
+ EXAMPLES::
409
+
410
+ sage: from sage.misc.lazy_import import LazyImport
411
+ sage: my_isprime = LazyImport('sage.arith.misc', 'is_prime')
412
+ sage: is_prime(12) == my_isprime(12)
413
+ True
414
+ sage: is_prime(13) == my_isprime(13)
415
+ True
416
+ """
417
+ return self.get_object()(*args, **kwds)
418
+
419
+ def __repr__(self):
420
+ """
421
+ TESTS::
422
+
423
+ sage: from sage.misc.lazy_import import LazyImport
424
+ sage: lazy_ZZ = LazyImport('sage.rings.integer_ring', 'ZZ')
425
+ sage: repr(lazy_ZZ) == repr(ZZ)
426
+ True
427
+ """
428
+ try:
429
+ obj = self.get_object()
430
+ return repr(obj)
431
+ except FeatureNotPresentError as e:
432
+ return "Failed lazy import:\n" + str(e)
433
+
434
+ def __str__(self):
435
+ """
436
+ TESTS::
437
+
438
+ sage: from sage.misc.lazy_import import LazyImport
439
+ sage: lazy_ZZ = LazyImport('sage.rings.integer_ring', 'ZZ')
440
+ sage: str(lazy_ZZ) == str(ZZ)
441
+ True
442
+ """
443
+ return str(self.get_object())
444
+
445
+ def __bool__(self):
446
+ """
447
+ TESTS::
448
+
449
+ sage: from sage.misc.lazy_import import LazyImport
450
+ sage: lazy_ZZ = LazyImport('sage.rings.integer_ring', 'ZZ')
451
+ sage: bool(lazy_ZZ) == bool(ZZ)
452
+ True
453
+ """
454
+ return bool(self.get_object())
455
+
456
+ def __hash__(self):
457
+ """
458
+ TESTS::
459
+
460
+ sage: from sage.misc.lazy_import import LazyImport
461
+ sage: lazy_ZZ = LazyImport('sage.rings.integer_ring', 'ZZ')
462
+ sage: hash(lazy_ZZ) == hash(ZZ)
463
+ True
464
+ """
465
+ return hash(self.get_object())
466
+
467
+ def __richcmp__(left, right, int op):
468
+ """
469
+ TESTS::
470
+
471
+ sage: from sage.misc.lazy_import import LazyImport
472
+ sage: lazy_ZZ = LazyImport('sage.rings.integer_ring', 'ZZ')
473
+ sage: lazy_ZZ == ZZ
474
+ True
475
+ sage: lazy_ZZ == RR
476
+ False
477
+ """
478
+ return PyObject_RichCompare(obj(left), obj(right), op)
479
+
480
+ def __len__(self):
481
+ """
482
+ TESTS::
483
+
484
+ sage: lazy_import('sys', 'version_info')
485
+ sage: type(version_info)
486
+ <class 'sage.misc.lazy_import.LazyImport'>
487
+ sage: len(version_info)
488
+ 5
489
+ """
490
+ return len(self.get_object())
491
+
492
+ def __get__(self, instance, owner):
493
+ """
494
+ EXAMPLES:
495
+
496
+ Here we show how to take a function in a module, and lazy
497
+ import it as a method of a class. For the sake of this
498
+ example, we add manually a function in :mod:`sage.all__sagemath_objects`::
499
+
500
+ sage: def my_method(self): return self
501
+ sage: import sage.all__sagemath_objects
502
+ sage: sage.all__sagemath_objects.my_method = my_method
503
+
504
+ Now we lazy import it as a method of a new class ``Foo``::
505
+
506
+ sage: from sage.misc.lazy_import import LazyImport
507
+ sage: class Foo():
508
+ ....: my_method = LazyImport('sage.all__sagemath_objects', 'my_method')
509
+
510
+ Now we can use it as a usual method::
511
+
512
+ sage: Foo().my_method()
513
+ <__main__.Foo object at ...>
514
+ sage: Foo.my_method
515
+ <function my_method at 0x...>
516
+ sage: Foo().my_method
517
+ <bound method my_method of <__main__.Foo object at ...>>
518
+
519
+ When a :class:`LazyImport` method is a method (or attribute)
520
+ of a class, then extra work must be done to replace this
521
+ :class:`LazyImport` object with the actual object. See the
522
+ documentation of :meth:`_get_object` for an explanation of
523
+ this.
524
+
525
+ .. NOTE::
526
+
527
+ For a :class:`LazyImport` object that appears in a class
528
+ namespace, we need to do something special. Indeed, the
529
+ class namespace dictionary at the time of the class
530
+ definition is not the one that actually gets used. Thus,
531
+ ``__get__`` needs to manually modify the class dict::
532
+
533
+ sage: class Foo():
534
+ ....: lazy_import('sage.plot.plot', 'plot')
535
+ sage: class Bar(Foo):
536
+ ....: pass
537
+ sage: type(Foo.__dict__['plot'])
538
+ <class 'sage.misc.lazy_import.LazyImport'>
539
+
540
+ We access the ``plot`` method::
541
+
542
+ sage: Bar.plot # needs sage.plot
543
+ <function plot at 0x...>
544
+
545
+ Now ``plot`` has been replaced in the dictionary of ``Foo``::
546
+
547
+ sage: type(Foo.__dict__['plot']) # needs sage.plot
548
+ <... 'function'>
549
+ """
550
+ # Don't use the namespace of the class definition
551
+ self._namespace = None
552
+ obj = self.get_object()
553
+
554
+ name = self._as_name
555
+ for cls in inspect.getmro(owner):
556
+ if cls.__dict__.get(name) is self:
557
+ setattr(cls, name, obj)
558
+ break
559
+
560
+ # Check whether the imported object is itself a descriptor
561
+ try:
562
+ get = obj.__get__
563
+ except AttributeError:
564
+ return obj
565
+ else:
566
+ return get(instance, owner)
567
+
568
+ def __getitem__(self, key):
569
+ """
570
+ TESTS::
571
+
572
+ sage: import sys
573
+ sage: py_version = sys.version_info[0]
574
+ sage: lazy_import('sys', 'version_info')
575
+ sage: version_info[0] == py_version
576
+ True
577
+ """
578
+ return self.get_object()[key]
579
+
580
+ def __setitem__(self, key, value):
581
+ """
582
+ TESTS::
583
+
584
+ sage: from sage.misc.lazy_import import LazyImport
585
+ sage: import sage.all__sagemath_objects
586
+ sage: sage.all__sagemath_objects.foo = list(range(10))
587
+ sage: lazy_foo = LazyImport('sage.all__sagemath_objects', 'foo')
588
+ sage: lazy_foo[1] = 100
589
+ sage: print(lazy_foo)
590
+ [0, 100, 2, 3, 4, 5, 6, 7, 8, 9]
591
+ sage: sage.all__sagemath_objects.foo
592
+ [0, 100, 2, 3, 4, 5, 6, 7, 8, 9]
593
+ """
594
+ self.get_object()[key] = value
595
+
596
+ def __delitem__(self, key):
597
+ """
598
+ TESTS::
599
+
600
+ sage: from sage.misc.lazy_import import LazyImport
601
+ sage: import sage.all__sagemath_objects
602
+ sage: sage.all__sagemath_objects.foo = list(range(10))
603
+ sage: lazy_foo = LazyImport('sage.all__sagemath_objects', 'foo')
604
+ sage: del lazy_foo[1]
605
+ sage: print(lazy_foo)
606
+ [0, 2, 3, 4, 5, 6, 7, 8, 9]
607
+ sage: print(sage.all__sagemath_objects.foo)
608
+ [0, 2, 3, 4, 5, 6, 7, 8, 9]
609
+ """
610
+ del self.get_object()[key]
611
+
612
+ def __iter__(self):
613
+ """
614
+ TESTS::
615
+
616
+ sage: lazy_import('sys', 'version_info')
617
+ sage: iter(version_info)
618
+ <...iterator object at ...>
619
+ """
620
+ return iter(self.get_object())
621
+
622
+ def __contains__(self, item):
623
+ """
624
+ TESTS::
625
+
626
+ sage: import sys
627
+ sage: py_version = sys.version_info[0]
628
+ sage: lazy_import('sys', 'version_info')
629
+ sage: py_version in version_info
630
+ True
631
+
632
+ sage: lazy_import('sys', 'version_info')
633
+ sage: 2000 not in version_info
634
+ True
635
+ """
636
+ return item in self.get_object()
637
+
638
+ def __add__(left, right):
639
+ """
640
+ TESTS::
641
+
642
+ sage: import sage.all__sagemath_objects
643
+ sage: sage.all__sagemath_objects.foo = 10
644
+ sage: lazy_import('sage.all__sagemath_objects', 'foo')
645
+ sage: foo + 1
646
+ 11
647
+ """
648
+ return obj(left) + obj(right)
649
+
650
+ def __sub__(left, right):
651
+ """
652
+ TESTS::
653
+
654
+ sage: import sage.all__sagemath_objects
655
+ sage: sage.all__sagemath_objects.foo = 10
656
+ sage: lazy_import('sage.all__sagemath_objects', 'foo')
657
+ sage: foo - 1
658
+ 9
659
+ """
660
+ return obj(left) - obj(right)
661
+
662
+ def __mul__(left, right):
663
+ """
664
+ TESTS::
665
+
666
+ sage: import sage.all__sagemath_objects
667
+ sage: sage.all__sagemath_objects.foo = 10
668
+ sage: lazy_import('sage.all__sagemath_objects', 'foo')
669
+ sage: foo * 2
670
+ 20
671
+ """
672
+ return obj(left) * obj(right)
673
+
674
+ def __matmul__(left, right):
675
+ """
676
+ TESTS::
677
+
678
+ sage: # needs sympy
679
+ sage: from sympy import Matrix
680
+ sage: import sage.all__sagemath_objects
681
+ sage: sage.all__sagemath_objects.foo = Matrix([[1,1], [0,1]])
682
+ sage: lazy_import('sage.all__sagemath_objects', 'foo')
683
+ sage: foo.__matmul__(foo)
684
+ Matrix([
685
+ [1, 2],
686
+ [0, 1]])
687
+ """
688
+ return obj(left) @ obj(right)
689
+
690
+ def __floordiv__(left, right):
691
+ """
692
+ TESTS::
693
+
694
+ sage: import sage.all__sagemath_objects
695
+ sage: sage.all__sagemath_objects.foo = 10
696
+ sage: lazy_import('sage.all__sagemath_objects', 'foo')
697
+ sage: foo // 3
698
+ 3
699
+ """
700
+ return obj(left) // obj(right)
701
+
702
+ def __truediv__(left, right):
703
+ """
704
+ TESTS::
705
+
706
+ sage: import sage.all__sagemath_objects
707
+ sage: sage.all__sagemath_objects.foo = 10
708
+ sage: lazy_import('sage.all__sagemath_objects', 'foo')
709
+ sage: operator.truediv(foo, 3)
710
+ 10/3
711
+ """
712
+ return PyNumber_TrueDivide(obj(left), obj(right))
713
+
714
+ def __pow__(left, right, mod):
715
+ """
716
+ TESTS::
717
+
718
+ sage: import sage.all__sagemath_objects
719
+ sage: sage.all__sagemath_objects.foo = 10
720
+ sage: lazy_import('sage.all__sagemath_objects', 'foo')
721
+ sage: foo ** 2
722
+ 100
723
+ """
724
+ return PyNumber_Power(obj(left), obj(right), obj(mod))
725
+
726
+ def __mod__(left, right):
727
+ """
728
+ TESTS::
729
+
730
+ sage: import sage.all__sagemath_objects
731
+ sage: sage.all__sagemath_objects.foo = 10
732
+ sage: lazy_import('sage.all__sagemath_objects', 'foo')
733
+ sage: foo % 7
734
+ 3
735
+ """
736
+ return obj(left) % obj(right)
737
+
738
+ def __lshift__(left, right):
739
+ """
740
+ TESTS::
741
+
742
+ sage: import sage.all__sagemath_objects
743
+ sage: sage.all__sagemath_objects.foo = 10
744
+ sage: lazy_import('sage.all__sagemath_objects', 'foo')
745
+ sage: foo << 3
746
+ 80
747
+ """
748
+ return obj(left) << obj(right)
749
+
750
+ def __rshift__(left, right):
751
+ """
752
+ TESTS::
753
+
754
+ sage: import sage.all__sagemath_objects
755
+ sage: sage.all__sagemath_objects.foo = 10
756
+ sage: lazy_import('sage.all__sagemath_objects', 'foo')
757
+ sage: foo >> 2
758
+ 2
759
+ """
760
+ return obj(left) >> obj(right)
761
+
762
+ def __and__(left, right):
763
+ """
764
+ TESTS::
765
+
766
+ sage: import sage.all__sagemath_objects
767
+ sage: sage.all__sagemath_objects.foo = 10
768
+ sage: lazy_import('sage.all__sagemath_objects', 'foo')
769
+ sage: foo & 7
770
+ 2
771
+ """
772
+ return obj(left) & obj(right)
773
+
774
+ def __or__(left, right):
775
+ """
776
+ TESTS::
777
+
778
+ sage: import sage.all__sagemath_objects
779
+ sage: sage.all__sagemath_objects.foo = 10
780
+ sage: lazy_import('sage.all__sagemath_objects', 'foo')
781
+ sage: foo | 7
782
+ 15
783
+ """
784
+ return obj(left) | obj(right)
785
+
786
+ def __xor__(left, right):
787
+ """
788
+ TESTS::
789
+
790
+ sage: import sage.all__sagemath_objects
791
+ sage: sage.all__sagemath_objects.foo = 10
792
+ sage: lazy_import('sage.all__sagemath_objects', 'foo')
793
+ sage: foo ^^ 7
794
+ 13
795
+ """
796
+ return obj(left) ^ obj(right)
797
+
798
+ def __neg__(self):
799
+ """
800
+ TESTS::
801
+
802
+ sage: import sage.all__sagemath_objects
803
+ sage: sage.all__sagemath_objects.foo = 10
804
+ sage: lazy_import('sage.all__sagemath_objects', 'foo')
805
+ sage: -foo
806
+ -10
807
+ """
808
+ return -self.get_object()
809
+
810
+ def __pos__(self):
811
+ """
812
+ TESTS::
813
+
814
+ sage: import sage.all__sagemath_objects
815
+ sage: sage.all__sagemath_objects.foo = 10
816
+ sage: lazy_import('sage.all__sagemath_objects', 'foo')
817
+ sage: +foo
818
+ 10
819
+ """
820
+ return +self.get_object()
821
+
822
+ def __abs__(self):
823
+ """
824
+ TESTS::
825
+
826
+ sage: import sage.all__sagemath_objects
827
+ sage: sage.all__sagemath_objects.foo = -1000
828
+ sage: lazy_import('sage.all__sagemath_objects', 'foo')
829
+ sage: abs(foo)
830
+ 1000
831
+ """
832
+ return abs(self.get_object())
833
+
834
+ def __invert__(self):
835
+ """
836
+ TESTS::
837
+
838
+ sage: import sage.all__sagemath_objects
839
+ sage: sage.all__sagemath_objects.foo = 10
840
+ sage: lazy_import('sage.all__sagemath_objects', 'foo')
841
+ sage: ~foo
842
+ 1/10
843
+ """
844
+ return ~self.get_object()
845
+
846
+ def __complex__(self):
847
+ """
848
+ TESTS::
849
+
850
+ sage: import sage.all__sagemath_objects
851
+ sage: sage.all__sagemath_objects.foo = 10
852
+ sage: lazy_import('sage.all__sagemath_objects', 'foo')
853
+ sage: complex(foo)
854
+ (10+0j)
855
+ """
856
+ return complex(self.get_object())
857
+
858
+ def __int__(self):
859
+ """
860
+ TESTS::
861
+
862
+ sage: import sage.all__sagemath_objects
863
+ sage: sage.all__sagemath_objects.foo = 10
864
+ sage: lazy_import('sage.all__sagemath_objects', 'foo')
865
+ sage: int(foo)
866
+ 10
867
+ """
868
+ return int(self.get_object())
869
+
870
+ def __float__(self):
871
+ """
872
+ TESTS::
873
+
874
+ sage: import sage.all__sagemath_objects
875
+ sage: sage.all__sagemath_objects.foo = 10
876
+ sage: lazy_import('sage.all__sagemath_objects', 'foo')
877
+ sage: float(foo)
878
+ 10.0
879
+ """
880
+ return float(self.get_object())
881
+
882
+ def __oct__(self):
883
+ """
884
+ TESTS::
885
+
886
+ sage: import sage.all__sagemath_objects
887
+ sage: sage.all__sagemath_objects.foo = 10
888
+ sage: lazy_import('sage.all__sagemath_objects', 'foo')
889
+ sage: oct(foo)
890
+ '0o12'
891
+ """
892
+ return self.get_object().__oct__()
893
+
894
+ def __hex__(self):
895
+ """
896
+ TESTS::
897
+
898
+ sage: import sage.all__sagemath_objects
899
+ sage: sage.all__sagemath_objects.foo = 10
900
+ sage: lazy_import('sage.all__sagemath_objects', 'foo')
901
+ sage: hex(foo)
902
+ '0xa'
903
+ """
904
+ return self.get_object().__hex__()
905
+
906
+ def __index__(self):
907
+ """
908
+ TESTS::
909
+
910
+ sage: import sage.all__sagemath_objects
911
+ sage: sage.all__sagemath_objects.foo = 10
912
+ sage: lazy_import('sage.all__sagemath_objects', 'foo')
913
+ sage: list(range(100))[foo]
914
+ 10
915
+ """
916
+ return PyNumber_Index(self.get_object())
917
+
918
+ def __copy__(self):
919
+ """
920
+ Support ``copy()``.
921
+
922
+ TESTS::
923
+
924
+ sage: from sage.misc.lazy_import import LazyImport
925
+ sage: import sage.all__sagemath_objects
926
+ sage: sage.all__sagemath_objects.foo = [[1,2], 3]
927
+ sage: lazy_foo = LazyImport('sage.all__sagemath_objects', 'foo')
928
+ sage: a = copy(lazy_foo)
929
+ sage: a is sage.all__sagemath_objects.foo # copy
930
+ False
931
+ sage: a[0] is sage.all__sagemath_objects.foo[0] # copy but not deep
932
+ True
933
+ sage: type(lazy_foo) is LazyImport
934
+ True
935
+ """
936
+ import copy
937
+ return copy.copy(self.get_object())
938
+
939
+ def __deepcopy__(self, memo=None):
940
+ """
941
+ Support ``copy()``.
942
+
943
+ TESTS::
944
+
945
+ sage: from sage.misc.lazy_import import LazyImport
946
+ sage: import sage.all__sagemath_objects
947
+ sage: sage.all__sagemath_objects.foo = [[1,2], 3]
948
+ sage: lazy_foo = LazyImport('sage.all__sagemath_objects', 'foo')
949
+ sage: a = deepcopy(lazy_foo)
950
+ sage: a is sage.all__sagemath_objects.foo # copy
951
+ False
952
+ sage: a[0] is sage.all__sagemath_objects.foo[0] # deep copy
953
+ False
954
+ sage: type(lazy_foo) is LazyImport
955
+ True
956
+ """
957
+ import copy
958
+ return copy.deepcopy(self.get_object())
959
+
960
+ def __instancecheck__(self, x):
961
+ """
962
+ Support ``isinstance()``.
963
+
964
+ EXAMPLES::
965
+
966
+ sage: lazy_import('sage.rings.rational_field', 'RationalField')
967
+ sage: isinstance(QQ, RationalField)
968
+ True
969
+
970
+ No object is an instance of a class that cannot be imported::
971
+
972
+ sage: lazy_import('sage.xxxxx_does_not_exist', 'DoesNotExist')
973
+ sage: isinstance(QQ, DoesNotExist)
974
+ False
975
+ """
976
+ try:
977
+ return isinstance(x, self.get_object())
978
+ except ImportError:
979
+ return False
980
+
981
+ def __subclasscheck__(self, x):
982
+ """
983
+ Support ``issubclass()``.
984
+
985
+ EXAMPLES::
986
+
987
+ sage: lazy_import('sage.structure.parent', 'Parent')
988
+ sage: issubclass(RationalField, Parent)
989
+ True
990
+
991
+ No class is a subclass of a class that cannot be imported::
992
+
993
+ sage: lazy_import('sage.xxxxx_does_not_exist', 'DoesNotExist')
994
+ sage: issubclass(RationalField, DoesNotExist)
995
+ False
996
+ """
997
+ try:
998
+ return issubclass(x, self.get_object())
999
+ except ImportError:
1000
+ return False
1001
+
1002
+
1003
+ def lazy_import(module, names, as_=None, *,
1004
+ at_startup=False, namespace=None,
1005
+ deprecation=None, feature=None):
1006
+ """
1007
+ Create a lazy import object and inject it into the caller's global
1008
+ namespace. For the purposes of introspection and calling, this is
1009
+ like performing a lazy "from module import name" where the import
1010
+ is delayed until the object actually is used or inspected.
1011
+
1012
+ INPUT:
1013
+
1014
+ - ``module`` -- string representing the module to import
1015
+
1016
+ - ``names`` -- string or list of strings representing the names to
1017
+ import from module
1018
+
1019
+ - ``as_`` -- (optional) a string or list of strings representing the
1020
+ names of the objects in the importing module. This is analogous to
1021
+ ``from ... import ... as ...``.
1022
+
1023
+ - ``at_startup`` -- boolean (default: ``False``);
1024
+ whether the lazy import is supposed to be resolved at startup time
1025
+
1026
+ - ``namespace`` -- the namespace where importing the names; by default,
1027
+ import the names to current namespace
1028
+
1029
+ - ``deprecation`` -- (optional) if not ``None``, a deprecation warning
1030
+ will be issued when the object is actually imported;
1031
+ ``deprecation`` should be either a trac number (integer) or a
1032
+ pair ``(issue_number, message)``
1033
+
1034
+ - ``feature`` -- a python module (optional), if it cannot be imported
1035
+ an appropriate error is raised
1036
+
1037
+ .. SEEALSO:: :mod:`sage.misc.lazy_import`, :class:`LazyImport`
1038
+
1039
+ EXAMPLES::
1040
+
1041
+ sage: lazy_import('sage.rings.integer_ring', 'ZZ')
1042
+ sage: type(ZZ)
1043
+ <class 'sage.misc.lazy_import.LazyImport'>
1044
+ sage: ZZ(4.0)
1045
+ 4
1046
+ sage: lazy_import('sage.rings.real_double', 'RDF', 'my_RDF')
1047
+ sage: my_RDF._get_object() is RDF
1048
+ True
1049
+ sage: my_RDF(1/2)
1050
+ 0.5
1051
+
1052
+ sage: lazy_import('sage.rings.rational_field', ['QQ', 'frac'], ['my_QQ', 'my_frac'])
1053
+ sage: my_QQ._get_object() is QQ
1054
+ True
1055
+ sage: my_frac._get_object() is sage.rings.rational_field.frac
1056
+ True
1057
+
1058
+ Upon the first use, the object is injected directly into
1059
+ the calling namespace::
1060
+
1061
+ sage: lazy_import('sage.rings.integer_ring', 'ZZ', 'my_ZZ')
1062
+ sage: my_ZZ is ZZ
1063
+ False
1064
+ sage: my_ZZ(37)
1065
+ 37
1066
+ sage: my_ZZ is ZZ
1067
+ True
1068
+
1069
+ We check that :func:`lazy_import` also works for methods::
1070
+
1071
+ sage: class Foo():
1072
+ ....: lazy_import('sage.plot.plot', 'plot')
1073
+ sage: class Bar(Foo):
1074
+ ....: pass
1075
+ sage: type(Foo.__dict__['plot'])
1076
+ <class 'sage.misc.lazy_import.LazyImport'>
1077
+ sage: 'EXAMPLES' in Bar.plot.__doc__ # needs sage.plot
1078
+ True
1079
+ sage: type(Foo.__dict__['plot']) # needs sage.plot
1080
+ <... 'function'>
1081
+
1082
+ If deprecated then a deprecation warning is issued::
1083
+
1084
+ sage: lazy_import('sage.rings.padics.factory', 'Qp', 'my_Qp',
1085
+ ....: deprecation=14275)
1086
+ sage: my_Qp(5) # needs sage.rings.padics
1087
+ doctest:...: DeprecationWarning:
1088
+ Importing my_Qp from here is deprecated;
1089
+ please use "from sage.rings.padics.factory import Qp as my_Qp" instead.
1090
+ See https://github.com/sagemath/sage/issues/14275 for details.
1091
+ 5-adic Field with capped relative precision 20
1092
+
1093
+ An example of deprecation with a message::
1094
+
1095
+ sage: lazy_import('sage.rings.padics.factory', 'Qp', 'my_Qp_msg',
1096
+ ....: deprecation=(14275, "This is an example."))
1097
+ sage: my_Qp_msg(5) # needs sage.rings.padics
1098
+ doctest:...: DeprecationWarning: This is an example.
1099
+ See https://github.com/sagemath/sage/issues/14275 for details.
1100
+ 5-adic Field with capped relative precision 20
1101
+
1102
+ An example of an import relying on a feature::
1103
+
1104
+ sage: from sage.features import PythonModule
1105
+ sage: lazy_import('ppl', 'equation',
1106
+ ....: feature=PythonModule('ppl', spkg='pplpy', type='standard'))
1107
+ sage: equation # needs pplpy
1108
+ <cyfunction equation at ...>
1109
+ sage: lazy_import('PyNormaliz', 'NmzListConeProperties',
1110
+ ....: feature=PythonModule('PyNormaliz', spkg='pynormaliz'))
1111
+ sage: NmzListConeProperties # optional - pynormaliz
1112
+ <built-in function NmzListConeProperties>
1113
+ sage: lazy_import('foo', 'not_there',
1114
+ ....: feature=PythonModule('foo', spkg='non-existing-package'))
1115
+ sage: not_there
1116
+ Failed lazy import:
1117
+ foo is not available.
1118
+ Importing not_there failed: No module named 'foo'...
1119
+ No equivalent system packages for ... are known to Sage...
1120
+ """
1121
+ if as_ is None:
1122
+ as_ = names
1123
+ if isinstance(names, str):
1124
+ names = [names]
1125
+ as_ = [as_]
1126
+ else:
1127
+ names = list(names)
1128
+ as_ = list(as_)
1129
+ if namespace is None:
1130
+ namespace = inspect.currentframe().f_locals
1131
+ if "*" in names:
1132
+ from sage.misc.superseded import deprecation_cython
1133
+
1134
+ deprecation_cython(37433,
1135
+ 'lazy_import of * is deprecated; provide the names to be imported explicitly')
1136
+
1137
+ ix = names.index("*")
1138
+ all = get_star_imports(module)
1139
+ names[ix:ix+1] = all
1140
+ as_[ix:ix+1] = all
1141
+ for name, alias in zip(names, as_):
1142
+ namespace[alias] = LazyImport(module, name, alias, at_startup, namespace, deprecation, feature)
1143
+
1144
+
1145
+ star_imports = None
1146
+
1147
+
1148
+ def save_cache_file():
1149
+ """
1150
+ Used to save the cached * import names.
1151
+
1152
+ TESTS::
1153
+
1154
+ sage: import sage.misc.lazy_import
1155
+ sage: sage.misc.lazy_import.save_cache_file()
1156
+ """
1157
+ from sage.misc.temporary_file import atomic_write
1158
+ from sage.misc.lazy_import_cache import get_cache_file
1159
+
1160
+ global star_imports
1161
+ if star_imports is None:
1162
+ star_imports = {}
1163
+ cache_file = get_cache_file()
1164
+ cache_dir = os.path.dirname(cache_file)
1165
+
1166
+ os.makedirs(cache_dir, exist_ok=True)
1167
+ with atomic_write(cache_file, binary=True) as f:
1168
+ pickle.dump(star_imports, f)
1169
+
1170
+
1171
+ def get_star_imports(module_name):
1172
+ """
1173
+ Lookup the list of names in a module that would be imported with "import \\*"
1174
+ either via a cache or actually importing.
1175
+
1176
+ EXAMPLES::
1177
+
1178
+ sage: from sage.misc.lazy_import import get_star_imports
1179
+ sage: 'get_star_imports' in get_star_imports('sage.misc.lazy_import')
1180
+ True
1181
+ sage: 'EllipticCurve' in get_star_imports('sage.schemes.all') # needs sage.schemes
1182
+ True
1183
+
1184
+ TESTS::
1185
+
1186
+ sage: import os, tempfile
1187
+ sage: fd, cache_file = tempfile.mkstemp()
1188
+ sage: os.write(fd, b'invalid')
1189
+ 7
1190
+ sage: os.close(fd)
1191
+ sage: import sage.misc.lazy_import as lazy
1192
+ sage: import sage.misc.lazy_import_cache as cache
1193
+ sage: cache.get_cache_file = (lambda: cache_file)
1194
+ sage: lazy.star_imports = None
1195
+ sage: lazy.get_star_imports('sage.schemes.all') # needs sage.schemes
1196
+ doctest:...: UserWarning: star_imports cache is corrupted
1197
+ [...]
1198
+ sage: os.remove(cache_file)
1199
+ """
1200
+ global star_imports
1201
+ if star_imports is None:
1202
+ from sage.misc.lazy_import_cache import get_cache_file
1203
+ star_imports = {}
1204
+ try:
1205
+ with open(get_cache_file(), "rb") as cache_file:
1206
+ star_imports = pickle.load(cache_file)
1207
+ except IOError: # file does not exist
1208
+ pass
1209
+ except Exception: # unpickling failed
1210
+ import warnings
1211
+ warnings.warn('star_imports cache is corrupted')
1212
+ try:
1213
+ return star_imports[module_name]
1214
+ except KeyError:
1215
+ module = __import__(module_name, {}, {}, ["*"])
1216
+ if hasattr(module, "__all__"):
1217
+ all = module.__all__
1218
+ else:
1219
+ all = [key for key in dir(module) if key[0] != "_"]
1220
+ star_imports[module_name] = all
1221
+ return all
1222
+
1223
+
1224
+ def attributes(a):
1225
+ """
1226
+ Return the private attributes of a :class:`LazyImport` object in a dictionary.
1227
+
1228
+ This is for debugging and doctesting purposes only.
1229
+
1230
+ EXAMPLES::
1231
+
1232
+ sage: from sage.misc.lazy_import import attributes
1233
+ sage: lazy_import("sage.structure.unique_representation", "foo")
1234
+ sage: attributes(foo)['_namespace'] is globals()
1235
+ True
1236
+ sage: D = attributes(foo)
1237
+ sage: del D['_namespace']
1238
+ sage: D
1239
+ {'_as_name': 'foo',
1240
+ '_at_startup': False,
1241
+ '_deprecation': None,
1242
+ '_module': 'sage.structure.unique_representation',
1243
+ '_name': 'foo',
1244
+ '_object': None}
1245
+ """
1246
+ cdef LazyImport b
1247
+ b = a
1248
+ return {"_object": b._object,
1249
+ "_module": b._module,
1250
+ "_name": b._name,
1251
+ "_as_name": b._as_name,
1252
+ "_namespace": b._namespace,
1253
+ "_at_startup": b._at_startup,
1254
+ "_deprecation": b._deprecation}
1255
+
1256
+
1257
+ def clean_namespace(namespace=None):
1258
+ """
1259
+ Adjust :class:`LazyImport` bindings in given namespace to refer to this actual namespace.
1260
+
1261
+ When :class:`LazyImport` objects are imported into other namespaces via normal ``import``
1262
+ instructions, the data stored on a :class:`LazyImport` object that helps it to adjust the
1263
+ binding in the namespace to the actual imported object upon access is not adjusted.
1264
+ This routine fixes that.
1265
+
1266
+ INPUT:
1267
+
1268
+ - ``namespace`` -- the namespace where importing the names; by default,
1269
+ import the names to current namespace
1270
+
1271
+ EXAMPLES::
1272
+
1273
+ sage: # needs sage.symbolic
1274
+ sage: from sage.misc.lazy_import import attributes, clean_namespace
1275
+ sage: from sage.calculus.calculus import maxima as C
1276
+ sage: attributes(C)['_as_name']
1277
+ 'maxima'
1278
+ sage: attributes(C)['_namespace'] is sage.calculus.calculus.__dict__
1279
+ True
1280
+ sage: clean_namespace(globals())
1281
+ sage: attributes(C)['_as_name']
1282
+ 'C'
1283
+ sage: attributes(C)['_namespace'] is globals()
1284
+ True
1285
+ """
1286
+ cdef LazyImport w
1287
+ if namespace is None:
1288
+ namespace = inspect.currentframe().f_locals
1289
+ for k, v in namespace.items():
1290
+ if type(v) is LazyImport:
1291
+ w = v
1292
+ if w._namespace is not None and (w._namespace is not namespace or w._as_name != k):
1293
+ namespace[k] = LazyImport(w._module, w._name, as_name=k, at_startup=w._at_startup,
1294
+ namespace=namespace, deprecation=w._deprecation)
1295
+
1296
+
1297
+ # Add support for _instancedoc_
1298
+ from sage.misc.instancedoc import instancedoc
1299
+ instancedoc(LazyImport)