Source code for ase2sprkkr.common.tools

"""This module contain support for the tools"""

from pathlib import Path
import pyparsing as pp
import argparse

unyt = None


[docs] def parse_inches(string): """ .. doctest:: >>> parse_inches(1) 1.0 >>> int(parse_inches("2cm") * 10000) 7874 """ global unyt if isinstance(string, (int, float)): return float(string) if not unyt: import unyt out = unyt.unyt_quantity.from_string(string) if out.units != unyt.dimensionless: out = out.to(unyt.inch) return float(out)
[docs] def parse_tuple_function(type, length=None, max_length=True, delimiter=","): """Returns a function, that can parse a comma delimited tuple of values .. doctest :: >>> parse_tuple_function(float, 2)("5,4.7") (5.0, 4.7) >>> parse_tuple_function(float, 3)("1,2") # doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): ValueError: The given value "1,2" should contain at least 3 values, delimited by ","' >>> parse_tuple_function(float, 1)("1,2") # doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): ValueError: The given value "1,2" should contain no more than 1 values, delimited by ","' >>> parse_tuple_function(float, 1, 3)("1,2") (1.0, 2.0) >>> parse_tuple_function(float, 1, 1)("1,2") # doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): ValueError: The given value "1,2" should contain no more than 1 values, delimited by ","' """ if max_length is True: max_length = length def parse(string): out = string.split(delimiter) if length and len(out) < length: raise ValueError( f'The given value "{string}" should contain at least {length} values, delimited by "{delimiter}"' ) if max_length and len(out) > max_length: raise ValueError( f'The given value "{string}" should contain no more than {max_length} values, delimited by "{delimiter}"' ) out = tuple([type(i) for i in out]) return out return parse
[docs] def append_id_to_filename(filename, id, connector="_"): p = Path(filename) return f"{Path.joinpath(p.parent, p.stem)}{connector}{id}{p.suffix}"
string = pp.Regex('"([^"]|"")*"').set_parse_action(lambda x: x[0][1:-1].replace('""', '"')) | pp.Regex( "'([^']|'')*'" ).set_parse_action(lambda x: x[0][1:-1].replace("''", "'")) boolean = pp.Keyword("True").set_parse_action(lambda x: True) | pp.Keyword("False").set_parse_action(lambda x: False) forward = pp.Forward() token = pp.pyparsing_common.number | pp.Word(pp.alphanums + "-_@#$!/[]") | forward | string | boolean tupl = ( pp.Literal("(").suppress() + pp.DelimitedList(token, delim=",").set_parse_action(lambda x: tuple(x)) + pp.Literal(")").suppress() ) dict_token = ( (pp.pyparsing_common.number | pp.Word(pp.alphanums + "-_@#$!/[]")) + pp.Literal(":").suppress() + token ).set_parse_action(lambda x: (x[0], x[1])) dicti = ( pp.Literal("{").suppress() + pp.DelimitedList(dict_token, delim=":").set_parse_action(lambda x: dict(x.as_list())) + pp.Literal("}").suppress() ) forward << (dicti | tupl) option = token ^ pp.Regex(".*").set_parse_action(lambda x: x[0]) equal_value = pp.Literal("=").suppress() + option
[docs] def parse_named_option(x: str, numbers_allowed: bool = False): """Parse a given string of the format `name=value` If it recognizes number, bool or tuple of values or quoted string in the value, it converts it to a given type. Returns ------- name:str Name of the parsed option value:Any Value of the parsed option """ if numbers_allowed: p = pp.Word(pp.alphanums + "_") else: p = pp.Word(pp.alphas) return tuple((p + equal_value).parse_string(x, True))
[docs] def main(local): """ Cli subcommands can be runned on its own. This method creates the main function for the the sub-scripts. """ parser = argparse.ArgumentParser( description=local["description"], formatter_class=argparse.RawDescriptionHelpFormatter ) local["parser"](parser) args = parser.parse_args() local["run"](args)