influxdb3-python 0.3.6__tar.gz → 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/PKG-INFO +11 -7
- {influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/README.md +7 -4
- {influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/influxdb3_python.egg-info/PKG-INFO +11 -7
- {influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/influxdb3_python.egg-info/SOURCES.txt +1 -0
- {influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/influxdb_client_3/__init__.py +34 -27
- {influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/influxdb_client_3/read_file.py +6 -4
- {influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/_sync/api_client.py +8 -8
- {influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/client/_base.py +4 -10
- {influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/client/influxdb_client.py +0 -8
- {influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/client/write/dataframe_serializer.py +46 -46
- {influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/client/write_api.py +6 -6
- {influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/setup.py +4 -3
- influxdb3_python-0.4.0/tests/test_dataframe_serializer.py +45 -0
- {influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/tests/test_influxdb_client_3.py +4 -10
- {influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/LICENSE +0 -0
- {influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/influxdb3_python.egg-info/dependency_links.txt +0 -0
- {influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/influxdb3_python.egg-info/requires.txt +0 -0
- {influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/influxdb3_python.egg-info/top_level.txt +0 -0
- {influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/__init__.py +0 -0
- {influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/_sync/__init__.py +0 -0
- {influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/_sync/rest.py +0 -0
- {influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/client/__init__.py +0 -0
- {influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/client/exceptions.py +0 -0
- {influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/client/logging_handler.py +0 -0
- {influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/client/util/__init__.py +0 -0
- {influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/client/util/date_utils.py +0 -0
- {influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/client/util/date_utils_pandas.py +0 -0
- {influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/client/util/helpers.py +0 -0
- {influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/client/util/multiprocessing_helper.py +0 -0
- {influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/client/warnings.py +0 -0
- {influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/client/write/__init__.py +0 -0
- {influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/client/write/point.py +0 -0
- {influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/client/write/retry.py +0 -0
- {influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/configuration.py +0 -0
- {influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/domain/__init__.py +0 -0
- {influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/domain/write_precision.py +0 -0
- {influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/extras.py +0 -0
- {influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/rest.py +0 -0
- {influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/service/__init__.py +0 -0
- {influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/service/_base_service.py +0 -0
- {influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/service/signin_service.py +0 -0
- {influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/service/signout_service.py +0 -0
- {influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/service/write_service.py +0 -0
- {influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/version.py +0 -0
- {influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: influxdb3-python
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Community Python client for InfluxDB 3.0
|
|
5
5
|
Home-page: https://github.com/InfluxCommunity/influxdb3-python
|
|
6
6
|
Author: InfluxData
|
|
@@ -8,11 +8,12 @@ Author-email: contact@influxdata.com
|
|
|
8
8
|
Classifier: Development Status :: 4 - Beta
|
|
9
9
|
Classifier: Intended Audience :: Developers
|
|
10
10
|
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
-
Classifier: Programming Language :: Python :: 3.7
|
|
12
11
|
Classifier: Programming Language :: Python :: 3.8
|
|
13
12
|
Classifier: Programming Language :: Python :: 3.9
|
|
14
13
|
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
-
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Requires-Python: >=3.8
|
|
16
17
|
Description-Content-Type: text/markdown
|
|
17
18
|
License-File: LICENSE
|
|
18
19
|
Requires-Dist: reactivex>=4.0.4
|
|
@@ -40,11 +41,14 @@ Requires-Dist: polars; extra == "dataframe"
|
|
|
40
41
|
<a href="https://pypi.org/project/influxdb3-python/">
|
|
41
42
|
<img src="https://img.shields.io/pypi/dm/influxdb3-python.svg" alt="PyPI downloads">
|
|
42
43
|
</a>
|
|
43
|
-
<a href="https://github.com/InfluxCommunity/influxdb3-python/actions/workflows/
|
|
44
|
-
<img src="https://github.com/InfluxCommunity/influxdb3-python/actions/workflows/
|
|
44
|
+
<a href="https://github.com/InfluxCommunity/influxdb3-python/actions/workflows/codeql-analysis.yml">
|
|
45
|
+
<img src="https://github.com/InfluxCommunity/influxdb3-python/actions/workflows/codeql-analysis.yml/badge.svg?branch=main" alt="CodeQL analysis">
|
|
45
46
|
</a>
|
|
46
|
-
|
|
47
|
-
<img src="https://
|
|
47
|
+
<a href="https://dl.circleci.com/status-badge/redirect/gh/InfluxCommunity/influxdb3-python/tree/main">
|
|
48
|
+
<img src="https://dl.circleci.com/status-badge/img/gh/InfluxCommunity/influxdb3-python/tree/main.svg?style=svg" alt="CircleCI">
|
|
49
|
+
</a>
|
|
50
|
+
<a href="https://codecov.io/gh/InfluxCommunity/influxdb3-python">
|
|
51
|
+
<img src="https://codecov.io/gh/InfluxCommunity/influxdb3-python/branch/main/graph/badge.svg" alt="Code Cov"/>
|
|
48
52
|
</a>
|
|
49
53
|
<a href="https://influxcommunity.slack.com">
|
|
50
54
|
<img src="https://img.shields.io/badge/slack-join_chat-white.svg?logo=slack&style=social" alt="Community Slack">
|
|
@@ -9,11 +9,14 @@
|
|
|
9
9
|
<a href="https://pypi.org/project/influxdb3-python/">
|
|
10
10
|
<img src="https://img.shields.io/pypi/dm/influxdb3-python.svg" alt="PyPI downloads">
|
|
11
11
|
</a>
|
|
12
|
-
<a href="https://github.com/InfluxCommunity/influxdb3-python/actions/workflows/
|
|
13
|
-
<img src="https://github.com/InfluxCommunity/influxdb3-python/actions/workflows/
|
|
12
|
+
<a href="https://github.com/InfluxCommunity/influxdb3-python/actions/workflows/codeql-analysis.yml">
|
|
13
|
+
<img src="https://github.com/InfluxCommunity/influxdb3-python/actions/workflows/codeql-analysis.yml/badge.svg?branch=main" alt="CodeQL analysis">
|
|
14
14
|
</a>
|
|
15
|
-
|
|
16
|
-
<img src="https://
|
|
15
|
+
<a href="https://dl.circleci.com/status-badge/redirect/gh/InfluxCommunity/influxdb3-python/tree/main">
|
|
16
|
+
<img src="https://dl.circleci.com/status-badge/img/gh/InfluxCommunity/influxdb3-python/tree/main.svg?style=svg" alt="CircleCI">
|
|
17
|
+
</a>
|
|
18
|
+
<a href="https://codecov.io/gh/InfluxCommunity/influxdb3-python">
|
|
19
|
+
<img src="https://codecov.io/gh/InfluxCommunity/influxdb3-python/branch/main/graph/badge.svg" alt="Code Cov"/>
|
|
17
20
|
</a>
|
|
18
21
|
<a href="https://influxcommunity.slack.com">
|
|
19
22
|
<img src="https://img.shields.io/badge/slack-join_chat-white.svg?logo=slack&style=social" alt="Community Slack">
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: influxdb3-python
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Community Python client for InfluxDB 3.0
|
|
5
5
|
Home-page: https://github.com/InfluxCommunity/influxdb3-python
|
|
6
6
|
Author: InfluxData
|
|
@@ -8,11 +8,12 @@ Author-email: contact@influxdata.com
|
|
|
8
8
|
Classifier: Development Status :: 4 - Beta
|
|
9
9
|
Classifier: Intended Audience :: Developers
|
|
10
10
|
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
-
Classifier: Programming Language :: Python :: 3.7
|
|
12
11
|
Classifier: Programming Language :: Python :: 3.8
|
|
13
12
|
Classifier: Programming Language :: Python :: 3.9
|
|
14
13
|
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
-
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Requires-Python: >=3.8
|
|
16
17
|
Description-Content-Type: text/markdown
|
|
17
18
|
License-File: LICENSE
|
|
18
19
|
Requires-Dist: reactivex>=4.0.4
|
|
@@ -40,11 +41,14 @@ Requires-Dist: polars; extra == "dataframe"
|
|
|
40
41
|
<a href="https://pypi.org/project/influxdb3-python/">
|
|
41
42
|
<img src="https://img.shields.io/pypi/dm/influxdb3-python.svg" alt="PyPI downloads">
|
|
42
43
|
</a>
|
|
43
|
-
<a href="https://github.com/InfluxCommunity/influxdb3-python/actions/workflows/
|
|
44
|
-
<img src="https://github.com/InfluxCommunity/influxdb3-python/actions/workflows/
|
|
44
|
+
<a href="https://github.com/InfluxCommunity/influxdb3-python/actions/workflows/codeql-analysis.yml">
|
|
45
|
+
<img src="https://github.com/InfluxCommunity/influxdb3-python/actions/workflows/codeql-analysis.yml/badge.svg?branch=main" alt="CodeQL analysis">
|
|
45
46
|
</a>
|
|
46
|
-
|
|
47
|
-
<img src="https://
|
|
47
|
+
<a href="https://dl.circleci.com/status-badge/redirect/gh/InfluxCommunity/influxdb3-python/tree/main">
|
|
48
|
+
<img src="https://dl.circleci.com/status-badge/img/gh/InfluxCommunity/influxdb3-python/tree/main.svg?style=svg" alt="CircleCI">
|
|
49
|
+
</a>
|
|
50
|
+
<a href="https://codecov.io/gh/InfluxCommunity/influxdb3-python">
|
|
51
|
+
<img src="https://codecov.io/gh/InfluxCommunity/influxdb3-python/branch/main/graph/badge.svg" alt="Code Cov"/>
|
|
48
52
|
</a>
|
|
49
53
|
<a href="https://influxcommunity.slack.com">
|
|
50
54
|
<img src="https://img.shields.io/badge/slack-join_chat-white.svg?logo=slack&style=social" alt="Community Slack">
|
|
@@ -39,4 +39,5 @@ influxdb_client_3/write_client/service/_base_service.py
|
|
|
39
39
|
influxdb_client_3/write_client/service/signin_service.py
|
|
40
40
|
influxdb_client_3/write_client/service/signout_service.py
|
|
41
41
|
influxdb_client_3/write_client/service/write_service.py
|
|
42
|
+
tests/test_dataframe_serializer.py
|
|
42
43
|
tests/test_influxdb_client_3.py
|
|
@@ -1,20 +1,24 @@
|
|
|
1
|
-
import
|
|
1
|
+
import json
|
|
2
|
+
import urllib.parse
|
|
3
|
+
|
|
2
4
|
import pyarrow as pa
|
|
3
|
-
from influxdb_client_3.write_client import InfluxDBClient as _InfluxDBClient, WriteOptions, Point
|
|
4
|
-
from influxdb_client_3.write_client.client.write_api import WriteApi as _WriteApi, SYNCHRONOUS, ASYNCHRONOUS, PointSettings
|
|
5
|
-
from influxdb_client_3.write_client.domain.write_precision import WritePrecision
|
|
6
|
-
from influxdb_client_3.write_client.client.exceptions import InfluxDBError
|
|
7
5
|
from pyarrow.flight import FlightClient, Ticket, FlightCallOptions
|
|
6
|
+
|
|
8
7
|
from influxdb_client_3.read_file import UploadFile
|
|
9
|
-
import
|
|
8
|
+
from influxdb_client_3.write_client import InfluxDBClient as _InfluxDBClient, WriteOptions, Point
|
|
9
|
+
from influxdb_client_3.write_client.client.exceptions import InfluxDBError
|
|
10
|
+
from influxdb_client_3.write_client.client.write_api import WriteApi as _WriteApi, SYNCHRONOUS, ASYNCHRONOUS, \
|
|
11
|
+
PointSettings
|
|
12
|
+
from influxdb_client_3.write_client.domain.write_precision import WritePrecision
|
|
13
|
+
|
|
10
14
|
try:
|
|
11
15
|
import polars as pl
|
|
16
|
+
|
|
12
17
|
polars = True
|
|
13
18
|
except ImportError:
|
|
14
19
|
polars = False
|
|
15
20
|
|
|
16
21
|
|
|
17
|
-
|
|
18
22
|
def write_client_options(**kwargs):
|
|
19
23
|
"""
|
|
20
24
|
Function for providing additional arguments for the WriteApi client.
|
|
@@ -24,9 +28,11 @@ def write_client_options(**kwargs):
|
|
|
24
28
|
"""
|
|
25
29
|
return kwargs
|
|
26
30
|
|
|
31
|
+
|
|
27
32
|
def default_client_options(**kwargs):
|
|
28
33
|
return kwargs
|
|
29
34
|
|
|
35
|
+
|
|
30
36
|
def flight_client_options(**kwargs):
|
|
31
37
|
"""
|
|
32
38
|
Function for providing additional arguments for the FlightClient.
|
|
@@ -36,6 +42,7 @@ def flight_client_options(**kwargs):
|
|
|
36
42
|
"""
|
|
37
43
|
return kwargs
|
|
38
44
|
|
|
45
|
+
|
|
39
46
|
def file_parser_options(**kwargs):
|
|
40
47
|
"""
|
|
41
48
|
Function for providing additional arguments for the file parser.
|
|
@@ -43,7 +50,7 @@ def file_parser_options(**kwargs):
|
|
|
43
50
|
:param kwargs: Additional arguments for the file parser.
|
|
44
51
|
:return: dict with the arguments.
|
|
45
52
|
"""
|
|
46
|
-
return kwargs
|
|
53
|
+
return kwargs
|
|
47
54
|
|
|
48
55
|
|
|
49
56
|
def _deep_merge(target, source):
|
|
@@ -67,6 +74,7 @@ def _deep_merge(target, source):
|
|
|
67
74
|
target = source
|
|
68
75
|
return target
|
|
69
76
|
|
|
77
|
+
|
|
70
78
|
class InfluxDBClient3:
|
|
71
79
|
def __init__(
|
|
72
80
|
self,
|
|
@@ -99,11 +107,12 @@ class InfluxDBClient3:
|
|
|
99
107
|
self._org = org if org is not None else "default"
|
|
100
108
|
self._database = database
|
|
101
109
|
self._token = token
|
|
102
|
-
self._write_client_options = write_client_options if write_client_options is not None
|
|
103
|
-
|
|
110
|
+
self._write_client_options = write_client_options if write_client_options is not None \
|
|
111
|
+
else default_client_options(write_options=SYNCHRONOUS)
|
|
112
|
+
|
|
104
113
|
# Parse the host input
|
|
105
114
|
parsed_url = urllib.parse.urlparse(host)
|
|
106
|
-
|
|
115
|
+
|
|
107
116
|
# Determine the protocol (scheme), hostname, and port
|
|
108
117
|
scheme = parsed_url.scheme if parsed_url.scheme else "https"
|
|
109
118
|
hostname = parsed_url.hostname if parsed_url.hostname else host
|
|
@@ -118,10 +127,10 @@ class InfluxDBClient3:
|
|
|
118
127
|
token=self._token,
|
|
119
128
|
org=self._org,
|
|
120
129
|
**kwargs)
|
|
121
|
-
|
|
130
|
+
|
|
122
131
|
self._write_api = _WriteApi(influxdb_client=self._client, **self._write_client_options)
|
|
123
132
|
self._flight_client_options = flight_client_options or {}
|
|
124
|
-
|
|
133
|
+
|
|
125
134
|
if query_port_overwrite is not None:
|
|
126
135
|
port = query_port_overwrite
|
|
127
136
|
self._flight_client = FlightClient(f"grpc+tls://{hostname}:{port}", **self._flight_client_options)
|
|
@@ -134,7 +143,7 @@ class InfluxDBClient3:
|
|
|
134
143
|
return defaults
|
|
135
144
|
return _deep_merge(defaults, {key: value for key, value in custom.items()})
|
|
136
145
|
|
|
137
|
-
def write(self, record=None, database=None
|
|
146
|
+
def write(self, record=None, database=None, **kwargs):
|
|
138
147
|
"""
|
|
139
148
|
Write data to InfluxDB.
|
|
140
149
|
|
|
@@ -151,9 +160,9 @@ class InfluxDBClient3:
|
|
|
151
160
|
self._write_api.write(bucket=database, record=record, **kwargs)
|
|
152
161
|
except InfluxDBError as e:
|
|
153
162
|
raise e
|
|
154
|
-
|
|
155
163
|
|
|
156
|
-
def write_file(self, file, measurement_name=None, tag_columns=None, timestamp_column='time', database=None,
|
|
164
|
+
def write_file(self, file, measurement_name=None, tag_columns=None, timestamp_column='time', database=None,
|
|
165
|
+
file_parser_options=None, **kwargs):
|
|
157
166
|
"""
|
|
158
167
|
Write data from a file to InfluxDB.
|
|
159
168
|
|
|
@@ -177,10 +186,10 @@ class InfluxDBClient3:
|
|
|
177
186
|
try:
|
|
178
187
|
table = UploadFile(file, file_parser_options).load_file()
|
|
179
188
|
df = table.to_pandas() if isinstance(table, pa.Table) else table
|
|
180
|
-
self._process_dataframe(df, measurement_name, tag_columns or [], timestamp_column, database=database,
|
|
189
|
+
self._process_dataframe(df, measurement_name, tag_columns or [], timestamp_column, database=database,
|
|
190
|
+
**kwargs)
|
|
181
191
|
except Exception as e:
|
|
182
192
|
raise e
|
|
183
|
-
|
|
184
193
|
|
|
185
194
|
def _process_dataframe(self, df, measurement_name, tag_columns, timestamp_column, database, **kwargs):
|
|
186
195
|
# This function is factored out for clarity.
|
|
@@ -204,9 +213,8 @@ class InfluxDBClient3:
|
|
|
204
213
|
data_frame_measurement_name=measurement_name,
|
|
205
214
|
data_frame_tag_columns=tag_columns,
|
|
206
215
|
data_frame_timestamp_column=timestamp_column, **kwargs)
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
def query(self, query, language="sql", mode="all", database=None,**kwargs ):
|
|
216
|
+
|
|
217
|
+
def query(self, query, language="sql", mode="all", database=None, **kwargs):
|
|
210
218
|
"""
|
|
211
219
|
Query data from InfluxDB.
|
|
212
220
|
|
|
@@ -223,12 +231,10 @@ class InfluxDBClient3:
|
|
|
223
231
|
"""
|
|
224
232
|
if mode == "polars" and polars is False:
|
|
225
233
|
raise ImportError("Polars is not installed. Please install it with `pip install polars`.")
|
|
226
|
-
|
|
227
|
-
|
|
228
234
|
|
|
229
235
|
if database is None:
|
|
230
236
|
database = self._database
|
|
231
|
-
|
|
237
|
+
|
|
232
238
|
try:
|
|
233
239
|
# Create an authorization header
|
|
234
240
|
optargs = {
|
|
@@ -237,7 +243,7 @@ class InfluxDBClient3:
|
|
|
237
243
|
}
|
|
238
244
|
opts = self._merge_options(optargs, kwargs)
|
|
239
245
|
_options = FlightCallOptions(**opts)
|
|
240
|
-
|
|
246
|
+
|
|
241
247
|
ticket_data = {"database": database, "sql_query": query, "query_type": language}
|
|
242
248
|
ticket = Ticket(json.dumps(ticket_data).encode('utf-8'))
|
|
243
249
|
flight_reader = self._flight_client.do_get(ticket, _options)
|
|
@@ -249,7 +255,7 @@ class InfluxDBClient3:
|
|
|
249
255
|
"chunk": lambda: flight_reader,
|
|
250
256
|
"reader": flight_reader.to_reader,
|
|
251
257
|
"schema": lambda: flight_reader.schema
|
|
252
|
-
|
|
258
|
+
|
|
253
259
|
}.get(mode, flight_reader.read_all)
|
|
254
260
|
|
|
255
261
|
return mode_func() if callable(mode_func) else mode_func
|
|
@@ -267,7 +273,8 @@ class InfluxDBClient3:
|
|
|
267
273
|
|
|
268
274
|
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
269
275
|
self.close()
|
|
270
|
-
|
|
276
|
+
|
|
277
|
+
|
|
271
278
|
__all__ = [
|
|
272
279
|
"InfluxDBClient3",
|
|
273
280
|
"Point",
|
|
@@ -12,6 +12,7 @@ class UploadFile:
|
|
|
12
12
|
"""
|
|
13
13
|
Class for uploading and reading different types of files.
|
|
14
14
|
"""
|
|
15
|
+
|
|
15
16
|
def __init__(self, file, file_parser_options=None):
|
|
16
17
|
"""
|
|
17
18
|
Initialize an UploadFile instance.
|
|
@@ -44,7 +45,7 @@ class UploadFile:
|
|
|
44
45
|
else:
|
|
45
46
|
raise ValueError("Unsupported file type")
|
|
46
47
|
|
|
47
|
-
def load_feather(self, file
|
|
48
|
+
def load_feather(self, file):
|
|
48
49
|
"""
|
|
49
50
|
Load a Feather file.
|
|
50
51
|
|
|
@@ -99,6 +100,7 @@ class UploadFile:
|
|
|
99
100
|
try:
|
|
100
101
|
import pandas as pd
|
|
101
102
|
except ImportError:
|
|
102
|
-
raise ImportError("Pandas is required for write_file(). Please install it using 'pip install pandas' or
|
|
103
|
-
|
|
104
|
-
|
|
103
|
+
raise ImportError("Pandas is required for write_file(). Please install it using 'pip install pandas' or "
|
|
104
|
+
"'pip install influxdb3-python[pandas]'")
|
|
105
|
+
|
|
106
|
+
return pd.read_json(file, **self._kwargs)
|
{influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/_sync/api_client.py
RENAMED
|
@@ -267,7 +267,7 @@ class ApiClient(object):
|
|
|
267
267
|
if data is None:
|
|
268
268
|
return None
|
|
269
269
|
|
|
270
|
-
if
|
|
270
|
+
if klass is str:
|
|
271
271
|
if klass.startswith('list['):
|
|
272
272
|
sub_kls = re.match(r'list\[(.*)\]', klass).group(1)
|
|
273
273
|
return [self.__deserialize(sub_data, sub_kls)
|
|
@@ -348,13 +348,13 @@ class ApiClient(object):
|
|
|
348
348
|
_preload_content, _request_timeout, urlopen_kw)
|
|
349
349
|
else:
|
|
350
350
|
thread = self.pool.apply_async(self.__call_api, (resource_path,
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
351
|
+
method, path_params, query_params,
|
|
352
|
+
header_params, body,
|
|
353
|
+
post_params, files,
|
|
354
|
+
response_type, auth_settings,
|
|
355
|
+
_return_http_data_only,
|
|
356
|
+
collection_formats,
|
|
357
|
+
_preload_content, _request_timeout, urlopen_kw))
|
|
358
358
|
return thread
|
|
359
359
|
|
|
360
360
|
def request(self, method, url, query_params=None, headers=None,
|
{influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/client/_base.py
RENAMED
|
@@ -5,16 +5,13 @@ import base64
|
|
|
5
5
|
import configparser
|
|
6
6
|
import logging
|
|
7
7
|
import os
|
|
8
|
-
from
|
|
9
|
-
from typing import List, Generator, Any, Union, Iterable, AsyncGenerator
|
|
10
|
-
|
|
11
|
-
from urllib3 import HTTPResponse
|
|
8
|
+
from typing import Iterable
|
|
12
9
|
|
|
10
|
+
from influxdb_client_3.write_client.client.write.dataframe_serializer import DataframeSerializer, \
|
|
11
|
+
PolarsDataframeSerializer
|
|
13
12
|
from influxdb_client_3.write_client.configuration import Configuration
|
|
14
|
-
from influxdb_client_3.write_client.service.write_service import WriteService
|
|
15
|
-
|
|
16
|
-
from influxdb_client_3.write_client.client.write.dataframe_serializer import DataframeSerializer, PolarsDataframeSerializer
|
|
17
13
|
from influxdb_client_3.write_client.rest import _UTF_8_encoding
|
|
14
|
+
from influxdb_client_3.write_client.service.write_service import WriteService
|
|
18
15
|
|
|
19
16
|
try:
|
|
20
17
|
import dataclasses
|
|
@@ -208,7 +205,6 @@ class _BaseClient(object):
|
|
|
208
205
|
profilers=profilers, **kwargs)
|
|
209
206
|
|
|
210
207
|
|
|
211
|
-
|
|
212
208
|
class _BaseWriteApi(object):
|
|
213
209
|
def __init__(self, influxdb_client, point_settings=None):
|
|
214
210
|
self._influxdb_client = influxdb_client
|
|
@@ -260,7 +256,6 @@ class _BaseWriteApi(object):
|
|
|
260
256
|
serializer = DataframeSerializer(record, self._point_settings, write_precision, **kwargs)
|
|
261
257
|
self._serialize(serializer.serialize(), write_precision, payload, **kwargs)
|
|
262
258
|
|
|
263
|
-
|
|
264
259
|
elif hasattr(record, "_asdict"):
|
|
265
260
|
# noinspection PyProtectedMember
|
|
266
261
|
self._serialize(record._asdict(), write_precision, payload, **kwargs)
|
|
@@ -271,7 +266,6 @@ class _BaseWriteApi(object):
|
|
|
271
266
|
self._serialize(item, write_precision, payload, **kwargs)
|
|
272
267
|
|
|
273
268
|
|
|
274
|
-
|
|
275
269
|
class _Configuration(Configuration):
|
|
276
270
|
def __init__(self):
|
|
277
271
|
Configuration.__init__(self)
|
|
@@ -3,8 +3,6 @@
|
|
|
3
3
|
from __future__ import absolute_import
|
|
4
4
|
|
|
5
5
|
import logging
|
|
6
|
-
import warnings
|
|
7
|
-
|
|
8
6
|
|
|
9
7
|
from influxdb_client_3.write_client.client._base import _BaseClient
|
|
10
8
|
from influxdb_client_3.write_client.client.write_api import WriteApi, WriteOptions, PointSettings
|
|
@@ -284,7 +282,6 @@ class InfluxDBClient(_BaseClient):
|
|
|
284
282
|
"""
|
|
285
283
|
return WriteApi(influxdb_client=self, write_options=write_options, point_settings=point_settings, **kwargs)
|
|
286
284
|
|
|
287
|
-
|
|
288
285
|
def close(self):
|
|
289
286
|
"""Shutdown the client."""
|
|
290
287
|
self.__del__()
|
|
@@ -294,8 +291,3 @@ class InfluxDBClient(_BaseClient):
|
|
|
294
291
|
if self.api_client:
|
|
295
292
|
self.api_client.__del__()
|
|
296
293
|
self.api_client = None
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
@@ -9,20 +9,22 @@ import math
|
|
|
9
9
|
import re
|
|
10
10
|
|
|
11
11
|
from influxdb_client_3.write_client.domain import WritePrecision
|
|
12
|
-
from influxdb_client_3.write_client.client.write.point import _ESCAPE_KEY, _ESCAPE_STRING, _ESCAPE_MEASUREMENT,
|
|
12
|
+
from influxdb_client_3.write_client.client.write.point import _ESCAPE_KEY, _ESCAPE_STRING, _ESCAPE_MEASUREMENT, \
|
|
13
|
+
DEFAULT_WRITE_PRECISION
|
|
13
14
|
|
|
14
15
|
logger = logging.getLogger('influxdb_client.client.write.dataframe_serializer')
|
|
15
16
|
|
|
16
17
|
|
|
18
|
+
def _not_nan(x):
|
|
19
|
+
from ...extras import pd
|
|
20
|
+
return not pd.isna(x)
|
|
21
|
+
|
|
22
|
+
|
|
17
23
|
def _itertuples(data_frame):
|
|
18
24
|
cols = [data_frame.iloc[:, k] for k in range(len(data_frame.columns))]
|
|
19
25
|
return zip(data_frame.index, *cols)
|
|
20
26
|
|
|
21
27
|
|
|
22
|
-
def _not_nan(x):
|
|
23
|
-
return x == x
|
|
24
|
-
|
|
25
|
-
|
|
26
28
|
def _any_not_nan(p, indexes):
|
|
27
29
|
return any(map(lambda x: _not_nan(p[x]), indexes))
|
|
28
30
|
|
|
@@ -175,7 +177,7 @@ class DataframeSerializer:
|
|
|
175
177
|
# This column is a tag column.
|
|
176
178
|
if null_columns.iloc[index]:
|
|
177
179
|
key_value = f"""{{
|
|
178
|
-
'' if {val_format} == '' or
|
|
180
|
+
'' if {val_format} == '' or pd.isna({val_format}) else
|
|
179
181
|
f',{key_format}={{str({val_format}).translate(_ESCAPE_STRING)}}'
|
|
180
182
|
}}"""
|
|
181
183
|
else:
|
|
@@ -191,20 +193,22 @@ class DataframeSerializer:
|
|
|
191
193
|
# It's important to omit it because when the first
|
|
192
194
|
# field column has no nulls, we don't run the comma-removal
|
|
193
195
|
# regexp substitution step.
|
|
196
|
+
|
|
194
197
|
sep = '' if len(field_indexes) == 0 else ','
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
elif issubclass(value.type, np.floating):
|
|
198
|
+
|
|
199
|
+
if (issubclass(value.type, np.integer) or issubclass(value.type, np.floating) or
|
|
200
|
+
issubclass(value.type, np.bool_)):
|
|
201
|
+
suffix = 'i' if issubclass(value.type, np.integer) else ''
|
|
200
202
|
if null_columns.iloc[index]:
|
|
201
|
-
field_value =
|
|
203
|
+
field_value = (
|
|
204
|
+
f"""{{"" if pd.isna({val_format}) else f"{sep}{key_format}={{{val_format}}}{suffix}"}}"""
|
|
205
|
+
)
|
|
202
206
|
else:
|
|
203
|
-
field_value = f'{sep}{key_format}={{{val_format}}}'
|
|
207
|
+
field_value = f'{sep}{key_format}={{{val_format}}}{suffix}'
|
|
204
208
|
else:
|
|
205
209
|
if null_columns.iloc[index]:
|
|
206
210
|
field_value = f"""{{
|
|
207
|
-
'' if
|
|
211
|
+
'' if pd.isna({val_format}) else
|
|
208
212
|
f'{sep}{key_format}="{{str({val_format}).translate(_ESCAPE_STRING)}}"'
|
|
209
213
|
}}"""
|
|
210
214
|
else:
|
|
@@ -229,7 +233,7 @@ class DataframeSerializer:
|
|
|
229
233
|
'_ESCAPE_KEY': _ESCAPE_KEY,
|
|
230
234
|
'_ESCAPE_STRING': _ESCAPE_STRING,
|
|
231
235
|
'keys': keys,
|
|
232
|
-
'
|
|
236
|
+
'pd': pd,
|
|
233
237
|
})
|
|
234
238
|
|
|
235
239
|
for k, v in dict(data_frame.dtypes).items():
|
|
@@ -297,8 +301,7 @@ class PolarsDataframeSerializer:
|
|
|
297
301
|
:key data_frame_timestamp_column: name of DataFrame column which contains a timestamp.
|
|
298
302
|
:key data_frame_timestamp_timezone: name of the timezone which is used for timestamp column
|
|
299
303
|
"""
|
|
300
|
-
|
|
301
|
-
|
|
304
|
+
|
|
302
305
|
self.data_frame = data_frame
|
|
303
306
|
self.point_settings = point_settings
|
|
304
307
|
self.precision = precision
|
|
@@ -311,7 +314,9 @@ class PolarsDataframeSerializer:
|
|
|
311
314
|
self.column_indices = {name: index for index, name in enumerate(data_frame.columns)}
|
|
312
315
|
|
|
313
316
|
if self.timestamp_column is None or self.timestamp_column not in self.column_indices:
|
|
314
|
-
raise ValueError(
|
|
317
|
+
raise ValueError(
|
|
318
|
+
f"Timestamp column {self.timestamp_column} not found in DataFrame. Please define a valid timestamp "
|
|
319
|
+
f"column.")
|
|
315
320
|
|
|
316
321
|
#
|
|
317
322
|
# prepare chunks
|
|
@@ -321,20 +326,19 @@ class PolarsDataframeSerializer:
|
|
|
321
326
|
self.chunk_size = chunk_size
|
|
322
327
|
else:
|
|
323
328
|
self.number_of_chunks = None
|
|
324
|
-
|
|
325
|
-
def escape_key(self,value):
|
|
329
|
+
|
|
330
|
+
def escape_key(self, value):
|
|
326
331
|
return str(value).translate(_ESCAPE_KEY)
|
|
327
|
-
|
|
328
|
-
def escape_value(self,value):
|
|
332
|
+
|
|
333
|
+
def escape_value(self, value):
|
|
329
334
|
return str(value).translate(_ESCAPE_STRING)
|
|
330
335
|
|
|
331
|
-
|
|
332
336
|
def to_line_protocol(self, row):
|
|
333
337
|
# Filter out None or empty values for tags
|
|
334
338
|
tags = ""
|
|
335
|
-
|
|
339
|
+
|
|
336
340
|
tags = ",".join(
|
|
337
|
-
f'{self.escape_key(col)}={self.escape_key(row[self.column_indices[col]])}'
|
|
341
|
+
f'{self.escape_key(col)}={self.escape_key(row[self.column_indices[col]])}'
|
|
338
342
|
for col in self.tag_columns
|
|
339
343
|
if row[self.column_indices[col]] is not None and row[self.column_indices[col]] != ""
|
|
340
344
|
)
|
|
@@ -348,23 +352,21 @@ class PolarsDataframeSerializer:
|
|
|
348
352
|
if tags and default_tags:
|
|
349
353
|
tags += ","
|
|
350
354
|
tags += default_tags
|
|
351
|
-
|
|
352
|
-
|
|
353
355
|
|
|
354
|
-
|
|
355
356
|
# add escape symbols for special characters to tags
|
|
356
357
|
|
|
357
358
|
fields = ",".join(
|
|
358
|
-
f"{col}=\"{self.escape_value(row[self.column_indices[col]])}\"" if isinstance(row[self.column_indices[col]],
|
|
359
|
-
|
|
359
|
+
f"{col}=\"{self.escape_value(row[self.column_indices[col]])}\"" if isinstance(row[self.column_indices[col]],
|
|
360
|
+
str)
|
|
361
|
+
else f"{col}={str(row[self.column_indices[col]]).lower()}" if isinstance(row[self.column_indices[col]],
|
|
362
|
+
bool) # Check for bool first
|
|
360
363
|
else f"{col}={row[self.column_indices[col]]}i" if isinstance(row[self.column_indices[col]], int)
|
|
361
364
|
else f"{col}={row[self.column_indices[col]]}"
|
|
362
365
|
for col in self.column_indices
|
|
363
|
-
if col not in self.tag_columns + [self.timestamp_column]
|
|
364
|
-
|
|
366
|
+
if col not in self.tag_columns + [self.timestamp_column] and
|
|
367
|
+
row[self.column_indices[col]] is not None and row[self.column_indices[col]] != ""
|
|
365
368
|
)
|
|
366
369
|
|
|
367
|
-
|
|
368
370
|
# Access the Unix timestamp
|
|
369
371
|
timestamp = row[self.column_indices[self.timestamp_column]]
|
|
370
372
|
if tags != "":
|
|
@@ -374,10 +376,9 @@ class PolarsDataframeSerializer:
|
|
|
374
376
|
|
|
375
377
|
return line_protocol
|
|
376
378
|
|
|
377
|
-
|
|
378
379
|
def serialize(self, chunk_idx: int = None):
|
|
379
380
|
from ...extras import pl
|
|
380
|
-
|
|
381
|
+
|
|
381
382
|
df = self.data_frame
|
|
382
383
|
|
|
383
384
|
# Check if the timestamp column is already an integer
|
|
@@ -387,16 +388,19 @@ class PolarsDataframeSerializer:
|
|
|
387
388
|
else:
|
|
388
389
|
# Convert timestamp to Unix timestamp based on specified precision
|
|
389
390
|
if self.precision in [None, 'ns']:
|
|
390
|
-
df = df.with_columns(
|
|
391
|
+
df = df.with_columns(
|
|
392
|
+
pl.col(self.timestamp_column).dt.epoch(time_unit="ns").alias(self.timestamp_column))
|
|
391
393
|
elif self.precision == 'us':
|
|
392
|
-
df = df.with_columns(
|
|
394
|
+
df = df.with_columns(
|
|
395
|
+
pl.col(self.timestamp_column).dt.epoch(time_unit="us").alias(self.timestamp_column))
|
|
393
396
|
elif self.precision == 'ms':
|
|
394
|
-
df = df.with_columns(
|
|
397
|
+
df = df.with_columns(
|
|
398
|
+
pl.col(self.timestamp_column).dt.epoch(time_unit="ms").alias(self.timestamp_column))
|
|
395
399
|
elif self.precision == 's':
|
|
396
400
|
df = df.with_columns(pl.col(self.timestamp_column).dt.epoch(time_unit="s").alias(self.timestamp_column))
|
|
397
401
|
else:
|
|
398
402
|
raise ValueError(f"Unsupported precision: {self.precision}")
|
|
399
|
-
|
|
403
|
+
|
|
400
404
|
if chunk_idx is None:
|
|
401
405
|
chunk = df
|
|
402
406
|
else:
|
|
@@ -404,18 +408,13 @@ class PolarsDataframeSerializer:
|
|
|
404
408
|
chunk = df[chunk_idx * self.chunk_size:(chunk_idx + 1) * self.chunk_size]
|
|
405
409
|
|
|
406
410
|
# Apply the UDF to each row
|
|
407
|
-
line_protocol_expr = chunk.apply(self.to_line_protocol,return_dtype=pl.Object)
|
|
411
|
+
line_protocol_expr = chunk.apply(self.to_line_protocol, return_dtype=pl.Object)
|
|
408
412
|
|
|
409
413
|
lp = line_protocol_expr['map'].to_list()
|
|
410
414
|
|
|
411
|
-
|
|
412
415
|
return lp
|
|
413
416
|
|
|
414
417
|
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
418
|
def data_frame_to_list_of_points(data_frame, point_settings, precision=DEFAULT_WRITE_PRECISION, **kwargs):
|
|
420
419
|
"""
|
|
421
420
|
Serialize DataFrame into LineProtocols.
|
|
@@ -432,6 +431,7 @@ def data_frame_to_list_of_points(data_frame, point_settings, precision=DEFAULT_W
|
|
|
432
431
|
""" # noqa: E501
|
|
433
432
|
return DataframeSerializer(data_frame, point_settings, precision, **kwargs).serialize()
|
|
434
433
|
|
|
434
|
+
|
|
435
435
|
def polars_data_frame_to_list_of_points(data_frame, point_settings, precision=DEFAULT_WRITE_PRECISION, **kwargs):
|
|
436
436
|
"""
|
|
437
437
|
Serialize DataFrame into LineProtocols.
|
|
@@ -446,4 +446,4 @@ def polars_data_frame_to_list_of_points(data_frame, point_settings, precision=DE
|
|
|
446
446
|
or other formats and types supported by `pandas.to_datetime <https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.to_datetime.html#pandas.to_datetime>`_ - ``DataFrame``
|
|
447
447
|
:key data_frame_timestamp_timezone: name of the timezone which is used for timestamp column - ``DataFrame``
|
|
448
448
|
""" # noqa: E501
|
|
449
|
-
return PolarsDataframeSerializer(data_frame, point_settings, precision, **kwargs).serialize()
|
|
449
|
+
return PolarsDataframeSerializer(data_frame, point_settings, precision, **kwargs).serialize()
|
{influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/client/write_api.py
RENAMED
|
@@ -19,14 +19,14 @@ from reactivex.subject import Subject
|
|
|
19
19
|
from influxdb_client_3.write_client.domain import WritePrecision
|
|
20
20
|
from influxdb_client_3.write_client.client._base import _BaseWriteApi, _HAS_DATACLASS
|
|
21
21
|
from influxdb_client_3.write_client.client.util.helpers import get_org_query_param
|
|
22
|
-
from influxdb_client_3.write_client.client.write.dataframe_serializer import DataframeSerializer,
|
|
22
|
+
from influxdb_client_3.write_client.client.write.dataframe_serializer import (DataframeSerializer,
|
|
23
|
+
PolarsDataframeSerializer)
|
|
23
24
|
from influxdb_client_3.write_client.client.write.point import Point, DEFAULT_WRITE_PRECISION
|
|
24
25
|
from influxdb_client_3.write_client.client.write.retry import WritesRetry
|
|
25
26
|
from influxdb_client_3.write_client.rest import _UTF_8_encoding
|
|
26
27
|
|
|
27
28
|
logger = logging.getLogger('influxdb_client_3.write_client.client.write_api')
|
|
28
29
|
|
|
29
|
-
|
|
30
30
|
if _HAS_DATACLASS:
|
|
31
31
|
import dataclasses
|
|
32
32
|
from dataclasses import dataclass
|
|
@@ -460,10 +460,11 @@ You can use native asynchronous version of the client:
|
|
|
460
460
|
elif isinstance(data, dict):
|
|
461
461
|
self._write_batching(bucket, org, Point.from_dict(data, write_precision=precision, **kwargs),
|
|
462
462
|
precision, **kwargs)
|
|
463
|
-
|
|
463
|
+
|
|
464
464
|
elif 'polars' in str(type(data)):
|
|
465
|
-
serializer = PolarsDataframeSerializer(data,
|
|
466
|
-
|
|
465
|
+
serializer = PolarsDataframeSerializer(data,
|
|
466
|
+
self._point_settings, precision,
|
|
467
|
+
self._write_options.batch_size, **kwargs)
|
|
467
468
|
for chunk_idx in range(serializer.number_of_chunks):
|
|
468
469
|
self._write_batching(bucket, org,
|
|
469
470
|
serializer.serialize(chunk_idx),
|
|
@@ -477,7 +478,6 @@ You can use native asynchronous version of the client:
|
|
|
477
478
|
serializer.serialize(chunk_idx),
|
|
478
479
|
precision, **kwargs)
|
|
479
480
|
|
|
480
|
-
|
|
481
481
|
elif hasattr(data, "_asdict"):
|
|
482
482
|
# noinspection PyProtectedMember
|
|
483
483
|
self._write_batching(bucket, org, data._asdict(), precision, **kwargs)
|
|
@@ -47,14 +47,15 @@ setup(
|
|
|
47
47
|
packages=find_packages(exclude=['tests', 'tests.*', 'examples', 'examples.*']),
|
|
48
48
|
extras_require={'pandas': ['pandas'], 'polars': ['polars'], 'dataframe': ['pandas', 'polars']},
|
|
49
49
|
install_requires=requires,
|
|
50
|
-
python_requires='>=3.
|
|
50
|
+
python_requires='>=3.8',
|
|
51
51
|
classifiers=[
|
|
52
52
|
'Development Status :: 4 - Beta',
|
|
53
53
|
'Intended Audience :: Developers',
|
|
54
54
|
'License :: OSI Approved :: MIT License',
|
|
55
|
-
'Programming Language :: Python :: 3.7',
|
|
56
55
|
'Programming Language :: Python :: 3.8',
|
|
57
56
|
'Programming Language :: Python :: 3.9',
|
|
58
57
|
'Programming Language :: Python :: 3.10',
|
|
58
|
+
'Programming Language :: Python :: 3.11',
|
|
59
|
+
'Programming Language :: Python :: 3.12',
|
|
59
60
|
]
|
|
60
|
-
)
|
|
61
|
+
)
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
|
|
3
|
+
from influxdb_client_3 import PointSettings
|
|
4
|
+
from influxdb_client_3.write_client.client.write.dataframe_serializer import DataframeSerializer
|
|
5
|
+
import pandas as pd
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class TestDataFrameSerializer(unittest.TestCase):
|
|
9
|
+
|
|
10
|
+
def test_nullable_types(self):
|
|
11
|
+
df = pd.DataFrame({
|
|
12
|
+
"bool_nulls": [True, None, False],
|
|
13
|
+
"int_nulls": [None, 1, 2],
|
|
14
|
+
"float_nulls": [1.0, 2.0, None],
|
|
15
|
+
"str_nulls": ["a", "b", None],
|
|
16
|
+
})
|
|
17
|
+
df['bool_nulls_pd'] = df['bool_nulls'].astype(pd.BooleanDtype())
|
|
18
|
+
df['int_nulls_pd'] = df['int_nulls'].astype(pd.Int64Dtype())
|
|
19
|
+
df['float_nulls_pd'] = df['float_nulls'].astype(pd.Float64Dtype())
|
|
20
|
+
df['str_nulls_pd'] = df['str_nulls'].astype(pd.StringDtype())
|
|
21
|
+
|
|
22
|
+
df.index = pd.to_datetime(["2021-01-01", "2021-01-02", "2021-01-03"])
|
|
23
|
+
|
|
24
|
+
ps = PointSettings()
|
|
25
|
+
|
|
26
|
+
serializer = DataframeSerializer(df, ps, data_frame_measurement_name="test")
|
|
27
|
+
|
|
28
|
+
lines = serializer.serialize()
|
|
29
|
+
|
|
30
|
+
# make sure there are no `<NA>` values in the serialized lines
|
|
31
|
+
# first line should not have "int"
|
|
32
|
+
first_line = lines[0]
|
|
33
|
+
self.assertNotIn('<NA>', first_line)
|
|
34
|
+
self.assertNotIn('int_nulls', first_line)
|
|
35
|
+
|
|
36
|
+
# the second line should not have "bool"
|
|
37
|
+
second_line = lines[1]
|
|
38
|
+
self.assertNotIn('<NA>', second_line)
|
|
39
|
+
self.assertNotIn('bool_nulls', second_line)
|
|
40
|
+
|
|
41
|
+
# the third line should not have "str" or "float"
|
|
42
|
+
third_line = lines[2]
|
|
43
|
+
self.assertNotIn('<NA>', third_line)
|
|
44
|
+
self.assertNotIn('str_nulls', third_line)
|
|
45
|
+
self.assertNotIn('float_nulls', third_line)
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import unittest
|
|
2
|
-
from unittest.mock import patch
|
|
2
|
+
from unittest.mock import patch
|
|
3
|
+
|
|
3
4
|
from influxdb_client_3 import InfluxDBClient3
|
|
4
5
|
|
|
6
|
+
|
|
5
7
|
class TestInfluxDBClient3(unittest.TestCase):
|
|
6
8
|
|
|
7
9
|
@patch('influxdb_client_3._InfluxDBClient')
|
|
@@ -25,14 +27,6 @@ class TestInfluxDBClient3(unittest.TestCase):
|
|
|
25
27
|
self.assertEqual(self.client._write_api, self.mock_write_api.return_value)
|
|
26
28
|
self.assertEqual(self.client._flight_client, self.mock_flight_client.return_value)
|
|
27
29
|
|
|
28
|
-
@patch('influxdb_client_3._WriteApi.write')
|
|
29
|
-
def test_write(self, mock_write):
|
|
30
|
-
record = "test_record"
|
|
31
|
-
self.client.write(record=record)
|
|
32
|
-
mock_write.assert_called_once_with(bucket=self.client._database, record=record)
|
|
33
|
-
|
|
34
|
-
# Add more tests for other methods
|
|
35
|
-
|
|
36
30
|
|
|
37
31
|
if __name__ == '__main__':
|
|
38
|
-
unittest.main()
|
|
32
|
+
unittest.main()
|
|
File without changes
|
{influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/influxdb3_python.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/__init__.py
RENAMED
|
File without changes
|
{influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/_sync/__init__.py
RENAMED
|
File without changes
|
{influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/_sync/rest.py
RENAMED
|
File without changes
|
{influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/client/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/client/warnings.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/configuration.py
RENAMED
|
File without changes
|
{influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/domain/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{influxdb3-python-0.3.6 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/service/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|