Allow `ini` format to support nested structures.

This commit is contained in:
Fabio Caccamo 2023-05-16 09:24:02 +02:00
parent 9e07e48880
commit 332638df64
2 changed files with 51 additions and 4 deletions

View File

@ -1,8 +1,10 @@
from configparser import DEFAULTSECT as default_section
from configparser import RawConfigParser
from io import StringIO
from json.decoder import JSONDecodeError
from benedict.serializers.abstract import AbstractSerializer
from benedict.serializers.json import JSONSerializer
from benedict.utils import type_util
@ -17,6 +19,7 @@ class INISerializer(AbstractSerializer):
"ini",
],
)
self._json = JSONSerializer()
@staticmethod
def _get_parser(options):
@ -49,9 +52,14 @@ class INISerializer(AbstractSerializer):
for section in parser.sections():
data[section] = {}
for option, _ in parser.items(section):
data[section][option] = self._get_section_option_value(
parser, section, option
)
value = self._get_section_option_value(parser, section, option)
if type_util.is_string(value):
try:
value_decoded = self._json.decode(value)
value = value_decoded
except JSONDecodeError:
pass
data[section][option] = value
return data
def encode(self, d, **kwargs):
@ -63,7 +71,10 @@ class INISerializer(AbstractSerializer):
section = key
parser.add_section(section)
for option_key, option_value in value.items():
parser.set(section, option_key, f"{option_value}")
if type_util.is_collection(option_value):
parser.set(section, option_key, self._json.encode(option_value))
else:
parser.set(section, option_key, option_value)
str_data = StringIO()
parser.write(str_data)
return str_data.getvalue()

View File

@ -0,0 +1,36 @@
import unittest
from benedict import benedict
class github_issue_0284_test_case(unittest.TestCase):
"""
This class describes a github issue 0284 test case.
https://github.com/fabiocaccamo/python-benedict/issues/284
To run this specific test:
- Run python -m unittest tests.github.test_issue_0284
"""
def test_from_ini_returns_str_instead_of_dict(self):
original = benedict(
{
"section1": {
"key1": "value1",
},
"sectionA": {
"keyA": "valueA",
"keyB": "valueB",
"keyC": {
"subkeyC": "subvalueC",
},
},
}
)
readback = benedict.from_ini(original.to_ini())
keypath = "sectionA.keyC"
# print("original vs readback")
# print(original.get(keypath), type(original.get(keypath)))
# print("-- vs --")
# print(readback.get(keypath), type(readback.get(keypath)))
self.assertEqual(original.get(keypath), readback.get(keypath))