diff --git a/src/app/dialogs/action_sorter.py b/src/app/dialogs/action_sorter.py index 48ef84e..6296bf0 100644 --- a/src/app/dialogs/action_sorter.py +++ b/src/app/dialogs/action_sorter.py @@ -2,6 +2,7 @@ Created on Dec 8, 2013 @author: Chris + ''' import wx @@ -10,12 +11,14 @@ from argparse import ( _StoreFalseAction, _StoreTrueAction, _CountAction, _AppendAction) + +DEBUG = 1 + class ActionSorter(object): ''' - So this thing is the thing that will - pull out all of the "types" from the - argparse object and turn them into the - correct wx components + Sorts all of the actions into their appropriate containers. + + Containers are based on the following map: COMPONENT MAP Action WxWidget @@ -27,7 +30,16 @@ class ActionSorter(object): append TextCtrl count DropDown choice DropDown - + + Instance Variables: + self._positionals + self._choices + self._optionals + self._flags + self._counters + + Example Argparse Def + _HelpAction(option_strings=['-h', '--help'], dest='help', nargs=0, const=None, default='==SUPPRESS==', type=None, choices=None, help='show this help message and exit', metavar=None) _StoreAction(option_strings=[], dest='filename', nargs=None, const=None, default=None, type=None, choices=None, help='filename', metavar=None) _StoreTrueAction(option_strings=['-r', '--recursive'], dest='recurse', nargs=0, const=True, default=False, type=None, choices=None, help='recurse into subfolders [default: %(default)s]', metavar=None) @@ -40,21 +52,21 @@ class ActionSorter(object): usage: example_argparse_souce.py [-h] [-r] [-v] [-i RE] [-e RE] [-V] ''' - def __init__(self, parser): - self._parser = parser - self._actions = self._parser._actions[:] # Copy all of the actions + def __init__(self, actions): + self._actions = actions[:] # Copy all of the actions self._positionals = self.get_positionals(self._actions) self._choices = self.get_optionals_with_choices(self._actions) self._optionals = self.get_optionals_without_choices(self._actions) - self._booleans = self.get_flag_style_optionals(self._actions) + self._flags = self.get_flag_style_optionals(self._actions) self._counters = self.get_counter_actions(self._actions) - self._display('ActionSorter: positionals', self._positionals) - self._display('ActionSorter: choices', self._choices) - self._display('ActionSorter: optionals', self._optionals) - self._display('ActionSorter: booleans', self._booleans) - self._display('ActionSorter: counters', self._counters) + if DEBUG: + self._display('ActionSorter: positionals', self._positionals) + self._display('ActionSorter: choices', self._choices) + self._display('ActionSorter: optionals', self._optionals) + self._display('ActionSorter: booleans', self._flags) + self._display('ActionSorter: counters', self._counters) def _display(self, _type, something): for i in something: diff --git a/src/app/dialogs/advanced_config.py b/src/app/dialogs/advanced_config.py index d688968..e32e984 100644 --- a/src/app/dialogs/advanced_config.py +++ b/src/app/dialogs/advanced_config.py @@ -5,59 +5,48 @@ Created on Dec 28, 2013 ''' import wx + +from component_factory import ComponentFactory from wx.lib.scrolledpanel import ScrolledPanel + + class AdvancedConfigPanel(ScrolledPanel): ''' Abstract class for the Footer panels. ''' - def __init__(self, parent, **kwargs): + def __init__(self, parent, parser, **kwargs): ScrolledPanel.__init__(self, parent, **kwargs) self.SetupScrolling() - self.components = [] + self.components = ComponentFactory(parser) self.container = wx.BoxSizer(wx.VERTICAL) self.container.AddSpacer(10) + self.AddRequiredArgsHeaderMsg() - self.Add + self.AddWidgets(self.components.positionals) + + self.SetSizer(self.container) - def AddRequiredArgsHeaderMsg(self): required_msg = wx.StaticText(self, label="Required Arguments") self.container.Add(required_msg, 0, wx.LEFT | wx.RIGHT, 20) - def AddWidgets(self, actions, widget_type): - if len(actions) == 0: - return - action = actions.pop(0) - self.CreateHelpMsgWidget(action) - if self.hasNargs(action): - self.AddNargsMsg(action) - self.AddWidget(widget_type) - self.AddWidgets(actions, widget_type) + def AddWidgets(self, components): + if not components: + return + component = components[0] + widget_group = component.Build(parent=self) + self.container.Add(widget_group) + self.AddWidgets(components[1:]) - def CreateHelpMsgWidget(self, action): - help_msg = action.help - return wx.StaticText(self, label=help_msg) - - def HasNargs(self, action): - return action.nargs > 0 - - def AddNargsMsg(self, action): - msg = action.nargs - return wx.StaticText(self, label=msg) - - def AddWidget(self, _type): - widget = getattr(wx, _type) if __name__ == '__main__': - a = getattr(wx, 'StaticText') - print a - + pass diff --git a/src/app/dialogs/advanced_config.pyc b/src/app/dialogs/advanced_config.pyc index b54f7cb..aa35c90 100644 Binary files a/src/app/dialogs/advanced_config.pyc and b/src/app/dialogs/advanced_config.pyc differ diff --git a/src/app/dialogs/advanced_config_unittest.py b/src/app/dialogs/advanced_config_unittest.py new file mode 100644 index 0000000..3942a35 --- /dev/null +++ b/src/app/dialogs/advanced_config_unittest.py @@ -0,0 +1,41 @@ +''' +Created on Jan 7, 2014 + +@author: Chris +''' + +import wx +import os +import sys +import unittest +import advanced_config +from argparse import ArgumentParser + +class Test(unittest.TestCase): + + + def setUp(self): + parser = ArgumentParser(description='Example Argparse Program') + parser.add_argument("filename", help="Name of the file you want to read") + parser.add_argument('-T', '--tester', choices=['yes','no']) + parser.add_argument('-o', '--outfile', help='Redirects output to the specified file') + parser.add_argument('-v', '--verbose', help='Toggles verbosity off') + parser.add_argument('-e', '--repeat', action='count', help='Set the number of times to repeat') + self.parser = parser + + def buildWindow(self): + app = wx.PySimpleApp() + module_name = os.path.split(sys.argv[0])[-1] + frame = wx.Frame(None, -1, module_name) + + panel = advanced_config.AdvancedConfigPanel(frame, self.parser) + frame.Show() + app.MainLoop() + + def testAdvancedConfigPanel(self): + self.buildWindow() + + +if __name__ == "__main__": + #import sys;sys.argv = ['', 'Test.testName'] + unittest.main() \ No newline at end of file diff --git a/src/app/dialogs/component_factory.py b/src/app/dialogs/component_factory.py index 443bcbc..98f1af8 100644 --- a/src/app/dialogs/component_factory.py +++ b/src/app/dialogs/component_factory.py @@ -5,48 +5,54 @@ Created on Dec 8, 2013 ''' import wx -from argparse import ( - _StoreAction, _StoreConstAction, - _StoreFalseAction, _StoreTrueAction, - _CountAction, _AppendAction) +import components +import action_sorter + class ComponentFactory(object): ''' - Generates Wx Components from the argparse action types - - COMPONENT MAP - Action WxWidget - -------------------------- - store TextCtrl - store_const CheckBox - store_true CheckBox - store_False CheckBox - append TextCtrl - count DropDown - choice DropDown - - _HelpAction(option_strings=['-h', '--help'], dest='help', nargs=0, const=None, default='==SUPPRESS==', type=None, choices=None, help='show this help message and exit', metavar=None) - _StoreAction(option_strings=[], dest='filename', nargs=None, const=None, default=None, type=None, choices=None, help='filename', metavar=None) - _StoreTrueAction(option_strings=['-r', '--recursive'], dest='recurse', nargs=0, const=True, default=False, type=None, choices=None, help='recurse into subfolders [default: %(default)s]', metavar=None) - _CountAction(option_strings=['-v', '--verbose'], dest='verbose', nargs=0, const=None, default=None, type=None, choices=None, help='set verbosity level [default: %(default)s]', metavar=None) - _AppendAction(option_strings=['-i', '--include'], dest='include', nargs=None, const=None, default=None, type=None, choices=None, help='only include paths matching this regex pattern. Note: exclude is given preference over include. [default: %(default)s]', metavar='RE') - _StoreAction(option_strings=['-e', '--exclude'], dest='exclude', nargs=None, const=None, default=None, type=None, choices=None, help='exclude paths matching this regex pattern. [default: %(default)s]', metavar='RE') - _VersionAction(option_strings=['-V', '--version'], dest='version', nargs=0, const=None, default='==SUPPRESS==', type=None, choices=None, help="show program's version number and exit", metavar=None) - _StoreAction(option_strings=['-T', '--tester'], dest='tester', nargs=None, const=None, default=None, type=None, choices=['yes', 'no'], help=None, metavar=None) - _StoreAction(option_strings=[], dest='paths', nargs='+', const=None, default=None, type=None, choices=None, help='paths to folder(s) with source file(s) [default: %(default)s]', metavar='path') - usage: example_argparse_souce.py [-h] [-r] [-v] [-i RE] [-e RE] [-V] + Aggregates all of the Widgets and dispatches + them to the caller. ''' def __init__(self, parser): - self._parser = parser - self._actions = self._parser._actions[:] # Copy all of the actions - self._positionals = self.get_positionals(self._actions) - self._choices = self.get_optionals_with_choices(self._actions) - self._optionals = self.get_optionals_without_choices(self._actions) - self._booleans = self.get_flag_style_optionals(self._actions) - self._counters = self.get_counter_actions(self._actions) + self._actions = action_sorter.ActionSorter(parser._actions[:]) + + self.positionals = self.BuildPositionals(self._actions) + self.choices = self.BuildChoices(self._actions) + self.optionals = self.BuildOptionals(self._actions) + self.booleans = self.BuildFlags(self._actions) + self.counters = self.BuildCounters(self._actions) + + self._components = [ + self.positionals, + self.choices, + self.optionals, + self.booleans, + self.counters + ] + + def BuildPositionals(self, actions): + return self._AssembleWidgetsFromActions(actions, 'Positional', '_positionals') + + def BuildChoices(self, actions): + return self._AssembleWidgetsFromActions(actions, 'Choice', '_choices') + + def BuildOptionals(self, actions): + return self._AssembleWidgetsFromActions(actions, 'Optional', '_optionals') + + def BuildFlags(self, actions): + return self._AssembleWidgetsFromActions(actions, 'Flag', '_flags') + + def BuildCounters(self, actions): + return self._AssembleWidgetsFromActions(actions, 'Counter', '_counters') + def _AssembleWidgetsFromActions(self, actions, classname, actiontype): + cls = getattr(components, classname) + actions_list = getattr(actions, actiontype) + return [cls(action) + for action in actions_list] if __name__ == '__main__': diff --git a/src/app/dialogs/component_factory.pyc b/src/app/dialogs/component_factory.pyc index 43005fa..6c2b340 100644 Binary files a/src/app/dialogs/component_factory.pyc and b/src/app/dialogs/component_factory.pyc differ diff --git a/src/app/dialogs/components.py b/src/app/dialogs/components.py index 94c22c5..25c3210 100644 --- a/src/app/dialogs/components.py +++ b/src/app/dialogs/components.py @@ -61,7 +61,7 @@ class AbstractComponent(object): def CreateDestNameWidget(self, parent, action): label = str(action.dest).title() - if action.option_strings: + if len(action.option_strings) > 1: label += ' (%s)' % action.option_strings[0] text = wx.StaticText(parent, label=label) self.MakeBold(text) @@ -83,16 +83,12 @@ class AbstractComponent(object): @abstractmethod def BuildWidget(self, parent, action): - ''' - Must construct the main widget type for the Action - ''' + ''' Must construct the main widget type for the Action ''' pass @abstractmethod def GetValue(self): - ''' - Returns the state of the given widget - ''' + ''' Returns the state of the given widget ''' pass @@ -138,23 +134,57 @@ class Optional(AbstractComponent): self.contents = None def BuildWidget(self, parent, action): - pass + return wx.TextCtrl(parent) + + def GetValue(self): + self.AssertInitialization('Optional') + return self._widget.GetValue() + - - +class Flag(AbstractComponent): + def __init__(self, action): + self._action = action + self._widget = None + self.contents = None + + def BuildWidget(self, parent, action): + if len(action.option_strings) > 1: + label = action.option_strings[0] + else: + label = '' + return wx.CheckBox(parent, -1, label=label) + + def GetValue(self): + return self._widget.GetValue() - - - + + +class Counter(AbstractComponent): + def __init__(self, action): + self._action = action + self._widget = None + self.contents = None + + def BuildWidget(self, parent, action): + levels = [str(x) for x in range(1, 7)] + return wx.ComboBox( + parent=parent, + id=-1, + value='', + choices=levels, + style=wx.CB_DROPDOWN + ) + + def GetValue(self): + return self._widget.GetValue() + + + if __name__ == '__main__': - parser = ArgumentParser(description='Example Argparse Program') - parser.add_argument("filename", help="filename") - action = parser._actions[1] - positional = Positional(action) - - a = getattr + pass + diff --git a/src/app/dialogs/components_unittest.py b/src/app/dialogs/components_unittest.py index 289a265..a7a2631 100644 --- a/src/app/dialogs/components_unittest.py +++ b/src/app/dialogs/components_unittest.py @@ -22,16 +22,21 @@ class ComponentsTest(unittest.TestCase): parser = ArgumentParser(description='Example Argparse Program') parser.add_argument("filename", help="Name of the file you want to read") parser.add_argument('-T', '--tester', choices=['yes','no']) + parser.add_argument('-o', '--outfile', help='Redirects output to the specified file') + parser.add_argument('-v', '--verbose', help='Toggles verbosity off') + parser.add_argument('-e', '--repeat', action='count', help='Set the number of times to repeat') action = parser._actions self.actions = { 'help' : action[0], 'Positional' : action[1], - 'Choice' : action[2] + 'Choice' : action[2], + 'Optional' : action[3], + 'Flag' : action[4], + 'Counter' : action[5] } def BuildWindow(self, component): - app = wx.PySimpleApp() module_name = os.path.split(sys.argv[0])[-1] frame = wx.Frame(None, -1, module_name) @@ -42,17 +47,25 @@ class ComponentsTest(unittest.TestCase): frame.Show(True) - print component.GetValue() app.MainLoop() + def testPositionalWidgetBuild(self): self.SetupWidgetAndBuildWindow('Positional') -# component = components.Positional(self.actions['positional']) -# self.BuildWindow(component) def testChoiceWidgetBuild(self): self.SetupWidgetAndBuildWindow('Choice') + def testOptionalWidgetBuild(self): + self.SetupWidgetAndBuildWindow('Optional') + + def testFlagWidgetBuild(self): + self.SetupWidgetAndBuildWindow('Flag') + + def testCounterWidgetBuild(self): + self.SetupWidgetAndBuildWindow('Counter') + + def SetupWidgetAndBuildWindow(self, _type): component = getattr(components, _type)(self.actions[_type]) self.BuildWindow(component)