示例#1
0
    def test_frozentable(self):
        # Python exports a PyImport_FrozenModules symbol. This is a
        # pointer to an array of struct _frozen entries.  The end of the
        # array is marked by an entry containing a NULL name and zero
        # size.

        # In standard Python, this table contains a __hello__
        # module, and a __phello__ package containing a spam
        # module.
        class struct_frozen(Structure):
            _fields_ = [
                ("name", c_char_p),
                ("code", POINTER(c_ubyte)),
                ("size", c_int),
                ("is_package", c_bool),
                ("get_code", POINTER(c_ubyte)),  # Function ptr
            ]

        FrozenTable = POINTER(struct_frozen)

        modules = []
        for group in ["Bootstrap", "Stdlib", "Test"]:
            ft = FrozenTable.in_dll(pythonapi, f"_PyImport_Frozen{group}")
            # ft is a pointer to the struct_frozen entries:
            for entry in ft:
                # This is dangerous. We *can* iterate over a pointer, but
                # the loop will not terminate (maybe with an access
                # violation;-) because the pointer instance has no size.
                if entry.name is None:
                    break
                modname = entry.name.decode("ascii")
                modules.append(modname)
                with self.subTest(modname):
                    if entry.size != 0:
                        # Do a sanity check on entry.size and entry.code.
                        self.assertGreater(abs(entry.size), 10)
                        self.assertTrue(
                            [entry.code[i] for i in range(abs(entry.size))])
                    # Check the module's package-ness.
                    with import_helper.frozen_modules():
                        spec = importlib.util.find_spec(modname)
                    if entry.is_package:
                        # It's a package.
                        self.assertIsNotNone(spec.submodule_search_locations)
                    else:
                        self.assertIsNone(spec.submodule_search_locations)

        with import_helper.frozen_modules():
            expected = _imp._frozen_module_names()
        self.maxDiff = None
        self.assertEqual(
            modules, expected, "_PyImport_FrozenBootstrap example "
            "in Doc/library/ctypes.rst may be out of date")

        from ctypes import _pointer_type_cache
        del _pointer_type_cache[struct_frozen]
def list_frozen(names):
    submodules = set()
    for name in _imp._frozen_module_names():
        # To skip __hello__, __hello_alias__ and etc.
        if name.startswith('__'):
            continue
        if '.' in name:
            submodules.add(name)
        else:
            names.add(name)
    # Make sure all frozen submodules have a known parent.
    for name in list(submodules):
        if name.partition('.')[0] in names:
            submodules.remove(name)
    if submodules:
        raise Exception(f'unexpected frozen submodules: {sorted(submodules)}')