mirror of
https://github.com/tursodatabase/limbo.git
synced 2025-08-03 17:48:17 +00:00
ci: integrate pyo3
ci: add manylinux fix: maturin build error ci: add wheels upload ci: use venv
This commit is contained in:
parent
93964c6655
commit
fc2962e04e
9 changed files with 134 additions and 55 deletions
|
@ -17,7 +17,7 @@ extension-module = ["pyo3/extension-module"]
|
|||
[dependencies]
|
||||
anyhow = "1.0"
|
||||
limbo_core = { path = "../../core" }
|
||||
pyo3 = { version = "0.22.2", features = ["anyhow", "auto-initialize"] }
|
||||
pyo3 = { version = "0.22.2", features = ["anyhow"] }
|
||||
|
||||
[build-dependencies]
|
||||
version_check = "0.9.5"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from _limbo import (
|
||||
from ._limbo import (
|
||||
Connection,
|
||||
Cursor,
|
||||
DatabaseError,
|
||||
|
@ -14,16 +14,16 @@ from _limbo import (
|
|||
)
|
||||
|
||||
__all__ = [
|
||||
"__version__",
|
||||
"Connection",
|
||||
"Cursor",
|
||||
"InterfaceError",
|
||||
"DatabaseError",
|
||||
"DataError",
|
||||
"OperationalError",
|
||||
"IntegrityError",
|
||||
"InternalError",
|
||||
"ProgrammingError",
|
||||
"NotSupportedError",
|
||||
"connect",
|
||||
'__version__',
|
||||
'Connection',
|
||||
'Cursor',
|
||||
'InterfaceError',
|
||||
'DatabaseError',
|
||||
'DataError',
|
||||
'OperationalError',
|
||||
'IntegrityError',
|
||||
'InternalError',
|
||||
'ProgrammingError',
|
||||
'NotSupportedError',
|
||||
'connect',
|
||||
]
|
||||
|
|
|
@ -35,7 +35,6 @@ dynamic = [
|
|||
|
||||
[project.optional-dependencies]
|
||||
dev = [
|
||||
"maturin==1.7.0",
|
||||
"black==24.4.2",
|
||||
"isort==5.13.2",
|
||||
"mypy==1.11.0",
|
||||
|
@ -50,6 +49,8 @@ Source = "https://github.com/penberg/limbo"
|
|||
|
||||
[tool.maturin]
|
||||
bindings = 'pyo3'
|
||||
module-name = "limbo._limbo"
|
||||
features = ["pyo3/extension-module"]
|
||||
|
||||
[tool.ruff]
|
||||
line-length = 120
|
||||
|
@ -70,7 +71,6 @@ quote-style = 'single'
|
|||
testpaths = 'tests'
|
||||
log_format = '%(name)s %(levelname)s: %(message)s'
|
||||
|
||||
|
||||
[tool.coverage.run]
|
||||
source = ['limbo']
|
||||
branch = true
|
||||
|
|
|
@ -14,8 +14,6 @@ iniconfig==2.0.0
|
|||
# via pytest
|
||||
isort==5.13.2
|
||||
# via limbo (pyproject.toml)
|
||||
maturin==1.7.0
|
||||
# via limbo (pyproject.toml)
|
||||
mypy==1.11.0
|
||||
# via limbo (pyproject.toml)
|
||||
mypy-extensions==1.0.0
|
||||
|
|
8
bindings/python/requirements.txt
Normal file
8
bindings/python/requirements.txt
Normal file
|
@ -0,0 +1,8 @@
|
|||
#
|
||||
# This file is autogenerated by pip-compile with Python 3.11
|
||||
# by the following command:
|
||||
#
|
||||
# pip-compile --strip-extras pyproject.toml
|
||||
#
|
||||
typing-extensions==4.12.2
|
||||
# via limbo (pyproject.toml)
|
|
@ -119,22 +119,23 @@ impl Cursor {
|
|||
let mut smt_lock = smt.lock().map_err(|_| {
|
||||
PyErr::new::<OperationalError, _>("Failed to acquire statement lock")
|
||||
})?;
|
||||
|
||||
match smt_lock
|
||||
.step()
|
||||
.map_err(|e| PyErr::new::<OperationalError, _>(format!("Step error: {:?}", e)))?
|
||||
{
|
||||
limbo_core::RowResult::Row(row) => {
|
||||
let py_row = row_to_py(py, &row);
|
||||
Ok(Some(py_row))
|
||||
loop {
|
||||
match smt_lock.step().map_err(|e| {
|
||||
PyErr::new::<OperationalError, _>(format!("Step error: {:?}", e))
|
||||
})? {
|
||||
limbo_core::RowResult::Row(row) => {
|
||||
let py_row = row_to_py(py, &row);
|
||||
return Ok(Some(py_row));
|
||||
}
|
||||
limbo_core::RowResult::IO => {
|
||||
self.conn.io.run_once().map_err(|e| {
|
||||
PyErr::new::<OperationalError, _>(format!("IO error: {:?}", e))
|
||||
})?;
|
||||
}
|
||||
limbo_core::RowResult::Done => {
|
||||
return Ok(None);
|
||||
}
|
||||
}
|
||||
limbo_core::RowResult::IO => {
|
||||
self.conn.io.run_once().map_err(|e| {
|
||||
PyErr::new::<OperationalError, _>(format!("IO error: {:?}", e))
|
||||
})?;
|
||||
Ok(None)
|
||||
}
|
||||
limbo_core::RowResult::Done => Ok(None),
|
||||
}
|
||||
} else {
|
||||
Err(PyErr::new::<ProgrammingError, _>("No statement prepared for execution").into())
|
||||
|
@ -143,10 +144,33 @@ impl Cursor {
|
|||
|
||||
pub fn fetchall(&mut self, py: Python) -> Result<Vec<PyObject>> {
|
||||
let mut results = Vec::new();
|
||||
while let Some(row) = self.fetchone(py)? {
|
||||
results.push(row);
|
||||
|
||||
if let Some(smt) = &self.smt {
|
||||
let mut smt_lock = smt.lock().map_err(|_| {
|
||||
PyErr::new::<OperationalError, _>("Failed to acquire statement lock")
|
||||
})?;
|
||||
|
||||
loop {
|
||||
match smt_lock.step().map_err(|e| {
|
||||
PyErr::new::<OperationalError, _>(format!("Step error: {:?}", e))
|
||||
})? {
|
||||
limbo_core::RowResult::Row(row) => {
|
||||
let py_row = row_to_py(py, &row);
|
||||
results.push(py_row);
|
||||
}
|
||||
limbo_core::RowResult::IO => {
|
||||
self.conn.io.run_once().map_err(|e| {
|
||||
PyErr::new::<OperationalError, _>(format!("IO error: {:?}", e))
|
||||
})?;
|
||||
}
|
||||
limbo_core::RowResult::Done => {
|
||||
return Ok(results);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Err(PyErr::new::<ProgrammingError, _>("No statement prepared for execution").into())
|
||||
}
|
||||
Ok(results)
|
||||
}
|
||||
|
||||
pub fn close(&self) -> Result<()> {
|
||||
|
|
|
@ -5,53 +5,54 @@ import pytest
|
|||
import limbo
|
||||
|
||||
|
||||
@pytest.mark.parametrize("provider", ["sqlite3", "limbo"])
|
||||
@pytest.mark.parametrize('provider', ['sqlite3', 'limbo'])
|
||||
def test_fetchall_select_all_users(provider):
|
||||
conn = connect(provider, "tests/database.db")
|
||||
conn = connect(provider, 'tests/database.db')
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("SELECT * FROM users")
|
||||
cursor.execute('SELECT * FROM users')
|
||||
|
||||
users = cursor.fetchall()
|
||||
assert users
|
||||
assert users == [(1, "alice"), (2, "bob")]
|
||||
assert users == [(1, 'alice'), (2, 'bob')]
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"provider",
|
||||
'provider',
|
||||
[
|
||||
"sqlite3",
|
||||
'sqlite3',
|
||||
'limbo'
|
||||
],
|
||||
)
|
||||
def test_fetchall_select_user_ids(provider):
|
||||
conn = connect(provider, "tests/database.db")
|
||||
conn = connect(provider, 'tests/database.db')
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("SELECT id FROM users")
|
||||
cursor.execute('SELECT id FROM users')
|
||||
|
||||
user_ids = cursor.fetchall()
|
||||
assert user_ids
|
||||
assert user_ids == [(1,), (2,)]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("provider", ["sqlite3", "limbo"])
|
||||
@pytest.mark.parametrize('provider', ['sqlite3', 'limbo'])
|
||||
def test_fetchone_select_all_users(provider):
|
||||
conn = connect(provider, "tests/database.db")
|
||||
conn = connect(provider, 'tests/database.db')
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("SELECT * FROM users")
|
||||
cursor.execute('SELECT * FROM users')
|
||||
|
||||
alice = cursor.fetchone()
|
||||
assert alice
|
||||
assert alice == (1, "alice")
|
||||
assert alice == (1, 'alice')
|
||||
|
||||
bob = cursor.fetchone()
|
||||
assert bob
|
||||
assert bob == (2, "bob")
|
||||
assert bob == (2, 'bob')
|
||||
|
||||
|
||||
@pytest.mark.parametrize("provider", ["sqlite3", "limbo"])
|
||||
@pytest.mark.parametrize('provider', ['sqlite3', 'limbo'])
|
||||
def test_fetchone_select_max_user_id(provider):
|
||||
conn = connect(provider, "tests/database.db")
|
||||
conn = connect(provider, 'tests/database.db')
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("SELECT MAX(id) FROM users")
|
||||
cursor.execute('SELECT MAX(id) FROM users')
|
||||
|
||||
max_id = cursor.fetchone()
|
||||
assert max_id
|
||||
|
@ -59,8 +60,8 @@ def test_fetchone_select_max_user_id(provider):
|
|||
|
||||
|
||||
def connect(provider, database):
|
||||
if provider == "limbo":
|
||||
if provider == 'limbo':
|
||||
return limbo.connect(database)
|
||||
if provider == "sqlite3":
|
||||
if provider == 'sqlite3':
|
||||
return sqlite3.connect(database)
|
||||
raise Exception(f"Provider `{provider}` is not supported")
|
||||
raise Exception(f'Provider `{provider}` is not supported')
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue