mirror of https://github.com/chriskiehl/Gooey.git
commit
b731171651
52 changed files with 1844 additions and 0 deletions
Split View
Diff Options
-
17.project
-
8.pydevproject
-
3.settings/org.eclipse.core.resources.prefs
-
0src/app/__init__.py
-
BINsrc/app/__init__.pyc
-
0src/app/dialogs/__init__.py
-
BINsrc/app/dialogs/__init__.pyc
-
43src/app/dialogs/advanced_config.py
-
BINsrc/app/dialogs/advanced_config.pyc
-
26src/app/dialogs/body.py
-
BINsrc/app/dialogs/body.pyc
-
132src/app/dialogs/component_factory.py
-
BINsrc/app/dialogs/component_factory.pyc
-
107src/app/dialogs/display_main.py
-
BINsrc/app/dialogs/display_main.pyc
-
51src/app/dialogs/experiments.py
-
80src/app/dialogs/footer.py
-
BINsrc/app/dialogs/footer.pyc
-
71src/app/dialogs/header.py
-
BINsrc/app/dialogs/header.pyc
-
54src/app/dialogs/simple_config_panel.py
-
15src/app/dialogs/test.py
-
60src/app/images/__init__.py
-
BINsrc/app/images/__init__.pyc
-
BINsrc/app/images/computer.png
-
BINsrc/app/images/computer2.png
-
BINsrc/app/images/computer3.png
-
BINsrc/app/images/icon.ico
-
14src/app/images/image_store.py
-
BINsrc/app/images/image_store.pyc
-
BINsrc/app/images/images.jpg
-
BINsrc/app/images/terminal.png
-
21src/app/testrun.py
-
0src/app/widgets/__init__.py
-
0src/mockapplication/__init__.py
-
32src/mockapplication/mockapp.py
-
0src/model/__init__.py
-
BINsrc/model/__init__.pyc
-
572src/model/codegen.py
-
BINsrc/model/codegen.pyc
-
17src/model/controller.py
-
BINsrc/model/controller.pyc
-
141src/model/example_argparse_souce.py
-
56src/model/gui.py
-
276src/model/source_parser.py
-
34src/model/test_queue.py
-
0src/parser/MultiChoiceOption.py
-
0src/parser/RequiredOption.py
-
0src/parser/__init__.py
-
0src/parser/asdfasdf.py
-
0src/parser/example.py
-
14src/parser/option.py
@ -0,0 +1,17 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<projectDescription> |
|||
<name>Gooey</name> |
|||
<comment></comment> |
|||
<projects> |
|||
</projects> |
|||
<buildSpec> |
|||
<buildCommand> |
|||
<name>org.python.pydev.PyDevBuilder</name> |
|||
<arguments> |
|||
</arguments> |
|||
</buildCommand> |
|||
</buildSpec> |
|||
<natures> |
|||
<nature>org.python.pydev.pythonNature</nature> |
|||
</natures> |
|||
</projectDescription> |
@ -0,0 +1,8 @@ |
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
|||
<?eclipse-pydev version="1.0"?><pydev_project> |
|||
<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH"> |
|||
<path>/${PROJECT_DIR_NAME}/src</path> |
|||
</pydev_pathproperty> |
|||
<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.7</pydev_property> |
|||
<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">C:\Python27\python.exe</pydev_property> |
|||
</pydev_project> |
@ -0,0 +1,3 @@ |
|||
eclipse.preferences.version=1 |
|||
encoding//src/model/codegen.py=utf-8 |
|||
encoding//src/model/example_argparse_souce.py=utf-8 |
@ -0,0 +1,43 @@ |
|||
''' |
|||
Created on Dec 28, 2013 |
|||
|
|||
@author: Chris |
|||
''' |
|||
|
|||
import wx |
|||
from wx.lib.scrolledpanel import ScrolledPanel |
|||
|
|||
|
|||
class AdvancedConfigPanel(ScrolledPanel): |
|||
''' |
|||
Abstract class for the Footer panels. |
|||
''' |
|||
def __init__(self, parent, **kwargs): |
|||
ScrolledPanel.__init__(self, parent, **kwargs) |
|||
self.SetupScrolling() |
|||
|
|||
self.components = [] |
|||
|
|||
self.container = wx.BoxSizer(wx.VERTICAL) |
|||
self.container.AddSpacer(10) |
|||
self.AddRequiredArgsHeaderMsg() |
|||
|
|||
|
|||
|
|||
def AddRequiredArgsHeaderMsg(self): |
|||
required_msg = wx.StaticText(self, label="Required Arguments") |
|||
self.container.Add(required_msg, 0, wx.LEFT | wx.RIGHT, 20) |
|||
|
|||
def AddRequiredWidgets(self, factory): |
|||
widgets = factory._positionals |
|||
for widget in widgets: |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
@ -0,0 +1,26 @@ |
|||
''' |
|||
Created on Dec 23, 2013 |
|||
|
|||
@author: Chris |
|||
''' |
|||
|
|||
import wx |
|||
|
|||
class BodyDisplayPanel(wx.Panel): |
|||
def __init__(self, parent, **kwargs): |
|||
wx.Panel.__init__(self, parent, **kwargs) |
|||
|
|||
self.SetBackgroundColour('#F0F0F0') |
|||
|
|||
sizer = wx.BoxSizer(wx.VERTICAL) |
|||
sizer.AddSpacer(10) |
|||
text = wx.StaticText(self, label="Running bla bla bla") |
|||
sizer.Add(text, 0, wx.LEFT, 20) |
|||
sizer.AddSpacer(10) |
|||
|
|||
self.cmd_textbox = wx.TextCtrl( |
|||
self, -1, "", |
|||
style=wx.TE_MULTILINE | wx.TE_READONLY) |
|||
sizer.Add(self.cmd_textbox, 1, wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, 20) |
|||
self.SetSizer(sizer) |
|||
|
@ -0,0 +1,132 @@ |
|||
''' |
|||
Created on Dec 8, 2013 |
|||
|
|||
@author: Chris |
|||
''' |
|||
|
|||
import wx |
|||
from argparse import ( |
|||
_StoreAction, _StoreConstAction, |
|||
_StoreFalseAction, _StoreTrueAction, |
|||
_CountAction, _AppendAction) |
|||
|
|||
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 |
|||
|
|||
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('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__': |
|||
pass |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
@ -0,0 +1,107 @@ |
|||
''' |
|||
Created on Dec 8, 2013 |
|||
|
|||
@author: Chris |
|||
''' |
|||
|
|||
import wx |
|||
import os |
|||
import sys |
|||
import threading |
|||
from model.controller import Controller |
|||
from app.images import image_store |
|||
from app.dialogs.header import FrameHeader |
|||
from app.dialogs.body import BodyDisplayPanel |
|||
from app.dialogs.footer import ConfigFooter |
|||
|
|||
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 MainWindow(wx.Frame): |
|||
|
|||
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 |
|||
|
|||
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._frame_header = FrameHeader |
|||
self._simple_config_body = None |
|||
self._adv_config_body = None |
|||
self._config_footer = None |
|||
self._output_footer = None |
|||
|
|||
self._init_components() |
|||
|
|||
self.queue = queue |
|||
# the client's main function |
|||
self._payload = payload |
|||
|
|||
_stdout = sys.stdout |
|||
sys.stdout = MessagePump(queue) |
|||
listener = MainWindow.Listener(queue, self.panel2.cmd_textbox) |
|||
listener.start() |
|||
|
|||
def _init_components(self): |
|||
# init components |
|||
self.SetMinSize((400,300)) |
|||
self.icon = wx.Icon(image_store.icon, wx.BITMAP_TYPE_ICO) |
|||
self.SetIcon(self.icon) |
|||
|
|||
panel1 = FrameHeader(image_path=image_store.computer3, parent=self, size=(30,90)) |
|||
|
|||
self.sizer = wx.BoxSizer(wx.VERTICAL) |
|||
self.sizer.Add(panel1, 0, wx.EXPAND) |
|||
|
|||
self._draw_horizontal_line() |
|||
|
|||
self.panel2 = BodyDisplayPanel(parent=self) |
|||
self.sizer.Add(self.panel2, 1, wx.EXPAND) |
|||
self.SetSizer(self.sizer) |
|||
|
|||
self._draw_horizontal_line() |
|||
|
|||
self.footer = ConfigFooter(self, self._controller) |
|||
self.sizer.Add(self.footer, 0, wx.EXPAND) |
|||
|
|||
def _draw_horizontal_line(self): |
|||
line = wx.StaticLine(self, -1, style=wx.LI_HORIZONTAL) |
|||
line.SetSize((10, 10)) |
|||
self.sizer.Add(line, 0, wx.EXPAND) |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
@ -0,0 +1,51 @@ |
|||
''' |
|||
Created on Dec 28, 2013 |
|||
|
|||
@author: Chris |
|||
''' |
|||
import os |
|||
import wx |
|||
from wx.lib import scrolledpanel |
|||
from app.dialogs.advanced_config import AdvancedConfigPanel |
|||
|
|||
class MainWindow(wx.Frame): |
|||
|
|||
def __init__(self): |
|||
wx.Frame.__init__( |
|||
self, |
|||
parent=None, |
|||
id=-1, |
|||
title=os.path.basename(__file__), |
|||
size=(640,480) |
|||
) |
|||
|
|||
self._init_components() |
|||
|
|||
def _init_components(self): |
|||
# init components |
|||
self.SetMinSize((400,300)) |
|||
|
|||
panel = AdvancedConfigPanel(self) |
|||
|
|||
sizer = wx.BoxSizer(wx.VERTICAL) |
|||
|
|||
# for i in range(40): |
|||
# t = wx.TextCtrl(panel, -1) |
|||
# sizer.Add(t, 0) |
|||
|
|||
panel.SetSizer(sizer) |
|||
|
|||
_sizer = wx.BoxSizer(wx.VERTICAL) |
|||
_sizer.Add(panel, 1, wx.EXPAND) |
|||
self.SetSizer(_sizer) |
|||
|
|||
def _draw_horizontal_line(self): |
|||
line = wx.StaticLine(self, -1, style=wx.LI_HORIZONTAL) |
|||
line.SetSize((10, 10)) |
|||
self.sizer.Add(line, 0, wx.EXPAND) |
|||
|
|||
if __name__ == '__main__': |
|||
app = wx.App(False) |
|||
frame = MainWindow() |
|||
frame.Show(True) # Show the frame. |
|||
app.MainLoop() |
@ -0,0 +1,80 @@ |
|||
''' |
|||
Created on Dec 23, 2013 |
|||
|
|||
@author: Chris |
|||
''' |
|||
|
|||
import wx |
|||
|
|||
class AbstractFooter(wx.Panel): |
|||
''' |
|||
Abstract class for the Footer panels. |
|||
''' |
|||
def __init__(self, parent, **kwargs): |
|||
wx.Panel.__init__(self, parent, **kwargs) |
|||
self.SetMinSize((30, 50)) |
|||
|
|||
self.cancel_button = self._button('Cancel', wx.ID_CANCEL) |
|||
self.next_button = self._button("Next", wx.ID_OK) |
|||
|
|||
sizer = wx.BoxSizer(wx.HORIZONTAL) |
|||
sizer.AddStretchSpacer(1) |
|||
sizer.Add(self.cancel_button, 0, wx.ALIGN_RIGHT | wx.RIGHT | wx.TOP, 20) |
|||
sizer.Add(self.next_button, 0, wx.ALIGN_RIGHT | wx.RIGHT | wx.TOP, 20) |
|||
self.SetSizer(sizer) |
|||
|
|||
def _button(self,label=None, style=None): |
|||
return wx.Button( |
|||
parent=self, |
|||
id=-1, |
|||
size=(75, 23), |
|||
label=label, |
|||
style=style) |
|||
|
|||
|
|||
class ConfigFooter(AbstractFooter): |
|||
''' |
|||
Footer section used on the configuration |
|||
screen of the application |
|||
|
|||
args: |
|||
parent: wxPython parent window |
|||
controller: controller class used in delagating all the commands |
|||
''' |
|||
|
|||
def __init__(self, parent, controller, **kwargs): |
|||
AbstractFooter.__init__(self, parent, **kwargs) |
|||
|
|||
self._controller = controller |
|||
self.Bind(wx.EVT_BUTTON, self.OnConfigCancel, self.cancel_button) |
|||
self.Bind(wx.EVT_BUTTON, self.OnConfigNext, self.next_button) |
|||
|
|||
def OnConfigCancel(self, event): |
|||
self._controller.OnConfigCancel(event) |
|||
|
|||
def OnConfigNext(self, event): |
|||
self._controller.OnConfigNext(event) |
|||
|
|||
|
|||
class MainFooter(AbstractFooter): |
|||
''' |
|||
Footer section used on the Main Status |
|||
screen of the application |
|||
|
|||
args: |
|||
parent: wxPython parent window |
|||
controller: controller class used in delagating all the commands |
|||
''' |
|||
def __init__(self, parent, controller, **kwargs): |
|||
AbstractFooter.__init__(self, parent, **kwargs) |
|||
|
|||
self._controller = controller |
|||
|
|||
self.Bind(wx.EVT_BUTTON, self.OnConfigCancel, self.cancel_button) |
|||
self.Bind(wx.EVT_BUTTON, self.OnConfigNext, self.next_button) |
|||
|
|||
def OnMainCancel(self, event): |
|||
self._controller.OnMainCancel(event) |
|||
|
|||
def OnMainNext(self, event): |
|||
self._controller.OnMainNext(event) |
@ -0,0 +1,71 @@ |
|||
''' |
|||
Created on Dec 23, 2013 |
|||
|
|||
@author: Chris |
|||
''' |
|||
|
|||
import wx |
|||
|
|||
class FrameHeader(wx.Panel): |
|||
|
|||
def __init__(self, |
|||
heading="Doin Stuff here", |
|||
subheading="Small notification or intructional message", |
|||
image_path=None, |
|||
dlg_style=1, |
|||
**kwargs): |
|||
|
|||
wx.Panel.__init__(self, **kwargs) |
|||
self.SetBackgroundColour('#ffffff') |
|||
self.SetMinSize((120, 90)) |
|||
|
|||
header = self._bold_static_text(label=heading) |
|||
subheader = wx.StaticText(self, label=subheading) |
|||
img = self._load_image(image_path) |
|||
|
|||
sizer = wx.BoxSizer(wx.HORIZONTAL) |
|||
headings_sizer = self.build_heading_sizer(header, subheader) |
|||
sizer.Add(headings_sizer, 1, wx.ALIGN_LEFT | wx.EXPAND | wx.LEFT, 20) |
|||
sizer.Add(img, 0, wx.ALIGN_RIGHT | wx.EXPAND | wx.RIGHT, 20) |
|||
self.SetSizer(sizer) |
|||
|
|||
# for i in dir(self): print i |
|||
|
|||
def _load_image(self, image_path): |
|||
try: |
|||
bitmap = wx.Bitmap(image_path) |
|||
|
|||
bitmap = self._resize_bitmap(bitmap) |
|||
return wx.StaticBitmap(self, -1, bitmap) |
|||
except: |
|||
raise IOError('Invalid Image path') |
|||
|
|||
def _resize_bitmap(self, bmap): |
|||
''' |
|||
Resizes a bitmap to a height of 89 pixels (the |
|||
size of the top panel), while keeping aspect ratio |
|||
in tact |
|||
''' |
|||
image = wx.ImageFromBitmap(bmap) |
|||
width, height = image.GetSize() |
|||
ratio = float(width) / height |
|||
target_height = 79 |
|||
image = image.Scale(target_height * ratio, target_height, |
|||
wx.IMAGE_QUALITY_HIGH |
|||
) |
|||
return wx.BitmapFromImage(image) |
|||
|
|||
def _bold_static_text(self, label): |
|||
txt = wx.StaticText(self, label=label) |
|||
txt.SetFont(wx.Font(8, wx.FONTFAMILY_DEFAULT, |
|||
wx.FONTWEIGHT_NORMAL, wx.FONTWEIGHT_BOLD, False) |
|||
) |
|||
return txt |
|||
|
|||
def build_heading_sizer(self, header, subheader): |
|||
sizer = wx.BoxSizer(wx.VERTICAL) |
|||
sizer.AddStretchSpacer(1) |
|||
sizer.Add(header, 1) |
|||
sizer.Add(subheader, 1) |
|||
sizer.AddStretchSpacer(1) |
|||
return sizer |
@ -0,0 +1,54 @@ |
|||
''' |
|||
Created on Dec 9, 2013 |
|||
|
|||
@author: Chris |
|||
|
|||
|
|||
''' |
|||
|
|||
import wx |
|||
import os |
|||
|
|||
class BodyDisplayPanel(wx.Panel): |
|||
def __init__(self, parent, **kwargs): |
|||
wx.Panel.__init__(self, parent, **kwargs) |
|||
|
|||
self.SetBackgroundColour('#F0F0F0') |
|||
|
|||
sizer = wx.BoxSizer(wx.VERTICAL) |
|||
sizer.AddSpacer(10) |
|||
|
|||
# about_header = wx.StaticText(self, label="About") |
|||
# about_header = self._bold_static_text("About") |
|||
# about_body = wx.StaticText(self, label="This program does bla. Enter the command line args of your choice to control bla and bla.") |
|||
# |
|||
# sizer.Add(about_header, 0, wx.LEFT | wx.RIGHT, 20) |
|||
# sizer.AddSpacer(5) |
|||
# sizer.Add(about_body, 0, wx.LEFT | wx.RIGHT, 20) |
|||
|
|||
sizer.AddSpacer(40) |
|||
|
|||
text = self._bold_static_text("Enter Command Line Arguments") |
|||
# |
|||
sizer.Add(text, 0, wx.LEFT, 20) |
|||
sizer.AddSpacer(10) |
|||
|
|||
h_sizer = wx.BoxSizer(wx.HORIZONTAL) |
|||
self.cmd_textbox = wx.TextCtrl( |
|||
self, -1, "") |
|||
h_sizer.Add(self.cmd_textbox, 1, wx.ALL | wx.EXPAND) |
|||
sizer.Add(h_sizer, 0, wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, 20) |
|||
|
|||
self.SetSizer(sizer) |
|||
|
|||
def get_contents(self): |
|||
return self.cmd_textbox.GetValue() |
|||
|
|||
def _bold_static_text(self, text_label): |
|||
bold = wx.Font(8, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD) |
|||
text = wx.StaticText(self, label=text_label) |
|||
text.SetFont(bold) |
|||
return text |
|||
|
|||
|
|||
|
@ -0,0 +1,15 @@ |
|||
''' |
|||
Created on Dec 8, 2013 |
|||
|
|||
@author: Chris |
|||
''' |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
# im = Image.open(images.computer) |
@ -0,0 +1,60 @@ |
|||
''' |
|||
generates the internals of the image_store module |
|||
|
|||
Nice perk of this approach is that it turns path errors into |
|||
things that lint can catch, rather than something that gets stumbled |
|||
upon randomly at runtime. |
|||
''' |
|||
|
|||
|
|||
import os |
|||
|
|||
PATH = __path__[0] |
|||
print PATH |
|||
|
|||
def render_class(assignments): |
|||
template = ''' |
|||
""" |
|||
GENERATED CODE: DO NOT EDIT |
|||
|
|||
Simple mapping of image names to their location on disc. |
|||
Convenience module for keeping the filepaths in one place. |
|||
|
|||
""" |
|||
|
|||
{variables} |
|||
''' |
|||
return template.format(variables=assignments) |
|||
|
|||
|
|||
def load_imagepaths(): |
|||
file_extension = lambda x: os.path.splitext(x)[-1] |
|||
|
|||
return [os.path.join(PATH, f) for f in os.listdir(PATH) |
|||
if file_extension(f) in ('.jpeg','.png', '.ico')] |
|||
|
|||
|
|||
|
|||
def write_module(contents): |
|||
module_path = os.path.join(PATH, 'image_store.py') |
|||
with open(module_path, 'wb') as f: |
|||
f.write(contents) |
|||
|
|||
|
|||
def build_assignments(paths): |
|||
get_name = lambda x: os.path.splitext(os.path.split(x)[-1])[0] |
|||
|
|||
assignments = ('%s = r"%s"' % (get_name(p), p) |
|||
for p in paths) |
|||
return '\n'.join(assignments) |
|||
|
|||
paths = load_imagepaths() |
|||
assignments = build_assignments(paths) |
|||
write_module(render_class(assignments)) |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
@ -0,0 +1,14 @@ |
|||
|
|||
""" |
|||
GENERATED CODE: DO NOT EDIT |
|||
|
|||
Simple mapping of image names to their location on disc. |
|||
Convenience module for keeping the filepaths in one place. |
|||
|
|||
""" |
|||
|
|||
computer = r"C:\Users\Chris\Dropbox\pretty_gui\Gui\src\app\images\computer.png" |
|||
computer2 = r"C:\Users\Chris\Dropbox\pretty_gui\Gui\src\app\images\computer2.png" |
|||
computer3 = r"C:\Users\Chris\Dropbox\pretty_gui\Gui\src\app\images\computer3.png" |
|||
icon = r"C:\Users\Chris\Dropbox\pretty_gui\Gui\src\app\images\icon.ico" |
|||
terminal = r"C:\Users\Chris\Dropbox\pretty_gui\Gui\src\app\images\terminal.png" |
@ -0,0 +1,21 @@ |
|||
''' |
|||
Created on Dec 8, 2013 |
|||
|
|||
@author: Chris |
|||
''' |
|||
|
|||
import wx |
|||
import Queue |
|||
from dialogs.display_main import MainWindow |
|||
|
|||
|
|||
if __name__ == '__main__': |
|||
queue = Queue.Queue() |
|||
# stdoutput = sys.stdout |
|||
# out = TestObj(queue) |
|||
# sys.stdout = out |
|||
|
|||
app = wx.App(False) |
|||
frame = MainWindow(queue) |
|||
frame.Show(True) # Show the frame. |
|||
app.MainLoop() |
@ -0,0 +1,32 @@ |
|||
''' |
|||
Created on Dec 21, 2013 |
|||
|
|||
@author: Chris |
|||
''' |
|||
import sys |
|||
from time import time as _time |
|||
from time import sleep as _sleep |
|||
from argparse import ArgumentParser |
|||
import hashlib |
|||
|
|||
def main(): |
|||
|
|||
my_cool_parser = ArgumentParser(description="Mock application to test @Gui's functionality") |
|||
my_cool_parser.add_argument('-c', '--countdown', default=10, type=int, help='sets the time to count down from') |
|||
my_cool_parser.add_argument("-s", "--showtime", action="store_true", help="display the countdown timer") |
|||
my_cool_parser.add_argument("-w", "--whatevs", default="No, NOT whatevs", help="...") |
|||
args = my_cool_parser.parse_args() |
|||
|
|||
start_time = _time() |
|||
print 'Counting down from %s' % args.countdown |
|||
while _time() - start_time < args.countdown: |
|||
if args.showtime: |
|||
print 'printing message at: %s' % _time() |
|||
else: |
|||
print 'printing message at: %s' % hashlib.md5(str(_time())).hexdigest() |
|||
_sleep(.5) |
|||
print 'Finished running the program. Byeeeeesss!' |
|||
|
|||
if __name__ == '__main__': |
|||
sys.argv.append('-sc 5') |
|||
main() |
@ -0,0 +1,572 @@ |
|||
# -*- coding: utf-8 -*- |
|||
""" |
|||
codegen |
|||
~~~~~~~ |
|||
|
|||
Extension to ast that allow ast -> python code generation. |
|||
|
|||
:copyright: Copyright 2008 by Armin Ronacher. |
|||
:license: BSD. |
|||
""" |
|||
from ast import * |
|||
|
|||
|
|||
BOOLOP_SYMBOLS = { |
|||
And: 'and', |
|||
Or: 'or' |
|||
} |
|||
|
|||
BINOP_SYMBOLS = { |
|||
Add: '+', |
|||
Sub: '-', |
|||
Mult: '*', |
|||
Div: '/', |
|||
FloorDiv: '//', |
|||
Mod: '%', |
|||
LShift: '<<', |
|||
RShift: '>>', |
|||
BitOr: '|', |
|||
BitAnd: '&', |
|||
BitXor: '^' |
|||
} |
|||
|
|||
CMPOP_SYMBOLS = { |
|||
Eq: '==', |
|||
Gt: '>', |
|||
GtE: '>=', |
|||
In: 'in', |
|||
Is: 'is', |
|||
IsNot: 'is not', |
|||
Lt: '<', |
|||
LtE: '<=', |
|||
NotEq: '!=', |
|||
NotIn: 'not in' |
|||
} |
|||
|
|||
UNARYOP_SYMBOLS = { |
|||
Invert: '~', |
|||
Not: 'not', |
|||
UAdd: '+', |
|||
USub: '-' |
|||
} |
|||
|
|||
ALL_SYMBOLS = {} |
|||
ALL_SYMBOLS.update(BOOLOP_SYMBOLS) |
|||
ALL_SYMBOLS.update(BINOP_SYMBOLS) |
|||
ALL_SYMBOLS.update(CMPOP_SYMBOLS) |
|||
ALL_SYMBOLS.update(UNARYOP_SYMBOLS) |
|||
|
|||
|
|||
def to_source(node, indent_with=' ' * 4, add_line_information=False): |
|||
"""This function can convert a node tree back into python sourcecode. |
|||
This is useful for debugging purposes, especially if you're dealing with |
|||
custom asts not generated by python itself. |
|||
|
|||
It could be that the sourcecode is evaluable when the AST itself is not |
|||
compilable / evaluable. The reason for this is that the AST contains some |
|||
more data than regular sourcecode does, which is dropped during |
|||
conversion. |
|||
|
|||
Each level of indentation is replaced with `indent_with`. Per default this |
|||
parameter is equal to four spaces as suggested by PEP 8, but it might be |
|||
adjusted to match the application's styleguide. |
|||
|
|||
If `add_line_information` is set to `True` comments for the line numbers |
|||
of the nodes are added to the output. This can be used to spot wrong line |
|||
number information of statement nodes. |
|||
""" |
|||
generator = SourceGenerator(indent_with, add_line_information) |
|||
generator.visit(node) |
|||
return ''.join(generator.result) |
|||
|
|||
|
|||
class SourceGenerator(NodeVisitor): |
|||
"""This visitor is able to transform a well formed syntax tree into python |
|||
sourcecode. For more details have a look at the docstring of the |
|||
`node_to_source` function. |
|||
""" |
|||
|
|||
def __init__(self, indent_with, add_line_information=False): |
|||
self.result = [] |
|||
self.indent_with = indent_with |
|||
self.add_line_information = add_line_information |
|||
self.indentation = 0 |
|||
self.new_lines = 0 |
|||
|
|||
def write(self, x): |
|||
if self.new_lines: |
|||
if self.result: |
|||
self.result.append('\n' * self.new_lines) |
|||
self.result.append(self.indent_with * self.indentation) |
|||
self.new_lines = 0 |
|||
self.result.append(x) |
|||
|
|||
def newline(self, node=None, extra=0): |
|||
self.new_lines = max(self.new_lines, 1 + extra) |
|||
if node is not None and self.add_line_information: |
|||
self.write('# line: %s' % node.lineno) |
|||
self.new_lines = 1 |
|||
|
|||
def body(self, statements): |
|||
self.new_line = True |
|||
self.indentation += 1 |
|||
for stmt in statements: |
|||
self.visit(stmt) |
|||
self.indentation -= 1 |
|||
|
|||
def body_or_else(self, node): |
|||
self.body(node.body) |
|||
if node.orelse: |
|||
self.newline() |
|||
self.write('else:') |
|||
self.body(node.orelse) |
|||
|
|||
def signature(self, node): |
|||
want_comma = [] |
|||
def write_comma(): |
|||
if want_comma: |
|||
self.write(', ') |
|||
else: |
|||
want_comma.append(True) |
|||
|
|||
padding = [None] * (len(node.args) - len(node.defaults)) |
|||
for arg, default in zip(node.args, padding + node.defaults): |
|||
write_comma() |
|||
self.visit(arg) |
|||
if default is not None: |
|||
self.write('=') |
|||
self.visit(default) |
|||
if node.vararg is not None: |
|||
write_comma() |
|||
self.write('*' + node.vararg) |
|||
if node.kwarg is not None: |
|||
write_comma() |
|||
self.write('**' + node.kwarg) |
|||
|
|||
def decorators(self, node): |
|||
for decorator in node.decorator_list: |
|||
self.newline(decorator) |
|||
self.write('@') |
|||
self.visit(decorator) |
|||
|
|||
# Statements |
|||
|
|||
def visit_Assign(self, node): |
|||
self.newline(node) |
|||
for idx, target in enumerate(node.targets): |
|||
if idx: |
|||
self.write(', ') |
|||
self.visit(target) |
|||
self.write(' = ') |
|||
self.visit(node.value) |
|||
|
|||
def visit_AugAssign(self, node): |
|||
self.newline(node) |
|||
self.visit(node.target) |
|||
self.write(BINOP_SYMBOLS[type(node.op)] + '=') |
|||
self.visit(node.value) |
|||
|
|||
def visit_ImportFrom(self, node): |
|||
self.newline(node) |
|||
self.write('from %s%s import ' % ('.' * node.level, node.module)) |
|||
for idx, item in enumerate(node.names): |
|||
if idx: |
|||
self.write(', ') |
|||
self.write(item) |
|||
|
|||
def visit_Import(self, node): |
|||
self.newline(node) |
|||
for item in node.names: |
|||
self.write('import ') |
|||
self.visit(item) |
|||
|
|||
def visit_Expr(self, node): |
|||
self.newline(node) |
|||
self.generic_visit(node) |
|||
|
|||
def visit_FunctionDef(self, node): |
|||
self.newline(extra=1) |
|||
self.decorators(node) |
|||
self.newline(node) |
|||
self.write('def %s(' % node.name) |
|||
self.signature(node.args) |
|||
self.write('):') |
|||
self.body(node.body) |
|||
|
|||
def visit_ClassDef(self, node): |
|||
have_args = [] |
|||
def paren_or_comma(): |
|||
if have_args: |
|||
self.write(', ') |
|||
else: |
|||
have_args.append(True) |
|||
self.write('(') |
|||
|
|||
self.newline(extra=2) |
|||
self.decorators(node) |
|||
self.newline(node) |
|||
self.write('class %s' % node.name) |
|||
for base in node.bases: |
|||
paren_or_comma() |
|||
self.visit(base) |
|||
# XXX: the if here is used to keep this module compatible |
|||
# with python 2.6. |
|||
if hasattr(node, 'keywords'): |
|||
for keyword in node.keywords: |
|||
paren_or_comma() |
|||
self.write(keyword.arg + '=') |
|||
self.visit(keyword.value) |
|||
if node.starargs is not None: |
|||
paren_or_comma() |
|||
self.write('*') |
|||
self.visit(node.starargs) |
|||
if node.kwargs is not None: |
|||
paren_or_comma() |
|||
self.write('**') |
|||
self.visit(node.kwargs) |
|||
self.write(have_args and '):' or ':') |
|||
self.body(node.body) |
|||
|
|||
def visit_If(self, node): |
|||
self.newline(node) |
|||
self.write('if ') |
|||
self.visit(node.test) |
|||
self.write(':') |
|||
self.body(node.body) |
|||
while True: |
|||
else_ = node.orelse |
|||
if len(else_) == 1 and isinstance(else_[0], If): |
|||
node = else_[0] |
|||
self.newline() |
|||
self.write('elif ') |
|||
self.visit(node.test) |
|||
self.write(':') |
|||
self.body(node.body) |
|||
else: |
|||
self.newline() |
|||
self.write('else:') |
|||
self.body(else_) |
|||
break |
|||
|
|||
def visit_For(self, node): |
|||
self.newline(node) |
|||
self.write('for ') |
|||
self.visit(node.target) |
|||
self.write(' in ') |
|||
self.visit(node.iter) |
|||
self.write(':') |
|||
self.body_or_else(node) |
|||
|
|||
def visit_While(self, node): |
|||
self.newline(node) |
|||
self.write('while ') |
|||
self.visit(node.test) |
|||
self.write(':') |
|||
self.body_or_else(node) |
|||
|
|||
def visit_With(self, node): |
|||
self.newline(node) |
|||
self.write('with ') |
|||
self.visit(node.context_expr) |
|||
if node.optional_vars is not None: |
|||
self.write(' as ') |
|||
self.visit(node.optional_vars) |
|||
self.write(':') |
|||
self.body(node.body) |
|||
|
|||
def visit_Pass(self, node): |
|||
self.newline(node) |
|||
self.write('pass') |
|||
|
|||
def visit_Print(self, node): |
|||
# XXX: python 2.6 only |
|||
self.newline(node) |
|||
self.write('print ') |
|||
want_comma = False |
|||
if node.dest is not None: |
|||
self.write(' >> ') |
|||
self.visit(node.dest) |
|||
want_comma = True |
|||
for value in node.values: |
|||
if want_comma: |
|||
self.write(', ') |
|||
self.visit(value) |
|||
want_comma = True |
|||
if not node.nl: |
|||
self.write(',') |
|||
|
|||
def visit_Delete(self, node): |
|||
self.newline(node) |
|||
self.write('del ') |
|||
for idx, target in enumerate(node): |
|||
if idx: |
|||
self.write(', ') |
|||
self.visit(target) |
|||
|
|||
def visit_TryExcept(self, node): |
|||
self.newline(node) |
|||
self.write('try:') |
|||
self.body(node.body) |
|||
for handler in node.handlers: |
|||
self.visit(handler) |
|||
|
|||
def visit_TryFinally(self, node): |
|||
self.newline(node) |
|||
self.write('try:') |
|||
self.body(node.body) |
|||
self.newline(node) |
|||
self.write('finally:') |
|||
self.body(node.finalbody) |
|||
|
|||
def visit_Global(self, node): |
|||
self.newline(node) |
|||
self.write('global ' + ', '.join(node.names)) |
|||
|
|||
def visit_Nonlocal(self, node): |
|||
self.newline(node) |
|||
self.write('nonlocal ' + ', '.join(node.names)) |
|||
|
|||
def visit_Return(self, node): |
|||
self.newline(node) |
|||
self.write('return ') |
|||
self.visit(node.value) |
|||
|
|||
def visit_Break(self, node): |
|||
self.newline(node) |
|||
self.write('break') |
|||
|
|||
def visit_Continue(self, node): |
|||
self.newline(node) |
|||
self.write('continue') |
|||
|
|||
def visit_Raise(self, node): |
|||
# XXX: Python 2.6 / 3.0 compatibility |
|||
self.newline(node) |
|||
self.write('raise') |
|||
if hasattr(node, 'exc') and node.exc is not None: |
|||
self.write(' ') |
|||
self.visit(node.exc) |
|||
if node.cause is not None: |
|||
self.write(' from ') |
|||
self.visit(node.cause) |
|||
elif hasattr(node, 'type') and node.type is not None: |
|||
self.visit(node.type) |
|||
if node.inst is not None: |
|||
self.write(', ') |
|||
self.visit(node.inst) |
|||
if node.tback is not None: |
|||
self.write(', ') |
|||
self.visit(node.tback) |
|||
|
|||
# Expressions |
|||
|
|||
def visit_Attribute(self, node): |
|||
self.visit(node.value) |
|||
self.write('.' + node.attr) |
|||
|
|||
def visit_Call(self, node): |
|||
want_comma = [] |
|||
def write_comma(): |
|||
if want_comma: |
|||
self.write(', ') |
|||
else: |
|||
want_comma.append(True) |
|||
|
|||
self.visit(node.func) |
|||
self.write('(') |
|||
for arg in node.args: |
|||
write_comma() |
|||
self.visit(arg) |
|||
for keyword in node.keywords: |
|||
write_comma() |
|||
self.write(keyword.arg + '=') |
|||
self.visit(keyword.value) |
|||
if node.starargs is not None: |
|||
write_comma() |
|||
self.write('*') |
|||
self.visit(node.starargs) |
|||
if node.kwargs is not None: |
|||
write_comma() |
|||
self.write('**') |
|||
self.visit(node.kwargs) |
|||
self.write(')') |
|||
|
|||
def visit_Name(self, node): |
|||
self.write(node.id) |
|||
|
|||
def visit_Str(self, node): |
|||
self.write(repr(node.s)) |
|||
|
|||
def visit_Bytes(self, node): |
|||
self.write(repr(node.s)) |
|||
|
|||
def visit_Num(self, node): |
|||
self.write(repr(node.n)) |
|||
|
|||
def visit_Tuple(self, node): |
|||
self.write('(') |
|||
idx = -1 |
|||
for idx, item in enumerate(node.elts): |
|||
if idx: |
|||
self.write(', ') |
|||
self.visit(item) |
|||
self.write(idx and ')' or ',)') |
|||
|
|||
def sequence_visit(left, right): |
|||
def visit(self, node): |
|||
self.write(left) |
|||
for idx, item in enumerate(node.elts): |
|||
if idx: |
|||
self.write(', ') |
|||
self.visit(item) |
|||
self.write(right) |
|||
return visit |
|||
|
|||
visit_List = sequence_visit('[', ']') |
|||
visit_Set = sequence_visit('{', '}') |
|||
del sequence_visit |
|||
|
|||
def visit_Dict(self, node): |
|||
self.write('{') |
|||
for idx, (key, value) in enumerate(zip(node.keys, node.values)): |
|||
if idx: |
|||
self.write(', ') |
|||
self.visit(key) |
|||
self.write(': ') |
|||
self.visit(value) |
|||
self.write('}') |
|||
|
|||
def visit_BinOp(self, node): |
|||
self.visit(node.left) |
|||
self.write(' %s ' % BINOP_SYMBOLS[type(node.op)]) |
|||
self.visit(node.right) |
|||
|
|||
def visit_BoolOp(self, node): |
|||
self.write('(') |
|||
for idx, value in enumerate(node.values): |
|||
if idx: |
|||
self.write(' %s ' % BOOLOP_SYMBOLS[type(node.op)]) |
|||
self.visit(value) |
|||
self.write(')') |
|||
|
|||
def visit_Compare(self, node): |
|||
self.write('(') |
|||
self.write(node.left) |
|||
for op, right in zip(node.ops, node.comparators): |
|||
self.write(' %s %%' % CMPOP_SYMBOLS[type(op)]) |
|||
self.visit(right) |
|||
self.write(')') |
|||
|
|||
def visit_UnaryOp(self, node): |
|||
self.write('(') |
|||
op = UNARYOP_SYMBOLS[type(node.op)] |
|||
self.write(op) |
|||
if op == 'not': |
|||
self.write(' ') |
|||
self.visit(node.operand) |
|||
self.write(')') |
|||
|
|||
def visit_Subscript(self, node): |
|||
self.visit(node.value) |
|||
self.write('[') |
|||
self.visit(node.slice) |
|||
self.write(']') |
|||
|
|||
def visit_Slice(self, node): |
|||
if node.lower is not None: |
|||
self.visit(node.lower) |
|||
self.write(':') |
|||
if node.upper is not None: |
|||
self.visit(node.upper) |
|||
if node.step is not None: |
|||
self.write(':') |
|||
if not (isinstance(node.step, Name) and node.step.id == 'None'): |
|||
self.visit(node.step) |
|||
|
|||
def visit_ExtSlice(self, node): |
|||
for idx, item in node.dims: |
|||
if idx: |
|||
self.write(', ') |
|||
self.visit(item) |
|||
|
|||
def visit_Yield(self, node): |
|||
self.write('yield ') |
|||
self.visit(node.value) |
|||
|
|||
def visit_Lambda(self, node): |
|||
self.write('lambda ') |
|||
self.signature(node.args) |
|||
self.write(': ') |
|||
self.visit(node.body) |
|||
|
|||
def visit_Ellipsis(self, node): |
|||
self.write('Ellipsis') |
|||
|
|||
def generator_visit(left, right): |
|||
def visit(self, node): |
|||
self.write(left) |
|||
self.visit(node.elt) |
|||
for comprehension in node.generators: |
|||
self.visit(comprehension) |
|||
self.write(right) |
|||
return visit |
|||
|
|||
visit_ListComp = generator_visit('[', ']') |
|||
visit_GeneratorExp = generator_visit('(', ')') |
|||
visit_SetComp = generator_visit('{', '}') |
|||
del generator_visit |
|||
|
|||
def visit_DictComp(self, node): |
|||
self.write('{') |
|||
self.visit(node.key) |
|||
self.write(': ') |
|||
self.visit(node.value) |
|||
for comprehension in node.generators: |
|||
self.visit(comprehension) |
|||
self.write('}') |
|||
|
|||
def visit_IfExp(self, node): |
|||
self.visit(node.body) |
|||
self.write(' if ') |
|||
self.visit(node.test) |
|||
self.write(' else ') |
|||
self.visit(node.orelse) |
|||
|
|||
def visit_Starred(self, node): |
|||
self.write('*') |
|||
self.visit(node.value) |
|||
|
|||
def visit_Repr(self, node): |
|||
# XXX: python 2.6 only |
|||
self.write('`') |
|||
self.visit(node.value) |
|||
self.write('`') |
|||
|
|||
# Helper Nodes |
|||
|
|||
def visit_alias(self, node): |
|||
self.write(node.name) |
|||
if node.asname is not None: |
|||
self.write(' as ' + node.asname) |
|||
|
|||
def visit_comprehension(self, node): |
|||
self.write(' for ') |
|||
self.visit(node.target) |
|||
self.write(' in ') |
|||
self.visit(node.iter) |
|||
if node.ifs: |
|||
for if_ in node.ifs: |
|||
self.write(' if ') |
|||
self.visit(if_) |
|||
|
|||
def visit_excepthandler(self, node): |
|||
self.newline(node) |
|||
self.write('except') |
|||
if node.type is not None: |
|||
self.write(' ') |
|||
self.visit(node.type) |
|||
if node.name is not None: |
|||
self.write(' as ') |
|||
self.visit(node.name) |
|||
self.write(':') |
|||
self.body(node.body) |
@ -0,0 +1,17 @@ |
|||
''' |
|||
Created on Dec 22, 2013 |
|||
|
|||
@author: Chris |
|||
''' |
|||
|
|||
class Controller(object): |
|||
''' |
|||
Main controller for the gui. |
|||
|
|||
Serves as a delagation for all of the various buttons/panels/events. |
|||
''' |
|||
|
|||
def __init__(self): |
|||
pass |
|||
|
|||
|
@ -0,0 +1,141 @@ |
|||
#!/usr/local/bin/python2.7 |
|||
# encoding: utf-8 |
|||
''' |
|||
bin.example_argparse_souce -- shortdesc |
|||
|
|||
bin.example_argparse_souce is a description |
|||
|
|||
It defines classes_and_methods |
|||
|
|||
@author: user_name |
|||
|
|||
@copyright: 2013 organization_name. All rights reserved. |
|||
|
|||
@license: license |
|||
|
|||
@contact: user_email |
|||
@deffield updated: Updated |
|||
''' |
|||
|
|||
import sys |
|||
import os |
|||
|
|||
from argparse import ArgumentParser |
|||
from argparse import RawDescriptionHelpFormatter |
|||
|
|||
__all__ = [] |
|||
__version__ = 0.1 |
|||
__date__ = '2013-12-13' |
|||
__updated__ = '2013-12-13' |
|||
|
|||
DEBUG = 1 |
|||
TESTRUN = 0 |
|||
PROFILE = 0 |
|||
|
|||
class CLIError(Exception): |
|||
'''Generic exception to raise and log different fatal errors.''' |
|||
def __init__(self, msg): |
|||
super(CLIError).__init__(type(self)) |
|||
self.msg = "E: %s" % msg |
|||
def __str__(self): |
|||
return self.msg |
|||
def __unicode__(self): |
|||
return self.msg |
|||
|
|||
def main(argv=None): # IGNORE:C0111 |
|||
'''Command line options.''' |
|||
|
|||
if argv is None: |
|||
argv = sys.argv |
|||
else: |
|||
sys.argv.extend(argv) |
|||
|
|||
program_name = os.path.basename(sys.argv[0]) |
|||
program_version = "v%s" % __version__ |
|||
program_build_date = str(__updated__) |
|||
program_version_message = '%%(prog)s %s (%s)' % (program_version, program_build_date) |
|||
program_shortdesc = __import__('__main__').__doc__.split("\n")[1] |
|||
program_license = '''%s |
|||
|
|||
Created by user_name on %s. |
|||
Copyright 2013 organization_name. All rights reserved. |
|||
|
|||
Licensed under the Apache License 2.0 |
|||
http://www.apache.org/licenses/LICENSE-2.0 |
|||
|
|||
Distributed on an "AS IS" basis without warranties |
|||
or conditions of any kind, either express or implied. |
|||
|
|||
USAGE |
|||
''' % (program_shortdesc, str(__date__)) |
|||
|
|||
try: |
|||
# Setup argument parser |
|||
parser = ArgumentParser(description='Example Argparse Program', formatter_class=RawDescriptionHelpFormatter) |
|||
parser.add_argument("filename", help="filename") |
|||
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("-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("-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('-T', '--tester', choices=['yes','no']) |
|||
parser.add_argument(dest="paths", help="paths to folder(s) with source file(s) [default: %(default)s]", metavar="path", nargs='+') |
|||
|
|||
for i in parser._actions: |
|||
print i |
|||
# Process arguments |
|||
args = parser.parse_args() |
|||
|
|||
paths = args.paths |
|||
verbose = args.verbose |
|||
recurse = args.recurse |
|||
inpat = args.include |
|||
expat = args.exclude |
|||
|
|||
if verbose > 0: |
|||
print("Verbose mode on") |
|||
if recurse: |
|||
print("Recursive mode on") |
|||
else: |
|||
print("Recursive mode off") |
|||
|
|||
if inpat and expat and inpat == expat: |
|||
raise CLIError("include and exclude pattern are equal! Nothing will be processed.") |
|||
|
|||
for inpath in paths: |
|||
### do something with inpath ### |
|||
print(inpath) |
|||
return 0 |
|||
except KeyboardInterrupt: |
|||
### handle keyboard interrupt ### |
|||
return 0 |
|||
except Exception, e: |
|||
if DEBUG or TESTRUN: |
|||
raise(e) |
|||
indent = len(program_name) * " " |
|||
sys.stderr.write(program_name + ": " + repr(e) + "\n") |
|||
sys.stderr.write(indent + " for help use --help") |
|||
return 2 |
|||
|
|||
if __name__ == "__main__": |
|||
if DEBUG: |
|||
sys.argv.append("-h") |
|||
# sys.argv.append("-v") |
|||
sys.argv.append("-r") |
|||
main() |
|||
sys.exit() |
|||
if TESTRUN: |
|||
import doctest |
|||
doctest.testmod() |
|||
if PROFILE: |
|||
import cProfile |
|||
import pstats |
|||
profile_filename = 'bin.example_argparse_souce_profile.txt' |
|||
cProfile.run('main()', profile_filename) |
|||
statsfile = open("profile_stats.txt", "wb") |
|||
p = pstats.Stats(profile_filename, stream=statsfile) |
|||
stats = p.strip_dirs().sort_stats('cumulative') |
|||
stats.print_stats() |
|||
statsfile.close() |
|||
sys.exit(0) |
|||
sys.exit(main()) |
@ -0,0 +1,56 @@ |
|||
''' |
|||
Created on Dec 9, 2013 |
|||
|
|||
@author: Chris |
|||
''' |
|||
|
|||
import wx |
|||
import sys |
|||
import time |
|||
import Queue |
|||
import datetime |
|||
import threading |
|||
from app.dialogs.display_main import MainWindow |
|||
from app.images import image_store |
|||
|
|||
|
|||
|
|||
class MockApplication(threading.Thread): |
|||
def __init__(self): |
|||
threading.Thread.__init__(self) |
|||
self.start_time = time.time() |
|||
|
|||
def run(self): |
|||
while time.time() - self.start_time < 5: |
|||
print 'printing message at: %s' % time.time() |
|||
time.sleep(.5) |
|||
print 'Exiting' |
|||
|
|||
|
|||
def decorator(main_func=None): |
|||
def real_decorator(main_func): |
|||
def wrapper(): |
|||
main_func() |
|||
return wrapper |
|||
if callable(main_func): |
|||
return real_decorator(main_func) |
|||
return real_decorator |
|||
|
|||
@decorator |
|||
def my_func(): |
|||
print 'inside my_func' |
|||
|
|||
if __name__ == '__main__': |
|||
|
|||
|
|||
queue = Queue.Queue() |
|||
|
|||
app = wx.App(False) |
|||
frame = MainWindow(queue) |
|||
frame.Show(True) # Show the frame. |
|||
|
|||
mock = MockApplication() |
|||
mock.start() |
|||
|
|||
app.MainLoop() |
|||
# |
@ -0,0 +1,276 @@ |
|||
''' |
|||
Created on Dec 11, 2013 |
|||
|
|||
@author: Chris |
|||
|
|||
Collection of functions for extracting argparse related statements from the |
|||
client code. |
|||
|
|||
|
|||
|
|||
''' |
|||
|
|||
import os |
|||
import ast |
|||
import sys |
|||
import random |
|||
import codegen |
|||
import argparse |
|||
import cStringIO |
|||
from itertools import chain |
|||
from functools import partial |
|||
from numpy.lib.utils import _split_line |
|||
from argparse import ArgumentParser |
|||
from argparse import RawDescriptionHelpFormatter |
|||
from app.dialogs.component_factory import ComponentFactory |
|||
|
|||
|
|||
class ParserError(Exception): |
|||
'''Thrown when the parser can't find argparse functions the client code''' |
|||
pass |
|||
|
|||
|
|||
class ParserFromSource(object): |
|||
''' |
|||
Builds a parser instance from the code |
|||
extracted from the client module. |
|||
|
|||
The instance is stored as a private variabel in the |
|||
class and all methods are delagted to it so that the |
|||
user of the class can treat it just as a normal argparse |
|||
instance. |
|||
''' |
|||
def __init__(self, source_code): |
|||
self._parser_instance = self._build_argparser_from_client_source(source_code) |
|||
# redirect future getattr requests |
|||
# self.__getattr__ = self._delegator |
|||
|
|||
def _build_argparser_from_client_source(self, source_code): |
|||
''' |
|||
runs the client code by evaling each line. |
|||
|
|||
Example input Code: |
|||
parser = ArgumentParser(description=program_license, formatter_class=RawDescriptionHelpFormatter) |
|||
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]") |
|||
|
|||
Method extracts the instance name (e.g. parser) from the first line, |
|||
and instantiates it in a local variable by evaling the rest of the lines. |
|||
Each subsequent line updates the local variable in turn. |
|||
''' |
|||
new_source_code = self._format_source_with_new_varname('clients_parser', source_code) |
|||
# variable of the same name as the one passed into the format_source method. |
|||
# Used to hold the eval'd statements |
|||
|
|||
first_line = new_source_code.pop(0) |
|||
clients_parser, assignment = self._split_line(first_line) |
|||
|
|||
clients_parser = eval(assignment) |
|||
|
|||
for line in new_source_code: |
|||
eval(line) |
|||
return clients_parser |
|||
|
|||
def _format_source_with_new_varname(self, variable_name, source): |
|||
''' |
|||
'injects' the client code with a known variable name so that it |
|||
can be `eval`d and assigned to a variable in the local code. |
|||
|
|||
For example, if the client code was: |
|||
parser = ArgumentParser(descrip...) |
|||
parser.add_argument("-r", "--re...) |
|||
parser.add_argument("-v", "--ve...) |
|||
|
|||
The variable "parser" would be overwritten with a custom name. e.g. |
|||
my_parser = ArgumentParser(descrip...) |
|||
my_parser.add_argument("-r", "--re...) |
|||
''' |
|||
source_code = source[:] |
|||
|
|||
first_line = source_code[0] |
|||
parser_variable, statement = self._split_line(first_line) |
|||
parser_variable = parser_variable.strip() |
|||
|
|||
for index, line in enumerate(source_code): |
|||
source_code[index] = line.replace(parser_variable, variable_name) |
|||
return source_code |
|||
|
|||
def _split_line(self, line): |
|||
# Splits line at the first = sign, |
|||
# joins everything after the first = |
|||
# to account for additional = signs in |
|||
# parameters |
|||
components = line.split('=') |
|||
var = components.pop(0) |
|||
return var, '='.join(components) |
|||
|
|||
def __getattr__(self, attr): |
|||
''' |
|||
Auto-delegates everything to the ArgumentParser instance''' |
|||
return getattr(self._parser_instance, attr) |
|||
|
|||
|
|||
def parse_source_file(file_name): |
|||
''' |
|||
Parses the AST of Python file for lines containing |
|||
references to the argparse module. |
|||
|
|||
returns the collection of ast objects found. |
|||
|
|||
Example client code: |
|||
|
|||
1. parser = ArgumentParser(desc="My help Message") |
|||
2. parser.add_argument('filename', help="Name of the file to load") |
|||
3. parser.add_argument('-f', '--format', help='Format of output \nOptions: ['md', 'html'] |
|||
4. args = parser.parse_args() |
|||
|
|||
Variables: |
|||
* nodes Primary syntax tree object |
|||
* _mainfunc_block main() method as found in the ast nodes |
|||
* _try_blocks Try/except/finally blocks found in the main method |
|||
* main_block The code block in which the ArgumentParser statements are located |
|||
* argparse_assign_obj The assignment of the ArgumentParser (line 1 in example code) |
|||
* parser_nodes Nodes which have parser references (lines 1-4 in example code) |
|||
* parser_var_name The instance variable of the ArgumentParser (line 1 in example code) |
|||
* ast_source The currated colleciton of all parser related nodes in the client code |
|||
''' |
|||
|
|||
nodes = ast.parse(_openfile(file_name)) |
|||
|
|||
_mainfunc_block = find_main(nodes) |
|||
_try_blocks = find_try_blocks(_mainfunc_block) |
|||
|
|||
search_locations = chain([_mainfunc_block], _try_blocks) |
|||
|
|||
main_block = find_argparse_location(search_locations) |
|||
if not main_block: |
|||
raise ParserError("Could not locate AugmentParser assignment.") |
|||
|
|||
argparse_assign_obj = [node for node in main_block.body |
|||
if has_instantiator(node, 'ArgumentParser')] |
|||
|
|||
parser_nodes = [node for node in main_block.body |
|||
if has_assignment(node, 'add_argument')] |
|||
|
|||
ast_source = chain(argparse_assign_obj, parser_nodes) |
|||
return ast_source |
|||
|
|||
|
|||
def find_try_blocks(block): |
|||
# Finds all try/catch/finally expressions in a given function block |
|||
_types = [ast.TryExcept, ast.TryFinally] |
|||
return [node for node in block.body |
|||
if any([isinstance(node, x) for x in _types])] |
|||
|
|||
|
|||
def find_main(nodes): |
|||
# Finds main function in the tree |
|||
for node in nodes.body: |
|||
if isinstance(node, ast.FunctionDef) and node.name == 'main': |
|||
return node |
|||
raise ParserError('Could not find `def main()`') |
|||
|
|||
|
|||
def get_assignment_name(node): |
|||
# return the variable name to which |
|||
# ArgumentParser is assigned |
|||
return node.targets[0].id |
|||
|
|||
|
|||
def _openfile(file_name): |
|||
with open(file_name, 'rb') as f: |
|||
return f.read() |
|||
|
|||
|
|||
def find_statement(block, name): |
|||
return [node for node in block.body |
|||
if has_instantiator(node, name)] |
|||
|
|||
def has_instantiator(x, name): |
|||
# Checks if the astObject is one with an |
|||
# instantiation of the ArgParse class |
|||
try: return x.value.func.id == name |
|||
except: return False # Wrong type. Contine. |
|||
|
|||
def has_assignment(x, name): |
|||
# Checks if the astObject is contains a |
|||
# function with a name of name |
|||
try: return x.value.func.attr == name |
|||
except: return False # Wrong type. Contine. |
|||
|
|||
def is_found(stmnt): |
|||
return len(stmnt) |
|||
|
|||
def has_argparse_assignment(block): |
|||
# Checks a given node for presence of an instantiation |
|||
argparse_assignment = find_statement(block, 'ArgumentParser') |
|||
return is_found(argparse_assignment) |
|||
|
|||
def find_argparse_location(locations): |
|||
# Browser a collection of Nodes for the one |
|||
# containing the Argparse instantiation |
|||
for location in locations: |
|||
if has_argparse_assignment(location): |
|||
return location |
|||
return None |
|||
|
|||
def convert_to_python(ast_source): |
|||
return map(codegen.to_source, ast_source) |
|||
|
|||
def generate_doc(f=None, format='html', noob=1, success_msg=1): |
|||
''' |
|||
Decorator for client code's main function. |
|||
It gets the name of the calling script, loads it |
|||
into parse_pyfile(), and generates the documentation, |
|||
before finally calling the main() function to resume |
|||
execution as normal. |
|||
''' |
|||
|
|||
# Handles if the passed in object is instance |
|||
# of ArgumentParser. If so, it's being called as |
|||
# a function, rather than a decorator |
|||
if isinstance(f, argparse.ArgumentParser): |
|||
filename = sys.argv[0] |
|||
|
|||
build_doc_from_parser_obj( |
|||
file_name=filename, |
|||
parser_obj=f, |
|||
format=format, |
|||
noob=noob, |
|||
success_msg=success_msg |
|||
) |
|||
return |
|||
|
|||
# --------------------------------- # |
|||
# Below code is all decorator stuff # |
|||
# --------------------------------- # |
|||
def get_caller_path(): |
|||
# utility func for decorator |
|||
# gets the name of the calling script |
|||
tmp_sys = __import__('sys') |
|||
return tmp_sys.argv[0] |
|||
|
|||
def generate_docs(f): |
|||
def inner(): |
|||
module_path = get_caller_path() |
|||
path = os.path.join(*os.path.split(module_path)[:-1]) |
|||
filename = '{}'.format(os.path.split(module_path)[-1]) |
|||
parse_pyfile(filename, format=format, noob=noob, success_msg=success_msg) |
|||
inner.__name__ = f.__name__ |
|||
return inner |
|||
|
|||
if callable(f): |
|||
return generate_docs(f) |
|||
return generate_docs |
|||
|
|||
|
|||
|
|||
if __name__ == '__main__': |
|||
ast_source = parse_source_file('example_argparse_souce.py') |
|||
python_code = convert_to_python(ast_source) |
|||
parser = ParserFromSource(python_code) |
|||
factory = ComponentFactory(parser) |
|||
|
|||
# |
|||
|
|||
|
@ -0,0 +1,34 @@ |
|||
''' |
|||
Created on Dec 9, 2013 |
|||
|
|||
@author: Chris |
|||
''' |
|||
|
|||
# import Queue |
|||
# |
|||
# q = Queue.Queue() |
|||
# |
|||
# q.get(timeout=5) |
|||
|
|||
|
|||
class A(object): |
|||
|
|||
def __init__(self): |
|||
self.value = 'a' |
|||
self.value2 = A.B() |
|||
|
|||
class B(object): |
|||
def __init__(self): |
|||
self.value = 'asdfasdf' |
|||
|
|||
def asdf(self): |
|||
print 'I was called!' |
|||
|
|||
|
|||
|
|||
# a = A() |
|||
# print a.value |
|||
# print a.value2.asdf() |
|||
|
|||
a = 'asdf.now()' |
|||
print 'asdf' in a |
@ -0,0 +1,14 @@ |
|||
''' |
|||
Created on Dec 12, 2013 |
|||
|
|||
@author: Chris |
|||
''' |
|||
|
|||
# parser.add_argument("-r", "--recursive", dest="recurse", action="store_true", help="recurse into subfolders [default: %(default)s]") |
|||
|
|||
class Option(object): |
|||
def __init__(self, arg_option): |
|||
self.arg_option = arg_option |
|||
|
|||
@classmethod |
|||
def |
Write
Preview
Loading…
Cancel
Save