python-benedict/benedict/dicts/io/io_dict.py

244 lines
9.4 KiB
Python
Raw Normal View History

2019-09-10 14:58:26 +00:00
# -*- coding: utf-8 -*-
from benedict.dicts.base import BaseDict
from benedict.dicts.io import io_util
from benedict.utils import type_util
2019-09-10 14:58:26 +00:00
class IODict(BaseDict):
2019-09-10 14:58:26 +00:00
def __init__(self, *args, **kwargs):
2019-12-12 17:24:16 +00:00
"""
Constructs a new instance.
"""
2020-01-25 11:08:24 +00:00
# if first argument is data-string, url or filepath try to decode it.
# use 'format' kwarg to specify the decoder to use, default 'json'.
if len(args) == 1 and type_util.is_string(args[0]):
d = IODict._decode_init(args[0], **kwargs)
2020-01-25 11:08:24 +00:00
super(IODict, self).__init__(d)
return
super(IODict, self).__init__(*args, **kwargs)
@staticmethod
def _decode_init(s, **kwargs):
autodetected_format = io_util.autodetect_format(s)
default_format = autodetected_format or 'json'
format = kwargs.pop('format', default_format).lower()
2020-01-25 11:08:24 +00:00
if format in ['b64', 'base64']:
kwargs.setdefault('subformat', 'json')
# decode data-string and initialize with dict data.
2020-08-12 10:47:43 +00:00
return IODict._decode(s, format, **kwargs)
2019-09-10 14:58:26 +00:00
@staticmethod
def _decode(s, format, **kwargs):
2019-09-10 14:58:26 +00:00
try:
2019-10-03 16:42:44 +00:00
content = io_util.read_content(s)
# decode content using the given format
data = io_util.decode(content, format, **kwargs)
if type_util.is_dict(data):
return data
elif type_util.is_list(data):
2019-09-17 09:50:06 +00:00
# force list to dict
2020-02-04 10:29:00 +00:00
return {'values': data}
2019-09-17 09:50:06 +00:00
else:
raise ValueError(
2020-02-04 10:29:00 +00:00
'Invalid data type: {}, expected dict or list.'.format(
type(data)))
2019-09-10 14:58:26 +00:00
except Exception as e:
raise ValueError(
2020-02-04 10:29:00 +00:00
'Invalid data or url or filepath argument: {}\n{}'.format(
s, e))
2019-09-10 14:58:26 +00:00
@staticmethod
def _encode(d, format, **kwargs):
filepath = kwargs.pop('filepath', None)
s = io_util.encode(d, format, **kwargs)
2019-09-10 14:58:26 +00:00
if filepath:
io_util.write_file(filepath, s)
return s
@classmethod
def from_base64(cls, s, subformat='json', encoding='utf-8', **kwargs):
2019-12-12 17:24:16 +00:00
"""
Load and decode Base64 data from url, filepath or data-string.
Data is decoded according to subformat and encoding.
Decoder specific options can be passed using kwargs.
Return a new dict instance. A ValueError is raised in case of failure.
"""
kwargs['subformat'] = subformat
kwargs['encoding'] = encoding
return cls(s, format='base64', **kwargs)
2019-09-10 14:58:26 +00:00
@classmethod
def from_csv(cls, s, columns=None, columns_row=True, **kwargs):
2019-12-12 17:24:16 +00:00
"""
Load and decode CSV data from url, filepath or data-string.
2020-02-04 10:29:00 +00:00
Decoder specific options can be passed using kwargs:
https://docs.python.org/3/library/csv.html
2019-12-12 17:24:16 +00:00
Return a new dict instance. A ValueError is raised in case of failure.
"""
kwargs['columns'] = columns
kwargs['columns_row'] = columns_row
return cls(s, format='csv', **kwargs)
2019-10-03 16:45:22 +00:00
@classmethod
2020-09-09 10:22:56 +00:00
def from_json(cls, s, **kwargs):
"""
2020-09-09 10:22:56 +00:00
Load and decode JSON data from url, filepath or data-string.
Decoder specific options can be passed using kwargs:
2020-09-09 10:22:56 +00:00
https://docs.python.org/3/library/json.html
Return a new dict instance. A ValueError is raised in case of failure.
"""
2020-09-09 10:22:56 +00:00
return cls(s, format='json', **kwargs)
@classmethod
2020-09-09 10:22:56 +00:00
def from_pickle(cls, s, **kwargs):
2019-12-12 17:24:16 +00:00
"""
2020-09-09 10:22:56 +00:00
Load and decode a pickle encoded in Base64 format data from url, filepath or data-string.
2020-02-04 10:29:00 +00:00
Decoder specific options can be passed using kwargs:
2020-09-09 10:22:56 +00:00
https://docs.python.org/3/library/pickle.html
2019-12-12 17:24:16 +00:00
Return a new dict instance. A ValueError is raised in case of failure.
"""
2020-09-09 10:22:56 +00:00
return cls(s, format='pickle', **kwargs)
2019-09-10 14:58:26 +00:00
2020-09-09 14:45:39 +00:00
@classmethod
def from_plist(cls, s, **kwargs):
"""
Load and decode p-list data from url, filepath or data-string.
Decoder specific options can be passed using kwargs:
https://docs.python.org/3/library/plistlib.html
Return a new dict instance. A ValueError is raised in case of failure.
"""
return cls(s, format='plist', **kwargs)
@classmethod
def from_query_string(cls, s, **kwargs):
2019-12-12 17:24:16 +00:00
"""
Load and decode query-string from url, filepath or data-string.
Return a new dict instance. A ValueError is raised in case of failure.
"""
return cls(s, format='query_string', **kwargs)
2019-10-14 12:47:11 +00:00
@classmethod
def from_toml(cls, s, **kwargs):
2019-12-12 17:24:16 +00:00
"""
Load and decode TOML data from url, filepath or data-string.
2020-02-04 10:29:00 +00:00
Decoder specific options can be passed using kwargs:
https://pypi.org/project/toml/
2019-12-12 17:24:16 +00:00
Return a new dict instance. A ValueError is raised in case of failure.
"""
return cls(s, format='toml', **kwargs)
2019-09-20 14:21:04 +00:00
@classmethod
def from_xml(cls, s, **kwargs):
2019-12-12 17:24:16 +00:00
"""
Load and decode XML data from url, filepath or data-string.
2020-02-04 10:29:00 +00:00
Decoder specific options can be passed using kwargs:
https://github.com/martinblech/xmltodict
2019-12-12 17:24:16 +00:00
Return a new dict instance. A ValueError is raised in case of failure.
"""
return cls(s, format='xml', **kwargs)
2019-09-23 12:13:52 +00:00
@classmethod
def from_yaml(cls, s, **kwargs):
2019-12-12 17:24:16 +00:00
"""
Load and decode YAML data from url, filepath or data-string.
2020-02-04 10:29:00 +00:00
Decoder specific options can be passed using kwargs:
https://pyyaml.org/wiki/PyYAMLDocumentation
2019-12-12 17:24:16 +00:00
Return a new dict instance. A ValueError is raised in case of failure.
"""
return cls(s, format='yaml', **kwargs)
2019-09-17 09:50:06 +00:00
def to_base64(self, subformat='json', encoding='utf-8', **kwargs):
2019-12-12 17:24:16 +00:00
"""
2020-02-04 10:29:00 +00:00
Encode the current dict instance in Base64 format
using the given subformat and encoding.
2019-12-12 17:24:16 +00:00
Encoder specific options can be passed using kwargs.
2020-02-04 10:29:00 +00:00
Return the encoded string and optionally save it at 'filepath'.
2019-12-12 17:24:16 +00:00
A ValueError is raised in case of failure.
"""
kwargs['subformat'] = subformat
2019-10-29 15:22:24 +00:00
kwargs['encoding'] = encoding
return self._encode(self.dict(), 'base64', **kwargs)
def to_csv(self, key='values', columns=None, columns_row=True, **kwargs):
2019-12-12 17:24:16 +00:00
"""
Encode a list of dicts in the current dict instance in CSV format.
2020-02-04 10:29:00 +00:00
Encoder specific options can be passed using kwargs:
https://docs.python.org/3/library/csv.html
Return the encoded string and optionally save it at 'filepath'.
2019-12-12 17:24:16 +00:00
A ValueError is raised in case of failure.
"""
kwargs['columns'] = columns
kwargs['columns_row'] = columns_row
return self._encode(self.dict()[key], 'csv', **kwargs)
2020-09-09 10:22:56 +00:00
def to_json(self, **kwargs):
"""
2020-09-09 10:22:56 +00:00
Encode the current dict instance in JSON format.
Encoder specific options can be passed using kwargs:
2020-09-09 10:22:56 +00:00
https://docs.python.org/3/library/json.html
Return the encoded string and optionally save it at 'filepath'.
A ValueError is raised in case of failure.
"""
return self._encode(self.dict(), 'json', **kwargs)
2020-09-09 10:22:56 +00:00
def to_pickle(self, **kwargs):
2019-12-12 17:24:16 +00:00
"""
2020-09-09 10:22:56 +00:00
Encode the current dict instance as pickle (encoded in Base64).
The pickle protocol used by default is 2.
2020-02-04 10:29:00 +00:00
Encoder specific options can be passed using kwargs:
2020-09-09 10:22:56 +00:00
https://docs.python.org/3/library/pickle.html
2020-02-04 10:29:00 +00:00
Return the encoded string and optionally save it at 'filepath'.
2019-12-12 17:24:16 +00:00
A ValueError is raised in case of failure.
"""
return self._encode(self.dict(), 'pickle', **kwargs)
2020-09-09 14:45:39 +00:00
def to_plist(self, **kwargs):
"""
Encode the current dict instance as p-list.
Encoder specific options can be passed using kwargs:
https://docs.python.org/3/library/plistlib.html
Return the encoded string and optionally save it at 'filepath'.
A ValueError is raised in case of failure.
"""
return self._encode(self.dict(), 'plist', **kwargs)
2020-09-09 14:45:39 +00:00
def to_query_string(self, **kwargs):
2019-12-12 17:24:16 +00:00
"""
Encode the current dict instance in query-string format.
2020-02-04 10:29:00 +00:00
Return the encoded string and optionally save it at 'filepath'.
2019-12-12 17:24:16 +00:00
A ValueError is raised in case of failure.
"""
return self._encode(self.dict(), 'query_string', **kwargs)
def to_toml(self, **kwargs):
2019-12-12 17:24:16 +00:00
"""
Encode the current dict instance in TOML format.
2020-02-04 10:29:00 +00:00
Encoder specific options can be passed using kwargs:
https://pypi.org/project/toml/
Return the encoded string and optionally save it at 'filepath'.
2019-12-12 17:24:16 +00:00
A ValueError is raised in case of failure.
"""
return self._encode(self.dict(), 'toml', **kwargs)
def to_xml(self, **kwargs):
2019-12-12 17:24:16 +00:00
"""
Encode the current dict instance in XML format.
2020-02-04 10:29:00 +00:00
Encoder specific options can be passed using kwargs:
https://github.com/martinblech/xmltodict
Return the encoded string and optionally save it at 'filepath'.
2019-12-12 17:24:16 +00:00
A ValueError is raised in case of failure.
"""
return self._encode(self.dict(), 'xml', **kwargs)
def to_yaml(self, **kwargs):
2019-12-12 17:24:16 +00:00
"""
Encode the current dict instance in YAML format.
2020-02-04 10:29:00 +00:00
Encoder specific options can be passed using kwargs:
https://pyyaml.org/wiki/PyYAMLDocumentation
Return the encoded string and optionally save it at 'filepath'.
2019-12-12 17:24:16 +00:00
A ValueError is raised in case of failure.
"""
return self._encode(self.dict(), 'yaml', **kwargs)