Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 8d11013

Browse files
committed
Implement InspectLoader for FrozenImporter.
1 parent 2b9fd47 commit 8d11013

6 files changed

Lines changed: 100 additions & 10 deletions

File tree

Doc/library/importlib.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,8 @@ find and load modules.
284284
.. class:: FrozenImporter
285285

286286
An :term:`importer` for frozen modules. This class implements the
287-
:class:`importlib.abc.Finder` and :class:`importlib.abc.Loader` ABCs.
287+
:class:`importlib.abc.Finder` and :class:`importlib.abc.InspectLoader`
288+
ABCs.
288289

289290
Only class methods are defined by this class to alleviate the need for
290291
instantiation.

Lib/importlib/NOTES

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
to do
22
/////
33

4-
* Implement InspectLoader for FrozenImporter.
5-
6-
+ Expose function to see if a frozen module is a package.
7-
84
* Make sure that there is documentation *somewhere* fully explaining the
95
semantics of import that can be referenced from the package's documentation
106
(even if it is in the package documentation itself, although it might be best

Lib/importlib/_bootstrap.py

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,16 @@ def wrapper(self, fullname):
183183
return wrapper
184184

185185

186+
def _requires_frozen(fxn):
187+
"""Decorator to verify the named module is frozen."""
188+
def wrapper(self, fullname):
189+
if not imp.is_frozen(fullname):
190+
raise ImportError("{0} is not a frozen module".format(fullname))
191+
return fxn(self, fullname)
192+
_wrap(wrapper, fxn)
193+
return wrapper
194+
195+
186196
def _suffix_list(suffix_type):
187197
"""Return a list of file suffixes based on the imp file type."""
188198
return [suffix[0] for suffix in imp.get_suffixes()
@@ -261,10 +271,9 @@ def find_module(cls, fullname, path=None):
261271
@classmethod
262272
@set_package
263273
@set_loader
274+
@_requires_frozen
264275
def load_module(cls, fullname):
265276
"""Load a frozen module."""
266-
if cls.find_module(fullname) is None:
267-
raise ImportError("{0} is not a frozen module".format(fullname))
268277
is_reload = fullname in sys.modules
269278
try:
270279
return imp.init_frozen(fullname)
@@ -273,6 +282,24 @@ def load_module(cls, fullname):
273282
del sys.modules[fullname]
274283
raise
275284

285+
@classmethod
286+
@_requires_frozen
287+
def get_code(cls, fullname):
288+
"""Return the code object for the frozen module."""
289+
return imp.get_frozen_object(fullname)
290+
291+
@classmethod
292+
@_requires_frozen
293+
def get_source(cls, fullname):
294+
"""Return None as frozen modules do not have source code."""
295+
return None
296+
297+
@classmethod
298+
@_requires_frozen
299+
def is_package(cls, fullname):
300+
"""Return if the frozen module is a package."""
301+
return imp.is_frozen_package(fullname)
302+
276303

277304
class PyLoader:
278305

Lib/importlib/abc.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ def load_module(self, fullname:str) -> types.ModuleType:
1414
"""Abstract method which when implemented should load a module."""
1515
raise NotImplementedError
1616

17-
Loader.register(machinery.FrozenImporter)
18-
1917

2018
class Finder(metaclass=abc.ABCMeta):
2119

@@ -75,6 +73,7 @@ def get_source(self, fullname:str) -> str:
7573
return NotImplementedError
7674

7775
InspectLoader.register(machinery.BuiltinImporter)
76+
InspectLoader.register(machinery.FrozenImporter)
7877

7978

8079
class PyLoader(_bootstrap.PyLoader, InspectLoader):

Lib/importlib/test/frozen/test_loader.py

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
from importlib import machinery
2+
import imp
3+
import unittest
24
from .. import abc
35
from .. import util
46

@@ -53,9 +55,41 @@ def test_unloadable(self):
5355
'_not_real')
5456

5557

58+
class InspectLoaderTests(unittest.TestCase):
59+
60+
"""Tests for the InspectLoader methods for FrozenImporter."""
61+
62+
def test_get_code(self):
63+
# Make sure that the code object is good.
64+
name = '__hello__'
65+
code = machinery.FrozenImporter.get_code(name)
66+
mod = imp.new_module(name)
67+
exec(code, mod.__dict__)
68+
self.assert_(hasattr(mod, 'initialized'))
69+
70+
def test_get_source(self):
71+
# Should always return None.
72+
result = machinery.FrozenImporter.get_source('__hello__')
73+
self.assert_(result is None)
74+
75+
def test_is_package(self):
76+
# Should be able to tell what is a package.
77+
test_for = (('__hello__', False), ('__phello__', True),
78+
('__phello__.spam', False))
79+
for name, is_package in test_for:
80+
result = machinery.FrozenImporter.is_package(name)
81+
self.assert_(bool(result) == is_package)
82+
83+
def test_failure(self):
84+
# Raise ImportError for modules that are not frozen.
85+
for meth_name in ('get_code', 'get_source', 'is_package'):
86+
method = getattr(machinery.FrozenImporter, meth_name)
87+
self.assertRaises(ImportError, method, 'importlib')
88+
89+
5690
def test_main():
5791
from test.support import run_unittest
58-
run_unittest(LoaderTests)
92+
run_unittest(LoaderTests, InspectLoaderTests)
5993

6094

6195
if __name__ == '__main__':

Python/import.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1951,6 +1951,28 @@ get_frozen_object(char *name)
19511951
return PyMarshal_ReadObjectFromString((char *)p->code, size);
19521952
}
19531953

1954+
static PyObject *
1955+
is_frozen_package(char *name)
1956+
{
1957+
struct _frozen *p = find_frozen(name);
1958+
int size;
1959+
1960+
if (p == NULL) {
1961+
PyErr_Format(PyExc_ImportError,
1962+
"No such frozen object named %.200s",
1963+
name);
1964+
return NULL;
1965+
}
1966+
1967+
size = p->size;
1968+
1969+
if (size < 0)
1970+
Py_RETURN_TRUE;
1971+
else
1972+
Py_RETURN_FALSE;
1973+
}
1974+
1975+
19541976
/* Initialize a frozen module.
19551977
Return 1 for success, 0 if the module is not found, and -1 with
19561978
an exception set if the initialization failed.
@@ -2958,6 +2980,16 @@ imp_get_frozen_object(PyObject *self, PyObject *args)
29582980
return get_frozen_object(name);
29592981
}
29602982

2983+
static PyObject *
2984+
imp_is_frozen_package(PyObject *self, PyObject *args)
2985+
{
2986+
char *name;
2987+
2988+
if (!PyArg_ParseTuple(args, "s:is_frozen_package", &name))
2989+
return NULL;
2990+
return is_frozen_package(name);
2991+
}
2992+
29612993
static PyObject *
29622994
imp_is_builtin(PyObject *self, PyObject *args)
29632995
{
@@ -3191,6 +3223,7 @@ static PyMethodDef imp_methods[] = {
31913223
{"reload", imp_reload, METH_O, doc_reload},
31923224
/* The rest are obsolete */
31933225
{"get_frozen_object", imp_get_frozen_object, METH_VARARGS},
3226+
{"is_frozen_package", imp_is_frozen_package, METH_VARARGS},
31943227
{"init_builtin", imp_init_builtin, METH_VARARGS},
31953228
{"init_frozen", imp_init_frozen, METH_VARARGS},
31963229
{"is_builtin", imp_is_builtin, METH_VARARGS},

0 commit comments

Comments
 (0)