On Apr 4, 2013 6:47 PM, "Guido van Rossum" <guido@python.org> wrote:
>
> +1 on Brett and PJE just doing this.

I'll file a bug when I get home.

-brett

>
> On Thu, Apr 4, 2013 at 3:38 PM, Brett Cannon <brett@python.org> wrote:
> >
> >
> >
> > On Thu, Apr 4, 2013 at 5:00 PM, PJ Eby <pje@telecommunity.com> wrote:
> >>
> >> On Thu, Apr 4, 2013 at 4:42 PM, Guido van Rossum <guido@python.org> wrote:
> >> > I do think it would be fine if "from a import b" returned the
> >> > attribute 'b' of module 'a' if it exists, and otherwise look for
> >> > module 'a.b' in sys.modules.
> >>
> >> Technically, it already does that -- but inside of __import__, not in
> >> the IMPORT_FROM opcode.
> >>
> >> But then *after* doing that check-and-fallback, __import__ doesn't
> >> assign a.b, because it assumes the recursive import it called has
> >> already done this...
> >
> >
> > It's an unfortunate side-effect of having loaders set sys.modules for new
> > modules not also set them as an attribute on their parent package
> > immediately as well (or you could argue it's a side-effect of not passing in
> > a module instead of a name to load_module() but that's another discussion).
> >
> >>
> >>  which means that when __import__ returns, the
> >> IMPORT_FROM opcode tries and fails to do the getattr.
> >>
> >> This could be fixed in one of two ways.   Either:
> >>
> >> 1. Change importlib._bootstrap._handle_fromlist() to set a.b if it
> >> successfully imports 'a.b' (inside its duplicate handling for what
> >> IMPORT_FROM does), or
> >
> >
> > It's three lines, one of which is 'else:'. Just did it.
> >
> >>
> >> 2. Change the IMPORT_FROM opcode to handle the fallback itself
> >>
> >>
> >> While the latter involves a bit of C coding, it has fewer potential
> >> side-effects on the import system as a whole, and simply ensures that
> >> if "import" would succeed, then so would "from...import" targeting the
> >> same module.
> >>
> >> (There might be other fixes I haven't thought of, but really, changing
> >> IMPORT_FROM to fallback to a sys.modules check is probably by far the
> >> least-invasive way to handle it.)
> >
> >
> > This is my preference as well. The change would be small: I think all you
> > need to do is if the getattr() fails then fall back to sys.modules. Although
> > if it were me and I was casting backwards-compatibility to the wind I would
> > rip out the whole fromlist part of __import__() and let the bytecode worry
> > about the fromlist, basically making the import opcode call
> > importlib.import_module().
> >
>
>
>
> --
> --Guido van Rossum (python.org/~guido)


">

(original) (raw)



On Thu, Apr 4, 2013 at 8:03 PM, Brett Cannon <brett@python.org> wrote:


On Apr 4, 2013 6:47 PM, "Guido van Rossum" <guido@python.org> wrote:
\>
\> +1 on Brett and PJE just doing this.

I'll file a bug when I get home.

-brett

>
\> On Thu, Apr 4, 2013 at 3:38 PM, Brett Cannon <brett@python.org> wrote:
\> >
\> >
\> >
\> > On Thu, Apr 4, 2013 at 5:00 PM, PJ Eby <pje@telecommunity.com> wrote:
\> >>
\> >> On Thu, Apr 4, 2013 at 4:42 PM, Guido van Rossum <guido@python.org> wrote:
\> >> > I do think it would be fine if "from a import b" returned the
\> >> > attribute 'b' of module 'a' if it exists, and otherwise look for
\> >> > module 'a.b' in sys.modules.
\> >>
\> >> Technically, it already does that -- but inside of \_\_import\_\_, not in
\> >> the IMPORT\_FROM opcode.
\> >>
\> >> But then \*after\* doing that check-and-fallback, \_\_import\_\_ doesn't
\> >> assign a.b, because it assumes the recursive import it called has
\> >> already done this...
\> >
\> >
\> > It's an unfortunate side-effect of having loaders set sys.modules for new
\> > modules not also set them as an attribute on their parent package
\> > immediately as well (or you could argue it's a side-effect of not passing in
\> > a module instead of a name to load\_module() but that's another discussion).
\> >
\> >>
\> >> which means that when \_\_import\_\_ returns, the
\> >> IMPORT\_FROM opcode tries and fails to do the getattr.
\> >>
\> >> This could be fixed in one of two ways. Either:
\> >>
\> >> 1\. Change importlib.\_bootstrap.\_handle\_fromlist() to set a.b if it
\> >> successfully imports 'a.b' (inside its duplicate handling for what
\> >> IMPORT\_FROM does), or
\> >
\> >
\> > It's three lines, one of which is 'else:'. Just did it.
\> >
\> >>
\> >> 2\. Change the IMPORT\_FROM opcode to handle the fallback itself
\> >>
\> >>
\> >> While the latter involves a bit of C coding, it has fewer potential
\> >> side-effects on the import system as a whole, and simply ensures that
\> >> if "import" would succeed, then so would "from...import" targeting the
\> >> same module.
\> >>
\> >> (There might be other fixes I haven't thought of, but really, changing
\> >> IMPORT\_FROM to fallback to a sys.modules check is probably by far the
\> >> least-invasive way to handle it.)
\> >
\> >
\> > This is my preference as well. The change would be small: I think all you
\> > need to do is if the getattr() fails then fall back to sys.modules. Although
\> > if it were me and I was casting backwards-compatibility to the wind I would
\> > rip out the whole fromlist part of \_\_import\_\_() and let the bytecode worry
\> > about the fromlist, basically making the import opcode call
\> > importlib.import\_module().
\> >
\>
\>
\>
\> --
\> --Guido van Rossum (python.org/\~guido)