Refactor command line argument parser
This commit is contained in:
parent
dba6338968
commit
b23aa4629c
@ -30,9 +30,9 @@ import signal
|
|||||||
import socket
|
import socket
|
||||||
import sys
|
import sys
|
||||||
from types import FrameType
|
from types import FrameType
|
||||||
from typing import Dict, List, cast
|
from typing import List, cast
|
||||||
|
|
||||||
from radicale import VERSION, config, log, server, storage
|
from radicale import VERSION, config, log, server, storage, types
|
||||||
from radicale.log import logger
|
from radicale.log import logger
|
||||||
|
|
||||||
|
|
||||||
@ -57,6 +57,7 @@ def run() -> None:
|
|||||||
log.setup()
|
log.setup()
|
||||||
|
|
||||||
# Get command-line arguments
|
# Get command-line arguments
|
||||||
|
# Configuration options are stored in dest with format "c:SECTION:OPTION"
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
prog="radicale", usage="%(prog)s [OPTIONS]", allow_abbrev=False)
|
prog="radicale", usage="%(prog)s [OPTIONS]", allow_abbrev=False)
|
||||||
|
|
||||||
@ -65,36 +66,38 @@ def run() -> None:
|
|||||||
help="check the storage for errors and exit")
|
help="check the storage for errors and exit")
|
||||||
parser.add_argument("-C", "--config",
|
parser.add_argument("-C", "--config",
|
||||||
help="use specific configuration files", nargs="*")
|
help="use specific configuration files", nargs="*")
|
||||||
parser.add_argument("-D", "--debug", action="store_true",
|
parser.add_argument("-D", "--debug", action="store_const", const="debug",
|
||||||
|
dest="c:logging:level", default=argparse.SUPPRESS,
|
||||||
help="print debug information")
|
help="print debug information")
|
||||||
|
|
||||||
groups: Dict["argparse._ArgumentGroup", List[str]] = {}
|
for section, section_data in config.DEFAULT_CONFIG_SCHEMA.items():
|
||||||
for section, values in config.DEFAULT_CONFIG_SCHEMA.items():
|
|
||||||
if section.startswith("_"):
|
if section.startswith("_"):
|
||||||
continue
|
continue
|
||||||
|
assert ":" not in section # check field separator
|
||||||
|
assert "-" not in section and "_" not in section # not implemented
|
||||||
group = parser.add_argument_group(section)
|
group = parser.add_argument_group(section)
|
||||||
groups[group] = []
|
for option, data in section_data.items():
|
||||||
for option, data in values.items():
|
|
||||||
if option.startswith("_"):
|
if option.startswith("_"):
|
||||||
continue
|
continue
|
||||||
kwargs = data.copy()
|
kwargs = data.copy()
|
||||||
long_name = "--%s-%s" % (section, option.replace("_", "-"))
|
long_name = "--%s-%s" % (section, option.replace("_", "-"))
|
||||||
args: List[str] = list(kwargs.pop("aliases", ()))
|
args: List[str] = list(kwargs.pop("aliases", ()))
|
||||||
args.append(long_name)
|
args.append(long_name)
|
||||||
kwargs["dest"] = "%s_%s" % (section, option)
|
kwargs["dest"] = "c:%s:%s" % (section, option)
|
||||||
groups[group].append(kwargs["dest"])
|
kwargs["metavar"] = "VALUE"
|
||||||
|
kwargs["default"] = argparse.SUPPRESS
|
||||||
del kwargs["value"]
|
del kwargs["value"]
|
||||||
with contextlib.suppress(KeyError):
|
with contextlib.suppress(KeyError):
|
||||||
del kwargs["internal"]
|
del kwargs["internal"]
|
||||||
|
|
||||||
if kwargs["type"] == bool:
|
if kwargs["type"] == bool:
|
||||||
del kwargs["type"]
|
del kwargs["type"]
|
||||||
kwargs["action"] = "store_const"
|
|
||||||
kwargs["const"] = "True"
|
|
||||||
opposite_args = list(kwargs.pop("opposite_aliases", ()))
|
opposite_args = list(kwargs.pop("opposite_aliases", ()))
|
||||||
opposite_args.append("--no%s" % long_name[1:])
|
opposite_args.append("--no%s" % long_name[1:])
|
||||||
|
kwargs["action"] = "store_const"
|
||||||
|
kwargs["const"] = "True"
|
||||||
group.add_argument(*args, **kwargs)
|
group.add_argument(*args, **kwargs)
|
||||||
|
# Opposite argument
|
||||||
kwargs["const"] = "False"
|
kwargs["const"] = "False"
|
||||||
kwargs["help"] = "do not %s (opposite of %s)" % (
|
kwargs["help"] = "do not %s (opposite of %s)" % (
|
||||||
kwargs["help"], long_name)
|
kwargs["help"], long_name)
|
||||||
@ -106,23 +109,17 @@ def run() -> None:
|
|||||||
args_ns = parser.parse_args()
|
args_ns = parser.parse_args()
|
||||||
|
|
||||||
# Preliminary configure logging
|
# Preliminary configure logging
|
||||||
if args_ns.debug:
|
|
||||||
args_ns.logging_level = "debug"
|
|
||||||
with contextlib.suppress(ValueError):
|
with contextlib.suppress(ValueError):
|
||||||
log.set_level(config.DEFAULT_CONFIG_SCHEMA["logging"]["level"]["type"](
|
log.set_level(config.DEFAULT_CONFIG_SCHEMA["logging"]["level"]["type"](
|
||||||
args_ns.logging_level))
|
vars(args_ns).get("c:logging:level", "")))
|
||||||
|
|
||||||
# Update Radicale configuration according to arguments
|
# Update Radicale configuration according to arguments
|
||||||
arguments_config = {}
|
arguments_config: types.MUTABLE_CONFIG = {}
|
||||||
for group, actions in groups.items():
|
for key, value in vars(args_ns).items():
|
||||||
section = group.title or ""
|
if key.startswith("c:"):
|
||||||
section_config = {}
|
_, section, option = key.split(":", maxsplit=2)
|
||||||
for action in actions:
|
arguments_config[section] = arguments_config.get(section, {})
|
||||||
value = getattr(args_ns, action)
|
arguments_config[section][option] = value
|
||||||
if value is not None:
|
|
||||||
section_config[action.split('_', 1)[1]] = value
|
|
||||||
if section_config:
|
|
||||||
arguments_config[section] = section_config
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
configuration = config.load(config.parse_compound_paths(
|
configuration = config.load(config.parse_compound_paths(
|
||||||
|
Loading…
Reference in New Issue
Block a user