|
2 | 2 | import textwrap |
3 | 3 | import email.message |
4 | 4 |
|
5 | | -from ._functools import method_cache |
| 5 | +from ._text import FoldedCase |
6 | 6 |
|
7 | 7 |
|
8 | 8 | class 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 | + ], |
| 23 | + ) |
| 24 | + ) |
| 25 | + """ |
| 26 | + Keys that may be indicated multiple times per PEP 566. |
| 27 | + """ |
| 28 | + |
9 | 29 | def __new__(cls, orig: email.message.Message): |
10 | 30 | res = super().__new__(cls) |
11 | 31 | vars(res).update(vars(orig)) |
@@ -36,124 +56,12 @@ def json(self): |
36 | 56 | Convert PackageMetadata to a JSON-compatible format |
37 | 57 | per PEP 0566. |
38 | 58 | """ |
39 | | - multiple_use = set( |
40 | | - map( |
41 | | - FoldedCase, |
42 | | - [ |
43 | | - 'Classifier', |
44 | | - 'Obsoletes-Dist', |
45 | | - 'Platform', |
46 | | - 'Project-URL', |
47 | | - 'Provides-Dist', |
48 | | - 'Provides-Extra', |
49 | | - 'Requires-Dist', |
50 | | - 'Requires-External', |
51 | | - 'Supported-Platform', |
52 | | - ], |
53 | | - ) |
54 | | - ) |
55 | 59 |
|
56 | 60 | def transform(key): |
57 | | - value = self.get_all(key) if key in multiple_use else self[key] |
| 61 | + value = self.get_all(key) if key in self.multiple_use_keys else self[key] |
58 | 62 | if key == 'Keywords': |
59 | 63 | value = re.split(r'\s+', value) |
60 | 64 | tk = key.lower().replace('-', '_') |
61 | 65 | return tk, value |
62 | 66 |
|
63 | 67 | return dict(map(transform, map(FoldedCase, self))) |
64 | | - |
65 | | - |
66 | | -# from jaraco.text 3.5 |
67 | | -class FoldedCase(str): |
68 | | - """ |
69 | | - A case insensitive string class; behaves just like str |
70 | | - except compares equal when the only variation is case. |
71 | | -
|
72 | | - >>> s = FoldedCase('hello world') |
73 | | -
|
74 | | - >>> s == 'Hello World' |
75 | | - True |
76 | | -
|
77 | | - >>> 'Hello World' == s |
78 | | - True |
79 | | -
|
80 | | - >>> s != 'Hello World' |
81 | | - False |
82 | | -
|
83 | | - >>> s.index('O') |
84 | | - 4 |
85 | | -
|
86 | | - >>> s.split('O') |
87 | | - ['hell', ' w', 'rld'] |
88 | | -
|
89 | | - >>> sorted(map(FoldedCase, ['GAMMA', 'alpha', 'Beta'])) |
90 | | - ['alpha', 'Beta', 'GAMMA'] |
91 | | -
|
92 | | - Sequence membership is straightforward. |
93 | | -
|
94 | | - >>> "Hello World" in [s] |
95 | | - True |
96 | | - >>> s in ["Hello World"] |
97 | | - True |
98 | | -
|
99 | | - You may test for set inclusion, but candidate and elements |
100 | | - must both be folded. |
101 | | -
|
102 | | - >>> FoldedCase("Hello World") in {s} |
103 | | - True |
104 | | - >>> s in {FoldedCase("Hello World")} |
105 | | - True |
106 | | -
|
107 | | - String inclusion works as long as the FoldedCase object |
108 | | - is on the right. |
109 | | -
|
110 | | - >>> "hello" in FoldedCase("Hello World") |
111 | | - True |
112 | | -
|
113 | | - But not if the FoldedCase object is on the left: |
114 | | -
|
115 | | - >>> FoldedCase('hello') in 'Hello World' |
116 | | - False |
117 | | -
|
118 | | - In that case, use in_: |
119 | | -
|
120 | | - >>> FoldedCase('hello').in_('Hello World') |
121 | | - True |
122 | | -
|
123 | | - >>> FoldedCase('hello') > FoldedCase('Hello') |
124 | | - False |
125 | | - """ |
126 | | - |
127 | | - def __lt__(self, other): |
128 | | - return self.lower() < other.lower() |
129 | | - |
130 | | - def __gt__(self, other): |
131 | | - return self.lower() > other.lower() |
132 | | - |
133 | | - def __eq__(self, other): |
134 | | - return self.lower() == other.lower() |
135 | | - |
136 | | - def __ne__(self, other): |
137 | | - return self.lower() != other.lower() |
138 | | - |
139 | | - def __hash__(self): |
140 | | - return hash(self.lower()) |
141 | | - |
142 | | - def __contains__(self, other): |
143 | | - return super(FoldedCase, self).lower().__contains__(other.lower()) |
144 | | - |
145 | | - def in_(self, other): |
146 | | - "Does self appear in other?" |
147 | | - return self in FoldedCase(other) |
148 | | - |
149 | | - # cache lower since it's likely to be called frequently. |
150 | | - @method_cache |
151 | | - def lower(self): |
152 | | - return super(FoldedCase, self).lower() |
153 | | - |
154 | | - def index(self, sub): |
155 | | - return self.lower().index(sub.lower()) |
156 | | - |
157 | | - def split(self, splitter=' ', maxsplit=0): |
158 | | - pattern = re.compile(re.escape(splitter), re.I) |
159 | | - return pattern.split(self, maxsplit) |
0 commit comments