Woah. Is this really a good idea ? I have seen 'from ... import *' in a function scope put to good (relatively -- we're talking 'import *' here) use. I also thought of 'import' as yet another assignment statement, so to me it's both logical and consistent if 'import' would listen to 'global'. Otherwise we have to re-invent 'import spam; eggs = spam' if we want eggs to be global.
Note that Jeremy is only raising errors for "from M import *".
No, he says he's also raising errors for 'import spam' if 'spam' is declared global, like so:
def viking(): global spam import spam
Yeah, this was just brought to my attention at our group meeting today. I'm with you on this one -- there really isn't a good reason why this shouldn't work. (I wonder why that constraint was ever added to the reference manual; maybe I was just upset that someone would *do* something as ugly as that, or maybe there was a J[P]ython reason???.)
I think Jeremy has an excellent reason. Compilers want to do analysis of name usage at compile time. The value of * cannot be determined at compile time (you cannot know what module will actually be imported at run time). Up till now, we were able to fudge this, but Jeremy's new compiler needs to know exactly which names are defined in all local scopes, in order to do nested scopes right.
Hrrmm.... I guess I have to agree with that. None the less, I wish we could have a "ack! this is stupid code! it uses 'from larch import *'! All bets are off, we do a lot of slow complicated runtime checking now!" mode. The thing I still enjoy most about Python is that it always does what I want, and though I'd never want to do 'from different import *' in a local scope, I do want other, less wise people to have the same experience, where possible :)
Hm, maybe, just *maybe* Jeremy can do this if there are no nested scopes in sight. But I don't think it's a big deal as long as the error message is clear -- it's bad style.
And I also want to be able to do:
def fill_me(with): global me if with == 1: import me elif with == 2: import me_too as me elif with == 3: from me.Tools import me_me as me elif with == 4: me = FakeModule() sys.modules['me'] = me else: raise ValueError
And I can't quite argue that away with 'the compiler needs to know ...' -- it's all there!
Sort of, although I would prefer to do a two-stager here: first some variation of "import me as meohmy", and then "global me; me = meohmy" .
I also have another issue with your recent patches, Jeremy, also in the backwards-compatibility departement :) You gave new.code two new, non-optional arguments, in the middle of the long argument list. I sent a note about it to python-checkins instead of python-dev by accident, but Fred seemed to agree with me there.
(Tim will love this. :-)
I don't know what those new arguments represent. If they can reasonably be assumed to be empty for code that doesn't use the new features, I'd say move them to the end and default them properly. If they must be specified, I'd say too bad, the new module is an accident of the implementation anyway, and its users should update their code.
Okay, I can live with that. It's sure to cause some gripes though. Then again, from looking at the code I'd say those arguments (freevars and cellvars) can easily default to empty tuples.
OK. I hope Jeremy can fix this when he gets home. --Guido van Rossum (home page: http://www.python.org/~guido/)