gh-139899: Introduce MetaPathFinder.discover and PathEntryFinder.disc… · python/cpython@157f271

GitHub

@@ -0,0 +1,121 @@

1+fromunittest.mockimportMock

2+3+fromtest.test_importlibimportutil

4+5+importlib=util.import_importlib('importlib')

6+machinery=util.import_importlib('importlib.machinery')

7+8+9+classDiscoverableFinder:

10+def__init__(self, discover=[]):

11+self._discovered_values=discover

12+13+deffind_spec(self, fullname, path=None, target=None):

14+raiseNotImplemented

15+16+defdiscover(self, parent=None):

17+yieldfromself._discovered_values

18+19+20+classTestPathFinder:

21+"""PathFinder implements MetaPathFinder, which uses the PathEntryFinder(s)

22+ registered in sys.path_hooks (and sys.path_importer_cache) to search

23+ sys.path or the parent's __path__.

24+25+ PathFinder.discover() should redirect to the .discover() method of the

26+ PathEntryFinder for each path entry.

27+ """

28+29+deftest_search_path_hooks_top_level(self):

30+modules= [

31+self.machinery.ModuleSpec(name='example1', loader=None),

32+self.machinery.ModuleSpec(name='example2', loader=None),

33+self.machinery.ModuleSpec(name='example3', loader=None),

34+ ]

35+36+withutil.import_state(

37+path_importer_cache={

38+'discoverable': DiscoverableFinder(discover=modules),

39+ },

40+path=['discoverable'],

41+ ):

42+discovered=list(self.machinery.PathFinder.discover())

43+44+self.assertEqual(discovered, modules)

45+46+47+deftest_search_path_hooks_parent(self):

48+parent=self.machinery.ModuleSpec(name='example', loader=None, is_package=True)

49+parent.submodule_search_locations.append('discoverable')

50+51+children= [

52+self.machinery.ModuleSpec(name='example.child1', loader=None),

53+self.machinery.ModuleSpec(name='example.child2', loader=None),

54+self.machinery.ModuleSpec(name='example.child3', loader=None),

55+ ]

56+57+withutil.import_state(

58+path_importer_cache={

59+'discoverable': DiscoverableFinder(discover=children)

60+ },

61+path=[],

62+ ):

63+discovered=list(self.machinery.PathFinder.discover(parent))

64+65+self.assertEqual(discovered, children)

66+67+deftest_invalid_parent(self):

68+parent=self.machinery.ModuleSpec(name='example', loader=None)

69+withself.assertRaises(ValueError):

70+list(self.machinery.PathFinder.discover(parent))

71+72+73+(

74+Frozen_TestPathFinder,

75+Source_TestPathFinder,

76+) =util.test_both(TestPathFinder, importlib=importlib, machinery=machinery)

77+78+79+classTestFileFinder:

80+"""FileFinder implements PathEntryFinder and provides the base finder

81+ implementation to search the file system.

82+ """

83+84+defget_finder(self, path):

85+loader_details= [

86+ (self.machinery.SourceFileLoader, self.machinery.SOURCE_SUFFIXES),

87+ (self.machinery.SourcelessFileLoader, self.machinery.BYTECODE_SUFFIXES),

88+ ]

89+returnself.machinery.FileFinder(path, *loader_details)

90+91+deftest_discover_top_level(self):

92+modules= {'example1', 'example2', 'example3'}

93+withutil.create_modules(*modules) asmapping:

94+finder=self.get_finder(mapping['.root'])

95+discovered=list(finder.discover())

96+self.assertEqual({spec.nameforspecindiscovered}, modules)

97+98+deftest_discover_parent(self):

99+modules= {

100+'example.child1',

101+'example.child2',

102+'example.child3',

103+ }

104+withutil.create_modules(*modules) asmapping:

105+example=self.get_finder(mapping['.root']).find_spec('example')

106+finder=self.get_finder(example.submodule_search_locations[0])

107+discovered=list(finder.discover(example))

108+self.assertEqual({spec.nameforspecindiscovered}, modules)

109+110+deftest_invalid_parent(self):

111+withutil.create_modules('example') asmapping:

112+finder=self.get_finder(mapping['.root'])

113+example=finder.find_spec('example')

114+withself.assertRaises(ValueError):

115+list(finder.discover(example))

116+117+118+(

119+Frozen_TestFileFinder,

120+Source_TestFileFinder,

121+) =util.test_both(TestFileFinder, importlib=importlib, machinery=machinery)