Browse Source

Drunk coding! Whoooooo!

pull/1/head
Chris Kiehl 11 years ago
parent
commit
9b65ef5430
7 changed files with 388 additions and 80 deletions
  1. 132
      src/app/dialogs/action_sorter.py
  2. 32
      src/app/dialogs/advanced_config.py
  3. 75
      src/app/dialogs/component_factory.py
  4. 152
      src/app/dialogs/components.py
  5. 71
      src/app/dialogs/components_unittest.py
  6. 1
      src/model/example_argparse_souce.py
  7. 5
      src/model/source_parser.py

132
src/app/dialogs/action_sorter.py

@ -0,0 +1,132 @@
'''
Created on Dec 8, 2013
@author: Chris
'''
import wx
from argparse import (
_StoreAction, _StoreConstAction,
_StoreFalseAction, _StoreTrueAction,
_CountAction, _AppendAction)
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
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]
'''
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._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)
def _display(self, _type, something):
for i in something:
print _type, i
def get_counter_actions(self, actions):
'''
Returns all instances of type _CountAction
'''
return [action
for action in actions
if isinstance(action, _CountAction)]
def get_positionals(self, actions):
'''
Get all required (positional) actions
'''
return [action
for action in actions
if not action.option_strings]
def get_optionals_without_choices(self, actions):
'''
All actions which are
(a) Optional, but without required choices
(b) Not of a "boolean" type (storeTrue, etc..)
(c) Of type _AppendAction
e.g. anything which has an argument style like:
>>> -f myfilename.txt
'''
boolean_actions = (
_StoreConstAction, _StoreFalseAction,
_StoreTrueAction
)
return [action
for action in actions
if action.option_strings
and not action.choices
and action not in boolean_actions]
def get_optionals_with_choices(self, actions):
'''
All optional arguments which are constrained
to specific choices.
'''
return [action
for action in actions
if action.choices]
def get_flag_style_optionals(self, actions):
'''
Gets all instances of "flag" type options.
i.e. options which either store a const, or
store boolean style options (e.g. StoreTrue).
Types:
_StoreTrueAction
_StoreFalseAction
_StoreConst
'''
return [action
for action in actions
if isinstance(action, _StoreTrueAction)
or isinstance(action, _StoreFalseAction)
or isinstance(action, _StoreConstAction)]
if __name__ == '__main__':
pass

32
src/app/dialogs/advanced_config.py

@ -21,6 +21,7 @@ class AdvancedConfigPanel(ScrolledPanel):
self.container = wx.BoxSizer(wx.VERTICAL) self.container = wx.BoxSizer(wx.VERTICAL)
self.container.AddSpacer(10) self.container.AddSpacer(10)
self.AddRequiredArgsHeaderMsg() self.AddRequiredArgsHeaderMsg()
self.Add
@ -28,11 +29,34 @@ class AdvancedConfigPanel(ScrolledPanel):
required_msg = wx.StaticText(self, label="Required Arguments") required_msg = wx.StaticText(self, label="Required Arguments")
self.container.Add(required_msg, 0, wx.LEFT | wx.RIGHT, 20) self.container.Add(required_msg, 0, wx.LEFT | wx.RIGHT, 20)
def AddRequiredWidgets(self, factory):
widgets = factory._positionals
for widget in widgets:
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 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

75
src/app/dialogs/component_factory.py

@ -12,10 +12,7 @@ from argparse import (
class ComponentFactory(object): class ComponentFactory(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
Generates Wx Components from the argparse action types
COMPONENT MAP COMPONENT MAP
Action WxWidget Action WxWidget
@ -50,76 +47,6 @@ class ComponentFactory(object):
self._booleans = self.get_flag_style_optionals(self._actions) self._booleans = self.get_flag_style_optionals(self._actions)
self._counters = self.get_counter_actions(self._actions) self._counters = self.get_counter_actions(self._actions)
self._display('positionals', self._positionals)
self._display('choices', self._choices)
self._display('optionals', self._optionals)
self._display('booleans', self._booleans)
self._display('counters', self._counters)
def _display(self, _type, something):
for i in something:
print _type, i
def get_counter_actions(self, actions):
'''
Returns all instances of type _CountAction
'''
return [action
for action in actions
if isinstance(action, _CountAction)]
def get_positionals(self, actions):
'''
Get all required (positional) actions
'''
return [action
for action in actions
if not action.option_strings]
def get_optionals_without_choices(self, actions):
'''
All actions which are
(a) Optional, but without required choices
(b) Not of a "boolean" type (storeTrue, etc..)
(c) Of type _AppendAction
e.g. anything which has an argument style like:
>>> -f myfilename.txt
'''
boolean_actions = (
_StoreConstAction, _StoreFalseAction,
_StoreTrueAction
)
return [action
for action in actions
if action.option_strings
and not action.choices
and action not in boolean_actions]
def get_optionals_with_choices(self, actions):
'''
All optional arguments which are constrained
to specific choices.
'''
return [action
for action in actions
if action.choices]
def get_flag_style_optionals(self, actions):
'''
Gets all instances of "flag" type options.
i.e. options which either store a const, or
store boolean style options (e.g. StoreTrue).
Types:
_StoreTrueAction
_StoreFalseAction
_StoreConst
'''
return [action
for action in actions
if isinstance(action, _StoreTrueAction)
or isinstance(action, _StoreFalseAction)
or isinstance(action, _StoreConstAction)]
if __name__ == '__main__': if __name__ == '__main__':

152
src/app/dialogs/components.py

@ -0,0 +1,152 @@
'''
Created on Jan 1, 2014
@author: Chris
'''
import wx
from argparse import ArgumentParser
from abc import ABCMeta, abstractmethod
class BuildException(RuntimeError):
pass
class AbstractComponent(object):
'''
Template pattern-y abstract class for the components.
Children must all implement the BuildWidget and getValue
methods.
'''
__metaclass__ = ABCMeta
def __init__(self):
self._widget = None
def Build(self, parent):
self._widget = self.BuildWidget(parent, self._action)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.CreateDestNameWidget(parent, self._action))
sizer.AddSpacer(2)
if self.HasHelpMsg(self._action):
sizer.Add(self.CreateHelpMsgWidget(parent, self._action))
sizer.AddSpacer(2)
if self.HasNargs(self._action):
sizer.Add(self.AddNargsMsg(parent, self._action))
sizer.Add(self._widget, 0, wx.EXPAND)
return sizer
def HasHelpMsg(self, action):
return action.help is not None
def HasNargs(self, action):
return action.nargs == '+'
def CreateHelpMsgWidget(self, parent, action):
text = wx.StaticText(parent, label=action.help)
self.MakeDarkGrey(text)
return text
def AddNargsMsg(self, parent, action):
msg = 'Note: at least 1 or more arguments are required'
return wx.StaticText(parent, label=msg)
def CreateDestNameWidget(self, parent, action):
text = wx.StaticText(parent, label=str(action.dest).title())
self.MakeBold(text)
return text
def AssertInitialization(self, widget, clsname):
print self._widget
if not self._widget:
raise BuildException('%s was not correctly initialized' % clsname)
def MakeBold(self, statictext):
pointsize = statictext.GetFont().GetPointSize()
statictext.SetFont(wx.Font(pointsize, wx.FONTFAMILY_DEFAULT,
wx.FONTWEIGHT_NORMAL, wx.FONTWEIGHT_BOLD, False))
def MakeDarkGrey(self, statictext):
darkgray = (54,54,54)
statictext.SetForegroundColour(darkgray)
@abstractmethod
def BuildWidget(self, parent, action):
'''
Must construct the main widget type for the Action
'''
pass
@abstractmethod
def GetValue(self):
'''
Returns the state of the given widget
'''
pass
class Positional(AbstractComponent):
def __init__(self, action):
self._action = action
self._widget = None
self.contents = None
def BuildWidget(self, parent, action):
return wx.TextCtrl(parent)
def GetValue(self):
self.AssertInitialization(self._widget, 'Positional')
return self._widget.GetValue()
class Choice(AbstractComponent):
def __init__(self, action):
self._action = action
self._widget = None
self.contents = None
def GetValue(self):
self.AssertInitialization()
return self._widget.GetValue()
def BuildWidget(self, parent, action):
return wx.ComboBox(
parent=parent,
id=-1,
value='Select Option',
choices=action.choices,
style=wx.CB_DROPDOWN
)
class Optional(AbstractComponent):
def __init__(self, action):
pass
if __name__ == '__main__':
parser = ArgumentParser(description='Example Argparse Program')
parser.add_argument("filename", help="filename")
action = parser._actions[1]
positional = Positional(action)
a = getattr

71
src/app/dialogs/components_unittest.py

@ -0,0 +1,71 @@
'''
Created on Jan 4, 2014
@author: Chris
'''
import wx
import os
import sys
import unittest
import components
from argparse import ArgumentParser
class ComponentsTest(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'])
action = parser._actions
self.actions = {
'help' : action[0],
'Positional' : action[1],
'Choice' : action[2]
}
def BuildWindow(self, component):
app = wx.PySimpleApp()
module_name = os.path.split(sys.argv[0])[-1]
frame = wx.Frame(None, -1, module_name)
panel = wx.Panel(frame, -1, size=(320,240))
component_sizer = component.Build(panel)
panel.SetSizer(component_sizer)
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 SetupWidgetAndBuildWindow(self, _type):
component = getattr(components, _type)(self.actions[_type])
self.BuildWindow(component)
if __name__ == "__main__":
# import sys;sys.argv = ['', 'Test.testName']
unittest.main()

1
src/model/example_argparse_souce.py

@ -76,6 +76,7 @@ USAGE
parser.add_argument("-r", "--recursive", dest="recurse", action="store_true", help="recurse into subfolders [default: %(default)s]") parser.add_argument("-r", "--recursive", dest="recurse", action="store_true", help="recurse into subfolders [default: %(default)s]")
parser.add_argument("-v", "--verbose", dest="verbose", action="count", help="set verbosity level [default: %(default)s]") parser.add_argument("-v", "--verbose", dest="verbose", action="count", help="set verbosity level [default: %(default)s]")
parser.add_argument("-i", "--include", action="append", help="only include paths matching this regex pattern. Note: exclude is given preference over include. [default: %(default)s]", metavar="RE" ) parser.add_argument("-i", "--include", action="append", help="only include paths matching this regex pattern. Note: exclude is given preference over include. [default: %(default)s]", metavar="RE" )
parser.add_argument("-m", "--mycoolargument", help="mycoolargument")
parser.add_argument("-e", "--exclude", dest="exclude", help="exclude paths matching this regex pattern. [default: %(default)s]", metavar="RE" ) parser.add_argument("-e", "--exclude", dest="exclude", help="exclude paths matching this regex pattern. [default: %(default)s]", metavar="RE" )
parser.add_argument('-V', '--version', action='version') parser.add_argument('-V', '--version', action='version')
parser.add_argument('-T', '--tester', choices=['yes','no']) parser.add_argument('-T', '--tester', choices=['yes','no'])

5
src/model/source_parser.py

@ -22,7 +22,7 @@ from functools import partial
from numpy.lib.utils import _split_line from numpy.lib.utils import _split_line
from argparse import ArgumentParser from argparse import ArgumentParser
from argparse import RawDescriptionHelpFormatter from argparse import RawDescriptionHelpFormatter
from app.dialogs.component_factory import ComponentFactory
from app.dialogs.action_sorter import ActionSorter
class ParserError(Exception): class ParserError(Exception):
@ -269,7 +269,8 @@ if __name__ == '__main__':
ast_source = parse_source_file('example_argparse_souce.py') ast_source = parse_source_file('example_argparse_souce.py')
python_code = convert_to_python(ast_source) python_code = convert_to_python(ast_source)
parser = ParserFromSource(python_code) parser = ParserFromSource(python_code)
factory = ComponentFactory(parser)
factory = ActionSorter(parser)
print factory._positionals
# #

Loading…
Cancel
Save