Esempio n. 1
0
    def performTest(self, configPath, assertionFunction):
        """
        Primary test harness.

        Instantiates the WX App, and spawns the threads
        required to make assertions against it
        """
        with open(configPath, 'r') as f:
            build_spec = json.loads(f.read())
            # swaps the absolute path stored by Gooey at write time
            # for a relative one based on our current test location
            target_pyfile = path.split(build_spec['target'].replace('"', ''))[-1]
            file_path = path.join(path.dirname(__file__), target_pyfile)
            run_cmd = '{} -u {}'.format(quote(sys.executable), quote(file_path))
            build_spec['language_dir'] = getResourcePath('languages')
            build_spec['target'] = run_cmd

        app = application.build_app(build_spec=build_spec)
        executor = futures.ThreadPoolExecutor(max_workers=1)
        testResult = executor.submit(assertionFunction, app, build_spec)
        app.MainLoop()
        testResult.result()
        # some extra padding time between starting/stopping the wx App
        app.Destroy()
        time.sleep(1)
Esempio n. 2
0
    def performTest(self, configPath, assertionFunction):
        """
        Primary test harness.

        Instantiates the WX App, and spawns the threads
        required to make assertions against it
        """
        with open(configPath, 'r') as f:
            build_spec = json.loads(f.read())
            # swaps the absolute path stored by Gooey at write time
            # for a relative one based on our current test location
            target_pyfile = path.split(build_spec['target'].replace('"', ''))[-1]
            file_path = path.join(path.dirname(__file__), target_pyfile)
            run_cmd = '{} -u {}'.format(quote(sys.executable), quote(file_path))
            build_spec['language_dir'] = getResourcePath('languages')
            build_spec['target'] = run_cmd

        app = application.build_app(build_spec=build_spec)
        executor = futures.ThreadPoolExecutor(max_workers=1)
        testResult = executor.submit(assertionFunction, app, build_spec)
        app.MainLoop()
        testResult.result()
        # some extra padding time between starting/stopping the wx App
        app.Destroy()
        time.sleep(1)
Esempio n. 3
0
def run_integration(module, assertionFunction, **kwargs):
    """
    Integration test harness.

    WXPython is *super* finicky when it comes to integration tests. It needs
    the main Python thread for its app loop, which means we have to integration
    test on a separate thread. The causes further strangeness in how Unittest
    and WXPython interact. In short, each test must be in its own module and
    thus import its own wx instance, and be run in its own "space."

    So long as the above is satisfied, then integration tests can run reliably.

    """
    from gooey.gui import application
    options = merge(
        {
            'image_dir': '::gooey/default',
            'language_dir': getResourcePath('languages'),
            'show_success_modal': False
        }, kwargs)
    module_path = os.path.abspath(module.__file__)
    parser = module.get_parser()
    build_spec = config_generator.create_from_parser(parser, module_path,
                                                     **options)

    time.sleep(2)
    app = application.build_app(build_spec=build_spec)
    executor = futures.ThreadPoolExecutor(max_workers=1)
    # executor runs in parallel and will submit a wx.Destroy request
    # when done making its assertions
    testResult = executor.submit(assertionFunction, app, build_spec)
    # main loop blocks the main thread
    app.MainLoop()
    # .result() blocks as well while we wait for the thread to finish
    # any waiting it may be doing.
    testResult.result()
    del app
Esempio n. 4
0
def getImageDirectory(targetDir):
    return getResourcePath('images') \
           if targetDir == 'default' \
           else targetDir
Esempio n. 5
0
def loadImages(targetDir):
    defaultImages = resolvePaths(getResourcePath('images'), filenames)
    return {
        'images': merge(defaultImages, collectOverrides(targetDir, filenames))
    }
Esempio n. 6
0
def Gooey(f=None,
          advanced=True,
          language='english',
          auto_start=False,  # TODO: add this to the docs. Used to be `show_config=True`
          target=None,
          program_name=None,
          program_description=None,
          default_size=(610, 530),
          use_legacy_titles=True,
          required_cols=2,
          optional_cols=2,
          dump_build_config=False,
          load_build_config=None,
          monospace_display=False,  # TODO: add this to the docs
          image_dir='::gooey/default',
          language_dir=getResourcePath('languages'),
          progress_regex=None,  # TODO: add this to the docs
          progress_expr=None,  # TODO: add this to the docs
          disable_progress_bar_animation=False,
          disable_stop_button=False,
          group_by_type=True,
          header_height=80,
          navigation='SIDEBAR', # TODO: add this to the docs
          tabbed_groups=False,
          **kwargs):
  '''
  Decorator for client code's main function.
  Serializes argparse data to JSON for use with the Gooey front end
  '''

  params = merge(locals(), locals()['kwargs'])

  def build(payload):
    def run_gooey(self, args=None, namespace=None):
      source_path = sys.argv[0]

      build_spec = None
      if load_build_config:
        try:
          build_spec = json.load(open(load_build_config, "r"))
        except Exception as e:
          print( 'Exception loading Build Config from {0}: {1}'.format(load_build_config, e))
          sys.exit(1)

      if not build_spec:
        build_spec = config_generator.create_from_parser(
          self,
          source_path,
          payload_name=payload.__name__,
          **params)

      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)

    def inner2(*args, **kwargs):
      ArgumentParser.original_parse_args = ArgumentParser.parse_args
      ArgumentParser.parse_args = run_gooey
      return payload(*args, **kwargs)

    inner2.__name__ = payload.__name__
    return inner2

  def run_without_gooey(func):
    return lambda: func()

  if IGNORE_COMMAND in sys.argv:
    sys.argv.remove(IGNORE_COMMAND)
    if callable(f):
      return run_without_gooey(f)
    return run_without_gooey

  if callable(f):
    return build(f)
  return build
def Gooey(
        f=None,
        advanced=True,
        language='english',
        auto_start=False,  # TODO: add this to the docs. Used to be `show_config=True`
        target=None,
        program_name=None,
        program_description=None,
        default_size=(610, 530),
        use_legacy_titles=True,
        required_cols=2,
        optional_cols=2,
        dump_build_config=False,
        load_build_config=None,
        monospace_display=False,  # TODO: add this to the docs
        image_dir='::gooey/default',
        language_dir=getResourcePath('languages'),
        progress_regex=None,  # TODO: add this to the docs
        progress_expr=None,  # TODO: add this to the docs
        hide_progress_msg=False,  # TODO: add this to the docs
        disable_progress_bar_animation=False,
        disable_stop_button=False,
        group_by_type=True,
        header_height=80,
        navigation='SIDEBAR',  # TODO: add this to the docs
        tabbed_groups=False,
        **kwargs):
    '''
  Decorator for client code's main function.
  Serializes argparse data to JSON for use with the Gooey front end
  '''

    params = merge(locals(), locals()['kwargs'])

    def build(payload):
        def run_gooey(self, args=None, namespace=None):
            # This import is delayed so it is not in the --ignore-gooey codepath.
            from gooey.gui import application
            source_path = sys.argv[0]

            build_spec = None
            if load_build_config:
                try:
                    exec_dir = os.path.dirname(sys.argv[0])
                    open_path = os.path.join(exec_dir, load_build_config)
                    build_spec = json.load(open(open_path, "r"))
                except Exception as e:
                    print(
                        'Exception loading Build Config from {0}: {1}'.format(
                            load_build_config, e))
                    sys.exit(1)

            if not build_spec:
                build_spec = config_generator.create_from_parser(
                    self, source_path, payload_name=payload.__name__, **params)

            if dump_build_config:
                config_path = os.path.join(os.path.dirname(sys.argv[0]),
                                           '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)

        def inner2(*args, **kwargs):
            ArgumentParser.original_parse_args = ArgumentParser.parse_args
            ArgumentParser.parse_args = run_gooey
            return payload(*args, **kwargs)

        inner2.__name__ = payload.__name__
        return inner2

    def run_without_gooey(func):
        return lambda *args, **kwargs: func(*args, **kwargs)

    if IGNORE_COMMAND in sys.argv:
        sys.argv.remove(IGNORE_COMMAND)
        if callable(f):
            return run_without_gooey(f)
        return run_without_gooey

    if callable(f):
        return build(f)
    return build
Esempio n. 8
0
    'advanced': True,
    'language': 'english',
    'auto_start':
    False,  # TODO: add this to the docs. Used to be `show_config=True`
    'target': None,
    'program_name': None,
    'program_description': None,
    'default_size': (610, 530),
    'use_legacy_titles': True,
    'required_cols': 2,
    'optional_cols': 2,
    'dump_build_config': False,
    'load_build_config': None,
    'monospace_display': False,  # TODO: add this to the docs
    'image_dir': '::gooey/default',
    'language_dir': getResourcePath('languages'),
    'progress_regex': None,  # TODO: add this to the docs
    'progress_expr': None,  # TODO: add this to the docs
    'hide_progress_msg': False,  # TODO: add this to the docs
    'disable_progress_bar_animation': False,
    'disable_stop_button': False,
    'group_by_type': True,
    'header_height': 80,
    'navigation': 'SIDEBAR',  # TODO: add this to the docs
    'tabbed_groups': False,
    'use_cmd_args': False,
    'timing_options': {
        'show_time_remaining': False,
        'hide_time_remaining_on_complete': True
    }
}
Esempio n. 9
0
def getImageDirectory(targetDir):
    return getResourcePath('images') \
           if targetDir == 'default' \
           else targetDir
Esempio n. 10
0
def loadImages(targetDir):
    defaultImages = resolvePaths(getResourcePath('images'), filenames)
    return {'images': merge(defaultImages, collectOverrides(targetDir, filenames))}
Esempio n. 11
0
def gooey_params(**kwargs) -> GooeyParams:
    """
    Builds the full GooeyParams object from an arbitrary subset of supplied values
    """
    return GooeyParams(**{  # type: ignore
        'show_preview_warning': kwargs.get('show_preview_warning', True),
        'language': kwargs.get('language', 'english'),
        'target': kwargs.get('target'),

        'dump_build_config': kwargs.get('dump_build_config', False),
        'load_build_config': kwargs.get('load_build_config'),
        'use_cmd_args': kwargs.get('use_cmd_args', False),

        'suppress_gooey_flag': kwargs.get('suppress_gooey_flag') or False,
        # TODO: I should not read from the environment.
        # remains here for legacy reasons pending refactor
        'program_name': kwargs.get('program_name') or os.path.basename(sys.argv[0]).replace('.py', ''),
        'program_description': kwargs.get('program_description') or '',
        'sidebar_title': kwargs.get('sidebar_title', 'Actions'),
        'default_size': kwargs.get('default_size', (610, 530)),
        'auto_start': kwargs.get('auto_start', False),
        'advanced': kwargs.get('advanced', True),
        'run_validators': kwargs.get('run_validators', True),
        'encoding': kwargs.get('encoding', 'utf-8'),
        'show_stop_warning': kwargs.get('show_stop_warning', True),
        'show_success_modal': kwargs.get('show_success_modal', True),
        'show_failure_modal': kwargs.get('show_failure_modal', True),
        'force_stop_is_error': kwargs.get('force_stop_is_error', True),
        'poll_external_updates': kwargs.get('poll_external_updates', False),
        'return_to_config': kwargs.get('return_to_config', False),
        'show_restart_button': kwargs.get('show_restart_button', True),
        'requires_shell': kwargs.get('requires_shell', True),
        'menu': kwargs.get('menu', []),
        'clear_before_run': kwargs.get('clear_before_run', False),
        'fullscreen': kwargs.get('fullscreen', False),

        'use_legacy_titles': kwargs.get('use_legacy_titles', True),
        'required_cols': kwargs.get('required_cols', 2),
        'optional_cols': kwargs.get('optional_cols', 2),
        'manual_start': False,
        'monospace_display': kwargs.get('monospace_display', False),

        'image_dir': kwargs.get('image_dir', '::gooey/default'),
        # TODO: this directory resolution shouldn't happen here!
        # TODO: leaving due to legacy for now
        'language_dir': kwargs.get('language_dir', getResourcePath('languages')),
        'progress_regex': kwargs.get('progress_regex'),
        'progress_expr': kwargs.get('progress_expr'),
        'hide_progress_msg': kwargs.get('hide_progress_msg', False),

        'timing_options': merge({
            'show_time_remaining': False,
            'hide_time_remaining_on_complete': True
        }, kwargs.get('timing_options', {})),
        'disable_progress_bar_animation': kwargs.get('disable_progress_bar_animation', False),
        'disable_stop_button': kwargs.get('disable_stop_button'),
        'shutdown_signal': kwargs.get('shutdown_signal', signal.SIGTERM),
        'use_events': parse_events(kwargs.get('use_events', [])),


        'navigation': kwargs.get('navigation', constants.SIDEBAR),
        'show_sidebar': kwargs.get('show_sidebar', False),
        'tabbed_groups': kwargs.get('tabbed_groups', False),
        'group_by_type': kwargs.get('group_by_type', True),


        'body_bg_color': kwargs.get('body_bg_color', '#f0f0f0'),
        'header_bg_color': kwargs.get('header_bg_color', '#ffffff'),
        'header_height': kwargs.get('header_height', 90),
        'header_show_title': kwargs.get('header_show_title', True),
        'header_show_subtitle': kwargs.get('header_show_subtitle', True),
        'header_image_center': kwargs.get('header_image_center', False),
        'footer_bg_color': kwargs.get('footer_bg_color', '#f0f0f0'),
        'sidebar_bg_color': kwargs.get('sidebar_bg_color', '#f2f2f2'),

        'terminal_panel_color': kwargs.get('terminal_panel_color', '#F0F0F0'),
        'terminal_font_color': kwargs.get('terminal_font_color', '#000000'),
        'terminal_font_family': kwargs.get('terminal_font_family', None),
        'terminal_font_weight': _get_font_weight(kwargs),
        'terminal_font_size': kwargs.get('terminal_font_size', None),
        'richtext_controls': kwargs.get('richtext_controls', False),
        'error_color': kwargs.get('error_color', '#ea7878'),
        # TODO: remove. Only useful for testing
        'cli': kwargs.get('cli', sys.argv),
    })