mirror of https://github.com/chriskiehl/Gooey.git
7 changed files with 388 additions and 80 deletions
Split View
Diff Options
-
132src/app/dialogs/action_sorter.py
-
32src/app/dialogs/advanced_config.py
-
75src/app/dialogs/component_factory.py
-
152src/app/dialogs/components.py
-
71src/app/dialogs/components_unittest.py
-
1src/model/example_argparse_souce.py
-
5src/model/source_parser.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 |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
@ -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 |
|||
|
|||
|
|||
|
|||
|
|||
|
@ -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() |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
Write
Preview
Loading…
Cancel
Save