diff --git a/argunparse/argument_unparser.py b/argunparse/argument_unparser.py index b3e0649..520d361 100644 --- a/argunparse/argument_unparser.py +++ b/argunparse/argument_unparser.py @@ -19,11 +19,10 @@ def option_should_be_skipped(value: t.Any) -> bool: class ArgumentUnparser: """For performing reverse operation to what argparse.ArgumentParser does.""" - # pylint: disable = too-many-arguments + # pylint: disable = too-many-arguments, too-many-positional-arguments def __init__( self, short_opt: str = '-', long_opt: str = '--', opt_value: str = '=', begin_delim: str = '"', end_delim: str = '"') -> None: - assert isinstance(short_opt, str) assert isinstance(long_opt, str) assert isinstance(opt_value, str) @@ -46,78 +45,66 @@ def unparse_arg(self, arg: t.Any) -> str: # pylint: disable = no-self-use arg = '""' return arg - def unparse_args(self, arguments: t.Sequence[t.Any], - *, to_list: bool = False) -> t.Union[str, t.List[str]]: - """Convert list to string of command-line args.""" + def unparse_args_to_list(self, arguments: t.Sequence[t.Any]) -> list[str]: + """Convert list of objects to a list of command-line args.""" unparsed_list = [] for arg in arguments: unparsed_list.append(self.unparse_arg(arg)) _LOG.debug('%s: unparsed args to %s', self, unparsed_list) - if to_list: - return unparsed_list - unparsed = ' '.join(unparsed_list) + return unparsed_list + + def unparse_args(self, arguments: t.Sequence[t.Any]) -> str: + """Convert list to string of command-line args.""" + unparsed = ' '.join(self.unparse_args_to_list(arguments)) _LOG.debug('%s: converted unparsed args to string "%s"', self, unparsed) return unparsed - def unparse_option(self, key: str, value: t.Any, - *, to_list: bool = False) -> t.Union[str, t.List[str]]: - """Convert a key-value pair into a string that can be used as a command-line option.""" + def unparse_option_to_list(self, key: str, value: t.Any) -> list[str]: + """Convert a key-value pair into a short list to be used as a command-line option.""" if option_should_be_skipped(value): - return [] if to_list else '' + return [] unparsed_key = f'{self._long_opt if len(key) > 1 else self._short_opt}{key}' - if not treat_as_option_with_no_value(value): - unparsed_value = self.unparse_arg(value) - if to_list and (self._opt_value == ' ' or treat_as_option_with_no_value(value)): - if treat_as_option_with_no_value(value): - return [unparsed_key] - return [unparsed_key, unparsed_value] - if not treat_as_option_with_no_value(value): - unparsed_option = f'{unparsed_key}{self._opt_value}{unparsed_value}' - if to_list: - return [unparsed_option] if treat_as_option_with_no_value(value): - return unparsed_key - return unparsed_option + return [unparsed_key] + unparsed_value = self.unparse_arg(value) + if self._opt_value == ' ': + return [unparsed_key, unparsed_value] + return [f'{unparsed_key}{self._opt_value}{unparsed_value}'] - def unparse_options(self, options: t.Mapping[str, t.Any], - *, to_list: bool = False) -> t.Union[str, t.List[str]]: - """Convert dictionary to string of command-line args.""" + def unparse_option(self, key: str, value: t.Any) -> str: + """Convert a key-value pair into a string that can be used as a command-line option.""" + if option_should_be_skipped(value): + return '' + unparsed = ' '.join(self.unparse_option_to_list(key, value)) + return unparsed + + def unparse_options_to_list(self, options: t.Mapping[str, t.Any]) -> list[str]: + """Convert dictionary to a list of command-line args.""" unparsed_list: t.List[str] = [] for key, value in options.items(): if option_should_be_skipped(value): continue - unparsed_option = self.unparse_option(key, value, to_list=to_list) - if to_list: - unparsed_list += unparsed_option - else: - assert isinstance(unparsed_option, str), type(unparsed_option) - unparsed_list.append(unparsed_option) + unparsed_list += self.unparse_option_to_list(key, value) _LOG.debug('%s: unparsed options to %s', self, unparsed_list) - if to_list: - return unparsed_list - unparsed = ' '.join(unparsed_list) + return unparsed_list + + def unparse_options(self, options: t.Mapping[str, t.Any]) -> str: + """Convert dictionary to string of command-line args.""" + unparsed = ' '.join(self.unparse_options_to_list(options)) _LOG.debug('%s: converted unparsed options to string "%s"', self, unparsed) return unparsed - def unparse_options_and_args(self, options: t.Mapping[str, t.Any], arguments: t.Sequence[t.Any], - *, to_list: bool = False) -> t.Union[str, t.List[str]]: + def unparse_options_and_args_to_list( + self, options: t.Mapping[str, t.Any], arguments: t.Sequence[t.Any]) -> list[str]: + """Convert dictionary and list to a list of command-line args.""" + unparsed_options = [] if options is None else self.unparse_options_to_list(options) + unparsed_args = [] if arguments is None else self.unparse_args_to_list(arguments) + return unparsed_options + unparsed_args + + def unparse_options_and_args( + self, options: t.Mapping[str, t.Any], arguments: t.Sequence[t.Any]) -> str: """Convert dictionary and list to string of command-line args.""" - if options is None: - unparsed_options = [] if to_list else '' - else: - unparsed_options = self.unparse_options(options, to_list=to_list) - if arguments is None: - unparsed_args = [] if to_list else '' - else: - unparsed_args = self.unparse_args(arguments, to_list=to_list) - if to_list: - return unparsed_options + unparsed_args - unparsed = [] - if unparsed_options: - unparsed.append(unparsed_options) - if unparsed_args: - unparsed.append(unparsed_args) - return ' '.join(unparsed) + return ' '.join(self.unparse_options_and_args_to_list(options, arguments)) def unparse_to_list(self, *args, **kwargs) -> list: """Unparse given args as command-line arguments and kwargs as command-line options. @@ -126,7 +113,7 @@ def unparse_to_list(self, *args, **kwargs) -> list: This process is a reverse of what built-in argparse module does with parse_args() method. """ - return self.unparse_options_and_args(kwargs, args, to_list=True) + return self.unparse_options_and_args_to_list(kwargs, args) def unparse(self, *args, **kwargs) -> str: """Unparse given args as command-line arguments and kwargs as command-line options. diff --git a/requirements_test.txt b/requirements_test.txt index 7b7b701..bcc1eb5 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -1,2 +1,2 @@ -r requirements.txt -boilerplates[logging,packaging_tests] ~= 1.2 +boilerplates[logging,packaging-tests] ~= 1.2 diff --git a/test/examples.py b/test/examples.py index 07a963b..0f2332c 100644 --- a/test/examples.py +++ b/test/examples.py @@ -3,13 +3,14 @@ import collections import itertools import pathlib +import typing as t _UNPARSER_INIT_ARGS_EXAMPLES = [ ('short_opt', {'-', '--', '_', '__'}), ('long_opt', {'-', '--', '_', '__'}), ('opt_value', {'=', ' ', ''})] -OPTIONS = { +OPTIONS: dict[str, dict[str, t.Any]] = { '-h': {'h': True}, '--verbosity=100': {'verbosity': 100}, '--DEFINE=NDEBUG': {'DEFINE': 'NDEBUG'}, '--long_flag': {'long_flag': True}, '-o=out_file.txt': {'o': 'out_file.txt'}, @@ -35,8 +36,6 @@ ('-123456790', -123456790), (str(2**16), 2**16), ('x', 'x'), ('y', 'y'), ('z', 'z'), (repr('hello world'), 'hello world')} -ARGUMENTS_SKIPPED = {} - ARGUMENTS_VARIANTS = [([ref1, ref2], [arg1, arg2]) for ((ref1, arg1), (ref2, arg2)) in itertools.permutations(ARGUMENTS, 2)] diff --git a/test/test_argument_unparser.py b/test/test_argument_unparser.py index 6868d1e..c394ffa 100644 --- a/test/test_argument_unparser.py +++ b/test/test_argument_unparser.py @@ -24,30 +24,30 @@ def test_option(self): for reference, option in OPTIONS.items(): with self.subTest(option=option): key, value = list(*itertools.chain(option.items())) + list_result = unparser.unparse_option_to_list(key, value) + self.assertListEqual([reference], list_result) result = unparser.unparse_option(key, value) self.assertEqual(reference, result) - list_result = unparser.unparse_option(key, value, to_list=True) - self.assertListEqual([reference], list_result) def test_option_skipped(self): unparser = ArgumentUnparser() for option in OPTIONS_SKIPPED.items(): with self.subTest(option=option): key, value = option + list_result = unparser.unparse_option_to_list(key, value) + self.assertListEqual(list_result, []) result = unparser.unparse_option(key, value) self.assertEqual(result, '') - list_result = unparser.unparse_option(key, value, to_list=True) - self.assertListEqual(list_result, []) def test_option_space(self): unparser = ArgumentUnparser(opt_value=' ') for reference, option in OPTIONS.items(): with self.subTest(option=option): key, value = list(*itertools.chain(option.items())) + list_result = unparser.unparse_option_to_list(key, value) + self.assertListEqual(reference.split('='), list_result) result = unparser.unparse_option(key, value) self.assertEqual(reference.replace('=', ' '), result) - list_result = unparser.unparse_option(key, value, to_list=True) - self.assertListEqual(reference.split('='), list_result) def test_options(self): _LOG.debug('testing %i option variants...', @@ -55,10 +55,10 @@ def test_options(self): unparser = ArgumentUnparser() for reference, options in itertools.chain(OPTIONS_VARIANTS, OPTIONS_SKIPPED_VARIANTS): with self.subTest(options=options): + list_result = unparser.unparse_options_to_list(options) + self.assertListEqual(reference, list_result) result = unparser.unparse_options(options) self.assertEqual(' '.join(reference), result) - list_result = unparser.unparse_options(options, to_list=True) - self.assertListEqual(reference, list_result) def test_options_space(self): _LOG.debug('testing %i option variants...', @@ -68,7 +68,7 @@ def test_options_space(self): with self.subTest(options=options): result = unparser.unparse_options(options) self.assertEqual(' '.join(reference).replace('=', ' '), result) - list_result = unparser.unparse_options(options, to_list=True) + list_result = unparser.unparse_options_to_list(options) fixed_reference = list(itertools.chain.from_iterable( [_.split('=') if '=' in _ else [_] for _ in reference])) self.assertListEqual(fixed_reference, list_result) @@ -84,30 +84,30 @@ def test_args(self): unparser = ArgumentUnparser() for reference, args in ARGUMENTS_VARIANTS: with self.subTest(args=args): + list_result = unparser.unparse_args_to_list(args) + self.assertListEqual(reference, list_result) result = unparser.unparse_args(args) self.assertEqual(' '.join(reference), result) - list_result = unparser.unparse_args(args, to_list=True) - self.assertListEqual(reference, list_result) def test_options_and_args(self): unparser = ArgumentUnparser() for (reference_options, options), (reference_args, args) in OPTIONS_AND_ARGUMENTS_VARIANTS: with self.subTest(options=options, args=args): + list_result = unparser.unparse_options_and_args_to_list(None, args) + self.assertListEqual(reference_args, list_result) result = unparser.unparse_options_and_args(None, args) self.assertEqual(' '.join(reference_args), result) - list_result = unparser.unparse_options_and_args(None, args, to_list=True) - self.assertListEqual(reference_args, list_result) + list_result = unparser.unparse_options_and_args_to_list(options, None) + self.assertListEqual(reference_options, list_result) result = unparser.unparse_options_and_args(options, None) self.assertEqual(' '.join(reference_options), result) - list_result = unparser.unparse_options_and_args(options, None, to_list=True) - self.assertListEqual(reference_options, list_result) + list_result = unparser.unparse_options_and_args_to_list(options, args) + self.assertListEqual(reference_options + reference_args, list_result) result = unparser.unparse_options_and_args(options, args) self.assertEqual( ' '.join(itertools.chain(reference_options, reference_args)), result) - list_result = unparser.unparse_options_and_args(options, args, to_list=True) - self.assertListEqual(reference_options + reference_args, list_result) def test_unparse(self): unparser = ArgumentUnparser()