test_api.py 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. import re
  2. import textwrap
  3. import unittest
  4. import importlib_metadata
  5. import packaging.requirements
  6. try:
  7. from collections.abc import Iterator
  8. except ImportError:
  9. from collections import Iterator # noqa: F401
  10. try:
  11. from builtins import str as text
  12. except ImportError:
  13. from __builtin__ import unicode as text
  14. class APITests(unittest.TestCase):
  15. version_pattern = r'\d+\.\d+(\.\d)?'
  16. def test_retrieves_version_of_self(self):
  17. version = importlib_metadata.version('importlib_metadata')
  18. assert isinstance(version, text)
  19. assert re.match(self.version_pattern, version)
  20. def test_retrieves_version_of_pip(self):
  21. # Assume pip is installed and retrieve the version of pip.
  22. version = importlib_metadata.version('pip')
  23. assert isinstance(version, text)
  24. assert re.match(self.version_pattern, version)
  25. def test_for_name_does_not_exist(self):
  26. with self.assertRaises(importlib_metadata.PackageNotFoundError):
  27. importlib_metadata.distribution('does-not-exist')
  28. def test_for_top_level(self):
  29. distribution = importlib_metadata.distribution('importlib_metadata')
  30. self.assertEqual(
  31. distribution.read_text('top_level.txt').strip(),
  32. 'importlib_metadata')
  33. def test_read_text(self):
  34. top_level = [
  35. path for path in importlib_metadata.files('importlib_metadata')
  36. if path.name == 'top_level.txt'
  37. ][0]
  38. self.assertEqual(top_level.read_text(), 'importlib_metadata\n')
  39. def test_entry_points(self):
  40. scripts = importlib_metadata.entry_points()['console_scripts']
  41. scripts = dict(scripts)
  42. pip_ep = scripts['pip']
  43. # We should probably not be dependent on a third party package's
  44. # internal API staying stable.
  45. self.assertEqual(pip_ep.value, 'pip._internal:main')
  46. self.assertEqual(pip_ep.extras, [])
  47. def test_metadata_for_this_package(self):
  48. md = importlib_metadata.metadata('importlib_metadata')
  49. assert md['author'] == 'Barry Warsaw'
  50. assert md['LICENSE'] == 'Apache Software License'
  51. assert md['Name'] == 'importlib-metadata'
  52. classifiers = md.get_all('Classifier')
  53. assert 'Topic :: Software Development :: Libraries' in classifiers
  54. def test_importlib_metadata_version(self):
  55. assert re.match(self.version_pattern, importlib_metadata.__version__)
  56. @staticmethod
  57. def _test_files(files_iter):
  58. assert isinstance(files_iter, Iterator)
  59. files = list(files_iter)
  60. root = files[0].root
  61. for file in files:
  62. assert file.root == root
  63. assert not file.hash or file.hash.value
  64. assert not file.hash or file.hash.mode == 'sha256'
  65. assert not file.size or file.size >= 0
  66. assert file.locate().exists()
  67. assert isinstance(file.read_binary(), bytes)
  68. if file.name.endswith('.py'):
  69. file.read_text()
  70. def test_file_hash_repr(self):
  71. try:
  72. assertRegex = self.assertRegex
  73. except AttributeError:
  74. # Python 2
  75. assertRegex = self.assertRegexpMatches
  76. util = [
  77. p for p in importlib_metadata.files('wheel')
  78. if p.name == 'util.py'
  79. ][0]
  80. assertRegex(
  81. repr(util.hash),
  82. '<FileHash mode: sha256 value: .*>')
  83. def test_files_dist_info(self):
  84. self._test_files(importlib_metadata.files('pip'))
  85. def test_files_egg_info(self):
  86. self._test_files(importlib_metadata.files('importlib_metadata'))
  87. def test_find_local(self):
  88. dist = importlib_metadata.api.local_distribution()
  89. assert dist.metadata['Name'] == 'importlib-metadata'
  90. def test_requires(self):
  91. deps = importlib_metadata.requires('importlib_metadata')
  92. parsed = list(map(packaging.requirements.Requirement, deps))
  93. assert all(parsed)
  94. assert any(
  95. dep.name == 'pathlib2' and dep.marker
  96. for dep in parsed
  97. )
  98. def test_requires_dist_info(self):
  99. # assume 'packaging' is installed as a wheel with dist-info
  100. deps = importlib_metadata.requires('packaging')
  101. parsed = list(map(packaging.requirements.Requirement, deps))
  102. assert parsed
  103. def test_more_complex_deps_requires_text(self):
  104. requires = textwrap.dedent("""
  105. dep1
  106. dep2
  107. [:python_version < "3"]
  108. dep3
  109. [extra1]
  110. dep4
  111. [extra2:python_version < "3"]
  112. dep5
  113. """)
  114. deps = sorted(
  115. importlib_metadata.api.Distribution._deps_from_requires_text(
  116. requires)
  117. )
  118. expected = [
  119. 'dep1',
  120. 'dep2',
  121. 'dep3; python_version < "3"',
  122. 'dep4; extra == "extra1"',
  123. 'dep5; (python_version < "3") and extra == "extra2"',
  124. ]
  125. # It's important that the environment marker expression be
  126. # wrapped in parentheses to avoid the following 'and' binding more
  127. # tightly than some other part of the environment expression.
  128. assert deps == expected
  129. assert all(map(packaging.requirements.Requirement, deps))