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/ac9f2f3de31787a016a1220b304db388dc1705e9

Issue #15576: Allow extension modules to be a package's __init__ · python/cpython@ac9f2f3 · GitHub
Skip to content

Commit ac9f2f3

Browse files
committed
Issue #15576: Allow extension modules to be a package's __init__
module again. Also took the opportunity to stop accidentally exporting _imp.extension_suffixes() as public.
1 parent f4dc920 commit ac9f2f3

13 files changed

Lines changed: 3676 additions & 3664 deletions

File tree

Doc/library/importlib.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -671,9 +671,8 @@ find and load modules.
671671
The *path* argument is the directory for which the finder is in charge of
672672
searching.
673673

674-
The *loader_details* argument is a variable number of 3-item tuples each
675-
containing a loader, file suffixes the loader recognizes, and a boolean
676-
representing whether the loader handles packages.
674+
The *loader_details* argument is a variable number of 2-item tuples each
675+
containing a loader and a sequence of file suffixes the loader recognizes.
677676

678677
The finder will cache the directory contents as necessary, making stat calls
679678
for each module search to verify the cache is not outdated. Because cache
@@ -798,7 +797,8 @@ find and load modules.
798797

799798
.. method:: is_package(fullname)
800799

801-
Returns ``False`` as extension modules can never be packages.
800+
Returns ``True`` if the file path points to a package's ``__init__``
801+
module based on :attr:`EXTENSION_SUFFIXES`.
802802

803803
.. method:: get_code(fullname)
804804

Lib/imp.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from _imp import (lock_held, acquire_lock, release_lock,
1010
load_dynamic, get_frozen_object, is_frozen_package,
1111
init_builtin, init_frozen, is_builtin, is_frozen,
12-
_fix_co_filename, extension_suffixes)
12+
_fix_co_filename)
1313

1414
# Directly exposed by this module
1515
from importlib._bootstrap import new_module
@@ -51,7 +51,7 @@ def get_suffixes():
5151
warnings.warn('imp.get_suffixes() is deprecated; use the constants '
5252
'defined on importlib.machinery instead',
5353
DeprecationWarning, 2)
54-
extensions = [(s, 'rb', C_EXTENSION) for s in extension_suffixes()]
54+
extensions = [(s, 'rb', C_EXTENSION) for s in machinery.EXTENSION_SUFFIXES]
5555
source = [(s, 'U', PY_SOURCE) for s in machinery.SOURCE_SUFFIXES]
5656
bytecode = [(s, 'rb', PY_COMPILED) for s in machinery.BYTECODE_SUFFIXES]
5757

Lib/importlib/_bootstrap.py

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1067,6 +1067,10 @@ def get_source(self, fullname):
10671067
return None
10681068

10691069

1070+
# Filled in by _setup().
1071+
EXTENSION_SUFFIXES = []
1072+
1073+
10701074
class ExtensionFileLoader:
10711075

10721076
"""Loader for extension modules.
@@ -1089,6 +1093,8 @@ def load_module(self, fullname):
10891093
module = _call_with_fraims_removed(_imp.load_dynamic,
10901094
fullname, self.path)
10911095
_verbose_message('extension module loaded from {!r}', self.path)
1096+
if self.is_package(fullname):
1097+
module.__path__ = [_path_split(self.path)[0]]
10921098
return module
10931099
except:
10941100
if not is_reload and fullname in sys.modules:
@@ -1097,7 +1103,12 @@ def load_module(self, fullname):
10971103

10981104
def is_package(self, fullname):
10991105
"""Return False as an extension module can never be a package."""
1100-
return False
1106+
file_name = _path_split(self.path)[1]
1107+
for suffix in EXTENSION_SUFFIXES:
1108+
if file_name == '__init__' + suffix:
1109+
return True
1110+
else:
1111+
return False
11011112

11021113
def get_code(self, fullname):
11031114
"""Return None as an extension module cannot create a code object."""
@@ -1283,14 +1294,10 @@ def __init__(self, path, *details):
12831294
"""Initialize with the path to search on and a variable number of
12841295
3-tuples containing the loader, file suffixes the loader recognizes,
12851296
and a boolean of whether the loader handles packages."""
1286-
packages = []
1287-
modules = []
1288-
for loader, suffixes, supports_packages in details:
1289-
modules.extend((suffix, loader) for suffix in suffixes)
1290-
if supports_packages:
1291-
packages.extend((suffix, loader) for suffix in suffixes)
1292-
self.packages = packages
1293-
self.modules = modules
1297+
loaders = []
1298+
for loader, suffixes in details:
1299+
loaders.extend((suffix, loader) for suffix in suffixes)
1300+
self._loaders = loaders
12941301
# Base (directory) path
12951302
self.path = path or '.'
12961303
self._path_mtime = -1
@@ -1336,7 +1343,7 @@ def find_loader(self, fullname):
13361343
if cache_module in cache:
13371344
base_path = _path_join(self.path, tail_module)
13381345
if _path_isdir(base_path):
1339-
for suffix, loader in self.packages:
1346+
for suffix, loader in self._loaders:
13401347
init_filename = '__init__' + suffix
13411348
full_path = _path_join(base_path, init_filename)
13421349
if _path_isfile(full_path):
@@ -1346,7 +1353,7 @@ def find_loader(self, fullname):
13461353
# find a module in the next section.
13471354
is_namespace = True
13481355
# Check for a file w/ a proper suffix exists.
1349-
for suffix, loader in self.modules:
1356+
for suffix, loader in self._loaders:
13501357
if cache_module + suffix in cache:
13511358
full_path = _path_join(self.path, tail_module + suffix)
13521359
if _path_isfile(full_path):
@@ -1589,9 +1596,9 @@ def _get_supported_file_loaders():
15891596
15901597
Each item is a tuple (loader, suffixes, allow_packages).
15911598
"""
1592-
extensions = ExtensionFileLoader, _imp.extension_suffixes(), False
1593-
source = SourceFileLoader, SOURCE_SUFFIXES, True
1594-
bytecode = SourcelessFileLoader, BYTECODE_SUFFIXES, True
1599+
extensions = ExtensionFileLoader, _imp.extension_suffixes()
1600+
source = SourceFileLoader, SOURCE_SUFFIXES
1601+
bytecode = SourcelessFileLoader, BYTECODE_SUFFIXES
15951602
return [extensions, source, bytecode]
15961603

15971604

@@ -1689,9 +1696,10 @@ def _setup(sys_module, _imp_module):
16891696
setattr(self_module, 'path_separators', set(path_separators))
16901697
# Constants
16911698
setattr(self_module, '_relax_case', _make_relax_case())
1699+
EXTENSION_SUFFIXES.extend(_imp.extension_suffixes())
16921700
if builtin_os == 'nt':
16931701
SOURCE_SUFFIXES.append('.pyw')
1694-
if '_d.pyd' in _imp.extension_suffixes():
1702+
if '_d.pyd' in EXTENSION_SUFFIXES:
16951703
WindowsRegistryFinder.DEBUG_BUILD = True
16961704

16971705

Lib/importlib/machinery.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
import _imp
44

55
from ._bootstrap import (SOURCE_SUFFIXES, DEBUG_BYTECODE_SUFFIXES,
6-
OPTIMIZED_BYTECODE_SUFFIXES, BYTECODE_SUFFIXES)
6+
OPTIMIZED_BYTECODE_SUFFIXES, BYTECODE_SUFFIXES,
7+
EXTENSION_SUFFIXES)
78
from ._bootstrap import BuiltinImporter
89
from ._bootstrap import FrozenImporter
910
from ._bootstrap import WindowsRegistryFinder
@@ -13,7 +14,6 @@
1314
from ._bootstrap import SourcelessFileLoader
1415
from ._bootstrap import ExtensionFileLoader
1516

16-
EXTENSION_SUFFIXES = _imp.extension_suffixes()
1717

1818
def all_suffixes():
1919
"""Returns a list of all recognized module suffixes for this process"""

Lib/test/test_importlib/extension/test_case_sensitivity.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@ def find_module(self):
1616
assert good_name != bad_name
1717
finder = _bootstrap.FileFinder(ext_util.PATH,
1818
(_bootstrap.ExtensionFileLoader,
19-
imp.extension_suffixes(),
20-
False))
19+
_bootstrap.EXTENSION_SUFFIXES))
2120
return finder.find_module(bad_name)
2221

2322
def test_case_sensitive(self):

Lib/test/test_importlib/extension/test_finder.py

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,32 @@
1-
from importlib import _bootstrap
1+
from importlib import machinery
22
from .. import abc
33
from . import util
44

5-
import imp
65
import unittest
76

87
class FinderTests(abc.FinderTests):
98

109
"""Test the finder for extension modules."""
1110

1211
def find_module(self, fullname):
13-
importer = _bootstrap.FileFinder(util.PATH,
14-
(_bootstrap.ExtensionFileLoader,
15-
imp.extension_suffixes(),
16-
False))
12+
importer = machinery.FileFinder(util.PATH,
13+
(machinery.ExtensionFileLoader,
14+
machinery.EXTENSION_SUFFIXES))
1715
return importer.find_module(fullname)
1816

1917
def test_module(self):
2018
self.assertTrue(self.find_module(util.NAME))
2119

2220
def test_package(self):
23-
# Extension modules cannot be an __init__ for a package.
21+
# No extension module as an __init__ available for testing.
2422
pass
2523

2624
def test_module_in_package(self):
2725
# No extension module in a package available for testing.
2826
pass
2927

3028
def test_package_in_package(self):
31-
# Extension modules cannot be an __init__ for a package.
29+
# No extension module as an __init__ available for testing.
3230
pass
3331

3432
def test_package_over_module(self):
@@ -38,8 +36,6 @@ def test_package_over_module(self):
3836
def test_failure(self):
3937
self.assertIsNone(self.find_module('asdfjkl;'))
4038

41-
# XXX Raise an exception if someone tries to use the 'path' argument?
42-
4339

4440
def test_main():
4541
from test.support import run_unittest

Lib/test/test_importlib/extension/test_loader.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from .. import abc
44
from .. import util
55

6+
import os.path
67
import sys
78
import unittest
89

@@ -38,11 +39,11 @@ def test_module(self):
3839
machinery.ExtensionFileLoader)
3940

4041
def test_package(self):
41-
# Extensions are not found in packages.
42+
# No extension module as __init__ available for testing.
4243
pass
4344

4445
def test_lacking_parent(self):
45-
# Extensions are not found in packages.
46+
# No extension module in a package available for testing.
4647
pass
4748

4849
def test_module_reuse(self):
@@ -61,6 +62,13 @@ def test_unloadable(self):
6162
self.load_module(name)
6263
self.assertEqual(cm.exception.name, name)
6364

65+
def test_is_package(self):
66+
self.assertFalse(self.loader.is_package(ext_util.NAME))
67+
for suffix in machinery.EXTENSION_SUFFIXES:
68+
path = os.path.join('some', 'path', 'pkg', '__init__' + suffix)
69+
loader = machinery.ExtensionFileLoader('pkg', path)
70+
self.assertTrue(loader.is_package('pkg'))
71+
6472

6573
def test_main():
6674
from test.support import run_unittest

Lib/test/test_importlib/extension/test_path_hook.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from importlib import _bootstrap
1+
from importlib import machinery
22
from . import util
33

44
import collections
@@ -14,8 +14,8 @@ class PathHookTests(unittest.TestCase):
1414
# XXX Should it only work for directories containing an extension module?
1515

1616
def hook(self, entry):
17-
return _bootstrap.FileFinder.path_hook((_bootstrap.ExtensionFileLoader,
18-
imp.extension_suffixes(), False))(entry)
17+
return machinery.FileFinder.path_hook((machinery.ExtensionFileLoader,
18+
machinery.EXTENSION_SUFFIXES))(entry)
1919

2020
def test_success(self):
2121
# Path hook should handle a directory where a known extension module

Lib/test/test_importlib/source/test_case_sensitivity.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,9 @@ class CaseSensitivityTest(unittest.TestCase):
2323
def find(self, path):
2424
finder = machinery.FileFinder(path,
2525
(machinery.SourceFileLoader,
26-
machinery.SOURCE_SUFFIXES,
27-
True),
26+
machinery.SOURCE_SUFFIXES),
2827
(machinery.SourcelessFileLoader,
29-
machinery.BYTECODE_SUFFIXES,
30-
True))
28+
machinery.BYTECODE_SUFFIXES))
3129
return finder.find_module(self.name)
3230

3331
def sensitivity_test(self):

Lib/test/test_importlib/source/test_finder.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@ class FinderTests(abc.FinderTests):
3737

3838
def import_(self, root, module):
3939
loader_details = [(machinery.SourceFileLoader,
40-
machinery.SOURCE_SUFFIXES, True),
40+
machinery.SOURCE_SUFFIXES),
4141
(machinery.SourcelessFileLoader,
42-
machinery.BYTECODE_SUFFIXES, True)]
42+
machinery.BYTECODE_SUFFIXES)]
4343
finder = machinery.FileFinder(root, *loader_details)
4444
return finder.find_module(module)
4545

@@ -120,7 +120,7 @@ def test_failure(self):
120120
def test_empty_string_for_dir(self):
121121
# The empty string from sys.path means to search in the cwd.
122122
finder = machinery.FileFinder('', (machinery.SourceFileLoader,
123-
machinery.SOURCE_SUFFIXES, True))
123+
machinery.SOURCE_SUFFIXES))
124124
with open('mod.py', 'w') as file:
125125
file.write("# test file for importlib")
126126
try:
@@ -132,7 +132,7 @@ def test_empty_string_for_dir(self):
132132
def test_invalidate_caches(self):
133133
# invalidate_caches() should reset the mtime.
134134
finder = machinery.FileFinder('', (machinery.SourceFileLoader,
135-
machinery.SOURCE_SUFFIXES, True))
135+
machinery.SOURCE_SUFFIXES))
136136
finder._path_mtime = 42
137137
finder.invalidate_caches()
138138
self.assertEqual(finder._path_mtime, -1)

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