Completed
Push — master ( ea8775...b21323 )
by Fabio
01:31
created

benedict.dicts.io.IODict.to_query_string()   A

Complexity

Conditions 1

Size

Total Lines 7
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 2
dl 0
loc 7
rs 10
c 0
b 0
f 0
cc 1
nop 2
1
# -*- coding: utf-8 -*-
2
3
from benedict.utils import io_util
4
5
from six import string_types, text_type
6
7
8
class IODict(dict):
9
10
    def __init__(self, *args, **kwargs):
11
        """
12
        Constructs a new instance.
13
        """
14
        # if first argument is data-string, url or filepath try to decode it.
15
        # use 'format' kwarg to specify the decoder to use, default 'json'.
16
        if len(args) and isinstance(args[0], string_types):
17
            d = IODict._decode_init(args[0], *args, **kwargs)
18
            super(IODict, self).__init__(d)
19
            return
20
        super(IODict, self).__init__(*args, **kwargs)
21
22
    @staticmethod
23
    def _decode_init(s, *args, **kwargs):
24
        format = kwargs.pop('format', 'json').lower()
25
        if format in ['b64', 'base64']:
26
            kwargs.setdefault('subformat', 'json')
27
        # decode data-string and initialize with dict data.
28
        d = IODict._decode(s, format, **kwargs)
29
        if isinstance(d, dict):
30
            return d
31
        raise ValueError('Invalid string data input.')
32
33
    @staticmethod
34
    def _decode(s, format, **kwargs):
35
        d = None
36
        try:
37
            content = io_util.read_content(s)
38
            # decode content using the given format
39
            data = io_util.decode(content, format, **kwargs)
40
            if isinstance(data, dict):
41
                d = data
42
            elif isinstance(data, list):
43
                # force list to dict
44
                d = { 'values': data }
45
            else:
46
                raise ValueError(
47
                    'Invalid data type: {}, expected dict or list.'.format(type(data)))
48
        except Exception as e:
49
            raise ValueError(
50
                'Invalid data or url or filepath input argument: {}\n{}'.format(s, text_type(e)))
51
        return d
52
53
    @staticmethod
54
    def _encode(d, format, **kwargs):
55
        filepath = kwargs.pop('filepath', None)
56
        s = io_util.encode(d, format, **kwargs)
57
        if filepath:
58
            io_util.write_file(filepath, s)
59
        return s
60
61
    @classmethod
62
    def from_base64(cls, s, subformat='json', encoding='utf-8', **kwargs):
63
        """
64
        Load and decode Base64 data from url, filepath or data-string.
65
        Data is decoded according to subformat and encoding.
66
        Decoder specific options can be passed using kwargs.
67
        Return a new dict instance. A ValueError is raised in case of failure.
68
        """
69
        kwargs['subformat'] = subformat
70
        kwargs['encoding'] = encoding
71
        return cls(IODict._decode(s, 'base64', **kwargs))
72
73
    @classmethod
74
    def from_csv(cls, s, columns=None, columns_row=True, **kwargs):
75
        """
76
        Load and decode CSV data from url, filepath or data-string.
77
        Decoder specific options can be passed using kwargs: https://docs.python.org/3/library/csv.html
78
        Return a new dict instance. A ValueError is raised in case of failure.
79
        """
80
        kwargs['columns'] = columns
81
        kwargs['columns_row'] = columns_row
82
        return cls(IODict._decode(s, 'csv', **kwargs))
83
84
    @classmethod
85
    def from_json(cls, s, **kwargs):
86
        """
87
        Load and decode JSON data from url, filepath or data-string.
88
        Decoder specific options can be passed using kwargs: https://docs.python.org/3/library/json.html
89
        Return a new dict instance. A ValueError is raised in case of failure.
90
        """
91
        return cls(IODict._decode(s, 'json', **kwargs))
92
93
    @classmethod
94
    def from_query_string(cls, s, **kwargs):
95
        """
96
        Load and decode query-string from url, filepath or data-string.
97
        Return a new dict instance. A ValueError is raised in case of failure.
98
        """
99
        return cls(IODict._decode(s, 'query_string', **kwargs))
100
101
    @classmethod
102
    def from_toml(cls, s, **kwargs):
103
        """
104
        Load and decode TOML data from url, filepath or data-string.
105
        Decoder specific options can be passed using kwargs: https://pypi.org/project/toml/
106
        Return a new dict instance. A ValueError is raised in case of failure.
107
        """
108
        return cls(IODict._decode(s, 'toml', **kwargs))
109
110
    @classmethod
111
    def from_xml(cls, s, **kwargs):
112
        """
113
        Load and decode XML data from url, filepath or data-string.
114
        Decoder specific options can be passed using kwargs: https://github.com/martinblech/xmltodict
115
        Return a new dict instance. A ValueError is raised in case of failure.
116
        """
117
        return cls(IODict._decode(s, 'xml', **kwargs))
118
119
    @classmethod
120
    def from_yaml(cls, s, **kwargs):
121
        """
122
        Load and decode YAML data from url, filepath or data-string.
123
        Decoder specific options can be passed using kwargs: https://pyyaml.org/wiki/PyYAMLDocumentation
124
        Return a new dict instance. A ValueError is raised in case of failure.
125
        """
126
        return cls(IODict._decode(s, 'yaml', **kwargs))
127
128
    def to_base64(self, subformat='json', encoding='utf-8', **kwargs):
129
        """
130
        Encode the current dict instance in Base64 format using the given subformat and encoding.
131
        Encoder specific options can be passed using kwargs.
132
        Return the encoded string and optionally save it at the specified 'filepath'.
133
        A ValueError is raised in case of failure.
134
        """
135
        kwargs['subformat'] = subformat
136
        kwargs['encoding'] = encoding
137
        return IODict._encode(self, 'base64', **kwargs)
138
139
    def to_csv(self, key='values', columns=None, columns_row=True, **kwargs):
140
        """
141
        Encode the current dict instance in CSV format.
142
        Encoder specific options can be passed using kwargs: https://docs.python.org/3/library/csv.html
143
        Return the encoded string and optionally save it at the specified 'filepath'.
144
        A ValueError is raised in case of failure.
145
        """
146
        kwargs['columns'] = columns
147
        kwargs['columns_row'] = columns_row
148
        return IODict._encode(self[key], 'csv', **kwargs)
149
150
    def to_json(self, **kwargs):
151
        """
152
        Encode the current dict instance in JSON format.
153
        Encoder specific options can be passed using kwargs: https://docs.python.org/3/library/json.html
154
        Return the encoded string and optionally save it at the specified 'filepath'.
155
        A ValueError is raised in case of failure.
156
        """
157
        return IODict._encode(self, 'json', **kwargs)
158
159
    def to_query_string(self, **kwargs):
160
        """
161
        Encode the current dict instance in query-string format.
162
        Return the encoded string and optionally save it at the specified 'filepath'.
163
        A ValueError is raised in case of failure.
164
        """
165
        return IODict._encode(self, 'query_string', **kwargs)
166
167
    def to_toml(self, **kwargs):
168
        """
169
        Encode the current dict instance in TOML format.
170
        Encoder specific options can be passed using kwargs: https://pypi.org/project/toml/
171
        Return the encoded string and optionally save it at the specified 'filepath'.
172
        A ValueError is raised in case of failure.
173
        """
174
        return IODict._encode(self, 'toml', **kwargs)
175
176
    def to_xml(self, **kwargs):
177
        """
178
        Encode the current dict instance in XML format.
179
        Encoder specific options can be passed using kwargs: https://github.com/martinblech/xmltodict
180
        Return the encoded string and optionally save it at the specified 'filepath'.
181
        A ValueError is raised in case of failure.
182
        """
183
        return IODict._encode(self, 'xml', **kwargs)
184
185
    def to_yaml(self, **kwargs):
186
        """
187
        Encode the current dict instance in YAML format.
188
        Encoder specific options can be passed using kwargs: https://pyyaml.org/wiki/PyYAMLDocumentation
189
        Return the encoded string and optionally save it at the specified 'filepath'.
190
        A ValueError is raised in case of failure.
191
        """
192
        return IODict._encode(self, 'yaml', **kwargs)
193