diff --git a/tabcmd/execution/global_options.py b/tabcmd/execution/global_options.py index 1a24133c..e9e29009 100644 --- a/tabcmd/execution/global_options.py +++ b/tabcmd/execution/global_options.py @@ -111,11 +111,31 @@ def set_embedded_datasources_options(parser): # used in create extract. listed in delete-extract but makes no sense there +def _parse_yes_no(value: str) -> bool: + # tabcmd Classic accepted "yes"/"no"/"true"/"false" on --encrypt; tabcmd 2 + # kept the flag but silently ignored a following value. Accept the Classic + # forms so scripts port cleanly. + lowered = value.strip().lower() + if lowered in ("yes", "true", "1"): + return True + if lowered in ("no", "false", "0"): + return False + import argparse + + raise argparse.ArgumentTypeError("Expected yes/no/true/false for --encrypt, got {!r}".format(value)) + + def set_encryption_option(parser): parser.add_argument( "--encrypt", dest="encrypt", - action="store_true", # set to true IF user passes in option --encrypt + # Classic parity: --encrypt yes / --encrypt no. Bare --encrypt still + # means True (default tabcmd 2 behavior). Omitted -> False. + nargs="?", + const=True, + default=False, + type=_parse_yes_no, + metavar="yes|no", help=_("createextracts.options.encrypt"), ) return parser diff --git a/tests/parsers/test_parser_create_extracts.py b/tests/parsers/test_parser_create_extracts.py index 94ca7a7e..0486f2d8 100644 --- a/tests/parsers/test_parser_create_extracts.py +++ b/tests/parsers/test_parser_create_extracts.py @@ -106,3 +106,39 @@ def test_create_extract_parser_missing_embedded_datasources(self): ] with self.assertRaises(SystemExit): args = self.parser_under_test.parse_args(mock_args) + + # --encrypt Classic-parity: accepts yes|no|true|false, bare flag still True, omitted False + def _base_args(self): + return [commandname, "--datasource", "ds", "--project", "p", "--parent-project-path", "pp"] + + def test_encrypt_omitted_is_false(self): + args = self.parser_under_test.parse_args(self._base_args()) + assert args.encrypt is False, args + + def test_encrypt_bare_flag_is_true(self): + args = self.parser_under_test.parse_args(self._base_args() + ["--encrypt"]) + assert args.encrypt is True, args + + def test_encrypt_yes_is_true(self): + args = self.parser_under_test.parse_args(self._base_args() + ["--encrypt", "yes"]) + assert args.encrypt is True, args + + def test_encrypt_no_is_false(self): + args = self.parser_under_test.parse_args(self._base_args() + ["--encrypt", "no"]) + assert args.encrypt is False, args + + def test_encrypt_true_is_true(self): + args = self.parser_under_test.parse_args(self._base_args() + ["--encrypt", "true"]) + assert args.encrypt is True, args + + def test_encrypt_false_is_false(self): + args = self.parser_under_test.parse_args(self._base_args() + ["--encrypt", "false"]) + assert args.encrypt is False, args + + def test_encrypt_case_insensitive(self): + args = self.parser_under_test.parse_args(self._base_args() + ["--encrypt", "YES"]) + assert args.encrypt is True, args + + def test_encrypt_bad_value_rejected(self): + with self.assertRaises(SystemExit): + self.parser_under_test.parse_args(self._base_args() + ["--encrypt", "maybe"])