[Python-Dev] BDFL-Delegate appointments for several PEPs

Cameron Simpson cs at cskk.id.au
Mon Mar 25 00:27:46 EDT 2019


On 24Mar2019 23:22, Terry Reedy <tjreedy at udel.edu> wrote:
>On 3/24/2019 10:01 PM, Terry Reedy wrote:
>>On 3/24/2019 7:00 PM, Cameron Simpson wrote:
>>>Did you have a specific scenario in mind?
>>
>>I was thinking about IDLE and its tangled web of circular inports, 
>>but I am now convinced that this change will not affect it.  Indeed, 
>>idlelib/pyshell.py already implements idea of the proposal, ending 
>>with
>>
>>if __name__ == "__main__":
>>     sys.modules['pyshell'] = sys.modules['__main__']
>>     main()
>
>After more investigation, I realized that to stop having duplicate modulue:
>1. The alias should be 'idlelib.pyshell', not 'pyshell', at least when 
>imports are all absolute.

The PEP499 patch effectively uses __main__.__spec__.name for the name of 
the alias. Does that simplify your issue?

The current PR is here if you want to look at it:

    https://github.com/python/cpython/pull/12490

>2. It should be done at the top of the file, before the import of 
>modules that import pyshell.

Hmm, if PEP499 comes in you shouldn't need to do this at all. If PEP499 
gets delayed or rejected I guess you're supporting this without it. Yes, 
you'll want to do it before any other imports happen (well, as you say, 
before any which import pyshell).

What about (untested):

    if __name__ == '__main__':
        if __spec__.name not in sys.modules:
            sys.modules[__spec__.name] = sys.modules['__main__']

as a forward compatible setup?

>If I run python f:/dev/3x/lib/idlelib/pyshell.py, the PEP patch would 
>have to notice that pyshell is a module within idlelib and alias 
>'__main__' to 'idlelib.pyshell', not 'pyshell'.  Would the same be true 
>if within-package import were all relative?

I think so because we're using .__spec__.name, which I though was post 
import name resolution.

Testing in my PEP499 branch:

Test 1:

    [~/src/cpython-cs at github(git:PEP499-cs)]fleet*> ./python.exe -i  Lib/idlelib/pyshell.py
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
    ModuleNotFoundError: No module named 'run'
    >>> sys.modules['__main__']
    <module '__main__' (<_frozen_importlib_external.SourceFileLoader object at 0x1088e6040>)>
    >>> sys.modules['pyshell']
    <module '__main__' (<_frozen_importlib_external.SourceFileLoader object at 0x1088e6040>)>
    >>> sys.modules['idlelib.pyshell']
    <module 'idlelib.pyshell' from '/Users/cameron/src/cpython-cs at github/Lib/idlelib/pyshell.py'>

So pyshell and idlelib.pyshell are distinct here. __main__ and pyshell 
are the same module, courtesy of your sys.modules assignment at the 
bottom of pyshell.py. Test 3 below will be with that commented out.

Test 2:

    [~/src/cpython-cs at github(git:PEP499-cs)]fleet*> PYTHONPATH=$PWD/Lib ./python.exe -i -m idlelib.pyshell
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
    ModuleNotFoundError: No module named 'run'
    >>> sys.modules['__main__']
    <module 'idlelib.pyshell' from '/Users/cameron/src/cpython-cs at github/Lib/idlelib/pyshell.py'>
    >>> sys.modules['pyshell']
    <module 'idlelib.pyshell' from '/Users/cameron/src/cpython-cs at github/Lib/idlelib/pyshell.py'>
    >>> sys.modules['idlelib.pyshell']
    <module 'idlelib.pyshell' from '/Users/cameron/src/cpython-cs at github/Lib/idlelib/pyshell.py'>
    >>> id(sys.modules['__main__'])
    4551072712
    >>> id(sys.modules['pyshell'])
    4551072712
    >>> id(sys.modules['idlelib.pyshell'])
    4551072712

So this has __main__ and idlelib.pyshell the same module from the PEP499 
patch and pyshell also the same from your sys.modules assignment.

Test 3, with the pyshell.py sys.modules assignment commented out:

    [~/src/cpython-cs at github(git:PEP499-cs)]fleet*> PYTHONPATH=$PWD/Lib ./python.exe -i -m idlelib.pyshell
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
    ModuleNotFoundError: No module named 'run'
    >>> sys.modules['__main__']
    <module 'idlelib.pyshell' from '/Users/cameron/src/cpython-cs at github/Lib/idlelib/pyshell.py'>
    >>> sys.modules['pyshell']
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    KeyError: 'pyshell'
    >>> sys.modules['idlelib.pyshell']
    <module 'idlelib.pyshell' from '/Users/cameron/src/cpython-cs at github/Lib/idlelib/pyshell.py'>
    >>> id(sys.modules['__main__'])
    4552379336
    >>> id(sys.modules['idlelib.pyshell'])
    4552379336

Here we've got __main__ and idlelib.pyshell the same module and no 
'pyshell' in sys.modules.

I don't think I understand your "relative import" scenario.

Cheers,
Cameron Simpson <cs at cskk.id.au>


More information about the Python-Dev mailing list