diff --git a/gooey/mockapplications/example_argparse_souce_in_main.py b/gooey/_tmp/example_argparse_souce_in_main.py similarity index 95% rename from gooey/mockapplications/example_argparse_souce_in_main.py rename to gooey/_tmp/example_argparse_souce_in_main.py index 7714f1d..7eb8c18 100644 --- a/gooey/mockapplications/example_argparse_souce_in_main.py +++ b/gooey/_tmp/example_argparse_souce_in_main.py @@ -48,7 +48,6 @@ class CLIError(Exception): def __unicode__(self): return self.msg -@Gooey def main(argv=None): # IGNORE:C0111 '''Command line options.''' diff --git a/gooey/_tmp/example_argparse_souce_in_try.py b/gooey/_tmp/example_argparse_souce_in_try.py new file mode 100644 index 0000000..dce2f20 --- /dev/null +++ b/gooey/_tmp/example_argparse_souce_in_try.py @@ -0,0 +1,171 @@ +#!/usr/local/bin/python2.7 +# encoding: utf-8 +''' + +TODO: Fix this. Currently breaks parser + + +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 + +from gooey.python_bindings.gooey_decorator import Gooey + + +__all__ = [] +__version__ = 0.1 +__date__ = '2013-12-13' +__updated__ = '2013-12-13' + +DEBUG = 0 +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", nargs='+', + help="only include paths matching this regex pattern. Note: exclude is given preference over include. ", + metavar="RE") + + parser.add_argument("-m", "--mycoolargument", help="mycoolargument") + + 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()) diff --git a/gooey/mockapplications/mock_app_vars_in_args.py b/gooey/_tmp/mock_app_vars_in_args.py similarity index 91% rename from gooey/mockapplications/mock_app_vars_in_args.py rename to gooey/_tmp/mock_app_vars_in_args.py index bcdd46c..85074a2 100644 --- a/gooey/mockapplications/mock_app_vars_in_args.py +++ b/gooey/_tmp/mock_app_vars_in_args.py @@ -4,7 +4,6 @@ from argparse import ArgumentParser from gooey import Gooey -@Gooey def main(): """Main""" bar = 'bar' diff --git a/gooey/mockapplications/mockapp_nargs.py b/gooey/_tmp/mock_argparse_example.py similarity index 73% rename from gooey/mockapplications/mockapp_nargs.py rename to gooey/_tmp/mock_argparse_example.py index 2369171..fbf9ed8 100644 --- a/gooey/mockapplications/mockapp_nargs.py +++ b/gooey/_tmp/mock_argparse_example.py @@ -1,14 +1,10 @@ -import sys +__author__ = 'Chris' import argparse from gooey import Gooey - -sys.argv.extend(['1', '2', '3', '4', '--sum']) - -# @Gooey def main(): parser = argparse.ArgumentParser(description='Process some integers.') - parser.add_argument('integers', metavar='N', type=int, nargs="+", + parser.add_argument('integers', metavar='N', type=int, nargs='+', help='an integer for the accumulator') parser.add_argument('--sum', dest='accumulate', action='store_const', const=sum, default=max, @@ -19,4 +15,4 @@ def main(): if __name__ == '__main__': - main() + main() \ No newline at end of file diff --git a/gooey/_tmp/mockapp.py b/gooey/_tmp/mockapp.py index 5e44441..5001cc4 100644 --- a/gooey/_tmp/mockapp.py +++ b/gooey/_tmp/mockapp.py @@ -17,6 +17,7 @@ from gooey import GooeyParser def main(): + print 'hello' ''' does stuff with parser.parse_args() ''' @@ -25,8 +26,9 @@ def main(): my_cool_parser = GooeyParser(description=desc) my_cool_parser.add_argument("filename", help=file_help_msg, widget="FileChooser") # positional my_cool_parser.add_argument("outfile", help="Name of the file where you'll save the output") # positional - # my_cool_parser.add_argument('-c', '--countdown', default=10, type=int, help='sets the time to count down from you see its quite simple!', widget='DateChooser') - my_cool_parser.add_argument('-c', '--cron-schedule', default=10, type=int, help='Set the datetime when the cron should begin', widget='DateChooser') + + my_cool_parser.add_argument('-c', '--countdown', default=2, type=int, help='sets the time to count down from you see its quite simple!') + # my_cool_parser.add_argument('-c', '--cron-schedule', default=10, type=int, help='Set the datetime when the cron should begin', widget='DateChooser') my_cool_parser.add_argument("-s", "--showtime", action="store_true", help="display the countdown timer") my_cool_parser.add_argument("-d", "--delay", action="store_true", help="Delay execution for a bit") my_cool_parser.add_argument('-v', '--verbose', action='count') @@ -34,15 +36,14 @@ def main(): my_cool_parser.add_argument('-r', '--recursive', choices=['yes', 'no'], help='Recurse into subfolders') my_cool_parser.add_argument("-w", "--writelog", default="No, NOT whatevs", help="write log to some file or something") my_cool_parser.add_argument("-e", "--expandAll", action="store_true", help="expand all processes") - verbosity = my_cool_parser.add_mutually_exclusive_group() - verbosity.add_argument('-t', '--verbozze', dest='verbose', action="store_true", help="Show more details") - verbosity.add_argument('-q', '--quiet', dest='quiet', action="store_true", help="Only output on error") + # verbosity = my_cool_parser.add_mutually_exclusive_group() + # verbosity.add_argument('-t', '--verbozze', dest='verbose', action="store_true", help="Show more details") + # verbosity.add_argument('-q', '--quiet', dest='quiet', action="store_true", help="Only output on error") print my_cool_parser._actions - print 'inside of main(), my_cool_parser =', my_cool_parser args = my_cool_parser.parse_args() - + print 'EHOOOOOOOOOOOO' print sys.argv print args.countdown print args.showtime diff --git a/gooey/_tmp/mockapp_import_argparse.py b/gooey/_tmp/mockapp_import_argparse.py new file mode 100644 index 0000000..1964f7c --- /dev/null +++ b/gooey/_tmp/mockapp_import_argparse.py @@ -0,0 +1,50 @@ +''' +Created on Dec 21, 2013 + +@author: Chris +''' +import sys +import hashlib +from time import time as _time +from time import sleep as _sleep +import argparse + +from gooey import Gooey + + +def main(): + my_cool_parser = argparse.ArgumentParser(description="Mock application to test Gooey's functionality") + my_cool_parser.add_argument("filename", help="Name of the file you want to read") # positional + my_cool_parser.add_argument("outfile", help="Name of the file where you'll save the output") # positional + 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("-d", "--delay", action="store_true", help="Delay execution for a bit") + my_cool_parser.add_argument('--verbose', '-v', action='count') + my_cool_parser.add_argument("-o", "--obfuscate", action="store_true", help="obfuscate the countdown timer!") + my_cool_parser.add_argument('-r', '--recursive', choices=['yes', 'no'], help='Recurse into subfolders') + my_cool_parser.add_argument("-w", "--writelog", default="No, NOT whatevs", help="write log to some file or something") + my_cool_parser.add_argument("-e", "--expandAll", action="store_true", help="expand all processes") + + print 'inside of main(), my_cool_parser =', my_cool_parser + args = my_cool_parser.parse_args() + + print sys.argv + print args.countdown + print args.showtime + + 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!' + +# raise ValueError("Something has gone wrong! AHHHHHHHHHHH") + +if __name__ == '__main__': + # sys.argv.extend('asdf -c 5 -s'.split()) + # print sys.argv + main() \ No newline at end of file diff --git a/gooey/_tmp/module_with_no_argparse.py b/gooey/_tmp/module_with_no_argparse.py new file mode 100644 index 0000000..a737909 --- /dev/null +++ b/gooey/_tmp/module_with_no_argparse.py @@ -0,0 +1,18 @@ +''' +Created on Feb 2, 2014 + +@author: Chris +''' +import time +from gooey import Gooey + +def main(): + end = time.time() + 10 + while end > time.time(): + print 'Jello!', time.time() + time.sleep(.8) + + +if __name__ == '__main__': + main() + diff --git a/gooey/gui/controller.py b/gooey/gui/controller.py index 32fbddd..08ccf6f 100644 --- a/gooey/gui/controller.py +++ b/gooey/gui/controller.py @@ -6,6 +6,7 @@ Created on Dec 22, 2013 import subprocess import sys from multiprocessing.dummy import Pool, Process +import time import wx @@ -49,10 +50,11 @@ class Controller(object): def OnStartButton(self, widget, event): cmd_line_args = self.core_gui.GetOptions() - _required = self.core_gui.GetRequiredArgs() - if _required and any(req == '' for req in _required): - self.ShowDialog(i18n.translate('error_title'), "Must fill in all fields in the Required section!", wx.ICON_ERROR) - return + if not self.build_spec['manual_start']: + _required = self.core_gui.GetRequiredArgs() + if _required and any(req == '' for req in _required): + self.ShowDialog(i18n.translate('error_title'), "Must fill in all fields in the Required section!", wx.ICON_ERROR) + return command = '{0} {1}'.format(self.build_spec['target'], cmd_line_args) self.core_gui.NextPage() @@ -81,12 +83,10 @@ class Controller(object): self.ShowBadFinishedDialog(_stderr) def OnRestartButton(self, widget, event): - self.OnStartButton(self, None, event) + self.OnStartButton(None, event) def ManualStart(self): - self.core_gui.NextPage() - wx.CallAfter(wx.ActivateEvent) - Process(target=self.RunClientCode).start() + self.OnStartButton(None, None) def OnCloseButton(self, widget, event): self.core_gui.Destroy() diff --git a/gooey/gui/widgets/components2.py b/gooey/gui/widgets/components2.py index 8f572ed..f46cf96 100644 --- a/gooey/gui/widgets/components2.py +++ b/gooey/gui/widgets/components2.py @@ -68,7 +68,7 @@ class BaseGuiComponent(object): return text def formatExtendedHelpMsg(self, data): - base_text = data['help_msg'] + base_text = data.get('help_msg', '') nargs = data['nargs'] if isinstance(nargs, int): return '{base}\n(Note: exactly {nargs} arguments are required)'.format(base=base_text, nargs=nargs) diff --git a/gooey/gui/windows/layouts.py b/gooey/gui/windows/layouts.py new file mode 100644 index 0000000..c604a3b --- /dev/null +++ b/gooey/gui/windows/layouts.py @@ -0,0 +1,15 @@ + + +basic_config = { + 'required': [{ + 'type': 'TextField', + 'data': { + 'display_name': 'Enter Commands', + 'help': 'Enter command line arguments', + 'nargs': '', + 'commands': '', + 'choices': [], + } + }], + 'optional': [] +} diff --git a/gooey/mockapplications/example_argparse_souce_in_try.py b/gooey/mockapplications/example_argparse_souce_in_try.py index 7bc6e6b..46c0315 100644 --- a/gooey/mockapplications/example_argparse_souce_in_try.py +++ b/gooey/mockapplications/example_argparse_souce_in_try.py @@ -1,6 +1,10 @@ #!/usr/local/bin/python2.7 # encoding: utf-8 ''' + +TODO: Fix this. Currently breaks parser + + bin.example_argparse_souce -- shortdesc bin.example_argparse_souce is a description diff --git a/gooey/mockapplications/mockapp.py b/gooey/mockapplications/mockapp.py index 84083c4..0837cb2 100644 --- a/gooey/mockapplications/mockapp.py +++ b/gooey/mockapplications/mockapp.py @@ -18,6 +18,7 @@ from gooey import GooeyParser @Gooey def main(): + print 'hello' ''' does stuff with parser.parse_args() ''' @@ -26,8 +27,9 @@ def main(): my_cool_parser = GooeyParser(description=desc) my_cool_parser.add_argument("filename", help=file_help_msg, widget="FileChooser") # positional my_cool_parser.add_argument("outfile", help="Name of the file where you'll save the output") # positional - # my_cool_parser.add_argument('-c', '--countdown', default=10, type=int, help='sets the time to count down from you see its quite simple!', widget='DateChooser') - my_cool_parser.add_argument('-c', '--cron-schedule', default=10, type=int, help='Set the datetime when the cron should begin', widget='DateChooser') + + my_cool_parser.add_argument('-c', '--countdown', default=2, type=int, help='sets the time to count down from you see its quite simple!') + # my_cool_parser.add_argument('-c', '--cron-schedule', default=10, type=int, help='Set the datetime when the cron should begin', widget='DateChooser') my_cool_parser.add_argument("-s", "--showtime", action="store_true", help="display the countdown timer") my_cool_parser.add_argument("-d", "--delay", action="store_true", help="Delay execution for a bit") my_cool_parser.add_argument('-v', '--verbose', action='count') @@ -35,15 +37,14 @@ def main(): my_cool_parser.add_argument('-r', '--recursive', choices=['yes', 'no'], help='Recurse into subfolders') my_cool_parser.add_argument("-w", "--writelog", default="No, NOT whatevs", help="write log to some file or something") my_cool_parser.add_argument("-e", "--expandAll", action="store_true", help="expand all processes") - verbosity = my_cool_parser.add_mutually_exclusive_group() - verbosity.add_argument('-t', '--verbozze', dest='verbose', action="store_true", help="Show more details") - verbosity.add_argument('-q', '--quiet', dest='quiet', action="store_true", help="Only output on error") + # verbosity = my_cool_parser.add_mutually_exclusive_group() + # verbosity.add_argument('-t', '--verbozze', dest='verbose', action="store_true", help="Show more details") + # verbosity.add_argument('-q', '--quiet', dest='quiet', action="store_true", help="Only output on error") print my_cool_parser._actions - print 'inside of main(), my_cool_parser =', my_cool_parser args = my_cool_parser.parse_args() - + print 'EHOOOOOOOOOOOO' print sys.argv print args.countdown print args.showtime diff --git a/gooey/mockapplications/module_with_no_argparse.py b/gooey/mockapplications/module_with_no_argparse.py index 6bf5a17..f8809f3 100644 --- a/gooey/mockapplications/module_with_no_argparse.py +++ b/gooey/mockapplications/module_with_no_argparse.py @@ -6,9 +6,9 @@ Created on Feb 2, 2014 import time from gooey import Gooey -@Gooey(show_config=False) +@Gooey def main(): - end = time.time() + 1 + end = time.time() + 10 while end > time.time(): print 'Jello!', time.time() time.sleep(.8) diff --git a/gooey/mockapplications/qwindelzorf _example.py b/gooey/mockapplications/qwindelzorf _example.py deleted file mode 100644 index 4180834..0000000 --- a/gooey/mockapplications/qwindelzorf _example.py +++ /dev/null @@ -1,89 +0,0 @@ -"""inline""" - -import argparse -from __builtin__ import getattr -from gooey import Gooey - -x = '''random line''' - -y = """ -Buncha text here -and here -and here -and here -""" - -# @Gooey -def main(): - """ - This is my main module - example: - args = parser.parse_args() - """ - parser = argparse.ArgumentParser('Get my users') - verbosity = parser.add_mutually_exclusive_group() - verbosity.add_argument('-v', '--verbose', dest='verbose', action="store_true", help="Show more details") - verbosity.add_argument('-q', '--quiet', dest='quiet', action="store_true", help="Only output on error") - parser.add_argument("filename", help="yo yo yo") # positional - parser.add_argument("outfile", help="Name of the file where you'll save the output") # positional - slervocity = parser.add_mutually_exclusive_group() - slervocity.add_argument('-c', '--countdown', action="store_true", help='sets the time to count down from') - slervocity.add_argument("-s", "--showtime", action="store_true", help="display the countdown timer") - parser.add_argument("-d", "--delay", action="store_true", help="Delay execution for a bit") - parser.add_argument("-o", "--obfuscate", action="store_true", help="obfuscate the countdown timer!") - parser.add_argument('-r', '--recursive', choices=['yes', 'no'], help='Recurse into subfolders') - parser.add_argument("-w", "--writelog", default="No, NOT whatevs", help="write log to some file or something") - parser.add_argument("-e", "--expandAll", action="store_true", help="expand all processes") - - mutually_exclusive_group = [mutex_action - for group_actions in parser._mutually_exclusive_groups - for mutex_action in group_actions._group_actions] - - base_actions = [action for action in parser._actions - if action not in mutually_exclusive_group] - - for i in base_actions: - print 'Base Action:', i.option_strings - # - # print - - for i in mutually_exclusive_group: - print 'Mute Action:', i - - # for i in base_actions: - # print dir(i) - # print i.nargs - # break - - -def moo(asdf): - '''single quoted inline comment''' - a = 1 - -def foo(): - """Double quoted inline comment """ - a = 1 - -def bar(): - """ - Double quoted - multiline comment - """ - a = 1 - -def baz(): - ''' - Double quoted - multiline comment - ''' - a = 1 - - -def foo(): - parser = argparse.ArgumentParser() - bar = 1 - baz = 2 - -if __name__ == '__main__': - main() - diff --git a/gooey/python_bindings/argparse_to_json.py b/gooey/python_bindings/argparse_to_json.py index c5fe56d..b4c8d3c 100644 --- a/gooey/python_bindings/argparse_to_json.py +++ b/gooey/python_bindings/argparse_to_json.py @@ -29,7 +29,7 @@ class UnknownWidgetType(Exception): def convert(parser): - widget_dict = getattr(parser, 'widgets', None) + widget_dict = getattr(parser, 'widgets', {}) mutually_exclusive_group = [ mutex_action diff --git a/gooey/python_bindings/gooey_decorator.py b/gooey/python_bindings/gooey_decorator.py index 3062f16..ef7be39 100644 --- a/gooey/python_bindings/gooey_decorator.py +++ b/gooey/python_bindings/gooey_decorator.py @@ -52,6 +52,7 @@ import types import wx from gooey.gui.lang import i18n +from gooey.gui.windows import layouts from gooey.python_bindings import argparse_to_json import source_parser @@ -75,6 +76,8 @@ def Gooey(f=None, advanced=True, 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) @@ -83,6 +86,9 @@ def Gooey(f=None, advanced=True, with open(filepath, 'w') as f: f.write(cleaned_source) + if not has_argparse(cleaned_source): + show_config = False + run_cmd = 'python {}'.format(filepath) # Must be called before anything else @@ -97,33 +103,39 @@ def Gooey(f=None, advanced=True, from gooey.gui.windows.advanced_config import AdvancedConfigPanel from gooey.gui.windows.basic_config_panel import BasicConfigPanel + meta = { + 'target': run_cmd, + 'program_name': program_name, + 'program_description': program_description or '', + 'show_config': show_config, + 'show_advanced': advanced, + 'default_size': (610, 530), + 'requireds_cols': 1, + 'optionals_cols': 2, + 'manual_start': False + } + if show_config: parser = get_parser(main_module_path) + meta['program_description'] = parser.description or program_description - meta = { - 'target': run_cmd, - 'program_name': program_name, - 'program_description': program_description or parser.description, - 'show_config': show_config, - 'show_advanced': advanced, - 'default_size': (610, 530), - 'requireds_cols': 1, - 'optionals_cols': 2 - } client_app = ClientApp(parser, payload) - build_spec = dict(meta.items() + argparse_to_json.convert(parser).items()) - if advanced: + build_spec = dict(meta.items() + argparse_to_json.convert(parser).items()) BodyPanel = partial(AdvancedConfigPanel, build_spec=build_spec) else: - BodyPanel = BasicConfigPanel + build_spec = dict(meta.items() + layouts.basic_config.items()) + BodyPanel = partial(AdvancedConfigPanel, build_spec=build_spec) # User doesn't want to display configuration screen # Just jump straight to the run panel else: - BodyPanel = BasicConfigPanel + build_spec = dict(meta.items() + layouts.basic_config.items()) + build_spec['manual_start'] = True + BodyPanel = partial(AdvancedConfigPanel, build_spec=build_spec) client_app = EmptyClientApp(payload) + frame = BaseWindow(BodyPanel, build_spec, params) if not show_config: @@ -153,6 +165,9 @@ 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) diff --git a/gooey/python_bindings/source_parser.py b/gooey/python_bindings/source_parser.py index 2888b6c..95914a2 100644 --- a/gooey/python_bindings/source_parser.py +++ b/gooey/python_bindings/source_parser.py @@ -145,6 +145,7 @@ def extract_parser(modulepath): client_module = modules.load(module_source) return client_module.main() + if __name__ == '__main__': filepath = os.path.join(os.path.dirname(__file__), 'mockapplications',