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