From 94cd36011ead28efeef7487d8617e7052e905a98 Mon Sep 17 00:00:00 2001 From: Matthias Bernt Date: Wed, 22 Jul 2020 22:01:34 +0200 Subject: [PATCH 1/4] an initial idea for parsing and storing defaults --- acclimatise/cli_types.py | 5 +++++ acclimatise/model.py | 21 ++++++++++++++------- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/acclimatise/cli_types.py b/acclimatise/cli_types.py index 4df8ed8..008f68d 100644 --- a/acclimatise/cli_types.py +++ b/acclimatise/cli_types.py @@ -13,6 +13,11 @@ class CliType: A data type used in the command-line """ + default: object = None + """ + A default value, None if unknown + """ + @property def representable(self) -> set: """ diff --git a/acclimatise/model.py b/acclimatise/model.py index 53eb03a..ae296e6 100644 --- a/acclimatise/model.py +++ b/acclimatise/model.py @@ -378,26 +378,33 @@ def capital(self): file_re = re.compile("file|path", flags=re.IGNORECASE) dir_re = re.compile("folder|directory", flags=re.IGNORECASE) +default_re = re.compile("default(?: value)?(?:[:=] ?| )([^ )\]]+)", flags=re.IGNORECASE) def infer_type(string) -> typing.Optional[cli_types.CliType]: """ Reads a string (argument description etc) to find hints about what type this argument might be. This is generally called by the get_type() methods """ + default_match = default_re.match() + if default_match is not None: + default = default_match.group(1) + else: + default = None + if bool_re.match(string): - return cli_types.CliBoolean() + return cli_types.CliBoolean(default = default) elif float_re.match(string): - return cli_types.CliFloat() + return cli_types.CliFloat(default = default) elif int_re.match(string): - return cli_types.CliInteger() + return cli_types.CliInteger(default = default) elif file_re.match(string): - return cli_types.CliFile() + return cli_types.CliFile(default = default) elif dir_re.match(string): - return cli_types.CliDir() + return cli_types.CliDir(default = default) elif str_re.match(string): - return cli_types.CliString() + return cli_types.CliString(default = default) else: - return cli_types.CliString() + return cli_types.CliString(default = default) @yaml_object(yaml) From 13c99b1f6ddc8d665632c3014ec8ec7f0478564e Mon Sep 17 00:00:00 2001 From: Matthias Bernt Date: Thu, 23 Jul 2020 11:17:24 +0200 Subject: [PATCH 2/4] set correct typing fro defaults --- acclimatise/cli_types.py | 53 +++++++++++++++++++++++++++++++++++----- 1 file changed, 47 insertions(+), 6 deletions(-) diff --git a/acclimatise/cli_types.py b/acclimatise/cli_types.py index 008f68d..1a7338b 100644 --- a/acclimatise/cli_types.py +++ b/acclimatise/cli_types.py @@ -13,7 +13,7 @@ class CliType: A data type used in the command-line """ - default: object = None + default: Optional[typing.Any] = None """ A default value, None if unknown """ @@ -36,6 +36,11 @@ class CliEnum(CliType): One of a list of possible options """ + default: Optional[Enum] = None + """ + A default value, None if unknown + """ + enum: Enum """ The possible options as a Python Enum @@ -48,7 +53,10 @@ class CliFloat(CliType): Takes a floating-point value """ - pass + default: Optional[float] = None + """ + A default value, None if unknown + """ @dataclass(unsafe_hash=True) @@ -57,6 +65,11 @@ class CliInteger(CliType): Takes an integer value """ + default: Optional[int] = None + """ + A default value, None if unknown + """ + _representable = {CliFloat} @@ -66,7 +79,10 @@ class CliString(CliType): Takes a string value """ - pass + default: Optional[str] = None + """ + A default value, None if unknown + """ @dataclass(unsafe_hash=True) @@ -75,7 +91,10 @@ class CliBoolean(CliType): Takes a boolean value """ - pass + default: Optional[bool] = None + """ + A default value, None if unknown + """ @dataclass(unsafe_hash=True) @@ -84,7 +103,10 @@ class CliDir(CliType): Takes a directory path """ - pass + default: Optional[str] = None + """ + A default value, None if unknown + """ @dataclass(unsafe_hash=True) @@ -93,7 +115,10 @@ class CliFile(CliType): Takes a file path """ - pass + default: Optional[str] = None + """ + A default value, None if unknown + """ @dataclass(unsafe_hash=True) @@ -102,6 +127,11 @@ class CliDict(CliType): Takes a dictionary value """ + default: Optional[str] = None + """ + A default value, None if unknown + """ + key: CliType """ Data type of the keys to this dictionary @@ -119,6 +149,11 @@ class CliList(CliType): Takes a list value """ + default: Optional[typing.List[CliType]] = None + """ + A default value, None if unknown + """ + value: CliType """ Data type of the values in this list @@ -131,6 +166,12 @@ class CliTuple(CliType): Takes a list of values with a fixed length, possibly each with different types """ + default: Optional[typing.Tuple[CliType]] = None + + """ + A default value, None if unknown + """ + values: typing.List[CliType] """ List of types, in order, held within the tuple From 35241ef7f2839f26e1e96676baa2a8eecd40f536 Mon Sep 17 00:00:00 2001 From: Matthias Bernt Date: Fri, 24 Jul 2020 17:19:51 +0200 Subject: [PATCH 3/4] add regular expressions for float and int and use them as fallback --- acclimatise/model.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/acclimatise/model.py b/acclimatise/model.py index ae296e6..2b10de2 100644 --- a/acclimatise/model.py +++ b/acclimatise/model.py @@ -371,7 +371,7 @@ def capital(self): ) -int_re = re.compile("(int(eger)?)|size|length|max|min", flags=re.IGNORECASE) +int_re = re.compile("(int(eger)?)|size|length|max|min|num(ber)?", flags=re.IGNORECASE) str_re = re.compile("str(ing)?", flags=re.IGNORECASE) float_re = re.compile("float|decimal", flags=re.IGNORECASE) bool_re = re.compile("bool(ean)?", flags=re.IGNORECASE) @@ -379,6 +379,9 @@ def capital(self): dir_re = re.compile("folder|directory", flags=re.IGNORECASE) default_re = re.compile("default(?: value)?(?:[:=] ?| )([^ )\]]+)", flags=re.IGNORECASE) +float_re = re.compile('[+-]?([0-9]+([.][0-9]*)?|[.][0-9]+)', flags=re.IGNORECASE) +int_re = re.compile('[+-]?([0-9]+[^.0-9])', flags=re.IGNORECASE) + def infer_type(string) -> typing.Optional[cli_types.CliType]: """ @@ -403,6 +406,10 @@ def infer_type(string) -> typing.Optional[cli_types.CliType]: return cli_types.CliDir(default = default) elif str_re.match(string): return cli_types.CliString(default = default) + elif float_re.search(string) and not int_re.search(string): + return cli_types.CliFloat(default = default) + elif not int_re.search(string) and int_re.search(string): + return cli_types.CliInteger(default = default) else: return cli_types.CliString(default = default) From 799b3ac4f2c260b9a17f3833ed4ba071e467e5ec Mon Sep 17 00:00:00 2001 From: Matthias Bernt Date: Tue, 28 Jul 2020 10:58:44 +0200 Subject: [PATCH 4/4] iregex string --- acclimatise/model.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/acclimatise/model.py b/acclimatise/model.py index 2b10de2..0745fa1 100644 --- a/acclimatise/model.py +++ b/acclimatise/model.py @@ -378,7 +378,8 @@ def capital(self): file_re = re.compile("file|path", flags=re.IGNORECASE) dir_re = re.compile("folder|directory", flags=re.IGNORECASE) -default_re = re.compile("default(?: value)?(?:[:=] ?| )([^ )\]]+)", flags=re.IGNORECASE) +default_re = re.compile(r"default(?: value)?(?:[:=] ?| )([^ )\]]+)", flags=re.IGNORECASE) + float_re = re.compile('[+-]?([0-9]+([.][0-9]*)?|[.][0-9]+)', flags=re.IGNORECASE) int_re = re.compile('[+-]?([0-9]+[^.0-9])', flags=re.IGNORECASE)