Skip to content

Commit 32bee38

Browse files
Release Managervbraun
Release Manager
authored andcommitted
Trac #14275: Lazy imports with deprecation
It's annoying when other people move something around in the Sage library and it's no longer available in the previous location to be imported. Sage currently has some mechanisms for alleviating this problem (`sage.misc.superceded.deprecated_callable_import` and `sage.structure.sage_object.register_unpickle_override` for example). This ticket adds another option: lazily import the old name so that a deprecation warning is issued whenever it is referred to. URL: http://trac.sagemath.org/14275 Reported by: roed Ticket author(s): David Roe, Travis Scrimshaw Reviewer(s): Travis Scrimshaw, Nathann Cohen
2 parents 504bd92 + a484809 commit 32bee38

File tree

1 file changed

+55
-14
lines changed

1 file changed

+55
-14
lines changed

src/sage/misc/lazy_import.pyx

+55-14
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,9 @@ cdef class LazyImport(object):
155155
cdef _as_name
156156
cdef _namespace
157157
cdef _at_startup
158+
cdef _deprecation
158159

159-
def __init__(self, module, name, as_name=None, namespace=None, at_startup=False):
160+
def __init__(self, module, name, as_name=None, namespace=None, at_startup=False, deprecation=None):
160161
"""
161162
EXAMPLES::
162163
@@ -173,6 +174,7 @@ cdef class LazyImport(object):
173174
self._as_name = as_name
174175
self._namespace = namespace
175176
self._at_startup = at_startup
177+
self._deprecation = deprecation
176178

177179
# Due to a bug in Cython-0.19, this must not be a cpdef method.
178180
# See http://trac.sagemath.org/sage_trac/ticket/14452
@@ -247,6 +249,18 @@ cdef class LazyImport(object):
247249
print 'Option ``at_startup=True`` for lazy import {0} not needed anymore'.format(self._name)
248250
self._object = getattr(__import__(self._module, {}, {}, [self._name]), self._name)
249251
alias = self._as_name or self._name
252+
if self._deprecation is not None:
253+
from sage.misc.superseded import deprecation
254+
try:
255+
trac_number, message = self._deprecation
256+
except TypeError:
257+
trac_number = self._deprecation
258+
message = None
259+
if message is None:
260+
message = ('\nImporting {name} from here is deprecated. ' +
261+
'If you need to use it, please import it directly from' +
262+
' {module_name}').format(name=alias, module_name=self._module)
263+
deprecation(trac_number, message)
250264
if owner is None:
251265
if self._namespace and self._namespace[alias] is self:
252266
self._namespace[alias] = self._object
@@ -905,7 +919,7 @@ cdef class LazyImport(object):
905919
return self._get_object()
906920

907921

908-
def lazy_import(module, names, _as=None, namespace=None, bint overwrite=True, at_startup=False):
922+
def lazy_import(module, names, _as=None, namespace=None, bint overwrite=True, at_startup=False, deprecation=None):
909923
"""
910924
Create a lazy import object and inject it into the caller's global
911925
namespace. For the purposes of introspection and calling, this is
@@ -914,17 +928,27 @@ def lazy_import(module, names, _as=None, namespace=None, bint overwrite=True, at
914928
915929
INPUT:
916930
917-
- module: a string representing the module to import.
918-
- names: a string or list of strings representing the names to import from
919-
module.
920-
- _as: (optional) a string or list of strings representing the aliases of the names
921-
imported.
922-
- namespace: The namespace where importing the names. By default, import
923-
the names to current namespace.
924-
- overwrite: (default: True) If set to True and a name is already in the
925-
namespace, overwrite it with the lazy_import-ed name.
926-
- ``at_startup``: a boolean (default: False)
927-
whether the lazy import is supposed to be resolved at startup time.
931+
- ``module`` -- a string representing the module to import
932+
933+
- ``names`` -- a string or list of strings representing the names to
934+
import from module
935+
936+
- ``_as`` -- (optional) a string or list of strings representing the
937+
aliases of the names imported
938+
939+
- ``namespace`` -- the namespace where importing the names; by default,
940+
import the names to current namespace
941+
942+
- ``overwrite`` -- (default: ``True``) if set to ``True`` and a name is
943+
already in the namespace, overwrite it with the lazy_import-ed name
944+
945+
- ``at_startup`` -- a boolean (default: ``False``);
946+
whether the lazy import is supposed to be resolved at startup time
947+
948+
- ``deprecation`` -- (optional) if not ``None``, a deprecation warning
949+
will be issued when the object is actually imported;
950+
``deprecation`` should be either a trac number (integer) or a
951+
pair ``(trac_number, message)``
928952
929953
.. SEEALSO:: :mod:`sage.misc.lazy_import`, :class:`LazyImport`
930954
@@ -971,6 +995,23 @@ def lazy_import(module, names, _as=None, namespace=None, bint overwrite=True, at
971995
True
972996
sage: type(Foo.__dict__['plot'])
973997
<type 'function'>
998+
999+
If deprecated then a deprecation warning is issued::
1000+
1001+
sage: lazy_import('sage.all', 'Qp', 'my_Qp', deprecation=14275)
1002+
sage: my_Qp(5)
1003+
doctest:...: DeprecationWarning:
1004+
Importing my_Qp from here is deprecated. If you need to use it, please import it directly from sage.all
1005+
See http://trac.sagemath.org/14275 for details.
1006+
5-adic Field with capped relative precision 20
1007+
1008+
An example of deprecation with a message::
1009+
1010+
sage: lazy_import('sage.all', 'Qp', 'my_Qp_msg', deprecation=(14275, "This is an example."))
1011+
sage: my_Qp_msg(5)
1012+
doctest:...: DeprecationWarning: This is an example.
1013+
See http://trac.sagemath.org/14275 for details.
1014+
5-adic Field with capped relative precision 20
9741015
"""
9751016
if _as is None:
9761017
_as = names
@@ -986,7 +1027,7 @@ def lazy_import(module, names, _as=None, namespace=None, bint overwrite=True, at
9861027
for name, alias in zip(names, _as):
9871028
if not overwrite and (alias or name) in namespace:
9881029
continue
989-
namespace[alias or name] = LazyImport(module, name, alias, namespace, at_startup)
1030+
namespace[alias or name] = LazyImport(module, name, alias, namespace, at_startup, deprecation)
9901031

9911032

9921033
star_imports = None

0 commit comments

Comments
 (0)