bindings/python: Rename package to pyturso

This commit is contained in:
Pekka Enberg 2025-06-27 10:58:57 +03:00
parent e23835ed8e
commit a5b539f1bf
24 changed files with 64 additions and 247 deletions

2
Cargo.lock generated
View file

@ -2716,7 +2716,7 @@ dependencies = [
]
[[package]]
name = "py-limbo"
name = "py-turso"
version = "0.0.22"
dependencies = [
"anyhow",

View file

@ -125,9 +125,9 @@ pip install pylimbo
Example usage:
```python
import limbo
import turso
con = limbo.connect("sqlite.db")
con = turso.connect("sqlite.db")
cur = con.cursor()
res = cur.execute("SELECT * FROM users")
print(res.fetchone())

View file

@ -1,10 +1,10 @@
#!/usr/bin/env -S python3 -u
import limbo
import turso
from antithesis.assertions import always
try:
con = limbo.connect("bank_test.db")
con = turso.connect("bank_test.db")
except Exception as e:
print(f"Error connecting to database: {e}")
exit(0)

View file

@ -1,10 +1,10 @@
#!/usr/bin/env -S python3 -u
import limbo
import turso
from antithesis.assertions import always
try:
con = limbo.connect("bank_test.db")
con = turso.connect("bank_test.db")
except Exception as e:
print(f"Error connecting to database: {e}")
exit(0)

View file

@ -1,10 +1,10 @@
#!/usr/bin/env -S python3 -u
import limbo
import turso
from antithesis.assertions import always
try:
con = limbo.connect("bank_test.db")
con = turso.connect("bank_test.db")
except Exception as e:
print(f"Error connecting to database: {e}")
exit(0)

View file

@ -1,10 +1,10 @@
#!/usr/bin/env -S python3 -u
import limbo
import turso
from antithesis.random import get_random
try:
con = limbo.connect("bank_test.db")
con = turso.connect("bank_test.db")
except Exception as e:
print(f"Error connecting to database: {e}")
exit(0)

View file

@ -3,7 +3,7 @@
import logging
from logging.handlers import RotatingFileHandler
import limbo
import turso
from antithesis.random import get_random
handler = RotatingFileHandler(
@ -17,7 +17,7 @@ logger.setLevel(logging.INFO)
logger.addHandler(handler)
try:
con = limbo.connect("bank_test.db")
con = turso.connect("bank_test.db")
except Exception as e:
print(f"Error connecting to database: {e}")
exit(0)

View file

@ -1,7 +1,7 @@
[project]
dependencies = [
"antithesis>=0.1.17",
"pylimbo"
"pyturso"
]
description = "Add your description here"
name = "antithesis-tests"
@ -9,4 +9,4 @@ requires-python = ">=3.13"
version = "0.1.0"
[tool.uv.sources]
pylimbo = { workspace = true }
pyturso = { workspace = true }

View file

@ -4,7 +4,7 @@ import glob
import json
import os
import limbo
import turso
from antithesis.random import get_random, random_choice
constraints = ["NOT NULL", ""]
@ -25,7 +25,7 @@ for f in glob.glob("*.db-wal"):
# store initial states in a separate db
try:
con_init = limbo.connect("init_state.db")
con_init = turso.connect("init_state.db")
except Exception as e:
print(f"Error connecting to database: {e}")
exit(0)
@ -35,7 +35,7 @@ cur_init.execute("CREATE TABLE schemas (schema TEXT, tbl INT)")
cur_init.execute("CREATE TABLE tables (count INT)")
try:
con = limbo.connect("stress_composer.db")
con = turso.connect("stress_composer.db")
except Exception as e:
print(f"Error connecting to database: {e}")
exit(0)

View file

@ -2,13 +2,13 @@
import json
import limbo
import turso
from antithesis.random import get_random
from utils import generate_random_value
# Get initial state
try:
con_init = limbo.connect("init_state.db")
con_init = turso.connect("init_state.db")
except Exception as e:
print(f"Error connecting to database: {e}")
exit(0)
@ -25,7 +25,7 @@ pk = tbl_schema["pk"]
cols = [f"col_{col}" for col in range(tbl_schema["colCount"]) if col != pk]
try:
con = limbo.connect("stress_composer.db")
con = turso.connect("stress_composer.db")
except Exception as e:
print(f"Failed to open stress_composer.db. Exiting... {e}")
exit(0)

View file

@ -2,13 +2,13 @@
import json
import limbo
import turso
from antithesis.random import get_random
from utils import generate_random_value
# Get initial state
try:
con_init = limbo.connect("init_state.db")
con_init = turso.connect("init_state.db")
except Exception as e:
print(f"Error connecting to database: {e}")
exit(0)
@ -21,7 +21,7 @@ tbl_schema = json.loads(cur_init.execute(f"SELECT schema FROM schemas WHERE tbl
cols = ", ".join([f"col_{col}" for col in range(tbl_schema["colCount"])])
try:
con = limbo.connect("stress_composer.db")
con = turso.connect("stress_composer.db")
except Exception as e:
print(f"Failed to open stress_composer.db. Exiting... {e}")
exit(0)
@ -39,7 +39,7 @@ for i in range(insertions):
INSERT INTO tbl_{selected_tbl} ({cols})
VALUES ({", ".join(values)})
""")
except limbo.OperationalError as e:
except turso.OperationalError as e:
if "UNIQUE constraint failed" in str(e):
# Ignore UNIQUE constraint violations
pass

View file

@ -2,13 +2,13 @@
import json
import limbo
import turso
from antithesis.assertions import always
from antithesis.random import get_random
# Get initial state
try:
con_init = limbo.connect("init_state.db")
con_init = turso.connect("init_state.db")
except Exception as e:
print(f"Error connecting to database: {e}")
exit(0)
@ -21,7 +21,7 @@ tbl_schema = json.loads(cur_init.execute(f"SELECT schema FROM schemas WHERE tbl
cols = ", ".join([f"col_{col}" for col in range(tbl_schema["colCount"])])
try:
con = limbo.connect("stress_composer.db")
con = turso.connect("stress_composer.db")
except Exception as e:
print(f"Failed to open stress_composer.db. Exiting... {e}")
exit(0)

View file

@ -2,13 +2,13 @@
import json
import limbo
import turso
from antithesis.random import get_random
from utils import generate_random_value
# Get initial state
try:
con_init = limbo.connect("init_state.db")
con_init = turso.connect("init_state.db")
except Exception as e:
print(f"Error connecting to database: {e}")
exit(0)
@ -21,7 +21,7 @@ tbl_schema = json.loads(cur_init.execute(f"SELECT schema FROM schemas WHERE tbl
cols = ", ".join([f"col_{col}" for col in range(tbl_schema["colCount"])])
try:
con = limbo.connect("stress_composer.db")
con = turso.connect("stress_composer.db")
except Exception as e:
print(f"Failed to open stress_composer.db. Exiting... {e}")
exit(0)
@ -39,7 +39,7 @@ for i in range(insertions):
INSERT INTO tbl_{selected_tbl} ({cols})
VALUES ({", ".join(values)})
""")
except limbo.OperationalError as e:
except turso.OperationalError as e:
if "UNIQUE constraint failed" in str(e):
# Ignore UNIQUE constraint violations
pass

View file

@ -2,13 +2,13 @@
import json
import limbo
import turso
from antithesis.random import get_random
from utils import generate_random_value
# Get initial state
try:
con_init = limbo.connect("init_state.db")
con_init = turso.connect("init_state.db")
except Exception as e:
print(f"Error connecting to database: {e}")
exit(0)
@ -25,7 +25,7 @@ pk = tbl_schema["pk"]
cols = [f"col_{col}" for col in range(tbl_schema["colCount"]) if col != pk]
# print(cols)
try:
con = limbo.connect("stress_composer.db")
con = turso.connect("stress_composer.db")
except Exception as e:
print(f"Failed to open stress_composer.db. Exiting... {e}")
exit(0)
@ -53,7 +53,7 @@ for i in range(updates):
cur.execute(f"""
UPDATE tbl_{selected_tbl} SET {set_clause} WHERE {where_clause}
""")
except limbo.OperationalError as e:
except turso.OperationalError as e:
if "UNIQUE constraint failed" in str(e):
# Ignore UNIQUE constraint violations
pass

View file

@ -1,5 +1,5 @@
[package]
name = "py-limbo"
name = "py-turso"
version.workspace = true
authors.workspace = true
edition.workspace = true
@ -8,7 +8,7 @@ repository.workspace = true
publish = false
[lib]
name = "_limbo"
name = "_turso"
crate-type = ["cdylib"]
[features]

View file

@ -1,7 +1,7 @@
import limbo
import turso
# Use the context manager to automatically close the connection
with limbo.connect("sqlite.db") as con:
with turso.connect("sqlite.db") as con:
cur = con.cursor()
cur.execute("""
CREATE TABLE IF NOT EXISTS users (

View file

@ -1,183 +0,0 @@
from typing import Any, List, Optional, Tuple
__version__: str
class Connection:
def cursor(self) -> "Cursor":
"""
Creates a new cursor object using this connection.
:return: A new Cursor object.
:raises InterfaceError: If the cursor cannot be created.
"""
...
def close(self) -> None:
"""
Closes the connection to the database.
:raises OperationalError: If there is an error closing the connection.
"""
...
def commit(self) -> None:
"""
Commits the current transaction.
:raises OperationalError: If there is an error during commit.
"""
...
def rollback(self) -> None:
"""
Rolls back the current transaction.
:raises OperationalError: If there is an error during rollback.
"""
...
class Cursor:
arraysize: int
description: Optional[
Tuple[
str,
str,
Optional[str],
Optional[str],
Optional[str],
Optional[str],
Optional[str],
]
]
rowcount: int
def execute(self, sql: str, parameters: Optional[Tuple[Any, ...]] = None) -> "Cursor":
"""
Prepares and executes a SQL statement using the connection.
:param sql: The SQL query to execute.
:param parameters: The parameters to substitute into the SQL query.
:raises ProgrammingError: If there is an error in the SQL query.
:raises OperationalError: If there is an error executing the query.
:return: The cursor object.
"""
...
def executemany(self, sql: str, parameters: Optional[List[Tuple[Any, ...]]] = None) -> None:
"""
Executes a SQL command against all parameter sequences or mappings found in the sequence `parameters`.
:param sql: The SQL command to execute.
:param parameters: A list of parameter sequences or mappings.
:raises ProgrammingError: If there is an error in the SQL query.
:raises OperationalError: If there is an error executing the query.
"""
...
def fetchone(self) -> Optional[Tuple[Any, ...]]:
"""
Fetches the next row from the result set.
:return: A tuple representing the next row, or None if no more rows are available.
:raises OperationalError: If there is an error fetching the row.
"""
...
def fetchall(self) -> List[Tuple[Any, ...]]:
"""
Fetches all remaining rows from the result set.
:return: A list of tuples, each representing a row in the result set.
:raises OperationalError: If there is an error fetching the rows.
"""
...
def fetchmany(self, size: Optional[int] = None) -> List[Tuple[Any, ...]]:
"""
Fetches the next set of rows of a size specified by the `arraysize` property.
:param size: Optional integer to specify the number of rows to fetch.
:return: A list of tuples, each representing a row in the result set.
:raises OperationalError: If there is an error fetching the rows.
"""
...
def close(self) -> None:
"""
Closes the cursor.
:raises OperationalError: If there is an error closing the cursor.
"""
...
# Exception classes
class Warning(Exception):
"""Exception raised for important warnings like data truncations while inserting."""
...
class Error(Exception):
"""Base class for all other error exceptions. Catch all database-related errors using this class."""
...
class InterfaceError(Error):
"""Exception raised for errors related to the database interface rather than the database itself."""
...
class DatabaseError(Error):
"""Exception raised for errors that are related to the database."""
...
class DataError(DatabaseError):
"""
Exception raised for errors due to problems with the processed data like division by zero, numeric value out of
range, etc.
"""
...
class OperationalError(DatabaseError):
"""
Exception raised for errors related to the databases operation, not necessarily under the programmer's control.
"""
...
class IntegrityError(DatabaseError):
"""Exception raised when the relational integrity of the database is affected, e.g., a foreign key check fails."""
...
class InternalError(DatabaseError):
"""
Exception raised when the database encounters an internal error, e.g., cursor is not valid anymore, transaction out
of sync.
"""
...
class ProgrammingError(DatabaseError):
"""
Exception raised for programming errors, e.g., table not found, syntax error in SQL, wrong number of parameters
specified.
"""
...
class NotSupportedError(DatabaseError):
"""Exception raised when a method or database API is used which is not supported by the database."""
...
def connect(path: str) -> Connection:
"""
Connects to a database at the specified path.
:param path: The path to the database file.
:return: A Connection object to the database.
:raises InterfaceError: If the database cannot be connected.
"""
...

View file

@ -3,7 +3,7 @@ requires = ['maturin>=1,<2', 'typing_extensions']
build-backend = 'maturin'
[project]
name = 'pylimbo'
name = 'pyturso'
description = "Limbo is a work-in-progress, in-process OLTP database management system, compatible with SQLite."
requires-python = '>=3.9'
classifiers = [
@ -45,7 +45,7 @@ Source = "https://github.com/tursodatabase/limbo"
[tool.maturin]
bindings = 'pyo3'
module-name = "limbo._limbo"
module-name = "turso._turso"
features = ["pyo3/extension-module"]
[tool.pip-tools]
@ -58,7 +58,7 @@ testpaths = 'tests'
log_format = '%(name)s %(levelname)s: %(message)s'
[tool.coverage.run]
source = ['limbo']
source = ['turso']
branch = true
[tool.coverage.report]

View file

@ -1,13 +1,13 @@
coverage==7.6.1
# via
# pylimbo (pyproject.toml)
# pyturso (pyproject.toml)
# pytest-cov
iniconfig==2.0.0
# via pytest
maturin==1.7.8
# via pylimbo (pyproject.toml)
# via pyturso (pyproject.toml)
mypy==1.11.0
# via pylimbo (pyproject.toml)
# via pyturso (pyproject.toml)
mypy-extensions==1.0.0
# via mypy
packaging==24.2
@ -16,13 +16,13 @@ pluggy==1.5.0
# via pytest
pytest==8.3.1
# via
# pylimbo (pyproject.toml)
# pyturso (pyproject.toml)
# pytest-cov
pytest-cov==5.0.0
# via pylimbo (pyproject.toml)
# via pyturso (pyproject.toml)
ruff==0.5.4
# via pylimbo (pyproject.toml)
# via pyturso (pyproject.toml)
typing-extensions==4.12.2
# via
# mypy
# pylimbo (pyproject.toml)
# pyturso (pyproject.toml)

View file

@ -1,2 +1,2 @@
typing-extensions==4.12.2
# via pylimbo (pyproject.toml)
# via pyturso (pyproject.toml)

View file

@ -365,7 +365,7 @@ fn py_to_owned_value(obj: &Bound<PyAny>) -> Result<limbo_core::Value> {
}
#[pymodule]
fn _limbo(m: &Bound<PyModule>) -> PyResult<()> {
fn _turso(m: &Bound<PyModule>) -> PyResult<()> {
m.add("__version__", env!("CARGO_PKG_VERSION"))?;
m.add_class::<Connection>()?;
m.add_class::<Cursor>()?;

View file

@ -1,8 +1,8 @@
import os
import sqlite3
import limbo
import pytest
import turso
@pytest.fixture(autouse=True)
@ -48,7 +48,7 @@ def setup_database():
print(f"Failed to clean up: {e}")
@pytest.mark.parametrize("provider", ["sqlite3", "limbo"])
@pytest.mark.parametrize("provider", ["sqlite3", "turso"])
def test_fetchall_select_all_users(provider, setup_database):
conn = connect(provider, setup_database)
cursor = conn.cursor()
@ -61,7 +61,7 @@ def test_fetchall_select_all_users(provider, setup_database):
assert users == [(1, "alice"), (2, "bob")]
@pytest.mark.parametrize("provider", ["sqlite3", "limbo"])
@pytest.mark.parametrize("provider", ["sqlite3", "turso"])
def test_fetchall_select_user_ids(provider):
conn = connect(provider, "tests/database.db")
cursor = conn.cursor()
@ -74,7 +74,7 @@ def test_fetchall_select_user_ids(provider):
assert user_ids == [(1,), (2,)]
@pytest.mark.parametrize("provider", ["sqlite3", "limbo"])
@pytest.mark.parametrize("provider", ["sqlite3", "turso"])
def test_in_memory_fetchone_select_all_users(provider):
conn = connect(provider, ":memory:")
cursor = conn.cursor()
@ -90,7 +90,7 @@ def test_in_memory_fetchone_select_all_users(provider):
assert alice == (1, "alice")
@pytest.mark.parametrize("provider", ["sqlite3", "limbo"])
@pytest.mark.parametrize("provider", ["sqlite3", "turso"])
def test_fetchone_select_all_users(provider):
conn = connect(provider, "tests/database.db")
cursor = conn.cursor()
@ -107,7 +107,7 @@ def test_fetchone_select_all_users(provider):
assert bob == (2, "bob")
@pytest.mark.parametrize("provider", ["sqlite3", "limbo"])
@pytest.mark.parametrize("provider", ["sqlite3", "turso"])
def test_fetchone_select_max_user_id(provider):
conn = connect(provider, "tests/database.db")
cursor = conn.cursor()
@ -120,8 +120,8 @@ def test_fetchone_select_max_user_id(provider):
assert max_id == (2,)
# Test case for: https://github.com/tursodatabase/limbo/issues/494
@pytest.mark.parametrize("provider", ["sqlite3", "limbo"])
# Test case for: https://github.com/tursodatabase/turso/issues/494
@pytest.mark.parametrize("provider", ["sqlite3", "turso"])
def test_commit(provider):
conn = connect(provider, "tests/database.db")
cur = conn.cursor()
@ -158,7 +158,7 @@ def test_commit(provider):
assert record
@pytest.mark.parametrize("provider", ["sqlite3", "limbo"])
@pytest.mark.parametrize("provider", ["sqlite3", "turso"])
def test_with_statement(provider):
with connect(provider, "tests/database.db") as conn:
cursor = conn.cursor()
@ -171,8 +171,8 @@ def test_with_statement(provider):
def connect(provider, database):
if provider == "limbo":
return limbo.connect(database)
if provider == "turso":
return turso.connect(database)
if provider == "sqlite3":
return sqlite3.connect(database)
raise Exception(f"Provider `{provider}` is not supported")

View file

@ -1,4 +1,4 @@
from ._limbo import (
from ._turso import (
Connection,
Cursor,
DatabaseError,