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

benedict.serializers.ini   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 72
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 16
eloc 53
dl 0
loc 72
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A INISerializer.__init__() 0 2 1
A INISerializer.encode() 0 8 2
A INISerializer._try_parse() 0 12 4
A INISerializer.decode() 0 11 3
B INISerializer._preprocessed_dict() 0 20 6
1
# -*- coding: utf-8 -*-
2
3
from __future__ import absolute_import
4
5
import io
6
from copy import deepcopy
7
8
from benedict.serializers.abstract import AbstractSerializer
9
10
import configparser
11
12
13
class INISerializer(AbstractSerializer):
14
15
    def __init__(self):
16
        super(INISerializer, self).__init__()
17
18
    @staticmethod
19
    def _try_parse(parser: configparser.ConfigParser, section, key):
20
        try:
21
            return parser.getint(section, key)
22
        except ValueError:
23
            try:
24
                return parser.getfloat(section, key)
25
            except ValueError:
26
                try:
27
                    return parser.getboolean(section, key)
28
                except ValueError:
29
                    return parser.get(section, key)
30
31
    def decode(self, s, **kwargs):
32
        parser = configparser.ConfigParser()
33
        kwargs.setdefault("source", "<string>")
34
        parser.read_string(s, **kwargs)
35
        data = {}
36
        for s in parser.sections():
37
            data[s] = {}
38
            for key, _ in parser.items(s):
39
                data[s][key] = INISerializer._try_parse(parser, s, key)
40
41
        return data
42
43
    def encode(self, d, **kwargs):
44
        parser = configparser.ConfigParser()
45
        processed_dict = self._preprocessed_dict(d, **kwargs)
46
        parser.read_dict(processed_dict)
47
        with io.StringIO() as data:
48
            parser.write(data, **kwargs)
49
            data.seek(0)
50
            return data.getvalue()
51
52
    def _preprocessed_dict(self, d, default_namespace="default"):
53
        sections = {
54
            default_namespace: {}
55
        }
56
        for key, value in d.items():
57
            if isinstance(value, dict):
58
                sections[key] = deepcopy(value)
59
            else:
60
                sections[default_namespace][key] = value
61
62
        # Stringify all the value
63
        for section in sections.values():
64
            for key, val in section.items():
65
                section[key] = str(val)
66
67
        # if the default section is empty, delete it
68
        if len(sections[default_namespace]) == 0:
69
            del sections[default_namespace]
70
71
        return sections
72