From f9e9966f2d53b1399a871bd1ab03c32cfce91351 Mon Sep 17 00:00:00 2001 From: chriskiehl Date: Sat, 4 Apr 2015 17:30:16 -0400 Subject: [PATCH] added cmd tools. moved config generation to own module --- gooey/__init__.py | 2 +- gooey/__main__.py | 12 +++++ gooey/examples/widget_demo.py | 1 - gooey/gui/action_sorter.py | 5 +- gooey/gui/application.py | 58 +++++++++++++++++----- gooey/gui/controller.py | 1 - gooey/gui/windows/base_window.py | 3 +- gooey/gui/windows/runtime_display_panel.py | 5 +- gooey/python_bindings/config_generator.py | 40 +++++++++++++++ gooey/python_bindings/gooey_decorator.py | 58 +++++++--------------- gooey/python_bindings/source_parser.py | 2 + 11 files changed, 124 insertions(+), 63 deletions(-) create mode 100644 gooey/__main__.py create mode 100644 gooey/python_bindings/config_generator.py diff --git a/gooey/__init__.py b/gooey/__init__.py index eb02fbd..fc4822f 100644 --- a/gooey/__init__.py +++ b/gooey/__init__.py @@ -1,8 +1,8 @@ import os from gooey.python_bindings.gooey_decorator import Gooey from gooey.python_bindings.gooey_parser import GooeyParser +from gooey.gui import application version_file = os.path.join(os.path.dirname(__file__), 'version') __version__ = '0.1.6' - diff --git a/gooey/__main__.py b/gooey/__main__.py new file mode 100644 index 0000000..3e819af --- /dev/null +++ b/gooey/__main__.py @@ -0,0 +1,12 @@ +''' +Delegates arguments to the main Gooey runner + +For use when run directly from command line with the -m (module) flag: + + e.g. $ python -m gooey + +''' + +from gooey import application + +application.main() diff --git a/gooey/examples/widget_demo.py b/gooey/examples/widget_demo.py index cd1da22..3679dec 100644 --- a/gooey/examples/widget_demo.py +++ b/gooey/examples/widget_demo.py @@ -58,7 +58,6 @@ def here_is_smore(): if __name__ == '__main__': - print sys.argv main() # import inspect # import dis diff --git a/gooey/gui/action_sorter.py b/gooey/gui/action_sorter.py index 9a15e30..da2b9eb 100644 --- a/gooey/gui/action_sorter.py +++ b/gooey/gui/action_sorter.py @@ -69,8 +69,9 @@ class ActionSorter(object): self._display('ActionSorter: counters', self._counters) def _display(self, _type, something): - for i in something: - print _type, i + pass + # for i in something: + # print _type, i def get_counter_actions(self, actions): """ diff --git a/gooey/gui/application.py b/gooey/gui/application.py index 60d448b..ee6b34f 100644 --- a/gooey/gui/application.py +++ b/gooey/gui/application.py @@ -2,7 +2,6 @@ Main runner entry point for Gooey. ''' - import wx import os import sys @@ -15,16 +14,59 @@ from gooey.gui.lang import i18n from gooey.gui.windows.base_window import BaseWindow from gooey.gui.windows.advanced_config import AdvancedConfigPanel +# C:\Users\Chris\Dropbox\pretty_gui\Gooey\gooey\gui\application.py +from gooey.python_bindings import config_generator, source_parser + def main(): - gooey_config = pull_cmd_args() if has_arg_supplied() else read_local_dir() + parser = argparse.ArgumentParser( + description='Gooey turns your command line programs into beautiful, user friendly GUIs') + + parser.add_argument( + '-b', '--create-build-script', + dest='build_script', + help='Parse the supplied Python File and generate a runnable Gooey build script' + ) + + parser.add_argument( + '-r', '--run', + dest='run', + nargs='?', + const='', + help='Run Gooey with build_config in local dir OR via the supplied config path' + ) + + args = parser.parse_args() + + if args.build_script: + do_build_script(args.build_script) + elif args.run is not None: + do_run(args) + + +def do_build_script(module_path): + with open(module_path, 'r') as f: + if not source_parser.has_argparse(f.read()): + raise AssertionError('Argparse not found in module. Unable to continue') + + gooey_config = config_generator.create_from_module(module_path, show_config=True) + outfile = os.path.join(os.getcwd(), 'gooey_config.json') + + print 'Writing config file to: {}'.format(outfile) + + with open(outfile, 'w') as f: + f.write(json.dumps(gooey_config, indent=2)) + + +def do_run(args): + gooey_config = args.run or read_local_dir() if not os.path.exists(gooey_config): raise IOError('Gooey Config not found') with open(gooey_config, 'r') as f: build_spec = json.load(f) - + print json.dumps(build_spec) run(build_spec) @@ -41,12 +83,6 @@ def run(build_spec): app.MainLoop() -def pull_cmd_args(): - parser = argparse.ArgumentParser(description='Gooey turns your command line programs into beautiful, user friendly GUIs') - parser.add_argument('file', help='Path to the configuration file for Gooey. We need this to run! :) ') - args = parser.parse_args() - return args.file - def read_local_dir(): local_files = os.listdir(os.getcwd()) if 'gooey_config.json' not in local_files: @@ -54,10 +90,6 @@ def read_local_dir(): sys.exit(1) return os.path.join(os.getcwd(), 'gooey_config.json') -def has_arg_supplied(): - return len(sys.argv) > 1 - - if __name__ == '__main__': main() diff --git a/gooey/gui/controller.py b/gooey/gui/controller.py index e81d263..f25156e 100644 --- a/gooey/gui/controller.py +++ b/gooey/gui/controller.py @@ -7,7 +7,6 @@ Created on Dec 22, 2013 import wx import sys import subprocess - from multiprocessing.dummy import Pool from gooey.gui.lang import i18n diff --git a/gooey/gui/windows/base_window.py b/gooey/gui/windows/base_window.py index 5f4d2b4..78da037 100644 --- a/gooey/gui/windows/base_window.py +++ b/gooey/gui/windows/base_window.py @@ -39,8 +39,7 @@ class BaseWindow(wx.Frame): self.Bind(wx.EVT_SIZE, self.onResize) def _init_properties(self): - title = self.build_spec['program_name'] - self.SetTitle(title) + self.SetTitle(self.build_spec['program_name']) self.SetSize(self.build_spec['default_size']) # self.SetMinSize((400, 300)) self.icon = wx.Icon(image_repository.icon, wx.BITMAP_TYPE_ICO) diff --git a/gooey/gui/windows/runtime_display_panel.py b/gooey/gui/windows/runtime_display_panel.py index c956b37..4909e67 100644 --- a/gooey/gui/windows/runtime_display_panel.py +++ b/gooey/gui/windows/runtime_display_panel.py @@ -66,5 +66,6 @@ class RuntimeDisplay(wx.Panel): self.AppendText(txt) def OnMsg(self, evt): - print 'It workded!!' - print locals() + pass + # print 'It workded!!' + # print locals() diff --git a/gooey/python_bindings/config_generator.py b/gooey/python_bindings/config_generator.py new file mode 100644 index 0000000..5a5cd45 --- /dev/null +++ b/gooey/python_bindings/config_generator.py @@ -0,0 +1,40 @@ +import os +import argparse_to_json +from gooey.gui.windows import layouts +from gooey.python_bindings import source_parser + + +def create_from_module(module_path, **kwargs): + show_config = kwargs.get('show_config', False) + + run_cmd = 'python {}'.format(module_path) + a = os.path.basename(module_path).replace('.py', '') + build_spec = { + 'language': kwargs.get('language', 'english'), + 'target': run_cmd, + 'program_name': kwargs.get('program_name') or os.path.basename(module_path).replace('.py', ''), + 'program_description': kwargs.get('program_description', ''), + 'show_config': show_config, + 'show_advanced': kwargs.get('show_advanced', True), + 'default_size': kwargs.get('default_size', (610, 530)), + 'requireds_cols': kwargs.get('required_cols', 1), + 'optionals_cols': kwargs.get('optional_cols', 3), + 'manual_start': False + } + + if show_config: + parser = source_parser.extract_parser(module_path) + build_spec['program_description'] = parser.description or build_spec['program_description'] + + layout_data = argparse_to_json.convert(parser) if build_spec['show_advanced'] else layouts.basic_config.items() + build_spec.update(layout_data) + + else: + build_spec['manual_start'] = True + + return build_spec + + + +def has_argparse(module_path): + return any(['.parse_args(' in line.lower() for line in f.readlines()]) diff --git a/gooey/python_bindings/gooey_decorator.py b/gooey/python_bindings/gooey_decorator.py index f6bab4d..a106c80 100644 --- a/gooey/python_bindings/gooey_decorator.py +++ b/gooey/python_bindings/gooey_decorator.py @@ -44,37 +44,36 @@ to us. No more complicated ast stuff. Just a little bit of string parsing and we done. ''' +import json -import wx import os import sys import atexit import tempfile import source_parser +import config_generator from gooey.gui import application from gooey.gui.windows import layouts from gooey.python_bindings import argparse_to_json -def Gooey(f=None, advanced=True, - language='english', show_config=True, - program_name=None, program_description=None): +def Gooey(f=None, + advanced=True, + language='english', + show_config=True, + program_name=None, + program_description=None, + dump_build_config=False): ''' Decorator for client code's main function. - Entry point for the GUI generator. - - Scans the client code for argparse data. - If found, extracts it and build the proper - configuration gui windows (basic or advanced). + Serializes argparse data to JSON for use with the Gooey front end ''' params = locals() def build(payload): def inner(): - show_config = params['show_config'] #because nonlocal keyword doesn't exist yet :( - main_module_path = get_caller_path() _, filename = os.path.split(main_module_path) cleaned_source = clean_source(main_module_path) @@ -85,36 +84,16 @@ def Gooey(f=None, advanced=True, with open(tmp_filepath, 'w') as f: f.write(cleaned_source) - if not has_argparse(cleaned_source): + if not source_parser.has_argparse(cleaned_source): show_config = False - run_cmd = 'python {}'.format(tmp_filepath) - - # Must be called before anything else - app = wx.App(False) - - build_spec = { - 'language': language, - 'target': run_cmd, - 'program_name': program_name or os.path.basename(sys.argv[0].replace('.py', '')), - 'program_description': program_description or '', - 'show_config': show_config, - 'show_advanced': advanced, - 'default_size': (610, 530), - 'requireds_cols': 1, - 'optionals_cols': 4, - 'manual_start': False - } - - if show_config: - parser = get_parser(main_module_path) - build_spec['program_description'] = parser.description or program_description - - layout_data = argparse_to_json.convert(parser) if advanced else layouts.basic_config.items() - build_spec.update(layout_data) + build_spec = config_generator.create_from_module(tmp_filepath, **params) - else: - build_spec['manual_start'] = True + if dump_build_config: + config_path = os.path.join(os.getcwd(), 'gooey_config.json') + print 'Writing Build Config to: {}'.format(config_path) + with open(config_path, 'w') as f: + f.write(json.dumps(build_spec, indent=2)) application.run(build_spec) @@ -140,9 +119,6 @@ def get_caller_path(): tmp_sys = __import__('sys') return tmp_sys.argv[0] -def has_argparse(source): - bla = ['.parse_args(' in line.lower() for line in source.split('\n')] - return any(bla) def cleanup(descriptor, filepath): os.close(descriptor) diff --git a/gooey/python_bindings/source_parser.py b/gooey/python_bindings/source_parser.py index d3174d6..4870dfc 100644 --- a/gooey/python_bindings/source_parser.py +++ b/gooey/python_bindings/source_parser.py @@ -153,6 +153,8 @@ def extract_parser(modulepath): client_module = modules.load(module_source) return client_module.main() +def has_argparse(source): + return any(['.parse_args(' in line.lower() for line in source.split('\n')]) if __name__ == '__main__': filepath = os.path.join(os.path.dirname(__file__),