_adapters.py 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. import re
  2. import textwrap
  3. import email.message
  4. from ._text import FoldedCase
  5. class Message(email.message.Message):
  6. multiple_use_keys = set(
  7. map(
  8. FoldedCase,
  9. [
  10. 'Classifier',
  11. 'Obsoletes-Dist',
  12. 'Platform',
  13. 'Project-URL',
  14. 'Provides-Dist',
  15. 'Provides-Extra',
  16. 'Requires-Dist',
  17. 'Requires-External',
  18. 'Supported-Platform',
  19. 'Dynamic',
  20. ],
  21. )
  22. )
  23. """
  24. Keys that may be indicated multiple times per PEP 566.
  25. """
  26. def __new__(cls, orig: email.message.Message):
  27. res = super().__new__(cls)
  28. vars(res).update(vars(orig))
  29. return res
  30. def __init__(self, *args, **kwargs):
  31. self._headers = self._repair_headers()
  32. # suppress spurious error from mypy
  33. def __iter__(self):
  34. return super().__iter__()
  35. def _repair_headers(self):
  36. def redent(value):
  37. "Correct for RFC822 indentation"
  38. if not value or '\n' not in value:
  39. return value
  40. return textwrap.dedent(' ' * 8 + value)
  41. headers = [(key, redent(value)) for key, value in vars(self)['_headers']]
  42. if self._payload:
  43. headers.append(('Description', self.get_payload()))
  44. return headers
  45. @property
  46. def json(self):
  47. """
  48. Convert PackageMetadata to a JSON-compatible format
  49. per PEP 0566.
  50. """
  51. def transform(key):
  52. value = self.get_all(key) if key in self.multiple_use_keys else self[key]
  53. if key == 'Keywords':
  54. value = re.split(r'\s+', value)
  55. tk = key.lower().replace('-', '_')
  56. return tk, value
  57. return dict(map(transform, map(FoldedCase, self)))