influxdb3-python 0.5.0__tar.gz → 0.6.1__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.5.0 → influxdb3_python-0.6.1}/PKG-INFO +1 -1
- {influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/influxdb3_python.egg-info/PKG-INFO +1 -1
- {influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/influxdb3_python.egg-info/SOURCES.txt +6 -1
- {influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/influxdb_client_3/__init__.py +12 -47
- influxdb3_python-0.6.1/influxdb_client_3/query/__init__.py +1 -0
- influxdb3_python-0.6.1/influxdb_client_3/query/query_api.py +104 -0
- {influxdb3_python-0.5.0/influxdb_client_3/write_client → influxdb3_python-0.6.1/influxdb_client_3}/version.py +2 -1
- {influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/influxdb_client_3/write_client/__init__.py +1 -1
- {influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/influxdb_client_3/write_client/_sync/api_client.py +2 -2
- {influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/influxdb_client_3/write_client/client/util/date_utils.py +5 -1
- {influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/influxdb_client_3/write_client/client/write/point.py +1 -1
- influxdb3_python-0.6.1/tests/test_api_client.py +71 -0
- influxdb3_python-0.6.1/tests/test_date_helper.py +21 -0
- {influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/tests/test_influxdb_client_3.py +4 -4
- {influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/tests/test_influxdb_client_3_integration.py +1 -0
- {influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/tests/test_merge_options.py +1 -1
- influxdb3_python-0.6.1/tests/test_point.py +14 -0
- influxdb3_python-0.6.1/tests/test_query.py +152 -0
- influxdb3_python-0.5.0/tests/test_query.py +0 -53
- {influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/LICENSE +0 -0
- {influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/README.md +0 -0
- {influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/influxdb3_python.egg-info/dependency_links.txt +0 -0
- {influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/influxdb3_python.egg-info/requires.txt +0 -0
- {influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/influxdb3_python.egg-info/top_level.txt +0 -0
- {influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/influxdb_client_3/py.typed +0 -0
- {influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/influxdb_client_3/read_file.py +0 -0
- {influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/influxdb_client_3/write_client/_sync/__init__.py +0 -0
- {influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/influxdb_client_3/write_client/_sync/rest.py +0 -0
- {influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/influxdb_client_3/write_client/client/__init__.py +0 -0
- {influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/influxdb_client_3/write_client/client/_base.py +0 -0
- {influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/influxdb_client_3/write_client/client/exceptions.py +0 -0
- {influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/influxdb_client_3/write_client/client/influxdb_client.py +0 -0
- {influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/influxdb_client_3/write_client/client/logging_handler.py +0 -0
- {influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/influxdb_client_3/write_client/client/util/__init__.py +0 -0
- {influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/influxdb_client_3/write_client/client/util/date_utils_pandas.py +0 -0
- {influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/influxdb_client_3/write_client/client/util/helpers.py +0 -0
- {influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/influxdb_client_3/write_client/client/util/multiprocessing_helper.py +0 -0
- {influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/influxdb_client_3/write_client/client/warnings.py +0 -0
- {influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/influxdb_client_3/write_client/client/write/__init__.py +0 -0
- {influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/influxdb_client_3/write_client/client/write/dataframe_serializer.py +0 -0
- {influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/influxdb_client_3/write_client/client/write/retry.py +0 -0
- {influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/influxdb_client_3/write_client/client/write_api.py +0 -0
- {influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/influxdb_client_3/write_client/configuration.py +0 -0
- {influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/influxdb_client_3/write_client/domain/__init__.py +0 -0
- {influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/influxdb_client_3/write_client/domain/write_precision.py +0 -0
- {influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/influxdb_client_3/write_client/extras.py +0 -0
- {influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/influxdb_client_3/write_client/rest.py +0 -0
- {influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/influxdb_client_3/write_client/service/__init__.py +0 -0
- {influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/influxdb_client_3/write_client/service/_base_service.py +0 -0
- {influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/influxdb_client_3/write_client/service/signin_service.py +0 -0
- {influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/influxdb_client_3/write_client/service/signout_service.py +0 -0
- {influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/influxdb_client_3/write_client/service/write_service.py +0 -0
- {influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/setup.cfg +0 -0
- {influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/setup.py +0 -0
- {influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/tests/test_dataframe_serializer.py +0 -0
- {influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/tests/test_deep_merge.py +0 -0
|
@@ -9,11 +9,13 @@ influxdb3_python.egg-info/top_level.txt
|
|
|
9
9
|
influxdb_client_3/__init__.py
|
|
10
10
|
influxdb_client_3/py.typed
|
|
11
11
|
influxdb_client_3/read_file.py
|
|
12
|
+
influxdb_client_3/version.py
|
|
13
|
+
influxdb_client_3/query/__init__.py
|
|
14
|
+
influxdb_client_3/query/query_api.py
|
|
12
15
|
influxdb_client_3/write_client/__init__.py
|
|
13
16
|
influxdb_client_3/write_client/configuration.py
|
|
14
17
|
influxdb_client_3/write_client/extras.py
|
|
15
18
|
influxdb_client_3/write_client/rest.py
|
|
16
|
-
influxdb_client_3/write_client/version.py
|
|
17
19
|
influxdb_client_3/write_client/_sync/__init__.py
|
|
18
20
|
influxdb_client_3/write_client/_sync/api_client.py
|
|
19
21
|
influxdb_client_3/write_client/_sync/rest.py
|
|
@@ -40,9 +42,12 @@ influxdb_client_3/write_client/service/_base_service.py
|
|
|
40
42
|
influxdb_client_3/write_client/service/signin_service.py
|
|
41
43
|
influxdb_client_3/write_client/service/signout_service.py
|
|
42
44
|
influxdb_client_3/write_client/service/write_service.py
|
|
45
|
+
tests/test_api_client.py
|
|
43
46
|
tests/test_dataframe_serializer.py
|
|
47
|
+
tests/test_date_helper.py
|
|
44
48
|
tests/test_deep_merge.py
|
|
45
49
|
tests/test_influxdb_client_3.py
|
|
46
50
|
tests/test_influxdb_client_3_integration.py
|
|
47
51
|
tests/test_merge_options.py
|
|
52
|
+
tests/test_point.py
|
|
48
53
|
tests/test_query.py
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import json
|
|
2
1
|
import urllib.parse
|
|
3
2
|
|
|
4
3
|
import pyarrow as pa
|
|
5
|
-
|
|
4
|
+
import importlib.util
|
|
6
5
|
|
|
6
|
+
from influxdb_client_3.query.query_api import QueryApi as _QueryApi
|
|
7
7
|
from influxdb_client_3.read_file import UploadFile
|
|
8
8
|
from influxdb_client_3.write_client import InfluxDBClient as _InfluxDBClient, WriteOptions, Point
|
|
9
9
|
from influxdb_client_3.write_client.client.exceptions import InfluxDBError
|
|
@@ -11,12 +11,7 @@ from influxdb_client_3.write_client.client.write_api import WriteApi as _WriteAp
|
|
|
11
11
|
PointSettings
|
|
12
12
|
from influxdb_client_3.write_client.domain.write_precision import WritePrecision
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
import polars as pl
|
|
16
|
-
|
|
17
|
-
polars = True
|
|
18
|
-
except ImportError:
|
|
19
|
-
polars = False
|
|
14
|
+
polars = importlib.util.find_spec("polars") is not None
|
|
20
15
|
|
|
21
16
|
|
|
22
17
|
def write_client_options(**kwargs):
|
|
@@ -143,11 +138,15 @@ class InfluxDBClient3:
|
|
|
143
138
|
**kwargs)
|
|
144
139
|
|
|
145
140
|
self._write_api = _WriteApi(influxdb_client=self._client, **self._write_client_options)
|
|
146
|
-
self._flight_client_options = flight_client_options or {}
|
|
147
141
|
|
|
148
142
|
if query_port_overwrite is not None:
|
|
149
143
|
port = query_port_overwrite
|
|
150
|
-
|
|
144
|
+
if scheme == 'https':
|
|
145
|
+
connection_string = f"grpc+tls://{hostname}:{port}"
|
|
146
|
+
else:
|
|
147
|
+
connection_string = f"grpc+tcp://{hostname}:{port}"
|
|
148
|
+
self._query_api = _QueryApi(connection_string=connection_string, token=token,
|
|
149
|
+
flight_client_options=flight_client_options)
|
|
151
150
|
|
|
152
151
|
def write(self, record=None, database=None, **kwargs):
|
|
153
152
|
"""
|
|
@@ -245,48 +244,14 @@ class InfluxDBClient3:
|
|
|
245
244
|
database = self._database
|
|
246
245
|
|
|
247
246
|
try:
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
"headers": [(b"authorization", f"Bearer {self._token}".encode('utf-8'))],
|
|
251
|
-
"timeout": 300
|
|
252
|
-
}
|
|
253
|
-
opts = _merge_options(optargs, exclude_keys=['query_parameters'], custom=kwargs)
|
|
254
|
-
_options = FlightCallOptions(**opts)
|
|
255
|
-
|
|
256
|
-
#
|
|
257
|
-
# Ticket data
|
|
258
|
-
#
|
|
259
|
-
ticket_data = {
|
|
260
|
-
"database": database,
|
|
261
|
-
"sql_query": query,
|
|
262
|
-
"query_type": language
|
|
263
|
-
}
|
|
264
|
-
# add query parameters
|
|
265
|
-
query_parameters = kwargs.get("query_parameters", None)
|
|
266
|
-
if query_parameters:
|
|
267
|
-
ticket_data["params"] = query_parameters
|
|
268
|
-
|
|
269
|
-
ticket = Ticket(json.dumps(ticket_data).encode('utf-8'))
|
|
270
|
-
flight_reader = self._flight_client.do_get(ticket, _options)
|
|
271
|
-
|
|
272
|
-
mode_func = {
|
|
273
|
-
"all": flight_reader.read_all,
|
|
274
|
-
"pandas": flight_reader.read_pandas,
|
|
275
|
-
"polars": lambda: pl.from_arrow(flight_reader.read_all()),
|
|
276
|
-
"chunk": lambda: flight_reader,
|
|
277
|
-
"reader": flight_reader.to_reader,
|
|
278
|
-
"schema": lambda: flight_reader.schema
|
|
279
|
-
|
|
280
|
-
}.get(mode, flight_reader.read_all)
|
|
281
|
-
|
|
282
|
-
return mode_func() if callable(mode_func) else mode_func
|
|
283
|
-
except Exception as e:
|
|
247
|
+
return self._query_api.query(query=query, language=language, mode=mode, database=database, **kwargs)
|
|
248
|
+
except InfluxDBError as e:
|
|
284
249
|
raise e
|
|
285
250
|
|
|
286
251
|
def close(self):
|
|
287
252
|
"""Close the client and clean up resources."""
|
|
288
253
|
self._write_api.close()
|
|
289
|
-
self.
|
|
254
|
+
self._query_api.close()
|
|
290
255
|
self._client.close()
|
|
291
256
|
|
|
292
257
|
def __enter__(self):
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Package for query module."""
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"""Query data in InfluxDB 3."""
|
|
2
|
+
|
|
3
|
+
# coding: utf-8
|
|
4
|
+
import json
|
|
5
|
+
|
|
6
|
+
from pyarrow.flight import FlightClient, Ticket, FlightCallOptions, FlightStreamReader
|
|
7
|
+
from influxdb_client_3.version import USER_AGENT
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class QueryApi(object):
|
|
11
|
+
"""
|
|
12
|
+
Implementation for '/api/v2/query' endpoint.
|
|
13
|
+
|
|
14
|
+
Example:
|
|
15
|
+
.. code-block:: python
|
|
16
|
+
|
|
17
|
+
from influxdb_client import InfluxDBClient
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
# Initialize instance of QueryApi
|
|
21
|
+
with InfluxDBClient(url="http://localhost:8086", token="my-token", org="my-org") as client:
|
|
22
|
+
query_api = client.query_api()
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
def __init__(self,
|
|
26
|
+
connection_string,
|
|
27
|
+
token,
|
|
28
|
+
flight_client_options) -> None:
|
|
29
|
+
"""
|
|
30
|
+
Initialize defaults.
|
|
31
|
+
|
|
32
|
+
:param connection_string: Flight/gRPC connection string
|
|
33
|
+
:param token: access token
|
|
34
|
+
:param flight_client_options: Flight client options
|
|
35
|
+
"""
|
|
36
|
+
self._token = token
|
|
37
|
+
self._flight_client_options = flight_client_options or {}
|
|
38
|
+
self._flight_client_options["generic_options"] = [
|
|
39
|
+
("grpc.secondary_user_agent", USER_AGENT)
|
|
40
|
+
]
|
|
41
|
+
self._flight_client = FlightClient(connection_string, **self._flight_client_options)
|
|
42
|
+
|
|
43
|
+
def query(self, query: str, language: str, mode: str, database: str, **kwargs):
|
|
44
|
+
"""Query data from InfluxDB.
|
|
45
|
+
|
|
46
|
+
:param query: The query to execute on the database.
|
|
47
|
+
:param language: The query language.
|
|
48
|
+
:param mode: The mode to use for the query.
|
|
49
|
+
It should be one of "all", "pandas", "polars", "chunk", "reader" or "schema".
|
|
50
|
+
:param database: The database to query from.
|
|
51
|
+
:param kwargs: Additional arguments to pass to the ``FlightCallOptions headers``.
|
|
52
|
+
For example, it can be used to set up per request headers.
|
|
53
|
+
:keyword query_parameters: The query parameters to use in the query.
|
|
54
|
+
It should be a ``dictionary`` of key-value pairs.
|
|
55
|
+
:return: The query result in the specified mode.
|
|
56
|
+
"""
|
|
57
|
+
from influxdb_client_3 import polars as has_polars, _merge_options as merge_options
|
|
58
|
+
try:
|
|
59
|
+
# Create an authorization header
|
|
60
|
+
optargs = {
|
|
61
|
+
"headers": [(b"authorization", f"Bearer {self._token}".encode('utf-8'))],
|
|
62
|
+
"timeout": 300
|
|
63
|
+
}
|
|
64
|
+
opts = merge_options(optargs, exclude_keys=['query_parameters'], custom=kwargs)
|
|
65
|
+
_options = FlightCallOptions(**opts)
|
|
66
|
+
|
|
67
|
+
#
|
|
68
|
+
# Ticket data
|
|
69
|
+
#
|
|
70
|
+
ticket_data = {
|
|
71
|
+
"database": database,
|
|
72
|
+
"sql_query": query,
|
|
73
|
+
"query_type": language
|
|
74
|
+
}
|
|
75
|
+
# add query parameters
|
|
76
|
+
query_parameters = kwargs.get("query_parameters", None)
|
|
77
|
+
if query_parameters:
|
|
78
|
+
ticket_data["params"] = query_parameters
|
|
79
|
+
|
|
80
|
+
ticket = Ticket(json.dumps(ticket_data).encode('utf-8'))
|
|
81
|
+
flight_reader = self._do_get(ticket, _options)
|
|
82
|
+
|
|
83
|
+
mode_funcs = {
|
|
84
|
+
"all": flight_reader.read_all,
|
|
85
|
+
"pandas": flight_reader.read_pandas,
|
|
86
|
+
"chunk": lambda: flight_reader,
|
|
87
|
+
"reader": flight_reader.to_reader,
|
|
88
|
+
"schema": lambda: flight_reader.schema
|
|
89
|
+
}
|
|
90
|
+
if has_polars:
|
|
91
|
+
import polars as pl
|
|
92
|
+
mode_funcs["polars"] = lambda: pl.from_arrow(flight_reader.read_all())
|
|
93
|
+
mode_func = mode_funcs.get(mode, flight_reader.read_all)
|
|
94
|
+
|
|
95
|
+
return mode_func() if callable(mode_func) else mode_func
|
|
96
|
+
except Exception as e:
|
|
97
|
+
raise e
|
|
98
|
+
|
|
99
|
+
def _do_get(self, ticket: Ticket, options: FlightCallOptions = None) -> FlightStreamReader:
|
|
100
|
+
return self._flight_client.do_get(ticket, options)
|
|
101
|
+
|
|
102
|
+
def close(self):
|
|
103
|
+
"""Close the Flight client."""
|
|
104
|
+
self._flight_client.close()
|
{influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/influxdb_client_3/write_client/__init__.py
RENAMED
|
@@ -27,5 +27,5 @@ from influxdb_client_3.write_client.service.signout_service import SignoutServic
|
|
|
27
27
|
from influxdb_client_3.write_client.domain.write_precision import WritePrecision
|
|
28
28
|
|
|
29
29
|
from influxdb_client_3.write_client.configuration import Configuration
|
|
30
|
-
from influxdb_client_3.
|
|
30
|
+
from influxdb_client_3.version import VERSION
|
|
31
31
|
__version__ = VERSION
|
{influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/influxdb_client_3/write_client/_sync/api_client.py
RENAMED
|
@@ -76,8 +76,8 @@ class ApiClient(object):
|
|
|
76
76
|
self.default_headers[header_name] = header_value
|
|
77
77
|
self.cookie = cookie
|
|
78
78
|
# Set default User-Agent.
|
|
79
|
-
from influxdb_client_3.
|
|
80
|
-
self.user_agent =
|
|
79
|
+
from influxdb_client_3.version import USER_AGENT
|
|
80
|
+
self.user_agent = USER_AGENT
|
|
81
81
|
|
|
82
82
|
def __del__(self):
|
|
83
83
|
"""Dispose pools."""
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import datetime
|
|
3
3
|
import threading
|
|
4
4
|
from datetime import timezone as tz
|
|
5
|
+
from sys import version_info
|
|
5
6
|
|
|
6
7
|
from dateutil import parser
|
|
7
8
|
|
|
@@ -90,7 +91,10 @@ def get_date_helper() -> DateHelper:
|
|
|
90
91
|
import ciso8601
|
|
91
92
|
_date_helper.parse_date = ciso8601.parse_datetime
|
|
92
93
|
except ModuleNotFoundError:
|
|
93
|
-
|
|
94
|
+
if (version_info.major, version_info.minor) >= (3, 11):
|
|
95
|
+
_date_helper.parse_date = datetime.datetime.fromisoformat
|
|
96
|
+
else:
|
|
97
|
+
_date_helper.parse_date = parser.parse
|
|
94
98
|
date_helper = _date_helper
|
|
95
99
|
|
|
96
100
|
return date_helper
|
|
@@ -10,7 +10,7 @@ from numbers import Integral
|
|
|
10
10
|
from influxdb_client_3.write_client.client.util.date_utils import get_date_helper
|
|
11
11
|
from influxdb_client_3.write_client.domain.write_precision import WritePrecision
|
|
12
12
|
|
|
13
|
-
EPOCH = datetime.
|
|
13
|
+
EPOCH = datetime.fromtimestamp(0, tz=timezone.utc)
|
|
14
14
|
|
|
15
15
|
DEFAULT_WRITE_PRECISION = WritePrecision.NS
|
|
16
16
|
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
from unittest import mock
|
|
3
|
+
|
|
4
|
+
from influxdb_client_3.write_client._sync.api_client import ApiClient
|
|
5
|
+
from influxdb_client_3.write_client.configuration import Configuration
|
|
6
|
+
from influxdb_client_3.write_client.service import WriteService
|
|
7
|
+
from influxdb_client_3.version import VERSION
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
_package = "influxdb3-python"
|
|
11
|
+
_sentHeaders = {}
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def mock_rest_request(method,
|
|
15
|
+
url,
|
|
16
|
+
query_params=None,
|
|
17
|
+
headers=None,
|
|
18
|
+
body=None,
|
|
19
|
+
post_params=None,
|
|
20
|
+
_preload_content=True,
|
|
21
|
+
_request_timeout=None,
|
|
22
|
+
**urlopen_kw):
|
|
23
|
+
class MockResponse:
|
|
24
|
+
def __init__(self, data, status_code):
|
|
25
|
+
self.data = data
|
|
26
|
+
self.status_code = status_code
|
|
27
|
+
|
|
28
|
+
def data(self):
|
|
29
|
+
return self.data
|
|
30
|
+
|
|
31
|
+
global _sentHeaders
|
|
32
|
+
_sentHeaders = headers
|
|
33
|
+
|
|
34
|
+
return MockResponse(None, 200)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class ApiClientTests(unittest.TestCase):
|
|
38
|
+
|
|
39
|
+
def test_default_headers(self):
|
|
40
|
+
global _package
|
|
41
|
+
conf = Configuration()
|
|
42
|
+
client = ApiClient(conf,
|
|
43
|
+
header_name="Authorization",
|
|
44
|
+
header_value="Bearer TEST_TOKEN")
|
|
45
|
+
self.assertIsNotNone(client.default_headers["User-Agent"])
|
|
46
|
+
self.assertIsNotNone(client.default_headers["Authorization"])
|
|
47
|
+
self.assertEqual(f"{_package}/{VERSION}", client.default_headers["User-Agent"])
|
|
48
|
+
self.assertEqual("Bearer TEST_TOKEN", client.default_headers["Authorization"])
|
|
49
|
+
|
|
50
|
+
@mock.patch("influxdb_client_3.write_client._sync.rest.RESTClientObject.request",
|
|
51
|
+
side_effect=mock_rest_request)
|
|
52
|
+
def test_call_api(self, mock_post):
|
|
53
|
+
global _package
|
|
54
|
+
global _sentHeaders
|
|
55
|
+
_sentHeaders = {}
|
|
56
|
+
|
|
57
|
+
conf = Configuration()
|
|
58
|
+
client = ApiClient(conf,
|
|
59
|
+
header_name="Authorization",
|
|
60
|
+
header_value="Bearer TEST_TOKEN")
|
|
61
|
+
service = WriteService(client)
|
|
62
|
+
service.post_write("TEST_ORG", "TEST_BUCKET", "data,foo=bar val=3.14")
|
|
63
|
+
self.assertEqual(4, len(_sentHeaders.keys()))
|
|
64
|
+
self.assertIsNotNone(_sentHeaders["Accept"])
|
|
65
|
+
self.assertEqual("application/json", _sentHeaders["Accept"])
|
|
66
|
+
self.assertIsNotNone(_sentHeaders["Content-Type"])
|
|
67
|
+
self.assertEqual("text/plain", _sentHeaders["Content-Type"])
|
|
68
|
+
self.assertIsNotNone(_sentHeaders["Authorization"])
|
|
69
|
+
self.assertEqual("Bearer TEST_TOKEN", _sentHeaders["Authorization"])
|
|
70
|
+
self.assertIsNotNone(_sentHeaders["User-Agent"])
|
|
71
|
+
self.assertEqual(f"{_package}/{VERSION}", _sentHeaders["User-Agent"])
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
from datetime import datetime, timezone
|
|
3
|
+
|
|
4
|
+
from dateutil import tz
|
|
5
|
+
|
|
6
|
+
from influxdb_client_3.write_client.client.util.date_utils import DateHelper, get_date_helper
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class TestDateHelper(unittest.TestCase):
|
|
10
|
+
|
|
11
|
+
def test_to_utc(self):
|
|
12
|
+
date = get_date_helper().to_utc(datetime(2021, 4, 29, 20, 30, 10, 0))
|
|
13
|
+
self.assertEqual(datetime(2021, 4, 29, 20, 30, 10, 0, timezone.utc), date)
|
|
14
|
+
|
|
15
|
+
def test_to_utc_different_timezone(self):
|
|
16
|
+
date = DateHelper(timezone=tz.gettz('ETC/GMT+2')).to_utc(datetime(2021, 4, 29, 20, 30, 10, 0))
|
|
17
|
+
self.assertEqual(datetime(2021, 4, 29, 22, 30, 10, 0, timezone.utc), date)
|
|
18
|
+
|
|
19
|
+
def test_parse(self):
|
|
20
|
+
date = get_date_helper().parse_date("2021-03-20T15:59:10.607352Z")
|
|
21
|
+
self.assertEqual(datetime(2021, 3, 20, 15, 59, 10, 607352, timezone.utc), date)
|
|
@@ -8,11 +8,11 @@ class TestInfluxDBClient3(unittest.TestCase):
|
|
|
8
8
|
|
|
9
9
|
@patch('influxdb_client_3._InfluxDBClient')
|
|
10
10
|
@patch('influxdb_client_3._WriteApi')
|
|
11
|
-
@patch('influxdb_client_3.
|
|
12
|
-
def setUp(self,
|
|
11
|
+
@patch('influxdb_client_3._QueryApi')
|
|
12
|
+
def setUp(self, mock_query_api, mock_write_api, mock_influx_db_client):
|
|
13
13
|
self.mock_influx_db_client = mock_influx_db_client
|
|
14
14
|
self.mock_write_api = mock_write_api
|
|
15
|
-
self.
|
|
15
|
+
self.mock_query_api = mock_query_api
|
|
16
16
|
self.client = InfluxDBClient3(
|
|
17
17
|
host="localhost",
|
|
18
18
|
org="my_org",
|
|
@@ -25,7 +25,7 @@ class TestInfluxDBClient3(unittest.TestCase):
|
|
|
25
25
|
self.assertEqual(self.client._database, "my_db")
|
|
26
26
|
self.assertEqual(self.client._client, self.mock_influx_db_client.return_value)
|
|
27
27
|
self.assertEqual(self.client._write_api, self.mock_write_api.return_value)
|
|
28
|
-
self.assertEqual(self.client.
|
|
28
|
+
self.assertEqual(self.client._query_api, self.mock_query_api.return_value)
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
if __name__ == '__main__':
|
{influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/tests/test_influxdb_client_3_integration.py
RENAMED
|
@@ -39,6 +39,7 @@ class TestInfluxDBClient3Integration(unittest.TestCase):
|
|
|
39
39
|
|
|
40
40
|
df = self.client.query(sql, mode="pandas", query_parameters={'type': 'used', 'test_id': test_id})
|
|
41
41
|
|
|
42
|
+
self.assertIsNotNone(df)
|
|
42
43
|
self.assertEqual(1, len(df))
|
|
43
44
|
self.assertEqual(test_id, df['test_id'][0])
|
|
44
45
|
self.assertEqual(123.0, df['value'][0])
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import datetime
|
|
2
|
+
import unittest
|
|
3
|
+
|
|
4
|
+
from influxdb_client_3.write_client.client.write.point import EPOCH, Point
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class TestPoint(unittest.TestCase):
|
|
8
|
+
|
|
9
|
+
def test_epoch(self):
|
|
10
|
+
self.assertEqual(EPOCH, datetime.datetime(1970, 1, 1, 0, 0, tzinfo=datetime.timezone.utc))
|
|
11
|
+
|
|
12
|
+
def test_point(self):
|
|
13
|
+
point = Point.measurement("h2o").tag("location", "europe").field("level", 2.2).time(1_000_000)
|
|
14
|
+
self.assertEqual('h2o,location=europe level=2.2 1000000', point.to_line_protocol())
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
import struct
|
|
3
|
+
from unittest.mock import Mock, ANY
|
|
4
|
+
|
|
5
|
+
from pyarrow import (
|
|
6
|
+
array,
|
|
7
|
+
Table
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
from pyarrow.flight import (
|
|
11
|
+
FlightServerBase,
|
|
12
|
+
FlightUnauthenticatedError,
|
|
13
|
+
GeneratorStream,
|
|
14
|
+
ServerMiddleware,
|
|
15
|
+
ServerMiddlewareFactory,
|
|
16
|
+
ServerAuthHandler,
|
|
17
|
+
Ticket
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
from influxdb_client_3 import InfluxDBClient3
|
|
21
|
+
from influxdb_client_3.version import USER_AGENT
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def case_insensitive_header_lookup(headers, lkey):
|
|
25
|
+
"""Lookup the value of a given key in the given headers.
|
|
26
|
+
The lkey is case-insensitive.
|
|
27
|
+
"""
|
|
28
|
+
for key in headers:
|
|
29
|
+
if key.lower() == lkey.lower():
|
|
30
|
+
return headers.get(key)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class NoopAuthHandler(ServerAuthHandler):
|
|
34
|
+
"""A no-op auth handler - as seen in pyarrow tests"""
|
|
35
|
+
|
|
36
|
+
def authenticate(self, outgoing, incoming):
|
|
37
|
+
"""Do nothing"""
|
|
38
|
+
|
|
39
|
+
def is_valid(self, token):
|
|
40
|
+
"""
|
|
41
|
+
Return an empty string
|
|
42
|
+
N.B. Returning None causes Type error
|
|
43
|
+
:param token:
|
|
44
|
+
:return:
|
|
45
|
+
"""
|
|
46
|
+
return ""
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
_req_headers = {}
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class HeaderCheckServerMiddlewareFactory(ServerMiddlewareFactory):
|
|
53
|
+
"""Factory to create HeaderCheckServerMiddleware and check header values"""
|
|
54
|
+
def start_call(self, info, headers):
|
|
55
|
+
auth_header = case_insensitive_header_lookup(headers, "Authorization")
|
|
56
|
+
values = auth_header[0].split(' ')
|
|
57
|
+
if values[0] != 'Bearer':
|
|
58
|
+
raise FlightUnauthenticatedError("Token required")
|
|
59
|
+
global _req_headers
|
|
60
|
+
_req_headers = headers
|
|
61
|
+
return HeaderCheckServerMiddleware(values[1])
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class HeaderCheckServerMiddleware(ServerMiddleware):
|
|
65
|
+
"""
|
|
66
|
+
Middleware needed to catch request headers via factory
|
|
67
|
+
N.B. As found in pyarrow tests
|
|
68
|
+
"""
|
|
69
|
+
def __init__(self, token, *args, **kwargs):
|
|
70
|
+
super().__init__(*args, **kwargs)
|
|
71
|
+
self.token = token
|
|
72
|
+
|
|
73
|
+
def sending_headers(self):
|
|
74
|
+
return {'authorization': 'Bearer ' + self.token}
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class HeaderCheckFlightServer(FlightServerBase):
|
|
78
|
+
"""Mock server handle gRPC do_get calls"""
|
|
79
|
+
def do_get(self, context, ticket):
|
|
80
|
+
"""Return something to avoid needless errors"""
|
|
81
|
+
data = [
|
|
82
|
+
array([b"Vltava", struct.pack('<i', 105), b"FM"])
|
|
83
|
+
]
|
|
84
|
+
table = Table.from_arrays(data, names=['a'])
|
|
85
|
+
return GeneratorStream(
|
|
86
|
+
table.schema,
|
|
87
|
+
self.number_batches(table),
|
|
88
|
+
options={})
|
|
89
|
+
|
|
90
|
+
@staticmethod
|
|
91
|
+
def number_batches(table):
|
|
92
|
+
for idx, batch in enumerate(table.to_batches()):
|
|
93
|
+
buf = struct.pack('<i', idx)
|
|
94
|
+
yield batch, buf
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def test_influx_default_query_headers():
|
|
98
|
+
with HeaderCheckFlightServer(
|
|
99
|
+
auth_handler=NoopAuthHandler(),
|
|
100
|
+
middleware={"check": HeaderCheckServerMiddlewareFactory()}) as server:
|
|
101
|
+
global _req_headers
|
|
102
|
+
_req_headers = {}
|
|
103
|
+
client = InfluxDBClient3(
|
|
104
|
+
host=f'http://localhost:{server.port}',
|
|
105
|
+
org='test_org',
|
|
106
|
+
databse='test_db',
|
|
107
|
+
token='TEST_TOKEN'
|
|
108
|
+
)
|
|
109
|
+
client.query('SELECT * FROM test')
|
|
110
|
+
assert len(_req_headers) > 0
|
|
111
|
+
assert _req_headers['authorization'][0] == "Bearer TEST_TOKEN"
|
|
112
|
+
assert _req_headers['user-agent'][0].find(USER_AGENT) > -1
|
|
113
|
+
_req_headers = {}
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
class TestQuery(unittest.TestCase):
|
|
117
|
+
|
|
118
|
+
def setUp(self):
|
|
119
|
+
self.client = InfluxDBClient3(
|
|
120
|
+
host="localhost",
|
|
121
|
+
org="my_org",
|
|
122
|
+
database="my_db",
|
|
123
|
+
token="my_token"
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
def test_query_without_parameters(self):
|
|
127
|
+
mock_do_get = Mock()
|
|
128
|
+
self.client._query_api._do_get = mock_do_get
|
|
129
|
+
|
|
130
|
+
self.client.query('SELECT * FROM measurement')
|
|
131
|
+
|
|
132
|
+
expected_ticket = Ticket(
|
|
133
|
+
'{"database": "my_db", '
|
|
134
|
+
'"sql_query": "SELECT * FROM measurement", '
|
|
135
|
+
'"query_type": "sql"}'.encode('utf-8')
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
mock_do_get.assert_called_once_with(expected_ticket, ANY)
|
|
139
|
+
|
|
140
|
+
def test_query_with_parameters(self):
|
|
141
|
+
mock_do_get = Mock()
|
|
142
|
+
self.client._query_api._do_get = mock_do_get
|
|
143
|
+
|
|
144
|
+
self.client.query('SELECT * FROM measurement WHERE time > $time', query_parameters={"time": "2021-01-01"})
|
|
145
|
+
|
|
146
|
+
expected_ticket = Ticket(
|
|
147
|
+
'{"database": "my_db", '
|
|
148
|
+
'"sql_query": "SELECT * FROM measurement WHERE time > $time", '
|
|
149
|
+
'"query_type": "sql", "params": {"time": "2021-01-01"}}'.encode('utf-8')
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
mock_do_get.assert_called_once_with(expected_ticket, ANY)
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import unittest
|
|
2
|
-
from unittest.mock import Mock, patch, ANY
|
|
3
|
-
|
|
4
|
-
from pyarrow.flight import Ticket
|
|
5
|
-
|
|
6
|
-
from influxdb_client_3 import InfluxDBClient3
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class QueryTests(unittest.TestCase):
|
|
10
|
-
|
|
11
|
-
@patch('influxdb_client_3._InfluxDBClient')
|
|
12
|
-
@patch('influxdb_client_3._WriteApi')
|
|
13
|
-
@patch('influxdb_client_3.FlightClient')
|
|
14
|
-
def setUp(self, mock_flight_client, mock_write_api, mock_influx_db_client):
|
|
15
|
-
self.mock_influx_db_client = mock_influx_db_client
|
|
16
|
-
self.mock_write_api = mock_write_api
|
|
17
|
-
self.mock_flight_client = mock_flight_client
|
|
18
|
-
self.client = InfluxDBClient3(
|
|
19
|
-
host="localhost",
|
|
20
|
-
org="my_org",
|
|
21
|
-
database="my_db",
|
|
22
|
-
token="my_token"
|
|
23
|
-
)
|
|
24
|
-
self.client._flight_client = mock_flight_client
|
|
25
|
-
self.client._write_api = mock_write_api
|
|
26
|
-
|
|
27
|
-
def test_query_without_parameters(self):
|
|
28
|
-
mock_do_get = Mock()
|
|
29
|
-
self.client._flight_client.do_get = mock_do_get
|
|
30
|
-
|
|
31
|
-
self.client.query('SELECT * FROM measurement')
|
|
32
|
-
|
|
33
|
-
expected_ticket = Ticket(
|
|
34
|
-
'{"database": "my_db", '
|
|
35
|
-
'"sql_query": "SELECT * FROM measurement", '
|
|
36
|
-
'"query_type": "sql"}'.encode('utf-8')
|
|
37
|
-
)
|
|
38
|
-
|
|
39
|
-
mock_do_get.assert_called_once_with(expected_ticket, ANY)
|
|
40
|
-
|
|
41
|
-
def test_query_with_parameters(self):
|
|
42
|
-
mock_do_get = Mock()
|
|
43
|
-
self.client._flight_client.do_get = mock_do_get
|
|
44
|
-
|
|
45
|
-
self.client.query('SELECT * FROM measurement WHERE time > $time', query_parameters={"time": "2021-01-01"})
|
|
46
|
-
|
|
47
|
-
expected_ticket = Ticket(
|
|
48
|
-
'{"database": "my_db", '
|
|
49
|
-
'"sql_query": "SELECT * FROM measurement WHERE time > $time", '
|
|
50
|
-
'"query_type": "sql", "params": {"time": "2021-01-01"}}'.encode('utf-8')
|
|
51
|
-
)
|
|
52
|
-
|
|
53
|
-
mock_do_get.assert_called_once_with(expected_ticket, ANY)
|
|
File without changes
|
|
File without changes
|
{influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/influxdb3_python.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/influxdb_client_3/write_client/_sync/__init__.py
RENAMED
|
File without changes
|
{influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/influxdb_client_3/write_client/_sync/rest.py
RENAMED
|
File without changes
|
{influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/influxdb_client_3/write_client/client/__init__.py
RENAMED
|
File without changes
|
{influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/influxdb_client_3/write_client/client/_base.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.5.0 → influxdb3_python-0.6.1}/influxdb_client_3/write_client/client/warnings.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/influxdb_client_3/write_client/client/write_api.py
RENAMED
|
File without changes
|
{influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/influxdb_client_3/write_client/configuration.py
RENAMED
|
File without changes
|
{influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/influxdb_client_3/write_client/domain/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{influxdb3_python-0.5.0 → influxdb3_python-0.6.1}/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
|
|
File without changes
|
|
File without changes
|