图片解析应用
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.

57 lines
2.1 KiB

  1. import functools
  2. import logging
  3. import re
  4. from typing import NewType, Optional, Tuple, cast
  5. from pip._vendor.packaging import specifiers, version
  6. from pip._vendor.packaging.requirements import Requirement
  7. NormalizedExtra = NewType("NormalizedExtra", str)
  8. logger = logging.getLogger(__name__)
  9. def check_requires_python(
  10. requires_python: Optional[str], version_info: Tuple[int, ...]
  11. ) -> bool:
  12. """
  13. Check if the given Python version matches a "Requires-Python" specifier.
  14. :param version_info: A 3-tuple of ints representing a Python
  15. major-minor-micro version to check (e.g. `sys.version_info[:3]`).
  16. :return: `True` if the given Python version satisfies the requirement.
  17. Otherwise, return `False`.
  18. :raises InvalidSpecifier: If `requires_python` has an invalid format.
  19. """
  20. if requires_python is None:
  21. # The package provides no information
  22. return True
  23. requires_python_specifier = specifiers.SpecifierSet(requires_python)
  24. python_version = version.parse(".".join(map(str, version_info)))
  25. return python_version in requires_python_specifier
  26. @functools.lru_cache(maxsize=512)
  27. def get_requirement(req_string: str) -> Requirement:
  28. """Construct a packaging.Requirement object with caching"""
  29. # Parsing requirement strings is expensive, and is also expected to happen
  30. # with a low diversity of different arguments (at least relative the number
  31. # constructed). This method adds a cache to requirement object creation to
  32. # minimize repeated parsing of the same string to construct equivalent
  33. # Requirement objects.
  34. return Requirement(req_string)
  35. def safe_extra(extra: str) -> NormalizedExtra:
  36. """Convert an arbitrary string to a standard 'extra' name
  37. Any runs of non-alphanumeric characters are replaced with a single '_',
  38. and the result is always lowercased.
  39. This function is duplicated from ``pkg_resources``. Note that this is not
  40. the same to either ``canonicalize_name`` or ``_egg_link_name``.
  41. """
  42. return cast(NormalizedExtra, re.sub("[^A-Za-z0-9.-]+", "_", extra).lower())