config_argparse.py 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. import argparse
  2. from pathlib import Path
  3. import yaml
  4. class ArgumentParser(argparse.ArgumentParser):
  5. """Simple implementation of ArgumentParser supporting config file
  6. This class is originated from https://github.com/bw2/ConfigArgParse,
  7. but this class is lack of some features that it has.
  8. - Not supporting multiple config files
  9. - Automatically adding "--config" as an option.
  10. - Not supporting any formats other than yaml
  11. - Not checking argument type
  12. """
  13. def __init__(self, *args, **kwargs):
  14. super().__init__(*args, **kwargs)
  15. self.add_argument("--config", help="Give config file in yaml format")
  16. def parse_known_args(self, args=None, namespace=None):
  17. # Once parsing for setting from "--config"
  18. _args, _ = super().parse_known_args(args, namespace)
  19. if _args.config is not None:
  20. if not Path(_args.config).exists():
  21. self.error(f"No such file: {_args.config}")
  22. with open(_args.config, "r", encoding="utf-8") as f:
  23. d = yaml.safe_load(f)
  24. if not isinstance(d, dict):
  25. self.error("Config file has non dict value: {_args.config}")
  26. for key in d:
  27. for action in self._actions:
  28. if key == action.dest:
  29. break
  30. else:
  31. self.error(f"unrecognized arguments: {key} (from {_args.config})")
  32. # NOTE(kamo): Ignore "--config" from a config file
  33. # NOTE(kamo): Unlike "configargparse", this module doesn't check type.
  34. # i.e. We can set any type value regardless of argument type.
  35. self.set_defaults(**d)
  36. return super().parse_known_args(args, namespace)