@@ -99,15 +99,41 @@ def from_dict(dictionary: dict, write_precision: WritePrecision = DEFAULT_WRITE_
9999 record_tag_keys=["location", "version"],
100100 record_field_keys=["pressure", "temperature"])
101101
102+ Int Types:
103+ The following example shows how to configure the types of integers fields.
104+ It is useful when you want to serialize integers always as ``float`` to avoid ``field type conflict``
105+ or use ``unsigned 64-bit integer`` as the type for serialization.
106+
107+ .. code-block:: python
108+
109+ # Use custom dictionary structure
110+ dict_structure = {
111+ "measurement": "h2o_feet",
112+ "tags": {"location": "coyote_creek"},
113+ "fields": {
114+ "water_level": 1.0,
115+ "some_counter": 108913123234
116+ },
117+ "time": 1
118+ }
119+
120+ point = Point.from_dict(dict_structure, field_types={"some_counter": "uint"})
121+
102122 :param dictionary: dictionary for serialize into data Point
103123 :param write_precision: sets the precision for the supplied time values
104124 :key record_measurement_key: key of dictionary with specified measurement
105125 :key record_measurement_name: static measurement name for data Point
106126 :key record_time_key: key of dictionary with specified timestamp
107127 :key record_tag_keys: list of dictionary keys to use as a tag
108128 :key record_field_keys: list of dictionary keys to use as a field
129+ :key field_types: optional dictionary to specify types of serialized fields. Currently, is supported customization for integer types.
130+ Possible integers types:
131+ - ``int`` - serialize integers as "**Signed 64-bit integers**" - ``9223372036854775807i`` (default behaviour)
132+ - ``uint`` - serialize integers as "**Unsigned 64-bit integers**" - ``9223372036854775807u``
133+ - ``float`` - serialize integers as "**IEEE-754 64-bit floating-point numbers**". Useful for unify number types in your pipeline to avoid field type conflict - ``9223372036854775807``
134+ The ``field_types`` can be also specified as part of incoming dictionary. For more info see an example above.
109135 :return: new data point
110- """
136+ """ # noqa: E501
111137 measurement_ = kwargs .get ('record_measurement_name' , None )
112138 if measurement_ is None :
113139 measurement_ = dictionary [kwargs .get ('record_measurement_key' , 'measurement' )]
@@ -134,6 +160,19 @@ def from_dict(dictionary: dict, write_precision: WritePrecision = DEFAULT_WRITE_
134160 record_time_key = kwargs .get ('record_time_key' , 'time' )
135161 if record_time_key in dictionary :
136162 point .time (dictionary [record_time_key ], write_precision = write_precision )
163+
164+ _field_types = kwargs .get ('field_types' , {})
165+ if 'field_types' in dictionary :
166+ _field_types = dictionary ['field_types' ]
167+ # Map API fields types to Line Protocol types postfix:
168+ # - int: 'i'
169+ # - uint: 'u'
170+ # - float: ''
171+ point ._field_types = dict (map (
172+ lambda item : (item [0 ], 'i' if item [1 ] == 'int' else 'u' if item [1 ] == 'uint' else '' ),
173+ _field_types .items ()
174+ ))
175+
137176 return point
138177
139178 def __init__ (self , measurement_name ):
@@ -143,6 +182,7 @@ def __init__(self, measurement_name):
143182 self ._name = measurement_name
144183 self ._time = None
145184 self ._write_precision = DEFAULT_WRITE_PRECISION
185+ self ._field_types = {}
146186
147187 def time (self , time , write_precision = DEFAULT_WRITE_PRECISION ):
148188 """
@@ -190,7 +230,7 @@ def to_line_protocol(self, precision=None):
190230"""
191231 warnings .warn (message , SyntaxWarning )
192232 _tags = _append_tags (self ._tags )
193- _fields = _append_fields (self ._fields )
233+ _fields = _append_fields (self ._fields , self . _field_types )
194234 if not _fields :
195235 return ""
196236 _time = _append_time (self ._time , self ._write_precision if precision is None else precision )
@@ -227,7 +267,7 @@ def _append_tags(tags):
227267 return f"{ ',' if _return else '' } { ',' .join (_return )} "
228268
229269
230- def _append_fields (fields ):
270+ def _append_fields (fields , field_types ):
231271 _return = []
232272
233273 for field , value in sorted (fields .items ()):
@@ -246,7 +286,8 @@ def _append_fields(fields):
246286 s = s [:- 2 ]
247287 _return .append (f'{ _escape_key (field )} ={ s } ' )
248288 elif (isinstance (value , int ) or _np_is_subtype (value , 'int' )) and not isinstance (value , bool ):
249- _return .append (f'{ _escape_key (field )} ={ str (value )} i' )
289+ _type = field_types .get (field , "i" )
290+ _return .append (f'{ _escape_key (field )} ={ str (value )} { _type } ' )
250291 elif isinstance (value , bool ):
251292 _return .append (f'{ _escape_key (field )} ={ str (value ).lower ()} ' )
252293 elif isinstance (value , str ):
0 commit comments