Skip to content

Commit cbaa421

Browse files
committed
Extract multiple_use_keys into a class property.
1 parent 401bb33 commit cbaa421

File tree

2 files changed

+121
-114
lines changed

2 files changed

+121
-114
lines changed

importlib_metadata/_adapters.py

Lines changed: 22 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,30 @@
22
import textwrap
33
import email.message
44

5-
from ._functools import method_cache
5+
from ._text import FoldedCase
66

77

88
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+
929
def __new__(cls, orig: email.message.Message):
1030
res = super().__new__(cls)
1131
vars(res).update(vars(orig))
@@ -36,124 +56,12 @@ def json(self):
3656
Convert PackageMetadata to a JSON-compatible format
3757
per PEP 0566.
3858
"""
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-
)
5559

5660
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]
5862
if key == 'Keywords':
5963
value = re.split(r'\s+', value)
6064
tk = key.lower().replace('-', '_')
6165
return tk, value
6266

6367
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)

importlib_metadata/_text.py

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import re
2+
3+
from ._functools import method_cache
4+
5+
6+
# from jaraco.text 3.5
7+
class FoldedCase(str):
8+
"""
9+
A case insensitive string class; behaves just like str
10+
except compares equal when the only variation is case.
11+
12+
>>> s = FoldedCase('hello world')
13+
14+
>>> s == 'Hello World'
15+
True
16+
17+
>>> 'Hello World' == s
18+
True
19+
20+
>>> s != 'Hello World'
21+
False
22+
23+
>>> s.index('O')
24+
4
25+
26+
>>> s.split('O')
27+
['hell', ' w', 'rld']
28+
29+
>>> sorted(map(FoldedCase, ['GAMMA', 'alpha', 'Beta']))
30+
['alpha', 'Beta', 'GAMMA']
31+
32+
Sequence membership is straightforward.
33+
34+
>>> "Hello World" in [s]
35+
True
36+
>>> s in ["Hello World"]
37+
True
38+
39+
You may test for set inclusion, but candidate and elements
40+
must both be folded.
41+
42+
>>> FoldedCase("Hello World") in {s}
43+
True
44+
>>> s in {FoldedCase("Hello World")}
45+
True
46+
47+
String inclusion works as long as the FoldedCase object
48+
is on the right.
49+
50+
>>> "hello" in FoldedCase("Hello World")
51+
True
52+
53+
But not if the FoldedCase object is on the left:
54+
55+
>>> FoldedCase('hello') in 'Hello World'
56+
False
57+
58+
In that case, use in_:
59+
60+
>>> FoldedCase('hello').in_('Hello World')
61+
True
62+
63+
>>> FoldedCase('hello') > FoldedCase('Hello')
64+
False
65+
"""
66+
67+
def __lt__(self, other):
68+
return self.lower() < other.lower()
69+
70+
def __gt__(self, other):
71+
return self.lower() > other.lower()
72+
73+
def __eq__(self, other):
74+
return self.lower() == other.lower()
75+
76+
def __ne__(self, other):
77+
return self.lower() != other.lower()
78+
79+
def __hash__(self):
80+
return hash(self.lower())
81+
82+
def __contains__(self, other):
83+
return super(FoldedCase, self).lower().__contains__(other.lower())
84+
85+
def in_(self, other):
86+
"Does self appear in other?"
87+
return self in FoldedCase(other)
88+
89+
# cache lower since it's likely to be called frequently.
90+
@method_cache
91+
def lower(self):
92+
return super(FoldedCase, self).lower()
93+
94+
def index(self, sub):
95+
return self.lower().index(sub.lower())
96+
97+
def split(self, splitter=' ', maxsplit=0):
98+
pattern = re.compile(re.escape(splitter), re.I)
99+
return pattern.split(self, maxsplit)

0 commit comments

Comments
 (0)