osdir.com


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Saving application configuration to the ini file respecting order of sections/options and providing mechanism for (nested) complex objects


zljubisic at gmail.com wrote:

> 1. saving json will result in unordered ini file. It could be solved by
> using OrderedDict that will than with json.dumps be saved to file in the
> same order as options are added to the ordered dict.

dict-s are guaranteed to keep insertion order in Python 3.7, see

https://docs.python.org/dev/whatsnew/3.7.html#summary-release-highlights

> 2. there is a problem with datatime values because json format serialize
> everything to string. I have found the solution on page
> https://gist.github.com/abhinav-upadhyay/5300137, but I dislike the idea
> that datetime is represented as unordered dict. When you have to change
> datetime manually in the ini file by using text editor, you first have to
> sort year,month,day... in order to be sure that you are setting correct
> date.

You're free to pick whatever serialisation you like:

$ cat datetimedecoder_isoformat.py
from datetime import datetime
import json
import re


def dict_to_object(d):
    if d.get("__type__") != "datetime":
        return d
    return datetime(*map(int, re.split("[-T:.]", d["isovalue"])))


def default(obj):
        if isinstance(obj, datetime):
            return {
                '__type__': 'datetime',
                'isovalue': obj.isoformat()
            }
        raise TypeError


original = {'name': 'foo', 'type': 'bar', 'date': datetime.now()}
print("original:", original)

serialized = json.dumps(original, default=default, indent=4)
print("serialized:", serialized)

reloaded = json.loads(serialized, object_hook=dict_to_object)
print("reloaded obj:", reloaded)

assert original == reloaded

$ python3 datetimedecoder_isoformat.py 
original: {'date': datetime.datetime(2018, 8, 21, 19, 25, 16, 852379), 
'type': 'bar', 'name': 'foo'}
serialized: {
    "date": {
        "__type__": "datetime",
        "isovalue": "2018-08-21T19:25:16.852379"
    },
    "type": "bar",
    "name": "foo"
}
reloaded obj: {'date': datetime.datetime(2018, 8, 21, 19, 25, 16, 852379), 
'type': 'bar', 'name': 'foo'}