Skip to content

Instantly share code, notes, and snippets.

@Lewiscowles1986
Last active May 7, 2018 05:22
Show Gist options
  • Save Lewiscowles1986/380425897b456a3f0d5b to your computer and use it in GitHub Desktop.
Save Lewiscowles1986/380425897b456a3f0d5b to your computer and use it in GitHub Desktop.
Python Dict / Multi-Dict to allow semantic structural nesting of formdata
# FormData / Flat-to-Structured Dictionary Accessories For Python
# Copyright (C) 2015 Lewis Cowles
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
def _build_struct(components, struct):
# Loop over all but last component calling setdefault to set and return
# the value of the added element as struct (does what recursion achieved)
# using only two lines.
for comp in components:
struct = struct.setdefault(comp or len(struct), {})
# return address of last object created or retrieved
return struct
def _parse_to_dict_val(key, value, struct):
components = [
node.replace(']', '') for node in key.split('[')
]
struct = _build_struct(components[:-1], struct)
struct[components[-1] or len(struct)] = value
return struct
def parse_to_dict_vals(assignments):
dictout = {}
if isinstance(assignments, dict):
assignments = assignments.items()
for key, value in assignments:
_parse_to_dict_val(key, value, dictout)
return dictout
if __name__ == "__main__":
import unittest
import json
def getRoninStarlord():
return parse_to_dict_vals([
("name[]", "starlord"),
("name[accusor]", "ronin")
])
def getGoodies():
return parse_to_dict_vals([
("goodies[starlord][age]", "29"),
("goodies[starlord][planet]", "Earth"),
("goodies[Yondu][species]", "Centaurian"),
("goodies[Yondu][abilities][]", "Magic Arrow"),
("goodies[Yondu][abilities][]", "Not Eating starlord")
])
def miniJSON(v):
return json.dumps(v, sort_keys=True, separators=(',', ':'))
class InternalTest(unittest.TestCase):
def testStarlordName(self):
self.assertEqual(
getRoninStarlord()['name'][0],
'starlord')
def testAccusorName(self):
self.assertEqual(
getRoninStarlord()['name']['accusor'],
'ronin')
def testGoodiesStarlordAge(self):
self.assertEqual(
getGoodies()['goodies']['starlord']['age'],
'29')
def testSimpleRootOnly(self):
self.assertEqual(
miniJSON(parse_to_dict_vals({"name": "bob"})),
'{"name":"bob"}')
def testYonduInGoodiesHasAbilities(self):
self.assertTrue(
'abilities' in getGoodies()['goodies']['Yondu'])
def testYonduInGoodiesHasTwoAbilities(self):
self.assertTrue(
len(getGoodies()['goodies']['Yondu']['abilities']),
2)
def testCanParseDeepDoubleAuto(self):
self.assertEqual(
miniJSON(
parse_to_dict_vals(
{"root[subnode][attribute][][]": "value"})
),
'{"root":{"subnode":{"attribute":{"0":{"0":"value"}}}}}')
def testCanParseDeepAutoWithNamedNode(self):
self.assertEqual(
miniJSON(
parse_to_dict_vals(
{"root[subnode][attribute][][me]": "value"})
),
'{"root":{"subnode":{"attribute":{"0":{"me":"value"}}}}}')
unittest.main()
@ThiefMaster
Copy link

You should really follow PEP8.

@Lewiscowles1986
Copy link
Author

I've put it on my todo ๐Ÿ˜‰ ๐Ÿ‘

@Lewiscowles1986
Copy link
Author

Updated to PEP8 (it's probably junk code anyway)

@Lewiscowles1986
Copy link
Author

Added doctests

@Lewiscowles1986
Copy link
Author

Switched out dict for list of tuple, although kept dict as input support so that duplicate names are not destroyed.

@Lewiscowles1986
Copy link
Author

Should probably be converted to multi-dict, right now seems to have parity with PHP HTTP form-data handling

@Lewiscowles1986
Copy link
Author

wget {gist-raw-url}
pep8 FDAcc.py 
python3 FDAcc.py

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment