Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion devtools/create_tag.sh
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ fi

# check if tag to create has already been created
WORKING_DIR=`dirname $0`
VERSION=`python setup.py --version`
VERSION=`hatch project metadata version`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This implies that there's now a hatch executable available in $PATH. Looks like this isn't mentioned in DEVELOP.rst - the whole file looks sort of outdated, together with the bootstrap.sh

Can we simplify that, so there's some sort of standard uv venv venv; uv pip install -Ue ".[dev]" with no special custom logic?

Copy link
Member Author

@amotl amotl Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hatch was introduced with GH-739, but updating the files you've mentioned apparently has been missed. Let's track this with a separate ticket so @surister can address it?

Copy link
Member Author

@amotl amotl Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've created a dedicated ticket. Thank you.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not fix it? Seems like things are sort of broken as they are in this PR

Copy link
Member Author

@amotl amotl Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like things are sort of broken as they are in this PR.

This patch was merely thought cosmetic to remove setup.py as intended. GH-739 already made the project use Hatch, because pyproject.toml takes precedence even when using the traditional setuptools build backend like before. In this spirit, the project would already be broken right now?

Why not fix it?

Switching to setuptools again requires more changes, because standard setuptools uses a different format in pyproject.toml than hatch. Let's discuss here?

Copy link
Member

@mfussenegger mfussenegger Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Switching to setuptools again requires more changes, because standard setuptools uses a different format in pyproject.toml than hatch. Let's discuss #766 (comment)?

I don't see the advantage of going from A (broken) -> B (this version - also broken) -> C (version that works) when we can do A (broken) -> C (not broken).

Also note that this doesn't require switching away from hatch. It just needs to become a build time dependency that's documented. Could even make use of uvx hatch if we already depend on uv (which should also be documented if that's the case, and isn't mentioned)

Copy link
Member Author

@amotl amotl Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi. Apologies that I still can't follow what is exactly broken here. Can you share an error message? Hatch is currently a build time dependency, and this works well.

[build-system]
requires = ["hatchling", "versioningit"]
build-backend = "hatchling.build"

Copy link
Member Author

@amotl amotl Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might be seeing the problem now: Is it hatchling vs. hatch? So, let's just add hatch, right! Fixed with 8a9a172.

EXISTS=`git tag | grep $VERSION`

if [ "$VERSION" == "$EXISTS" ]
Expand Down
20 changes: 14 additions & 6 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[build-system]
requires = ["hatchling >= 1.26", "versioningit"]
requires = ["hatch", "hatchling", "versioningit"]
build-backend = "hatchling.build"

[tool.hatch.build.targets.sdist]
Expand All @@ -26,7 +26,7 @@ name = "crate"
dynamic = ["version"]
description = "CrateDB Python Client"
authors = [{ name = "Crate.io", email = "[email protected]" }]
requires-python = ">=3.10"
requires-python = ">=3.6"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we lower this now? Afaik newer versions intentionally bumped this so that pip install on older python versions would install an old crate-python version - allowing us to drop compat logic for older versions.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

setup.py says python_requires=">=3.6", I've just transferred this to pyproject.toml.

readme = "README.rst"
license = "Apache-2.0"
classifiers = [
Expand All @@ -35,32 +35,40 @@ classifiers = [
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
"Programming Language :: SQL",
"Topic :: Database",
"Topic :: Internet :: WWW/HTTP",
"Topic :: Scientific/Engineering :: Interface Engine/Protocol Translator",
"Topic :: System :: Networking",
]
dependencies = [
"importlib-metadata; python_version<'3.8'",
"orjson>=3.11.3",
"orjson",
"urllib3",
"verlib2>=0.3.1",
]

[dependency-groups]
dev = [
"certifi>=2025.10.5",
"backports.zoneinfo<1; python_version<'3.9'",
"certifi",
"coverage<8",
"mypy<1.20",
"poethepoet<1",
"pytest<10",
"pytz>=2025.2",
"pytz",
"ruff<0.15",
"setuptools>=80.9.0",
"stopit<1.2",
]

Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
zc.buildout==5.1.1
zope.interface==8.2
zope.interface>=8,<9
zope.testrunner>=5,<9
101 changes: 0 additions & 101 deletions setup.py

This file was deleted.

4 changes: 3 additions & 1 deletion src/crate/client/cursor.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,8 @@ def duration(self):
def _convert_rows(self):
"""
Iterate rows, apply type converters, and generate converted rows.

The converter is only supported on Python >= 3.10.
"""
if not ("col_types" in self._result and self._result["col_types"]):
raise ValueError(
Expand All @@ -238,7 +240,7 @@ def _convert_rows(self):
for row in self._result["rows"]:
yield [
convert(value)
for convert, value in zip(converters, row, strict=False)
for convert, value in zip(converters, row, strict=False) # type: ignore[call-overload]
]

@property
Expand Down
25 changes: 25 additions & 0 deletions tests/client/test_cursor.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
# software solely pursuant to the terms of the relevant commercial agreement.

import datetime
import sys
from ipaddress import IPv4Address
from unittest import mock

Expand Down Expand Up @@ -58,6 +59,9 @@ def test_cursor_fetch(mocked_connection):
]


@pytest.mark.skipif(
sys.version_info < (3, 10), reason="Test needs Python >= 3.10"
)
def test_cursor_description(mocked_connection):
cursor = mocked_connection.cursor()
response = {
Expand Down Expand Up @@ -249,6 +253,9 @@ def test_execute_with_bulk_args(mocked_connection):
mocked_connection.client.sql.assert_called_once_with(statement, None, [[1]])


@pytest.mark.skipif(
sys.version_info < (3, 10), reason="Converter needs Python >= 3.10"
)
def test_execute_custom_converter(mocked_connection):
"""
Verify that a custom converter is correctly applied when passed to a cursor.
Expand Down Expand Up @@ -299,6 +306,9 @@ def test_execute_custom_converter(mocked_connection):
]


@pytest.mark.skipif(
sys.version_info < (3, 10), reason="Converter needs Python >= 3.10"
)
def test_execute_with_converter_and_invalid_data_type(mocked_connection):
converter = DefaultTypeConverter()

Expand All @@ -323,6 +333,9 @@ def test_execute_with_converter_and_invalid_data_type(mocked_connection):
assert e.exception.args == "999 is not a valid DataType"


@pytest.mark.skipif(
sys.version_info < (3, 10), reason="Converter needs Python >= 3.10"
)
def test_execute_array_with_converter(mocked_connection):
converter = DefaultTypeConverter()
cursor = mocked_connection.cursor(converter=converter)
Expand All @@ -345,6 +358,9 @@ def test_execute_array_with_converter(mocked_connection):
]


@pytest.mark.skipif(
sys.version_info < (3, 10), reason="Converter needs Python >= 3.10"
)
def test_execute_array_with_converter_invalid(mocked_connection):
converter = DefaultTypeConverter()
cursor = mocked_connection.cursor(converter=converter)
Expand All @@ -368,6 +384,9 @@ def test_execute_array_with_converter_invalid(mocked_connection):
)


@pytest.mark.skipif(
sys.version_info < (3, 10), reason="Converter needs Python >= 3.10"
)
def test_execute_nested_array_with_converter(mocked_connection):
converter = DefaultTypeConverter()
cursor = mocked_connection.cursor(converter=converter)
Expand Down Expand Up @@ -405,6 +424,9 @@ def test_execute_nested_array_with_converter(mocked_connection):
]


@pytest.mark.skipif(
sys.version_info < (3, 10), reason="Converter needs Python >= 3.10"
)
def test_executemany_with_converter(mocked_connection):
converter = DefaultTypeConverter()
cursor = mocked_connection.cursor(converter=converter)
Expand All @@ -426,6 +448,9 @@ def test_executemany_with_converter(mocked_connection):
assert result == []


@pytest.mark.skipif(
sys.version_info < (3, 10), reason="Converter needs Python >= 3.10"
)
def test_execute_with_timezone(mocked_connection):
# Create a `Cursor` object with `time_zone`.
tz_mst = datetime.timezone(datetime.timedelta(hours=7), name="MST")
Expand Down
20 changes: 12 additions & 8 deletions tests/client/tests.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import doctest
import sys
import unittest

from .layer import (
Expand All @@ -18,14 +19,17 @@ def test_suite():
suite.addTest(doctest.DocTestSuite("crate.client.connection"))
suite.addTest(doctest.DocTestSuite("crate.client.http"))

s = doctest.DocFileSuite(
"docs/by-example/connection.rst",
"docs/by-example/cursor.rst",
module_relative=False,
optionflags=flags,
encoding="utf-8",
)
suite.addTest(s)
if sys.version_info >= (3, 10):
# This suite includes converter tests,
# which are only available with Python 3.10 and newer.
s = doctest.DocFileSuite(
"docs/by-example/connection.rst",
"docs/by-example/cursor.rst",
module_relative=False,
optionflags=flags,
encoding="utf-8",
)
suite.addTest(s)

s = doctest.DocFileSuite(
"docs/by-example/https.rst",
Expand Down
Loading