예제 #1
0
 def test_mutually_exclusive_groups(self):
     script_path = os.path.join(self.script_dir, 'mutually_exclusive.py')
     parser = Parser(script_path=script_path)
     script_params = parser.get_script_description()
     self.assertDictEqual(
         script_params['inputs'][''][0],
         {
             'nodes': [
                 {
                     'model': 'BooleanField', 'type': 'checkbox', 'mutex_group': {'id': 0, 'title': None},
                     'name': 'foo', 'required': False, 'help': None, 'param': '--foo', 'param_action': set(),
                     'choices': None, 'choice_limit': 0, 'checked': False,
                 },
                 {
                     'model': 'BooleanField', 'type': 'checkbox', 'mutex_group': {'id': 0, 'title': None},
                     'name': 'bar', 'required': False, 'help': None, 'param': '--bar', 'param_action': set(),
                     'choices': None, 'choice_limit': 0, 'checked': True,
                 },
                 {
                     'model': 'BooleanField', 'type': 'checkbox', 'mutex_group': {'id': 1, 'title': None},
                     'name': 'foo2', 'required': False, 'help': None, 'param': '--foo2', 'param_action': set(),
                     'choices': None, 'choice_limit': 0, 'checked': False,
                 },
                 {
                     'model': 'BooleanField', 'type': 'checkbox', 'mutex_group': {'id': 1, 'title': None},
                     'name': 'bar2', 'required': False, 'help': None, 'param': '--bar2', 'param_action': set(),
                     'choices': None, 'choice_limit': 0, 'checked': True,
                 },
             ],
             'group': 'optional arguments',
         },
     )
예제 #2
0
    def test_argparse_specify_every_param(self):
        script_path = os.path.join(self.script_dir, 'choices.py')
        parser = Parser(script_path=script_path)

        script_params = parser.get_script_description()
        self.assertEqual(script_params['path'], script_path)

        append_field = [i for i in script_params['inputs'][''][1]['nodes'] if i['param'] == '--need-at-least-one-numbers'][0]
        self.assertIn(SPECIFY_EVERY_PARAM, append_field['param_action'])
예제 #3
0
    def test_argparse_specify_every_param(self):
        script_path = os.path.join(self.script_dir, 'choices.py')
        parser = Parser(script_path=script_path)

        script_params = parser.get_script_description()
        self.assertEqual(script_params['path'], script_path)

        append_field = [i for i in script_params['inputs'][''][1]['nodes'] if i['param'] == '--need-at-least-one-numbers'][0]
        self.assertIn(SPECIFY_EVERY_PARAM, append_field['param_action'])
예제 #4
0
def add_wooey_script(script=None, group=None):
    from ..models import Script, ScriptGroup, ScriptParameter, ScriptParameterGroup
    # if we have a script, it will at this point be saved in the model pointing to our file system, which may be
    # ephemeral. So the path attribute may not be implemented
    if not isinstance(script, six.string_types):
        try:
            script_path = script.script_path.path
        except NotImplementedError:
            script_path = script.script_path.name

    script_obj, script = (script, get_storage_object(script_path, local=True).path) if isinstance(script, Script) else (False, script)
    if isinstance(group, ScriptGroup):
        group = group.group_name
    if group is None:
        group = 'Wooey Scripts'
    basename, extension = os.path.splitext(script)
    filename = os.path.split(basename)[1]

    parser = Parser(script_name=filename, script_path=script)
    if not parser.valid:
        return (False, parser.error)
    # make our script
    d = parser.get_script_description()
    script_group, created = ScriptGroup.objects.get_or_create(group_name=group)
    if script_obj is False:
        wooey_script, created = Script.objects.get_or_create(script_group=script_group, script_description=d['description'],
                                                               script_path=script, script_name=d['name'])
    else:
        created = False
        if not script_obj.script_description:
            script_obj.script_description = d['description']
        if not script_obj.script_name:
            script_obj.script_name = d['name']
        # probably a much better way to avoid this recursion
        script_obj._add_script = False
        script_obj.save()
    if not created:
        if script_obj is False:
            wooey_script.script_version += 1
            wooey_script.save()
    if script_obj:
        wooey_script = script_obj
    # make our parameters
    for param_group_info in d['inputs']:
        param_group, created = ScriptParameterGroup.objects.get_or_create(group_name=param_group_info.get('group'), script=wooey_script)
        for param in param_group_info.get('nodes'):
            # TODO: fix 'file' to be global in argparse
            is_out = True if param.get('upload', None) is False and param.get('type') == 'file' else not param.get('upload', False)
            script_param, created = ScriptParameter.objects.get_or_create(script=wooey_script, short_param=param['param'], script_param=param['name'],
                                                                          is_output=is_out, required=param.get('required', False),
                                                                          form_field=param['model'], default=param.get('default'), input_type=param.get('type'),
                                                                          choices=json.dumps(param.get('choices')), choice_limit=json.dumps(param.get('choice_limit', 1)),
                                                                          param_help=param.get('help'), is_checked=param.get('checked', False),
                                                                          parameter_group=param_group)
    # update our loaded scripts
    load_scripts()
    return (True, '')
예제 #5
0
    def test_subparser(self):
        script_path = os.path.join(self.script_dir, 'subparser_script.py')
        parser = Parser(script_path=script_path)
        description = parser.get_script_description()
        main_parser = description['inputs']['']
        main_parser_group1 = main_parser[0]
        self.assertEqual(main_parser_group1['nodes'][0]['name'], 'test_arg')
        self.assertEqual(main_parser_group1['group'], 'optional arguments')

        subparser1 = description['inputs']['subparser1']
        subparser_group1 = subparser1[0]
        self.assertEqual(subparser_group1['nodes'][0]['name'], 'sp1')
예제 #6
0
    def test_subparser(self):
        script_path = os.path.join(self.script_dir, 'subparser_script.py')
        parser = Parser(script_path=script_path)
        description = parser.get_script_description()
        main_parser = description['inputs']['']
        main_parser_group1 = main_parser[0]
        self.assertEqual(main_parser_group1['nodes'][0]['name'], 'test_arg')
        self.assertEqual(main_parser_group1['group'], 'optional arguments')

        subparser1 = description['inputs']['subparser1']
        subparser_group1 = subparser1[0]
        self.assertEqual(subparser_group1['nodes'][0]['name'], 'sp1')
예제 #7
0
 def test_zipapp(self):
     script_path = os.path.join(self.script_dir, 'data_reader.zip')
     parser = Parser(script_path=script_path)
     script_params = parser.get_script_description()
     self.assertDictEqual(
         script_params['inputs'][''][0],
         {
             'nodes': [
                 {'param_action': set([]), 'name': 'n', 'required': False, 'param': '-n', 'choices': None, 'value': -1,
                 'choice_limit': None, 'model': 'IntegerField', 'type': 'text', 'help': 'The number of rows to read.'}],
             'group': 'optional arguments',
         }
     )
예제 #8
0
 def test_zipapp(self):
     script_path = os.path.join(self.script_dir, 'data_reader.zip')
     parser = Parser(script_path=script_path)
     script_params = parser.get_script_description()
     self.assertDictEqual(
         script_params['inputs'][''][0],
         {
             'nodes': [
                 {'param_action': set([]), 'name': 'n', 'required': False, 'param': '-n', 'choices': None, 'value': -1,
                 'choice_limit': None, 'model': 'IntegerField', 'type': 'text', 'help': 'The number of rows to read.', 'mutex_group': {},}],
             'group': 'optional arguments',
         }
     )
예제 #9
0
    def test_error_script(self):
        script_path = os.path.join(self.script_dir, 'error_script.py')
        parser = Parser(script_path=script_path)

        if PY_MINOR_VERSION >= PY36:
            self.assertIn('ModuleNotFoundError', parser.error)
        else:
            self.assertIn('ImportError', parser.error)
        self.assertIn('something_i_dont_have', parser.error)

        script_path = os.path.join(self.script_dir, 'choices.py')
        parser = Parser(script_path=script_path)
        self.assertEquals('', parser.error)
예제 #10
0
    def test_function_type_script(self):
        script_path = os.path.join(self.script_dir, 'function_argtype.py')
        parser = Parser(script_path=script_path)

        script_params = parser.get_script_description()
        self.assertEqual(script_params['path'], script_path)

        self.assertDictEqual(
            script_params['inputs'][''][0],
            {
                'nodes': [
                    {
                        'param_action': set([]),
                        'name': 'start_date',
                        'required': True,
                        'param': '',
                        'choices': None,
                        'choice_limit': None,
                        'model': 'CharField',
                        'type': 'text',
                        'help': 'Use date in format YYYYMMDD (e.g. 20180131)',
                        # The default argument
                        'value': '20180131',
                        'mutex_group': {},
                    },
                    {
                        'param_action': set([]),
                        'name': 'lowercase',
                        'required': True,
                        'param': '',
                        'choices': None,
                        'value': 'ABC',
                        'choice_limit': None,
                        'model': 'CharField',
                        'type': 'text',
                        'help': 'Lowercase it',
                        'mutex_group': {},
                    }

                ],
                'group': 'positional arguments'
            }
        )
예제 #11
0
    def test_function_type_script(self):
        script_path = os.path.join(self.script_dir, 'function_argtype.py')
        parser = Parser(script_path=script_path)

        script_params = parser.get_script_description()
        self.assertEqual(script_params['path'], script_path)

        self.assertDictEqual(
            script_params['inputs'][''][0],
            {
                'nodes': [
                    {
                        'param_action': set([]),
                        'name': 'start_date',
                        'required': True,
                        'param': '',
                        'choices': None,
                        'choice_limit': None,
                        'model': 'CharField',
                        'type': 'text',
                        'help': 'Use date in format YYYYMMDD (e.g. 20180131)',
                        # The default argument
                        'value': '20180131'
                    },
                    {
                        'param_action': set([]),
                        'name': 'lowercase',
                        'required': True,
                        'param': '',
                        'choices': None,
                        'value': 'ABC',
                        'choice_limit': None,
                        'model': 'CharField',
                        'type': 'text',
                        'help': 'Lowercase it'
                    }

                ],
                'group': 'positional arguments'
            }
        )
예제 #12
0
    def test_naval_fate(self):
        script_path = os.path.join(self.script_dir, 'naval_fate.py')
        parser = Parser(script_path=script_path)
        script_params = parser.get_script_description()
        self.assertEqual(script_params['path'], script_path)
        self.assertEqual(script_params['name'], 'naval_fate')

        # Make sure we return parameters in the order the script defined them and in groups
        # We do not test this that exhaustively atm since the structure is likely to change when subparsers
        # are added
        self.assertDictEqual(
            script_params['inputs'][''][0],
            {
                'nodes': [
                    {'model': 'CharField', 'type': 'text', 'name': 'speed', 'param': '--speed'},
                    {'model': 'BooleanField', 'type': 'checkbox', 'name': 'moored', 'param': '--moored'},
                    {'model': 'BooleanField', 'type': 'checkbox', 'name': 'drifting', 'param': '--drifting'}
                ],
                'group': 'default'
            }
        )
예제 #13
0
    def test_naval_fate(self):
        script_path = os.path.join(self.script_dir, 'naval_fate.py')
        parser = Parser(script_path=script_path)
        script_params = parser.get_script_description()
        self.assertEqual(script_params['path'], script_path)
        self.assertEqual(script_params['name'], 'naval_fate')

        # Make sure we return parameters in the order the script defined them and in groups
        # We do not test this that exhaustively atm since the structure is likely to change when subparsers
        # are added
        self.assertDictEqual(
            script_params['inputs'][''][0],
            {
                'nodes': [
                    {'model': 'CharField', 'type': 'text', 'name': 'speed', 'param': '--speed'},
                    {'model': 'BooleanField', 'type': 'checkbox', 'name': 'moored', 'param': '--moored'},
                    {'model': 'BooleanField', 'type': 'checkbox', 'name': 'drifting', 'param': '--drifting'}
                ],
                'group': 'default'
            }
        )
예제 #14
0
    def test_argparse_script(self):
        script_path = os.path.join(self.script_dir, 'choices.py')
        parser = Parser(script_path=script_path)

        script_params = parser.get_script_description()
        self.assertEqual(script_params['path'], script_path)

        # Make sure we return parameters in the order the script defined them and in groups
        # We do not test this that exhaustively atm since the structure is likely to change when subparsers
        # are added
        self.assertDictEqual(
            script_params['inputs'][''][0],
            {
                'nodes': [
                    {'param_action': set([]), 'name': 'first_pos', 'required': True, 'param': '', 'choices': None,
                    'choice_limit': None, 'model': 'CharField', 'type': 'text', 'help': None, 'mutex_group': {},},
                    {'param_action': set([]), 'name': 'second-pos', 'required': True, 'param': '', 'choices': None,
                    'choice_limit': None, 'model': 'CharField', 'type': 'text', 'help': None, 'mutex_group': {},}
                ],
                'group': 'positional arguments'
            }
        )
예제 #15
0
    def test_argparse_script(self):
        script_path = os.path.join(self.script_dir, 'choices.py')
        parser = Parser(script_path=script_path)

        script_params = parser.get_script_description()
        self.assertEqual(script_params['path'], script_path)

        # Make sure we return parameters in the order the script defined them and in groups
        # We do not test this that exhaustively atm since the structure is likely to change when subparsers
        # are added
        self.assertDictEqual(
            script_params['inputs'][''][0],
            {
                'nodes': [
                    {'param_action': set([]), 'name': 'first_pos', 'required': True, 'param': '', 'choices': None,
                    'choice_limit': None, 'model': 'CharField', 'type': 'text', 'help': None},
                    {'param_action': set([]), 'name': 'second-pos', 'required': True, 'param': '', 'choices': None,
                    'choice_limit': None, 'model': 'CharField', 'type': 'text', 'help': None}
                ],
                'group': 'positional arguments'
            }
        )
예제 #16
0
파일: utils.py 프로젝트: brumar/Wooey-1
def add_wooey_script(script_version=None,
                     script_path=None,
                     group=None,
                     script_name=None):
    # There is a class called 'Script' which contains the general information about a script. However, that is not where the file details
    # of the script lie. That is the ScriptVersion model. This allows the end user to tag a script as a favorite/etc. and set
    # information such as script descriptions/names that do not constantly need to be updated with every version change. Thus,
    # a ScriptVersion stores the file info and such.
    from ..models import Script, ScriptGroup, ScriptParser, ScriptParameter, ScriptParameterGroup, ScriptVersion
    # if we are adding through the admin, at this point the file will be saved already and this method will be receiving
    # the scriptversion object. Otherwise, we are adding through the managementment command. In this case, the file will be
    # a location and we need to setup the Script and ScriptVersion in here.
    # check if the script exists
    script_path = script_path or script_version.script_path.name
    script_name = script_name or (script_version.script.script_name
                                  if script_version else os.path.basename(
                                      os.path.splitext(script_path)[0]))
    with get_storage_object(script_path) as so:
        checksum = get_checksum(buff=so.read())
    existing_version = None
    try:
        existing_version = ScriptVersion.objects.get(
            checksum=checksum, script__script_name=script_name)
    except ObjectDoesNotExist:
        pass
    except MultipleObjectsReturned:
        # This exists because previous versions did not enforce a checksum, so multiple scriptverisons are
        # possible with the same checksum.
        existing_version = ScriptVersion.objects.filter(
            checksum=checksum, script__script_name=script_name).order_by(
                'script_version', 'script_iteration').last()
    # If script_verison is None, it likely came from `addscript`
    if existing_version is not None and (script_version is None or
                                         existing_version != script_version):
        return {
            'valid':
            False,
            'errors':
            errors.DuplicateScriptError(
                ScriptVersion.error_messages['duplicate_script']),
            'script':
            existing_version,
        }

    local_storage = get_storage(local=True)
    if script_version is not None:
        # we are updating the script here or creating it through the admin

        # we need to move the script to the wooey scripts directory now
        # handle remotely first, because by default scripts will be saved remotely if we are using an
        # ephemeral file system
        old_name = script_version.script_path.name
        new_name = os.path.normpath(
            os.path.join(wooey_settings.WOOEY_SCRIPT_DIR, old_name)
            if not old_name.startswith(wooey_settings.WOOEY_SCRIPT_DIR) else
            old_name)

        current_storage = get_storage(
            local=not wooey_settings.WOOEY_EPHEMERAL_FILES)
        current_file = current_storage.open(old_name)
        if current_storage.exists(new_name):
            new_name = current_storage.get_available_name(new_name)
        new_path = current_storage.save(new_name, current_file)

        # remove the old file
        if old_name != new_name:
            current_file.close()
            current_storage.delete(old_name)
            current_file = current_storage.open(new_path)

        script_version._rename_script = True
        script_version.script_path.name = new_name
        script_version.save()

        # download the script locally if it doesn't exist
        if not local_storage.exists(new_path):
            new_path = local_storage.save(new_path, current_file)

        # Close the old file if it is not yet
        if not current_file.closed:
            current_file.close()

        with get_storage_object(new_path, local=True) as so:
            script = so.path
        with local_storage.open(new_path) as local_handle:
            local_file = local_handle.name
    else:
        # we got a path, if we are using a remote file system, it will be located remotely by default
        # make sure we have it locally as well
        if wooey_settings.WOOEY_EPHEMERAL_FILES:
            remote_storage = get_storage(local=False)
            with remote_storage.open(script_path) as remote_file:
                local_file = local_storage.save(script_path, remote_file)
        else:
            with local_storage.open(script_path) as local_handle:
                local_file = local_handle.name
        with get_storage_object(local_file, local=True) as so:
            script = so.path
    if isinstance(group, ScriptGroup):
        group = group.group_name
    if group is None:
        group = 'Wooey Scripts'
    basename, extension = os.path.splitext(script)
    filename = os.path.split(basename)[1]

    parser = Parser(script_name=filename,
                    script_path=local_storage.path(local_file))
    if not parser.valid:
        return {
            'valid': False,
            'errors': errors.ParserError(parser.error),
        }
    # make our script
    script_schema = parser.get_script_description()
    script_group, created = ScriptGroup.objects.get_or_create(group_name=group)
    version_string = script_schema.get('version')
    if version_string is None:
        version_string = '1'
    try:
        parse_version(version_string)
    except:
        sys.stderr.write(
            'Error parsing version, defaulting to 1. Error message:\n {}'.
            format(traceback.format_exc()))
        version_string = '1'
    if script_version is None:
        # we are being loaded from the management command, create/update our script/version
        script_kwargs = {
            'script_group': script_group,
            'script_name': script_name or script_schema['name']
        }
        version_kwargs = {
            'script_version': version_string,
            'script_path': local_file,
            'default_version': True,
            'checksum': checksum
        }
        # does this script already exist in the database?
        script_created = Script.objects.filter(**script_kwargs).count() == 0
        if script_created:
            # we are creating it, add the description if we can
            script_kwargs.update(
                {'script_description': script_schema['description']})
            wooey_script = Script(**script_kwargs)
            wooey_script._script_cl_creation = True
            wooey_script.save()
            version_kwargs.update({'script_iteration': 1})
        else:
            # we're updating it
            wooey_script = Script.objects.get(**script_kwargs)
            if not wooey_script.script_description and script_schema[
                    'description']:
                wooey_script.script_description = script_schema['description']
                wooey_script.save()
            # check if we have the version in our script version
            current_versions = ScriptVersion.objects.filter(
                script=wooey_script, script_version=version_string)
            if current_versions.count() == 0:
                next_iteration = 1
            else:
                # get the largest iteration and add 1 to it
                next_iteration = sorted(
                    [i.script_iteration for i in current_versions])[-1] + 1
            # disable older versions
            ScriptVersion.objects.filter(script=wooey_script).update(
                default_version=False)
            version_kwargs.update({'script_iteration': next_iteration})
        version_kwargs.update({'script': wooey_script})
        script_version = ScriptVersion(**version_kwargs)
        script_version._script_cl_creation = True
        script_version.checksum = checksum
        script_version.save()
    else:
        # we are being created/updated from the admin
        wooey_script = script_version.script
        if not wooey_script.script_description:
            wooey_script.script_description = script_schema['description']
        if not wooey_script.script_name:
            wooey_script.script_name = script_name or script_schema['name']
        past_versions = ScriptVersion.objects.filter(
            script=wooey_script,
            script_version=version_string).exclude(pk=script_version.pk)
        if len(past_versions) == 0:
            script_version.script_version = version_string
        script_version.script_iteration = past_versions.count() + 1
        # Make all old versions non-default
        ScriptVersion.objects.filter(script=wooey_script).update(
            default_version=False)
        script_version.default_version = True
        script_version.checksum = checksum
        wooey_script.save()
        script_version.save()

    # make our parameters
    parameter_index = 0
    for parser_name, parser_inputs in six.iteritems(script_schema['inputs']):
        parsers = ScriptParser.objects.filter(
            name=parser_name, script_version__script=wooey_script).distinct()
        if len(parsers):
            parser = parsers.first()
        else:
            parser = ScriptParser.objects.create(name=parser_name, )
            parser.save()
        parser.script_version.add(script_version)

        for param_group_info in parser_inputs:
            param_group_name = param_group_info.get('group')

            param_groups = ScriptParameterGroup.objects.filter(
                group_name=param_group_name,
                script_version__script=wooey_script).distinct()

            # TODO: There should only ever be one, should probably do a harder enforcement of this.
            if len(param_groups):
                param_group = param_groups.first()
            else:
                param_group = ScriptParameterGroup.objects.create(
                    group_name=param_group_name, )
                param_group.save()
            param_group.script_version.add(script_version)

            for param in param_group_info.get('nodes'):
                # TODO: fix 'file' to be global in argparse
                is_out = True if (param.get('upload', None) == False
                                  and param.get('type') == 'file'
                                  ) else not param.get('upload', False)
                script_param_kwargs = {
                    'short_param':
                    param['param'],
                    'script_param':
                    param['name'],
                    'is_output':
                    is_out,
                    'required':
                    param.get('required', False),
                    'form_field':
                    param['model'],
                    'default':
                    param.get('value'),
                    'input_type':
                    param.get('type'),
                    'choices':
                    json.dumps(param.get('choices')),
                    'choice_limit':
                    json.dumps(param.get('choice_limit', 1)),
                    'param_help':
                    param.get('help'),
                    'is_checked':
                    param.get('checked', False),
                    # parameter_group': param_group,
                    'collapse_arguments':
                    SPECIFY_EVERY_PARAM
                    not in param.get('param_action', set()),
                }

                parameter_index += 1

                # This indicates the parameter is a positional argument. If these are changed between script versions,
                # the script can break. Therefore, we have to add an additional filter on the parameter order that
                # keyword arguments can ignore.
                if not param['param']:
                    script_param_kwargs['param_order'] = parameter_index

                script_params = ScriptParameter.objects.filter(
                    **script_param_kwargs).filter(
                        script_version__script=wooey_script,
                        parameter_group__group_name=param_group_name,
                        parser__name=parser_name).distinct()

                if not script_params:
                    script_param_kwargs['parser'] = parser
                    script_param_kwargs['parameter_group'] = param_group
                    if 'param_order' not in script_param_kwargs:
                        script_param_kwargs['param_order'] = parameter_index

                    script_param, created = ScriptParameter.objects.get_or_create(
                        **script_param_kwargs)
                    script_param.script_version.add(script_version)
                else:
                    # If we are here, the script parameter exists and has not changed since the last update. We can simply
                    # point the new script at the old script parameter. This lets us clone old scriptversions and have their
                    # parameters still auto populate.
                    script_param = script_params[0]
                    if 'param_order' not in script_param_kwargs:
                        script_param.param_order = parameter_index
                    script_param.script_version.add(script_version)
                    script_param.save()

    return {
        'valid': True,
        'errors': None,
        'script': script_version,
    }
예제 #17
0
def add_wooey_script(script_version=None, script_path=None, group=None):
    # There is a class called 'Script' which contains the general information about a script. However, that is not where the file details
    # of the script lie. That is the ScriptVersion model. This allows the end user to tag a script as a favorite/etc. and set
    # information such as script descriptions/names that do not constantly need to be updated with every version change. Thus,
    # a ScriptVersion stores the file info and such.
    from ..models import Script, ScriptGroup, ScriptParameter, ScriptParameterGroup, ScriptVersion
    # if we are adding through the admin, at this point the file will be saved already and this method will be receiving
    # the scriptversion object. Otherwise, we are adding through the managementment command. In this case, the file will be
    # a location and we need to setup the Script and ScriptVersion in here.

    local_storage = get_storage(local=True)
    if script_version is not None:
        # we are updating the script here or creating it through the admin

        # we need to move the script to the wooey scripts directory now
        # handle remotely first, because by default scripts will be saved remotely if we are using an
        # ephemeral file system
        old_name = script_version.script_path.name
        new_name = os.path.normpath(
            os.path.join(wooey_settings.WOOEY_SCRIPT_DIR, old_name)
            if not old_name.startswith(wooey_settings.WOOEY_SCRIPT_DIR) else
            old_name)

        current_storage = get_storage(
            local=not wooey_settings.WOOEY_EPHEMERAL_FILES)
        current_file = current_storage.open(old_name)
        if current_storage.exists(new_name):
            new_name = current_storage.get_available_name(new_name)
        new_path = current_storage.save(new_name, current_file)

        # remove the old file
        if old_name != new_name:
            current_file.close()
            current_storage.delete(old_name)
            current_file = current_storage.open(new_path)

        script_version._rename_script = True
        script_version.script_path.name = new_name
        script_version.save()

        # download the script locally if it doesn't exist
        if not local_storage.exists(new_path):
            new_path = local_storage.save(new_path, current_file)

        script = get_storage_object(new_path, local=True).path
        local_file = local_storage.open(new_path).name
    else:
        # we got a path, if we are using a remote file system, it will be located remotely by default
        # make sure we have it locally as well
        if wooey_settings.WOOEY_EPHEMERAL_FILES:
            remote_storage = get_storage(local=False)
            remote_file = remote_storage.open(script_path)
            local_file = local_storage.save(script_path, remote_file)
        else:
            local_file = local_storage.open(script_path).name
        script = get_storage_object(local_file, local=True).path

    if isinstance(group, ScriptGroup):
        group = group.group_name
    if group is None:
        group = 'Wooey Scripts'
    basename, extension = os.path.splitext(script)
    filename = os.path.split(basename)[1]

    parser = Parser(script_name=filename,
                    script_path=local_storage.path(local_file))
    if not parser.valid:
        return {'valid': False, 'errors': parser.error}
    # make our script
    d = parser.get_script_description()
    script_group, created = ScriptGroup.objects.get_or_create(group_name=group)
    version_string = d.get('version')
    if version_string is None:
        version_string = '1'
    try:
        parse_version(version_string)
    except:
        sys.stderr.write(
            'Error parsing version, defaulting to 1. Error message:\n {}'.
            format(traceback.format_exc()))
        version_string = '1'
    if script_version is None:
        # we are being loaded from the management command, create/update our script/version
        script_kwargs = {
            'script_group': script_group,
            'script_name': d['name']
        }
        version_kwargs = {
            'script_version': version_string,
            'script_path': local_file,
            'default_version': True
        }
        # does this script already exist in the database?
        script_created = Script.objects.filter(**script_kwargs).count() == 0
        if script_created:
            # we are creating it, add the description if we can
            script_kwargs.update({'script_description': d['description']})
            wooey_script = Script(**script_kwargs)
            wooey_script._script_cl_creation = True
            wooey_script.save()
            version_kwargs.update({'script_iteration': 1})
        else:
            # we're updating it
            wooey_script = Script.objects.get(**script_kwargs)
            if not wooey_script.script_description and d['description']:
                wooey_script.script_description = d['description']
                wooey_script.save()
            # check if we have the version in our script version
            current_versions = ScriptVersion.objects.filter(
                script=wooey_script, script_version=version_string)
            if current_versions.count() == 0:
                next_iteration = 1
                # disable older versions
                ScriptVersion.objects.filter(
                    script=wooey_script, script_version=version_string).update(
                        default_version=False)
            else:
                # get the largest iteration and add 1 to it
                next_iteration = sorted(
                    [i.script_iteration for i in current_versions])[-1] + 1
            version_kwargs.update({'script_iteration': next_iteration})
        version_kwargs.update({'script': wooey_script})
        script_version = ScriptVersion(**version_kwargs)
        script_version._script_cl_creation = True
        script_version.save()
    else:
        # we are being created/updated from the admin
        if not script_version.script.script_description:
            script_version.script.script_description = d['description']
        if not script_version.script.script_name:
            script_version.script.script_name = d['name']
        past_versions = ScriptVersion.objects.filter(
            script=script_version.script,
            script_version=version_string).exclude(pk=script_version.pk)
        script_version.script_iteration = past_versions.count() + 1
        past_versions.update(default_version=False)
        script_version.default_version = True
        script_version.script.save()
        script_version.save()

    # make our parameters
    for param_group_info in d['inputs']:
        param_group, created = ScriptParameterGroup.objects.get_or_create(
            group_name=param_group_info.get('group'),
            script_version=script_version)
        for param in param_group_info.get('nodes'):
            # TODO: fix 'file' to be global in argparse
            is_out = True if param.get('upload', None) is False and param.get(
                'type') == 'file' else not param.get('upload', False)
            script_param, created = ScriptParameter.objects.get_or_create(
                script_version=script_version,
                short_param=param['param'],
                script_param=param['name'],
                is_output=is_out,
                required=param.get('required', False),
                form_field=param['model'],
                default=param.get('value'),
                input_type=param.get('type'),
                choices=json.dumps(param.get('choices')),
                choice_limit=json.dumps(param.get('choice_limit', 1)),
                param_help=param.get('help'),
                is_checked=param.get('checked', False),
                parameter_group=param_group)
    return {'valid': True, 'errors': None, 'script': script_version}
예제 #18
0
파일: utils.py 프로젝트: hottwaj/Wooey
def add_wooey_script(script_version=None, script_path=None, group=None):
    # There is a class called 'Script' which contains the general information about a script. However, that is not where the file details
    # of the script lie. That is the ScriptVersion model. This allows the end user to tag a script as a favorite/etc. and set
    # information such as script descriptions/names that do not constantly need to be updated with every version change. Thus,
    # a ScriptVersion stores the file info and such.
    from ..models import Script, ScriptGroup, ScriptParameter, ScriptParameterGroup, ScriptVersion
    # if we are adding through the admin, at this point the file will be saved already and this method will be receiving
    # the scriptversion object. Otherwise, we are adding through the managementment command. In this case, the file will be
    # a location and we need to setup the Script and ScriptVersion in here.

    local_storage = get_storage(local=True)
    if script_version is not None:
        # we are updating the script here or creating it through the admin

        # we need to move the script to the wooey scripts directory now
        # handle remotely first, because by default scripts will be saved remotely if we are using an
        # ephemeral file system
        old_name = script_version.script_path.name
        new_name = os.path.normpath(os.path.join(wooey_settings.WOOEY_SCRIPT_DIR, old_name) if not old_name.startswith(wooey_settings.WOOEY_SCRIPT_DIR) else old_name)

        current_storage = get_storage(local=not wooey_settings.WOOEY_EPHEMERAL_FILES)
        current_file = current_storage.open(old_name)
        if current_storage.exists(new_name):
            new_name = current_storage.get_available_name(new_name)
        new_path = current_storage.save(new_name, current_file)

        # remove the old file
        if old_name != new_name:
            current_storage.delete(old_name)

        script_version._rename_script = True
        script_version.script_path.name = new_name
        script_version.save()

        # download the script locally if it doesn't exist
        if not local_storage.exists(new_path):
            new_path = local_storage.save(new_path, current_file)

        script = get_storage_object(new_path, local=True).path
        local_file = local_storage.open(new_path).name
    else:
        # we got a path, if we are using a remote file system, it will be located remotely by default
        # make sure we have it locally as well
        if wooey_settings.WOOEY_EPHEMERAL_FILES:
            remote_storage = get_storage(local=False)
            remote_file = remote_storage.open(script_path)
            local_file = local_storage.save(script_path, remote_file)
        else:
            local_file = local_storage.open(script_path).name
        script = get_storage_object(local_file, local=True).path

    if isinstance(group, ScriptGroup):
        group = group.group_name
    if group is None:
        group = 'Wooey Scripts'
    basename, extension = os.path.splitext(script)
    filename = os.path.split(basename)[1]

    parser = Parser(script_name=filename, script_path=local_storage.path(local_file))
    if not parser.valid:
        return {'valid': False, 'errors': parser.error}
    # make our script
    d = parser.get_script_description()
    script_group, created = ScriptGroup.objects.get_or_create(group_name=group)
    version_string = d.get('version')
    if version_string is None:
        version_string = '1'
    try:
        parse_version(version_string)
    except:
        sys.stderr.write('Error parsing version, defaulting to 1. Error message:\n {}'.format(traceback.format_exc()))
        version_string = '1'
    if script_version is None:
        # we are being loaded from the management command, create/update our script/version
        script_kwargs = {'script_group': script_group, 'script_name': d['name']}
        version_kwargs = {'script_version': version_string, 'script_path': local_file, 'default_version': True}
        # does this script already exist in the database?
        script_created = Script.objects.filter(**script_kwargs).count() == 0
        if script_created:
            # we are creating it, add the description if we can
            script_kwargs.update({'script_description': d['description']})
            wooey_script = Script(**script_kwargs)
            wooey_script._script_cl_creation = True
            wooey_script.save()
            version_kwargs.update({'script_iteration': 1})
        else:
            # we're updating it
            wooey_script = Script.objects.get(**script_kwargs)
            if not wooey_script.script_description and d['description']:
                wooey_script.script_description = d['description']
                wooey_script.save()
            # check if we have the version in our script version
            current_versions = ScriptVersion.objects.filter(script=wooey_script, script_version=version_string)
            if current_versions.count() == 0:
                next_iteration = 1
                # disable older versions
                ScriptVersion.objects.filter(script=wooey_script, script_version=version_string).update(default_version=False)
            else:
                # get the largest iteration and add 1 to it
                next_iteration = sorted([i.script_iteration for i in current_versions])[-1]+1
            version_kwargs.update({'script_iteration': next_iteration})
        version_kwargs.update({'script': wooey_script})
        script_version = ScriptVersion(**version_kwargs)
        script_version._script_cl_creation = True
        script_version.save()
    else:
        # we are being created/updated from the admin
        if not script_version.script.script_description:
            script_version.script.script_description = d['description']
        if not script_version.script.script_name:
            script_version.script.script_name = d['name']
        past_versions = ScriptVersion.objects.filter(script=script_version.script, script_version=version_string).exclude(pk=script_version.pk)
        script_version.script_iteration = past_versions.count()+1
        past_versions.update(default_version=False)
        script_version.default_version = True
        script_version.script.save()
        script_version.save()

    # make our parameters
    for param_group_info in d['inputs']:
        param_group, created = ScriptParameterGroup.objects.get_or_create(group_name=param_group_info.get('group'), script_version=script_version)
        for param in param_group_info.get('nodes'):
            # TODO: fix 'file' to be global in argparse
            is_out = True if param.get('upload', None) is False and param.get('type') == 'file' else not param.get('upload', False)
            script_param, created = ScriptParameter.objects.get_or_create(script_version=script_version, short_param=param['param'], script_param=param['name'],
                                                                          is_output=is_out, required=param.get('required', False),
                                                                          form_field=param['model'], default=param.get('default'), input_type=param.get('type'),
                                                                          choices=json.dumps(param.get('choices')), choice_limit=json.dumps(param.get('choice_limit', 1)),
                                                                          param_help=param.get('help'), is_checked=param.get('checked', False),
                                                                          parameter_group=param_group)
    return {'valid': True, 'errors': None, 'script': script_version}
예제 #19
0
 def test_script_version(self):
     script_path = os.path.join(self.script_dir, 'choices.py')
     parser = Parser(script_path=script_path)
     description = parser.get_script_description()
     self.assertEqual(description['version'], '2' if six.PY2 else '3')
예제 #20
0
 def test_script_version(self):
     script_path = os.path.join(self.script_dir, 'choices.py')
     parser = Parser(script_path=script_path)
     description = parser.get_script_description()
     self.assertEqual(description['version'], '2' if six.PY2 else '3')