Skip to content

Commit 4d988a0

Browse files
committed
Rename the string regex attribute of matchers to regex
It's kinda dumb that I didn't do that in the first place and I'm not entirely sure why I missed it... Anyway there is no reason to make `pattern` be the string pattern and `regex` be the compiled pattern, that unnecessarily diverges from the regexes.yaml naming for the corresponding attribute which is a shame, and the compiled regex in python is... `re.Pattern`, so it makes more sense on both axis to have `pattern: re.Pattern[str]` and `regex: str`. Also add a `regex_flag` attribute/property on the device matchers for the string version of the flags.
1 parent db3385d commit 4d988a0

File tree

4 files changed

+55
-45
lines changed

4 files changed

+55
-45
lines changed

src/ua_parser/core.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ def __call__(self, ua: str) -> Optional[T]:
240240

241241
@property
242242
@abc.abstractmethod
243-
def pattern(self) -> str:
243+
def regex(self) -> str:
244244
"""Returns the matcher's pattern."""
245245
...
246246

src/ua_parser/lazy.py

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class UserAgentMatcher(Matcher[UserAgent]):
1717
1818
"""
1919

20-
pattern: str = ""
20+
regex: str = ""
2121
family: str
2222
major: Optional[str]
2323
minor: Optional[str]
@@ -33,15 +33,15 @@ def __init__(
3333
patch: Optional[str] = None,
3434
patch_minor: Optional[str] = None,
3535
) -> None:
36-
self.pattern = regex
36+
self.regex = regex
3737
self.family = family or "$1"
3838
self.major = major
3939
self.minor = minor
4040
self.patch = patch
4141
self.patch_minor = patch_minor
4242

4343
def __call__(self, ua: str) -> Optional[UserAgent]:
44-
if m := self.regex.search(ua):
44+
if m := self.pattern.search(ua):
4545
return UserAgent(
4646
family=(
4747
self.family.replace("$1", m[1])
@@ -56,8 +56,8 @@ def __call__(self, ua: str) -> Optional[UserAgent]:
5656
return None
5757

5858
@cached_property
59-
def regex(self) -> Pattern[str]:
60-
return re.compile(self.pattern)
59+
def pattern(self) -> Pattern[str]:
60+
return re.compile(self.regex)
6161

6262
def __repr__(self) -> str:
6363
fields = [
@@ -69,7 +69,7 @@ def __repr__(self) -> str:
6969
]
7070
args = "".join(f", {k}={v!r}" for k, v in fields if v is not None)
7171

72-
return f"UserAgentMatcher({self.pattern!r}{args})"
72+
return f"UserAgentMatcher({self.regex!r}{args})"
7373

7474

7575
class OSMatcher(Matcher[OS]):
@@ -81,7 +81,7 @@ class OSMatcher(Matcher[OS]):
8181
8282
"""
8383

84-
pattern: str = ""
84+
regex: str = ""
8585
family: str
8686
major: str
8787
minor: str
@@ -97,15 +97,15 @@ def __init__(
9797
patch: Optional[str] = None,
9898
patch_minor: Optional[str] = None,
9999
) -> None:
100-
self.pattern = regex
100+
self.regex = regex
101101
self.family = family or "$1"
102102
self.major = major or "$2"
103103
self.minor = minor or "$3"
104104
self.patch = patch or "$4"
105105
self.patch_minor = patch_minor or "$5"
106106

107107
def __call__(self, ua: str) -> Optional[OS]:
108-
if m := self.regex.search(ua):
108+
if m := self.pattern.search(ua):
109109
family = replacer(self.family, m)
110110
if family is None:
111111
raise ValueError(f"Unable to find OS family in {ua}")
@@ -119,8 +119,8 @@ def __call__(self, ua: str) -> Optional[OS]:
119119
return None
120120

121121
@cached_property
122-
def regex(self) -> Pattern[str]:
123-
return re.compile(self.pattern)
122+
def pattern(self) -> Pattern[str]:
123+
return re.compile(self.regex)
124124

125125
def __repr__(self) -> str:
126126
fields = [
@@ -132,7 +132,7 @@ def __repr__(self) -> str:
132132
]
133133
args = "".join(f", {k}={v!r}" for k, v in fields if v is not None)
134134

135-
return f"OSMatcher({self.pattern!r}{args})"
135+
return f"OSMatcher({self.regex!r}{args})"
136136

137137

138138
class DeviceMatcher(Matcher[Device]):
@@ -144,8 +144,8 @@ class DeviceMatcher(Matcher[Device]):
144144
145145
"""
146146

147-
pattern: str = ""
148-
flags: int = 0
147+
regex: str = ""
148+
regex_flag: Optional[Literal["i"]] = None
149149
family: str
150150
brand: str
151151
model: str
@@ -158,14 +158,14 @@ def __init__(
158158
brand: Optional[str] = None,
159159
model: Optional[str] = None,
160160
) -> None:
161-
self.pattern = regex
162-
self.flags = re.IGNORECASE if regex_flag == "i" else 0
161+
self.regex = regex
162+
self.regex_flag = regex_flag
163163
self.family = family or "$1"
164164
self.brand = brand or ""
165165
self.model = model or "$1"
166166

167167
def __call__(self, ua: str) -> Optional[Device]:
168-
if m := self.regex.search(ua):
168+
if m := self.pattern.search(ua):
169169
family = replacer(self.family, m)
170170
if family is None:
171171
raise ValueError(f"Unable to find device family in {ua}")
@@ -176,17 +176,21 @@ def __call__(self, ua: str) -> Optional[Device]:
176176
)
177177
return None
178178

179+
@property
180+
def flags(self) -> int:
181+
return re.IGNORECASE if self.regex_flag == "i" else 0
182+
179183
@cached_property
180-
def regex(self) -> Pattern[str]:
181-
return re.compile(self.pattern, flags=self.flags)
184+
def pattern(self) -> Pattern[str]:
185+
return re.compile(self.regex, flags=self.flags)
182186

183187
def __repr__(self) -> str:
184188
fields = [
185189
("family", self.family if self.family != "$1" else None),
186190
("brand", self.brand or None),
187191
("model", self.model if self.model != "$1" else None),
188192
]
189-
iflag = ', "i"' if self.flags & re.IGNORECASE else ""
193+
iflag = ', "i"' if self.regex_flag else ""
190194
args = iflag + "".join(f", {k}={v!r}" for k, v in fields if v is not None)
191195

192-
return f"DeviceMatcher({self.pattern!r}{args})"
196+
return f"DeviceMatcher({self.regex!r}{args})"

src/ua_parser/matchers.py

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ class UserAgentMatcher(Matcher[UserAgent]):
1313
1414
"""
1515

16-
regex: Pattern[str]
16+
pattern: Pattern[str]
1717
family: str
1818
major: Optional[str]
1919
minor: Optional[str]
@@ -29,15 +29,15 @@ def __init__(
2929
patch: Optional[str] = None,
3030
patch_minor: Optional[str] = None,
3131
) -> None:
32-
self.regex = re.compile(regex)
32+
self.pattern = re.compile(regex)
3333
self.family = family or "$1"
3434
self.major = major
3535
self.minor = minor
3636
self.patch = patch
3737
self.patch_minor = patch_minor
3838

3939
def __call__(self, ua: str) -> Optional[UserAgent]:
40-
if m := self.regex.search(ua):
40+
if m := self.pattern.search(ua):
4141
return UserAgent(
4242
family=(
4343
self.family.replace("$1", m[1])
@@ -52,8 +52,8 @@ def __call__(self, ua: str) -> Optional[UserAgent]:
5252
return None
5353

5454
@property
55-
def pattern(self) -> str:
56-
return self.regex.pattern
55+
def regex(self) -> str:
56+
return self.pattern.pattern
5757

5858
def __repr__(self) -> str:
5959
fields = [
@@ -65,7 +65,7 @@ def __repr__(self) -> str:
6565
]
6666
args = "".join(f", {k}={v!r}" for k, v in fields if v is not None)
6767

68-
return f"UserAgentMatcher({self.pattern!r}{args})"
68+
return f"UserAgentMatcher({self.regex!r}{args})"
6969

7070

7171
class OSMatcher(Matcher[OS]):
@@ -74,7 +74,7 @@ class OSMatcher(Matcher[OS]):
7474
7575
"""
7676

77-
regex: Pattern[str]
77+
pattern: Pattern[str]
7878
family: str
7979
major: str
8080
minor: str
@@ -90,15 +90,15 @@ def __init__(
9090
patch: Optional[str] = None,
9191
patch_minor: Optional[str] = None,
9292
) -> None:
93-
self.regex = re.compile(regex)
93+
self.pattern = re.compile(regex)
9494
self.family = family or "$1"
9595
self.major = major or "$2"
9696
self.minor = minor or "$3"
9797
self.patch = patch or "$4"
9898
self.patch_minor = patch_minor or "$5"
9999

100100
def __call__(self, ua: str) -> Optional[OS]:
101-
if m := self.regex.search(ua):
101+
if m := self.pattern.search(ua):
102102
family = replacer(self.family, m)
103103
if family is None:
104104
raise ValueError(f"Unable to find OS family in {ua}")
@@ -112,8 +112,8 @@ def __call__(self, ua: str) -> Optional[OS]:
112112
return None
113113

114114
@property
115-
def pattern(self) -> str:
116-
return self.regex.pattern
115+
def regex(self) -> str:
116+
return self.pattern.pattern
117117

118118
def __repr__(self) -> str:
119119
fields = [
@@ -125,7 +125,7 @@ def __repr__(self) -> str:
125125
]
126126
args = "".join(f", {k}={v!r}" for k, v in fields if v is not None)
127127

128-
return f"OSMatcher({self.pattern!r}{args})"
128+
return f"OSMatcher({self.regex!r}{args})"
129129

130130

131131
class DeviceMatcher(Matcher[Device]):
@@ -134,7 +134,7 @@ class DeviceMatcher(Matcher[Device]):
134134
135135
"""
136136

137-
regex: Pattern[str]
137+
pattern: Pattern[str]
138138
family: str
139139
brand: str
140140
model: str
@@ -147,13 +147,15 @@ def __init__(
147147
brand: Optional[str] = None,
148148
model: Optional[str] = None,
149149
) -> None:
150-
self.regex = re.compile(regex, flags=re.IGNORECASE if regex_flag == "i" else 0)
150+
self.pattern = re.compile(
151+
regex, flags=re.IGNORECASE if regex_flag == "i" else 0
152+
)
151153
self.family = family or "$1"
152154
self.brand = brand or ""
153155
self.model = model or "$1"
154156

155157
def __call__(self, ua: str) -> Optional[Device]:
156-
if m := self.regex.search(ua):
158+
if m := self.pattern.search(ua):
157159
family = replacer(self.family, m)
158160
if family is None:
159161
raise ValueError(f"Unable to find device family in {ua}")
@@ -165,12 +167,16 @@ def __call__(self, ua: str) -> Optional[Device]:
165167
return None
166168

167169
@property
168-
def pattern(self) -> str:
169-
return self.regex.pattern
170+
def regex(self) -> str:
171+
return self.pattern.pattern
172+
173+
@property
174+
def regex_flag(self) -> str:
175+
return "i" if self.flags & re.IGNORECASE else ""
170176

171177
@property
172178
def flags(self) -> int:
173-
return self.regex.flags
179+
return self.pattern.flags
174180

175181
def __repr__(self) -> str:
176182
fields = [
@@ -181,4 +187,4 @@ def __repr__(self) -> str:
181187
iflag = ', "i"' if self.flags & re.IGNORECASE else ""
182188
args = iflag + "".join(f", {k}={v!r}" for k, v in fields if v is not None)
183189

184-
return f"DeviceMatcher({self.pattern!r}{args})"
190+
return f"DeviceMatcher({self.regex!r}{args})"

src/ua_parser/re2.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,15 @@ def __init__(
3838
if self.user_agent_matchers:
3939
self.ua = re2.Filter()
4040
for u in self.user_agent_matchers:
41-
self.ua.Add(u.pattern)
41+
self.ua.Add(u.regex)
4242
self.ua.Compile()
4343
else:
4444
self.ua = DummyFilter()
4545

4646
if self.os_matchers:
4747
self.os = re2.Filter()
4848
for o in self.os_matchers:
49-
self.os.Add(o.pattern)
49+
self.os.Add(o.regex)
5050
self.os.Compile()
5151
else:
5252
self.os = DummyFilter()
@@ -58,9 +58,9 @@ def __init__(
5858
# no pattern uses global flags, but since they're not
5959
# supported in JS that seems safe.
6060
if d.flags & re.IGNORECASE:
61-
self.devices.Add("(?i)" + d.pattern)
61+
self.devices.Add("(?i)" + d.regex)
6262
else:
63-
self.devices.Add(d.pattern)
63+
self.devices.Add(d.regex)
6464
self.devices.Compile()
6565
else:
6666
self.devices = DummyFilter()

0 commit comments

Comments
 (0)