예제 #1
0
    def run_command(self):
        """
        Run the command. Read the feature classes within a file geodatabase. For each desired feature class (can be
        specified by the Subset_Pattern parameter), create a GeoLayer object, and add to the GeoProcessor's geolayer
        list.

        Returns: None.

        Raises:
            RuntimeError if any warnings occurred during run_command method.
        """

        # Obtain the required and optional parameter values
        pv_SpatialDataFolder = self.get_parameter_value("SpatialDataFolder")
        pv_ReadOnlyOneFeatureClass = self.get_parameter_value(
            "ReadOnlyOneFeatureClass")
        pv_Subset_Pattern = self.get_parameter_value("Subset_Pattern")
        pv_GeoLayerID_prefix = self.get_parameter_value("GeoLayerID_prefix")
        pv_GeoLayerID = self.get_parameter_value("GeoLayerID")
        pv_FeatureClass = self.get_parameter_value("FeatureClass")

        # Convert the ReadOnlyOneFeatureClass from a string value to a Boolean value.
        pv_ReadOnlyOneFeatureClass = string_util.str_to_bool(
            pv_ReadOnlyOneFeatureClass)

        # Convert the SpatialDataFolder parameter value relative path to an absolute path
        sd_folder_abs = io_util.verify_path_for_os(
            io_util.to_absolute_path(
                self.command_processor.get_property('WorkingDir'),
                self.command_processor.expand_parameter_value(
                    pv_SpatialDataFolder, self)))

        # Run the initial checks on the parameter values. Only continue if the checks passed.
        if self.__should_read_gdb(sd_folder_abs):

            # If configured to only read one Feature Class into one GeoLayer.
            if pv_ReadOnlyOneFeatureClass:

                # Run the check to see if the GeoLayer should be read.
                if self.__should_read_geolayer(pv_GeoLayerID, True,
                                               pv_FeatureClass, sd_folder_abs):

                    try:

                        # Get the full pathname to the feature class
                        # TODO egiles 2018-01-04 Need to research how to properly document feature class source path
                        spatial_data_file_absolute = os.path.join(
                            sd_folder_abs, str(pv_FeatureClass))

                        # Create a QgsVectorLayer object from the feature class.
                        qgs_vector_layer = qgis_util.read_qgsvectorlayer_from_feature_class(
                            sd_folder_abs, pv_FeatureClass)

                        # Create a GeoLayer and add it to the geoprocessor's GeoLayers list
                        geolayer_obj = GeoLayer(pv_GeoLayerID,
                                                qgs_vector_layer,
                                                spatial_data_file_absolute)
                        self.command_processor.add_geolayer(geolayer_obj)

                    # Raise an exception if an unexpected error occurs during the process
                    except Exception as e:

                        self.warning_count += 1
                        message = "Unexpected error reading feature class ({}) from file geodatabase ({}).".format(
                            pv_FeatureClass, sd_folder_abs)
                        recommendation = "Check the log file for details."
                        self.logger.error(message, exc_info=True)
                        self.command_status.add_to_log(
                            CommandPhaseType.RUN,
                            CommandLogRecord(CommandStatusType.FAILURE,
                                             message, recommendation))

            # If configured to read multiple Feature Classes into multiple GeoLayers.
            else:

                # Get a list of all of the feature classes in the file geodatabase.
                fc_list = self.__return_a_list_of_fc(sd_folder_abs)

                # Filter the fc_list to only include feature classes that meet the Subset Pattern configuration. If
                # the Subset Pattern configuration is None, all feature classes will remain in the fc_list.
                fc_list = string_util.filter_list_of_strings(
                    fc_list, [pv_Subset_Pattern])

                # Iterate over the feature classes in the fc_list.
                for feature_class in fc_list:

                    # Determine the GeoLayerID.
                    if pv_GeoLayerID_prefix:
                        geolayer_id = "{}_{}".format(pv_GeoLayerID_prefix,
                                                     feature_class)
                    else:
                        geolayer_id = feature_class

                    # Run the secondary checks on the parameter values. Only continue if the checks passed.
                    if self.__should_read_geolayer(geolayer_id, False):

                        try:

                            # Get the full pathname to the feature class
                            # TODO egiles 2018-01-04 Need to research how to properly document feature class source path
                            spatial_data_file_absolute = os.path.join(
                                sd_folder_abs, str(feature_class))

                            # Create a QgsVectorLayer object from the feature class.
                            qgs_vector_layer = qgis_util.read_qgsvectorlayer_from_feature_class(
                                sd_folder_abs, feature_class)

                            # Create a GeoLayer and add it to the geoprocessor's GeoLayers list
                            geolayer_obj = GeoLayer(
                                geolayer_id, qgs_vector_layer,
                                spatial_data_file_absolute)
                            self.command_processor.add_geolayer(geolayer_obj)

                        # Raise an exception if an unexpected error occurs during the process
                        except Exception as e:

                            self.warning_count += 1
                            message = "Unexpected error reading feature class ({}) from file geodatabase ({}).".format(
                                feature_class, sd_folder_abs)
                            recommendation = "Check the log file for details."
                            self.logger.error(message, exc_info=True)
                            self.command_status.add_to_log(
                                CommandPhaseType.RUN,
                                CommandLogRecord(CommandStatusType.FAILURE,
                                                 message, recommendation))

        # Determine success of command processing. Raise Runtime Error if any errors occurred
        if self.warning_count > 0:
            message = "There were {} warnings proceeding this command.".format(
                self.warning_count)
            raise RuntimeError(message)

        # Set command status type as SUCCESS if there are no errors.
        else:
            self.command_status.refresh_phase_severity(
                CommandPhaseType.RUN, CommandStatusType.SUCCESS)
    def run_command(self):
        """
        Run the command. Extract the compressed file.

        Returns: None.

        Raises:
            RuntimeError if any warnings occurred during run_command method.
        """

        # Obtain the File and the DeleteFile parameter values.
        pv_File = self.get_parameter_value("File")
        pv_DeleteFile = self.get_parameter_value("DeleteFile",
                                                 default_value="False")

        # Convert the File parameter value relative path to an absolute path. Expand for ${Property} syntax.
        file_abs = io_util.verify_path_for_os(
            io_util.to_absolute_path(
                self.command_processor.get_property('WorkingDir'),
                self.command_processor.expand_parameter_value(pv_File, self)))

        # Get the FileType parameter value.
        default_file_ext = self.__get_default_file_type(file_abs)
        pv_FileType = self.get_parameter_value("FileType",
                                               default_value=default_file_ext)

        # Get the OutputFolder parameter value.
        parent_folder = io_util.get_path(file_abs)
        pv_OutputFolder = self.get_parameter_value("OutputFolder",
                                                   default_value=parent_folder)

        # Convert the OutputFolder parameter value relative path to an absolute path. Expand for ${Property} syntax.
        output_folder_abs = io_util.verify_path_for_os(
            io_util.to_absolute_path(
                self.command_processor.get_property('WorkingDir'),
                self.command_processor.expand_parameter_value(
                    pv_OutputFolder, self)))

        # Run the checks on the parameter values. Only continue if the checks passed.
        if self.__should_extract_file(file_abs, output_folder_abs,
                                      pv_FileType):

            try:

                # If the file is a .zip file, extract the zip file.
                if pv_FileType.upper() == "ZIP":

                    zip_util.unzip_all_files(file_abs, output_folder_abs)

                # If the file is a .tar file, extract the tar file.
                elif pv_FileType.upper() == "TAR":

                    zip_util.untar_all_files(file_abs, output_folder_abs)

                # If configured, remove the input compressed file.
                if string_util.str_to_bool(pv_DeleteFile):
                    os.remove(file_abs)

            # Raise an exception if an unexpected error occurs during the process
            except Exception as e:
                self.warning_count += 1
                message = "Unexpected error extracting the {} file ({}).".format(
                    pv_FileType, pv_File)
                recommendation = "Check the log file for details."
                self.logger.error(message, exc_info=True)
                self.command_status.add_to_log(
                    CommandPhaseType.RUN,
                    CommandLogRecord(CommandStatusType.FAILURE, message,
                                     recommendation))

        # Determine success of command processing. Raise Runtime Error if any errors occurred
        if self.warning_count > 0:
            message = "There were {} warnings proceeding this command.".format(
                self.warning_count)
            raise RuntimeError(message)

        # Set command status type as SUCCESS if there are no errors.
        else:
            self.command_status.refresh_phase_severity(
                CommandPhaseType.RUN, CommandStatusType.SUCCESS)
예제 #3
0
    def run_command(self):
        """
        Run the command. Write the Table to a delimited file.

        Returns: None.

        Raises:
            RuntimeError if any warnings occurred during run_command method.
        """

        # Obtain the parameter values.
        pv_TableID = self.get_parameter_value("TableID")
        pv_OutputFile = self.get_parameter_value("OutputFile")
        pv_Delimiter = self.get_parameter_value("Delimiter", default_value=",")
        pv_IncludeColumns = self.get_parameter_value("IncludeColumns",
                                                     default_value="*")
        pv_ExcludeColumns = self.get_parameter_value("ExcludeColumns",
                                                     default_value="")
        pv_WriteHeaderRow = self.get_parameter_value("WriteHeaderRow",
                                                     default_value="True")
        pv_WriteIndexColumn = self.get_parameter_value("WriteIndexColumn",
                                                       default_value="False")
        pv_SortColumns = self.get_parameter_value("SortColumns")
        pv_SortOrder = self.get_parameter_value("SortOrder", default_value="")
        pv_ArrayFormat = self.get_parameter_value(
            "ArrayFormat", default_value="SquareBrackets")
        pv_NullValueFormat = self.get_parameter_value("NullValueFormat",
                                                      default_value="Null")

        # Convert the IncludeColumns, ExcludeColumns, and SortColumns parameter values to lists.
        cols_to_include = string_util.delimited_string_to_list(
            pv_IncludeColumns)
        cols_to_exclude = string_util.delimited_string_to_list(
            pv_ExcludeColumns)
        sort_cols_list = string_util.delimited_string_to_list(pv_SortColumns)

        # Convert the SortOrder to a dictionary.
        sort_dictionary = string_util.delimited_string_to_dictionary_one_value(
            pv_SortOrder,
            entry_delimiter=",",
            key_value_delimiter=":",
            trim=True)

        # Convert the OutputFile parameter value relative path to an absolute path and expand for ${Property} syntax
        output_file_absolute = io_util.verify_path_for_os(
            io_util.to_absolute_path(
                self.command_processor.get_property('WorkingDir'),
                self.command_processor.expand_parameter_value(
                    pv_OutputFile, self)))

        # Covert the Boolean parameters from string to Boolean values.
        pv_WriteHeaderRow = string_util.str_to_bool(pv_WriteHeaderRow)
        pv_WriteIndexColumn = string_util.str_to_bool(pv_WriteIndexColumn)

        # Run the checks on the parameter values. Only continue if the checks passed.
        if self.__should_write_table(pv_TableID, output_file_absolute,
                                     pv_Delimiter, sort_cols_list):

            try:

                # Get the Table object
                table = self.command_processor.get_table(pv_TableID)

                # Determine if square brackets should be used depending on the user input of the ArrayFormat parameter.
                use_sq_brackets = False
                if pv_ArrayFormat.upper() == "SQUAREBRACKETS":
                    use_sq_brackets = True

                # Determine if the null values should be used depending on the user input of the NullValueFormat
                # parameter.
                use_null_value = False
                if pv_NullValueFormat.upper() == "NULL":
                    use_null_value = True

                # Write the table to the delimited file.
                self.__write_table_to_delimited_file(
                    output_file_absolute, table, pv_Delimiter, cols_to_include,
                    cols_to_exclude, pv_WriteHeaderRow, pv_WriteIndexColumn,
                    sort_cols_list, sort_dictionary, use_sq_brackets,
                    use_null_value)

            # Raise an exception if an unexpected error occurs during the process
            except Exception as e:
                self.warning_count += 1
                message = "Unexpected error writing Table {} to delimited file {}.".format(
                    pv_TableID, pv_OutputFile)
                recommendation = "Check the log file for details."
                self.logger.error(message, exc_info=True)
                self.command_status.add_to_log(
                    CommandPhaseType.RUN,
                    CommandLogRecord(CommandStatusType.FAILURE, message,
                                     recommendation))

        # Determine success of command processing. Raise Runtime Error if any errors occurred
        if self.warning_count > 0:
            message = "There were {} warnings proceeding this command.".format(
                self.warning_count)
            raise RuntimeError(message)

        # Set command status type as SUCCESS if there are no errors.
        else:
            self.command_status.refresh_phase_severity(
                CommandPhaseType.RUN, CommandStatusType.SUCCESS)
예제 #4
0
    def check_command_parameters(self, command_parameters):
        """
        Check the command parameters for validity.

        Args:
            command_parameters: the dictionary of command parameters to check (key:string_value)

        Returns: None.

        Raises:
            ValueError if any parameters are invalid or do not have a valid value.
            The command status messages for initialization are populated with validation messages.
        """
        warning = ""

        # Check that parameter SpatialDataFolder is a non-empty, non-None string.
        # - existence of the folder will also be checked in run_command().
        pv_SpatialDataFolder = self.get_parameter_value(
            parameter_name='SpatialDataFolder',
            command_parameters=command_parameters)

        if not validators.validate_string(pv_SpatialDataFolder, False, False):
            message = "SpatialDataFolder parameter has no value."
            recommendation = "Specify text for the SpatialDataFolder parameter to indicate the file geodatabase."
            warning += "\n" + message
            self.command_status.add_to_log(
                CommandPhaseType.INITIALIZATION,
                CommandLogRecord(CommandStatusType.FAILURE, message,
                                 recommendation))

        # Check that optional parameter IfGeoLayerIDExists is either `Replace`, `ReplaceAndWarn`, `Warn`, `Fail`, None.
        pv_IfGeoLayerIDExists = self.get_parameter_value(
            parameter_name="IfGeoLayerIDExists",
            command_parameters=command_parameters)
        acceptable_values = ["Replace", "ReplaceAndWarn", "Warn", "Fail"]
        if not validators.validate_string_in_list(pv_IfGeoLayerIDExists,
                                                  acceptable_values,
                                                  none_allowed=True,
                                                  empty_string_allowed=True,
                                                  ignore_case=True):
            message = "IfGeoLayerIDExists parameter value ({}) is not recognized.".format(
                pv_IfGeoLayerIDExists)
            recommendation = "Specify one of the acceptable values ({}) for the IfGeoLayerIDExists parameter.".format(
                acceptable_values)
            warning += "\n" + message
            self.command_status.add_to_log(
                CommandPhaseType.INITIALIZATION,
                CommandLogRecord(CommandStatusType.FAILURE, message,
                                 recommendation))

        # Check that the optional parameter ReadOnlyOneFeatureClass is a valid Boolean.
        pv_ReadOnlyOneFeatureClass = self.get_parameter_value(
            parameter_name="ReadOnlyOneFeatureClass",
            command_parameters=command_parameters)
        if not validators.validate_bool(pv_ReadOnlyOneFeatureClass, True,
                                        False):
            message = "ReadOnlyOneFeatureClass is not a valid boolean value."
            recommendation = "Specify a valid boolean value for the ReadOnlyOneFeatureClass parameter."
            warning += "\n" + message
            self.command_status.add_to_log(
                CommandPhaseType.INITIALIZATION,
                CommandLogRecord(CommandStatusType.FAILURE, message,
                                 recommendation))

        # Continue with checks if the ReadOnlyOneFeatureClass is a valid TRUE Boolean.
        elif string_util.str_to_bool(pv_ReadOnlyOneFeatureClass):

            # Check that parameter GeoLayerID is a non-empty, non-None string.
            pv_GeoLayerID = self.get_parameter_value(
                parameter_name='GeoLayerID',
                command_parameters=command_parameters)

            if not validators.validate_string(pv_GeoLayerID, False, False):
                message = "GeoLayerID parameter has no value."
                recommendation = "Specify the GeoLayerID parameter."
                warning += "\n" + message
                self.command_status.add_to_log(
                    CommandPhaseType.INITIALIZATION,
                    CommandLogRecord(CommandStatusType.FAILURE, message,
                                     recommendation))

        # Check for unrecognized parameters.
        # This returns a message that can be appended to the warning, which if non-empty triggers an exception below.
        warning = command_util.validate_command_parameter_names(self, warning)

        # If any warnings were generated, throw an exception.
        if len(warning) > 0:
            self.logger.warning(warning)
            raise ValueError(warning)

        else:
            # Refresh the phase severity
            self.command_status.refresh_phase_severity(
                CommandPhaseType.INITIALIZATION, CommandStatusType.SUCCESS)
예제 #5
0
    def run_command(self):
        """
        Run the command.  Initializes the If.

        Returns:
            None.
        """
        logger = logging.getLogger(__name__)
        debug = True  # Use for troubleshooting
        warning_count = 0  # General count for issues

        pv_Name = self.get_parameter_value("Name")
        pv_Condition = self.get_parameter_value("Condition")
        condition_upper = None
        if pv_Condition is not None:
            condition_upper = pv_Condition.upper()
        pv_CompareAsStrings = self.get_parameter_value("CompareAsStrings")
        compare_as_strings = False
        if pv_CompareAsStrings is not None and pv_CompareAsStrings.upper == "TRUE":
            compare_as_strings = True
        # TODO smalers 2018-02-18 need to add other special conditions such as empty properties, GeoLayer exists, etc.
        # - see TSTool code

        try:
            condition_eval = False
            self.__condition_eval = condition_eval
            if pv_Condition is not None and pv_Condition != "":
                # Condition is specified, rather than special check.
                # First determine the condition operator.
                # TODO SAM 2013-12-07 Figure out if there is a more elegant way to do this
                #  Currently only Value1 Operator Value2 is allowed.  Brute force split by finding the operator
                logger.info('Evaluating Condition="' + pv_Condition + '"')
                pos1 = -1
                pos2 = -1
                value1 = ""
                value2 = ""
                op = "??"
                if pv_Condition.find("<=") > 0:
                    pos = pv_Condition.find("<=")
                    op = "<="
                    pos1 = pos
                    pos2 = pos + 2
                elif pv_Condition.find("<") > 0:
                    pos = pv_Condition.find("<")
                    op = "<"
                    pos1 = pos
                    pos2 = pos + 1
                elif pv_Condition.find(">=") > 0:
                    pos = pv_Condition.find(">=")
                    op = ">="
                    pos1 = pos
                    pos2 = pos + 2
                elif pv_Condition.find(">") > 0:
                    pos = pv_Condition.find(">")
                    op = ">"
                    pos1 = pos
                    pos2 = pos + 1
                elif pv_Condition.find("==") > 0:
                    pos = pv_Condition.find("==")
                    op = "=="
                    pos1 = pos
                    pos2 = pos + 2
                elif pv_Condition.find("!=") > 0:
                    pos = pv_Condition.find("!=")
                    op = "!="
                    pos1 = pos
                    pos2 = pos + 2
                elif condition_upper.find("!CONTAINS") > 0:
                    # Put this before the next "CONTAINS" operator
                    pos = condition_upper.find("!CONTAINS")
                    op = "!CONTAINS"
                    pos1 = pos
                    pos2 = pos + 9
                    compare_as_strings = True  # "!contains" is only used on strings
                elif condition_upper.find("CONTAINS") > 0:
                    pos = condition_upper.find("CONTAINS")
                    op = "CONTAINS"
                    pos1 = pos
                    pos2 = pos + 8
                    compare_as_strings = True  # "contains" is only used on strings
                elif pv_Condition.find("=") > 0:
                    message = "Bad use of = in condition."
                    recommendation = "Use == to check for equality."
                    logger.warning(message)
                    self.command_status.add_to_log(
                        CommandPhaseType.RUN,
                        CommandLogRecord(CommandStatusType.FAILURE, message,
                                         recommendation))
                else:
                    message = 'Unknown condition operator for "' + pv_Condition + '"'
                    recommendation =\
                        "Make sure condition operator is supported - refer to command editor and documentation."
                    logger.warning(message)
                    self.command_status.add_to_log(
                        CommandPhaseType.RUN,
                        CommandLogRecord(CommandStatusType.FAILURE, message,
                                         recommendation))

                logger.info('operator="' + op + '" pos1=' + str(pos1) +
                            " pos2=" + str(pos2))
                # Now evaluate the left and right sides of the condition
                arg1 = pv_Condition[0:pos1].strip()
                if debug:
                    logger.info(
                        'Left side of condition before property expansion check: "'
                        + str(arg1) + '"')
                if arg1.find("${") >= 0:
                    value1 = self.command_processor.expand_parameter_value(
                        arg1, self)
                    if debug:
                        logger.info(
                            "Left side of condition after property expansion: "
                            + value1)
                else:
                    value1 = arg1
                    if debug:
                        logger.info("Left side (no expansion needed): " +
                                    value1)
                arg2 = pv_Condition[pos2:].strip()
                if debug:
                    logger.info(
                        'Right side of condition before property expansion check: "'
                        + str(arg2) + '"')
                if arg2.find("${") >= 0:
                    value2 = self.command_processor.expand_parameter_value(
                        arg2, self)
                    if debug:
                        logger.info("Right side after property expansion: " +
                                    value2)
                else:
                    value2 = arg2
                    if debug:
                        logger.info("Right side (no expansion needed): " +
                                    value2)
                # If the arguments are quoted, then all of the following will be false
                is_value1_int = string_util.is_int(value1)
                is_value2_int = string_util.is_int(value2)
                is_value1_float = string_util.is_float(value1)
                is_value2_float = string_util.is_float(value2)
                is_value1_bool = string_util.is_bool(value1)
                is_value2_bool = string_util.is_bool(value2)
                # Strip surrounding double quotes for comparisons below - do after above checks for type
                value1 = value1.replace('"', "")
                value2 = value2.replace('"', "")
                if not compare_as_strings and is_value1_int and is_value2_int:
                    # Do an integer comparison
                    ivalue1 = int(value1)
                    ivalue2 = int(value2)
                    if op == "<=":
                        if ivalue1 <= ivalue2:
                            condition_eval = True
                    elif op == "<":
                        if ivalue1 < ivalue2:
                            condition_eval = True
                    elif op == ">=":
                        if ivalue1 >= ivalue2:
                            condition_eval = True
                    elif op == ">":
                        if ivalue1 > ivalue2:
                            condition_eval = True
                    elif op == "==":
                        if ivalue1 == ivalue2:
                            condition_eval = True
                    elif op == "!=":
                        if ivalue1 != ivalue2:
                            condition_eval = True
                elif not compare_as_strings and is_value1_float and is_value2_float:
                    # Compare floats
                    fvalue1 = float(value1)
                    fvalue2 = float(value2)
                    if op == "<=":
                        if fvalue1 <= fvalue2:
                            condition_eval = True
                    elif op == "<":
                        if fvalue1 < fvalue2:
                            condition_eval = True
                    elif op == ">=":
                        if fvalue1 >= fvalue2:
                            condition_eval = True
                    elif op == ">":
                        if fvalue1 > fvalue2:
                            condition_eval = True
                    elif op == "==":
                        if fvalue1 == fvalue2:
                            condition_eval = True
                    elif op == "!=":
                        if fvalue1 != fvalue2:
                            condition_eval = True
                elif not compare_as_strings and is_value1_bool and is_value2_bool:
                    # Do a boolean comparison
                    # - bool("") is False, every other string is True!
                    bvalue1 = string_util.str_to_bool(value1)
                    bvalue2 = string_util.str_to_bool(value2)
                    if debug:
                        logger.info('Evaluating boolean condition "' +
                                    str(bvalue1) + " " + op + " " +
                                    str(bvalue2))
                    if op == "<=":
                        if not bvalue1:
                            # false <= false or true (does not matter what right side is)
                            condition_eval = True
                    elif op == "<":
                        if not bvalue1 and bvalue2:
                            # false < true
                            condition_eval = True
                    elif op == ">=":
                        if bvalue1:
                            # true >= false or true (does not matter what right side is)
                            condition_eval = True
                    elif op == ">":
                        if bvalue1 and not bvalue2:
                            # true > false
                            condition_eval = True
                    elif op == "==":
                        if bvalue1 == bvalue2:
                            condition_eval = True
                    elif op == "!=":
                        if bvalue1 != bvalue2:
                            condition_eval = True
                elif compare_as_strings or\
                    (not is_value1_int and not is_value2_int and
                     not is_value1_float and not is_value2_float and not is_value1_bool and not is_value2_bool):
                    # Always compare the string values or the input is not other types so assume strings
                    if op == "CONTAINS":
                        if value1.find(value2) >= 0:
                            condition_eval = True
                    elif op == "!CONTAINS":
                        if value1.find(value2) < 0:
                            condition_eval = True
                    else:
                        # Do a comparison of the strings to figure out lexicographically order
                        if value1 < value2:
                            comp = -1
                        elif value1 == value2:
                            comp = 0
                        else:
                            comp = 1
                        if op == "<=":
                            if comp <= 0:
                                condition_eval = True
                        elif op == "<":
                            if comp < 0:
                                condition_eval = True
                        elif op == ">=":
                            if comp >= 0:
                                condition_eval = True
                        elif op == ">":
                            if comp > 0:
                                condition_eval = True
                        elif op == "==":
                            if comp == 0:
                                condition_eval = True
                        elif op == "!=":
                            if comp != 0:
                                condition_eval = True
                else:
                    message = 'Left and right have different type - cannot evaluate condition "' + pv_Condition + '"'
                    recommendation = "Make sure data types on each side of operator are the same - " + \
                        "refer to command editor and documentation."
                    logger.warning(message)
                    self.command_status.add_to_log(
                        CommandPhaseType.RUN,
                        CommandLogRecord(CommandStatusType.FAILURE, message,
                                         recommendation))

                if debug:
                    logger.info("Condition evaluated to: " +
                                str(condition_eval))

                # For now leave the following two messages in to reinforce to user the evaluation
                # - may only output when in debug mode in the future
                if pv_Condition.find("${") >= 0:
                    # Show the original
                    message = pv_Condition + " (showing ${Property} notation) evaluates to " + str(
                        condition_eval)
                    recommendation = "Informational message."
                    self.command_status.add_to_log(
                        CommandPhaseType.RUN,
                        CommandLogRecord(CommandStatusType.SUCCESS, message,
                                         recommendation))

                # Always also show the expanded
                message = str(value1) + " " + op + " " + str(
                    value2) + " evaluates to " + str(condition_eval)
                recommendation = "Informational message."
                self.command_status.add_to_log(
                    CommandPhaseType.RUN,
                    CommandLogRecord(CommandStatusType.SUCCESS, message,
                                     recommendation))
                self.__condition_eval = condition_eval

        except Exception as e:
            warning_count += 1
            traceback.print_exc(
                file=sys.stdout)  # Formatting of error seems to have issue
            message = 'Unexpected error in If, Name="' + pv_Name + '"'
            logger.error(message, e, exc_info=True)
            self.command_status.add_to_log(
                CommandPhaseType.RUN,
                CommandLogRecord(CommandStatusType.FAILURE, message,
                                 "Check the log file for details."))

        if warning_count > 0:
            message = "There were " + str(
                warning_count) + " warnings processing the command."
            raise RuntimeError(message)

        self.command_status.refresh_phase_severity(CommandPhaseType.RUN,
                                                   CommandStatusType.SUCCESS)
예제 #6
0
    def run_command(self):

        # Obtain the parameter values.
        pv_Folder = self.get_parameter_value("Folder")
        pv_URL = self.get_parameter_value("URL")
        pv_ListFiles = self.get_parameter_value("ListFiles",
                                                default_value="True")
        pv_ListFolders = self.get_parameter_value("ListFolders",
                                                  default_value="True")
        pv_ListProperty = self.get_parameter_value("ListProperty")
        pv_IncludePatterns = self.get_parameter_value("IncludePatterns",
                                                      default_value="*")
        pv_ExcludePatterns = self.get_parameter_value("ExcludePatterns",
                                                      default_value="''")

        # Convert the IncludeAttributes and ExcludeAttributes to lists.
        to_include = string_util.delimited_string_to_list(pv_IncludePatterns)
        to_exclude = string_util.delimited_string_to_list(pv_ExcludePatterns)

        # Convert the pv_ListFiles and pv_ListFolders to Boolean values.
        list_files_bool = string_util.str_to_bool(pv_ListFiles)
        list_dirs_bool = string_util.str_to_bool(pv_ListFolders)

        # Set the absolute paths for the Folder and the URL to None until proven to exist within the command process.
        folder_abs = None
        url_abs = None

        # If the input is a local folder.
        if pv_Folder:

            # Convert the Folder parameter value relative path to an absolute path and expand for ${Property} syntax.
            folder_abs = io_util.verify_path_for_os(
                io_util.to_absolute_path(
                    self.command_processor.get_property('WorkingDir'),
                    self.command_processor.expand_parameter_value(
                        pv_Folder, self)))

        # If the input is a url.
        if pv_URL:

            # Convert the URL parameter to expand for ${Property} syntax.
            url_abs = self.command_processor.expand_parameter_value(
                pv_URL, self)

        # Run the checks on the parameter values. Only continue if the checks passed.
        if self.__should_list_files(folder_abs, url_abs, list_files_bool,
                                    list_dirs_bool, pv_ListProperty):

            try:
                # If the input is a local folder.
                if pv_Folder:

                    # Get a list of the files in the folder.
                    files = [
                        f for f in os.listdir(folder_abs)
                        if os.path.isfile(os.path.join(folder_abs, f))
                    ]

                    # Get a list of directories in the folder.
                    dirs = [
                        d for d in os.listdir(folder_abs)
                        if os.path.isdir(os.path.join(folder_abs, d))
                    ]

                    # If configured to list files and folders, continue.
                    if list_files_bool and list_dirs_bool:

                        # Filter the list of files and folders with regards to the IncludePatterns and ExcludePatterns.
                        output_filtered = string_util.filter_list_of_strings(
                            files + dirs, to_include, to_exclude)

                    # If configured to list files, continue.
                    elif list_files_bool:

                        # Filter the list of files with regards to the IIncludePatterns and ExcludePatterns.
                        output_filtered = string_util.filter_list_of_strings(
                            files, to_include, to_exclude)

                    # If configured to list folders, continue.
                    elif list_dirs_bool:

                        # Filter the list of folders with regards to the IIncludePatterns and ExcludePatterns.
                        output_filtered = string_util.filter_list_of_strings(
                            dirs, to_include, to_exclude)

                    else:
                        output_filtered = []

                    # Add the filtered list to the desired ListProperty. Sort the list alphabetically
                    self.command_processor.set_property(
                        pv_ListProperty, sorted(output_filtered,
                                                key=str.lower))

                # If the input is a url.
                if pv_URL:

                    # If configured to list files and folders, continue.
                    if list_files_bool and list_dirs_bool:
                        output_filtered = self.scrape_html(
                            url_abs, True, True, to_include, to_exclude)

                    # If configured to list files, continue.
                    elif list_files_bool:
                        output_filtered = self.scrape_html(
                            url_abs, True, False, to_include, to_exclude)

                    # If configured to list folders, continue.
                    elif list_dirs_bool:
                        output_filtered = self.scrape_html(
                            url_abs, False, True, to_include, to_exclude)

                    else:
                        output_filtered = None

                    # Add the filtered list to the desired ListProperty.
                    self.command_processor.set_property(
                        pv_ListProperty, sorted(output_filtered,
                                                key=str.lower))

            # Raise an exception if an unexpected error occurs during the process
            except Exception as e:
                self.warning_count += 1
                message = "Unexpected error running ListFiles command."
                recommendation = "Check the log file for details."
                self.logger.error(message, exc_info=True)
                self.command_status.add_to_log(
                    CommandPhaseType.RUN,
                    CommandLogRecord(CommandStatusType.FAILURE, message,
                                     recommendation))

        # Determine success of command processing. Raise Runtime Error if any errors occurred
        if self.warning_count > 0:
            message = "There were {} warnings proceeding this command.".format(
                self.warning_count)
            raise RuntimeError(message)

        # Set command status type as SUCCESS if there are no errors.
        else:
            self.command_status.refresh_phase_severity(
                CommandPhaseType.RUN, CommandStatusType.SUCCESS)
예제 #7
0
    def run_command(self):
        """
        Run the command.
        Remove the specified file from the operating system.

        Returns:
            Nothing.

        Raises:
                RuntimeError: if a runtime input error occurs.
        """
        warning_count = 0
        logger = logging.getLogger(__name__)

        # Get data for the command
        pv_SourceFile = self.get_parameter_value('SourceFile')
        pv_IfSourceFileNotFound = self.get_parameter_value(
            'IfSourceFileNotFound')
        if pv_IfSourceFileNotFound is None or pv_IfSourceFileNotFound == "":
            pv_IfSourceFileNotFound = 'Warn'  # Default
        pv_RemoveIfFolder = self.get_parameter_value('RemoveIfFolder',
                                                     default_value="False")
        pv_RemoveIfFolder = string_util.str_to_bool(pv_RemoveIfFolder)

        # Runtime checks on input

        pv_SourceFile_absolute = io_util.verify_path_for_os(
            io_util.to_absolute_path(
                self.command_processor.get_property('WorkingDir'),
                self.command_processor.expand_parameter_value(
                    pv_SourceFile, self)))

        if warning_count > 0:
            message = "There were " + str(
                warning_count) + " warnings about command parameters."
            logger.warning(message)
            raise ValueError(message)

        # Remove the file

        try:
            input_count = 1
            if not os.path.exists(pv_SourceFile_absolute):
                message = 'The source file does not exist: "' + pv_SourceFile_absolute + '"'
                if pv_IfSourceFileNotFound == 'Warn':
                    warning_count += 1
                    self.command_status.add_to_log(
                        CommandPhaseType.RUN,
                        CommandLogRecord(
                            CommandStatusType.WARNING, message,
                            "Verify that the source exists at the time the command is run."
                        ))
                    logger.warning(message)
                elif pv_IfSourceFileNotFound == 'Fail':
                    warning_count += 1
                    self.command_status.add_to_log(
                        CommandPhaseType.RUN,
                        CommandLogRecord(
                            CommandStatusType.FAILURE, message,
                            "Verify that the source exists at the time the command is run."
                        ))
                    logger.warning(message)
                input_count -= 1

            if input_count == 1:
                try:
                    logger.info('Removing file "' + pv_SourceFile_absolute +
                                '"')
                    os.remove(pv_SourceFile_absolute)
                except:
                    if pv_RemoveIfFolder:
                        shutil.rmtree(pv_SourceFile_absolute)

        except Exception as e:
            warning_count += 1
            message = 'Unexpected error removing file "' + pv_SourceFile_absolute + '"'
            traceback.print_exc(file=sys.stdout)
            logger.exception(message, e)
            self.command_status.add_to_log(
                CommandPhaseType.RUN,
                CommandLogRecord(CommandStatusType.FAILURE, message,
                                 "See the log file for details."))

        if warning_count > 0:
            message = "There were " + str(
                warning_count) + " warnings processing the command."
            raise RuntimeError(message)

        self.command_status.refresh_phase_severity(CommandPhaseType.RUN,
                                                   CommandStatusType.SUCCESS)
    def run_command(self):
        """
        Run the command.  Set a property on the GeoProcessor.

        Returns:
            Nothing.

        Raises:
            RuntimeError if there is any exception running the command.

        """
        warning_count = 0
        logger = logging.getLogger(__name__)

        pv_PropertyName = self.get_parameter_value('PropertyName')
        pv_PropertyType = self.get_parameter_value('PropertyType')
        pv_PropertyValue = self.get_parameter_value('PropertyValue')
        pv_PropertyValues = self.get_parameter_value('PropertyValues')
        # Expand the property value string before converting to the requested type
        pv_PropertyValue_expanded = self.command_processor.expand_parameter_value(
            pv_PropertyValue)
        pv_PropertyValues_expanded = self.command_processor.expand_parameter_value(
            pv_PropertyValues)
        do_list = False  # Single property is the default
        if pv_PropertyValues is not None and pv_PropertyValues != "":
            # Doing a list
            do_list = True

        try:
            parameter_value_as_list = []
            parameter_value_to_parse = ""
            if do_list:
                parameter_value_to_parse = pv_PropertyValues_expanded
            else:
                # Single property - add to a list as if a single-value list
                parameter_value_to_parse = pv_PropertyValue_expanded
            # logger.info('Parsing parameter "' + str(parameter_value_to_parse) + "'")
            # Parse the list into a string list
            # - Remove leading [ and trailing ] so only have simple string list
            parameter_value_to_parse = parameter_value_to_parse.strip(
            )  # First strip whitespace
            if parameter_value_to_parse.startswith("["):
                parameter_value_to_parse = parameter_value_to_parse[1:]
            if parameter_value_to_parse.endswith("]"):
                parameter_value_to_parse = parameter_value_to_parse[
                    0:len(parameter_value_to_parse) - 1]
            parameter_value_as_string_list = string_util.delimited_string_to_list(
                parameter_value_to_parse, trim=True)
            # logger.info('Parsed parameter "' + str(parameter_value_as_string_list) + "'")
            # Loop through the list
            parameter_value2 = None
            for parameter_value in parameter_value_as_string_list:
                # Convert the property value string to the requested type
                parameter_value2 = None
                if pv_PropertyType == 'bool':
                    # Use the following because conversion of strings to booleans is tricky, too many unexpected True
                    parameter_value2 = string_util.str_to_bool(parameter_value)
                elif pv_PropertyType == 'float':
                    parameter_value2 = float(parameter_value)
                elif pv_PropertyType == 'int':
                    parameter_value2 = int(parameter_value)
                elif pv_PropertyType == 'str':
                    parameter_value2 = str(parameter_value)
                # Now set the object as a property, will be the requested type
                if do_list:
                    # The property is a list
                    # - for now avoid adding None - later For command should process only valid values
                    if parameter_value2 is not None:
                        parameter_value_as_list.append(parameter_value2)
            if do_list:
                # Doing a list so set the property value to the list
                # - list could be empty - is this an issue?
                self.command_processor.set_property(pv_PropertyName,
                                                    parameter_value_as_list)
                # logger.info('Setting parameter "' + str(pv_PropertyName) + '"="' + str(parameter_value_as_list) + '"')
            else:
                # The property value is a single object and will have been processed in the loop's only iteration
                if parameter_value2 is not None:
                    self.command_processor.set_property(
                        pv_PropertyName, parameter_value2)
                    # logger.info('Setting parameter "' + str(pv_PropertyName) + '"="' + str(parameter_value2) + '"')
        except Exception as e:
            warning_count += 1
            message = 'Unexpected error setting property "' + str(
                pv_PropertyName) + '"'
            logger.error(message, e, exc_info=True)
            self.command_status.add_to_log(
                CommandPhaseType.RUN,
                CommandLogRecord(CommandStatusType.FAILURE, message,
                                 "Check the log file for details."))

        if warning_count > 0:
            message = "There were " + str(
                warning_count) + " warnings processing the command."
            raise RuntimeError(message)

        self.command_status.refresh_phase_severity(CommandPhaseType.RUN,
                                                   CommandStatusType.SUCCESS)
예제 #9
0
    def run_command(self):
        """
        Run the command. Write the Table to an excel file.

        Returns: None.

        Raises:
            RuntimeError if any warnings occurred during run_command method.
        """

        # Obtain the parameter values except for the OutputCRS
        pv_TableID = self.get_parameter_value("TableID")
        pv_OutputFile = self.get_parameter_value("OutputFile")
        pv_OutputWorksheet = self.get_parameter_value("OutputWorksheet")
        pv_ColumnsToInclude = self.get_parameter_value("ColumnsToInclude",
                                                       default_value="*")
        pv_ColumnsToExclude = self.get_parameter_value("ColumnsToExclude",
                                                       default_value="")
        pv_WriteIndexColumn = self.get_parameter_value("WriteIndexColumn",
                                                       default_value="True")

        # Convert the Boolean parameters from string to valid Boolean values.
        pv_WriteIndexColumn = string_util.str_to_bool(pv_WriteIndexColumn)

        # Convert the ColumnsToInclude and ColumnsToExclude parameter values to lists.
        cols_to_include = string_util.delimited_string_to_list(
            pv_ColumnsToInclude)
        cols_to_exclude = string_util.delimited_string_to_list(
            pv_ColumnsToExclude)

        # Convert the OutputFile parameter value relative path to an absolute path and expand for ${Property} syntax
        output_file_absolute = io_util.verify_path_for_os(
            io_util.to_absolute_path(
                self.command_processor.get_property('WorkingDir'),
                self.command_processor.expand_parameter_value(
                    pv_OutputFile, self)))

        # Run the checks on the parameter values. Only continue if the checks passed.
        if self.__should_write_table(pv_TableID, output_file_absolute):

            try:

                # Get the Table object
                table = self.command_processor.get_table(pv_TableID)

                # Get a list of all the available column names in the Table.
                all_cols_names = list(table.df)

                # Sort the list to create a second list that only includes the attributes that should be removed.
                cols_to_keep = string_util.filter_list_of_strings(
                    list(table.df),
                    cols_to_include,
                    cols_to_exclude,
                    return_inclusions=True)

                # For the columns configured to be written, order them in the same order that they were in with the
                # original table. This step ensures that the output table product has the columns in the same order as
                # the user would expect.
                sorted_cols_to_keep = []
                for col in all_cols_names:
                    if col in cols_to_keep:
                        sorted_cols_to_keep.append(col)

                # Write the tables to an Excel file.
                pandas_util.write_df_to_excel(table.df, output_file_absolute,
                                              pv_OutputWorksheet,
                                              sorted_cols_to_keep,
                                              pv_WriteIndexColumn)

                # Add the output file to the GeoProcessor's list of output files.
                self.command_processor.add_output_file(output_file_absolute)

            # Raise an exception if an unexpected error occurs during the process
            except Exception as e:
                self.warning_count += 1
                message = "Unexpected error writing Table {} to Excel workbook file {}.".format(
                    pv_TableID, pv_OutputFile)
                recommendation = "Check the log file for details."
                self.logger.error(message, exc_info=True)
                self.command_status.add_to_log(
                    CommandPhaseType.RUN,
                    CommandLogRecord(CommandStatusType.FAILURE, message,
                                     recommendation))

        # Determine success of command processing. Raise Runtime Error if any errors occurred
        if self.warning_count > 0:
            message = "There were {} warnings proceeding this command.".format(
                self.warning_count)
            raise RuntimeError(message)

        # Set command status type as SUCCESS if there are no errors.
        else:
            self.command_status.refresh_phase_severity(
                CommandPhaseType.RUN, CommandStatusType.SUCCESS)