def _split_on_commas(string: str) -> List[str]: """Split a bracketed string on commas. The commas inside brackets are preserved. """ items = [] char_buffer = [] # type: List[str] openings = [] # type: List[str] for i, char in enumerate(string): if char == "," and not openings: if char_buffer: items.append("".join(char_buffer)) char_buffer = [] continue elif char == " " and not char_buffer: continue elif char in ("(", "["): openings.append(char) elif char == ")": if openings.pop() != "(": raise ParseError("Invalid bracket end ')', col {}.".format(i)) elif char == "]": if openings.pop() != "[": raise ParseError("Invalid bracket end ']', col {}.".format(i)) char_buffer.append(char) if char_buffer: items.append("".join(char_buffer)) return items
def __missing__(self, key): """Try to fetch and parse the variable value from `os.environ`.""" if key in os.environ: try: value = _parse_value(os.environ[key], self) except ParseError: # If we cannot parse it, use it as a string. value = os.environ[key] log("Variable {}={!r} taken from the environment.".format( key, value)) return value raise ParseError("Undefined variable: {}".format(key))
def _parse_list(string: str, vars_dict: VarsDict) -> List[Any]: """Parse the string recursively as a list.""" matched_content = get_first_match(LIST, string) if not matched_content: return [] items = _split_on_commas(matched_content) values = [_parse_value(val, vars_dict) for val in items] types = [type(val) for val in values] if len(set(types)) > 1: raise ParseError("List must of a same type, is: {}".format(types)) return values
def _apply_change(config_dict: Dict[str, Any], setting: str) -> None: if "=" not in setting: raise ParseError("Invalid setting '{}'".format(setting)) key, value = (s.strip() for s in setting.split("=", maxsplit=1)) if "." in key: section, option = key.split(".", maxsplit=1) else: section = "main" option = key if section not in config_dict: log("Creating new section '{}'".format(section)) config_dict[section] = OrderedDict() config_dict[section][option] = -1, value # no line number
def _parse_value(string: str, vars_dict: VarsDict) -> Any: """Parse the value recursively according to the Nerualmonkey grammar. Arguments: string: the string to be parsed vars_dict: a dictionary of variables for substitution """ if string in CONSTANTS: return CONSTANTS[string] for matcher, parser in _keyval_parser_dict().items(): if matcher.match(string) is not None: return parser(string, vars_dict) raise ParseError("Cannot parse value: '{}'.".format(string))