@@ -99,15 +99,41 @@ def from_dict(dictionary: dict, write_precision: WritePrecision = DEFAULT_WRITE_
99
99
record_tag_keys=["location", "version"],
100
100
record_field_keys=["pressure", "temperature"])
101
101
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
+
102
122
:param dictionary: dictionary for serialize into data Point
103
123
:param write_precision: sets the precision for the supplied time values
104
124
:key record_measurement_key: key of dictionary with specified measurement
105
125
:key record_measurement_name: static measurement name for data Point
106
126
:key record_time_key: key of dictionary with specified timestamp
107
127
:key record_tag_keys: list of dictionary keys to use as a tag
108
128
: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.
109
135
:return: new data point
110
- """
136
+ """ # noqa: E501
111
137
measurement_ = kwargs .get ('record_measurement_name' , None )
112
138
if measurement_ is None :
113
139
measurement_ = dictionary [kwargs .get ('record_measurement_key' , 'measurement' )]
@@ -134,6 +160,19 @@ def from_dict(dictionary: dict, write_precision: WritePrecision = DEFAULT_WRITE_
134
160
record_time_key = kwargs .get ('record_time_key' , 'time' )
135
161
if record_time_key in dictionary :
136
162
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
+
137
176
return point
138
177
139
178
def __init__ (self , measurement_name ):
@@ -143,6 +182,7 @@ def __init__(self, measurement_name):
143
182
self ._name = measurement_name
144
183
self ._time = None
145
184
self ._write_precision = DEFAULT_WRITE_PRECISION
185
+ self ._field_types = {}
146
186
147
187
def time (self , time , write_precision = DEFAULT_WRITE_PRECISION ):
148
188
"""
@@ -190,7 +230,7 @@ def to_line_protocol(self, precision=None):
190
230
"""
191
231
warnings .warn (message , SyntaxWarning )
192
232
_tags = _append_tags (self ._tags )
193
- _fields = _append_fields (self ._fields )
233
+ _fields = _append_fields (self ._fields , self . _field_types )
194
234
if not _fields :
195
235
return ""
196
236
_time = _append_time (self ._time , self ._write_precision if precision is None else precision )
@@ -227,7 +267,7 @@ def _append_tags(tags):
227
267
return f"{ ',' if _return else '' } { ',' .join (_return )} "
228
268
229
269
230
- def _append_fields (fields ):
270
+ def _append_fields (fields , field_types ):
231
271
_return = []
232
272
233
273
for field , value in sorted (fields .items ()):
@@ -246,7 +286,8 @@ def _append_fields(fields):
246
286
s = s [:- 2 ]
247
287
_return .append (f'{ _escape_key (field )} ={ s } ' )
248
288
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 } ' )
250
291
elif isinstance (value , bool ):
251
292
_return .append (f'{ _escape_key (field )} ={ str (value ).lower ()} ' )
252
293
elif isinstance (value , str ):
0 commit comments