Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
965c3c7
refactor: write rest client
NguyenHoangSon96 Jun 12, 2026
454bea5
test: add multiprocess helper test
NguyenHoangSon96 Jun 22, 2026
45518f9
test: remove check blocking running of multiprocessing helper test.
karel-rehor Jul 3, 2026
8603236
test: restore skip test on CircleCI
karel-rehor Jul 3, 2026
86b03d5
refactor: write rest client
NguyenHoangSon96 Jul 7, 2026
06be327
refactor: write rest client
NguyenHoangSon96 Jul 7, 2026
280465f
refactor: write rest client
NguyenHoangSon96 Jul 8, 2026
ee3210e
refactor: write rest client
NguyenHoangSon96 Jul 8, 2026
b297888
refactor: write rest client
NguyenHoangSon96 Jul 8, 2026
d2ef48d
test: add multiprocess helper test
NguyenHoangSon96 Jul 8, 2026
5b56951
refactor: write rest client
NguyenHoangSon96 Jul 8, 2026
8af7679
refactor: write rest client
NguyenHoangSon96 Jul 8, 2026
ff7dbcb
refactor: write rest client
NguyenHoangSon96 Jul 8, 2026
691e56d
refactor: write rest client
NguyenHoangSon96 Jul 8, 2026
0f7af30
refactor: write rest client
NguyenHoangSon96 Jul 8, 2026
de0f075
refactor: write rest client
NguyenHoangSon96 Jul 9, 2026
20f56b4
refactor: write rest client
NguyenHoangSon96 Jul 9, 2026
db16713
refactor: write rest client
NguyenHoangSon96 Jul 9, 2026
a778c4d
refactor: write rest client
NguyenHoangSon96 Jul 9, 2026
c72ab3c
refactor: write rest client
NguyenHoangSon96 Jul 9, 2026
d518e72
refactor: write rest client
NguyenHoangSon96 Jul 13, 2026
20e9418
refactor: write rest client
NguyenHoangSon96 Jul 13, 2026
7faf76f
refactor: write rest client
NguyenHoangSon96 Jul 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,65 @@

## 0.21.0 [unreleased]

### Breaking Changes
Comment thread
NguyenHoangSon96 marked this conversation as resolved.

1. [#217](https://github.com/InfluxCommunity/influxdb3-python/pull/217): Make Write API simpler and consistent with other v3 clients.
- Remove unused `InfluxLoggingHandler` class.
- WriteApi now has all functions to write to InfluxDB. `Configuration`, `ApiClient`, `WriteService`, `InfluxDBClient` are no longer needed.
All settings needed for writing now can be passed to the constructor of WriteApi.
``` python
import time
from influxdb_client_3.write_client import WriteApi
from influxdb_client_3.write_client._sync import rest_client
from influxdb_client_3 import WriteOptions, write_client_options

default_header = {
'Authorization': 'Token my-token'
}
Comment thread
NguyenHoangSon96 marked this conversation as resolved.
rest = rest_client.RestClient(
base_url='http://localhost:8181',
default_header=default_header,
verify_ssl=True,
ssl_ca_cert=None,
cert_file=None,
cert_key_file=None,
cert_key_password=None,
ssl_context=None,
proxy=None,
proxy_headers=None,
retries=False,
debug=False,
connection_pool_maxsize=25
)

wco=write_client_options(write_options=WriteOptions(batch_size=100)))
write_api = WriteApi(
bucket='bucket_name',
org='my-org',
default_header=default_header,
gzip_threshold=None,
enable_gzip=False,
auth_scheme='Token',
timeout=None,
rest_client=rest,
point_settings=None,
**wco
)

test_id = time.time_ns()
write_api.write(record=f"cpu,type=used ram=16,test_id={test_id}i")
write_api.close()

```
- rest_client.RestClient will now be responsible for low-level handling the HTTP requests.
- `InfluxDBClient3` constructor will have additional parameters for configuring the RestClient and WriteApi.
- auth_scheme,
- enable_gzip,
- gzip_threshold,
- point_settings,
- debug,
- Refactor Multiprocessing helper class.

## 0.20.0 [2026-06-11]

### Features
Expand Down
117 changes: 87 additions & 30 deletions influxdb_client_3/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import multiprocessing

import importlib.util
import json
import os
import urllib.parse
from typing import Any, List, Literal, Optional, TYPE_CHECKING

import pyarrow as pa

from influxdb_client_3.version import USER_AGENT
from influxdb_client_3.write_client._sync import rest_client as rest

if TYPE_CHECKING:
import pandas as pd
import polars as pl
Expand All @@ -14,7 +20,7 @@
from influxdb_client_3.exceptions import InfluxDBError
from influxdb_client_3.query.query_api import QueryApi as _QueryApi, QueryApiOptionsBuilder
from influxdb_client_3.read_file import UploadFile
from influxdb_client_3.write_client import InfluxDBClient as _InfluxDBClient, WriteOptions, Point
from influxdb_client_3.write_client import WriteOptions, Point
from influxdb_client_3.write_client.client.write_api import WriteApi as _WriteApi, SYNCHRONOUS, ASYNCHRONOUS, \
PointSettings, DefaultWriteOptions, WriteType
from influxdb_client_3.write_client.domain.write_precision import WritePrecision
Expand Down Expand Up @@ -189,11 +195,16 @@ def __init__(
org=None,
database=None,
token=None,
auth_scheme=None,
enable_gzip=False,
gzip_threshold=None,
write_client_options=None,
flight_client_options=None,
write_port_overwrite=None,
query_port_overwrite=None,
disable_grpc_compression=False,
point_settings=None,
debug=False,
**kwargs):
"""
Initialize an InfluxDB client.
Expand All @@ -212,6 +223,14 @@ def __init__(
:type flight_client_options: dict[str, any]
:param disable_grpc_compression: Disable gRPC compression for Flight query responses. Default is False.
:type disable_grpc_compression: bool
:param point_settings The settings for Points
:type point_settings: PointSettings
:param debug: enable verbose logging of http requests
:type debug: bool
:param enable_gzip: Enable GZIP compression for write requests.
:type enable_gzip: bool
:param gzip_threshold: Minimum payload size (bytes) to trigger GZIP when enable_gzip is True.
:type gzip_threshold: int
:key auth_scheme: token authentication scheme. Set to "Bearer" for Edge.
:key bool verify_ssl: Set this to false to skip verifying SSL certificate when calling API from https server.
:key str ssl_ca_cert: Set this to customize the certificate file to verify the peer.
Expand Down Expand Up @@ -293,14 +312,49 @@ def __init__(
if write_port_overwrite is not None:
port = write_port_overwrite

self._client = _InfluxDBClient(
url=f"{scheme}://{hostname}:{port}",
token=self._token,
auth_schema = 'Token' if auth_scheme is None else auth_scheme
default_header = {
'User-Agent': USER_AGENT
}
if self._token is not None:
Comment thread
NguyenHoangSon96 marked this conversation as resolved.
default_header['Authorization'] = f'{auth_schema} {self._token}'
self.base_url = f"{scheme}://{hostname}:{port}"
self.default_header = default_header
Comment thread
NguyenHoangSon96 marked this conversation as resolved.
self.rest_client = rest.RestClient(
base_url=self.base_url,
default_header=default_header,
Comment thread
NguyenHoangSon96 marked this conversation as resolved.
verify_ssl=kwargs.get('verify_ssl', True),
ssl_ca_cert=kwargs.get('ssl_ca_cert', None),
cert_file=kwargs.get('cert_file', None),
cert_key_file=kwargs.get('cert_key_file', None),
cert_key_password=kwargs.get('cert_key_password', None),
ssl_context=kwargs.get('ssl_context', None),
proxy=kwargs.get('proxy', None),
proxy_headers=kwargs.get('proxy_headers', None),
retries=kwargs.get('retries', False),
debug=debug,
connection_pool_maxsize=kwargs.get('connection_pool_maxsize', multiprocessing.cpu_count() * 5,)
)

if point_settings is None:
point_settings = PointSettings()

# Keep WriteOptions.timeout in sync with the resolved write_timeout
if isinstance(self._write_client_options, dict) and self._write_client_options.get("write_options") is not None:
self._write_client_options["write_options"].timeout = write_timeout

self._write_api = _WriteApi(
Comment thread
NguyenHoangSon96 marked this conversation as resolved.
Comment thread
Copilot marked this conversation as resolved.
bucket=self._database,
org=self._org,
gzip_threshold=gzip_threshold,
enable_gzip=enable_gzip,
auth_scheme=auth_scheme,
timeout=write_timeout,
**kwargs)

self._write_api = _WriteApi(influxdb_client=self._client, **self._write_client_options)
default_header=default_header,
rest_client=self.rest_client,
point_settings=point_settings,
**self._write_client_options
)

if query_port_overwrite is not None:
port = query_port_overwrite
Expand Down Expand Up @@ -658,32 +712,32 @@ async def query_async(self, query: str, language: str = "sql", mode: str = "all"
except ArrowException as e:
raise InfluxDB3ClientQueryError(f"Error while executing query: {e}")

def get_server_version(self) -> str:
def get_server_version(self) -> Optional[str]:
"""
Get the version of the connected InfluxDB server.
Retrieves the server version by querying the designated endpoint and
extracting the version information from either response headers or
the response body.

This method makes a ping request to the server and extracts the version information
from either the response headers or response body.
This method interacts with a REST API endpoint to fetch the server's
version details, which might be stored in a specific HTTP header or
available in the response body as part of a JSON structure.

:return: The version string of the InfluxDB server.
:rtype: str
:return: The version string of the server if available, otherwise None.
:rtype: Optional[str]
"""
version = None
(resp_body, _, header) = self._client.api_client.call_api(
resource_path="/ping",
method="GET",
response_type=object
)

for key, value in header.items():
resp = self.rest_client.request(url='/ping', method="GET", headers=self.default_header)
for key, value in resp.getheaders().items():
if key.lower() == "x-influxdb-version":
version = value
break

if version is None and isinstance(resp_body, dict):
version = resp_body['version']
return value

return version
string_body = resp.get_string_body()
if not string_body:
return None
try:
data = json.loads(string_body)
except (ValueError, TypeError):
return None
return data.get('version')

def flush(self):
"""
Expand All @@ -700,9 +754,12 @@ def flush(self):

def close(self):
"""Close the client and clean up resources."""
self._write_api.close()
self._query_api.close()
self._client.close()
if self._write_api is not None:
self._write_api.close()
if self._query_api is not None:
Comment thread
NguyenHoangSon96 marked this conversation as resolved.
self._query_api.close()
if self.rest_client is not None:
self.rest_client.close()

def __enter__(self):
return self
Expand Down
10 changes: 2 additions & 8 deletions influxdb_client_3/write_client/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,9 @@

from __future__ import absolute_import

from influxdb_client_3.write_client.client.write_api import WriteApi, WriteOptions
from influxdb_client_3.write_client.client.influxdb_client import InfluxDBClient
from influxdb_client_3.write_client.client.logging_handler import InfluxLoggingHandler
from influxdb_client_3.version import VERSION
from influxdb_client_3.write_client.client.write.point import Point

from influxdb_client_3.write_client.service.write_service import WriteService

from influxdb_client_3.write_client.client.write_api import WriteApi, WriteOptions
from influxdb_client_3.write_client.domain.write_precision import WritePrecision

from influxdb_client_3.write_client.configuration import Configuration
from influxdb_client_3.version import VERSION
__version__ = VERSION
Loading
Loading