From 43ada4a220ca42e3e00d36b961caf8d8574ddd7b Mon Sep 17 00:00:00 2001 From: Stephen Tomkinson Date: Mon, 10 Aug 2020 11:45:35 +0100 Subject: [PATCH] Added test for parent inheritance behaviour and made "widgets" behave the same as "defaults" for duplicate named arguments. --- gooey/python_bindings/gooey_parser.py | 10 ++- gooey/tests/test_parent_inheritance.py | 86 ++++++++++++++++++++++++++ 2 files changed, 94 insertions(+), 2 deletions(-) create mode 100644 gooey/tests/test_parent_inheritance.py diff --git a/gooey/python_bindings/gooey_parser.py b/gooey/python_bindings/gooey_parser.py index bb26da9..8524603 100644 --- a/gooey/python_bindings/gooey_parser.py +++ b/gooey/python_bindings/gooey_parser.py @@ -93,8 +93,14 @@ class GooeyParser(object): action = self.parser.add_argument(*args, **kwargs) self.parser._actions[-1].metavar = metavar - self.widgets[self.parser._actions[-1].dest] = widget - self.options[self.parser._actions[-1].dest] = options + + action_dest = self.parser._actions[-1].dest + if action_dest not in self.widgets or self.widgets[action_dest] is None: + self.widgets[action_dest] = widget + + if action_dest not in self.options or self.options[action_dest] is None: + self.options[self.parser._actions[-1].dest] = options + self._validate_constraints( self.parser._actions[-1], widget, diff --git a/gooey/tests/test_parent_inheritance.py b/gooey/tests/test_parent_inheritance.py new file mode 100644 index 0000000..b53d711 --- /dev/null +++ b/gooey/tests/test_parent_inheritance.py @@ -0,0 +1,86 @@ +import argparse +import unittest + +from gooey import GooeyParser + + +class TestParentInheritance(unittest.TestCase): + + def test_parent_arguments_exist_in_child(self): + """ + Verifies that the parents parameter is honoured. + """ + base_parser = GooeyParser(add_help=False) + base_parser.add_argument("a_file", widget="FileChooser") + + parser = GooeyParser(parents=[base_parser]) + parser.add_argument("b_file", widget="DirChooser") + + found = 0 + for action in parser._actions: + if action.dest == "a_file": + found += 1 + elif action.dest == "b_file": + found += 1 + + self.assertEquals(2, found, "Did not find 2 expected arguments, found " + str(found)) + self.assertEquals(parser.widgets["a_file"], "FileChooser") + self.assertEquals(parser.widgets["b_file"], "DirChooser") + + def test_parent_arguments_are_not_overridden(self): + """ + Verifies that the same named argument in a parent and child parser is accepted, and only the child + parser survives. + """ + # Verify how vanilla argparse works + base_parser = argparse.ArgumentParser(add_help=False) + action1 = base_parser.add_argument("a_file", default="a") + + parser = argparse.ArgumentParser(parents=[base_parser]) + action2 = parser.add_argument("a_file", default="b") + + self._verify_duplicate_parameters(action1, action2, parser) + # So a child can't override a parent - this isn't textbook inheritance + + # Run the same test on GooeyParser + base_parser = GooeyParser(add_help=False) + action1 = base_parser.add_argument("a_file", widget="FileChooser", default="a") + + parser = GooeyParser(parents=[base_parser]) + action2 = parser.add_argument("a_file", widget="DirChooser", default="b") + + self._verify_duplicate_parameters(action1, action2, parser) + self.assertEquals(parser.widgets["a_file"], "FileChooser") + + def test_duplicates_on_same_parser_are_ignored(self): + """ + Verify that adding duplicate named arguments works the same in argparse and Gooey. + Assuming the behaviour of the "default" parameter is a good match for the "widget" parameter. + """ + + # Verify how vanilla argparse works + parser = argparse.ArgumentParser() + action1 = parser.add_argument("a_file", default="a") + action2 = parser.add_argument("a_file", default="b") + + self._verify_duplicate_parameters(action1, action2, parser) + + # Run the same test on GooeyParser + parser = GooeyParser() + action1 = parser.add_argument("a_file", default="a", widget="FileChooser") + action2 = parser.add_argument("a_file", default="b", widget="DirChooser") + + self._verify_duplicate_parameters(action1, action2, parser) + self.assertEquals(parser.widgets["a_file"], "FileChooser") + + def _verify_duplicate_parameters(self, action1, action2, parser): + """ + Verify two parameters named a_file exist and the default value is "a". + """ + found = 0 + for action in parser._actions: + if action.dest == "a_file": + found += 1 + self.assertEquals(2, found, "Expected a both actions handling a_file but got " + str(found)) + self.assertEquals(parser.get_default("a_file"), "a") + self.assertNotEqual(action1, action2) \ No newline at end of file