pFad - Phone/Frame/Anonymizer/Declutterfier! Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

URL: http://github.com/python/cpython/commit/52e14d640be3a7fa2c17f5a2a6bc9626d622aa40

PEP 302 + zipimport: · python/cpython@52e14d6 · GitHub
Skip to content

Commit 52e14d6

Browse files
committed
PEP 302 + zipimport:
- new import hooks in import.c, exposed in the sys module - new module called 'zipimport' - various changes to allow bootstrapping from zip files I hope I didn't break the Windows build (or anything else for that matter), but then again, it's been sitting on sf long enough... Regarding the latest discussions on python-dev: zipimport sets pkg.__path__ as specified in PEP 273, and likewise, sys.path item such as /path/to/Archive.zip/subdir/ are supported again.
1 parent 60087fb commit 52e14d6

13 files changed

Lines changed: 1887 additions & 35 deletions

File tree

Include/pythonrun.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ PyAPI_FUNC(PyObject *) _PyBuiltin_Init(void);
9999
PyAPI_FUNC(PyObject *) _PySys_Init(void);
100100
PyAPI_FUNC(void) _PyImport_Init(void);
101101
PyAPI_FUNC(void) _PyExc_Init(void);
102+
PyAPI_FUNC(void) _PyImportHooks_Init(void);
102103

103104
/* Various internal finalizers */
104105
PyAPI_FUNC(void) _PyExc_Fini(void);

Lib/site.py

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -73,16 +73,11 @@ def makepath(*paths):
7373
# only absolute pathnames, even if we're running from the build directory.
7474
L = []
7575
_dirs_in_sys_path = {}
76+
dir = dircase = None # sys.path may be empty at this point
7677
for dir in sys.path:
77-
# Filter out paths that don't exist, but leave in the empty string
78-
# since it's a special case. We also need to special-case the Mac,
79-
# as file names are allowed on sys.path there.
80-
if sys.platform != 'mac':
81-
if dir and not os.path.isdir(dir):
82-
continue
83-
else:
84-
if dir and not os.path.exists(dir):
85-
continue
78+
# Filter out duplicate paths (on case-insensitive file systems also
79+
# if they only differ in case); turn relative paths into absolute
80+
# paths.
8681
dir, dircase = makepath(dir)
8782
if not dircase in _dirs_in_sys_path:
8883
L.append(dir)

Lib/test/test_importhooks.py

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
import sys
2+
import imp
3+
import os
4+
import unittest
5+
from test import test_support
6+
7+
8+
test_src = """\
9+
def get_name():
10+
return __name__
11+
def get_file():
12+
return __file__
13+
"""
14+
15+
test_co = compile(test_src, "<???>", "exec")
16+
test_path = "!!!_test_!!!"
17+
18+
19+
class ImportTracker:
20+
"""Importer that only tracks attempted imports."""
21+
def __init__(self):
22+
self.imports = []
23+
def find_module(self, fullname, path=None):
24+
self.imports.append(fullname)
25+
return None
26+
27+
28+
class TestImporter:
29+
30+
modules = {
31+
"hooktestmodule": (False, test_co),
32+
"hooktestpackage": (True, test_co),
33+
"hooktestpackage.sub": (True, test_co),
34+
"hooktestpackage.sub.subber": (False, test_co),
35+
}
36+
37+
def __init__(self, path=test_path):
38+
if path != test_path:
39+
# if out class is on sys.path_hooks, we must raise
40+
# ImportError for any path item that we can't handle.
41+
raise ImportError
42+
self.path = path
43+
44+
def _get__path__(self):
45+
raise NotImplementedError
46+
47+
def find_module(self, fullname, path=None):
48+
if fullname in self.modules:
49+
return self
50+
else:
51+
return None
52+
53+
def load_module(self, fullname):
54+
ispkg, code = self.modules[fullname]
55+
mod = imp.new_module(fullname)
56+
sys.modules[fullname] = mod
57+
mod.__file__ = "<%s>" % self.__class__.__name__
58+
mod.__loader__ = self
59+
if ispkg:
60+
mod.__path__ = self._get__path__()
61+
exec code in mod.__dict__
62+
return mod
63+
64+
65+
class MetaImporter(TestImporter):
66+
def _get__path__(self):
67+
return []
68+
69+
class PathImporter(TestImporter):
70+
def _get__path__(self):
71+
return [self.path]
72+
73+
74+
class ImportBlocker:
75+
"""Place an ImportBlocker instance on sys.meta_path and you
76+
can be sure the modules you specified can't be imported, even
77+
if it's a builtin."""
78+
def __init__(self, *namestoblock):
79+
self.namestoblock = dict.fromkeys(namestoblock)
80+
def find_module(self, fullname, path=None):
81+
if fullname in self.namestoblock:
82+
return self
83+
return None
84+
def load_module(self, fullname):
85+
raise ImportError, "I dare you"
86+
87+
88+
class ImpWrapper:
89+
90+
def __init__(self, path=None):
91+
if path is not None and not os.path.isdir(path):
92+
raise ImportError
93+
self.path = path
94+
95+
def find_module(self, fullname, path=None):
96+
subname = fullname.split(".")[-1]
97+
if subname != fullname and self.path is None:
98+
return None
99+
if self.path is None:
100+
path = None
101+
else:
102+
path = [self.path]
103+
try:
104+
file, filename, stuff = imp.find_module(subname, path)
105+
except ImportError:
106+
return None
107+
return ImpLoader(file, filename, stuff)
108+
109+
110+
class ImpLoader:
111+
112+
def __init__(self, file, filename, stuff):
113+
self.file = file
114+
self.filename = filename
115+
self.stuff = stuff
116+
117+
def load_module(self, fullname):
118+
mod = imp.load_module(fullname, self.file, self.filename, self.stuff)
119+
if self.file:
120+
self.file.close()
121+
mod.__loader__ = self # for introspection
122+
return mod
123+
124+
125+
class ImportHooksBaseTestCase(unittest.TestCase):
126+
127+
def setUp(self):
128+
self.path = sys.path[:]
129+
self.meta_path = sys.meta_path[:]
130+
self.path_hooks = sys.path_hooks[:]
131+
sys.path_importer_cache.clear()
132+
self.tracker = ImportTracker()
133+
sys.meta_path.insert(0, self.tracker)
134+
135+
def tearDown(self):
136+
sys.path[:] = self.path
137+
sys.meta_path[:] = self.meta_path
138+
sys.path_hooks[:] = self.path_hooks
139+
sys.path_importer_cache.clear()
140+
for fullname in self.tracker.imports:
141+
if fullname in sys.modules:
142+
del sys.modules[fullname]
143+
144+
145+
class ImportHooksTestCase(ImportHooksBaseTestCase):
146+
147+
def doTestImports(self, importer=None):
148+
import hooktestmodule
149+
import hooktestpackage
150+
import hooktestpackage.sub
151+
import hooktestpackage.sub.subber
152+
self.assertEqual(hooktestmodule.get_name(),
153+
"hooktestmodule")
154+
self.assertEqual(hooktestpackage.get_name(),
155+
"hooktestpackage")
156+
self.assertEqual(hooktestpackage.sub.get_name(),
157+
"hooktestpackage.sub")
158+
self.assertEqual(hooktestpackage.sub.subber.get_name(),
159+
"hooktestpackage.sub.subber")
160+
if importer:
161+
self.assertEqual(hooktestmodule.__loader__, importer)
162+
self.assertEqual(hooktestpackage.__loader__, importer)
163+
self.assertEqual(hooktestpackage.sub.__loader__, importer)
164+
self.assertEqual(hooktestpackage.sub.subber.__loader__, importer)
165+
166+
def testMetaPath(self):
167+
i = MetaImporter()
168+
sys.meta_path.append(i)
169+
self.doTestImports(i)
170+
171+
def testPathHook(self):
172+
sys.path_hooks.append(PathImporter)
173+
sys.path.append(test_path)
174+
self.doTestImports()
175+
176+
def testBlocker(self):
177+
mname = "exceptions" # an arbitrary harmless builtin module
178+
if mname in sys.modules:
179+
del sys.modules[mname]
180+
sys.meta_path.append(ImportBlocker(mname))
181+
try:
182+
__import__(mname)
183+
except ImportError:
184+
pass
185+
else:
186+
self.fail("'%s' was not supposed to be importable" % mname)
187+
188+
def testImpWrapper(self):
189+
i = ImpWrapper()
190+
sys.meta_path.append(i)
191+
sys.path_hooks.append(ImpWrapper)
192+
mnames = ("colorsys", "urlparse", "distutils.core", "compiler.misc")
193+
for mname in mnames:
194+
parent = mname.split(".")[0]
195+
for n in sys.modules.keys():
196+
if n.startswith(parent):
197+
del sys.modules[n]
198+
for mname in mnames:
199+
m = __import__(mname, globals(), locals(), ["__dummy__"])
200+
m.__loader__ # to make sure we actually handled the import
201+
202+
203+
if __name__ == "__main__":
204+
test_support.run_unittest(ImportHooksTestCase)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.





Check this box to remove all script contents from the fetched content.



Check this box to remove all images from the fetched content.


Check this box to remove all CSS styles from the fetched content.


Check this box to keep images inefficiently compressed and original size.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy