Skip to content

Commit 8f2ea66

Browse files
authored
feat: protocol version 2 and n-dimensional array ingestion support
1 parent 443cfa0 commit 8f2ea66

28 files changed

+3064
-1933
lines changed

.bumpversion.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[bumpversion]
2-
current_version = 2.0.4
2+
current_version = 3.0.0rc1
33
commit = True
44
tag = False
55

CHANGELOG.rst

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,74 @@
11
.. _changelog:
22

3+
34
Changelog
5+
46
=========
57

8+
3.0.0rc1 (2025-06-02)
9+
---------------------
10+
11+
This is the pre-release of a major release introducing array ingestion and some
12+
minor breaking changes.
13+
14+
Features
15+
~~~~~~~~
16+
* Array Data Type Support. Adds native support for NumPy arrays
17+
(currently only for ``np.float64`` element type and up to 32 dimensions).
18+
19+
.. code-block:: python
20+
21+
import numpy as np
22+
23+
# Create 2D numpy array
24+
array_2d = np.array([
25+
[1.1, 2.2, 3.3],
26+
[4.4, 5.5, 6.6]], dtype=np.float64)
27+
28+
sender.row(
29+
'table',
30+
columns={'array_2d': array_2d},
31+
at=timestamp)
32+
33+
* Implements binary protocol for columns of ``float`` (double-precision) and
34+
``numpy.ndarray[np.float64]``, with performance improvements for these
35+
two datatypes.
36+
37+
Breaking Changes
38+
~~~~~~~~~~~~~~~~
39+
* Buffer Constructor Changes. The ``Buffer`` constructor now requires the ``protocol_version`` parameter.
40+
You can create buffer through the sender for automatic ``protocol_version`` management:
41+
42+
.. code-block:: python
43+
44+
buf = sender.new_buffer() # protocol_version determined automatically
45+
buf.row(
46+
'table',
47+
columns={'arr': np.array([1.5, 3.0], dtype=np.float64)},
48+
at=timestamp)
49+
50+
* To access the raw payload, call ``bytes(sender)`` or ``bytes(buffer)`` (
51+
rather than calling the ``str`` function on the same objects as in version
52+
2.x.x of the questdb library) method.
53+
54+
* **NumPy Dependency**
55+
56+
Array functionality mandates NumPy installation.
57+
58+
* **Sender/Buffer String Conversion Removal**
59+
60+
The legacy string conversion via `str(sender)` is removed.
61+
Access raw binary payloads through the `bytes(sender)` method:
62+
63+
.. code-block:: python
64+
65+
# for debugging
66+
payload = bytes(sender)
67+
68+
* Python 3.8 support is dropped.
69+
70+
The minimum supported Python version is now 3.9.
71+
672
2.0.4 (2025-04-02)
773
------------------
874

README.rst

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ QuestDB Client Library for Python
55
This is the official Python client library for `QuestDB <https://questdb.io>`_.
66

77
This client library implements QuestDB's variant of the
8-
`InfluxDB Line Protocol <https://questdb.io/docs/reference/api/ilp/overview/>`_
8+
`Ingestion Line Protocol <https://questdb.io/docs/reference/api/ilp/overview/>`_
99
(ILP) over HTTP and TCP.
1010

1111
ILP provides the fastest way to insert data into QuestDB.
@@ -15,16 +15,29 @@ This implementation supports `authentication
1515
and full-connection encryption with
1616
`TLS <https://py-questdb-client.readthedocs.io/en/latest/conf.html#tls>`_.
1717

18-
Quickstart
19-
==========
18+
Install
19+
=======
2020

21-
The latest version of the library is 2.0.3 (`changelog <https://py-questdb-client.readthedocs.io/en/latest/changelog.html>`_).
21+
The latest *stable* version of the library is **2.0.4** (`changelog <https://py-questdb-client.readthedocs.io/en/latest/changelog.html>`_).
2222

2323
::
2424

2525
python3 -m pip install -U questdb[dataframe]
2626

27-
Please start by `setting up QuestDB <https://questdb.io/docs/quick-start/>`_ . Once set up, you can use this library to insert data.
27+
28+
The latest *pre-release* version of the library is **3.0.0r1** (`changelog <https://py-questdb-client.readthedocs.io/en/latest/changelog.html>`_).
29+
This release supports NumPy float64 arrays which are transmitted over a new
30+
protocol version supported by QuestDB 8.4.0 or later.
31+
32+
::
33+
34+
python3 -m pip install --pre -U questdb[dataframe]
35+
36+
Quickstart
37+
==========
38+
39+
Start by `setting up QuestDB <https://questdb.io/docs/quick-start/>`_ .
40+
Once set up, you can use this library to insert data.
2841

2942
The most common way to insert data is from a Pandas dataframe.
3043

@@ -38,6 +51,13 @@ The most common way to insert data is from a Pandas dataframe.
3851
'side': pd.Categorical(['sell', 'sell']),
3952
'price': [2615.54, 39269.98],
4053
'amount': [0.00044, 0.001],
54+
55+
# NumPy float64 arrays are supported from v3.0.0rc1 onwards.
56+
'ord_book_bids': [
57+
np.array([2615.54, 2618.63]),
58+
np.array([39269.98, 39270.00])
59+
],
60+
4161
'timestamp': pd.to_datetime(['2021-01-01', '2021-01-02'])})
4262
4363
conf = f'http::addr=localhost:9000;'
@@ -57,7 +77,13 @@ You can also send individual rows. This only requires a more minimal installatio
5777
sender.row(
5878
'trades',
5979
symbols={'symbol': 'ETH-USD', 'side': 'sell'},
60-
columns={'price': 2615.54, 'amount': 0.00044},
80+
columns={
81+
'price': 2615.54,
82+
'amount': 0.00044,
83+
84+
# NumPy float64 arrays are supported from v3.0.0rc1 onwards.
85+
'ord_book_bids': np.array([2615.54, 2618.63]),
86+
},
6187
at=TimestampNanos.now())
6288
sender.flush()
6389

RELEASING.rst

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,10 +93,9 @@ Inside the VM, open a terminal (or use the terminal Window in VSCode) and run th
9393

9494
rustup update stable
9595

96-
/Library/Frameworks/Python.framework/Versions/3.8/bin/python3 \
97-
-m pip install -U pip
98-
/Library/Frameworks/Python.framework/Versions/3.8/bin/python3 \
99-
-m pip install -U setuptools wheel twine Cython cibuildwheel pandas numpy pyarrow
96+
python3 -m pip install -U pip
97+
python3 -m pip install -U \
98+
setuptools wheel twine Cython cibuildwheel pandas numpy pyarrow
10099

101100
Smoke-testing the build
102101
-----------------------

c-questdb-client

Submodule c-questdb-client updated 110 files

ci/cibuildwheel.yaml

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ stages:
5252
- job: linux_arm64
5353
pool:
5454
name: "arm64-clients"
55-
vmImage:
5655
demands:
5756
- Agent.Name -equals arm64-clients-$(Build.BuildId)
5857
dependsOn:
@@ -92,23 +91,6 @@ stages:
9291
- task: PublishBuildArtifacts@1
9392
inputs: {pathtoPublish: 'wheelhouse'}
9493

95-
- job: linux_x64_cpython_manylinux_i686
96-
pool: {vmImage: 'ubuntu-latest'}
97-
timeoutInMinutes: 90
98-
steps:
99-
- task: UsePythonVersion@0
100-
- bash: |
101-
set -o errexit
102-
python3 -m pip install --upgrade pip
103-
python3 -m pip install cibuildwheel
104-
displayName: Install dependencies
105-
- bash: cibuildwheel --output-dir wheelhouse .
106-
displayName: Build wheels
107-
env:
108-
CIBW_BUILD: cp*-manylinux_i686
109-
- task: PublishBuildArtifacts@1
110-
inputs: {pathtoPublish: 'wheelhouse'}
111-
11294
- job: linux_x64_cpython_musllinux
11395
pool: {vmImage: 'ubuntu-latest'}
11496
timeoutInMinutes: 90
@@ -168,9 +150,22 @@ stages:
168150
python3 -m pip install --upgrade pip
169151
python3 -m pip install cibuildwheel
170152
displayName: Install dependencies
171-
- bash: cibuildwheel --output-dir wheelhouse .
153+
- powershell: |
154+
$vsPath = Resolve-Path "C:\Program Files (x86)\Microsoft Visual Studio\2019\*\VC\Auxiliary\Build\vcvars32.bat"
155+
cmd /c "call `"$vsPath`" && set > env_vars.txt"
156+
157+
Get-Content env_vars.txt | ForEach-Object {
158+
if ($_ -match "^([^=]+?)=(.*)$" -and $matches[1] -notmatch '^(SYSTEM|AGENT|BUILD|RELEASE|VSTS|TASK|USE_|FAIL_|MSDEPLOY|AZP_75787|AZP_AGENT|AZP_ENABLE|AZURE_HTTP|COPYFILESOVERSSHV0|ENABLE_ISSUE_SOURCE_VALIDATION|MODIFY_NUMBER_OF_RETRIES_IN_ROBOCOPY|MSBUILDHELPERS_ENABLE_TELEMETRY|RETIRE_AZURERM_POWERSHELL_MODULE|ROSETTA2_WARNING|AZP_PS_ENABLE)') {
159+
[System.Environment]::SetEnvironmentVariable($matches[1], $matches[2], "Process")
160+
Write-Host "##vso[task.setvariable variable=$($matches[1])]$($matches[2])"
161+
}
162+
}
163+
164+
where.exe cl.exe
165+
cibuildwheel --output-dir wheelhouse .
172166
displayName: Build wheels
173167
env:
168+
CIBW_ENVIRONMENT: "MSSdk=1 DISTUTILS_USE_SDK=1 SETUP_DO_GIT_SUBMODULE_INIT=1"
174169
CIBW_BUILD: "*win32*"
175170
- task: PublishBuildArtifacts@1
176171
inputs: {pathtoPublish: 'wheelhouse'}
@@ -185,9 +180,24 @@ stages:
185180
python3 -m pip install --upgrade pip
186181
python3 -m pip install cibuildwheel
187182
displayName: Install dependencies
188-
- bash: cibuildwheel --output-dir wheelhouse .
183+
- powershell: |
184+
$vsPath = Resolve-Path "C:\Program Files (x86)\Microsoft Visual Studio\2019\*\VC\Auxiliary\Build\vcvars64.bat"
185+
cmd /c "call `"$vsPath`" && set > env_vars.txt"
186+
187+
Get-Content env_vars.txt | ForEach-Object {
188+
if ($_ -match "^([^=]+?)=(.*)$" -and $matches[1] -notmatch '^(SYSTEM|AGENT|BUILD|RELEASE|VSTS|TASK|USE_|FAIL_|MSDEPLOY|AZP_75787|AZP_AGENT|AZP_ENABLE|AZURE_HTTP|COPYFILESOVERSSHV0|ENABLE_ISSUE_SOURCE_VALIDATION|MODIFY_NUMBER_OF_RETRIES_IN_ROBOCOPY|MSBUILDHELPERS_ENABLE_TELEMETRY|RETIRE_AZURERM_POWERSHELL_MODULE|ROSETTA2_WARNING|AZP_PS_ENABLE)') {
189+
[System.Environment]::SetEnvironmentVariable($matches[1], $matches[2], "Process")
190+
Write-Host "##vso[task.setvariable variable=$($matches[1])]$($matches[2])"
191+
}
192+
}
193+
194+
where.exe cl.exe
195+
cibuildwheel --output-dir wheelhouse .
189196
displayName: Build wheels
190197
env:
191198
CIBW_BUILD: "*win_amd64*"
199+
CIBW_ENVIRONMENT: "MSSdk=1 DISTUTILS_USE_SDK=1 SETUP_DO_GIT_SUBMODULE_INIT=1"
200+
CIBW_BUILD_VERBOSITY: "3"
201+
DISTUTILS_DEBUG: "1"
192202
- task: PublishBuildArtifacts@1
193203
inputs: {pathtoPublish: 'wheelhouse'}

ci/pip_install_deps.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,20 +66,19 @@ def install_old_pandas_and_numpy(args):
6666
try_pip_install('numpy<2')
6767

6868
def install_new_pandas_and_numpy():
69-
try_pip_install('pandas')
70-
try_pip_install('numpy')
69+
try_pip_install('pandas>2')
70+
try_pip_install('numpy>2')
7171

7272
def main(args):
7373
ensure_timezone()
7474
pip_install('pip')
7575
pip_install('setuptools')
76-
try_pip_install('fastparquet>=2023.10.1')
77-
7876
if args.pandas_version is not None and args.pandas_version != '':
7977
install_old_pandas_and_numpy(args)
8078
else:
8179
install_new_pandas_and_numpy()
8280

81+
try_pip_install('fastparquet>=2023.10.1')
8382
try_pip_install('pyarrow')
8483

8584
on_linux_is_glibc = (

docs/api.rst

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,61 @@ questdb.ingress
99

1010
from questdb.ingress import *
1111

12-
.. automodule:: questdb.ingress
12+
.. autoclass:: questdb.ingress.Sender
13+
:members:
14+
:undoc-members:
15+
:show-inheritance:
16+
17+
.. autoclass:: questdb.ingress.Buffer
18+
:members:
19+
:undoc-members:
20+
:show-inheritance:
21+
22+
.. autoclass:: questdb.ingress.SenderTransaction
23+
:members:
24+
:undoc-members:
25+
:show-inheritance:
26+
27+
.. autoclass:: questdb.ingress.IngressError
28+
:members:
29+
:undoc-members:
30+
:show-inheritance:
31+
32+
.. autoclass:: questdb.ingress.IngressErrorCode
33+
:members:
34+
:undoc-members:
35+
:show-inheritance:
36+
37+
.. autoclass:: questdb.ingress.Protocol
38+
:members:
39+
:undoc-members:
40+
:show-inheritance:
41+
42+
.. autoclass:: questdb.ingress.TimestampMicros
43+
:members:
44+
:undoc-members:
45+
:show-inheritance:
46+
47+
.. autoclass:: questdb.ingress.TimestampNanos
48+
:members:
49+
:undoc-members:
50+
:show-inheritance:
51+
52+
.. autoclass:: questdb.ingress.TlsCa
53+
:members:
54+
:undoc-members:
55+
:show-inheritance:
56+
57+
.. autoclass:: questdb.ingress.ServerTimestampType
58+
:members:
59+
:undoc-members:
60+
:show-inheritance:
61+
62+
.. autodata:: questdb.ingress.ServerTimestamp
63+
:annotation:
64+
:no-value:
65+
66+
.. autoclass:: questdb.ingress.TaggedEnum
1367
:members:
1468
:undoc-members:
1569
:show-inheritance:

docs/conf.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
import os
55

6+
from questdb.ingress import *
7+
68
extensions = [
79
'sphinx.ext.autodoc',
810
'sphinx.ext.autosummary',
@@ -12,15 +14,16 @@
1214
'sphinx.ext.ifconfig',
1315
'sphinx.ext.napoleon',
1416
'sphinx.ext.todo',
15-
'sphinx.ext.viewcode'
17+
'sphinx.ext.viewcode',
18+
"sphinx.ext.intersphinx",
1619
]
1720
source_suffix = '.rst'
1821
master_doc = 'index'
1922
project = 'questdb'
2023
year = '2024'
2124
author = 'QuestDB'
2225
copyright = '{0}, {1}'.format(year, author)
23-
version = release = '2.0.4'
26+
version = release = '3.0.0rc1'
2427

2528
github_repo_url = 'https://github.com/questdb/py-questdb-client'
2629

@@ -67,6 +70,11 @@
6770
'undoc-members': True
6871
}
6972

73+
intersphinx_mapping = {
74+
"python": ("https://docs.python.org/3", None),
75+
"numpy": ("https://numpy.org/doc/stable/", None),
76+
"pandas": ("https://pandas.pydata.org/pandas-docs/stable/", None),
77+
}
7078

7179
# def do_not_skip_dunder_members(_app, _what, name, _obj, would_skip, _options):
7280
# if name in ('__init__', '__call__', '__str__', '__enter__', '__exit__'):

0 commit comments

Comments
 (0)