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