mirror of https://github.com/chriskiehl/Gooey.git
chriskiehl
9 years ago
10 changed files with 0 additions and 548 deletions
Split 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