-
-
Notifications
You must be signed in to change notification settings - Fork 654
Description
We have several places where lazy_import objects are used in a way that prevents them from behaving as designed.
The original idea of LazyImport
proxies is that they have a pointer to the namespace in which they are bound, so that once the import gets triggered, the proxy object redirects the binding in the namespace to point straight to the proxied object. Once this redirection has happened, the proxy object should not play a role anymore and no performance impact should happen at all.
The problem occurs from statements such as:
calculus/all.py:1:from calculus import maxima as maxima_calculus
This doesn't work, because this is a LazyImport
proxy, which needs to know the namespace in which it is bound to do the proper replacement. This one is tied to sage.calculus.calculus.maxima
, so it can't rebind the global maxima_calculus
. Indeed:
sage: type(sage.calculus.calculus.maxima)
<type 'sage.misc.lazy_import.LazyImport'>
sage: type(maxima_calculus)
<type 'sage.misc.lazy_import.LazyImport'>
sage: hash(maxima_calculus)
-7971541566211231133
sage: type(sage.calculus.calculus.maxima)
<class 'sage.interfaces.maxima_lib.MaximaLib'>
sage: type(maxima_calculus)
<type 'sage.misc.lazy_import.LazyImport'>
The binding of maxima_calculus
in the global namespace (and the one in calculus.all
too) remains to the LazyImport
proxy. Thus we suffer from indirection overhead [one might worry we'd suffer repeated extraneous dictionary modifications, but LazyImport
is smart enough to only attempt to rebind sage.calculus.calculus.maxima
only on the first access] as well as problems that things like id(LazyImportShim)
and type(LazyImportShim)
are not what they're supposed to model.
If instead we do:
sage: lazy_import('sage.interfaces.maxima_lib','maxima','maxima_calculus')
we see that things do resolve:
sage: type(maxima_calculus)
<type 'sage.misc.lazy_import.LazyImport'>
sage: hash(maxima_calculus)
-7971541566211231133
sage: type(maxima_calculus)
<class 'sage.interfaces.maxima_lib.MaximaLib'>
Other bindings need their own chance to resolve, but do:
sage: type(sage.calculus.calculus.maxima)
<type 'sage.misc.lazy_import.LazyImport'>
sage: hash(sage.calculus.calculus.maxima)
-7971541566211231133
sage: type(sage.calculus.calculus.maxima)
<class 'sage.interfaces.maxima_lib.MaximaLib'>
The obvious fix: in calculus.all
, import maximalib
directly and lazily, rather than indirectly from sage.calculus.calculus
only kicks the can further, since in sage.all
we have from sage.calculus.all import *
(which I think is where it really gets placed in the global sage namespace).
Component: misc
Author: Nils Bruin, Matthias Koeppe
Branch/Commit: 9837dec
Reviewer: Matthias Koeppe, Nils Bruin
Issue created by migration from https://trac.sagemath.org/ticket/16522