Last active
November 3, 2021 21:10
-
-
Save kurtbrose/555f3b4e3c64182c39f9c31f0203c8e4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import re | |
def stripe_form(data): | |
"""perform a stripe nested-data form-encoding""" | |
form = [] | |
def _form2(pre, val): | |
if type(val) not in (list, dict): | |
form.append((pre, val)) | |
return | |
if type(val) is list: | |
items = enumerate(val) | |
elif type(val) is dict: | |
items = val.items() | |
for k, v in items: | |
_form2(pre + f"[{k}]", v) | |
for k, v in data.items(): | |
_form2(k, v) | |
return form | |
def stripe_deform(form): | |
"""perform a stripe nested-data form-decoding""" | |
# invariant: last level before values is always an object | |
# invariant: cannot double-nest arrays, no [[]] | |
def _check_index(index, array): | |
assert not (index > len(array)), "index more than 1 past end of array" | |
assert not (index < len(array) - 1), "out of order array values" | |
def _assign_into(parent, keys, val): | |
assert keys | |
key = keys[0] | |
if len(keys) == 1: # stopping case | |
assert type(parent) is dict, "invalid array of non-objects" | |
assert key not in parent, "two values for same path" | |
parent[key] = val | |
return | |
if type(key) is int: # list case | |
assert type(keys[1]) is str, "invalid array of arrays" | |
if key == -1: # implicit index | |
if not parent or keys[1] in parent[-1]: | |
parent.append({}) | |
else: # explicit index | |
if key == len(parent): | |
parent.append({}) | |
else: | |
_check_index(key, parent) | |
key = -1 | |
elif key not in parent: | |
parent[key] = [] if type(keys[1]) is int else {} | |
_assign_into(parent[key], keys[1:], val) | |
def _str_key_to_key(key): | |
if key == '': | |
return -1 | |
if key.isdigit(): | |
return int(key) | |
return key | |
def _form_key_to_keys(form_key): | |
if '[' not in form_key: | |
return form_key | |
pre, key = form_key.split('[', 1) | |
key = '[' + key | |
keys = [pre] + re.findall(r'\[(\w+)?\]', key) | |
return [_str_key_to_key(key) for key in keys] | |
if type(form) is dict: | |
form = form.items() | |
data = {} | |
for key, val in form: | |
_assign_into(data, _form_key_to_keys(key), val) | |
return data | |
def test(): | |
messages = [ | |
{'array_of_obj': [{'a': 1}, {'a': 1}]}, | |
{'nested': {'b': {'b': 2}}}, | |
{'nested_arr': {'c': [{'c': 3}]}}, | |
] | |
for message in messages: | |
assert stripe_deform(stripe_form(message)) == message, message | |
if __name__ == "__main__": | |
try: | |
test() | |
except: | |
import pdb; pdb.post_mortem() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment