#16522: lazy_import doesn't resolve properly when indirectly imported.
--------------------------+------------------------
       Reporter:  nbruin  |        Owner:
           Type:  defect  |       Status:  new
       Priority:  major   |    Milestone:  sage-6.3
      Component:  misc    |   Resolution:
       Keywords:          |    Merged in:
        Authors:          |    Reviewers:
Report Upstream:  N/A     |  Work issues:
         Branch:          |       Commit:
   Dependencies:          |     Stopgaps:
--------------------------+------------------------
Changes (by nbruin):

 * priority:  minor => major
 * component:  calculus => misc


Old description:

> We have the problem:
> {{{
> 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'>
> }}}
> 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'>
> }}}
> So, the proposed fix: in `calculus.all`, import `maximalib` directly and
> lazily, rather than indirectly from `sage.calculus.calculus`.
> !LazyImports can't handle indirect imports.

New description:

 We have the problem:
 {{{
 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'>
 }}}
 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).

--

Comment:

 Ouch. This is difficult to fix. Sure, we can put in
 `sage/calculus/all.py`:
 {{{
 from sage.misc.lazy_import import lazy_import
 #this is sage.calculus.calculus.maxima. It needs to be lazily imported.
 lazy_import("sage.interfaces.maxima_lib","maxima","maxima_calculus")
 }}}
 but that only solves one step of the problem. Next we get in
 `sage/all.py`:
 {{{
 from sage.calculus.all   import *
 }}}
 so if we want to solve this problem, we'd have to do so manually unless we
 come up with very smart hack in `lazy_import`. There are other
 lazy_imports of this type:
 {{{
 sage: type(Riemann_Map)
 <type 'sage.misc.lazy_import.LazyImport'>
 sage: %time hash(Riemann_Map)
 CPU times: user 42 ms, sys: 5 ms, total: 47 ms
 Wall time: 45.2 ms
 8795750155546
 sage: %time hash(Riemann_Map)
 CPU times: user 0 ns, sys: 0 ns, total: 0 ns
 Wall time: 7.87 µs
 8795750155546
 sage: type(Riemann_Map)
 <type 'sage.misc.lazy_import.LazyImport'>
 }}}
 Exactly the same story. Luckily, the lazy_import proxy objects are pretty
 transparent when the import has already happened, so it's not too much of
 an issue when they're in the way (unless you're in a very tight loop).
 I'll be upgrading the severity and scope of this ticket.

--
Ticket URL: <http://trac.sagemath.org/ticket/16522#comment:2>
Sage <http://www.sagemath.org>
Sage: Creating a Viable Open Source Alternative to Magma, Maple, Mathematica, 
and MATLAB

-- 
You received this message because you are subscribed to the Google Groups 
"sage-trac" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/sage-trac.
For more options, visit https://groups.google.com/d/optout.

Reply via email to