Skip to content

Commit 6db977d

Browse files
authored
Merge pull request #4 from remigermain/sparator-mixed-dot
Separator mixed dot
2 parents a62d535 + defb801 commit 6db977d

File tree

4 files changed

+338
-34
lines changed

4 files changed

+338
-34
lines changed

README.md

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,10 @@ Attributes where sub keys are other than full numbers are converted into Python
141141
'the.0.chained.key.0.are.awesome.0.0': 'im here !!'
142142
}
143143
# with "mixed" separator option:
144+
data = {
145+
'the[0]chained.key[0]are.awesome[0][0]': 'im here !!'
146+
}
147+
# with "mixed-dot" separator option (same as 'mixed' but with dot after list to object):
144148
data = {
145149
'the[0].chained.key[0].are.awesome[0][0]': 'im here !!'
146150
}
@@ -154,7 +158,9 @@ For this to work perfectly, you must follow the following rules:
154158

155159
- Each sub key need to be separate by brackets `[ ]` or dot `.` (depends of your options)
156160

157-
- For `mixed` options, brackets `[]` is for list, and dot `.` is for object
161+
- For `mixed` or `mixed-dot` options, brackets `[]` is for list, and dot `.` is for object
162+
163+
- For `mixed-dot` options is look like `mixed` but with dot when object follow list
158164

159165
- Don't put spaces between separators.
160166

@@ -167,10 +173,11 @@ For this to work perfectly, you must follow the following rules:
167173
```python
168174
{
169175
# Separators:
170-
# with bracket: article[title][authors][0]: "jhon doe"
171-
# with dot: article.title.authors.0: "jhon doe"
172-
# with mixed: article.title.authors[0]: "jhon doe"
173-
'separator': 'bracket' or 'dot' or 'mixed', # default is bracket
176+
# with bracket: article[0][title][authors][0]: "jhon doe"
177+
# with dot: article.0.title.authors.0: "jhon doe"
178+
# with mixed: article[0]title.authors[0]: "jhon doe"
179+
# with mixed-dot: article[0].title.authors[0]: "jhon doe"
180+
'separator': 'bracket' or 'dot' or 'mixed' or 'mixed-dot', # default is bracket
174181

175182

176183
# raise a expections when you have duplicate keys

nested_multipart_parser/parser.py

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,20 @@ def _merge_options(self, options):
2020
self._options = options
2121

2222
assert self._options.get("separator", "dot") in [
23-
"dot", "bracket", "mixed"]
23+
"dot", "bracket", "mixed", "mixed-dot"]
2424
assert isinstance(self._options.get("raise_duplicate", False), bool)
2525
assert isinstance(self._options.get("assign_duplicate", False), bool)
2626

2727
self.__is_dot = False
2828
self.__is_mixed = False
2929
self.__is_bracket = False
30+
self.__is_mixed_dot = False
3031
if self._options["separator"] == "dot":
3132
self.__is_dot = True
3233
elif self._options["separator"] == "mixed":
3334
self.__is_mixed = True
35+
elif self._options["separator"] == "mixed-dot":
36+
self.__is_mixed_dot = True
3437
else:
3538
self.__is_bracket = True
3639
self._reg = re.compile(r"\[|\]")
@@ -54,13 +57,9 @@ def span(key, i):
5457
key = key[idx:]
5558

5659
i = 0
60+
last_is_list = False
5761
while i < len(key):
58-
if key[i] == '.':
59-
i += 1
60-
idx = span(key, i)
61-
keys.append(key[i: idx])
62-
i = idx
63-
elif key[i] == '[':
62+
if key[i] == '[':
6463
i += 1
6564
idx = span(key, i)
6665
if key[idx] != ']':
@@ -72,9 +71,22 @@ def span(key, i):
7271
f"invalid format key '{full_keys}', list key is not a valid number at position {i + pos}")
7372
keys.append(int(key[i: idx]))
7473
i = idx + 1
74+
last_is_list = True
7575
elif key[i] == ']':
7676
raise ValueError(
7777
f"invalid format key '{full_keys}', not start with bracket at position {i + pos}")
78+
elif (key[i] == '.' and self.__is_mixed_dot) or (
79+
not self.__is_mixed_dot and (
80+
(key[i] != '.' and last_is_list) or
81+
(key[i] == '.' and not last_is_list)
82+
)
83+
):
84+
if self.__is_mixed_dot or not last_is_list:
85+
i += 1
86+
idx = span(key, i)
87+
keys.append(key[i: idx])
88+
i = idx
89+
last_is_list = False
7890
else:
7991
raise ValueError(
8092
f"invalid format key '{full_keys}', invalid char at position {i + pos}")
@@ -90,7 +102,7 @@ def split_key(self, key):
90102
# reduce + filter are a hight cost so do manualy with for loop
91103

92104
# optimize by split with string func
93-
if self.__is_mixed:
105+
if self.__is_mixed or self.__is_mixed_dot:
94106
return self.mixed_split(key)
95107
if self.__is_dot:
96108
length = 1
@@ -133,7 +145,7 @@ def set_type(self, dtc, key, value, full_keys, prev=None, last=False):
133145
return key
134146

135147
def get_next_type(self, key):
136-
if self.__is_mixed:
148+
if self.__is_mixed or self.__is_mixed_dot:
137149
return [] if isinstance(key, int) else {}
138150
return [] if key.isdigit() else {}
139151

0 commit comments

Comments
 (0)