Use deferral mechanism for cfg file options

Fixes #3162
This commit is contained in:
Aldo Cortesi 2018-05-27 10:12:24 +12:00
parent d1e3968fa8
commit e59ba13417
3 changed files with 17 additions and 17 deletions

View File

@ -217,6 +217,10 @@ class OptManager:
self.changed.send(self, updated=updated) self.changed.send(self, updated=updated)
return unknown return unknown
def update_defer(self, **kwargs):
unknown = self.update_known(**kwargs)
self._deferred.update(unknown)
def update(self, **kwargs): def update(self, **kwargs):
u = self.update_known(**kwargs) u = self.update_known(**kwargs)
if u: if u:
@ -494,26 +498,21 @@ def parse(text):
return data return data
def load(opts, text): def load(opts: OptManager, text: str) -> None:
""" """
Load configuration from text, over-writing options already set in Load configuration from text, over-writing options already set in
this object. May raise OptionsError if the config file is invalid. this object. May raise OptionsError if the config file is invalid.
Returns a dictionary of all unknown options.
""" """
data = parse(text) data = parse(text)
return opts.update_known(**data) opts.update_defer(**data)
def load_paths(opts, *paths): def load_paths(opts: OptManager, *paths: str) -> None:
""" """
Load paths in order. Each path takes precedence over the previous Load paths in order. Each path takes precedence over the previous
path. Paths that don't exist are ignored, errors raise an path. Paths that don't exist are ignored, errors raise an
OptionsError. OptionsError.
Returns a dictionary of unknown options.
""" """
ret = {}
for p in paths: for p in paths:
p = os.path.expanduser(p) p = os.path.expanduser(p)
if os.path.exists(p) and os.path.isfile(p): if os.path.exists(p) and os.path.isfile(p):
@ -525,15 +524,14 @@ def load_paths(opts, *paths):
"Error reading %s: %s" % (p, e) "Error reading %s: %s" % (p, e)
) )
try: try:
ret.update(load(opts, txt)) load(opts, txt)
except exceptions.OptionsError as e: except exceptions.OptionsError as e:
raise exceptions.OptionsError( raise exceptions.OptionsError(
"Error reading %s: %s" % (p, e) "Error reading %s: %s" % (p, e)
) )
return ret
def serialize(opts, text, defaults=False): def serialize(opts: OptManager, text: str, defaults: bool = False) -> str:
""" """
Performs a round-trip serialization. If text is not None, it is Performs a round-trip serialization. If text is not None, it is
treated as a previous serialization that should be modified treated as a previous serialization that should be modified
@ -554,7 +552,7 @@ def serialize(opts, text, defaults=False):
return ruamel.yaml.round_trip_dump(data) return ruamel.yaml.round_trip_dump(data)
def save(opts, path, defaults=False): def save(opts: OptManager, path: str, defaults: bool =False) -> None:
""" """
Save to path. If the destination file exists, modify it in-place. Save to path. If the destination file exists, modify it in-place.

View File

@ -93,7 +93,7 @@ def run(
sys.exit(1) sys.exit(1)
try: try:
opts.confdir = args.confdir opts.confdir = args.confdir
unknown = optmanager.load_paths( optmanager.load_paths(
opts, opts,
os.path.join(opts.confdir, OPTIONS_FILE_NAME), os.path.join(opts.confdir, OPTIONS_FILE_NAME),
) )
@ -109,7 +109,6 @@ def run(
server = proxy.server.DummyServer(pconf) server = proxy.server.DummyServer(pconf)
master.server = server master.server = server
opts.update_known(**unknown)
if args.options: if args.options:
print(optmanager.dump_defaults(opts)) print(optmanager.dump_defaults(opts))
sys.exit(0) sys.exit(0)

View File

@ -269,11 +269,13 @@ def test_serialize():
t = "# a comment" t = "# a comment"
optmanager.load(o2, t) optmanager.load(o2, t)
assert optmanager.load(o2, "foobar: '123'") == {"foobar": "123"} optmanager.load(o2, "foobar: '123'")
assert o2._deferred == {"foobar": "123"}
t = "" t = ""
optmanager.load(o2, t) optmanager.load(o2, t)
assert optmanager.load(o2, "foobar: '123'") == {"foobar": "123"} optmanager.load(o2, "foobar: '123'")
assert o2._deferred == {"foobar": "123"}
def test_serialize_defaults(): def test_serialize_defaults():
@ -297,7 +299,8 @@ def test_saving(tmpdir):
with open(dst, 'a') as f: with open(dst, 'a') as f:
f.write("foobar: '123'") f.write("foobar: '123'")
assert optmanager.load_paths(o, dst) == {"foobar": "123"} optmanager.load_paths(o, dst)
assert o._deferred == {"foobar": "123"}
with open(dst, 'a') as f: with open(dst, 'a') as f:
f.write("'''") f.write("'''")