From 8b7749060ad2066f252afa702fb19d68e58579e8 Mon Sep 17 00:00:00 2001 From: Kevin Smith Date: Wed, 8 Oct 2025 09:54:26 -0500 Subject: [PATCH 01/13] feature: Modernize the build and install system MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Migrated from setup.py/setup.cfg to pyproject.toml-based build system while maintaining all existing functionality including C extension builds. Created .flake8 configuration file and updated all utility scripts (bump_version.py, create_release.py) and documentation (RELEASE.md) to use pyproject.toml. Updated .pre-commit-config.yaml to use --py39-plus for reorder-python-imports and configured flake8 with min-python-version=3.9.0 to align with project's Python 3.9+ requirement. Removed obsolete setup-cfg-fmt hook. All build options, optional dependencies, entry points, and package metadata have been preserved. Tested with both editable install and wheel/sdist builds. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .flake8 | 15 +++ .pre-commit-config.yaml | 6 +- RELEASE.md | 2 +- pyproject.toml | 89 +++++++++++++++ resources/build_docs.py | 2 +- resources/bump_version.py | 26 ++--- resources/create_release.py | 26 ++--- setup.cfg | 121 --------------------- singlestoredb/connection.py | 4 +- singlestoredb/functions/ext/asgi.py | 6 +- singlestoredb/functions/ext/rowdat_1.py | 2 +- singlestoredb/functions/signature.py | 2 +- singlestoredb/functions/typing/__init__.py | 2 +- singlestoredb/functions/utils.py | 2 +- singlestoredb/fusion/handler.py | 2 +- singlestoredb/fusion/result.py | 2 +- singlestoredb/http/connection.py | 4 +- singlestoredb/management/utils.py | 2 +- singlestoredb/mysql/connection.py | 2 +- singlestoredb/pytest.py | 2 +- singlestoredb/utils/config.py | 4 +- singlestoredb/utils/mogrify.py | 2 +- singlestoredb/utils/xdict.py | 8 +- 23 files changed, 156 insertions(+), 177 deletions(-) create mode 100644 .flake8 create mode 100644 pyproject.toml delete mode 100644 setup.cfg diff --git a/.flake8 b/.flake8 new file mode 100644 index 000000000..d2f090777 --- /dev/null +++ b/.flake8 @@ -0,0 +1,15 @@ +[flake8] +exclude = + docs/* + resources/* + licenses/* +max-complexity = 45 +max-line-length = 90 +min-python-version = 3.9.0 +per-file-ignores = + singlestoredb/__init__.py:F401 + singlestoredb/fusion/__init__.py:F401 + singlestoredb/fusion/grammar.py:E501 + singlestoredb/http/__init__.py:F401 + singlestoredb/management/__init__.py:F401 + singlestoredb/mysql/__init__.py:F401 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 524ce3581..b9a9cf276 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -29,16 +29,12 @@ repos: rev: v3.12.0 hooks: - id: reorder-python-imports - args: [--py36-plus] + args: [--py39-plus] - repo: https://github.com/asottile/add-trailing-comma rev: v3.1.0 hooks: - id: add-trailing-comma args: [--py36-plus] -- repo: https://github.com/asottile/setup-cfg-fmt - rev: v2.5.0 - hooks: - - id: setup-cfg-fmt - repo: https://github.com/pre-commit/mirrors-mypy rev: v1.14.1 hooks: diff --git a/RELEASE.md b/RELEASE.md index 3af452714..30fd56dda 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -8,7 +8,7 @@ resources/bump_version.py < major | minor | patch > ``` -This will bump the version number in `setup.cfg` and `singlestoredb/__init__.py` +This will bump the version number in `pyproject.toml` and `singlestoredb/__init__.py` using semantic versioning rules: minor bump for new features, patch bump for bug fixes. It will genarete a list of changes since the last version and ask for confirmation of the release notes in `docs/src/whatsnew.rst`. diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 000000000..e6c82fc5c --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,89 @@ +[build-system] +requires = ["build", "setuptools>=61.0", "wheel"] +build-backend = "setuptools.build_meta" + +[project] +name = "singlestoredb" +version = "1.15.8" +description = "Interface to the SingleStoreDB database and workspace management APIs" +readme = {file = "README.md", content-type = "text/markdown"} +license = "Apache-2.0" +license-files = ["LICENSE"] +authors = [ + {name = "SingleStore", email = "support@singlestore.com"} +] +requires-python = ">=3.9" +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3 :: Only", + "Topic :: Database", +] +dependencies = [ + "PyJWT", + "parsimonious", + "requests", + "sqlparams", + "tomli>=1.1.0; python_version < '3.11'", + "typing-extensions<=4.13.2; python_version < '3.11'", +] + +[project.urls] +Homepage = "https://github.com/singlestore-labs/singlestoredb-python" + +[project.optional-dependencies] +dataframe = ["ibis-singlestoredb"] +dbt = ["dbt-singlestore"] +docker = ["docker"] +ed22519 = ["PyNaCl>=1.4.0"] +gssapi = ["gssapi"] +ibis = ["ibis-singlestoredb"] +kerberos = ["gssapi"] +pytest = ["pytest"] +rsa = ["cryptography"] +sqlalchemy = ["sqlalchemy-singlestoredb>=1.0.0"] +vectorstore = ["singlestore-vectorstore>=0.1.2"] + +[project.entry-points.pytest11] +singlestoredb = "singlestoredb.pytest" + +[tool.setuptools] +include-package-data = true + +[tool.setuptools.packages.find] +exclude = ["docs*", "resources*", "examples*", "licenses*"] + +[tool.setuptools.package-data] +"*" = ["*.typed", "*.sql", "*.csv", "*.ipynb"] + +[tool.pytest.ini_options] +markers = [ + "management", +] + +[tool.mypy] +check_untyped_defs = true +disallow_any_generics = true +disallow_incomplete_defs = true +disallow_untyped_defs = true +no_implicit_optional = true +warn_redundant_casts = true +warn_unused_ignores = false + +[[tool.mypy.overrides]] +module = "testing.*" +disallow_untyped_defs = false + +[[tool.mypy.overrides]] +module = "tests.*" +disallow_untyped_defs = false + +[tool.coverage.run] +source_pkgs = ["singlestoredb"] + +[tool.coverage.report] +omit = [ + "setup.py", + "*/tests/*", + "*/docs/*", +] diff --git a/resources/build_docs.py b/resources/build_docs.py index aa78b2c42..628f3a1fd 100755 --- a/resources/build_docs.py +++ b/resources/build_docs.py @@ -27,10 +27,10 @@ import sys import time from pathlib import Path +from re import Match from typing import Any from typing import Dict from typing import List -from typing import Match from typing import Optional # Detect script location and set up paths diff --git a/resources/bump_version.py b/resources/bump_version.py index 7345772ef..3730aec07 100755 --- a/resources/bump_version.py +++ b/resources/bump_version.py @@ -36,14 +36,14 @@ def step(step_num: int, total_steps: int, message: str) -> None: def get_current_version() -> str: - """Get the current version from setup.cfg.""" - setup_cfg_path = Path(__file__).parent.parent / 'setup.cfg' - with open(setup_cfg_path, 'r') as f: + """Get the current version from pyproject.toml.""" + pyproject_path = Path(__file__).parent.parent / 'pyproject.toml' + with open(pyproject_path, 'r') as f: content = f.read() - match = re.search(r'^version\s*=\s*(.+)$', content, re.MULTILINE) + match = re.search(r'^version\s*=\s*["\'](.+)["\']$', content, re.MULTILINE) if not match: - raise ValueError('Could not find version in setup.cfg') + raise ValueError('Could not find version in pyproject.toml') return match.group(1).strip() @@ -75,10 +75,10 @@ def update_version_in_file(file_path: Path, old_version: str, new_version: str) with open(file_path, 'r') as f: content = f.read() - # For setup.cfg - if file_path.name == 'setup.cfg': - pattern = r'^(version\s*=\s*)' + re.escape(old_version) + r'$' - replacement = r'\g<1>' + new_version + # For pyproject.toml + if file_path.name == 'pyproject.toml': + pattern = r'^(version\s*=\s*["\'])' + re.escape(old_version) + r'(["\'])$' + replacement = r'\g<1>' + new_version + r'\g<2>' content = re.sub(pattern, replacement, content, flags=re.MULTILINE) # For __init__.py @@ -307,7 +307,7 @@ def stage_files() -> None: status('📦 Staging files for commit...') files_to_stage = [ - 'setup.cfg', + 'pyproject.toml', 'singlestoredb/__init__.py', 'docs/src/whatsnew.rst', 'docs/', # All generated documentation files @@ -360,8 +360,8 @@ def main() -> None: step(2, 6, 'Updating version in files') start_time = time.time() - update_version_in_file(Path(__file__).parent.parent / 'setup.cfg', current_version, new_version) - status(' ✓ Updated setup.cfg') + update_version_in_file(Path(__file__).parent.parent / 'pyproject.toml', current_version, new_version) + status(' ✓ Updated pyproject.toml') update_version_in_file( Path(__file__).parent.parent / 'singlestoredb' / '__init__.py', @@ -399,7 +399,7 @@ def main() -> None: status('🔄 Reverting version changes...') # Revert version changes - update_version_in_file(Path(__file__).parent.parent / 'setup.cfg', new_version, current_version) + update_version_in_file(Path(__file__).parent.parent / 'pyproject.toml', new_version, current_version) update_version_in_file( Path(__file__).parent.parent / 'singlestoredb' / '__init__.py', new_version, diff --git a/resources/create_release.py b/resources/create_release.py index a7494ee7d..a67699ad0 100755 --- a/resources/create_release.py +++ b/resources/create_release.py @@ -13,7 +13,7 @@ python create_release.py [--version VERSION] [--dry-run] Examples: - python create_release.py # Use current version from setup.cfg + python create_release.py # Use current version from pyproject.toml python create_release.py --version 1.15.6 # Use specific version python create_release.py --dry-run # Preview without executing """ @@ -39,19 +39,19 @@ def step(step_num: int, total_steps: int, message: str) -> None: print(f'📍 Step {step_num}/{total_steps}: {message}', file=sys.stderr) -def get_version_from_setup_cfg() -> str: - """Extract the current version from setup.cfg.""" - setup_cfg_path = Path(__file__).parent.parent / 'setup.cfg' +def get_version_from_pyproject() -> str: + """Extract the current version from pyproject.toml.""" + pyproject_path = Path(__file__).parent.parent / 'pyproject.toml' - if not setup_cfg_path.exists(): - raise FileNotFoundError(f'Could not find setup.cfg at {setup_cfg_path}') + if not pyproject_path.exists(): + raise FileNotFoundError(f'Could not find pyproject.toml at {pyproject_path}') - with open(setup_cfg_path, 'r') as f: + with open(pyproject_path, 'r') as f: content = f.read() - match = re.search(r'^version\s*=\s*(.+)$', content, re.MULTILINE) + match = re.search(r'^version\s*=\s*["\'](.+)["\']$', content, re.MULTILINE) if not match: - raise ValueError('Could not find version in setup.cfg') + raise ValueError('Could not find version in pyproject.toml') return match.group(1).strip() @@ -228,14 +228,14 @@ def main() -> None: description='Create GitHub release for SingleStoreDB Python SDK', formatter_class=argparse.RawDescriptionHelpFormatter, epilog='''Examples: - %(prog)s # Use current version from setup.cfg + %(prog)s # Use current version from pyproject.toml %(prog)s --version 1.15.6 # Use specific version %(prog)s --dry-run # Preview without executing''', ) parser.add_argument( '--version', - help='Version to release (default: extract from setup.cfg)', + help='Version to release (default: extract from pyproject.toml)', ) parser.add_argument( @@ -267,8 +267,8 @@ def main() -> None: version = args.version status(f'Using specified version: {version}') else: - version = get_version_from_setup_cfg() - status(f'Extracted from setup.cfg: {version}') + version = get_version_from_pyproject() + status(f'Extracted from pyproject.toml: {version}') elapsed = time.time() - start_time status(f'✅ Version determined in {elapsed:.1f}s') diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index acf91319b..000000000 --- a/setup.cfg +++ /dev/null @@ -1,121 +0,0 @@ -[metadata] -name = singlestoredb -version = 1.15.8 -description = Interface to the SingleStoreDB database and workspace management APIs -long_description = file: README.md -long_description_content_type = text/markdown -url = https://github.com/singlestore-labs/singlestoredb-python -author = SingleStore -author_email = support@singlestore.com -license = Apache-2.0 -license_files = LICENSE -classifiers = - Development Status :: 5 - Production/Stable - License :: OSI Approved :: Apache Software License - Programming Language :: Python :: 3 - Programming Language :: Python :: 3 :: Only - Topic :: Database - -[options] -packages = find: -install_requires = - PyJWT - build - parsimonious - requests - setuptools - sqlparams - wheel - tomli>=1.1.0;python_version < '3.11' - typing-extensions<=4.13.2;python_version < '3.11' -python_requires = >=3.9 -include_package_data = True -tests_require = - coverage - pytest - pandas - -[options.packages.find] -exclude = - docs* - resources* - examples* - licenses* - -[options.entry_points] -pytest11 = - singlestoredb = singlestoredb.pytest - -[options.extras_require] -dataframe = - ibis-singlestoredb -dbt = - dbt-singlestore -docker = - docker -ed22519 = - PyNaCl>=1.4.0 -gssapi = - gssapi -ibis = - ibis-singlestoredb -kerberos = - gssapi -pytest = - pytest -rsa = - cryptography -sqlalchemy = - sqlalchemy-singlestoredb>=1.0.0 -vectorstore = - singlestore-vectorstore>=0.1.2 - -[options.package_data] -* = - *.typed - *.sql - *.csv - *.ipynb - -[tool:pytest] -markers = - management - -[flake8] -exclude = - docs/* - resources/* - licenses/* -max-complexity = 45 -max-line-length = 90 -per-file-ignores = - singlestoredb/__init__.py:F401 - singlestoredb/fusion/__init__.py:F401 - singlestoredb/fusion/grammar.py:E501 - singlestoredb/http/__init__.py:F401 - singlestoredb/management/__init__.py:F401 - singlestoredb/mysql/__init__.py:F401 - -[mypy] -check_untyped_defs = true -disallow_any_generics = true -disallow_incomplete_defs = true -disallow_untyped_defs = true -no_implicit_optional = true -warn_redundant_casts = true -warn_unused_ignores = false - -[mypy-testing.*] -disallow_untyped_defs = false - -[mypy-tests.*] -disallow_untyped_defs = false - -[coverage:run] -source_pkgs = singlestoredb - -[coverage:report] -omit = - setup.py - */tests/* - */docs/* diff --git a/singlestoredb/connection.py b/singlestoredb/connection.py index 258ab5813..425def6f2 100644 --- a/singlestoredb/connection.py +++ b/singlestoredb/connection.py @@ -9,15 +9,15 @@ import sys import warnings import weakref +from collections.abc import Iterator from collections.abc import Mapping from collections.abc import MutableMapping +from collections.abc import Sequence from typing import Any from typing import Callable from typing import Dict -from typing import Iterator from typing import List from typing import Optional -from typing import Sequence from typing import Tuple from typing import Union from urllib.parse import parse_qs diff --git a/singlestoredb/functions/ext/asgi.py b/singlestoredb/functions/ext/asgi.py index f2e33a338..d9090b38f 100755 --- a/singlestoredb/functions/ext/asgi.py +++ b/singlestoredb/functions/ext/asgi.py @@ -48,15 +48,15 @@ import uuid import zipfile import zipimport +from collections.abc import Awaitable +from collections.abc import Iterable +from collections.abc import Sequence from types import ModuleType from typing import Any -from typing import Awaitable from typing import Callable from typing import Dict -from typing import Iterable from typing import List from typing import Optional -from typing import Sequence from typing import Set from typing import Tuple from typing import Union diff --git a/singlestoredb/functions/ext/rowdat_1.py b/singlestoredb/functions/ext/rowdat_1.py index 83052b671..94e966b77 100644 --- a/singlestoredb/functions/ext/rowdat_1.py +++ b/singlestoredb/functions/ext/rowdat_1.py @@ -1,11 +1,11 @@ #!/usr/bin/env python3 import struct import warnings +from collections.abc import Sequence from io import BytesIO from typing import Any from typing import List from typing import Optional -from typing import Sequence from typing import Tuple from typing import TYPE_CHECKING diff --git a/singlestoredb/functions/signature.py b/singlestoredb/functions/signature.py index 841be0eb2..69cbb437c 100644 --- a/singlestoredb/functions/signature.py +++ b/singlestoredb/functions/signature.py @@ -9,12 +9,12 @@ import sys import types import typing +from collections.abc import Sequence from typing import Any from typing import Callable from typing import Dict from typing import List from typing import Optional -from typing import Sequence from typing import Tuple from typing import TypeVar from typing import Union diff --git a/singlestoredb/functions/typing/__init__.py b/singlestoredb/functions/typing/__init__.py index 12770a78d..66bb98522 100644 --- a/singlestoredb/functions/typing/__init__.py +++ b/singlestoredb/functions/typing/__init__.py @@ -1,5 +1,5 @@ +from collections.abc import Iterable from typing import Any -from typing import Iterable from typing import Tuple from typing import TypeVar diff --git a/singlestoredb/functions/utils.py b/singlestoredb/functions/utils.py index 8849f32c0..6e4aa6295 100644 --- a/singlestoredb/functions/utils.py +++ b/singlestoredb/functions/utils.py @@ -4,10 +4,10 @@ import sys import types import typing +from collections.abc import Iterable from enum import Enum from typing import Any from typing import Dict -from typing import Iterable from typing import Tuple from typing import Union diff --git a/singlestoredb/fusion/handler.py b/singlestoredb/fusion/handler.py index 98b082893..b70d9e6d1 100644 --- a/singlestoredb/fusion/handler.py +++ b/singlestoredb/fusion/handler.py @@ -5,10 +5,10 @@ import re import sys import textwrap +from collections.abc import Iterable from typing import Any from typing import Callable from typing import Dict -from typing import Iterable from typing import List from typing import Optional from typing import Set diff --git a/singlestoredb/fusion/result.py b/singlestoredb/fusion/result.py index c9c0229a5..82640b7b7 100644 --- a/singlestoredb/fusion/result.py +++ b/singlestoredb/fusion/result.py @@ -2,8 +2,8 @@ from __future__ import annotations import re +from collections.abc import Iterable from typing import Any -from typing import Iterable from typing import List from typing import Optional from typing import Tuple diff --git a/singlestoredb/http/connection.py b/singlestoredb/http/connection.py index 1b5ceb515..28f48e8bf 100644 --- a/singlestoredb/http/connection.py +++ b/singlestoredb/http/connection.py @@ -10,13 +10,13 @@ import re import time from base64 import b64decode +from collections.abc import Iterable +from collections.abc import Sequence from typing import Any from typing import Callable from typing import Dict -from typing import Iterable from typing import List from typing import Optional -from typing import Sequence from typing import Tuple from typing import Union from urllib.parse import urljoin diff --git a/singlestoredb/management/utils.py b/singlestoredb/management/utils.py index c398f006d..5aa072e41 100644 --- a/singlestoredb/management/utils.py +++ b/singlestoredb/management/utils.py @@ -6,11 +6,11 @@ import os import re import sys +from collections.abc import Mapping from typing import Any from typing import Callable from typing import Dict from typing import List -from typing import Mapping from typing import Optional from typing import SupportsIndex from typing import Tuple diff --git a/singlestoredb/mysql/connection.py b/singlestoredb/mysql/connection.py index 7bc34f000..f96ebb0cd 100644 --- a/singlestoredb/mysql/connection.py +++ b/singlestoredb/mysql/connection.py @@ -13,9 +13,9 @@ import sys import traceback import warnings +from collections.abc import Iterable from typing import Any from typing import Dict -from typing import Iterable try: import _singlestoredb_accel diff --git a/singlestoredb/pytest.py b/singlestoredb/pytest.py index ae3b189c5..22efd68df 100644 --- a/singlestoredb/pytest.py +++ b/singlestoredb/pytest.py @@ -6,8 +6,8 @@ import subprocess import time import uuid +from collections.abc import Iterator from enum import Enum -from typing import Iterator from typing import Optional import pytest diff --git a/singlestoredb/utils/config.py b/singlestoredb/utils/config.py index 8197ce72a..6b7cdd9f3 100644 --- a/singlestoredb/utils/config.py +++ b/singlestoredb/utils/config.py @@ -27,12 +27,12 @@ import contextlib import os import re +from collections.abc import Iterator +from collections.abc import Mapping from typing import Any from typing import Callable from typing import Dict -from typing import Iterator from typing import List -from typing import Mapping from typing import Optional from typing import Tuple from typing import Union diff --git a/singlestoredb/utils/mogrify.py b/singlestoredb/utils/mogrify.py index adcd46360..2785e46ab 100644 --- a/singlestoredb/utils/mogrify.py +++ b/singlestoredb/utils/mogrify.py @@ -1,8 +1,8 @@ #!/usr/bin/env python3 +from collections.abc import Sequence from typing import Any from typing import Dict from typing import Optional -from typing import Sequence from typing import Union from ..mysql import converters diff --git a/singlestoredb/utils/xdict.py b/singlestoredb/utils/xdict.py index bdeebc6ce..56a906e25 100644 --- a/singlestoredb/utils/xdict.py +++ b/singlestoredb/utils/xdict.py @@ -19,14 +19,14 @@ """Dictionary that allows setting nested keys by period (.) delimited strings.""" import copy import re +from collections.abc import ItemsView +from collections.abc import Iterable +from collections.abc import KeysView +from collections.abc import ValuesView from typing import Any from typing import Dict -from typing import ItemsView -from typing import Iterable -from typing import KeysView from typing import List from typing import Tuple -from typing import ValuesView def _is_compound_key(key: str) -> bool: From ab6a63e0799c6634977d13ead7c119022980240f Mon Sep 17 00:00:00 2001 From: Kevin Smith Date: Wed, 8 Oct 2025 10:00:24 -0500 Subject: [PATCH 02/13] Update requirements files --- CONTRIBUTING.md | 2 +- test-requirements.txt => requirements-dev.txt | 3 +++ requirements.txt | 3 --- 3 files changed, 4 insertions(+), 4 deletions(-) rename test-requirements.txt => requirements-dev.txt (89%) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ebf27708c..e3cb6cb67 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -28,7 +28,7 @@ pre-commit run --all-files To create a test environment, do the following: ``` pip install -r requirements.txt -pip install -r test-requirements.txt +pip install -r requirements-dev.txt ``` If you have Docker installed, you can run the tests as follows. Note that diff --git a/test-requirements.txt b/requirements-dev.txt similarity index 89% rename from test-requirements.txt rename to requirements-dev.txt index 641ad5f22..7e6e9a701 100644 --- a/test-requirements.txt +++ b/requirements-dev.txt @@ -1,3 +1,4 @@ +build coverage dash fastapi @@ -11,8 +12,10 @@ pydantic pygeos ; python_version < '3.12' pytest pytest-cov +setuptools shapely singlestore-vectorstore>=0.1.2 sphinx sphinx_rtd_theme uvicorn +wheel diff --git a/requirements.txt b/requirements.txt index bdc386103..00d4f1864 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,9 +1,6 @@ -build parsimonious PyJWT requests -setuptools sqlparams tomli>=1.1.0; python_version < '3.11' typing_extensions<=4.13.2 -wheel From 777966c291b59330775eba53d24772bbe87e0d3a Mon Sep 17 00:00:00 2001 From: Kevin Smith Date: Wed, 8 Oct 2025 10:28:02 -0500 Subject: [PATCH 03/13] fix: Use table format for license field in pyproject.toml The newer string format for license (license = "Apache-2.0") requires setuptools >= 77.0.0. Changed to table format (license = {text = "Apache-2.0"}) to maintain compatibility with setuptools >= 61.0. Removed license-files field as setuptools automatically includes LICENSE file. --- pyproject.toml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index e6c82fc5c..f9f414752 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,8 +7,7 @@ name = "singlestoredb" version = "1.15.8" description = "Interface to the SingleStoreDB database and workspace management APIs" readme = {file = "README.md", content-type = "text/markdown"} -license = "Apache-2.0" -license-files = ["LICENSE"] +license = {text = "Apache-2.0"} authors = [ {name = "SingleStore", email = "support@singlestore.com"} ] From 77ef8ab4e09c229de43582869271514753d1ab28 Mon Sep 17 00:00:00 2001 From: Kevin Smith Date: Wed, 8 Oct 2025 10:32:59 -0500 Subject: [PATCH 04/13] Update requirements paths --- .github/workflows/code-check.yml | 2 +- .github/workflows/coverage.yml | 2 +- .github/workflows/publish.yml | 2 +- .github/workflows/smoke-test.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/code-check.yml b/.github/workflows/code-check.yml index dc19d8952..2e08bc5fc 100644 --- a/.github/workflows/code-check.yml +++ b/.github/workflows/code-check.yml @@ -40,7 +40,7 @@ jobs: run: | python -m pip install --upgrade pip pip install -r requirements.txt - pip install -r test-requirements.txt + pip install -r requirements-dev.txt - name: Install SingleStore package run: | diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 7a456260a..3bd04bbd3 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -34,7 +34,7 @@ jobs: run: | python -m pip install --upgrade pip pip install -r requirements.txt - pip install -r test-requirements.txt + pip install -r requirements-dev.txt - name: Install SingleStore package run: | diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 4b89ea077..40ae2d367 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -79,7 +79,7 @@ jobs: run: | python -m pip install --upgrade pip pip install -r requirements.txt - pip install -r test-requirements.txt + pip install -r requirements-dev.txt - name: Build sdist if: runner.os == 'Linux' diff --git a/.github/workflows/smoke-test.yml b/.github/workflows/smoke-test.yml index 5dad06360..ad113d5c1 100644 --- a/.github/workflows/smoke-test.yml +++ b/.github/workflows/smoke-test.yml @@ -112,7 +112,7 @@ jobs: run: | python -m pip install --upgrade pip pip install -r requirements.txt - pip install -r test-requirements.txt + pip install -r requirements-dev.txt - name: Install SingleStore package run: | From db54eda5869ce5016408e361ffd3bdc72c1c288a Mon Sep 17 00:00:00 2001 From: Kevin Smith Date: Wed, 8 Oct 2025 10:49:45 -0500 Subject: [PATCH 05/13] Remove pygeos requirement --- requirements-dev.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 7e6e9a701..2774f671b 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -9,7 +9,6 @@ parameterized polars pyarrow pydantic -pygeos ; python_version < '3.12' pytest pytest-cov setuptools From 7793e7fab863c586044d758e861028e85f02708e Mon Sep 17 00:00:00 2001 From: Kevin Smith Date: Wed, 8 Oct 2025 10:59:20 -0500 Subject: [PATCH 06/13] Remove shapely requirement --- requirements-dev.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 2774f671b..9cbb48ee9 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -12,7 +12,6 @@ pydantic pytest pytest-cov setuptools -shapely singlestore-vectorstore>=0.1.2 sphinx sphinx_rtd_theme From 25d23d2533e1411702a63e3e773fa70aba7b68ba Mon Sep 17 00:00:00 2001 From: Kevin Smith Date: Wed, 8 Oct 2025 11:10:39 -0500 Subject: [PATCH 07/13] Pin setuptools; eliminate C warnings --- accel.c | 4 ++-- requirements-dev.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/accel.c b/accel.c index b1ef0419d..a785b9754 100644 --- a/accel.c +++ b/accel.c @@ -3079,11 +3079,11 @@ static PyObject *dump_rowdat_1_numpy(PyObject *self, PyObject *args, PyObject *k PyErr_SetString(PyExc_ValueError, "value is outside the valid range for UNSIGNED INT"); \ goto error; \ } -#define CHECK_BIGINT(x, unsigned_input) if ((x) < ((unsigned_input) ? 0 : -9223372036854775808) || (x) > 9223372036854775807) { \ +#define CHECK_BIGINT(x, unsigned_input) if ((x) < ((unsigned_input) ? 0 : INT64_MIN) || (x) > INT64_MAX) { \ PyErr_SetString(PyExc_ValueError, "value is outside the valid range for BIGINT"); \ goto error; \ } -#define CHECK_UNSIGNED_BIGINT(x, unsigned_input) if ((x) < 0 || (x) > 18446744073709551615) { \ +#define CHECK_UNSIGNED_BIGINT(x, unsigned_input) if ((x) < 0) { \ PyErr_SetString(PyExc_ValueError, "value is outside the valid range for UNSIGNED BIGINT"); \ goto error; \ } diff --git a/requirements-dev.txt b/requirements-dev.txt index 9cbb48ee9..36d0e1fe8 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -11,7 +11,7 @@ pyarrow pydantic pytest pytest-cov -setuptools +setuptools>=61.0" singlestore-vectorstore>=0.1.2 sphinx sphinx_rtd_theme From 47250c11f01b9ef2be3cbbd042baf8dea43dda07 Mon Sep 17 00:00:00 2001 From: Kevin Smith Date: Wed, 8 Oct 2025 11:15:28 -0500 Subject: [PATCH 08/13] Pin setuptools; eliminate C warnings --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 36d0e1fe8..905b8882e 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -11,7 +11,7 @@ pyarrow pydantic pytest pytest-cov -setuptools>=61.0" +setuptools>=61.0 singlestore-vectorstore>=0.1.2 sphinx sphinx_rtd_theme From 63724641ee0f4a418186851129d0b400c4cf9566 Mon Sep 17 00:00:00 2001 From: Kevin Smith Date: Wed, 8 Oct 2025 13:38:31 -0500 Subject: [PATCH 09/13] Update dependency locations --- .github/workflows/code-check.yml | 7 +------ .github/workflows/coverage.yml | 7 +------ .github/workflows/fusion-docs.yml | 4 ---- .github/workflows/publish.yml | 7 +++---- .github/workflows/smoke-test.yml | 11 +++-------- CONTRIBUTING.md | 9 +++++++-- pyproject.toml | 30 ++++++++++++++++++++++++++++++ requirements-dev.txt | 19 ------------------- requirements.txt | 6 ------ 9 files changed, 45 insertions(+), 55 deletions(-) delete mode 100644 requirements-dev.txt delete mode 100644 requirements.txt diff --git a/.github/workflows/code-check.yml b/.github/workflows/code-check.yml index 2e08bc5fc..8bad6fd3b 100644 --- a/.github/workflows/code-check.yml +++ b/.github/workflows/code-check.yml @@ -39,12 +39,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install -r requirements.txt - pip install -r requirements-dev.txt - - - name: Install SingleStore package - run: | - pip install . + pip install -e ".[dev]" - name: Check for changes in monitored directories id: check-changes diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 3bd04bbd3..9b388cf62 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -33,12 +33,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install -r requirements.txt - pip install -r requirements-dev.txt - - - name: Install SingleStore package - run: | - pip install . + pip install -e ".[dev]" - name: Run MySQL protocol tests run: | diff --git a/.github/workflows/fusion-docs.yml b/.github/workflows/fusion-docs.yml index 11b94e298..c82840512 100644 --- a/.github/workflows/fusion-docs.yml +++ b/.github/workflows/fusion-docs.yml @@ -27,10 +27,6 @@ jobs: run: | python --version python -m pip install --upgrade pip - pip install -r requirements.txt - - - name: Install package - run: | pip install . - name: Build Fusion docs diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 40ae2d367..e555bc4a3 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -39,7 +39,7 @@ jobs: run: | python --version python -m pip install --upgrade pip - pip install -r requirements.txt + pip install . - name: Initialize database id: initialize-database @@ -78,8 +78,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install -r requirements.txt - pip install -r requirements-dev.txt + pip install -e ".[dev]" - name: Build sdist if: runner.os == 'Linux' @@ -211,7 +210,7 @@ jobs: run: | python --version python -m pip install --upgrade pip - pip install -r requirements.txt + pip install . - name: Drop database if: ${{ always() }} diff --git a/.github/workflows/smoke-test.yml b/.github/workflows/smoke-test.yml index ad113d5c1..fe5c01c6f 100644 --- a/.github/workflows/smoke-test.yml +++ b/.github/workflows/smoke-test.yml @@ -24,7 +24,7 @@ jobs: run: | python --version python -m pip install --upgrade pip - pip install -r requirements.txt + pip install . - name: Initialize database id: initialize-database @@ -111,12 +111,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install -r requirements.txt - pip install -r requirements-dev.txt - - - name: Install SingleStore package - run: | - pip install . --no-build-isolation + pip install -e ".[dev]" --no-build-isolation - name: Run tests if: ${{ matrix.driver != 'https' }} @@ -151,7 +146,7 @@ jobs: run: | python --version python -m pip install --upgrade pip - pip install -r requirements.txt + pip install . - name: Drop database if: ${{ always() }} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e3cb6cb67..d6ca0304b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -27,8 +27,13 @@ pre-commit run --all-files To create a test environment, do the following: ``` -pip install -r requirements.txt -pip install -r requirements-dev.txt +pip install -e ".[dev]" +``` + +Or if you only need specific dependency groups: +``` +pip install -e ".[test]" # Just testing dependencies +pip install -e ".[docs]" # Just documentation dependencies ``` If you have Docker installed, you can run the tests as follows. Note that diff --git a/pyproject.toml b/pyproject.toml index f9f414752..256ff3a4b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -43,6 +43,36 @@ rsa = ["cryptography"] sqlalchemy = ["sqlalchemy-singlestoredb>=1.0.0"] vectorstore = ["singlestore-vectorstore>=0.1.2"] +# Development dependency groups +test = [ + "coverage", + "dash", + "fastapi", + "ipython", + "jupysql", + "pandas", + "parameterized", + "polars", + "pyarrow", + "pydantic", + "pytest", + "pytest-cov", + "singlestore-vectorstore>=0.1.2", + "uvicorn", +] +docs = [ + "sphinx", + "sphinx_rtd_theme", +] +build = [ + "build", + "setuptools>=61.0", + "wheel", +] +dev = [ + "singlestoredb[test,docs,build]", +] + [project.entry-points.pytest11] singlestoredb = "singlestoredb.pytest" diff --git a/requirements-dev.txt b/requirements-dev.txt deleted file mode 100644 index 905b8882e..000000000 --- a/requirements-dev.txt +++ /dev/null @@ -1,19 +0,0 @@ -build -coverage -dash -fastapi -ipython -jupysql -pandas -parameterized -polars -pyarrow -pydantic -pytest -pytest-cov -setuptools>=61.0 -singlestore-vectorstore>=0.1.2 -sphinx -sphinx_rtd_theme -uvicorn -wheel diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 00d4f1864..000000000 --- a/requirements.txt +++ /dev/null @@ -1,6 +0,0 @@ -parsimonious -PyJWT -requests -sqlparams -tomli>=1.1.0; python_version < '3.11' -typing_extensions<=4.13.2 From f8e070ba7147e97b4634039fbbdf26300032fb37 Mon Sep 17 00:00:00 2001 From: Kevin Smith Date: Wed, 8 Oct 2025 13:57:13 -0500 Subject: [PATCH 10/13] Remove build isolation --- .github/workflows/smoke-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/smoke-test.yml b/.github/workflows/smoke-test.yml index fe5c01c6f..27c2a9282 100644 --- a/.github/workflows/smoke-test.yml +++ b/.github/workflows/smoke-test.yml @@ -111,7 +111,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install -e ".[dev]" --no-build-isolation + pip install -e ".[dev]" - name: Run tests if: ${{ matrix.driver != 'https' }} From cb1a71c91025ae3b72472b135f6c676b98aab742 Mon Sep 17 00:00:00 2001 From: Kevin Smith Date: Thu, 9 Oct 2025 10:08:42 -0500 Subject: [PATCH 11/13] Change metadata to boolean --- singlestoredb/management/files.py | 2 +- singlestoredb/management/workspace.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/singlestoredb/management/files.py b/singlestoredb/management/files.py index ac3561ad7..08d5f6f21 100644 --- a/singlestoredb/management/files.py +++ b/singlestoredb/management/files.py @@ -839,7 +839,7 @@ def info(self, path: PathLike) -> FilesObject: """ res = self._manager._get( re.sub(r'/+$', r'/', f'files/fs/{self._location}/{path}'), - params=dict(metadata=1), + params=dict(metadata=True), ).json() return FilesObject.from_dict(res, self) diff --git a/singlestoredb/management/workspace.py b/singlestoredb/management/workspace.py index 7c394ade2..cb6ff6e87 100644 --- a/singlestoredb/management/workspace.py +++ b/singlestoredb/management/workspace.py @@ -378,7 +378,7 @@ def info(self, stage_path: PathLike) -> FilesObject: """ res = self._manager._get( re.sub(r'/+$', r'/', f'stage/{self._deployment_id}/fs/{stage_path}'), - params=dict(metadata=1), + params=dict(metadata=True), ).json() return FilesObject.from_dict(res, self) From ac3711d608de634ee97bd8853d018be05c2c9121 Mon Sep 17 00:00:00 2001 From: Kevin Smith Date: Thu, 9 Oct 2025 12:45:20 -0500 Subject: [PATCH 12/13] Change metadata to int --- singlestoredb/management/files.py | 2 +- singlestoredb/management/workspace.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/singlestoredb/management/files.py b/singlestoredb/management/files.py index 08d5f6f21..ac3561ad7 100644 --- a/singlestoredb/management/files.py +++ b/singlestoredb/management/files.py @@ -839,7 +839,7 @@ def info(self, path: PathLike) -> FilesObject: """ res = self._manager._get( re.sub(r'/+$', r'/', f'files/fs/{self._location}/{path}'), - params=dict(metadata=True), + params=dict(metadata=1), ).json() return FilesObject.from_dict(res, self) diff --git a/singlestoredb/management/workspace.py b/singlestoredb/management/workspace.py index cb6ff6e87..7c394ade2 100644 --- a/singlestoredb/management/workspace.py +++ b/singlestoredb/management/workspace.py @@ -378,7 +378,7 @@ def info(self, stage_path: PathLike) -> FilesObject: """ res = self._manager._get( re.sub(r'/+$', r'/', f'stage/{self._deployment_id}/fs/{stage_path}'), - params=dict(metadata=True), + params=dict(metadata=1), ).json() return FilesObject.from_dict(res, self) From f258fe8ad96d71ea47aa1b84ff95c05d7179f405 Mon Sep 17 00:00:00 2001 From: Kevin Smith Date: Fri, 10 Oct 2025 13:26:55 -0500 Subject: [PATCH 13/13] Disable legacy cluster API --- singlestoredb/tests/test_management.py | 1 + 1 file changed, 1 insertion(+) diff --git a/singlestoredb/tests/test_management.py b/singlestoredb/tests/test_management.py index b7ceb5e8d..dd176f3de 100755 --- a/singlestoredb/tests/test_management.py +++ b/singlestoredb/tests/test_management.py @@ -30,6 +30,7 @@ def shared_database_name(s): return re.sub(r'[^\w]', '', s).replace('-', '_').lower() +@pytest.mark.skip(reason='Legacy cluster Management API is going away') @pytest.mark.management class TestCluster(unittest.TestCase):