Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/importlib_metadata/_adapters.py: 76%

41 statements  

« prev     ^ index     » next       coverage.py v7.0.1, created at 2022-12-25 06:11 +0000

1import functools 

2import warnings 

3import re 

4import textwrap 

5import email.message 

6 

7from ._text import FoldedCase 

8from ._compat import pypy_partial 

9 

10 

11# Do not remove prior to 2024-01-01 or Python 3.14 

12_warn = functools.partial( 

13 warnings.warn, 

14 "Implicit None on return values is deprecated and will raise KeyErrors.", 

15 DeprecationWarning, 

16 stacklevel=pypy_partial(2), 

17) 

18 

19 

20class Message(email.message.Message): 

21 multiple_use_keys = set( 

22 map( 

23 FoldedCase, 

24 [ 

25 'Classifier', 

26 'Obsoletes-Dist', 

27 'Platform', 

28 'Project-URL', 

29 'Provides-Dist', 

30 'Provides-Extra', 

31 'Requires-Dist', 

32 'Requires-External', 

33 'Supported-Platform', 

34 'Dynamic', 

35 ], 

36 ) 

37 ) 

38 """ 

39 Keys that may be indicated multiple times per PEP 566. 

40 """ 

41 

42 def __new__(cls, orig: email.message.Message): 

43 res = super().__new__(cls) 

44 vars(res).update(vars(orig)) 

45 return res 

46 

47 def __init__(self, *args, **kwargs): 

48 self._headers = self._repair_headers() 

49 

50 # suppress spurious error from mypy 

51 def __iter__(self): 

52 return super().__iter__() 

53 

54 def __getitem__(self, item): 

55 """ 

56 Warn users that a ``KeyError`` can be expected when a 

57 mising key is supplied. Ref python/importlib_metadata#371. 

58 """ 

59 res = super().__getitem__(item) 

60 if res is None: 

61 _warn() 

62 return res 

63 

64 def _repair_headers(self): 

65 def redent(value): 

66 "Correct for RFC822 indentation" 

67 if not value or '\n' not in value: 

68 return value 

69 return textwrap.dedent(' ' * 8 + value) 

70 

71 headers = [(key, redent(value)) for key, value in vars(self)['_headers']] 

72 if self._payload: 

73 headers.append(('Description', self.get_payload())) 

74 return headers 

75 

76 @property 

77 def json(self): 

78 """ 

79 Convert PackageMetadata to a JSON-compatible format 

80 per PEP 0566. 

81 """ 

82 

83 def transform(key): 

84 value = self.get_all(key) if key in self.multiple_use_keys else self[key] 

85 if key == 'Keywords': 

86 value = re.split(r'\s+', value) 

87 tk = key.lower().replace('-', '_') 

88 return tk, value 

89 

90 return dict(map(transform, map(FoldedCase, self)))