I am using solution in the related answer for How to auto-dump modified values in nested dictionaries using ruamel.yaml .
I have observe that when self.update(self.yaml.load(f) or {})
is called: it keeps reformatting the yaml
file by sorting it based on the alphabetic order and changes its indention into 2.
=> Would it be possible to prevent reformatting?
I have also tried following line, which did not make any affect on it in order to keep indention as 4 space:
yaml = YAML(typ="safe")
yaml.indent(mapping=2, sequence=4, offset=2)
yaml.default_flow_style = False
config.yaml:
c: # my comment
b:
f: 5
e: 22
a:
z: 4
b: 4 # my comment
code (exactly same code from How to auto-dump modified values in nested dictionaries using ruamel.yaml ):
#!/usr/bin/env python3
import sys
import os
from pathlib import Path
import ruamel.yaml
class SubConfig(dict):
def __init__(self, parent):
self.parent = parent
def updated(self):
self.parent.updated()
def __setitem__(self, key, value):
if isinstance(value, dict):
v = SubConfig(self)
v.update(value)
value = v
super().__setitem__(key, value)
self.updated()
def __getitem__(self, key):
try:
res = super().__getitem__(key)
except KeyError:
super().__setitem__(key, SubConfig(self))
self.updated()
return super().__getitem__(key)
return res
def __delitem__(self, key):
res = super().__delitem__(key)
self.updated()
def update(self, *args, **kw):
for arg in args:
for k, v in arg.items():
self[k] = v
for k, v in kw.items():
self[k] = v
self.updated()
return
_SR = ruamel.yaml.representer.SafeRepresenter
_SR.add_representer(SubConfig, _SR.represent_dict)
class Config(dict):
def __init__(self, filename, auto_dump=True):
self.filename = filename if hasattr(filename, "open") else Path(filename)
self.auto_dump = auto_dump
self.changed = False
self.yaml = ruamel.yaml.YAML(typ="safe")
self.yaml.default_flow_style = False
if self.filename.exists():
with open(filename) as f:
self.update(self.yaml.load(f) or {})
def updated(self):
if self.auto_dump:
self.dump(force=True)
else:
self.changed = True
def dump(self, force=False):
if not self.changed and not force:
return
with open(self.filename, "w") as f:
self.yaml.dump(dict(self), f)
self.changed = False
def __setitem__(self, key, value):
if isinstance(value, dict):
v = SubConfig(self)
v.update(value)
value = v
super().__setitem__(key, value)
self.updated()
def __getitem__(self, key):
try:
res = super().__getitem__(key)
except KeyError:
super().__setitem__(key, SubConfig(self))
self.updated()
return super().__getitem__(key)
def __delitem__(self, key):
res = super().__delitem__(key)
self.updated()
def update(self, *args, **kw):
for arg in args:
for k, v in arg.items():
self[k] = v
for k, v in kw.items():
self[k] = v
self.updated()
cfg = Config(Path("config.yaml"))
=> config.yaml
file is updated as follows, where, its sorted and indention changed into 2, and comments are removed:
a:
b: 4
z: 4
c:
b:
e: 5
f: 22