Exemplo n.º 1
0
    def newRow(self, values=None):
        """
        Returns a new MutableRow instance (optionally populated with data).

        :param values:      Optional ``list`` or ``tuple`` of field values in the correct ``InsertCursor`` field order
                            or a ``dict`` of key-value pairs, where the keys specify the field names to set.
        :raises ValueError: If *values* is a ``list`` or ``tuple`` and the length does not match the number of
                            cursor fields, or if *values* is a ``dict`` and one of the keys does not match with the
                            cursor field names.
        :rtype:             _MutableRow
        """

        _vld.raise_if(values and not _vld.is_iterable(values), ValueError,
                      "newRow() 'values' should be iterable or None")

        # Although it would be more efficient to initialize _MutableRow once and simply call it
        # to set its values, this might not be what the user expects. Therefore, we (re)initialize it each time.
        if isinstance(values, dict):
            row = _MutableRow(self._field_map)
            for k, v in values.iteritems():
                row.setValue(k, v)
        else:
            row = _MutableRow(self._field_map)(values)

        return row
Exemplo n.º 2
0
 def __init__(self, table_path, key_field, value_field, where_clause=None, **kwargs):
     _vld.raise_if(_vld.is_iterable(value_field), ValueError,
                   '{} expects a single value field: use {} instead'.format(ValueLookup.__name__,
                                                                            RowLookup.__name__))
     _vld.pass_if(all(_vld.has_value(v) for v in (table_path, key_field, value_field)), ValueError,
                  '{} requires valid table_path, key_field and value_field arguments')
     super(ValueLookup, self).__init__(table_path, key_field, value_field, where_clause, **kwargs)
Exemplo n.º 3
0
def format_iterable(iterable, conjunction=AND):
    """
    Function that pretty-prints an iterable, separated by commas and adding a conjunction before the last item.

    Example:

        >>> iterable = [1, 2, 3, 4]
        >>> format_iterable(iterable)
        '1, 2, 3 and 4'

    :param iterable:    The iterable (e.g. list or tuple) to format.
    :param conjunction: The conjunction to use before the last item. Defaults to "and".
    :type iterable:     list, tuple
    :type conjunction:  str
    """
    _vld.pass_if(_vld.is_iterable(iterable), TypeError,
                 "'iterable' attribute must be an iterable (e.g. list)")

    num_items = len(iterable)
    if num_items == 0:
        return ''
    if num_items == 1:
        return to_str(iterable[-1])
    return '{} {} {}'.format(', '.join(to_str(v) for v in iterable[:-1]),
                             conjunction, iterable[-1])
Exemplo n.º 4
0
def test_isiterable():
    assert validate.is_iterable([1, 2, 3]) is True
    assert validate.is_iterable((1, 2, 3)) is True
    assert validate.is_iterable({1, 2, 3}) is False
    assert validate.is_iterable({'a': 1, 'b': 2}) is True
    assert validate.is_iterable(v for v in (1, 2, 3)) is False
    assert validate.is_iterable('test') is False
    assert validate.is_iterable(0) is False
    assert validate.is_iterable(None) is False
Exemplo n.º 5
0
    def extend(self, values: _tp.Iterable):
        """
        Adds multiple coordinates to the geometry.

        :param values:      An iterable of numeric coordinate values, ``Point``, ``Array`` or ``ShapeBuilder`` objects.
        :type values:       tuple, list
        :raises ValueError: If the *values* argument is not an iterable.
        """
        _vld.pass_if(_vld.is_iterable(values), ValueError, 'extend() expects an iterable')
        for v in values:
            self.append(v)
Exemplo n.º 6
0
    def __init__(self, table_path, key_field, value_field, where_clause=None, **kwargs):
        _vld.raise_if(_vld.is_iterable(value_field), ValueError,
                      '{} expects a single value field: use {} instead'.format(ValueLookup.__name__,
                                                                               RowLookup.__name__))
        _vld.pass_if(all(_vld.has_value(v) for v in (table_path, key_field, value_field)), ValueError,
                     '{} requires valid table_path, key_field and value_field arguments'.format(ValueLookup.__name__))

        # User cannot override row processor function for this class
        if _ROWFUNC_ARG in kwargs:
            del kwargs[_ROWFUNC_ARG]

        self._dupekeys = kwargs.get(_DUPEKEYS_ARG, False)
        super(ValueLookup, self).__init__(table_path, key_field, value_field, where_clause, **kwargs)
Exemplo n.º 7
0
    def __init__(self,
                 table_path: str,
                 key_field: str,
                 value_fields: _tp.Union[str, _tp.Sequence[str]],
                 where_clause: _tp.Union[str, _q.Where, None] = None,
                 **kwargs):
        super().__init__()

        fields = tuple([key_field] +
                       list(value_fields if _vld.is_iterable(value_fields) else
                            (value_fields, )))
        self._hascoordkey = key_field.upper().startswith(_const.FIELD_X)
        self._populate(table_path, fields, where_clause, **kwargs)
Exemplo n.º 8
0
def get_vertices(geometry) -> _tp.Generator:
    """
    Returns a generator of coordinate tuples (x, y[, z] floats) for all vertices in an Esri Geometry.
    If the geometry is not Z aware, the coordinate tuples will only hold 2 values (X and Y).

    :param geometry:    The Esri Geometry (e.g. Polygon, Polyline etc.) for which to extract all vertices.
    """

    if _vld.is_iterable(geometry):
        _vld.pass_if(isinstance(geometry, (_arcpy.Geometry, _arcpy.Array)),
                     ValueError, 'get_vertices() requires an Esri Geometry or Array')
        for g in geometry:
            for v in get_vertices(g):
                yield v
    else:
        yield tuple(v for v in get_xyz(geometry) if v)
Exemplo n.º 9
0
def list_fields(
        obj: _tp.Union[str, _tp.Sequence],
        names_only: bool = True,
        uppercase: bool = False) -> _tp.List[_tp.Union[str, _arcpy.Field]]:
    """
    Returns a list of Field objects or field names for a given list of Field objects or a dataset.

    :param obj:             Dataset path or list of original ``Field`` instances.
    :param names_only:      When ``True`` (default), a list of field names instead of ``Field`` instances is returned.
    :param uppercase:       When ``True`` (default=``False``), the returned field names will be uppercase.
                            This does **not** apply when *names_only* is ``False`` and ``Field`` instances are returned.
    :return:                List of field names or ``Field`` instances.
    """
    # Get field list if input is not a list (or tuple)
    fields = obj
    if not _vld.is_iterable(obj):
        fields = _arcpy.ListFields(obj) or []

    return [
        get_name(field, uppercase) if names_only else field for field in fields
    ]
Exemplo n.º 10
0
def get_bucket_class(field_names, writable=True):
    """
    Factory function to obtain a :class:`FrozenBucket` or a :class:`Bucket` container class.

    The function instantiates a :class:`BucketFactory` and calls its `get_bucket_class` method.

    :param field_names: An iterable of field names for which to create a bucket class.
    :param writable:    If ``False`` (default = ``True``), a :class:`FrozenBucket` type will be returned.
                        By default, a :class:`Bucket` type will be returned.
    :type field_names:  iterable
    :type writable:     bool
    :rtype:             type

    In theory, you could immediately instantiate the returned bucket class.
    This is okay for a single bucket, but considered bad practice if you do this consecutively (e.g. in a loop).
    For example, it's fine if you do this once:

        >>> my_bucket = get_bucket_class(['field1', 'field2'])(1, 2)
        >>> print(my_bucket)
        Bucket(field1=1, field2=2)

    However, if you need to reuse the bucket class to instantiate multiple buckets, this is better:

        >>> fields = ('Field-With-Dash', 'UPPERCASE_FIELD')
        >>> bucket_cls = get_bucket_class(fields, writable=False)
        >>> for i in range(3):
        >>>     print(bucket_cls(i, i+1))
        FrozenBucket(field_with_dash=0, uppercase_field=1)
        FrozenBucket(field_with_dash=1, uppercase_field=2)
        FrozenBucket(field_with_dash=2, uppercase_field=3)

    .. seealso::    :class:`BucketFactory`, :class:`Bucket`, :class:`FrozenBucket`
    """
    # Input validation
    _vld.raise_if(field_names == _tu.ASTERISK, NotImplementedError,
                  "{} does not support {!r} as 'field_names' attribute".format(get_bucket_class.__name__, _tu.ASTERISK))
    _vld.pass_if(_vld.is_iterable(field_names), TypeError, "'field_names' attribute must be an iterable")

    rec_fields = _iter.collapse(field_names, levels=1)
    return BucketFactory(rec_fields).get_bucket_class(writable)
Exemplo n.º 11
0
def serialize(geometry):
    """
    Serializes Esri Geometry, an Esri Point, EsriJSON or a coordinate iterable into GEONIS Protocol XML geometry.
    Regardless of the dimensions of the input geometry, the output geometry will always be 2D.

    :param geometry:    An Esri Geometry or Point instance, an Esri JSON string or a coordinate iterable.
    :type geometry:     Geometry, str, unicode, tuple, list
    :return:            An XML 'Geometry' element.
    :rtype:             Element

    .. seealso::        :class:`gntools.protocol.Logger`, :class:`gntools.protocol.Feature`
    """

    json_shape = None

    try:
        if hasattr(geometry, 'JSON'):
            # Extract EsriJSON string from arcpy Geometry instance
            geometry = geometry.JSON
        elif hasattr(geometry, 'X') and hasattr(geometry, 'Y'):
            # Convert arcpy Point instance to EsriJSON dict
            json_shape = {_JSON_X: geometry.X, _JSON_Y: geometry.Y}
        elif _vld.is_iterable(geometry) and len(geometry) > 1:
            # Geometry consists of at least 2 coordinates (assume x and y): convert to EsriJSON dict
            json_shape = {_JSON_X: geometry[0], _JSON_Y: geometry[1]}

        if isinstance(geometry, basestring):
            # Geometry is an EsriJSON string: load as dict
            json_shape = _json.loads(geometry)

    except Exception as e:
        raise GeometrySerializationError(
            'serialize() requires an EsriJSON string, '
            'Geometry or Point instance, or a coordinate tuple: {}'.format(e))

    return _serialize_geometry(json_shape)
Exemplo n.º 12
0
    def __init__(self, table_path, key_field, value_fields, where_clause=None, **kwargs):
        super(dict, self).__init__()

        fields = tuple([key_field] + list(value_fields if _vld.is_iterable(value_fields) else (value_fields, )))
        self._iscoordkey = key_field.upper().startswith(_FLD_SHAPEXY)
        self._populate(table_path, fields, where_clause, **kwargs)
Exemplo n.º 13
0
 def __init__(self, in_table, field_names='*', where_clause=None, **kwargs):
     _q.add_where(kwargs, where_clause, in_table)
     super(SearchCursor, self).__init__(in_table, field_names, **kwargs)
     self._row = _Row(
         _map_fields(
             field_names if _vld.is_iterable(field_names) else self.fields))