Skip to content

Commit 8b77490

Browse files
kesmit13claude
andcommitted
feature: Modernize the build and install system
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 <noreply@anthropic.com>
1 parent a3aa638 commit 8b77490

File tree

23 files changed

+156
-177
lines changed

23 files changed

+156
-177
lines changed

.flake8

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
[flake8]
2+
exclude =
3+
docs/*
4+
resources/*
5+
licenses/*
6+
max-complexity = 45
7+
max-line-length = 90
8+
min-python-version = 3.9.0
9+
per-file-ignores =
10+
singlestoredb/__init__.py:F401
11+
singlestoredb/fusion/__init__.py:F401
12+
singlestoredb/fusion/grammar.py:E501
13+
singlestoredb/http/__init__.py:F401
14+
singlestoredb/management/__init__.py:F401
15+
singlestoredb/mysql/__init__.py:F401

.pre-commit-config.yaml

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,12 @@ repos:
2929
rev: v3.12.0
3030
hooks:
3131
- id: reorder-python-imports
32-
args: [--py36-plus]
32+
args: [--py39-plus]
3333
- repo: https://github.com/asottile/add-trailing-comma
3434
rev: v3.1.0
3535
hooks:
3636
- id: add-trailing-comma
3737
args: [--py36-plus]
38-
- repo: https://github.com/asottile/setup-cfg-fmt
39-
rev: v2.5.0
40-
hooks:
41-
- id: setup-cfg-fmt
4238
- repo: https://github.com/pre-commit/mirrors-mypy
4339
rev: v1.14.1
4440
hooks:

RELEASE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ resources/bump_version.py < major | minor | patch >
88
99
```
1010

11-
This will bump the version number in `setup.cfg` and `singlestoredb/__init__.py`
11+
This will bump the version number in `pyproject.toml` and `singlestoredb/__init__.py`
1212
using semantic versioning rules: minor bump for new features, patch bump for
1313
bug fixes. It will genarete a list of changes since the last version and
1414
ask for confirmation of the release notes in `docs/src/whatsnew.rst`.

pyproject.toml

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
[build-system]
2+
requires = ["build", "setuptools>=61.0", "wheel"]
3+
build-backend = "setuptools.build_meta"
4+
5+
[project]
6+
name = "singlestoredb"
7+
version = "1.15.8"
8+
description = "Interface to the SingleStoreDB database and workspace management APIs"
9+
readme = {file = "README.md", content-type = "text/markdown"}
10+
license = "Apache-2.0"
11+
license-files = ["LICENSE"]
12+
authors = [
13+
{name = "SingleStore", email = "support@singlestore.com"}
14+
]
15+
requires-python = ">=3.9"
16+
classifiers = [
17+
"Development Status :: 5 - Production/Stable",
18+
"Programming Language :: Python :: 3",
19+
"Programming Language :: Python :: 3 :: Only",
20+
"Topic :: Database",
21+
]
22+
dependencies = [
23+
"PyJWT",
24+
"parsimonious",
25+
"requests",
26+
"sqlparams",
27+
"tomli>=1.1.0; python_version < '3.11'",
28+
"typing-extensions<=4.13.2; python_version < '3.11'",
29+
]
30+
31+
[project.urls]
32+
Homepage = "https://github.com/singlestore-labs/singlestoredb-python"
33+
34+
[project.optional-dependencies]
35+
dataframe = ["ibis-singlestoredb"]
36+
dbt = ["dbt-singlestore"]
37+
docker = ["docker"]
38+
ed22519 = ["PyNaCl>=1.4.0"]
39+
gssapi = ["gssapi"]
40+
ibis = ["ibis-singlestoredb"]
41+
kerberos = ["gssapi"]
42+
pytest = ["pytest"]
43+
rsa = ["cryptography"]
44+
sqlalchemy = ["sqlalchemy-singlestoredb>=1.0.0"]
45+
vectorstore = ["singlestore-vectorstore>=0.1.2"]
46+
47+
[project.entry-points.pytest11]
48+
singlestoredb = "singlestoredb.pytest"
49+
50+
[tool.setuptools]
51+
include-package-data = true
52+
53+
[tool.setuptools.packages.find]
54+
exclude = ["docs*", "resources*", "examples*", "licenses*"]
55+
56+
[tool.setuptools.package-data]
57+
"*" = ["*.typed", "*.sql", "*.csv", "*.ipynb"]
58+
59+
[tool.pytest.ini_options]
60+
markers = [
61+
"management",
62+
]
63+
64+
[tool.mypy]
65+
check_untyped_defs = true
66+
disallow_any_generics = true
67+
disallow_incomplete_defs = true
68+
disallow_untyped_defs = true
69+
no_implicit_optional = true
70+
warn_redundant_casts = true
71+
warn_unused_ignores = false
72+
73+
[[tool.mypy.overrides]]
74+
module = "testing.*"
75+
disallow_untyped_defs = false
76+
77+
[[tool.mypy.overrides]]
78+
module = "tests.*"
79+
disallow_untyped_defs = false
80+
81+
[tool.coverage.run]
82+
source_pkgs = ["singlestoredb"]
83+
84+
[tool.coverage.report]
85+
omit = [
86+
"setup.py",
87+
"*/tests/*",
88+
"*/docs/*",
89+
]

resources/build_docs.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@
2727
import sys
2828
import time
2929
from pathlib import Path
30+
from re import Match
3031
from typing import Any
3132
from typing import Dict
3233
from typing import List
33-
from typing import Match
3434
from typing import Optional
3535

3636
# Detect script location and set up paths

resources/bump_version.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,14 @@ def step(step_num: int, total_steps: int, message: str) -> None:
3636

3737

3838
def get_current_version() -> str:
39-
"""Get the current version from setup.cfg."""
40-
setup_cfg_path = Path(__file__).parent.parent / 'setup.cfg'
41-
with open(setup_cfg_path, 'r') as f:
39+
"""Get the current version from pyproject.toml."""
40+
pyproject_path = Path(__file__).parent.parent / 'pyproject.toml'
41+
with open(pyproject_path, 'r') as f:
4242
content = f.read()
4343

44-
match = re.search(r'^version\s*=\s*(.+)$', content, re.MULTILINE)
44+
match = re.search(r'^version\s*=\s*["\'](.+)["\']$', content, re.MULTILINE)
4545
if not match:
46-
raise ValueError('Could not find version in setup.cfg')
46+
raise ValueError('Could not find version in pyproject.toml')
4747

4848
return match.group(1).strip()
4949

@@ -75,10 +75,10 @@ def update_version_in_file(file_path: Path, old_version: str, new_version: str)
7575
with open(file_path, 'r') as f:
7676
content = f.read()
7777

78-
# For setup.cfg
79-
if file_path.name == 'setup.cfg':
80-
pattern = r'^(version\s*=\s*)' + re.escape(old_version) + r'$'
81-
replacement = r'\g<1>' + new_version
78+
# For pyproject.toml
79+
if file_path.name == 'pyproject.toml':
80+
pattern = r'^(version\s*=\s*["\'])' + re.escape(old_version) + r'(["\'])$'
81+
replacement = r'\g<1>' + new_version + r'\g<2>'
8282
content = re.sub(pattern, replacement, content, flags=re.MULTILINE)
8383

8484
# For __init__.py
@@ -307,7 +307,7 @@ def stage_files() -> None:
307307
status('📦 Staging files for commit...')
308308

309309
files_to_stage = [
310-
'setup.cfg',
310+
'pyproject.toml',
311311
'singlestoredb/__init__.py',
312312
'docs/src/whatsnew.rst',
313313
'docs/', # All generated documentation files
@@ -360,8 +360,8 @@ def main() -> None:
360360
step(2, 6, 'Updating version in files')
361361
start_time = time.time()
362362

363-
update_version_in_file(Path(__file__).parent.parent / 'setup.cfg', current_version, new_version)
364-
status(' ✓ Updated setup.cfg')
363+
update_version_in_file(Path(__file__).parent.parent / 'pyproject.toml', current_version, new_version)
364+
status(' ✓ Updated pyproject.toml')
365365

366366
update_version_in_file(
367367
Path(__file__).parent.parent / 'singlestoredb' / '__init__.py',
@@ -399,7 +399,7 @@ def main() -> None:
399399
status('🔄 Reverting version changes...')
400400

401401
# Revert version changes
402-
update_version_in_file(Path(__file__).parent.parent / 'setup.cfg', new_version, current_version)
402+
update_version_in_file(Path(__file__).parent.parent / 'pyproject.toml', new_version, current_version)
403403
update_version_in_file(
404404
Path(__file__).parent.parent / 'singlestoredb' / '__init__.py',
405405
new_version,

resources/create_release.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
python create_release.py [--version VERSION] [--dry-run]
1414
1515
Examples:
16-
python create_release.py # Use current version from setup.cfg
16+
python create_release.py # Use current version from pyproject.toml
1717
python create_release.py --version 1.15.6 # Use specific version
1818
python create_release.py --dry-run # Preview without executing
1919
"""
@@ -39,19 +39,19 @@ def step(step_num: int, total_steps: int, message: str) -> None:
3939
print(f'📍 Step {step_num}/{total_steps}: {message}', file=sys.stderr)
4040

4141

42-
def get_version_from_setup_cfg() -> str:
43-
"""Extract the current version from setup.cfg."""
44-
setup_cfg_path = Path(__file__).parent.parent / 'setup.cfg'
42+
def get_version_from_pyproject() -> str:
43+
"""Extract the current version from pyproject.toml."""
44+
pyproject_path = Path(__file__).parent.parent / 'pyproject.toml'
4545

46-
if not setup_cfg_path.exists():
47-
raise FileNotFoundError(f'Could not find setup.cfg at {setup_cfg_path}')
46+
if not pyproject_path.exists():
47+
raise FileNotFoundError(f'Could not find pyproject.toml at {pyproject_path}')
4848

49-
with open(setup_cfg_path, 'r') as f:
49+
with open(pyproject_path, 'r') as f:
5050
content = f.read()
5151

52-
match = re.search(r'^version\s*=\s*(.+)$', content, re.MULTILINE)
52+
match = re.search(r'^version\s*=\s*["\'](.+)["\']$', content, re.MULTILINE)
5353
if not match:
54-
raise ValueError('Could not find version in setup.cfg')
54+
raise ValueError('Could not find version in pyproject.toml')
5555

5656
return match.group(1).strip()
5757

@@ -228,14 +228,14 @@ def main() -> None:
228228
description='Create GitHub release for SingleStoreDB Python SDK',
229229
formatter_class=argparse.RawDescriptionHelpFormatter,
230230
epilog='''Examples:
231-
%(prog)s # Use current version from setup.cfg
231+
%(prog)s # Use current version from pyproject.toml
232232
%(prog)s --version 1.15.6 # Use specific version
233233
%(prog)s --dry-run # Preview without executing''',
234234
)
235235

236236
parser.add_argument(
237237
'--version',
238-
help='Version to release (default: extract from setup.cfg)',
238+
help='Version to release (default: extract from pyproject.toml)',
239239
)
240240

241241
parser.add_argument(
@@ -267,8 +267,8 @@ def main() -> None:
267267
version = args.version
268268
status(f'Using specified version: {version}')
269269
else:
270-
version = get_version_from_setup_cfg()
271-
status(f'Extracted from setup.cfg: {version}')
270+
version = get_version_from_pyproject()
271+
status(f'Extracted from pyproject.toml: {version}')
272272

273273
elapsed = time.time() - start_time
274274
status(f'✅ Version determined in {elapsed:.1f}s')

setup.cfg

Lines changed: 0 additions & 121 deletions
This file was deleted.

0 commit comments

Comments
 (0)