Skip to content

Commit 1435f8a

Browse files
committed
Refine concrete regex implementations
Primarily, make the regress forms inherit and share most of their code.
1 parent a1c3eb9 commit 1435f8a

File tree

1 file changed

+22
-61
lines changed

1 file changed

+22
-61
lines changed

src/check_jsonschema/regex_variants.py

+22-61
Original file line numberDiff line numberDiff line change
@@ -12,98 +12,54 @@ class RegexVariantName(enum.Enum):
1212
python = "python"
1313

1414

15-
class _ConcreteImplementation(t.Protocol):
16-
def check_format(self, instance: t.Any) -> bool: ...
17-
18-
def pattern_keyword(
19-
self, validator: t.Any, pattern: str, instance: str, schema: t.Any
20-
) -> t.Iterator[jsonschema.ValidationError]: ...
21-
22-
def patternProperties_keyword(
23-
self,
24-
validator: t.Any,
25-
patternProperties: dict[str, t.Any],
26-
instance: dict[str, t.Any],
27-
schema: t.Any,
28-
) -> t.Iterator[jsonschema.ValidationError]: ...
29-
30-
3115
class RegexImplementation:
3216
"""
3317
A high-level interface for getting at the different possible
3418
implementations of regex behaviors.
3519
"""
3620

37-
_real_implementation: _ConcreteImplementation
21+
_concrete: "_ConcreteImplementation"
3822

3923
def __init__(self, variant: RegexVariantName) -> None:
4024
self.variant = variant
4125

4226
if self.variant == RegexVariantName.default:
43-
self._real_implementation = _UnicodeRegressImplementation()
27+
self._concrete = _RegressImplementation()
4428
elif self.variant == RegexVariantName.nonunicode:
45-
self._real_implementation = _NonunicodeRegressImplementation()
29+
self._concrete = _NonunicodeRegressImplementation()
4630
else:
47-
self._real_implementation = _PythonImplementation()
31+
self._concrete = _PythonImplementation()
4832

49-
self.check_format = self._real_implementation.check_format
50-
self.pattern_keyword = self._real_implementation.pattern_keyword
51-
self.patternProperties_keyword = (
52-
self._real_implementation.patternProperties_keyword
53-
)
33+
self.check_format = self._concrete.check_format
34+
self.pattern_keyword = self._concrete.pattern_keyword
35+
self.patternProperties_keyword = self._concrete.patternProperties_keyword
5436

5537

56-
class _UnicodeRegressImplementation:
57-
def check_format(self, instance: t.Any) -> bool:
58-
if not isinstance(instance, str):
59-
return True
60-
try:
61-
regress.Regex(instance, flags="u")
62-
except regress.RegressError:
63-
return False
64-
return True
38+
class _ConcreteImplementation(t.Protocol):
39+
def check_format(self, instance: t.Any) -> bool: ...
6540

6641
def pattern_keyword(
6742
self, validator: t.Any, pattern: str, instance: str, schema: t.Any
68-
) -> t.Iterator[jsonschema.ValidationError]:
69-
if not validator.is_type(instance, "string"):
70-
return
71-
72-
try:
73-
regress_pattern = regress.Regex(pattern, flags="u")
74-
except regress.RegressError:
75-
yield jsonschema.ValidationError(f"pattern {pattern!r} failed to compile")
76-
if not regress_pattern.find(instance):
77-
yield jsonschema.ValidationError(f"{instance!r} does not match {pattern!r}")
43+
) -> t.Iterator[jsonschema.ValidationError]: ...
7844

7945
def patternProperties_keyword(
8046
self,
8147
validator: t.Any,
8248
patternProperties: dict[str, t.Any],
8349
instance: dict[str, t.Any],
8450
schema: t.Any,
85-
) -> t.Iterator[jsonschema.ValidationError]:
86-
if not validator.is_type(instance, "object"):
87-
return
51+
) -> t.Iterator[jsonschema.ValidationError]: ...
8852

89-
for pattern, subschema in patternProperties.items():
90-
regress_pattern = regress.Regex(pattern, flags="u")
91-
for k, v in instance.items():
92-
if regress_pattern.find(k):
93-
yield from validator.descend(
94-
v,
95-
subschema,
96-
path=k,
97-
schema_path=pattern,
98-
)
9953

54+
class _RegressImplementation:
55+
def _compile_pattern(self, pattern: str) -> regress.Regex:
56+
return regress.Regex(pattern, flags="u")
10057

101-
class _NonunicodeRegressImplementation:
10258
def check_format(self, instance: t.Any) -> bool:
10359
if not isinstance(instance, str):
10460
return True
10561
try:
106-
regress.Regex(instance)
62+
self._compile_pattern(instance)
10763
except regress.RegressError:
10864
return False
10965
return True
@@ -115,7 +71,7 @@ def pattern_keyword(
11571
return
11672

11773
try:
118-
regress_pattern = regress.Regex(pattern)
74+
regress_pattern = self._compile_pattern(pattern)
11975
except regress.RegressError:
12076
yield jsonschema.ValidationError(f"pattern {pattern!r} failed to compile")
12177
if not regress_pattern.find(instance):
@@ -132,7 +88,7 @@ def patternProperties_keyword(
13288
return
13389

13490
for pattern, subschema in patternProperties.items():
135-
regress_pattern = regress.Regex(pattern)
91+
regress_pattern = self._compile_pattern(pattern)
13692
for k, v in instance.items():
13793
if regress_pattern.find(k):
13894
yield from validator.descend(
@@ -143,6 +99,11 @@ def patternProperties_keyword(
14399
)
144100

145101

102+
class _NonunicodeRegressImplementation(_RegressImplementation):
103+
def _compile_pattern(self, pattern: str) -> regress.Regex:
104+
return regress.Regex(pattern)
105+
106+
146107
class _PythonImplementation:
147108
def check_format(self, instance: t.Any) -> bool:
148109
if not isinstance(instance, str):

0 commit comments

Comments
 (0)