You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

packaging.py 2.7KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. from __future__ import absolute_import
  2. import logging
  3. import sys
  4. from email.parser import FeedParser
  5. from pip._vendor import pkg_resources
  6. from pip._vendor.packaging import specifiers, version
  7. from pip._internal import exceptions
  8. from pip._internal.utils.misc import display_path
  9. from pip._internal.utils.typing import MYPY_CHECK_RUNNING
  10. if MYPY_CHECK_RUNNING:
  11. from typing import Optional # noqa: F401
  12. from email.message import Message # noqa: F401
  13. from pip._vendor.pkg_resources import Distribution # noqa: F401
  14. logger = logging.getLogger(__name__)
  15. def check_requires_python(requires_python):
  16. # type: (Optional[str]) -> bool
  17. """
  18. Check if the python version in use match the `requires_python` specifier.
  19. Returns `True` if the version of python in use matches the requirement.
  20. Returns `False` if the version of python in use does not matches the
  21. requirement.
  22. Raises an InvalidSpecifier if `requires_python` have an invalid format.
  23. """
  24. if requires_python is None:
  25. # The package provides no information
  26. return True
  27. requires_python_specifier = specifiers.SpecifierSet(requires_python)
  28. # We only use major.minor.micro
  29. python_version = version.parse('.'.join(map(str, sys.version_info[:3])))
  30. return python_version in requires_python_specifier
  31. def get_metadata(dist):
  32. # type: (Distribution) -> Message
  33. if (isinstance(dist, pkg_resources.DistInfoDistribution) and
  34. dist.has_metadata('METADATA')):
  35. metadata = dist.get_metadata('METADATA')
  36. elif dist.has_metadata('PKG-INFO'):
  37. metadata = dist.get_metadata('PKG-INFO')
  38. else:
  39. logger.warning("No metadata found in %s", display_path(dist.location))
  40. metadata = ''
  41. feed_parser = FeedParser()
  42. feed_parser.feed(metadata)
  43. return feed_parser.close()
  44. def check_dist_requires_python(dist):
  45. pkg_info_dict = get_metadata(dist)
  46. requires_python = pkg_info_dict.get('Requires-Python')
  47. try:
  48. if not check_requires_python(requires_python):
  49. raise exceptions.UnsupportedPythonVersion(
  50. "%s requires Python '%s' but the running Python is %s" % (
  51. dist.project_name,
  52. requires_python,
  53. '.'.join(map(str, sys.version_info[:3])),)
  54. )
  55. except specifiers.InvalidSpecifier as e:
  56. logger.warning(
  57. "Package %s has an invalid Requires-Python entry %s - %s",
  58. dist.project_name, requires_python, e,
  59. )
  60. return
  61. def get_installer(dist):
  62. # type: (Distribution) -> str
  63. if dist.has_metadata('INSTALLER'):
  64. for line in dist.get_metadata_lines('INSTALLER'):
  65. if line.strip():
  66. return line.strip()
  67. return ''