Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.
 
 
 
 

103 rader
3.1 KiB

  1. import sys
  2. import unicodedata
  3. from configparser import RawConfigParser
  4. from .compat import py39
  5. from .warnings import SetuptoolsDeprecationWarning
  6. # HFS Plus uses decomposed UTF-8
  7. def decompose(path):
  8. if isinstance(path, str):
  9. return unicodedata.normalize('NFD', path)
  10. try:
  11. path = path.decode('utf-8')
  12. path = unicodedata.normalize('NFD', path)
  13. path = path.encode('utf-8')
  14. except UnicodeError:
  15. pass # Not UTF-8
  16. return path
  17. def filesys_decode(path):
  18. """
  19. Ensure that the given path is decoded,
  20. ``None`` when no expected encoding works
  21. """
  22. if isinstance(path, str):
  23. return path
  24. fs_enc = sys.getfilesystemencoding() or 'utf-8'
  25. candidates = fs_enc, 'utf-8'
  26. for enc in candidates:
  27. try:
  28. return path.decode(enc)
  29. except UnicodeDecodeError:
  30. continue
  31. return None
  32. def try_encode(string, enc):
  33. "turn unicode encoding into a functional routine"
  34. try:
  35. return string.encode(enc)
  36. except UnicodeEncodeError:
  37. return None
  38. def _read_utf8_with_fallback(file: str, fallback_encoding=py39.LOCALE_ENCODING) -> str:
  39. """
  40. First try to read the file with UTF-8, if there is an error fallback to a
  41. different encoding ("locale" by default). Returns the content of the file.
  42. Also useful when reading files that might have been produced by an older version of
  43. setuptools.
  44. """
  45. try:
  46. with open(file, "r", encoding="utf-8") as f:
  47. return f.read()
  48. except UnicodeDecodeError: # pragma: no cover
  49. _Utf8EncodingNeeded.emit(file=file, fallback_encoding=fallback_encoding)
  50. with open(file, "r", encoding=fallback_encoding) as f:
  51. return f.read()
  52. def _cfg_read_utf8_with_fallback(
  53. cfg: RawConfigParser, file: str, fallback_encoding=py39.LOCALE_ENCODING
  54. ) -> None:
  55. """Same idea as :func:`_read_utf8_with_fallback`, but for the
  56. :meth:`RawConfigParser.read` method.
  57. This method may call ``cfg.clear()``.
  58. """
  59. try:
  60. cfg.read(file, encoding="utf-8")
  61. except UnicodeDecodeError: # pragma: no cover
  62. _Utf8EncodingNeeded.emit(file=file, fallback_encoding=fallback_encoding)
  63. cfg.clear()
  64. cfg.read(file, encoding=fallback_encoding)
  65. class _Utf8EncodingNeeded(SetuptoolsDeprecationWarning):
  66. _SUMMARY = """
  67. `encoding="utf-8"` fails with {file!r}, trying `encoding={fallback_encoding!r}`.
  68. """
  69. _DETAILS = """
  70. Fallback behaviour for UTF-8 is considered **deprecated** and future versions of
  71. `setuptools` may not implement it.
  72. Please encode {file!r} with "utf-8" to ensure future builds will succeed.
  73. If this file was produced by `setuptools` itself, cleaning up the cached files
  74. and re-building/re-installing the package with a newer version of `setuptools`
  75. (e.g. by updating `build-system.requires` in its `pyproject.toml`)
  76. might solve the problem.
  77. """
  78. # TODO: Add a deadline?
  79. # Will we be able to remove this?
  80. # The question comes to mind mainly because of sdists that have been produced
  81. # by old versions of setuptools and published to PyPI...