Skip to content

Commit

Permalink
feat: supports numpy types in serialization to Line protocol (#306)
Browse files Browse the repository at this point in the history
  • Loading branch information
bednar authored Aug 16, 2021
1 parent ad58f9e commit f455a87
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
1. [#281](https://github.com/influxdata/influxdb-client-python/pull/281): `FluxTable`, `FluxColumn` and `FluxRecord` objects have helpful reprs
1. [#293](https://github.com/influxdata/influxdb-client-python/pull/293): `dataframe_serializer` supports batching
1. [#301](https://github.com/influxdata/influxdb-client-python/pull/301): Add `proxy_headers` to configuration options
1. [#306](https://github.com/influxdata/influxdb-client-python/pull/306): Supports `numpy` type in serialization to Line protocol

### Documentation
1. [#301](https://github.com/influxdata/influxdb-client-python/pull/301): How to configure proxy
Expand Down
22 changes: 20 additions & 2 deletions influxdb_client/client/write/point.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@
'\\': r'\\',
})

try:
import numpy as np

_HAS_NUMPY = True
except ModuleNotFoundError:
_HAS_NUMPY = False


class Point(object):
"""
Expand Down Expand Up @@ -145,7 +152,7 @@ def _append_fields(fields):
if value is None:
continue

if isinstance(value, float) or isinstance(value, Decimal):
if isinstance(value, float) or isinstance(value, Decimal) or _np_is_subtype(value, 'float'):
if not math.isfinite(value):
continue
s = str(value)
Expand All @@ -156,7 +163,7 @@ def _append_fields(fields):
if s.endswith('.0'):
s = s[:-2]
_return.append(f'{_escape_key(field)}={s}')
elif isinstance(value, int) and not isinstance(value, bool):
elif (isinstance(value, int) or _np_is_subtype(value, 'int')) and not isinstance(value, bool):
_return.append(f'{_escape_key(field)}={str(value)}i')
elif isinstance(value, bool):
_return.append(f'{_escape_key(field)}={str(value).lower()}')
Expand Down Expand Up @@ -216,3 +223,14 @@ def _convert_timestamp(timestamp, precision=DEFAULT_WRITE_PRECISION):
return ns / 1e9

raise ValueError(timestamp)


def _np_is_subtype(value, np_type):
if not _HAS_NUMPY or not hasattr(value, 'dtype'):
return False

if np_type == 'float':
return np.issubdtype(value, np.floating)
elif np_type == 'int':
return np.issubdtype(value, np.integer)
return False
20 changes: 20 additions & 0 deletions tests/test_point.py
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,26 @@ def test_backslash(self):
"test,tag1=value1,tag2=value\2,tag3=value\\3,tag4=value\\4,tag5=value\\\\5 value=10i 1624989000000000000",
point.to_line_protocol())

def test_numpy_types(self):
from influxdb_client.extras import np

point = Point.measurement("h2o")\
.tag("location", "europe")\
.field("np.float1", np.float(1.123))\
.field("np.float2", np.float16(2.123))\
.field("np.float3", np.float32(3.123))\
.field("np.float4", np.float64(4.123))\
.field("np.int1", np.int8(1))\
.field("np.int2", np.int16(2))\
.field("np.int3", np.int32(3))\
.field("np.int4", np.int64(4))\
.field("np.uint1", np.uint8(5))\
.field("np.uint2", np.uint16(6))\
.field("np.uint3", np.uint32(7))\
.field("np.uint4", np.uint64(8))

self.assertEqual("h2o,location=europe np.float1=1.123,np.float2=2.123,np.float3=3.123,np.float4=4.123,np.int1=1i,np.int2=2i,np.int3=3i,np.int4=4i,np.uint1=5i,np.uint2=6i,np.uint3=7i,np.uint4=8i", point.to_line_protocol())


if __name__ == '__main__':
unittest.main()

0 comments on commit f455a87

Please sign in to comment.