influxdb3-python 0.3.5__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.5 → influxdb3_python-0.4.0}/PKG-INFO +11 -7
- {influxdb3-python-0.3.5 → influxdb3_python-0.4.0}/README.md +7 -4
- {influxdb3-python-0.3.5 → influxdb3_python-0.4.0}/influxdb3_python.egg-info/PKG-INFO +11 -7
- {influxdb3-python-0.3.5 → influxdb3_python-0.4.0}/influxdb3_python.egg-info/SOURCES.txt +1 -0
- {influxdb3-python-0.3.5 → influxdb3_python-0.4.0}/influxdb_client_3/__init__.py +34 -27
- {influxdb3-python-0.3.5 → influxdb3_python-0.4.0}/influxdb_client_3/read_file.py +6 -4
- {influxdb3-python-0.3.5 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/_sync/api_client.py +8 -8
- {influxdb3-python-0.3.5 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/client/_base.py +10 -10
- {influxdb3-python-0.3.5 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/client/influxdb_client.py +0 -8
- {influxdb3-python-0.3.5 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/client/write/dataframe_serializer.py +60 -52
- {influxdb3-python-0.3.5 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/client/write_api.py +6 -6
- {influxdb3-python-0.3.5 → 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.5 → influxdb3_python-0.4.0}/tests/test_influxdb_client_3.py +4 -10
- {influxdb3-python-0.3.5 → influxdb3_python-0.4.0}/LICENSE +0 -0
- {influxdb3-python-0.3.5 → influxdb3_python-0.4.0}/influxdb3_python.egg-info/dependency_links.txt +0 -0
- {influxdb3-python-0.3.5 → influxdb3_python-0.4.0}/influxdb3_python.egg-info/requires.txt +0 -0
- {influxdb3-python-0.3.5 → influxdb3_python-0.4.0}/influxdb3_python.egg-info/top_level.txt +0 -0
- {influxdb3-python-0.3.5 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/__init__.py +0 -0
- {influxdb3-python-0.3.5 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/_sync/__init__.py +0 -0
- {influxdb3-python-0.3.5 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/_sync/rest.py +0 -0
- {influxdb3-python-0.3.5 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/client/__init__.py +0 -0
- {influxdb3-python-0.3.5 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/client/exceptions.py +0 -0
- {influxdb3-python-0.3.5 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/client/logging_handler.py +0 -0
- {influxdb3-python-0.3.5 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/client/util/__init__.py +0 -0
- {influxdb3-python-0.3.5 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/client/util/date_utils.py +0 -0
- {influxdb3-python-0.3.5 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/client/util/date_utils_pandas.py +0 -0
- {influxdb3-python-0.3.5 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/client/util/helpers.py +0 -0
- {influxdb3-python-0.3.5 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/client/util/multiprocessing_helper.py +0 -0
- {influxdb3-python-0.3.5 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/client/warnings.py +0 -0
- {influxdb3-python-0.3.5 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/client/write/__init__.py +0 -0
- {influxdb3-python-0.3.5 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/client/write/point.py +0 -0
- {influxdb3-python-0.3.5 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/client/write/retry.py +0 -0
- {influxdb3-python-0.3.5 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/configuration.py +0 -0
- {influxdb3-python-0.3.5 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/domain/__init__.py +0 -0
- {influxdb3-python-0.3.5 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/domain/write_precision.py +0 -0
- {influxdb3-python-0.3.5 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/extras.py +0 -0
- {influxdb3-python-0.3.5 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/rest.py +0 -0
- {influxdb3-python-0.3.5 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/service/__init__.py +0 -0
- {influxdb3-python-0.3.5 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/service/_base_service.py +0 -0
- {influxdb3-python-0.3.5 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/service/signin_service.py +0 -0
- {influxdb3-python-0.3.5 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/service/signout_service.py +0 -0
- {influxdb3-python-0.3.5 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/service/write_service.py +0 -0
- {influxdb3-python-0.3.5 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/version.py +0 -0
- {influxdb3-python-0.3.5 → 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.5 → 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.5 → 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
|
|
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
|
|
@@ -252,9 +248,14 @@ class _BaseWriteApi(object):
|
|
|
252
248
|
elif isinstance(record, dict):
|
|
253
249
|
self._serialize(Point.from_dict(record, write_precision=write_precision, **kwargs),
|
|
254
250
|
write_precision, payload, **kwargs)
|
|
255
|
-
elif '
|
|
251
|
+
elif 'polars' in str(type(record)):
|
|
252
|
+
serializer = PolarsDataframeSerializer(record, self._point_settings, write_precision, **kwargs)
|
|
253
|
+
self._serialize(serializer.serialize(), write_precision, payload, **kwargs)
|
|
254
|
+
|
|
255
|
+
elif 'pandas' in str(type(record)):
|
|
256
256
|
serializer = DataframeSerializer(record, self._point_settings, write_precision, **kwargs)
|
|
257
257
|
self._serialize(serializer.serialize(), write_precision, payload, **kwargs)
|
|
258
|
+
|
|
258
259
|
elif hasattr(record, "_asdict"):
|
|
259
260
|
# noinspection PyProtectedMember
|
|
260
261
|
self._serialize(record._asdict(), write_precision, payload, **kwargs)
|
|
@@ -265,7 +266,6 @@ class _BaseWriteApi(object):
|
|
|
265
266
|
self._serialize(item, write_precision, payload, **kwargs)
|
|
266
267
|
|
|
267
268
|
|
|
268
|
-
|
|
269
269
|
class _Configuration(Configuration):
|
|
270
270
|
def __init__(self):
|
|
271
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,43 +326,45 @@ class PolarsDataframeSerializer:
|
|
|
321
326
|
self.chunk_size = chunk_size
|
|
322
327
|
else:
|
|
323
328
|
self.number_of_chunks = None
|
|
324
|
-
|
|
325
|
-
def
|
|
329
|
+
|
|
330
|
+
def escape_key(self, value):
|
|
326
331
|
return str(value).translate(_ESCAPE_KEY)
|
|
327
332
|
|
|
328
|
-
|
|
333
|
+
def escape_value(self, value):
|
|
334
|
+
return str(value).translate(_ESCAPE_STRING)
|
|
335
|
+
|
|
329
336
|
def to_line_protocol(self, row):
|
|
330
337
|
# Filter out None or empty values for tags
|
|
331
338
|
tags = ""
|
|
332
|
-
|
|
339
|
+
|
|
333
340
|
tags = ",".join(
|
|
334
|
-
f'{self.
|
|
341
|
+
f'{self.escape_key(col)}={self.escape_key(row[self.column_indices[col]])}'
|
|
335
342
|
for col in self.tag_columns
|
|
336
343
|
if row[self.column_indices[col]] is not None and row[self.column_indices[col]] != ""
|
|
337
344
|
)
|
|
338
345
|
|
|
339
346
|
if self.point_settings.defaultTags:
|
|
340
347
|
default_tags = ",".join(
|
|
341
|
-
f'{self.
|
|
348
|
+
f'{self.escape_key(key)}={self.escape_key(value)}'
|
|
342
349
|
for key, value in self.point_settings.defaultTags.items()
|
|
343
350
|
)
|
|
344
351
|
# Ensure there's a comma between existing tags and default tags if both are present
|
|
345
352
|
if tags and default_tags:
|
|
346
353
|
tags += ","
|
|
347
354
|
tags += default_tags
|
|
348
|
-
|
|
349
|
-
|
|
350
355
|
|
|
351
|
-
|
|
352
356
|
# add escape symbols for special characters to tags
|
|
353
357
|
|
|
354
358
|
fields = ",".join(
|
|
355
|
-
f"{col}=\"{row[self.column_indices[col]]}\"" if isinstance(row[self.column_indices[col]],
|
|
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
|
|
356
363
|
else f"{col}={row[self.column_indices[col]]}i" if isinstance(row[self.column_indices[col]], int)
|
|
357
364
|
else f"{col}={row[self.column_indices[col]]}"
|
|
358
365
|
for col in self.column_indices
|
|
359
|
-
if col not in self.tag_columns + [self.timestamp_column]
|
|
360
|
-
|
|
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]] != ""
|
|
361
368
|
)
|
|
362
369
|
|
|
363
370
|
# Access the Unix timestamp
|
|
@@ -369,26 +376,31 @@ class PolarsDataframeSerializer:
|
|
|
369
376
|
|
|
370
377
|
return line_protocol
|
|
371
378
|
|
|
372
|
-
|
|
373
379
|
def serialize(self, chunk_idx: int = None):
|
|
374
380
|
from ...extras import pl
|
|
375
|
-
|
|
381
|
+
|
|
376
382
|
df = self.data_frame
|
|
377
383
|
|
|
378
|
-
#
|
|
379
|
-
if self.
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
df = df.with_columns(pl.col(self.timestamp_column).dt.epoch(time_unit="ns").alias(self.timestamp_column))
|
|
383
|
-
elif self.precision == 'us':
|
|
384
|
-
df = df.with_columns(pl.col(self.timestamp_column).dt.epoch(time_unit="us").alias(self.timestamp_column))
|
|
385
|
-
elif self.precision == 'ms':
|
|
386
|
-
df = df.with_columns(pl.col(self.timestamp_column).dt.epoch(time_unit="ms").alias(self.timestamp_column))
|
|
387
|
-
elif self.precision == 's':
|
|
388
|
-
df = df.with_columns(pl.col(self.timestamp_column).dt.epoch(time_unit="s").alias(self.timestamp_column))
|
|
384
|
+
# Check if the timestamp column is already an integer
|
|
385
|
+
if df[self.timestamp_column].dtype in [pl.Int32, pl.Int64]:
|
|
386
|
+
# The timestamp column is already an integer, assuming it's in Unix format
|
|
387
|
+
pass
|
|
389
388
|
else:
|
|
390
|
-
|
|
391
|
-
|
|
389
|
+
# Convert timestamp to Unix timestamp based on specified precision
|
|
390
|
+
if self.precision in [None, 'ns']:
|
|
391
|
+
df = df.with_columns(
|
|
392
|
+
pl.col(self.timestamp_column).dt.epoch(time_unit="ns").alias(self.timestamp_column))
|
|
393
|
+
elif self.precision == 'us':
|
|
394
|
+
df = df.with_columns(
|
|
395
|
+
pl.col(self.timestamp_column).dt.epoch(time_unit="us").alias(self.timestamp_column))
|
|
396
|
+
elif self.precision == 'ms':
|
|
397
|
+
df = df.with_columns(
|
|
398
|
+
pl.col(self.timestamp_column).dt.epoch(time_unit="ms").alias(self.timestamp_column))
|
|
399
|
+
elif self.precision == 's':
|
|
400
|
+
df = df.with_columns(pl.col(self.timestamp_column).dt.epoch(time_unit="s").alias(self.timestamp_column))
|
|
401
|
+
else:
|
|
402
|
+
raise ValueError(f"Unsupported precision: {self.precision}")
|
|
403
|
+
|
|
392
404
|
if chunk_idx is None:
|
|
393
405
|
chunk = df
|
|
394
406
|
else:
|
|
@@ -396,18 +408,13 @@ class PolarsDataframeSerializer:
|
|
|
396
408
|
chunk = df[chunk_idx * self.chunk_size:(chunk_idx + 1) * self.chunk_size]
|
|
397
409
|
|
|
398
410
|
# Apply the UDF to each row
|
|
399
|
-
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)
|
|
400
412
|
|
|
401
413
|
lp = line_protocol_expr['map'].to_list()
|
|
402
414
|
|
|
403
|
-
|
|
404
415
|
return lp
|
|
405
416
|
|
|
406
417
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
418
|
def data_frame_to_list_of_points(data_frame, point_settings, precision=DEFAULT_WRITE_PRECISION, **kwargs):
|
|
412
419
|
"""
|
|
413
420
|
Serialize DataFrame into LineProtocols.
|
|
@@ -424,6 +431,7 @@ def data_frame_to_list_of_points(data_frame, point_settings, precision=DEFAULT_W
|
|
|
424
431
|
""" # noqa: E501
|
|
425
432
|
return DataframeSerializer(data_frame, point_settings, precision, **kwargs).serialize()
|
|
426
433
|
|
|
434
|
+
|
|
427
435
|
def polars_data_frame_to_list_of_points(data_frame, point_settings, precision=DEFAULT_WRITE_PRECISION, **kwargs):
|
|
428
436
|
"""
|
|
429
437
|
Serialize DataFrame into LineProtocols.
|
|
@@ -438,4 +446,4 @@ def polars_data_frame_to_list_of_points(data_frame, point_settings, precision=DE
|
|
|
438
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``
|
|
439
447
|
:key data_frame_timestamp_timezone: name of the timezone which is used for timestamp column - ``DataFrame``
|
|
440
448
|
""" # noqa: E501
|
|
441
|
-
return PolarsDataframeSerializer(data_frame, point_settings, precision, **kwargs).serialize()
|
|
449
|
+
return PolarsDataframeSerializer(data_frame, point_settings, precision, **kwargs).serialize()
|
{influxdb3-python-0.3.5 → 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.5 → 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.5 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/__init__.py
RENAMED
|
File without changes
|
{influxdb3-python-0.3.5 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/_sync/__init__.py
RENAMED
|
File without changes
|
{influxdb3-python-0.3.5 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/_sync/rest.py
RENAMED
|
File without changes
|
{influxdb3-python-0.3.5 → 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.5 → 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.5 → influxdb3_python-0.4.0}/influxdb_client_3/write_client/configuration.py
RENAMED
|
File without changes
|
{influxdb3-python-0.3.5 → 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.5 → 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
|