Re: [Patches] [Patch #101234] Allow all assignment expressions after 'import something as'
On Sun, Aug 20, 2000 at 01:02:32PM -0700, noreply@sourceforge.net wrote:
Summary: Allow all assignment expressions after 'import something as'
Date: 2000-Aug-19 21:29 By: twouters
Comment: This absurdly simple patch (4 lines changed in 2 files) turns 'import-as' and 'from-import-as' into true assignment expressions: the name given after 'as' can be any expression that is a valid l-value:
from sys import version_info as (maj,min,pl,relnam,relno) maj,min,pl,relnam,relno (2, 0, 0, 'beta', 1)
[snip other examples]
This looks so natural, I would almost treat this as a bugfix instead of a new feature ;)
-------------------------------------------------------
Date: 2000-Aug-20 20:02 By: nowonder
Comment: Looks fine. Works as I expect. Doesn't break old code. I hope Guido likes it (assigned to gvanrossum).
Actually, it *will* break old code. Try using some of those tricks on, say, 'encodings', like so (excessively convoluted to prove a point ;):
x = {} from encodings import cp1006 as x[oct(1)], cp1026 as x[hex(20)] Traceback (most recent call last): File "<stdin>", line 1, in ? ImportError: cannot import name cp1026
I've another patch waiting which I'll upload after some cleanup, which circumvents this. The problem is that find_from_args is having a hard time figuring out how 'import' is being called, exactly. So instead, I create a list *before* calling import, straight from the information available at compile-time. (It's only a list because it is currently a list, I would prefer to make it a tuple instead but I donno if it would break stuff) That patch is necessary to be able to support this new behaviour, but I think it's worth checking in even if this patch is rejected -- it speeds up pystone ! :-) Basically it moves the logic of finding out what the import arguments are to com_import_stmt() (at compiletime), rather than the 'IMPORT_NAME' bytecode (at runtime). The only downside is that it adds all 'from-import' arguments to the co_consts list (as PyString objects) as well as where they already are, the co_names list (as normal strings). I don't think that's a high price to pay, myself, and mayhaps the actual storage use could be reduced by making the one point to the data of the other. Not sure if it's worth it, though. I've just uploaded the other patch, it can be found here: http://sourceforge.net/patch/?func=detailpatch&patch_id=101243&group_id=5470 -- Thomas Wouters <thomas@xs4all.net> Hi! I'm a .signature virus! copy me into your .signature file to help me spread!
Thomas Wouters wrote:
Date: 2000-Aug-20 20:02 By: nowonder
Comment: Looks fine. Works as I expect. Doesn't break old code. I hope Guido likes it (assigned to gvanrossum).
Actually, it *will* break old code. Try using some of those tricks on, say, 'encodings', like so (excessively convoluted to prove a point ;):
Actually, I meant that it won't break any existing code (because there is no code using 'import x as y' yet). Although I don't understand your example (because the word "encoding" makes me want to stick my head into the sand), I am fine with your shift of the list building to compile-time. When I realized what IMPORT_NAME does at runtime, I wondered if this was really neccessary. Peter -- Peter Schneider-Kamp ++47-7388-7331 Herman Krags veg 51-11 mailto:peter@schneider-kamp.de N-7050 Trondheim http://schneider-kamp.de
Summary: Allow all assignment expressions after 'import something as'
-1. Hypergeneralization. By the way, notice that import foo.bar places 'foo' in the current namespace, after ensuring that 'foo.bar' is defined. What should import foo.bar as spam assign to spam? I hope foo.bar, not foo. I note that the CVS version doesn't support this latter syntax at all; it should be fixed, even though the same effect can be has with from foo import bar as spam --Guido van Rossum (home page: http://www.pythonlabs.com/~guido/)
On Sun, Aug 20, 2000 at 11:37:46PM -0500, Guido van Rossum wrote:
Summary: Allow all assignment expressions after 'import something as' -1. Hypergeneralization.
I don't think it's hypergeneralization. In fact, people might expect it[*], if we claim that the 'import-as' syntax is a shortcut for the current practice of import somemod sspam = somemod.somesubmod.spam (or similar constructs.) However, I realize you're under a lot of pressure to Pronounce a number of things now that you're back, and we can always change this later (if you change your mind.) I dare to predict, though, that we'll see questions about why this isn't generalized, on c.l.py. (*] I know 'people might expect it' and 'hypergeneralization' aren't mutually exclusive, but you know what I mean.)
By the way, notice that import foo.bar places 'foo' in the current namespace, after ensuring that 'foo.bar' is defined.
Oh, I noticed ;) We had a small thread about that, this weekend. The subject was something like ''import as'' or so.
What should import foo.bar as spam assign to spam? I hope foo.bar, not foo.
The original patch assigned foo to spam, not foo.bar. Why ? Well, all the patch did was use a different name for the STORE operation that follows an IMPORT_NAME. To elaborate, 'import foo.bar' does this: IMPORT_NAME "foo.bar" <resulting object, 'foo', is pushed on the stack> STORE_NAME "foo" and all the patch did was replace the "foo" in STORE_NAME with the name given in the "as" clause.
I note that the CVS version doesn't support this latter syntax at all; it should be fixed, even though the same effect can be has with from foo import bar as spam
Well, "general consensus" (where the general was a three-headed beast, see the thread I mentioned) prompted me to make it illegal for now. At least noone is going to rely on it just yet ;) Making it work as you suggest requires a separate approach, though. I'll think about how to do it best. -- Thomas Wouters <thomas@xs4all.net> Hi! I'm a .signature virus! copy me into your .signature file to help me spread!
Summary: Allow all assignment expressions after 'import something as'
[GvR]
-1. Hypergeneralization.
[TW]
I don't think it's hypergeneralization. In fact, people might expect it[*], if we claim that the 'import-as' syntax is a shortcut for the current practice of
import somemod sspam = somemod.somesubmod.spam
(or similar constructs.) However, I realize you're under a lot of pressure to Pronounce a number of things now that you're back, and we can always change this later (if you change your mind.) I dare to predict, though, that we'll see questions about why this isn't generalized, on c.l.py.
I kind of doubt it, because it doesn't look useful. I do want "import foo.bar as spam" back, assigning foo.bar to spam. --Guido van Rossum (home page: http://www.pythonlabs.com/~guido/)
On Mon, 21 Aug 2000, Guido van Rossum wrote:
Summary: Allow all assignment expressions after 'import something as' [...] I kind of doubt it, because it doesn't look useful.
Looks potentially useful to me. If nothing else, it's certainly easier to explain than any other behaviour i could think of, since assignment is already well-understood.
I do want "import foo.bar as spam" back, assigning foo.bar to spam.
No no no no. Or at least let's step back and look at the whole situation first. "import foo.bar as spam" makes me uncomfortable because: (a) It's not clear whether spam should get foo or foo.bar, as evidenced by the discussion between Gordon and Thomas. (b) There's a straightforward and unambiguous way to express this already: "from foo import bar as spam". (c) It's not clear whether this should work only for modules named bar, or any symbol named bar. Before packages, the only two forms of the import statement were: import <module> from <module> import <symbol> After packages, the permitted forms are now: import <module> import <package> import <pkgpath>.<module> import <pkgpath>.<package> from <module> import <symbol> from <package> import <module> from <pkgpath>.<module> import <symbol> from <pkgpath>.<package> import <module> where a <pkgpath> is a dot-separated list of package names. With "as" clauses, we could permit: import <module> as <localmodule> import <package> as <localpackage> ?? import <pkgpath>.<module> as <localmodule> ?? import <pkgpath>.<package> as <localpackage> ?? import <module>.<symbol> as <localsymbol> ?? import <pkgpath>.<module>.<symbol> as <localsymbol> from <module> import <symbol> as <localsymbol> from <package> import <symbol> as <localsymbol> from <pkgpath>.<module> import <symbol> as <localsymbol> from <pkgpath>.<package> import <module> as <localmodule> It's not clear that we should allow "as" on the forms marked with ??, since the other six clearly identify the thing being renamed and they do not. Also note that all the other forms using "as" assign exactly one thing: the name after the "as". Would the forms marked with ?? assign just the name after the "as" (consistent with the other "as" forms), or also the top-level package name as well (consistent with the current behaviour of "import <pkgpath>.<module>")? That is, would import foo.bar as spam define just spam or both foo and spam? All these questions make me uncertain... -- ?!ng
On Mon, 21 Aug 2000, Guido van Rossum wrote:
Summary: Allow all assignment expressions after 'import something as' [...] I kind of doubt it, because it doesn't look useful.
[Ping]
Looks potentially useful to me. If nothing else, it's certainly easier to explain than any other behaviour i could think of, since assignment is already well-understood.
KISS suggests not to add it. We had a brief discussion about this at our 2.0 planning meeting and nobody there thought it would be worth it, and several of us felt it would be asking for trouble.
I do want "import foo.bar as spam" back, assigning foo.bar to spam.
No no no no. Or at least let's step back and look at the whole situation first.
"import foo.bar as spam" makes me uncomfortable because:
(a) It's not clear whether spam should get foo or foo.bar, as evidenced by the discussion between Gordon and Thomas.
As far as I recall that conversation, it's just that Thomas (more or less accidentally) implemented what was easiest from the implementation's point of view without thinking about what it should mean. *Of course* it should mean what I said if it's allowed. Even Thomas agrees to that now.
(b) There's a straightforward and unambiguous way to express this already: "from foo import bar as spam".
Without syntax coloring that looks word soup to me. import foo.bar as spam uses fewer words to say the same clearer.
(c) It's not clear whether this should work only for modules named bar, or any symbol named bar.
Same as for import: bar must be a submodule (or subpackage) in package foo.
Before packages, the only two forms of the import statement were:
import <module> from <module> import <symbol>
After packages, the permitted forms are now:
import <module> import <package> import <pkgpath>.<module> import <pkgpath>.<package> from <module> import <symbol> from <package> import <module> from <pkgpath>.<module> import <symbol> from <pkgpath>.<package> import <module>
You're creating more cases than necessary to get a grip on this. This is enough, if you realize that a package is also a module and the package path doesn't add any new cases: import <module> from <module> import <symbol> from <package> import <module>
where a <pkgpath> is a dot-separated list of package names.
With "as" clauses, we could permit:
import <module> as <localmodule> import <package> as <localpackage> ?? import <pkgpath>.<module> as <localmodule> ?? import <pkgpath>.<package> as <localpackage> ?? import <module>.<symbol> as <localsymbol> ?? import <pkgpath>.<module>.<symbol> as <localsymbol> from <module> import <symbol> as <localsymbol> from <package> import <symbol> as <localsymbol> from <pkgpath>.<module> import <symbol> as <localsymbol> from <pkgpath>.<package> import <module> as <localmodule>
Let's simplify that to: import <module> as <localname> from <module> import <symbol> as <localname> from <package> import <module> as <localname>
It's not clear that we should allow "as" on the forms marked with ??, since the other six clearly identify the thing being renamed and they do not.
Also note that all the other forms using "as" assign exactly one thing: the name after the "as". Would the forms marked with ?? assign just the name after the "as" (consistent with the other "as" forms), or also the top-level package name as well (consistent with the current behaviour of "import <pkgpath>.<module>")?
That is, would
import foo.bar as spam
define just spam or both foo and spam?
Aargh! Just spam, of course!
All these questions make me uncertain...
Not me. --Guido van Rossum (home page: http://www.pythonlabs.com/~guido/)
On Wed, 23 Aug 2000, Guido van Rossum wrote:
[Ping]
Looks potentially useful to me. If nothing else, it's certainly easier to explain than any other behaviour i could think of, since assignment is already well-understood.
KISS suggests not to add it. We had a brief discussion about this at our 2.0 planning meeting and nobody there thought it would be worth it, and several of us felt it would be asking for trouble.
What i'm trying to say is that it's *easier* to explain "import as" with Thomas' enhancement than without it. The current explanation of "import <x> as <y>" is something like Find and import the module named <x> and assign it to <y> in the normal way you do assignment, except <y> has to be a pure name. Thomas' suggestion lifts the restriction and makes the explanation simpler than it would have been: Find and import the module named <x> and assign it to <y> in the normal way you do assignment. "The normal way you do assignment" is shorthand for "decide whether to assign to the local or global namespace depending on whether <y> has been assigned to in the current scope, unless <y> has been declared global with a 'global' statement" -- and that applies in any case. Luckily, it's a concept that has been explained before and which Python programmers already need to understand anyway. The net effect is essentially a direct translation to <y> = __import__("<x>")
"import foo.bar as spam" makes me uncomfortable because:
(a) It's not clear whether spam should get foo or foo.bar, as evidenced by the discussion between Gordon and Thomas.
As far as I recall that conversation, it's just that Thomas (more or less accidentally) implemented what was easiest from the implementation's point of view without thinking about what it should mean. *Of course* it should mean what I said if it's allowed. Even Thomas agrees to that now.
Careful: import foo.bar "import the package named foo and its submodule bar, then put *foo* into the current namespace" import foo.bar as spam "import the package named foo and its submodule bar, then put *bar* into the current namespace, as spam" Only this case causes import to import a *different* object just because you used "as". import foo "import the module named foo, then put foo into the current namespace" import foo as spam "import the module named foo, then put foo into the current namespace, as spam" The above, and all the other forms of "import ... as", put the *same* object into the current namespace as they would have done, without the "as" clause.
(b) There's a straightforward and unambiguous way to express this already: "from foo import bar as spam".
Without syntax coloring that looks word soup to me.
import foo.bar as spam
uses fewer words to say the same clearer.
But then: from foo import bar as spam # give me bar, but name it spam import foo.bar as spam # give me bar, but name it spam are two ways to say the same thing -- but only if bar is a module. If bar happens to be some other kind of symbol, the first works but the second doesn't! Not so without "as spam": from foo import bar # give me bar import foo.bar # give me foo
That is, would
import foo.bar as spam
define just spam or both foo and spam?
Aargh! Just spam, of course!
I apologize if this is annoying you. I hope you see the inconsistency that i'm trying to point out, though. If you see it and decide that it's okay to live with the inconsistency, that's okay with me. -- ?!ng
On Thu, Aug 24, 2000 at 04:14:12AM -0500, Ka-Ping Yee wrote:
The current explanation of "import <x> as <y>" is something like
Find and import the module named <x> and assign it to <y> in the normal way you do assignment, except <y> has to be a pure name.
Thomas' suggestion lifts the restriction and makes the explanation simpler than it would have been:
Find and import the module named <x> and assign it to <y> in the normal way you do assignment.
"The normal way you do assignment" is shorthand for "decide whether to assign to the local or global namespace depending on whether <y> has been assigned to in the current scope, unless <y> has been declared global with a 'global' statement" -- and that applies in any case. Luckily, it's a concept that has been explained before and which Python programmers already need to understand anyway.
This is not true. The *current* situation already does the local/global namespace trick, except that 'import ..' *is* a local assignment, so the resulting name is always local (unless there is a "global" statement.) My patch wouldn't change that one bit. It would only expand the allowable expressions in the 'as' clause: is it a normal name-binding assignment (like now), or a subscription-assignment, or a slice-assignment, or an attribute-assignment. In other words, all types of assignment.
The net effect is essentially a direct translation to
<y> = __import__("<x>")
Exactly :)
Careful:
import foo.bar "import the package named foo and its submodule bar, then put *foo* into the current namespace"
Wrong. What it does is: import the package named foo and its submodule bar, and make it so you can access foo.bar via the name 'foo.bar'. That this has to put 'foo' in the local namespace is a side issue :-) And when seen like that,
import foo.bar as spam "import the package named foo and its submodule bar, then put *bar* into the current namespace, as spam"
Becomes obvious as well. -- Thomas Wouters <thomas@xs4all.net> Hi! I'm a .signature virus! copy me into your .signature file to help me spread!
On Thu, 24 Aug 2000, Thomas Wouters wrote:
import foo.bar "import the package named foo and its submodule bar, then put *foo* into the current namespace"
Wrong. What it does is: import the package named foo and its submodule bar, and make it so you can access foo.bar via the name 'foo.bar'. That this has to put 'foo' in the local namespace is a side issue
I understand now. Sorry for my thickheadedness. Yes, when i look at it as "please give this to me as foo.bar", it makes much more sense. Apologies, Guido. That's two brain-farts in a day or so. :( -- ?!ng
participants (4)
-
Guido van Rossum -
Ka-Ping Yee -
Peter Schneider-Kamp -
Thomas Wouters