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
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)
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])
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
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)
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)
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)
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)
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 ]
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)
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)
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)
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))