Passed
Pull Request — master (#40)
by
unknown
02:52
created

benedict.dicts.io.io_dict.IODict.from_ini()   A

Complexity

Conditions 1

Size

Total Lines 8
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 3
dl 0
loc 8
rs 10
c 0
b 0
f 0
cc 1
nop 3
1
# -*- coding: utf-8 -*-
2
3
from benedict.dicts.base import BaseDict
4
from benedict.dicts.io import io_util
5
from benedict.utils import type_util
6
7
8
class IODict(BaseDict):
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) == 1 and type_util.is_string(args[0]):
17
            d = IODict._decode_init(args[0], **kwargs)
18
            super(IODict, self).__init__(d)
19
            return
20
        super(IODict, self).__init__(*args, **kwargs)
21
22
    @staticmethod
23
    def _decode_init(s, **kwargs):
24
        autodetected_format = io_util.autodetect_format(s)
25
        default_format = autodetected_format or 'json'
26
        format = kwargs.pop('format', default_format).lower()
27
        if format in ['b64', 'base64']:
28
            kwargs.setdefault('subformat', 'json')
29
        # decode data-string and initialize with dict data.
30
        return IODict._decode(s, format, **kwargs)
31
32
    @staticmethod
33
    def _decode(s, format, **kwargs):
34
        try:
35
            content = io_util.read_content(s)
36
            # decode content using the given format
37
            data = io_util.decode(content, format, **kwargs)
38
            if type_util.is_dict(data):
39
                return data
40
            elif type_util.is_list(data):
41
                # force list to dict
42
                return {
43
                    'values': data
44
                }
45
            else:
46
                raise ValueError(
47
                        'Invalid data type: {}, expected dict or list.'.format(
48
                                type(data)))
49
        except Exception as e:
50
            raise ValueError(
51
                    'Invalid data or url or filepath argument: {}\n{}'.format(
52
                            s, e))
53
54
    @staticmethod
55
    def _encode(d, format, **kwargs):
56
        filepath = kwargs.pop('filepath', None)
57
        s = io_util.encode(d, format, **kwargs)
58
        if filepath:
59
            io_util.write_file(filepath, s)
60
        return s
61
62
    @classmethod
63
    def from_base64(cls, s, subformat='json', encoding='utf-8', **kwargs):
64
        """
65
        Load and decode Base64 data from url, filepath or data-string.
66
        Data is decoded according to subformat and encoding.
67
        Decoder specific options can be passed using kwargs.
68
        Return a new dict instance. A ValueError is raised in case of failure.
69
        """
70
        kwargs['subformat'] = subformat
71
        kwargs['encoding'] = encoding
72
        return cls(s, format='base64', **kwargs)
73
74
    @classmethod
75
    def from_csv(cls, s, columns=None, columns_row=True, **kwargs):
76
        """
77
        Load and decode CSV data from url, filepath or data-string.
78
        Decoder specific options can be passed using kwargs:
79
        https://docs.python.org/3/library/csv.html
80
        Return a new dict instance. A ValueError is raised in case of failure.
81
        """
82
        kwargs['columns'] = columns
83
        kwargs['columns_row'] = columns_row
84
        return cls(s, format='csv', **kwargs)
85
86
    @classmethod
87
    def from_ini(cls, s, **kwargs):
88
        """
89
        Load and decode .ini data from url, filepath or data-string.
90
        Decoder specific options can be passed using kwargs.
91
        Return a new dict instance. A ValueError is raised in case of failure.
92
        """
93
        return cls(s, format='ini', **kwargs)
94
95
    @classmethod
96
    def from_json(cls, s, **kwargs):
97
        """
98
        Load and decode JSON data from url, filepath or data-string.
99
        Decoder specific options can be passed using kwargs:
100
        https://docs.python.org/3/library/json.html
101
        Return a new dict instance. A ValueError is raised in case of failure.
102
        """
103
        return cls(s, format='json', **kwargs)
104
105
    @classmethod
106
    def from_pickle(cls, s, **kwargs):
107
        """
108
        Load and decode a pickle encoded in Base64 format data from url, filepath or data-string.
109
        Decoder specific options can be passed using kwargs:
110
        https://docs.python.org/3/library/pickle.html
111
        Return a new dict instance. A ValueError is raised in case of failure.
112
        """
113
        return cls(s, format='pickle', **kwargs)
114
115
    @classmethod
116
    def from_plist(cls, s, **kwargs):
117
        """
118
        Load and decode p-list data from url, filepath or data-string.
119
        Decoder specific options can be passed using kwargs:
120
        https://docs.python.org/3/library/plistlib.html
121
        Return a new dict instance. A ValueError is raised in case of failure.
122
        """
123
        return cls(s, format='plist', **kwargs)
124
125
    @classmethod
126
    def from_query_string(cls, s, **kwargs):
127
        """
128
        Load and decode query-string from url, filepath or data-string.
129
        Return a new dict instance. A ValueError is raised in case of failure.
130
        """
131
        return cls(s, format='query_string', **kwargs)
132
133
    @classmethod
134
    def from_toml(cls, s, **kwargs):
135
        """
136
        Load and decode TOML data from url, filepath or data-string.
137
        Decoder specific options can be passed using kwargs:
138
        https://pypi.org/project/toml/
139
        Return a new dict instance. A ValueError is raised in case of failure.
140
        """
141
        return cls(s, format='toml', **kwargs)
142
143
    @classmethod
144
    def from_xml(cls, s, **kwargs):
145
        """
146
        Load and decode XML data from url, filepath or data-string.
147
        Decoder specific options can be passed using kwargs:
148
        https://github.com/martinblech/xmltodict
149
        Return a new dict instance. A ValueError is raised in case of failure.
150
        """
151
        return cls(s, format='xml', **kwargs)
152
153
    @classmethod
154
    def from_yaml(cls, s, **kwargs):
155
        """
156
        Load and decode YAML data from url, filepath or data-string.
157
        Decoder specific options can be passed using kwargs:
158
        https://pyyaml.org/wiki/PyYAMLDocumentation
159
        Return a new dict instance. A ValueError is raised in case of failure.
160
        """
161
        return cls(s, format='yaml', **kwargs)
162
163
    def to_base64(self, subformat='json', encoding='utf-8', **kwargs):
164
        """
165
        Encode the current dict instance in Base64 format
166
        using the given subformat and encoding.
167
        Encoder specific options can be passed using kwargs.
168
        Return the encoded string and optionally save it at 'filepath'.
169
        A ValueError is raised in case of failure.
170
        """
171
        kwargs['subformat'] = subformat
172
        kwargs['encoding'] = encoding
173
        return self._encode(self, 'base64', **kwargs)
174
175
    def to_csv(self, key='values', columns=None, columns_row=True, **kwargs):
176
        """
177
        Encode the current dict instance in CSV format.
178
        Encoder specific options can be passed using kwargs:
179
        https://docs.python.org/3/library/csv.html
180
        Return the encoded string and optionally save it at 'filepath'.
181
        A ValueError is raised in case of failure.
182
        """
183
        kwargs['columns'] = columns
184
        kwargs['columns_row'] = columns_row
185
        return self._encode(self[key], 'csv', **kwargs)
186
187
    def to_json(self, **kwargs):
188
        """
189
        Encode the current dict instance in JSON format.
190
        Encoder specific options can be passed using kwargs:
191
        https://docs.python.org/3/library/json.html
192
        Return the encoded string and optionally save it at 'filepath'.
193
        A ValueError is raised in case of failure.
194
        """
195
        return self._encode(self, 'json', **kwargs)
196
197
    def to_ini(self, **kwargs):
198
        """
199
        Encode the current dict instance in INI format.
200
        Encoder specific options can be passed using kwargs: (method 'write')
201
        https://docs.python.org/3/library/configparser.html
202
        Return the encoded string and optionally save it at 'filepath'.
203
        A ValueError is raised in case of failure.
204
        """
205
        return self._encode(self, 'ini', **kwargs)
206
207
    def to_pickle(self, **kwargs):
208
        """
209
        Encode the current dict instance as pickle (encoded in Base64).
210
        The pickle protocol used by default is 2.
211
        Encoder specific options can be passed using kwargs:
212
        https://docs.python.org/3/library/pickle.html
213
        Return the encoded string and optionally save it at 'filepath'.
214
        A ValueError is raised in case of failure.
215
        """
216
        return self._encode(self, 'pickle', **kwargs)
217
218
    def to_plist(self, **kwargs):
219
        """
220
        Encode the current dict instance as p-list.
221
        Encoder specific options can be passed using kwargs:
222
        https://docs.python.org/3/library/plistlib.html
223
        Return the encoded string and optionally save it at 'filepath'.
224
        A ValueError is raised in case of failure.
225
        """
226
        return self._encode(self, 'plist', **kwargs)
227
228
    def to_query_string(self, **kwargs):
229
        """
230
        Encode the current dict instance in query-string format.
231
        Return the encoded string and optionally save it at 'filepath'.
232
        A ValueError is raised in case of failure.
233
        """
234
        return self._encode(self, 'query_string', **kwargs)
235
236
    def to_toml(self, **kwargs):
237
        """
238
        Encode the current dict instance in TOML format.
239
        Encoder specific options can be passed using kwargs:
240
        https://pypi.org/project/toml/
241
        Return the encoded string and optionally save it at 'filepath'.
242
        A ValueError is raised in case of failure.
243
        """
244
        return self._encode(self, 'toml', **kwargs)
245
246
    def to_xml(self, **kwargs):
247
        """
248
        Encode the current dict instance in XML format.
249
        Encoder specific options can be passed using kwargs:
250
        https://github.com/martinblech/xmltodict
251
        Return the encoded string and optionally save it at 'filepath'.
252
        A ValueError is raised in case of failure.
253
        """
254
        return self._encode(self, 'xml', **kwargs)
255
256
    def to_yaml(self, **kwargs):
257
        """
258
        Encode the current dict instance in YAML format.
259
        Encoder specific options can be passed using kwargs:
260
        https://pyyaml.org/wiki/PyYAMLDocumentation
261
        Return the encoded string and optionally save it at 'filepath'.
262
        A ValueError is raised in case of failure.
263
        """
264
        return self._encode(self, 'yaml', **kwargs)
265