import sys
from typing import Any, Dict, List, Optional, Tuple
-from kazoo.client import KazooClient
-from kazoo.protocol.states import WatchedEvent
-
-import scott_secrets
-
# This module is commonly used by others in here and should avoid
# taking any unnecessary dependencies back on them.
action='store_true',
help='If present, config will raise an exception if it doesn\'t recognize an argument. The default behavior is to ignore unknown arguments so as to allow interoperability with programs that want to use their own argparse calls to parse their own, separate commandline args.',
)
+GROUP.add_argument(
+ '--config_exit_after_parse',
+ default=False,
+ action='store_true',
+ help='If present, halt the program after parsing config. Useful, for example, to write a --config_savefile and then terminate.',
+)
class Config:
# A zookeeper client that is lazily created so as to not incur
# the latency of connecting to zookeeper for programs that are
# not reading or writing their config data into zookeeper.
- self.zk: Optional[KazooClient] = None
+ self.zk: Optional[Any] = None
# Per known zk file, what is the max version we have seen?
self.max_version: Dict[str, int] = {}
def __contains__(self, key: str) -> bool:
return key in self.config
+ def get(self, key: str, default: Any = None) -> Optional[Any]:
+ return self.config.get(key, default)
+
@staticmethod
def add_commandline_args(title: str, description: str = "") -> argparse._ArgumentGroup:
"""Create a new context for arguments and return a handle.
env = env[1:]
return var, env, chunks
+ @staticmethod
+ def _to_bool(in_str: str) -> bool:
+ """
+ Args:
+ in_str: the string to convert to boolean
+
+ Returns:
+ A boolean equivalent of the original string based on its contents.
+ All conversion is case insensitive. A positive boolean (True) is
+ returned if the string value is any of the following:
+
+ * "true"
+ * "t"
+ * "1"
+ * "yes"
+ * "y"
+ * "on"
+
+ Otherwise False is returned.
+
+ >>> to_bool('True')
+ True
+
+ >>> to_bool('1')
+ True
+
+ >>> to_bool('yes')
+ True
+
+ >>> to_bool('no')
+ False
+
+ >>> to_bool('huh?')
+ False
+
+ >>> to_bool('on')
+ True
+ """
+ return in_str.lower() in ("true", "1", "yes", "y", "t", "on")
+
def _augment_sys_argv_from_environment_variables(self):
"""Internal. Look at the system environment for variables that match
commandline arg names. This is done via some munging such that:
self.saved_messages.append(
f'Initialized from environment: {var} = {value}'
)
- from string_utils import to_bool
-
- if len(chunks) == 1 and to_bool(value):
+ if len(chunks) == 1 and Config._to_bool(value):
sys.argv.append(var)
elif len(chunks) > 1:
sys.argv.append(var)
sys.argv.append(value)
arg = ''
- def _process_dynamic_args(self, event: WatchedEvent):
+ def _process_dynamic_args(self, event):
assert self.zk
logger = logging.getLogger(__name__)
contents, meta = self.zk.get(event.path, watch=self._process_dynamic_args)
if loadfile is not None:
zkpath = None
if loadfile[:3] == 'zk:':
+ from kazoo.client import KazooClient
+
+ import scott_secrets
+
try:
if self.zk is None:
+
self.zk = KazooClient(
hosts=scott_secrets.ZOOKEEPER_NODES,
use_ssl=True,
zkpath = re.sub(r'//+', '/', zkpath)
try:
if not self.zk:
+ from kazoo.client import KazooClient
+
+ import scott_secrets
+
self.zk = KazooClient(
hosts=scott_secrets.ZOOKEEPER_NODES,
use_ssl=True,
self.dump_config()
self.config_parse_called = True
+ if config['config_exit_after_parse']:
+ print("Exiting because of --config_exit_after_parse.")
+ if self.zk:
+ self.zk.stop()
+ sys.exit(0)
return self.config
def has_been_parsed(self) -> bool: