Skip to content

Commit

Permalink
Merge pull request #4 from remigermain/sparator-mixed-dot
Browse files Browse the repository at this point in the history
Separator mixed dot
  • Loading branch information
remigermain authored Oct 27, 2021
2 parents a62d535 + defb801 commit 6db977d
Show file tree
Hide file tree
Showing 4 changed files with 338 additions and 34 deletions.
17 changes: 12 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,10 @@ Attributes where sub keys are other than full numbers are converted into Python
'the.0.chained.key.0.are.awesome.0.0': 'im here !!'
}
# with "mixed" separator option:
data = {
'the[0]chained.key[0]are.awesome[0][0]': 'im here !!'
}
# with "mixed-dot" separator option (same as 'mixed' but with dot after list to object):
data = {
'the[0].chained.key[0].are.awesome[0][0]': 'im here !!'
}
Expand All @@ -154,7 +158,9 @@ For this to work perfectly, you must follow the following rules:

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

- For `mixed` options, brackets `[]` is for list, and dot `.` is for object
- For `mixed` or `mixed-dot` options, brackets `[]` is for list, and dot `.` is for object

- For `mixed-dot` options is look like `mixed` but with dot when object follow list

- Don't put spaces between separators.

Expand All @@ -167,10 +173,11 @@ For this to work perfectly, you must follow the following rules:
```python
{
# Separators:
# with bracket: article[title][authors][0]: "jhon doe"
# with dot: article.title.authors.0: "jhon doe"
# with mixed: article.title.authors[0]: "jhon doe"
'separator': 'bracket' or 'dot' or 'mixed', # default is bracket
# with bracket: article[0][title][authors][0]: "jhon doe"
# with dot: article.0.title.authors.0: "jhon doe"
# with mixed: article[0]title.authors[0]: "jhon doe"
# with mixed-dot: article[0].title.authors[0]: "jhon doe"
'separator': 'bracket' or 'dot' or 'mixed' or 'mixed-dot', # default is bracket


# raise a expections when you have duplicate keys
Expand Down
30 changes: 21 additions & 9 deletions nested_multipart_parser/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,20 @@ def _merge_options(self, options):
self._options = options

assert self._options.get("separator", "dot") in [
"dot", "bracket", "mixed"]
"dot", "bracket", "mixed", "mixed-dot"]
assert isinstance(self._options.get("raise_duplicate", False), bool)
assert isinstance(self._options.get("assign_duplicate", False), bool)

self.__is_dot = False
self.__is_mixed = False
self.__is_bracket = False
self.__is_mixed_dot = False
if self._options["separator"] == "dot":
self.__is_dot = True
elif self._options["separator"] == "mixed":
self.__is_mixed = True
elif self._options["separator"] == "mixed-dot":
self.__is_mixed_dot = True
else:
self.__is_bracket = True
self._reg = re.compile(r"\[|\]")
Expand All @@ -54,13 +57,9 @@ def span(key, i):
key = key[idx:]

i = 0
last_is_list = False
while i < len(key):
if key[i] == '.':
i += 1
idx = span(key, i)
keys.append(key[i: idx])
i = idx
elif key[i] == '[':
if key[i] == '[':
i += 1
idx = span(key, i)
if key[idx] != ']':
Expand All @@ -72,9 +71,22 @@ def span(key, i):
f"invalid format key '{full_keys}', list key is not a valid number at position {i + pos}")
keys.append(int(key[i: idx]))
i = idx + 1
last_is_list = True
elif key[i] == ']':
raise ValueError(
f"invalid format key '{full_keys}', not start with bracket at position {i + pos}")
elif (key[i] == '.' and self.__is_mixed_dot) or (
not self.__is_mixed_dot and (
(key[i] != '.' and last_is_list) or
(key[i] == '.' and not last_is_list)
)
):
if self.__is_mixed_dot or not last_is_list:
i += 1
idx = span(key, i)
keys.append(key[i: idx])
i = idx
last_is_list = False
else:
raise ValueError(
f"invalid format key '{full_keys}', invalid char at position {i + pos}")
Expand All @@ -90,7 +102,7 @@ def split_key(self, key):
# reduce + filter are a hight cost so do manualy with for loop

# optimize by split with string func
if self.__is_mixed:
if self.__is_mixed or self.__is_mixed_dot:
return self.mixed_split(key)
if self.__is_dot:
length = 1
Expand Down Expand Up @@ -133,7 +145,7 @@ def set_type(self, dtc, key, value, full_keys, prev=None, last=False):
return key

def get_next_type(self, key):
if self.__is_mixed:
if self.__is_mixed or self.__is_mixed_dot:
return [] if isinstance(key, int) else {}
return [] if key.isdigit() else {}

Expand Down
Loading

0 comments on commit 6db977d

Please sign in to comment.