mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	bpo-39791: Refresh importlib.metadata from importlib_metadata 1.6.1. (GH-20659) (GH-20661)
* Refresh importlib.metadata from importlib_metadata 1.6.1.
* 📜🤖 Added by blurb_it.
Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com>
(cherry picked from commit 161541ab45)
Co-authored-by: Jason R. Coombs <jaraco@jaraco.com>
Co-authored-by: Jason R. Coombs <jaraco@jaraco.com>
			
			
This commit is contained in:
		
							parent
							
								
									cdc3d9cb22
								
							
						
					
					
						commit
						a4fa9a9515
					
				
					 6 changed files with 84 additions and 18 deletions
				
			
		|  | @ -77,7 +77,9 @@ Entry points | ||||||
| The ``entry_points()`` function returns a dictionary of all entry points, | The ``entry_points()`` function returns a dictionary of all entry points, | ||||||
| keyed by group.  Entry points are represented by ``EntryPoint`` instances; | keyed by group.  Entry points are represented by ``EntryPoint`` instances; | ||||||
| each ``EntryPoint`` has a ``.name``, ``.group``, and ``.value`` attributes and | each ``EntryPoint`` has a ``.name``, ``.group``, and ``.value`` attributes and | ||||||
| a ``.load()`` method to resolve the value. | a ``.load()`` method to resolve the value.  There are also ``.module``, | ||||||
|  | ``.attr``, and ``.extras`` attributes for getting the components of the | ||||||
|  | ``.value`` attribute:: | ||||||
| 
 | 
 | ||||||
|     >>> eps = entry_points()  # doctest: +SKIP |     >>> eps = entry_points()  # doctest: +SKIP | ||||||
|     >>> list(eps)  # doctest: +SKIP |     >>> list(eps)  # doctest: +SKIP | ||||||
|  | @ -86,6 +88,12 @@ a ``.load()`` method to resolve the value. | ||||||
|     >>> wheel = [ep for ep in scripts if ep.name == 'wheel'][0]  # doctest: +SKIP |     >>> wheel = [ep for ep in scripts if ep.name == 'wheel'][0]  # doctest: +SKIP | ||||||
|     >>> wheel  # doctest: +SKIP |     >>> wheel  # doctest: +SKIP | ||||||
|     EntryPoint(name='wheel', value='wheel.cli:main', group='console_scripts') |     EntryPoint(name='wheel', value='wheel.cli:main', group='console_scripts') | ||||||
|  |     >>> wheel.module  # doctest: +SKIP | ||||||
|  |     'wheel.cli' | ||||||
|  |     >>> wheel.attr  # doctest: +SKIP | ||||||
|  |     'main' | ||||||
|  |     >>> wheel.extras  # doctest: +SKIP | ||||||
|  |     [] | ||||||
|     >>> main = wheel.load()  # doctest: +SKIP |     >>> main = wheel.load()  # doctest: +SKIP | ||||||
|     >>> main  # doctest: +SKIP |     >>> main  # doctest: +SKIP | ||||||
|     <function main at 0x103528488> |     <function main at 0x103528488> | ||||||
|  | @ -94,7 +102,7 @@ The ``group`` and ``name`` are arbitrary values defined by the package author | ||||||
| and usually a client will wish to resolve all entry points for a particular | and usually a client will wish to resolve all entry points for a particular | ||||||
| group.  Read `the setuptools docs | group.  Read `the setuptools docs | ||||||
| <https://setuptools.readthedocs.io/en/latest/setuptools.html#dynamic-discovery-of-services-and-plugins>`_ | <https://setuptools.readthedocs.io/en/latest/setuptools.html#dynamic-discovery-of-services-and-plugins>`_ | ||||||
| for more information on entrypoints, their definition, and usage. | for more information on entry points, their definition, and usage. | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| .. _metadata: | .. _metadata: | ||||||
|  | @ -235,7 +243,7 @@ method:: | ||||||
|         """ |         """ | ||||||
| 
 | 
 | ||||||
| The ``DistributionFinder.Context`` object provides ``.path`` and ``.name`` | The ``DistributionFinder.Context`` object provides ``.path`` and ``.name`` | ||||||
| properties indicating the path to search and names to match and may | properties indicating the path to search and name to match and may | ||||||
| supply other relevant context. | supply other relevant context. | ||||||
| 
 | 
 | ||||||
| What this means in practice is that to support finding distribution package | What this means in practice is that to support finding distribution package | ||||||
|  |  | ||||||
|  | @ -78,6 +78,16 @@ def load(self): | ||||||
|         attrs = filter(None, (match.group('attr') or '').split('.')) |         attrs = filter(None, (match.group('attr') or '').split('.')) | ||||||
|         return functools.reduce(getattr, attrs, module) |         return functools.reduce(getattr, attrs, module) | ||||||
| 
 | 
 | ||||||
|  |     @property | ||||||
|  |     def module(self): | ||||||
|  |         match = self.pattern.match(self.value) | ||||||
|  |         return match.group('module') | ||||||
|  | 
 | ||||||
|  |     @property | ||||||
|  |     def attr(self): | ||||||
|  |         match = self.pattern.match(self.value) | ||||||
|  |         return match.group('attr') | ||||||
|  | 
 | ||||||
|     @property |     @property | ||||||
|     def extras(self): |     def extras(self): | ||||||
|         match = self.pattern.match(self.value) |         match = self.pattern.match(self.value) | ||||||
|  | @ -170,7 +180,7 @@ def from_name(cls, name): | ||||||
|         """ |         """ | ||||||
|         for resolver in cls._discover_resolvers(): |         for resolver in cls._discover_resolvers(): | ||||||
|             dists = resolver(DistributionFinder.Context(name=name)) |             dists = resolver(DistributionFinder.Context(name=name)) | ||||||
|             dist = next(dists, None) |             dist = next(iter(dists), None) | ||||||
|             if dist is not None: |             if dist is not None: | ||||||
|                 return dist |                 return dist | ||||||
|         else: |         else: | ||||||
|  | @ -213,6 +223,17 @@ def _discover_resolvers(): | ||||||
|             ) |             ) | ||||||
|         return filter(None, declared) |         return filter(None, declared) | ||||||
| 
 | 
 | ||||||
|  |     @classmethod | ||||||
|  |     def _local(cls, root='.'): | ||||||
|  |         from pep517 import build, meta | ||||||
|  |         system = build.compat_system(root) | ||||||
|  |         builder = functools.partial( | ||||||
|  |             meta.build, | ||||||
|  |             source_dir=root, | ||||||
|  |             system=system, | ||||||
|  |             ) | ||||||
|  |         return PathDistribution(zipfile.Path(meta.build_as_zip(builder))) | ||||||
|  | 
 | ||||||
|     @property |     @property | ||||||
|     def metadata(self): |     def metadata(self): | ||||||
|         """Return the parsed metadata for this Distribution. |         """Return the parsed metadata for this Distribution. | ||||||
|  | @ -391,7 +412,7 @@ class FastPath: | ||||||
| 
 | 
 | ||||||
|     def __init__(self, root): |     def __init__(self, root): | ||||||
|         self.root = root |         self.root = root | ||||||
|         self.base = os.path.basename(root).lower() |         self.base = os.path.basename(self.root).lower() | ||||||
| 
 | 
 | ||||||
|     def joinpath(self, child): |     def joinpath(self, child): | ||||||
|         return pathlib.Path(self.root, child) |         return pathlib.Path(self.root, child) | ||||||
|  | @ -408,8 +429,8 @@ def zip_children(self): | ||||||
|         names = zip_path.root.namelist() |         names = zip_path.root.namelist() | ||||||
|         self.joinpath = zip_path.joinpath |         self.joinpath = zip_path.joinpath | ||||||
| 
 | 
 | ||||||
|         return ( |         return dict.fromkeys( | ||||||
|             posixpath.split(child)[0] |             child.split(posixpath.sep, 1)[0] | ||||||
|             for child in names |             for child in names | ||||||
|             ) |             ) | ||||||
| 
 | 
 | ||||||
|  | @ -475,7 +496,6 @@ def _search_paths(cls, name, paths): | ||||||
|             ) |             ) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| class PathDistribution(Distribution): | class PathDistribution(Distribution): | ||||||
|     def __init__(self, path): |     def __init__(self, path): | ||||||
|         """Construct a distribution from a path to the metadata directory. |         """Construct a distribution from a path to the metadata directory. | ||||||
|  |  | ||||||
|  | @ -161,6 +161,21 @@ def setUp(self): | ||||||
|         build_files(EggInfoFile.files, prefix=self.site_dir) |         build_files(EggInfoFile.files, prefix=self.site_dir) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | class LocalPackage: | ||||||
|  |     files = { | ||||||
|  |         "setup.py": """ | ||||||
|  |             import setuptools | ||||||
|  |             setuptools.setup(name="local-pkg", version="2.0.1") | ||||||
|  |             """, | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |     def setUp(self): | ||||||
|  |         self.fixtures = contextlib.ExitStack() | ||||||
|  |         self.addCleanup(self.fixtures.close) | ||||||
|  |         self.fixtures.enter_context(tempdir_as_cwd()) | ||||||
|  |         build_files(self.files) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| def build_files(file_defs, prefix=pathlib.Path()): | def build_files(file_defs, prefix=pathlib.Path()): | ||||||
|     """Build a set of files/directories, as described by the |     """Build a set of files/directories, as described by the | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -246,3 +246,19 @@ def test_json_dump(self): | ||||||
|         """ |         """ | ||||||
|         with self.assertRaises(Exception): |         with self.assertRaises(Exception): | ||||||
|             json.dumps(self.ep) |             json.dumps(self.ep) | ||||||
|  | 
 | ||||||
|  |     def test_module(self): | ||||||
|  |         assert self.ep.module == 'value' | ||||||
|  | 
 | ||||||
|  |     def test_attr(self): | ||||||
|  |         assert self.ep.attr is None | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class FileSystem(fixtures.OnSysPath, fixtures.SiteDir, unittest.TestCase): | ||||||
|  |     def test_unicode_dir_on_sys_path(self): | ||||||
|  |         """ | ||||||
|  |         Ensure a Unicode subdirectory of a directory on sys.path | ||||||
|  |         does not crash. | ||||||
|  |         """ | ||||||
|  |         fixtures.build_files({'☃': {}}, prefix=self.site_dir) | ||||||
|  |         list(distributions()) | ||||||
|  |  | ||||||
|  | @ -3,9 +3,10 @@ | ||||||
| 
 | 
 | ||||||
| from contextlib import ExitStack | from contextlib import ExitStack | ||||||
| from importlib.metadata import ( | from importlib.metadata import ( | ||||||
|     distribution, entry_points, files, PackageNotFoundError, version, |     distribution, entry_points, files, PackageNotFoundError, | ||||||
|  |     version, distributions, | ||||||
| ) | ) | ||||||
| from importlib.resources import path | from importlib import resources | ||||||
| 
 | 
 | ||||||
| from test.support import requires_zlib | from test.support import requires_zlib | ||||||
| 
 | 
 | ||||||
|  | @ -14,15 +15,19 @@ | ||||||
| class TestZip(unittest.TestCase): | class TestZip(unittest.TestCase): | ||||||
|     root = 'test.test_importlib.data' |     root = 'test.test_importlib.data' | ||||||
| 
 | 
 | ||||||
|  |     def _fixture_on_path(self, filename): | ||||||
|  |         pkg_file = resources.files(self.root).joinpath(filename) | ||||||
|  |         file = self.resources.enter_context(resources.as_file(pkg_file)) | ||||||
|  |         assert file.name.startswith('example-'), file.name | ||||||
|  |         sys.path.insert(0, str(file)) | ||||||
|  |         self.resources.callback(sys.path.pop, 0) | ||||||
|  | 
 | ||||||
|     def setUp(self): |     def setUp(self): | ||||||
|         # Find the path to the example-*.whl so we can add it to the front of |         # Find the path to the example-*.whl so we can add it to the front of | ||||||
|         # sys.path, where we'll then try to find the metadata thereof. |         # sys.path, where we'll then try to find the metadata thereof. | ||||||
|         self.resources = ExitStack() |         self.resources = ExitStack() | ||||||
|         self.addCleanup(self.resources.close) |         self.addCleanup(self.resources.close) | ||||||
|         wheel = self.resources.enter_context( |         self._fixture_on_path('example-21.12-py3-none-any.whl') | ||||||
|             path(self.root, 'example-21.12-py3-none-any.whl')) |  | ||||||
|         sys.path.insert(0, str(wheel)) |  | ||||||
|         self.resources.callback(sys.path.pop, 0) |  | ||||||
| 
 | 
 | ||||||
|     def test_zip_version(self): |     def test_zip_version(self): | ||||||
|         self.assertEqual(version('example'), '21.12') |         self.assertEqual(version('example'), '21.12') | ||||||
|  | @ -49,6 +54,10 @@ def test_files(self): | ||||||
|             path = str(file.dist.locate_file(file)) |             path = str(file.dist.locate_file(file)) | ||||||
|             assert '.whl/' in path, path |             assert '.whl/' in path, path | ||||||
| 
 | 
 | ||||||
|  |     def test_one_distribution(self): | ||||||
|  |         dists = list(distributions(path=sys.path[:1])) | ||||||
|  |         assert len(dists) == 1 | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| @requires_zlib() | @requires_zlib() | ||||||
| class TestEgg(TestZip): | class TestEgg(TestZip): | ||||||
|  | @ -57,10 +66,7 @@ def setUp(self): | ||||||
|         # sys.path, where we'll then try to find the metadata thereof. |         # sys.path, where we'll then try to find the metadata thereof. | ||||||
|         self.resources = ExitStack() |         self.resources = ExitStack() | ||||||
|         self.addCleanup(self.resources.close) |         self.addCleanup(self.resources.close) | ||||||
|         egg = self.resources.enter_context( |         self._fixture_on_path('example-21.12-py3.6.egg') | ||||||
|             path(self.root, 'example-21.12-py3.6.egg')) |  | ||||||
|         sys.path.insert(0, str(egg)) |  | ||||||
|         self.resources.callback(sys.path.pop, 0) |  | ||||||
| 
 | 
 | ||||||
|     def test_files(self): |     def test_files(self): | ||||||
|         for file in files('example'): |         for file in files('example'): | ||||||
|  |  | ||||||
|  | @ -0,0 +1 @@ | ||||||
|  | Refresh importlib.metadata from importlib_metadata 1.6.1. | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Miss Islington (bot)
						Miss Islington (bot)