Skip to content

Commit bd559a7

Browse files
committed
feat: add lazy regex
1 parent 3a1689d commit bd559a7

File tree

3 files changed

+31
-23
lines changed

3 files changed

+31
-23
lines changed

nested_multipart_parser/lazy.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import re
2+
3+
# compatibilty python < 3.9
4+
try:
5+
from functools import cache
6+
except ImportError:
7+
from functools import lru_cache as cache
8+
9+
10+
@cache
11+
def lazy_regex_compile(*ar, **kw):
12+
return re.compile(*ar, **kw)

nested_multipart_parser/options.py

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import re
1+
from nested_multipart_parser.lazy import lazy_regex_compile
22

33

44
class InvalidFormat(Exception):
@@ -16,7 +16,7 @@ def __new__(cls, cls_name, ns, childs):
1616
return super().__new__(cls, cls_name, ns, childs)
1717

1818

19-
TOKEN_PARSER = ("[", "]", ".")
19+
INVALID_TOKEN_PARSER = ("[", "]", ".")
2020

2121

2222
class NestedParserOptionsAbstract(metaclass=NestedParserOptionsType):
@@ -25,7 +25,7 @@ def check(self, key, keys):
2525
raise InvalidFormat(key)
2626

2727
first = keys[0]
28-
for token in TOKEN_PARSER:
28+
for token in INVALID_TOKEN_PARSER:
2929
if token in first:
3030
raise InvalidFormat(key)
3131

@@ -35,7 +35,7 @@ def check(self, key, keys):
3535
for c in key:
3636
if c.isspace():
3737
raise InvalidFormat(key)
38-
38+
3939
def split(self, key):
4040
contents = list(filter(None, self._reg_spliter.split(key)))
4141
if not contents:
@@ -50,18 +50,10 @@ def split(self, key):
5050
return list(filter(None, lst))
5151

5252

53-
REGEX_SEPARATOR = {
54-
"dot": r"(\.[^\.]+)",
55-
"bracket": r"([^\[\]]+)",
56-
"mixed": r"(\[\d+\])|([^\[\]]+)",
57-
"mixed-dot": r"(\[\d+\])|(\.[^\[\]\.]+)",
58-
}
59-
60-
6153
class NestedParserOptionsDot(NestedParserOptionsAbstract):
6254
def __init__(self):
63-
self._reg_spliter = re.compile(r"^([^\.]+)(.*?)(\.)?$")
64-
self._reg_options = re.compile(r"(\.[^\.]+)")
55+
self._reg_spliter = lazy_regex_compile(r"^([^\.]+)(.*?)(\.)?$")
56+
self._reg_options = lazy_regex_compile(r"(\.[^\.]+)")
6557

6658
def sanitize(self, key, value):
6759
contents = self.split(key)
@@ -88,8 +80,8 @@ def sanitize(self, key, value):
8880

8981
class NestedParserOptionsBracket(NestedParserOptionsAbstract):
9082
def __init__(self):
91-
self._reg_spliter = re.compile(r"^([^\[\]]+)(.*?)(\[\])?$")
92-
self._reg_options = re.compile(r"(\[[^\[\]]+\])")
83+
self._reg_spliter = lazy_regex_compile(r"^([^\[\]]+)(.*?)(\[\])?$")
84+
self._reg_options = lazy_regex_compile(r"(\[[^\[\]]+\])")
9385

9486
def sanitize(self, key, value):
9587
first, *lst = self.split(key)
@@ -117,8 +109,10 @@ def sanitize(self, key, value):
117109

118110
class NestedParserOptionsMixedDot(NestedParserOptionsAbstract):
119111
def __init__(self):
120-
self._reg_spliter = re.compile(r"^([^\[\]\.]+)(.*?)((?:\.)|(?:\[\]))?$")
121-
self._reg_options = re.compile(r"(\[\d+\])|(\.[^\[\]\.]+)")
112+
self._reg_spliter = lazy_regex_compile(
113+
r"^([^\[\]\.]+)(.*?)((?:\.)|(?:\[\]))?$"
114+
)
115+
self._reg_options = lazy_regex_compile(r"(\[\d+\])|(\.[^\[\]\.]+)")
122116

123117
def sanitize(self, key, value):
124118
first, *lst = self.split(key)
@@ -152,8 +146,10 @@ def sanitize(self, key, value):
152146

153147
class NestedParserOptionsMixed(NestedParserOptionsMixedDot):
154148
def __init__(self):
155-
self._reg_spliter = re.compile(r"^([^\[\]\.]+)(.*?)((?:\.)|(?:\[\]))?$")
156-
self._reg_options = re.compile(r"(\[\d+\])|(\.?[^\[\]\.]+)")
149+
self._reg_spliter = lazy_regex_compile(
150+
r"^([^\[\]\.]+)(.*?)((?:\.)|(?:\[\]))?$"
151+
)
152+
self._reg_options = lazy_regex_compile(r"(\[\d+\])|(\.?[^\[\]\.]+)")
157153

158154
def sanitize(self, key, value):
159155
first, *lst = self.split(key)

nested_multipart_parser/parser.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ class NestedParser:
2424
_valid = None
2525
errors = None
2626

27-
def __init__(self, data, options={}):
27+
def __init__(self, data, options=None):
2828
self.data = data
29-
self._options = {**DEFAULT_OPTIONS, **options}
29+
self._options = {**DEFAULT_OPTIONS, **(options or {})}
3030

3131
assert self._options["separator"] in [
3232
"dot",
@@ -40,8 +40,8 @@ def __init__(self, data, options={}):
4040
self._cls_options = REGEX_SEPARATOR[self._options["separator"]]
4141

4242
def _split_keys(self, data):
43+
checker = self._cls_options()
4344
for key, value in data.items():
44-
checker = self._cls_options()
4545
keys, value = checker.sanitize(key, value)
4646
checker.check(key, keys)
4747

0 commit comments

Comments
 (0)