From fc2ac8e1a336d8ce0ff72ee3d8a10272f6aebb54 Mon Sep 17 00:00:00 2001 From: Matthias Bernt Date: Wed, 22 Jul 2020 21:20:53 +0200 Subject: [PATCH 01/18] an idea to guess if files / dirs are in / output --- acclimatise/cli_types.py | 10 ++++++++-- acclimatise/model.py | 16 ++++++++++++++-- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/acclimatise/cli_types.py b/acclimatise/cli_types.py index 4df8ed8..2e05582 100644 --- a/acclimatise/cli_types.py +++ b/acclimatise/cli_types.py @@ -79,7 +79,10 @@ class CliDir(CliType): Takes a directory path """ - pass + output: bool = None + """ + Indicator if the file is input or output (None if unknown) + """ @dataclass(unsafe_hash=True) @@ -88,7 +91,10 @@ class CliFile(CliType): Takes a file path """ - pass + output: bool = None + """ + Indicator if the file is input or output (None if unknown) + """ @dataclass(unsafe_hash=True) diff --git a/acclimatise/model.py b/acclimatise/model.py index 0a90795..8438dec 100644 --- a/acclimatise/model.py +++ b/acclimatise/model.py @@ -375,6 +375,8 @@ def capital(self): float_re = re.compile("float|decimal", flags=re.IGNORECASE) bool_re = re.compile("bool(ean)?", flags=re.IGNORECASE) file_re = re.compile("file|path", flags=re.IGNORECASE) +input_re = re.compile("read|in(put)?", flags=re.IGNORECASE) +output_re = re.compile("write|out(put)?", flags=re.IGNORECASE) dir_re = re.compile("folder|directory", flags=re.IGNORECASE) @@ -390,9 +392,19 @@ def infer_type(string) -> typing.Optional[cli_types.CliType]: elif int_re.match(string): return cli_types.CliInteger() elif file_re.match(string): - return cli_types.CliFile() + if input_re.match(string) and not output_re.match(string): + return cli_types.CliFile(output=False) + elif not input_re.match(string) and output_re.match(string): + return cli_types.CliFile(output=True) + else: + return cli_types.CliFile() elif dir_re.match(string): - return cli_types.CliDir() + if input_re.match(string) and not output_re.match(string): + return cli_types.CliDir(output=False) + elif not input_re.match(string) and output_re.match(string): + return cli_types.CliDir(output=True) + else: + return cli_types.CliDir() elif str_re.match(string): return cli_types.CliString() else: From a608d051c36a4a11cac922b09fb4ffe70819e120 Mon Sep 17 00:00:00 2001 From: Matthias Bernt Date: Thu, 23 Jul 2020 13:03:12 +0200 Subject: [PATCH 02/18] test for infer_type --- acclimatise/model.py | 4 ++-- test/test_type_inference.py | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 test/test_type_inference.py diff --git a/acclimatise/model.py b/acclimatise/model.py index 8438dec..1ff95f5 100644 --- a/acclimatise/model.py +++ b/acclimatise/model.py @@ -394,14 +394,14 @@ def infer_type(string) -> typing.Optional[cli_types.CliType]: elif file_re.match(string): if input_re.match(string) and not output_re.match(string): return cli_types.CliFile(output=False) - elif not input_re.match(string) and output_re.match(string): + elif not input_re.match(string) and output_re.match(string): return cli_types.CliFile(output=True) else: return cli_types.CliFile() elif dir_re.match(string): if input_re.match(string) and not output_re.match(string): return cli_types.CliDir(output=False) - elif not input_re.match(string) and output_re.match(string): + elif not input_re.match(string) and output_re.match(string): return cli_types.CliDir(output=True) else: return cli_types.CliDir() diff --git a/test/test_type_inference.py b/test/test_type_inference.py new file mode 100644 index 0000000..53a4ee1 --- /dev/null +++ b/test/test_type_inference.py @@ -0,0 +1,20 @@ +from acclimatise.cli_types import CliString +from acclimatise.model import infer_type + + +def test_type_inference(): + test_strings = [("", CliString, False), ("int", CliInteger, False), + ("size", CliInteger, False), ("length", CliInteger, False), + ("max", CliInteger, False), ("min", CliInteger, False), + ("str", CliString, False), ("float", CliFloat, False), + ("decimal", CliFloat, False), ("bool", CliBoolean, False), + ("file", CliFile, False), ("path", CliFile, False), + ("input file", CliFile, False), + ("output file", CliFile, True), ("folder", CliDir, False), + ("directory", CliDir, False), + ("output directory", CliDir, False)] + + for ts in test_strings: + typ = infer_type(ts[0]) + assert isinstance(typ, ts[1]), "%s should be %s but is %s" % (ts[0], ts[1], typ) + assert not typ.hasattr("output") or typ.output == ts[2] From 73de563ec9545d63e02e3f95547f754b2ad8394b Mon Sep 17 00:00:00 2001 From: Matthias Bernt Date: Fri, 24 Jul 2020 12:31:07 +0200 Subject: [PATCH 03/18] test with pytest parametrisation --- test/test_type_inference.py | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/test/test_type_inference.py b/test/test_type_inference.py index 53a4ee1..3ba6a70 100644 --- a/test/test_type_inference.py +++ b/test/test_type_inference.py @@ -1,20 +1,22 @@ +import pytest + from acclimatise.cli_types import CliString from acclimatise.model import infer_type -def test_type_inference(): - test_strings = [("", CliString, False), ("int", CliInteger, False), - ("size", CliInteger, False), ("length", CliInteger, False), - ("max", CliInteger, False), ("min", CliInteger, False), - ("str", CliString, False), ("float", CliFloat, False), - ("decimal", CliFloat, False), ("bool", CliBoolean, False), - ("file", CliFile, False), ("path", CliFile, False), - ("input file", CliFile, False), - ("output file", CliFile, True), ("folder", CliDir, False), - ("directory", CliDir, False), - ("output directory", CliDir, False)] - - for ts in test_strings: - typ = infer_type(ts[0]) - assert isinstance(typ, ts[1]), "%s should be %s but is %s" % (ts[0], ts[1], typ) - assert not typ.hasattr("output") or typ.output == ts[2] +@pytest.mark.parametrize( + "string,typ,isoutput", + [("", CliString, False), ("int", CliInteger, False), + ("size", CliInteger, False), ("length", CliInteger, False), + ("max", CliInteger, False), ("min", CliInteger, False), + ("str", CliString, False), ("float", CliFloat, False), + ("decimal", CliFloat, False), ("bool", CliBoolean, False), + ("file", CliFile, False), ("path", CliFile, False), + ("input file", CliFile, False), + ("output file", CliFile, True), ("folder", CliDir, False), + ("directory", CliDir, False), + ("output directory", CliDir, False)]) +def test_type_inference(string, typ, isoutput): + result_typ = infer_type(string) + assert isinstance(result_typ, typ) + assert not result_typ.hasattr("output") or result_typ.output == isoutput From f74c77b370cf8187d1533cae08119c3300f1a4cf Mon Sep 17 00:00:00 2001 From: Matthias Bernt Date: Fri, 24 Jul 2020 12:39:29 +0200 Subject: [PATCH 04/18] subclass instead of property for outfiles/dirs --- acclimatise/cli_types.py | 20 ++++++++++++++++---- test/test_type_inference.py | 37 +++++++++++++++++++++---------------- 2 files changed, 37 insertions(+), 20 deletions(-) diff --git a/acclimatise/cli_types.py b/acclimatise/cli_types.py index 2e05582..c7cc67d 100644 --- a/acclimatise/cli_types.py +++ b/acclimatise/cli_types.py @@ -79,11 +79,17 @@ class CliDir(CliType): Takes a directory path """ - output: bool = None + pass + + +@dataclass(unsafe_hash=True) +class CliOutputDir(CliType): """ - Indicator if the file is input or output (None if unknown) + Takes a directory path """ + pass + @dataclass(unsafe_hash=True) class CliFile(CliType): @@ -91,11 +97,17 @@ class CliFile(CliType): Takes a file path """ - output: bool = None + pass + + +@dataclass(unsafe_hash=True) +class CliOutputFile(CliType): """ - Indicator if the file is input or output (None if unknown) + Takes a file path """ + pass + @dataclass(unsafe_hash=True) class CliDict(CliType): diff --git a/test/test_type_inference.py b/test/test_type_inference.py index 3ba6a70..77b4cc6 100644 --- a/test/test_type_inference.py +++ b/test/test_type_inference.py @@ -1,22 +1,27 @@ import pytest -from acclimatise.cli_types import CliString +from acclimatise.cli_types import CliBoolean, CliDir, CliFile, CliFloat, CliInteger, CliOutputDir, CliOutputFile, CliString from acclimatise.model import infer_type @pytest.mark.parametrize( - "string,typ,isoutput", - [("", CliString, False), ("int", CliInteger, False), - ("size", CliInteger, False), ("length", CliInteger, False), - ("max", CliInteger, False), ("min", CliInteger, False), - ("str", CliString, False), ("float", CliFloat, False), - ("decimal", CliFloat, False), ("bool", CliBoolean, False), - ("file", CliFile, False), ("path", CliFile, False), - ("input file", CliFile, False), - ("output file", CliFile, True), ("folder", CliDir, False), - ("directory", CliDir, False), - ("output directory", CliDir, False)]) -def test_type_inference(string, typ, isoutput): - result_typ = infer_type(string) - assert isinstance(result_typ, typ) - assert not result_typ.hasattr("output") or result_typ.output == isoutput + "string,typ", + [("", CliString), + ("int", CliInteger), + ("size", CliInteger), + ("length", CliInteger), + ("max", CliInteger), + ("min", CliInteger), + ("str", CliString), + ("float", CliFloat), + ("decimal", CliFloat), + ("bool", CliBoolean), + ("file", CliFile), + ("path", CliFile), + ("input file", CliFile), + ("output file", CliOutputFile), + ("folder", CliDir), + ("directory", CliDir), + ("output directory", CliOutputDir)]) +def test_type_inference(string, typ): + assert isinstance(infer_type(string), typ) From 5c77c4cf601d2ef6d08303f05a1c80df48a10159 Mon Sep 17 00:00:00 2001 From: Matthias Bernt Date: Fri, 24 Jul 2020 13:19:30 +0200 Subject: [PATCH 05/18] change subclassing --- acclimatise/cli_types.py | 20 ++++++----------- test/test_type_inference.py | 44 +++++++++++++++++++------------------ 2 files changed, 30 insertions(+), 34 deletions(-) diff --git a/acclimatise/cli_types.py b/acclimatise/cli_types.py index c7cc67d..19a6247 100644 --- a/acclimatise/cli_types.py +++ b/acclimatise/cli_types.py @@ -74,34 +74,28 @@ class CliBoolean(CliType): @dataclass(unsafe_hash=True) -class CliDir(CliType): +class CliFileSystemType(CliType): """ - Takes a directory path + Takes a directory / file path """ - pass - - -@dataclass(unsafe_hash=True) -class CliOutputDir(CliType): + output: bool = None """ - Takes a directory path + Indicator if it is input or output (None if unknown) """ - pass - @dataclass(unsafe_hash=True) -class CliFile(CliType): +class CliDir(CliFileSystemType): """ - Takes a file path + Takes a directory path """ pass @dataclass(unsafe_hash=True) -class CliOutputFile(CliType): +class CliFile(CliFileSystemType): """ Takes a file path """ diff --git a/test/test_type_inference.py b/test/test_type_inference.py index 77b4cc6..5e48192 100644 --- a/test/test_type_inference.py +++ b/test/test_type_inference.py @@ -1,27 +1,29 @@ import pytest -from acclimatise.cli_types import CliBoolean, CliDir, CliFile, CliFloat, CliInteger, CliOutputDir, CliOutputFile, CliString +from acclimatise.cli_types import CliBoolean, CliDir, CliFile, CliFloat, CliInteger, CliString from acclimatise.model import infer_type @pytest.mark.parametrize( - "string,typ", - [("", CliString), - ("int", CliInteger), - ("size", CliInteger), - ("length", CliInteger), - ("max", CliInteger), - ("min", CliInteger), - ("str", CliString), - ("float", CliFloat), - ("decimal", CliFloat), - ("bool", CliBoolean), - ("file", CliFile), - ("path", CliFile), - ("input file", CliFile), - ("output file", CliOutputFile), - ("folder", CliDir), - ("directory", CliDir), - ("output directory", CliOutputDir)]) -def test_type_inference(string, typ): - assert isinstance(infer_type(string), typ) + "string,typ,isoutput", + [("", CliString, False), + ("int", CliInteger, False), + ("size", CliInteger, False), + ("length", CliInteger, False), + ("max", CliInteger, False), + ("min", CliInteger, False), + ("str", CliString, False), + ("float", CliFloat, False), + ("decimal", CliFloat, False), + ("bool", CliBoolean, False), + ("file", CliFile, False), + ("path", CliFile, False), + ("input file", CliFile, False), + ("output file", CliFile, True), + ("folder", CliDir, False), + ("directory", CliDir, False), + ("output directory", CliDir, True)]) +def test_type_inference(string, typ, isoutput): + inferred_type = infer_type(string) + assert isinstance(inferred_type, typ) + assert not hasattr(inferred_type, "output") or inferred_type.output == isoutput From 3f55247c47eb4b8bcf989800033359e1e9696527 Mon Sep 17 00:00:00 2001 From: Matthias Bernt Date: Fri, 24 Jul 2020 13:39:07 +0200 Subject: [PATCH 06/18] search for regular expression (instead of match) --- acclimatise/model.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/acclimatise/model.py b/acclimatise/model.py index 1ff95f5..fce3d21 100644 --- a/acclimatise/model.py +++ b/acclimatise/model.py @@ -385,27 +385,27 @@ 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 """ - if bool_re.match(string): + if bool_re.search(string): return cli_types.CliBoolean() - elif float_re.match(string): + elif float_re.search(string): return cli_types.CliFloat() - elif int_re.match(string): + elif int_re.search(string): return cli_types.CliInteger() - elif file_re.match(string): - if input_re.match(string) and not output_re.match(string): + elif file_re.search(string): + if input_re.search(string) and not output_re.search(string): return cli_types.CliFile(output=False) - elif not input_re.match(string) and output_re.match(string): + elif not input_re.search(string) and output_re.search(string): return cli_types.CliFile(output=True) else: return cli_types.CliFile() - elif dir_re.match(string): - if input_re.match(string) and not output_re.match(string): + elif dir_re.search(string): + if input_re.search(string) and not output_re.search(string): return cli_types.CliDir(output=False) - elif not input_re.match(string) and output_re.match(string): + elif not input_re.search(string) and output_re.search(string): return cli_types.CliDir(output=True) else: return cli_types.CliDir() - elif str_re.match(string): + elif str_re.search(string): return cli_types.CliString() else: return None From b793b3610c02de7e8c5bca928ed53f3f4e2d407c Mon Sep 17 00:00:00 2001 From: Matthias Bernt Date: Fri, 24 Jul 2020 13:55:19 +0200 Subject: [PATCH 07/18] style improvenents --- test/test_type_inference.py | 46 ++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/test/test_type_inference.py b/test/test_type_inference.py index 5e48192..fb3f362 100644 --- a/test/test_type_inference.py +++ b/test/test_type_inference.py @@ -1,28 +1,38 @@ import pytest -from acclimatise.cli_types import CliBoolean, CliDir, CliFile, CliFloat, CliInteger, CliString +from acclimatise.cli_types import ( + CliBoolean, + CliDir, + CliFile, + CliFloat, + CliInteger, + CliString +) from acclimatise.model import infer_type @pytest.mark.parametrize( "string,typ,isoutput", - [("", CliString, False), - ("int", CliInteger, False), - ("size", CliInteger, False), - ("length", CliInteger, False), - ("max", CliInteger, False), - ("min", CliInteger, False), - ("str", CliString, False), - ("float", CliFloat, False), - ("decimal", CliFloat, False), - ("bool", CliBoolean, False), - ("file", CliFile, False), - ("path", CliFile, False), - ("input file", CliFile, False), - ("output file", CliFile, True), - ("folder", CliDir, False), - ("directory", CliDir, False), - ("output directory", CliDir, True)]) + [ + ("", CliString, False), + ("int", CliInteger, False), + ("size", CliInteger, False), + ("length", CliInteger, False), + ("max", CliInteger, False), + ("min", CliInteger, False), + ("str", CliString, False), + ("float", CliFloat, False), + ("decimal", CliFloat, False), + ("bool", CliBoolean, False), + ("file", CliFile, False), + ("path", CliFile, False), + ("input file", CliFile, False), + ("output file", CliFile, True), + ("folder", CliDir, False), + ("directory", CliDir, False), + ("output directory", CliDir, True) + ] +) def test_type_inference(string, typ, isoutput): inferred_type = infer_type(string) assert isinstance(inferred_type, typ) From 186e567548294cef08a9110bd3a14fb1010183fc Mon Sep 17 00:00:00 2001 From: Matthias Bernt Date: Fri, 24 Jul 2020 15:02:08 +0200 Subject: [PATCH 08/18] don't search for read guess its to unspecific --- acclimatise/model.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/acclimatise/model.py b/acclimatise/model.py index fce3d21..a9d42af 100644 --- a/acclimatise/model.py +++ b/acclimatise/model.py @@ -375,8 +375,8 @@ def capital(self): float_re = re.compile("float|decimal", flags=re.IGNORECASE) bool_re = re.compile("bool(ean)?", flags=re.IGNORECASE) file_re = re.compile("file|path", flags=re.IGNORECASE) -input_re = re.compile("read|in(put)?", flags=re.IGNORECASE) -output_re = re.compile("write|out(put)?", flags=re.IGNORECASE) +input_re = re.compile("input", flags=re.IGNORECASE) +output_re = re.compile("output", flags=re.IGNORECASE) dir_re = re.compile("folder|directory", flags=re.IGNORECASE) From 83692f16610f54d9d42136487b29404c3528127b Mon Sep 17 00:00:00 2001 From: Matthias Bernt Date: Fri, 24 Jul 2020 15:11:38 +0200 Subject: [PATCH 09/18] styling --- test/test_type_inference.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/test_type_inference.py b/test/test_type_inference.py index fb3f362..a9cfcf4 100644 --- a/test/test_type_inference.py +++ b/test/test_type_inference.py @@ -6,7 +6,7 @@ CliFile, CliFloat, CliInteger, - CliString + CliString, ) from acclimatise.model import infer_type @@ -30,8 +30,8 @@ ("output file", CliFile, True), ("folder", CliDir, False), ("directory", CliDir, False), - ("output directory", CliDir, True) - ] + ("output directory", CliDir, True), + ], ) def test_type_inference(string, typ, isoutput): inferred_type = infer_type(string) From 21d0b605b65d27c33e9d95af30d6ebfc9fefabdb Mon Sep 17 00:00:00 2001 From: Matthias Bernt Date: Fri, 24 Jul 2020 16:15:51 +0200 Subject: [PATCH 10/18] fix tests --- test/test_type_inference.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/test_type_inference.py b/test/test_type_inference.py index a9cfcf4..ed7f8b9 100644 --- a/test/test_type_inference.py +++ b/test/test_type_inference.py @@ -24,12 +24,12 @@ ("float", CliFloat, False), ("decimal", CliFloat, False), ("bool", CliBoolean, False), - ("file", CliFile, False), - ("path", CliFile, False), + ("file", CliFile, None), + ("path", CliFile, None), ("input file", CliFile, False), ("output file", CliFile, True), - ("folder", CliDir, False), - ("directory", CliDir, False), + ("folder", CliDir, None), + ("directory", CliDir, None), ("output directory", CliDir, True), ], ) From 50f8493bc57b532d3347b4d108eaa5272bd0f0bd Mon Sep 17 00:00:00 2001 From: Matthias Bernt Date: Fri, 24 Jul 2020 17:23:59 +0200 Subject: [PATCH 11/18] require word boundaries for menay regular expressions seems more useful when searching instead of matching --- acclimatise/model.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/acclimatise/model.py b/acclimatise/model.py index a9d42af..7eeb40e 100644 --- a/acclimatise/model.py +++ b/acclimatise/model.py @@ -370,14 +370,18 @@ def capital(self): ) -int_re = re.compile("(int(eger)?)|size|length|max|min", 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) -file_re = re.compile("file|path", flags=re.IGNORECASE) -input_re = re.compile("input", flags=re.IGNORECASE) -output_re = re.compile("output", flags=re.IGNORECASE) -dir_re = re.compile("folder|directory", flags=re.IGNORECASE) +int_re = re.compile(r"\b((int(eger)?)|size|length|max|min|num(ber)?)\b", flags=re.IGNORECASE) +str_re = re.compile(r"\bstr(ing)?\b", flags=re.IGNORECASE) +float_re = re.compile(r"\b(float|decimal)\b", flags=re.IGNORECASE) +bool_re = re.compile(r"\bbool(ean)?\b", flags=re.IGNORECASE) +file_re = re.compile(r"\b(file|path)\b", flags=re.IGNORECASE) +input_re = re.compile(r"input", flags=re.IGNORECASE) +output_re = re.compile(r"output", flags=re.IGNORECASE) +dir_re = re.compile(r"\b(folder|directory)\b", flags=re.IGNORECASE) + +default_re = re.compile(r"default(?: value)?(?:[:=] ?| )([^ )\]]+)", flags=re.IGNORECASE) +float_re = re.compile(r'[+-]?([0-9]+([.][0-9]*)?|[.][0-9]+)', flags=re.IGNORECASE) +int_re = re.compile(r'[+-]?([0-9]+[^.0-9])', flags=re.IGNORECASE) def infer_type(string) -> typing.Optional[cli_types.CliType]: From edb232286dc6e225c419a763af77409bf61bcf89 Mon Sep 17 00:00:00 2001 From: Matthias Bernt Date: Fri, 24 Jul 2020 17:35:57 +0200 Subject: [PATCH 12/18] style improvements --- acclimatise/model.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/acclimatise/model.py b/acclimatise/model.py index 7eeb40e..85a2c11 100644 --- a/acclimatise/model.py +++ b/acclimatise/model.py @@ -370,7 +370,9 @@ def capital(self): ) -int_re = re.compile(r"\b((int(eger)?)|size|length|max|min|num(ber)?)\b", flags=re.IGNORECASE) +int_re = re.compile( + r"\b((int(eger)?)|size|length|max|min|num(ber)?)\b", flags=re.IGNORECASE +) str_re = re.compile(r"\bstr(ing)?\b", flags=re.IGNORECASE) float_re = re.compile(r"\b(float|decimal)\b", flags=re.IGNORECASE) bool_re = re.compile(r"\bbool(ean)?\b", flags=re.IGNORECASE) @@ -379,9 +381,11 @@ def capital(self): output_re = re.compile(r"output", flags=re.IGNORECASE) dir_re = re.compile(r"\b(folder|directory)\b", flags=re.IGNORECASE) -default_re = re.compile(r"default(?: value)?(?:[:=] ?| )([^ )\]]+)", flags=re.IGNORECASE) -float_re = re.compile(r'[+-]?([0-9]+([.][0-9]*)?|[.][0-9]+)', flags=re.IGNORECASE) -int_re = re.compile(r'[+-]?([0-9]+[^.0-9])', flags=re.IGNORECASE) +default_re = re.compile( + r"default(?: value)?(?:[:=] ?| )([^ )\]]+)", flags=re.IGNORECASE +) +float_re = re.compile(r"[+-]?([0-9]+([.][0-9]*)?|[.][0-9]+)", flags=re.IGNORECASE) +int_re = re.compile(r"[+-]?([0-9]+[^.0-9])", flags=re.IGNORECASE) def infer_type(string) -> typing.Optional[cli_types.CliType]: From 6e99ddc9c61b7fa49aaede4ec5e8c6970d284567 Mon Sep 17 00:00:00 2001 From: Matthias Bernt Date: Mon, 27 Jul 2020 16:03:40 +0200 Subject: [PATCH 13/18] recognize int and float options if there is a int/float --- acclimatise/model.py | 17 +++++++++++++---- test/test_type_inference.py | 4 ++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/acclimatise/model.py b/acclimatise/model.py index 85a2c11..2055cf9 100644 --- a/acclimatise/model.py +++ b/acclimatise/model.py @@ -371,7 +371,7 @@ def capital(self): int_re = re.compile( - r"\b((int(eger)?)|size|length|max|min|num(ber)?)\b", flags=re.IGNORECASE + r"\b((int(eger)?)|size|length|max|min|(num(ber)?))\b", flags=re.IGNORECASE ) str_re = re.compile(r"\bstr(ing)?\b", flags=re.IGNORECASE) float_re = re.compile(r"\b(float|decimal)\b", flags=re.IGNORECASE) @@ -384,8 +384,11 @@ def capital(self): default_re = re.compile( r"default(?: value)?(?:[:=] ?| )([^ )\]]+)", flags=re.IGNORECASE ) -float_re = re.compile(r"[+-]?([0-9]+([.][0-9]*)?|[.][0-9]+)", flags=re.IGNORECASE) -int_re = re.compile(r"[+-]?([0-9]+[^.0-9])", flags=re.IGNORECASE) +float_num_re = re.compile( + r"[+-]?(([0-9]*\.[0-9]+)|((?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)))", + flags=re.IGNORECASE, +) +int_num_re = re.compile(r"([+-]?[0-9]+)", flags=re.IGNORECASE) def infer_type(string) -> typing.Optional[cli_types.CliType]: @@ -416,7 +419,13 @@ def infer_type(string) -> typing.Optional[cli_types.CliType]: elif str_re.search(string): return cli_types.CliString() else: - return None + if float_num_re.search(string): + return cli_types.CliFloat() + elif int_num_re.search(string): + print("int num") + return cli_types.CliInteger() + else: + return None @yaml_object(yaml) diff --git a/test/test_type_inference.py b/test/test_type_inference.py index ed7f8b9..7f6cb1c 100644 --- a/test/test_type_inference.py +++ b/test/test_type_inference.py @@ -31,6 +31,10 @@ ("folder", CliDir, None), ("directory", CliDir, None), ("output directory", CliDir, True), + ("blah 23 blub", CliInteger, False), + ("nonsense 23.42", CliFloat, True), + (".42 gibberish", CliFloat, True), + ("1E-5", CliFloat, True), ], ) def test_type_inference(string, typ, isoutput): From 5b39972c28ef8aac1e7d232539473147c6f31b97 Mon Sep 17 00:00:00 2001 From: Matthias Bernt Date: Tue, 28 Jul 2020 10:51:30 +0200 Subject: [PATCH 14/18] simplify test --- test/test_type_inference.py | 49 ++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/test/test_type_inference.py b/test/test_type_inference.py index 7f6cb1c..432b2ff 100644 --- a/test/test_type_inference.py +++ b/test/test_type_inference.py @@ -12,32 +12,31 @@ @pytest.mark.parametrize( - "string,typ,isoutput", + "string,typ", [ - ("", CliString, False), - ("int", CliInteger, False), - ("size", CliInteger, False), - ("length", CliInteger, False), - ("max", CliInteger, False), - ("min", CliInteger, False), - ("str", CliString, False), - ("float", CliFloat, False), - ("decimal", CliFloat, False), - ("bool", CliBoolean, False), - ("file", CliFile, None), - ("path", CliFile, None), - ("input file", CliFile, False), - ("output file", CliFile, True), - ("folder", CliDir, None), - ("directory", CliDir, None), - ("output directory", CliDir, True), - ("blah 23 blub", CliInteger, False), - ("nonsense 23.42", CliFloat, True), - (".42 gibberish", CliFloat, True), - ("1E-5", CliFloat, True), + ("", None), + ("int", CliInteger()), + ("size", CliInteger()), + ("length", CliInteger()), + ("max", CliInteger()), + ("min", CliInteger()), + ("str", CliString()), + ("float", CliFloat()), + ("decimal", CliFloat()), + ("bool", CliBoolean()), + ("file", CliFile()), + ("path", CliFile()), + ("input file", CliFile(output=False)), + ("output file", CliFile(output=True)), + ("folder", CliDir()), + ("directory", CliDir()), + ("output directory", CliDir(output=True)), + ("blah 23 blub", CliInteger()), + ("nonsense 23.42", CliFloat()), + (".42 gibberish", CliFloat()), + ("1E-5", CliFloat()), ], ) -def test_type_inference(string, typ, isoutput): +def test_type_inference(string, typ): inferred_type = infer_type(string) - assert isinstance(inferred_type, typ) - assert not hasattr(inferred_type, "output") or inferred_type.output == isoutput + assert inferred_type == typ From a4ff588623fcc6cfcccdad68d38a107cab040898 Mon Sep 17 00:00:00 2001 From: Matthias Bernt Date: Tue, 28 Jul 2020 10:54:07 +0200 Subject: [PATCH 15/18] move default_re to correct branch and remove leftover debug print statement --- acclimatise/model.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/acclimatise/model.py b/acclimatise/model.py index 2055cf9..a6975e2 100644 --- a/acclimatise/model.py +++ b/acclimatise/model.py @@ -381,9 +381,6 @@ def capital(self): output_re = re.compile(r"output", flags=re.IGNORECASE) dir_re = re.compile(r"\b(folder|directory)\b", flags=re.IGNORECASE) -default_re = re.compile( - r"default(?: value)?(?:[:=] ?| )([^ )\]]+)", flags=re.IGNORECASE -) float_num_re = re.compile( r"[+-]?(([0-9]*\.[0-9]+)|((?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)))", flags=re.IGNORECASE, @@ -422,7 +419,6 @@ def infer_type(string) -> typing.Optional[cli_types.CliType]: if float_num_re.search(string): return cli_types.CliFloat() elif int_num_re.search(string): - print("int num") return cli_types.CliInteger() else: return None From 7a9890377cf316b5eccbbb7c68eefb0d5cb8ff03 Mon Sep 17 00:00:00 2001 From: Matthias Bernt Date: Tue, 28 Jul 2020 11:01:43 +0200 Subject: [PATCH 16/18] check for integer and float values in the main if statement --- acclimatise/model.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/acclimatise/model.py b/acclimatise/model.py index a6975e2..9dd3d7d 100644 --- a/acclimatise/model.py +++ b/acclimatise/model.py @@ -415,13 +415,12 @@ def infer_type(string) -> typing.Optional[cli_types.CliType]: return cli_types.CliDir() elif str_re.search(string): return cli_types.CliString() + elif float_num_re.search(string): + return cli_types.CliFloat() + elif int_num_re.search(string): + return cli_types.CliInteger() else: - if float_num_re.search(string): - return cli_types.CliFloat() - elif int_num_re.search(string): - return cli_types.CliInteger() - else: - return None + return None @yaml_object(yaml) From 7aaac45926a50efd04301ff96599e252b0bb4d58 Mon Sep 17 00:00:00 2001 From: Matthias Bernt Date: Tue, 28 Jul 2020 11:22:02 +0200 Subject: [PATCH 17/18] add distinguish_inout foo to avoid code duplication --- acclimatise/model.py | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/acclimatise/model.py b/acclimatise/model.py index 9dd3d7d..dac183f 100644 --- a/acclimatise/model.py +++ b/acclimatise/model.py @@ -388,6 +388,20 @@ def capital(self): int_num_re = re.compile(r"([+-]?[0-9]+)", flags=re.IGNORECASE) +def distinguish_inout(string, cls) -> cli_types.CliFileSystemType: + """ + distinguish input/output files/directories given a string + """ + im = input_re.search(string) + om = output_re.search(string) + if im and not om: + return cls(output=False) + elif not im and om: + return cls(output=True) + else: + return cls() + + 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 @@ -400,19 +414,9 @@ def infer_type(string) -> typing.Optional[cli_types.CliType]: elif int_re.search(string): return cli_types.CliInteger() elif file_re.search(string): - if input_re.search(string) and not output_re.search(string): - return cli_types.CliFile(output=False) - elif not input_re.search(string) and output_re.search(string): - return cli_types.CliFile(output=True) - else: - return cli_types.CliFile() + return distinguish_inout(string, cli_types.CliFile) elif dir_re.search(string): - if input_re.search(string) and not output_re.search(string): - return cli_types.CliDir(output=False) - elif not input_re.search(string) and output_re.search(string): - return cli_types.CliDir(output=True) - else: - return cli_types.CliDir() + return distinguish_inout(string, cli_types.CliDir) elif str_re.search(string): return cli_types.CliString() elif float_num_re.search(string): From 40fbc688ce95c3ad21f7c473a04c0f82da68be55 Mon Sep 17 00:00:00 2001 From: Matthias Bernt Date: Mon, 24 Aug 2020 15:33:02 +0200 Subject: [PATCH 18/18] do not use unknown in/out --- acclimatise/cli_types.py | 4 ++-- acclimatise/model.py | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/acclimatise/cli_types.py b/acclimatise/cli_types.py index 19a6247..602b6df 100644 --- a/acclimatise/cli_types.py +++ b/acclimatise/cli_types.py @@ -79,9 +79,9 @@ class CliFileSystemType(CliType): Takes a directory / file path """ - output: bool = None + output: bool = False """ - Indicator if it is input or output (None if unknown) + Indicator if it is input or output """ diff --git a/acclimatise/model.py b/acclimatise/model.py index dac183f..e5e088e 100644 --- a/acclimatise/model.py +++ b/acclimatise/model.py @@ -388,18 +388,18 @@ def capital(self): int_num_re = re.compile(r"([+-]?[0-9]+)", flags=re.IGNORECASE) -def distinguish_inout(string, cls) -> cli_types.CliFileSystemType: +def distinguish_inout( + string, cls: typing.Type[cli_types.CliFileSystemType] +) -> cli_types.CliFileSystemType: """ distinguish input/output files/directories given a string """ im = input_re.search(string) om = output_re.search(string) - if im and not om: - return cls(output=False) - elif not im and om: + if not im and om: return cls(output=True) else: - return cls() + return cls(output=False) def infer_type(string) -> typing.Optional[cli_types.CliType]: