mirror of https://github.com/chriskiehl/Gooey.git
chriskiehl
9 years ago
10 changed files with 0 additions and 548 deletions
Unified View
Diff Options
-
141gooey/gui/action_sorter.py
-
79gooey/gui/build_spec_validator.py
-
63gooey/gui/client_app.py
-
30gooey/gui/commands.py
-
63gooey/gui/component_factory.py
-
14gooey/gui/component_register.py
-
115gooey/gui/display_main.py
-
19gooey/gui/message_router.py
-
18gooey/gui/msg_dialog.py
-
6gooey/gui/routes.py
@ -1,141 +0,0 @@ |
|||||
""" |
|
||||
Created on Dec 8, 2013 |
|
||||
|
|
||||
@author: Chris |
|
||||
|
|
||||
""" |
|
||||
|
|
||||
from argparse import ( |
|
||||
_CountAction, |
|
||||
_HelpAction, |
|
||||
_StoreConstAction, |
|
||||
_StoreFalseAction, |
|
||||
_StoreTrueAction |
|
||||
) |
|
||||
|
|
||||
|
|
||||
class ActionSorter(object): |
|
||||
""" |
|
||||
Sorts all of the actions into their appropriate containers. |
|
||||
|
|
||||
Containers are based on the following map: |
|
||||
|
|
||||
COMPONENT MAP |
|
||||
Action WxWidget |
|
||||
-------------------------- |
|
||||
store TextCtrl |
|
||||
store_const CheckBox |
|
||||
store_true CheckBox |
|
||||
store_False CheckBox |
|
||||
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) |
|
||||
_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, actions): |
|
||||
self._actions = 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._flags = self.get_flag_style_optionals(self._actions) |
|
||||
self._counters = self.get_counter_actions(self._actions) |
|
||||
|
|
||||
def verbose(self): |
|
||||
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): |
|
||||
pass |
|
||||
# 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 not isinstance(action, _CountAction) |
|
||||
and not isinstance(action, _HelpAction) |
|
||||
and type(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 |
|
@ -1,79 +0,0 @@ |
|||||
''' |
|
||||
Validates that the json has meaningful keys |
|
||||
''' |
|
||||
|
|
||||
import itertools |
|
||||
|
|
||||
|
|
||||
a = { |
|
||||
'required' : [ |
|
||||
{ |
|
||||
'component': 'TextField', |
|
||||
'data': { |
|
||||
'display_name': 'filename', |
|
||||
'help_text': 'path to file you want to process', |
|
||||
'command_args': ['-f', '--infile'] |
|
||||
} |
|
||||
}, |
|
||||
{ |
|
||||
'component': 'FileChooser', |
|
||||
'data': { |
|
||||
'display_name': 'Output Location', |
|
||||
'help_text': 'Where to save the file', |
|
||||
'command_args': ['-o', '--outfile'] |
|
||||
} |
|
||||
} |
|
||||
], |
|
||||
'optional' : [ |
|
||||
{ |
|
||||
'component': 'RadioGroup', |
|
||||
'data': [ |
|
||||
{ |
|
||||
'display_name': 'Output Location', |
|
||||
'help_text': 'Where to save the file', |
|
||||
'command_args': ['-o', '--outfile'] |
|
||||
}, { |
|
||||
'display_name': 'Output Location', |
|
||||
'help_text': 'Where to save the file', |
|
||||
'command_args': ['-o', '--outfile'] |
|
||||
} |
|
||||
] |
|
||||
} |
|
||||
] |
|
||||
} |
|
||||
|
|
||||
VALID_WIDGETS = ( |
|
||||
'FileChooser', |
|
||||
'DirChooser', |
|
||||
'DateChooser', |
|
||||
'TextField', |
|
||||
'Dropdown', |
|
||||
'Counter', |
|
||||
'RadioGroup' |
|
||||
) |
|
||||
|
|
||||
|
|
||||
class MalformedBuildSpecException(Exception): |
|
||||
pass |
|
||||
|
|
||||
def validate(json_string): |
|
||||
required = json_string.get('required') |
|
||||
optional = json_string.get('optional') |
|
||||
|
|
||||
if not required or not optional: |
|
||||
raise MalformedBuildSpecException("All objects must be children of 'required,' or 'optional'") |
|
||||
|
|
||||
objects = [item for key in json_string for item in json_string[key]] |
|
||||
|
|
||||
for obj in objects: |
|
||||
if obj['component'] not in VALID_WIDGETS: |
|
||||
raise MalformedBuildSpecException("Invalid Component name: {0}".format(obj['component'])) |
|
||||
|
|
||||
|
|
||||
if __name__ == '__main__': |
|
||||
|
|
||||
validate(a) |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
@ -1,63 +0,0 @@ |
|||||
''' |
|
||||
Created on Jan 23, 2014 |
|
||||
|
|
||||
@author: Chris |
|
||||
''' |
|
||||
|
|
||||
import sys |
|
||||
|
|
||||
from gooey.gui.action_sorter import ActionSorter |
|
||||
|
|
||||
|
|
||||
class ClientApp(object): |
|
||||
def __init__(self, parser, payload): |
|
||||
self._parser = parser |
|
||||
self.description = parser.description |
|
||||
self.action_groups = ActionSorter(self._parser._actions) |
|
||||
self.payload = payload |
|
||||
|
|
||||
def HasPositionals(self): |
|
||||
if self.action_groups._positionals: |
|
||||
return True |
|
||||
return False |
|
||||
|
|
||||
def IsValidArgString(self, arg_string): |
|
||||
if isinstance(self._Parse(arg_string), str): |
|
||||
return False |
|
||||
return True |
|
||||
|
|
||||
def _Parse(self, arg_string): |
|
||||
try: |
|
||||
self._parser.parse_args(arg_string.split()) |
|
||||
return True |
|
||||
except Exception as e: |
|
||||
return str(e) |
|
||||
|
|
||||
def GetErrorMsg(self, arg_string): |
|
||||
return self._FormatMsg(self._Parse(arg_string)) |
|
||||
|
|
||||
def _FormatMsg(self, msg): |
|
||||
output = list(msg) |
|
||||
if ':' in output: |
|
||||
output[output.index(':')] = ':\n ' |
|
||||
return ''.join(output) |
|
||||
|
|
||||
def AddToArgv(self, arg_string): |
|
||||
sys.argv.extend(arg_string.split()) |
|
||||
|
|
||||
|
|
||||
class EmptyClientApp(object): |
|
||||
def __init__(self, payload): |
|
||||
''' |
|
||||
initializes a BlankModel object |
|
||||
|
|
||||
As you can see. This class does nothing.. |
|
||||
''' |
|
||||
|
|
||||
self.description = '' |
|
||||
self.payload = payload |
|
||||
|
|
||||
|
|
||||
if __name__ == '__main__': |
|
||||
pass |
|
||||
|
|
@ -1,30 +0,0 @@ |
|||||
import itertools |
|
||||
import docopt |
|
||||
from gooey.python_bindings import argparse_to_json |
|
||||
|
|
||||
|
|
||||
class Required(object): |
|
||||
def __init__(self, id): |
|
||||
|
|
||||
class Optional(object): |
|
||||
pass |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
parser = [] |
|
||||
|
|
||||
command_list = CommandList(argparse_to_json.convert(parser)) |
|
||||
|
|
||||
print command_list.required_args |
|
||||
command_list['filter'].value = 123 |
|
||||
command_list['compress'].value = True |
|
||||
|
|
||||
if not command_list.is_valid(): |
|
||||
raise "invalid" |
|
||||
|
|
||||
|
|
||||
|
|
@ -1,63 +0,0 @@ |
|||||
''' |
|
||||
Created on Dec 8, 2013 |
|
||||
|
|
||||
@author: Chris |
|
||||
''' |
|
||||
|
|
||||
import itertools |
|
||||
|
|
||||
import components |
|
||||
from gooey.gui import argparse_test_data |
|
||||
|
|
||||
|
|
||||
class ComponentFactory(object): |
|
||||
''' |
|
||||
Aggregates all of the actions and |
|
||||
''' |
|
||||
|
|
||||
def __init__(self, sorted_actions): |
|
||||
self._actions = sorted_actions |
|
||||
|
|
||||
self.required_args = self.BuildPositionals(self._actions) |
|
||||
self.flags = self.BuildFlags(self._actions) |
|
||||
self.general_options = (self.BuildChoices(self._actions) |
|
||||
+ self.BuildOptionals(self._actions) |
|
||||
+ self.BuildCounters(self._actions)) |
|
||||
|
|
||||
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] |
|
||||
|
|
||||
def __iter__(self): |
|
||||
''' |
|
||||
return an iterator for all of the contained gui |
|
||||
''' |
|
||||
return itertools.chain(self.required_args, |
|
||||
self.flags, |
|
||||
self.general_options) |
|
||||
|
|
||||
|
|
||||
if __name__ == '__main__': |
|
||||
a = ComponentFactory(argparse_test_data.parser) |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
@ -1,14 +0,0 @@ |
|||||
''' |
|
||||
Created on Jan 20, 2014 |
|
||||
|
|
||||
@author: Chris |
|
||||
''' |
|
||||
|
|
||||
|
|
||||
class ComponentRegister(object): |
|
||||
''' Mixin class for attaching controllers to objects ''' |
|
||||
|
|
||||
def Registercontroller(self, controller): |
|
||||
''' Assigns a Controller to a view (usually panel or frame) object''' |
|
||||
if self._controller in None: |
|
||||
self._controller = controller |
|
@ -1,115 +0,0 @@ |
|||||
''' |
|
||||
Created on Dec 8, 2013 |
|
||||
|
|
||||
@author: Chris |
|
||||
''' |
|
||||
|
|
||||
import os |
|
||||
import sys |
|
||||
import threading |
|
||||
|
|
||||
import wx |
|
||||
|
|
||||
from app.dialogs.controller import Controller |
|
||||
from app.images import image_store |
|
||||
from app.dialogs.header import FrameHeader |
|
||||
from app.dialogs.basic_config_panel import RuntimeDisplay |
|
||||
from app.dialogs.footer import Footer |
|
||||
from gooey.gui.message_event import EVT_MSG |
|
||||
|
|
||||
|
|
||||
class MessagePump(object): |
|
||||
def __init__(self, queue): |
|
||||
self.queue = queue |
|
||||
self.stdout = sys.stdout |
|
||||
|
|
||||
# Overrides stdout's write method |
|
||||
def write(self, text): |
|
||||
if text != '': |
|
||||
self.queue.put(text) |
|
||||
|
|
||||
|
|
||||
class Listener(threading.Thread): |
|
||||
def __init__(self, queue, textbox): |
|
||||
threading.Thread.__init__(self) |
|
||||
self.queue = queue |
|
||||
self.update_text = lambda x: textbox.AppendText(x) |
|
||||
|
|
||||
def run(self): |
|
||||
while True: |
|
||||
try: |
|
||||
stdout_msg = self.queue.get(timeout=1) |
|
||||
if stdout_msg != '': |
|
||||
self.update_text(stdout_msg) |
|
||||
except Exception as e: |
|
||||
pass # Timeout. Aint nobody care 'bout dat |
|
||||
|
|
||||
|
|
||||
class MainWindow(wx.Frame): |
|
||||
def __init__(self, queue, payload=None): |
|
||||
wx.Frame.__init__( |
|
||||
self, |
|
||||
parent=None, |
|
||||
id=-1, |
|
||||
title=os.path.basename(__file__), |
|
||||
size=(640, 480) |
|
||||
) |
|
||||
|
|
||||
self._controller = Controller() |
|
||||
|
|
||||
self._init_properties() |
|
||||
self._init_components() |
|
||||
self._do_layout() |
|
||||
|
|
||||
self.queue = queue |
|
||||
# the client's main function |
|
||||
self._payload = payload |
|
||||
|
|
||||
_stdout = sys.stdout |
|
||||
sys.stdout = MessagePump(queue) |
|
||||
listener = Listener(queue, self.config_panel.cmd_textbox) |
|
||||
listener.start() |
|
||||
|
|
||||
def _init_properties(self): |
|
||||
self.SetMinSize((400, 300)) |
|
||||
self.icon = wx.Icon(image_store.icon, wx.BITMAP_TYPE_ICO) |
|
||||
self.SetIcon(self.icon) |
|
||||
|
|
||||
def _init_components(self): |
|
||||
# init gui |
|
||||
self.head_panel = FrameHeader(image_path=image_store.computer3, parent=self, size=(30, 90)) |
|
||||
self.config_panel = RuntimeDisplay(parent=self) |
|
||||
self.foot_panel = Footer(self, self._controller) |
|
||||
|
|
||||
def _do_layout(self): |
|
||||
sizer = wx.BoxSizer(wx.VERTICAL) |
|
||||
sizer.Add(self.head_panel, 0, wx.EXPAND) |
|
||||
self._draw_horizontal_line(sizer) |
|
||||
sizer.Add(self.config_panel, 1, wx.EXPAND) |
|
||||
self._draw_horizontal_line(sizer) |
|
||||
sizer.Add(self.foot_panel, 0, wx.EXPAND) |
|
||||
self.SetSizer(sizer) |
|
||||
|
|
||||
self.Bind(EVT_MSG, self.OnMsg) |
|
||||
|
|
||||
def _init_panels(self): |
|
||||
self._frame_header = FrameHeader |
|
||||
self._basic_config_body = None |
|
||||
self._adv_config_body = None |
|
||||
self._config_footer = None |
|
||||
self._output_footer = None |
|
||||
|
|
||||
def _draw_horizontal_line(self, sizer): |
|
||||
line = wx.StaticLine(self, -1, style=wx.LI_HORIZONTAL) |
|
||||
line.SetSize((10, 10)) |
|
||||
sizer.Add(line, 0, wx.EXPAND) |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
@ -1,19 +0,0 @@ |
|||||
import threading |
|
||||
|
|
||||
__author__ = 'Chris' |
|
||||
|
|
||||
|
|
||||
class MessageRouter(threading.Thread): |
|
||||
def __init__(self, textbox, process_to_route): |
|
||||
threading.Thread.__init__(self) |
|
||||
self.textbox = textbox |
|
||||
self.process = process_to_route |
|
||||
|
|
||||
def run(self): |
|
||||
while True: |
|
||||
line = self.process.stdout.readline() |
|
||||
if not line: |
|
||||
break |
|
||||
|
|
||||
|
|
||||
|
|
@ -1,18 +0,0 @@ |
|||||
''' |
|
||||
Created on Jan 23, 2014 |
|
||||
|
|
||||
@author: Chris |
|
||||
''' |
|
||||
import wx |
|
||||
|
|
||||
|
|
||||
def ShowError(msg): |
|
||||
wx.MessageDialog( |
|
||||
None, |
|
||||
msg, |
|
||||
'Argument Error', |
|
||||
wx.ICON_ERROR) |
|
||||
|
|
||||
|
|
||||
if __name__ == '__main__': |
|
||||
pass |
|
@ -1,6 +0,0 @@ |
|||||
|
|
||||
import wx |
|
||||
|
|
||||
|
|
||||
|
|
||||
config = lambda self: self.Bind(wx.EVT_BUTTON, 'handler', id=wx.NewId()) |
|
Write
Preview
Loading…
Cancel
Save