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.
- passagemath_objects/.dylibs/libgmp.10.dylib +0 -0
- passagemath_objects/__init__.py +3 -0
- passagemath_objects-10.6.41.dist-info/METADATA +115 -0
- passagemath_objects-10.6.41.dist-info/RECORD +280 -0
- passagemath_objects-10.6.41.dist-info/WHEEL +6 -0
- passagemath_objects-10.6.41.dist-info/top_level.txt +3 -0
- sage/all__sagemath_objects.py +37 -0
- sage/arith/all__sagemath_objects.py +5 -0
- sage/arith/long.pxd +411 -0
- sage/arith/numerical_approx.cpython-314t-darwin.so +0 -0
- sage/arith/numerical_approx.pxd +35 -0
- sage/arith/numerical_approx.pyx +75 -0
- sage/arith/power.cpython-314t-darwin.so +0 -0
- sage/arith/power.pxd +31 -0
- sage/arith/power.pyx +127 -0
- sage/categories/action.cpython-314t-darwin.so +0 -0
- sage/categories/action.pxd +29 -0
- sage/categories/action.pyx +641 -0
- sage/categories/algebra_functor.py +745 -0
- sage/categories/all__sagemath_objects.py +33 -0
- sage/categories/basic.py +62 -0
- sage/categories/cartesian_product.py +295 -0
- sage/categories/category.py +3401 -0
- sage/categories/category_cy_helper.cpython-314t-darwin.so +0 -0
- sage/categories/category_cy_helper.pxd +8 -0
- sage/categories/category_cy_helper.pyx +322 -0
- sage/categories/category_singleton.cpython-314t-darwin.so +0 -0
- sage/categories/category_singleton.pxd +3 -0
- sage/categories/category_singleton.pyx +342 -0
- sage/categories/category_types.py +637 -0
- sage/categories/category_with_axiom.py +2876 -0
- sage/categories/covariant_functorial_construction.py +703 -0
- sage/categories/facade_sets.py +228 -0
- sage/categories/functor.cpython-314t-darwin.so +0 -0
- sage/categories/functor.pxd +7 -0
- sage/categories/functor.pyx +691 -0
- sage/categories/homset.py +1338 -0
- sage/categories/homsets.py +364 -0
- sage/categories/isomorphic_objects.py +73 -0
- sage/categories/map.cpython-314t-darwin.so +0 -0
- sage/categories/map.pxd +34 -0
- sage/categories/map.pyx +2112 -0
- sage/categories/morphism.cpython-314t-darwin.so +0 -0
- sage/categories/morphism.pxd +14 -0
- sage/categories/morphism.pyx +895 -0
- sage/categories/objects.py +167 -0
- sage/categories/primer.py +1696 -0
- sage/categories/pushout.py +4834 -0
- sage/categories/quotients.py +64 -0
- sage/categories/realizations.py +200 -0
- sage/categories/sets_cat.py +3228 -0
- sage/categories/sets_with_partial_maps.py +52 -0
- sage/categories/subobjects.py +64 -0
- sage/categories/subquotients.py +21 -0
- sage/categories/with_realizations.py +311 -0
- sage/cpython/__init__.py +19 -0
- sage/cpython/_py2_random.py +619 -0
- sage/cpython/all.py +3 -0
- sage/cpython/atexit.cpython-314t-darwin.so +0 -0
- sage/cpython/atexit.pyx +269 -0
- sage/cpython/builtin_types.cpython-314t-darwin.so +0 -0
- sage/cpython/builtin_types.pyx +7 -0
- sage/cpython/cython_metaclass.cpython-314t-darwin.so +0 -0
- sage/cpython/cython_metaclass.h +117 -0
- sage/cpython/cython_metaclass.pxd +3 -0
- sage/cpython/cython_metaclass.pyx +130 -0
- sage/cpython/debug.cpython-314t-darwin.so +0 -0
- sage/cpython/debug.pyx +302 -0
- sage/cpython/dict_del_by_value.cpython-314t-darwin.so +0 -0
- sage/cpython/dict_del_by_value.pxd +9 -0
- sage/cpython/dict_del_by_value.pyx +191 -0
- sage/cpython/dict_internal.h +245 -0
- sage/cpython/getattr.cpython-314t-darwin.so +0 -0
- sage/cpython/getattr.pxd +9 -0
- sage/cpython/getattr.pyx +439 -0
- sage/cpython/pycore_long.h +97 -0
- sage/cpython/pycore_long.pxd +10 -0
- sage/cpython/python_debug.h +44 -0
- sage/cpython/python_debug.pxd +47 -0
- sage/cpython/pyx_visit.h +13 -0
- sage/cpython/string.cpython-314t-darwin.so +0 -0
- sage/cpython/string.pxd +76 -0
- sage/cpython/string.pyx +34 -0
- sage/cpython/string_impl.h +60 -0
- sage/cpython/type.cpython-314t-darwin.so +0 -0
- sage/cpython/type.pxd +2 -0
- sage/cpython/type.pyx +40 -0
- sage/cpython/wrapperdescr.pxd +67 -0
- sage/ext/all__sagemath_objects.py +3 -0
- sage/ext/ccobject.h +64 -0
- sage/ext/cplusplus.pxd +17 -0
- sage/ext/mod_int.h +30 -0
- sage/ext/mod_int.pxd +24 -0
- sage/ext/stdsage.pxd +39 -0
- sage/groups/all__sagemath_objects.py +1 -0
- sage/groups/group.cpython-314t-darwin.so +0 -0
- sage/groups/group.pxd +14 -0
- sage/groups/group.pyx +322 -0
- sage/groups/old.cpython-314t-darwin.so +0 -0
- sage/groups/old.pxd +14 -0
- sage/groups/old.pyx +219 -0
- sage/libs/all__sagemath_objects.py +3 -0
- sage/libs/gmp/__init__.py +1 -0
- sage/libs/gmp/all.pxd +6 -0
- sage/libs/gmp/binop.pxd +23 -0
- sage/libs/gmp/misc.pxd +8 -0
- sage/libs/gmp/mpf.pxd +88 -0
- sage/libs/gmp/mpn.pxd +57 -0
- sage/libs/gmp/mpq.pxd +57 -0
- sage/libs/gmp/mpz.pxd +202 -0
- sage/libs/gmp/pylong.cpython-314t-darwin.so +0 -0
- sage/libs/gmp/pylong.pxd +12 -0
- sage/libs/gmp/pylong.pyx +150 -0
- sage/libs/gmp/random.pxd +25 -0
- sage/libs/gmp/randomize.pxd +59 -0
- sage/libs/gmp/types.pxd +53 -0
- sage/libs/gmpxx.pxd +19 -0
- sage/misc/abstract_method.py +276 -0
- sage/misc/all__sagemath_objects.py +43 -0
- sage/misc/bindable_class.py +253 -0
- sage/misc/c3_controlled.cpython-314t-darwin.so +0 -0
- sage/misc/c3_controlled.pxd +2 -0
- sage/misc/c3_controlled.pyx +1402 -0
- sage/misc/cachefunc.cpython-314t-darwin.so +0 -0
- sage/misc/cachefunc.pxd +43 -0
- sage/misc/cachefunc.pyx +3781 -0
- sage/misc/call.py +188 -0
- sage/misc/classcall_metaclass.cpython-314t-darwin.so +0 -0
- sage/misc/classcall_metaclass.pxd +14 -0
- sage/misc/classcall_metaclass.pyx +599 -0
- sage/misc/constant_function.cpython-314t-darwin.so +0 -0
- sage/misc/constant_function.pyx +130 -0
- sage/misc/decorators.py +747 -0
- sage/misc/fast_methods.cpython-314t-darwin.so +0 -0
- sage/misc/fast_methods.pxd +20 -0
- sage/misc/fast_methods.pyx +351 -0
- sage/misc/flatten.py +90 -0
- sage/misc/fpickle.cpython-314t-darwin.so +0 -0
- sage/misc/fpickle.pyx +177 -0
- sage/misc/function_mangling.cpython-314t-darwin.so +0 -0
- sage/misc/function_mangling.pxd +11 -0
- sage/misc/function_mangling.pyx +308 -0
- sage/misc/inherit_comparison.cpython-314t-darwin.so +0 -0
- sage/misc/inherit_comparison.pxd +5 -0
- sage/misc/inherit_comparison.pyx +105 -0
- sage/misc/instancedoc.cpython-314t-darwin.so +0 -0
- sage/misc/instancedoc.pyx +331 -0
- sage/misc/lazy_attribute.cpython-314t-darwin.so +0 -0
- sage/misc/lazy_attribute.pyx +607 -0
- sage/misc/lazy_format.py +135 -0
- sage/misc/lazy_import.cpython-314t-darwin.so +0 -0
- sage/misc/lazy_import.pyx +1299 -0
- sage/misc/lazy_import_cache.py +36 -0
- sage/misc/lazy_list.cpython-314t-darwin.so +0 -0
- sage/misc/lazy_list.pxd +19 -0
- sage/misc/lazy_list.pyx +1187 -0
- sage/misc/lazy_string.cpython-314t-darwin.so +0 -0
- sage/misc/lazy_string.pxd +7 -0
- sage/misc/lazy_string.pyx +546 -0
- sage/misc/misc.py +1066 -0
- sage/misc/misc_c.cpython-314t-darwin.so +0 -0
- sage/misc/misc_c.pxd +3 -0
- sage/misc/misc_c.pyx +766 -0
- sage/misc/namespace_package.py +37 -0
- sage/misc/nested_class.cpython-314t-darwin.so +0 -0
- sage/misc/nested_class.pxd +3 -0
- sage/misc/nested_class.pyx +394 -0
- sage/misc/persist.cpython-314t-darwin.so +0 -0
- sage/misc/persist.pyx +1251 -0
- sage/misc/prandom.py +418 -0
- sage/misc/randstate.cpython-314t-darwin.so +0 -0
- sage/misc/randstate.pxd +30 -0
- sage/misc/randstate.pyx +1059 -0
- sage/misc/repr.py +203 -0
- sage/misc/reset.cpython-314t-darwin.so +0 -0
- sage/misc/reset.pyx +196 -0
- sage/misc/sage_ostools.cpython-314t-darwin.so +0 -0
- sage/misc/sage_ostools.pyx +323 -0
- sage/misc/sage_timeit.py +276 -0
- sage/misc/sage_timeit_class.cpython-314t-darwin.so +0 -0
- sage/misc/sage_timeit_class.pyx +120 -0
- sage/misc/sage_unittest.py +637 -0
- sage/misc/sageinspect.py +2768 -0
- sage/misc/session.cpython-314t-darwin.so +0 -0
- sage/misc/session.pyx +392 -0
- sage/misc/superseded.py +557 -0
- sage/misc/test_nested_class.py +228 -0
- sage/misc/timing.py +264 -0
- sage/misc/unknown.py +222 -0
- sage/misc/verbose.py +253 -0
- sage/misc/weak_dict.cpython-314t-darwin.so +0 -0
- sage/misc/weak_dict.pxd +15 -0
- sage/misc/weak_dict.pyx +1231 -0
- sage/modules/all__sagemath_objects.py +1 -0
- sage/modules/module.cpython-314t-darwin.so +0 -0
- sage/modules/module.pxd +5 -0
- sage/modules/module.pyx +329 -0
- sage/rings/all__sagemath_objects.py +3 -0
- sage/rings/integer_fake.h +22 -0
- sage/rings/integer_fake.pxd +55 -0
- sage/sets/all__sagemath_objects.py +3 -0
- sage/sets/pythonclass.cpython-314t-darwin.so +0 -0
- sage/sets/pythonclass.pxd +9 -0
- sage/sets/pythonclass.pyx +247 -0
- sage/structure/__init__.py +4 -0
- sage/structure/all.py +30 -0
- sage/structure/category_object.cpython-314t-darwin.so +0 -0
- sage/structure/category_object.pxd +28 -0
- sage/structure/category_object.pyx +1087 -0
- sage/structure/coerce.cpython-314t-darwin.so +0 -0
- sage/structure/coerce.pxd +44 -0
- sage/structure/coerce.pyx +2107 -0
- sage/structure/coerce_actions.cpython-314t-darwin.so +0 -0
- sage/structure/coerce_actions.pxd +27 -0
- sage/structure/coerce_actions.pyx +988 -0
- sage/structure/coerce_dict.cpython-314t-darwin.so +0 -0
- sage/structure/coerce_dict.pxd +51 -0
- sage/structure/coerce_dict.pyx +1557 -0
- sage/structure/coerce_exceptions.py +23 -0
- sage/structure/coerce_maps.cpython-314t-darwin.so +0 -0
- sage/structure/coerce_maps.pxd +28 -0
- sage/structure/coerce_maps.pyx +718 -0
- sage/structure/debug_options.cpython-314t-darwin.so +0 -0
- sage/structure/debug_options.pxd +6 -0
- sage/structure/debug_options.pyx +54 -0
- sage/structure/dynamic_class.py +541 -0
- sage/structure/element.cpython-314t-darwin.so +0 -0
- sage/structure/element.pxd +272 -0
- sage/structure/element.pyx +4772 -0
- sage/structure/element_wrapper.cpython-314t-darwin.so +0 -0
- sage/structure/element_wrapper.pxd +12 -0
- sage/structure/element_wrapper.pyx +582 -0
- sage/structure/factorization.py +1422 -0
- sage/structure/factorization_integer.py +105 -0
- sage/structure/factory.cpython-314t-darwin.so +0 -0
- sage/structure/factory.pyx +786 -0
- sage/structure/formal_sum.py +489 -0
- sage/structure/gens_py.py +73 -0
- sage/structure/global_options.py +1743 -0
- sage/structure/indexed_generators.py +863 -0
- sage/structure/list_clone.cpython-314t-darwin.so +0 -0
- sage/structure/list_clone.pxd +65 -0
- sage/structure/list_clone.pyx +1867 -0
- sage/structure/list_clone_demo.cpython-314t-darwin.so +0 -0
- sage/structure/list_clone_demo.pyx +248 -0
- sage/structure/list_clone_timings.py +179 -0
- sage/structure/list_clone_timings_cy.cpython-314t-darwin.so +0 -0
- sage/structure/list_clone_timings_cy.pyx +86 -0
- sage/structure/mutability.cpython-314t-darwin.so +0 -0
- sage/structure/mutability.pxd +21 -0
- sage/structure/mutability.pyx +348 -0
- sage/structure/nonexact.py +69 -0
- sage/structure/parent.cpython-314t-darwin.so +0 -0
- sage/structure/parent.pxd +112 -0
- sage/structure/parent.pyx +3093 -0
- sage/structure/parent_base.cpython-314t-darwin.so +0 -0
- sage/structure/parent_base.pxd +13 -0
- sage/structure/parent_base.pyx +44 -0
- sage/structure/parent_gens.cpython-314t-darwin.so +0 -0
- sage/structure/parent_gens.pxd +22 -0
- sage/structure/parent_gens.pyx +377 -0
- sage/structure/parent_old.cpython-314t-darwin.so +0 -0
- sage/structure/parent_old.pxd +25 -0
- sage/structure/parent_old.pyx +294 -0
- sage/structure/proof/__init__.py +1 -0
- sage/structure/proof/all.py +243 -0
- sage/structure/proof/proof.py +300 -0
- sage/structure/richcmp.cpython-314t-darwin.so +0 -0
- sage/structure/richcmp.pxd +213 -0
- sage/structure/richcmp.pyx +495 -0
- sage/structure/sage_object.cpython-314t-darwin.so +0 -0
- sage/structure/sage_object.pxd +3 -0
- sage/structure/sage_object.pyx +988 -0
- sage/structure/sage_object_test.py +19 -0
- sage/structure/sequence.py +937 -0
- sage/structure/set_factories.py +1178 -0
- sage/structure/set_factories_example.py +527 -0
- sage/structure/support_view.py +179 -0
- sage/structure/test_factory.py +56 -0
- 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)
|