Пример #1
0
def split_gdbpath(path: str, remove_qualifier: bool = True) -> tuple:
    """
    Splits the Esri Geodatabase *path* into a ``tuple`` of *(workspace, feature_dataset, feature_class/table)*.
    If any of the output tuple parts is not present, these will be set to an empty string.
    Note that if the path refers to a table or feature class that is not stored in a feature dataset,
    the *feature_dataset* part in the output tuple will be an empty string and the last part will contain the table
    or feature class name.

    Examples:

        >>> split_gdbpath('C:/test.gdb/table')
        ('C:\\test.gdb', '', 'table')
        >>> split_gdbpath('C:/test.sde/qualifier.featureclass', False)
        ('C:\\test.sde', '', 'qualifier.featureclass')
        >>> split_gdbpath('C:/test.sde/qualifier.fds/qualifier.fc')
        ('C:\\test.sde', 'fds', 'fc')

    :param path:                The full path to the Geodatabase feature class or table.
    :param remove_qualifier:    If ``True``, the split parts are "unqualified". If any DB qualifiers exist in the path,
                                they will be removed. This is the default behaviour.
                                Set this parameter to ``False`` if qualifiers must be persisted.
    :raises ValueError:         If the given path does not seem to be a Geodatabase path or
                                there are more than 2 levels in the Geodatabase.
    """
    _vld.pass_if(is_gdbpath(path), ValueError,
                 f'{path} does not seem to be a valid Esri Geodatabase path')
    path = normalize(path, False)
    path_parts = path.split('\\')
    num_parts = len(path_parts)

    # Find the part that contains the GDB extension
    endpos = 1
    for endpos, p in enumerate(path_parts):
        if p.lower().endswith(ESRI_GDB_EXTENSIONS):
            break
    startpos = endpos + 1

    # Set the workspace path and return it if the path isn't any longer than that
    ws_path = '\\'.join(path_parts[:startpos])
    if num_parts == startpos:
        return ws_path, _const.CHAR_EMPTY, _const.CHAR_EMPTY

    # If there are more than 2 levels (i.e. feature dataset and feature class), raise an error
    _vld.raise_if(num_parts > startpos + 2, ValueError,
                  'Geodatabase path cannot be more than 2 levels deep')

    last_parts = [(unqualify(p) if remove_qualifier else p)
                  for p in path_parts[startpos:]]
    if len(last_parts) == 2:
        # If the path is 2 elements deep, output all as-is
        return tuple([ws_path] + last_parts)
    else:
        # Detect if the input path was a feature dataset or not and output accordingly
        try:
            meta = _arcpy.Describe(path)
            if not meta.dataType == 'FeatureDataset':
                raise ValueError
        except (RuntimeError, IOError, AttributeError, ValueError, NameError):
            return ws_path, _const.CHAR_EMPTY, last_parts[0]
        return ws_path, last_parts[0], _const.CHAR_EMPTY
Пример #2
0
def list_missing(table, expected_fields):
    """
    Returns a list of missing field **names** for a specified table or feature class.
    The expected field names are case-insensitive.
    If an empty list is returned, all fields are accounted for.

    If one ore more expected field names are a "special field" (containing an '@' sign),
    these will be resolved to the actual field names.
    If this process fails, the field will be considered missing.

    :param table:           The table or feature class for which to check the fields.
    :param expected_fields: A list of fields that should be present in the table or feature class.
    :type table:            str, unicode
    :type expected_fields:  list, tuple
    :rtype:                 list
    """

    table_fields = list_fields(table, True, True)

    desc = None
    missing = []
    for f in expected_fields:
        field = f.upper()
        if _const.CHAR_AT in field:
            if desc is None:
                # Only describe the input table (= time-consuming) if @ has been used in a field name and only once
                try:
                    # Use arcpy's built-in Describe function, to avoid cyclic imports (in metadata module)
                    desc = _arcpy.Describe(table)
                except (RuntimeError, OSError, AttributeError, ValueError,
                        TypeError):
                    desc = object()
            if (field == _const.FIELD_OID and not getattr(desc, _const.DESC_FIELD_OID, None)) or \
               (field.startswith(_const.FIELD_SHAPE) and not getattr(desc, _const.DESC_FIELD_SHAPE, None)) or \
               (field == _const.FIELD_LENGTH and not getattr(desc, _const.DESC_FIELD_LENGTH, None)) or \
               (field == _const.FIELD_AREA and not getattr(desc, _const.DESC_FIELD_AREA, None)):
                missing.append(f)
            continue
        if field not in table_fields:
            missing.append(f)

    return missing
Пример #3
0
 def __init__(self, element):
     self._obj = None
     try:
         self._obj = _arcpy.Describe(element)
     except Exception as e:
         _warn(str(e), DescribeWarning)