Source code for envipyarclib.gptool.parameter.builder

"""
The GPTool Parameter Builder is responsible for creating code blocks to be placed \
into the main GPTool template.
Each create method corresponds to a GPTool method that must be defined in order \
for it to be a valid tool.
These methods implement the GetParameterInfo, UpdateParameter, and \
Execute methods of the GPTool Python class.

For example, to define a GPTool in a Python toolbox, start out with a class definition and implement
the methods arcpy expects::

    class myTool(Object):
        def __init__(self):
            self.label = "My Tool"
            self.description = "Tool description"
            self.canRunInBackground = True

        def getParameterInfo(self):
            # builder.create_param_info() goes here

        def is Licensed(self):
            return True

        def updateParameters(self, parameters):
            # builder.create_update_parameter goes here

        def updateMessages(self, parameters):
            return

        def execute(self, parameters, messages):
            # builder.create_pre_execute goes here
            # submit job
            # builder.create_post_execute goes here

"""
from string import Template
import pkgutil
import importlib
from . import templates


[docs]class UnknownDataTypeError(Exception): """Error class for raising unknown datatypes""" pass
_PARAM_RETURN_TEMPLATE = Template(''' params = $paramList return params ''') _CHOICELIST_TEMPLATE = Template(''' ${name}.filter.type="ValueList" ${name}.filter.list = $choiceList ''') _DIRECTION_MAP = {'input': 'Input', 'output': 'Output'} _PARAM_INDEX_TEMPLATE = Template(''' i${name} = $idx''')
[docs]class ParameterMap(object): """Convenience class for holding a template map""" def __init__(self): self.parameter_map = {} self.load_default_templates()
[docs] def load_default_templates(self): """Load the default templates""" for importer, modname, is_pkg in pkgutil.iter_modules(templates.__path__): self.register_template('.'.join((templates.__name__, modname)))
[docs] def register_template(self, module): """ Register a non-default template :param module: The full package path including the module name of the template to load. """ parameter_module = importlib.import_module(module) parameter_template = parameter_module.template() self.parameter_map[parameter_template.__class__.__name__.upper()] = \ parameter_template
def __getitem__(self, key): return self.parameter_map[key] def __contains__(self, item): return item in self.parameter_map
[docs]def convert_list(in_list): """Converts a list of strings to a printable list of object names""" return ''.join(('[', ','.join(in_list), ']'))
[docs]def create_param_info(task_params, parameter_map): """ Builds the code block for the GPTool GetParameterInfo method based on the input task_params. :param task_params: A list of task parameters to map to GPTool parameters. :return: A string representing the code block to the GPTool GetParameterInfo method. """ gp_params = [] gp_param_list = [] gp_param_idx_list = [] gp_param_idx = 0 for task_param in task_params: # Setup to gp_param dictionary used to substitute against the parameter info template. gp_param = {} # Convert DataType data_type = task_param['type'].upper() if 'dimensions' in task_param: if len(task_param['dimensions'].split(',')) > 1: raise UnknownDataTypeError('Only one-dimensional arrays are supported.') data_type += 'ARRAY' if data_type in parameter_map: gp_param['dataType'] = parameter_map[data_type].data_type else: # No Mapping exists for this data type! raise UnknownDataTypeError('Unable to map task datatype: ' + data_type + '. A template must be created.') gp_param['name'] = task_param['name'] gp_param['displayName'] = task_param['display_name'] gp_param['direction'] = _DIRECTION_MAP[task_param['direction']] gp_param['paramType'] = 'Required' if task_param['required'] else 'Optional' # ENVI/IDL output type translates to a derived output type in Arc if gp_param['direction'] is 'Output': gp_param['paramType'] = 'Derived' gp_param['multiValue'] = True if 'dimensions' in task_param else False # Substitute values into the template gp_params.append(parameter_map[data_type].get_parameter(task_param).substitute(gp_param)) # Convert the default value if 'default_value' in task_param: gp_param['defaultValue'] = task_param['default_value'] gp_params.append(parameter_map[data_type].default_value().substitute(gp_param)) # Convert any choicelist if 'choice_list' in task_param: gp_param['choiceList'] = task_param['choice_list'] gp_params.append(_CHOICELIST_TEMPLATE.substitute(gp_param)) # Construct the parameter list and indicies for future reference for param_name in parameter_map[data_type].parameter_names(task_param): gp_param_list.append(param_name.substitute(gp_param)) gp_param_idx_list.append(_PARAM_INDEX_TEMPLATE.substitute( {'name': param_name.substitute(gp_param), 'idx': gp_param_idx})) gp_param_idx += 1 # Construct the final parameter string gp_params.append(_PARAM_RETURN_TEMPLATE.substitute({'paramList': convert_list(gp_param_list)})) return ''.join((''.join(gp_params), ''.join(gp_param_idx_list)))
[docs]def create_update_parameter(task_params, parameter_map): """ Builds the code block for the GPTool UpdateParameter method based on the input task_params. :param task_params: A list of task parameters from the task info structure. :return: A string representing the code block to the GPTool UpdateParameter method. """ gp_params = [] for param in task_params: if param['direction'].upper() == 'OUTPUT': continue # Convert DataType data_type = param['type'].upper() if 'dimensions' in param: data_type += 'ARRAY' if data_type in parameter_map: gp_params.append(parameter_map[data_type].update_parameter().substitute(param)) return ''.join(gp_params)
_PRE_EXECUTE_INIT_TEMPLATE = ''' #Get all the user input parameters from the GPTool input_params = {} ''' _PRE_EXECUTE_CLEANUP_TEMPLATE = ''' # Remove any empty values from the input parameters for key, value in list(input_params.items()): if value is None: messages.AddMessage('Removing empty input: ' + key) input_params.pop(key) messages.AddMessage('Collected input: ' + str(input_params)) '''
[docs]def create_pre_execute(task_params, parameter_map): """ Builds the code block for the GPTool Execute method before the job is submitted based on the input task_params. :param task_params: A list of task parameters from the task info structure. :return: A string representing the code block to the GPTool Execute method. """ gp_params = [_PRE_EXECUTE_INIT_TEMPLATE] for task_param in task_params: if task_param['direction'].upper() == 'OUTPUT': continue # Convert DataType data_type = task_param['type'].upper() if 'dimensions' in task_param: data_type += 'ARRAY' if data_type in parameter_map: gp_params.append(parameter_map[data_type].pre_execute().substitute(task_param)) gp_params.append(_PRE_EXECUTE_CLEANUP_TEMPLATE) return ''.join(gp_params)
[docs]def create_post_execute(task_params, parameter_map): """ Builds the code block for the GPTool Execute method after the job is submitted based on the input task_params. :param task_params: A list of task parameters from the task info structure. :return: A string representing the code block to the GPTool Execute method. """ gp_params = [] for task_param in task_params: if task_param['direction'].upper() == 'INPUT': continue # Convert DataType data_type = task_param['type'].upper() if 'dimensions' in task_param: data_type += 'ARRAY' if data_type in parameter_map: gp_params.append(parameter_map[data_type].post_execute().substitute(task_param)) return ''.join(gp_params)