Added query-string I/O support.
This commit is contained in:
parent
fc9b2549ea
commit
8334993d96
|
@ -60,6 +60,11 @@ class benedict(IODict, KeypathDict, ParseDict):
|
|||
def from_json(s, **kwargs):
|
||||
return IODict.from_json(s, **kwargs)
|
||||
|
||||
@staticmethod
|
||||
@benediction
|
||||
def from_query_string(s, **kwargs):
|
||||
return IODict.from_query_string(s, **kwargs)
|
||||
|
||||
@staticmethod
|
||||
@benediction
|
||||
def from_toml(s, **kwargs):
|
||||
|
|
|
@ -49,31 +49,21 @@ class IODict(dict):
|
|||
|
||||
@staticmethod
|
||||
def _from_any_data_string(s, **kwargs):
|
||||
try:
|
||||
d = IODict.from_base64(s, **kwargs)
|
||||
return d
|
||||
except ValueError:
|
||||
pass
|
||||
try:
|
||||
d = IODict.from_json(s, **kwargs)
|
||||
return d
|
||||
except ValueError:
|
||||
pass
|
||||
try:
|
||||
d = IODict.from_toml(s, **kwargs)
|
||||
return d
|
||||
except ValueError:
|
||||
pass
|
||||
try:
|
||||
d = IODict.from_xml(s, **kwargs)
|
||||
return d
|
||||
except ValueError:
|
||||
pass
|
||||
try:
|
||||
d = IODict.from_yaml(s, **kwargs)
|
||||
return d
|
||||
except ValueError:
|
||||
pass
|
||||
funcs = [
|
||||
IODict.from_base64,
|
||||
IODict.from_json,
|
||||
IODict.from_query_string,
|
||||
IODict.from_toml,
|
||||
IODict.from_xml,
|
||||
IODict.from_yaml,
|
||||
]
|
||||
for f in funcs:
|
||||
try:
|
||||
options = kwargs.copy()
|
||||
d = f(s, **options)
|
||||
return d
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def from_base64(s, format='json', **kwargs):
|
||||
|
@ -86,6 +76,11 @@ class IODict(dict):
|
|||
return IODict._decode(s,
|
||||
decoder=io_util.decode_json, **kwargs)
|
||||
|
||||
@staticmethod
|
||||
def from_query_string(s, **kwargs):
|
||||
return IODict._decode(s,
|
||||
decoder=io_util.decode_query_string, **kwargs)
|
||||
|
||||
@staticmethod
|
||||
def from_toml(s, **kwargs):
|
||||
return IODict._decode(s,
|
||||
|
@ -112,6 +107,11 @@ class IODict(dict):
|
|||
encoder=io_util.encode_json,
|
||||
filepath=filepath, **kwargs)
|
||||
|
||||
def to_query_string(self, filepath=None, **kwargs):
|
||||
return IODict._encode(self,
|
||||
encoder=io_util.encode_query_string,
|
||||
filepath=filepath, **kwargs)
|
||||
|
||||
def to_toml(self, filepath=None, **kwargs):
|
||||
return IODict._encode(self,
|
||||
encoder=io_util.encode_toml,
|
||||
|
|
|
@ -6,6 +6,7 @@ import base64
|
|||
import errno
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import requests
|
||||
import xmltodict
|
||||
import toml
|
||||
|
@ -14,9 +15,13 @@ import yaml
|
|||
try:
|
||||
# python 3
|
||||
from urllib.parse import unquote_plus as urldecode
|
||||
from urllib.parse import urlencode
|
||||
from urllib.parse import parse_qs
|
||||
except ImportError:
|
||||
# python 2
|
||||
from urllib import unquote_plus as urldecode
|
||||
from urllib import urlencode
|
||||
from urlparse import parse_qs
|
||||
|
||||
|
||||
def decode_base64(s, **kwargs):
|
||||
|
@ -48,6 +53,19 @@ def decode_json(s, **kwargs):
|
|||
return data
|
||||
|
||||
|
||||
def decode_query_string(s, **kwargs):
|
||||
flat = kwargs.pop('flat', True)
|
||||
qs_re = r'^(([\w\-\%\+]+\=[\w\-\%\+]*)+([\&]{1})?)+'
|
||||
qs_pattern = re.compile(qs_re)
|
||||
if qs_pattern.match(s):
|
||||
data = parse_qs(s)
|
||||
if flat:
|
||||
data = { key:value[0] for key, value in data.items() }
|
||||
return data
|
||||
else:
|
||||
raise ValueError('Invalid query string: {}'.format(s))
|
||||
|
||||
|
||||
def decode_xml(s, **kwargs):
|
||||
kwargs.setdefault('dict_constructor', dict)
|
||||
data = xmltodict.parse(s, **kwargs)
|
||||
|
@ -89,6 +107,11 @@ def encode_json(d, **kwargs):
|
|||
return data
|
||||
|
||||
|
||||
def encode_query_string(d, **kwargs):
|
||||
data = urlencode(d, **kwargs)
|
||||
return data
|
||||
|
||||
|
||||
def encode_toml(d, **kwargs):
|
||||
data = toml.dumps(d, **kwargs)
|
||||
return data
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
Lorem ipsum consectetur sint id aute officia sed excepteur consectetur labore laboris dolore in labore consequat ut in eu ut deserunt.
|
||||
Elit aliqua velit aliquip voluptate consequat reprehenderit occaecat dolor ut esse aute laboris cillum fugiat esse est laborum.
|
|
@ -0,0 +1 @@
|
|||
ok=1&test=2&page=3&lib=python%20benedict&author=Fabio+Caccamo&author=Fabio%20Caccamo
|
|
@ -483,6 +483,18 @@ class BenedictTestCase(unittest.TestCase):
|
|||
self.assertTrue(isinstance(d, benedict))
|
||||
self.assertEqual(d, { 'a': 1, 'b': 2, 'c': 3, })
|
||||
|
||||
def test_from_query_string_with_valid_data(self):
|
||||
s = 'ok=1&test=2&page=3&lib=python%20benedict&author=Fabio+Caccamo&author=Fabio%20Caccamo'
|
||||
r = { 'ok': '1', 'test': '2', 'page': '3', 'lib':'python benedict', 'author':'Fabio Caccamo' }
|
||||
# static method
|
||||
d = benedict.from_query_string(s)
|
||||
self.assertTrue(isinstance(d, benedict))
|
||||
self.assertEqual(d, r)
|
||||
# constructor
|
||||
d = benedict(s)
|
||||
self.assertTrue(isinstance(d, benedict))
|
||||
self.assertEqual(d, r)
|
||||
|
||||
def test_from_toml(self):
|
||||
j = """
|
||||
a = 1
|
||||
|
|
|
@ -263,7 +263,113 @@ class IODictTestCase(unittest.TestCase):
|
|||
self.assertTrue(d, os.path.isfile(filepath))
|
||||
self.assertEqual(d, IODict.from_json(filepath))
|
||||
|
||||
# YAML
|
||||
# QUERY STRING
|
||||
|
||||
def test_from_query_string_with_valid_data(self):
|
||||
s = 'ok=1&test=2&page=3&lib=python%20benedict&author=Fabio+Caccamo&author=Fabio%20Caccamo'
|
||||
r = { 'ok': '1', 'test': '2', 'page': '3', 'lib':'python benedict', 'author':'Fabio Caccamo' }
|
||||
# static method
|
||||
d = IODict.from_query_string(s)
|
||||
self.assertTrue(isinstance(d, dict))
|
||||
self.assertEqual(d, r)
|
||||
# constructor
|
||||
d = IODict(s)
|
||||
self.assertTrue(isinstance(d, dict))
|
||||
self.assertEqual(d, r)
|
||||
|
||||
def test_from_query_string_with_invalid_data(self):
|
||||
s = 'Lorem ipsum est in ea occaecat nisi officia.'
|
||||
# static method
|
||||
with self.assertRaises(ValueError):
|
||||
IODict.from_query_string(s)
|
||||
# constructor
|
||||
with self.assertRaises(ValueError):
|
||||
IODict(s)
|
||||
|
||||
def test_from_query_string_with_valid_file_valid_content(self):
|
||||
filepath = self.input_path('valid-content.qs')
|
||||
# static method
|
||||
d = IODict.from_query_string(filepath)
|
||||
self.assertTrue(isinstance(d, dict))
|
||||
# constructor
|
||||
d = IODict(filepath)
|
||||
self.assertTrue(isinstance(d, dict))
|
||||
|
||||
def test_from_query_string_with_valid_file_valid_content_invalid_format(self):
|
||||
filepath = self.input_path('valid-content.base64')
|
||||
with self.assertRaises(ValueError):
|
||||
IODict.from_query_string(filepath)
|
||||
filepath = self.input_path('valid-content.json')
|
||||
with self.assertRaises(ValueError):
|
||||
IODict.from_query_string(filepath)
|
||||
filepath = self.input_path('valid-content.toml')
|
||||
with self.assertRaises(ValueError):
|
||||
IODict.from_query_string(filepath)
|
||||
filepath = self.input_path('valid-content.xml')
|
||||
with self.assertRaises(ValueError):
|
||||
IODict.from_query_string(filepath)
|
||||
filepath = self.input_path('valid-content.yml')
|
||||
with self.assertRaises(ValueError):
|
||||
IODict.from_query_string(filepath)
|
||||
|
||||
def test_from_query_string_with_valid_file_invalid_content(self):
|
||||
filepath = self.input_path('invalid-content.qs')
|
||||
# static method
|
||||
with self.assertRaises(ValueError):
|
||||
IODict.from_query_string(filepath)
|
||||
# constructor
|
||||
with self.assertRaises(ValueError):
|
||||
IODict(filepath)
|
||||
|
||||
def test_from_query_string_with_invalid_file(self):
|
||||
filepath = self.input_path('invalid-file.qs')
|
||||
# static method
|
||||
with self.assertRaises(ValueError):
|
||||
IODict.from_query_string(filepath)
|
||||
# constructor
|
||||
with self.assertRaises(ValueError):
|
||||
IODict(filepath)
|
||||
|
||||
# def test_from_query_string_with_valid_url_valid_content(self):
|
||||
# url = 'https://raw.githubusercontent.com/fabiocaccamo/python-benedict/master/tests/input/valid-content.qs'
|
||||
# # static method
|
||||
# d = IODict.from_query_string(url)
|
||||
# self.assertTrue(isinstance(d, dict))
|
||||
# # constructor
|
||||
# d = IODict(url)
|
||||
# self.assertTrue(isinstance(d, dict))
|
||||
|
||||
def test_from_query_string_with_valid_url_invalid_content(self):
|
||||
url = 'https://github.com/fabiocaccamo/python-benedict'
|
||||
# static method
|
||||
with self.assertRaises(ValueError):
|
||||
IODict.from_query_string(url)
|
||||
# constructor
|
||||
with self.assertRaises(ValueError):
|
||||
IODict(url)
|
||||
|
||||
def test_from_query_string_with_invalid_url(self):
|
||||
url = 'https://github.com/fabiocaccamo/python-benedict-invalid'
|
||||
# static method
|
||||
with self.assertRaises(ValueError):
|
||||
IODict.from_query_string(url)
|
||||
# constructor
|
||||
with self.assertRaises(ValueError):
|
||||
IODict(url)
|
||||
|
||||
def test_to_query_string(self):
|
||||
data = { 'ok': '1', 'test': '2', 'page': '3', 'lib':'python benedict', 'author':'Fabio Caccamo' }
|
||||
d = IODict({ 'ok': '1', 'test': '2', 'page': '3', 'lib':'python benedict', 'author':'Fabio Caccamo' })
|
||||
s = d.to_query_string()
|
||||
self.assertEqual(d, IODict.from_query_string(s))
|
||||
|
||||
def test_to_query_string_file(self):
|
||||
d = IODict({ 'ok': '1', 'test': '2', 'page': '3', 'lib':'python benedict', 'author':'Fabio Caccamo' })
|
||||
filepath = self.output_path('test_to_query_string_file.qs')
|
||||
d.to_query_string(filepath=filepath)
|
||||
self.assertTrue(d, os.path.isfile(filepath))
|
||||
self.assertEqual(d, IODict.from_query_string(filepath))
|
||||
|
||||
# TOML
|
||||
|
||||
def test_from_toml_with_valid_data(self):
|
||||
|
|
Loading…
Reference in New Issue