Repository navigation
Re-implement parts of imp in pure Python #58167
Copy link
Copy link
Closed
Labels
release-blockerstdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directory
Description
| BPO | 13959 |
|---|---|
| Nosy | @brettcannon, @birkenfeld, @pitrou, @vstinner, @benjaminp, @merwok, @meadori, @ericsnowcurrently, @berkerpeksag |
| PRs | |
| Dependencies | |
| Files |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
assignee = 'https://github.com/brettcannon'
closed_at = <Date 2012-07-09.20:23:48.007>
created_at = <Date 2012-02-07.00:51:29.679>
labels = ['library', 'release-blocker']
title = 'Re-implement parts of imp in pure Python'
updated_at = <Date 2017-12-06.16:25:57.617>
user = 'https://github.com/brettcannon'bugs.python.org fields:
activity = <Date 2017-12-06.16:25:57.617>
actor = 'vstinner'
assignee = 'brett.cannon'
closed = True
closed_date = <Date 2012-07-09.20:23:48.007>
closer = 'brett.cannon'
components = ['Library (Lib)']
creation = <Date 2012-02-07.00:51:29.679>
creator = 'brett.cannon'
dependencies = ['2377', '14605', '14657', '15166', '15167']
files = ['24846', '24979', '24980', '25250', '25302', '25303', '25308', '25309', '25335', '25336', '25834', '26058']
hgrepos = []
issue_num = 13959
keywords = ['patch']
message_count = 76.0
messages = ['152800', '155790', '156473', '156474', '156475', '156527', '156530', '156964', '158269', '158362', '158364', '158365', '158370', '158371', '158377', '158383', '158398', '158474', '158522', '158531', '158555', '158575', '158593', '158594', '158622', '158628', '158704', '158895', '158908', '158930', '158931', '158939', '158941', '158951', '158955', '158968', '158971', '158985', '158986', '158995', '158998', '158999', '159118', '159119', '159628', '159630', '159631', '159641', '159644', '159757', '159758', '159960', '159962', '159969', '160424', '160433', '160434', '160439', '160493', '160495', '160524', '162276', '162356', '162357', '162364', '162384', '162940', '163212', '163232', '163569', '163798', '164102', '165116', '165120', '165148', '307747']
nosy_count = 12.0
nosy_names = ['brett.cannon', 'georg.brandl', 'jpe', 'pitrou', 'vstinner', 'benjamin.peterson', 'eric.araujo', 'Arfrever', 'meador.inge', 'python-dev', 'eric.snow', 'berker.peksag']
pr_nums = ['4736']
priority = 'release blocker'
resolution = 'fixed'
stage = 'needs patch'
status = 'closed'
superseder = None
type = None
url = 'https://bugs.python.org/issue13959'
versions = ['Python 3.3']Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
release-blockerstdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directory
Activity
python-dev commentedon Apr 15, 2012
New changeset 4dce3afc392c by Brett Cannon in branch 'default':
Issue bpo-13959: Simplify imp.reload() by relying on a module's
http://hg.python.org/cpython/rev/4dce3afc392c
brettcannon commentedon Apr 15, 2012
I am seeing how this is going to go down. the load_dynamic, load_source, etc. family of functions are simply dispatched to by load_module(). So to keep some semblance of backwards-compatibility, each of those modules need to be implemented and then have load_module() simply dispatch to them based on the "type" of module it is.
python-dev commentedon Apr 16, 2012
New changeset 2df37938b8e1 by Brett Cannon in branch 'default':
Issue bpo-13959: Re-implement imp.load_module() in imp.py.
http://hg.python.org/cpython/rev/2df37938b8e1
python-dev commentedon Apr 16, 2012
New changeset 4256df44023b by Brett Cannon in branch 'default':
Issue bpo-13959: Re-implement imp.load_package() in imp.py.
http://hg.python.org/cpython/rev/4256df44023b
brettcannon commentedon Apr 16, 2012
From Eric Smith on python-dev:
Should this be:
if mode and (not mode.startswith(('r', 'U')) or '+' in mode):
to match:
python-dev commentedon Apr 17, 2012
New changeset 3b5b4b4bb43c by Brett Cannon in branch 'default':
Issue bpo-13959: Re-implement imp.load_source() in imp.py.
http://hg.python.org/cpython/rev/3b5b4b4bb43c
ericsnowcurrently commentedon Apr 17, 2012
This is a mostly-working sketch of find_module() in imp.py. I've run out of time tonight, but wanted to get it up in case it's useful to anyone else (a.k.a Brett). If nobody's touched it before then, I'll finish it up tomorrow.
brettcannon commentedon Apr 17, 2012
I doubt I will beat you to it, Eric, but I did want to say that your overall design was what I had in my head when I was thinking about how to re-implement the function, so keep at it!
python-dev commentedon Apr 17, 2012
New changeset 66bd85bcf916 by Brett Cannon in branch 'default':
Issue bpo-13959: Re-implement imp.load_compiled() in imp.py.
http://hg.python.org/cpython/rev/66bd85bcf916
ericsnowcurrently commentedon Apr 18, 2012
2 "problems" with that last patch:
ericsnowcurrently commentedon Apr 18, 2012
rather, tokenize.detect_encoding()
brettcannon commentedon Apr 18, 2012
You could change Lib/imp.py to have
import _frozen_importlib as _bootstrapif you want the same modules coming from imp, but I would argue against changing importlib itself being changed as that complicates development since if you screw up importlib._bootstrap when you compile it becomes a major pain to revert the importlib.h change, recompile, and continue to do that until you get it right. Plus you would only care about this if you are doing isinstance() checks on what kind of loader you have which you shouldn't care about since we have clearly defined ABCs to test against.As for Lib/test/badsyntax_pep3120.py, it *does* have a source encoding of UTF-8 since it does not explicitly specify an encoding. Based on the name I'm assuming the file itself has bad UTF-8 characters, but that doesn't mean that the file is not supposed to be interpreted as UTF-8.
ericsnowcurrently commentedon Apr 18, 2012
On the _frozen_importlib point, I'm fine with that. It was just counter-intuitive that the importlib._bootstrap functions were returning loaders whose classes weren't also defined there.
I'll have another look at that test tonight and run the patch through the full test suite, but otherwise I think find_module() is basically done.
ericsnowcurrently commentedon Apr 19, 2012
Looking it over, I'm confident that tokenizer.detect_encoding() does not raise a SyntaxError where PyTokenizer_FindEncodingFilename() does. I've run out of time tonight, but I'll look at it more tomorrow.
Once find_module() is done, I'd like to move on to reload(), which I expect will be pretty straightforward at this point. Then the feasibility of bpo-14618 should be clear.
python-dev commentedon Apr 20, 2012
New changeset c820aa9c0c00 by Brett Cannon in branch 'default':
Issue bpo-13959: Keep imp.get_magic() in C code, but cache in importlib
http://hg.python.org/cpython/rev/c820aa9c0c00
ericsnowcurrently commentedon Apr 21, 2012
I'd still like to consider this a bit more. When you're trying to understand imports, having one place to look (Lib/importlib/_bootstrap.py) is better than two, especially when the one is pure Python code. So it still may be worth it to pull in the odds and ends that play into that.
python-dev commentedon Apr 21, 2012
New changeset b773a751c2e7 by Brett Cannon in branch 'default':
Issue bpo-13959: Re-implement imp.cache_from_source() in Lib/imp.py.
http://hg.python.org/cpython/rev/b773a751c2e7
New changeset ea46ebba8a0f by Brett Cannon in branch 'default':
Issue bpo-13959: Re-implement imp.source_from_cache() in Lib/imp.py.
http://hg.python.org/cpython/rev/ea46ebba8a0f
brettcannon commentedon Apr 21, 2012
Time for a recap!
I am personally not bothering with moving imp.get_tag() and imp.get_magic() to importlib._bootstrap as the amount of C code required to support the public C API is not worth it. If someone else once to do the work then by all means attach a patch.
I still need to port imp.find_module() (and the various constants) and will base it off of Eric's code.
NullImporter will get ported once issue bpo-14605 (exposing the import machinery) lands.
get_suffixes() will also get ported, but that is a little bit more involved as I need to change how _DynLoadFiletab works by only storing the file extensions and not the other fluff (which is the same for all OSs).
After all of that is done then I will expose some API in importlib to replace find_module() and load_*() functions and then deprecate them (see issue bpo-14551 for an ongoing discussion the possible API).
ericsnowcurrently commentedon Apr 22, 2012
Yeah, I'm hoping to keep pressing those odds and ends forward. I have one lingering, oddball bug in find_module, but that patch is pretty much standing on its own.
python-dev commentedon Apr 22, 2012
New changeset 085cf1480cfe by Brett Cannon in branch 'default':
Issue bpo-13959: Re-implement imp.find_module() in Lib/imp.py.
http://hg.python.org/cpython/rev/085cf1480cfe
ericsnowcurrently commentedon Apr 22, 2012
Ported _imp.reload() (Python/import.c) to Lib/imp.py. Included is the change to PyImport_ReloadModule() to make it simply a wrapper around the pure Python imp.reload(). There's a good chance I don't have this right or that I have some reference leak. I haven't worked a ton on the C side of Python (sounds tropical). This patch also removes 'modules_reloading' from the interpreter state, since it's no longer used anywhere (see bpo-14618).
ericsnowcurrently commentedon Apr 22, 2012
A patch for magic and tag. It's not quite finished, but I wanted to see if the approach was palatable. FYI, I'm also trying to push forward the sys.implementation stuff, which would help on the pyc tag.
ericsnowcurrently commentedon Apr 22, 2012
After thinking about it, is MAGIC an implementation detail? It certainly reflects changes specific to the CPython interpreter. I'm much more comfortable with leaving implementation details in Python/import.c.
On the other hand, there's already no small amount of rather CPython-specific stuff in Lib/importlib/_bootstrap.py, which belongs there. The pyc magic bytes are tightly coupled with it. Because of that, I realize, I'm still fine with the patch.
But it makes me wonder if it might be worth having a clear separation between the general and CPython-specific stuff in _bootstrap.py, for the sake of people who look at the code for the first (or tenth) time. That's the same rationale I have for advocating moving as much over from import.c as relates to the importlib implementation.
python-dev commentedon Apr 22, 2012
New changeset 4e853913054c by Brett Cannon in branch 'default':
Issue bpo-13959: Continue to try to accomodate altsep in importlib by not
http://hg.python.org/cpython/rev/4e853913054c
brettcannon commentedon Apr 22, 2012
First off, you should separate the patches for get_magic() and get_tag(). Second, why is there _get_pyc_magic_int() when it is never called? Third, all of this would be greatly simplified if you just had a _RAW_MAGIC_NUMBER of 3220, did the bytes object creation for _MAGIC_NUMBER in-place (i.e. no separate function), and then in the C code just got _RAW_MAGIC_NUMBER and did the MAGIC macro work there.
As for what is CPython-specific and what isn't, only the other VMs can state that officially, so I'm not going to worry about that yet (but I will ask before Python 3.3 goes out so as to minimize backporting patches in the future). But importlib needs to stabilize more before that can happen.
ericsnowcurrently commentedon Apr 22, 2012
Good feedback. The some of that code was the result of directly translating the C. I'll get a new, simpler patch up probably tomorrow night. Thanks.
ericsnowcurrently commentedon Apr 23, 2012
How consistent do the semantics of reload() need to remain? (The C version does more type checking than the Python version probably needs to worry about. reload() seems to be one of those bits that doesn't have much test coverage.)
Also, what's the best way to exercise the changes one makes to the C code?
brettcannon commentedon Apr 23, 2012
Loosening the type restrictions is fine.
As for testing, that's what the test suite is supposed to do. So if need be just write tests in Python that exercise the C code.
brettcannon commentedon Apr 23, 2012
To try and narrow down the issue, I now have separate patches for an explicit sys.meta_path and a sys.path_hooks. Both fail on tests, but for different reasons.
The explicit sys.meta_path is still failing on the __main__ issue on three of the tests and for threaded imports on the other.
The explicit sys.path_hooks patch fails on two tests: one on threading and then test_cmd_line_script on apparently lacking an absolute file path thanks to issue bpo-8202 (and why an explicit sys.path_hooks triggers that I don't know).
Both failures Nick might know about.
ericsnowcurrently commentedon Apr 24, 2012
updated patch for magic number support in imp/importlib
ericsnowcurrently commentedon Apr 24, 2012
updated patch for moving TAG to importlib/imp.py
python-dev commentedon Apr 29, 2012
New changeset eb5c5c23ca9b by Brett Cannon in branch 'default':
Issue bpo-13959: Re-implement imp.NullImporter in Lib/imp.py.
http://hg.python.org/cpython/rev/eb5c5c23ca9b
brettcannon commentedon Apr 29, 2012
Update time!
With NullImporter dealt with, that leaves get_magic(), get_tag(), reload(), and get_suffixes() as things to potentially move to Lib/imp.py. I would also like to re-implement PyImport_ExecCodeModuleObject() as it's keeping a lot of C code alive just for its personal use.
merwok commentedon Apr 29, 2012
1659 lines less than 3.2’s import.c so far!
python-dev commentedon Apr 29, 2012
New changeset eb68502731dd by Brett Cannon in branch 'default':
Issues bpo-13959, 14647: Re-implement imp.reload() in Lib/imp.py.
http://hg.python.org/cpython/rev/eb68502731dd
brettcannon commentedon Apr 29, 2012
So here is the deal with PyImport_ExecCodeModuleObject(): bootstrapping and Barry has made this a little annoying. =)
First off, PyImport_ImportFrozenModuleObject() uses PyImport_ExecCodeModuleObject(), so that precludes just directly importing imp to handle this function entirely. OK, so that means just trying to chop out the path manipulation stuff since that is duplicating code found in imp/importlib.
The problem, though, is that PyImport_ExecCodeModuleWithPathnames() will take its pathname argument and try to get a source path from it if it points to some .pyc file (PEP-3147 or sourceless .pyc, and if that new path exists then it is used instead of the given path. Unfortunately that API was introduced in Python 3.2, so there is a backwards-compatibility issue in that one can't just rip out the code w/o supporting it. But those semantics are the reason the equivalent of imp.source_from_cache() continues to exist in Python/import.c.
I see two options here. One is to simply leave the C code in, but that has the drawback of duplicated Python and C code. Two is to stick in a call to imp.source_from_cache() between PyImport_ExecCodeModuleWithPathnames() and PyImport_ExecCodeModuleObject() so the former retains the semantics and the latter doesn't pick up the bad habit before 3.3 is released.
benjaminp commentedon May 1, 2012
Windows is currently failing test_imp:
http://www.python.org/dev/buildbot/all/builders/x86%20XP-5%203.x/builds/214/steps/test/logs/stdio
brettcannon commentedon May 1, 2012
That test is going to stay intermittent until issue bpo-14657 gets resolved else the exact reason for the failure is going to be hard to debug remotely.
python-dev commentedon May 4, 2012
New changeset 257cbd2fac38 by Brett Cannon in branch 'default':
Issue bpo-13959: Re-implement imp.get_suffixes() in Lib/imp.py.
http://hg.python.org/cpython/rev/257cbd2fac38
brettcannon commentedon May 4, 2012
OK, I'm waiting on issue bpo-14657 (avoiding the _frozen_importlib/importlib dichotomy) is resolved before I document the new imp.extension_suffixes() as it would be good to know where I should pull in the source and bytecode suffixes.
I think this only leaves get_magic() and get_tag() as the only things to move + trying to figure out how to handle PyImport_ExecCodeModuleObject() and its grip on various bits of C code.
python-dev commentedon May 4, 2012
New changeset 22b0689346f9 by Brett Cannon in branch 'default':
Issue bpo-13959: Move module type constants to Lib/imp.py.
http://hg.python.org/cpython/rev/22b0689346f9
python-dev commentedon May 11, 2012
New changeset b81ddaf0db47 by Brett Cannon in branch 'default':
Issue bpo-13959: Deprecate imp.get_suffixes() for new attributes on
http://hg.python.org/cpython/rev/b81ddaf0db47
ericsnowcurrently commentedon May 11, 2012
Question on this one:
Should that be the following?
Also, why the "[:]"?
Finally, in a couple spots you use the first element of the list (like the old case of "machinery.SOURCE_SUFFIXES[0]" in source_from_cache() and the new one in find_module()). Will this be a problem where the source file has one of the other suffixes? I'm not sure it's a big enough deal for the moment to worry about, but thought I'd ask. :)
brettcannon commentedon May 11, 2012
Yes.
And the [:] copies the list so I don't accidentally mutate in-place (did that once already, so now I'm just being paranoid; I doubt I need it hardly anywhere I don't do +=).
As for using SOURCE_SUFFIXES[0], I'm done following the ported code. I really don't care if .pyw isn't supported in that case. But in general people shouldn't assume just .py (or .py at all).
python-dev commentedon May 11, 2012
New changeset 626d5c6fbd95 by Brett Cannon in branch 'default':
Issue bpo-13959: Have
http://hg.python.org/cpython/rev/626d5c6fbd95
python-dev commentedon May 12, 2012
New changeset 7bf8ac742d2f by Brett Cannon in branch 'default':
Issue bpo-13959: Introduce importlib.find_loader().
http://hg.python.org/cpython/rev/7bf8ac742d2f
brettcannon commentedon May 12, 2012
I have importlib.find_loader() coded up, but getting rid of find_module() is going to be a pain thanks to pkgutil, multiprocessing.forking, modulefinder, and idlelib.EditorWindow.
python-dev commentedon May 13, 2012
New changeset 59870239813c by Brett Cannon in branch 'default':
Issue bpo-13959: Document imp.find_module/load_module as deprecated.
http://hg.python.org/cpython/rev/59870239813c
brettcannon commentedon Jun 4, 2012
Need to update the docstrings for imp.find_module() and load_module() to mention the functions are deprecated since there is no specific raised deprecation, only documented deprecation.
jpe commentedon Jun 5, 2012
This may be a known problem, but imp.load_module fails when trying to load a C extension. This is with the 3.3a4 release on Windows, though I suspect the problem is cross-platform.
brettcannon commentedon Jun 5, 2012
Does it work in Python 3.2, John? If it does then it's just an oversight thanks to the lack of tests in test_imp and it shouldn't be too difficult to support.
But do realize I have deprecated the function. =)
jpe commentedon Jun 5, 2012
On 6/5/12 1:08 PM, Brett Cannon wrote:
Attached is a short test file to demonstrate this. It assumes the
standard win32 layout, but shouldn't be hard to modify. It does work in
Python 3.2, but the else: clause in 3.3's imp.load_module function
raises an ImportError. I think the fix is to add an elif C_EXTENSION:
clause that loads the .so / .pyd.
I've already rewritten my code to use importlib when running in Python 3.3.
brettcannon commentedon Jun 6, 2012
You're right about the solution, John. I (or someone else) just needs to code it up.
python-dev commentedon Jun 15, 2012
New changeset 034c814eb187 by Brett Cannon in branch 'default':
Issue bpo-13959: Add to imp.find_module() and load_module's docstrings
http://hg.python.org/cpython/rev/034c814eb187
birkenfeld commentedon Jun 19, 2012
Which parts are still missing here?
ericsnowcurrently commentedon Jun 19, 2012
Here are the things I'm aware of:
From my discussions with Brett, there was a laundry list he was aiming to get in for 3.3 (for import stuff in general). I know much of it got done, but not all of it. Of the remainder, I'm not sure how much of that he still wants to see get in. Some of it pertains to this issue, though not all.
birkenfeld commentedon Jun 23, 2012
OK, sounds like none of it would block beta1.
brettcannon commentedon Jun 24, 2012
Sorry, been on vacation the past week.
Georg is right, nothing left is a b1 blocker, just stuff I want to get in before 3.3 ships.
birkenfeld commentedon Jun 26, 2012
Moving back to blocker for beta2.
python-dev commentedon Jul 9, 2012
New changeset efb5e6ab10f4 by Brett Cannon in branch 'default':
Issue bpo-15167 (as part of bpo-13959): imp.get_magic() is no implemented in
http://hg.python.org/cpython/rev/efb5e6ab10f4
brettcannon commentedon Jul 9, 2012
Since the final issue is just a nicety, I am considering this issue closed.
ericsnowcurrently commentedon Jul 10, 2012
hurray!
vstinner commentedon Dec 6, 2017
New changeset 672b6ba by Victor Stinner in branch 'master':
bpo-32030: pass interp to _PyImport_Init() (bpo-4736)
672b6ba