From 1d6336208d0d7fb52f7fe9f47161d1e14d8e9633 Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Wed, 27 May 2026 18:27:27 -0700 Subject: [PATCH 1/4] Revert "Statically link JSON extension in pybind CI" This reverts commit 13d6905594093172d554eb37fda77eda894b7d46. --- .github/workflows/ci.yml | 3 +-- test/test_json.py | 2 ++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3b34cd5..10d0cb2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -140,7 +140,7 @@ jobs: - name: Update submodules working-directory: ladybug - run: git submodule update --init --recursive dataset extension + run: git submodule update --init --recursive dataset - name: Checkout ladybug-python into ladybug/tools/python_api uses: actions/checkout@v4 @@ -191,7 +191,6 @@ jobs: GEN: Ninja CMAKE_C_COMPILER_LAUNCHER: ccache CMAKE_CXX_COMPILER_LAUNCHER: ccache - EXTRA_CMAKE_FLAGS: -DBUILD_EXTENSIONS=json -DEXTENSION_STATIC_LINK_LIST=json run: | make python cp tools/python_api/src_py/*.py tools/python_api/build/ladybug/ diff --git a/test/test_json.py b/test/test_json.py index 376bba3..d7a7e9a 100644 --- a/test/test_json.py +++ b/test/test_json.py @@ -11,6 +11,8 @@ def test_to_json_string_param_roundtrip(conn_db_empty: ConnDB) -> None: """to_json() with a JSON string parameter should store the parsed object, not a string literal.""" conn, _ = conn_db_empty conn.execute(""" + INSTALL json; + LOAD json; CREATE NODE TABLE User (id SERIAL PRIMARY KEY, meta JSON); """) From 2e508ddcc7856f3daf00d1abbfbc626a769040d4 Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Thu, 28 May 2026 10:51:33 -0700 Subject: [PATCH 2/4] Close test database fixtures explicitly --- test/conftest.py | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/test/conftest.py b/test/conftest.py index ca0c583..fe29aa0 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -194,13 +194,17 @@ def init_db(path: Path) -> Path: Path.mkdir(path) db_path = get_db_file_path(path) - conn, _ = create_conn_db(db_path, read_only=False) - init_tinysnb(conn) - init_demo(conn) - init_npy(conn) - init_tensor(conn) - init_long_str(conn) - init_movie_serial(conn) + conn, db = create_conn_db(db_path, read_only=False) + try: + init_tinysnb(conn) + init_demo(conn) + init_npy(conn) + init_tensor(conn) + init_long_str(conn) + init_movie_serial(conn) + finally: + conn.close() + db.close() return db_path @@ -241,7 +245,12 @@ def conn_db_readonly(tmp_path: Path) -> ConnDB: @pytest.fixture def conn_db_readwrite(tmp_path: Path) -> ConnDB: """Return a new writable connection and database.""" - return create_conn_db(init_db(tmp_path), read_only=False) + conn, db = create_conn_db(init_db(tmp_path), read_only=False) + try: + yield conn, db + finally: + conn.close() + db.close() @pytest.fixture @@ -271,7 +280,12 @@ def async_connection_readwrite(tmp_path: Path) -> lb.AsyncConnection: @pytest.fixture def conn_db_empty(tmp_path: Path) -> ConnDB: """Return a new empty connection and database.""" - return create_conn_db(get_db_file_path(tmp_path), read_only=False) + conn, db = create_conn_db(get_db_file_path(tmp_path), read_only=False) + try: + yield conn, db + finally: + conn.close() + db.close() @pytest.fixture @@ -281,7 +295,11 @@ def conn_db_in_mem() -> ConnDB: database_path=":memory:", buffer_pool_size=_POOL_SIZE_, read_only=False ) conn = lb.Connection(db, num_threads=4) - return conn, db + try: + yield conn, db + finally: + conn.close() + db.close() def pytest_sessionfinish(session: pytest.Session, exitstatus: int) -> None: From 0f4af1bc6c18806760b78423a1e5b27e1271c6ec Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Thu, 28 May 2026 11:20:53 -0700 Subject: [PATCH 3/4] Close async read-only fixture per test --- test/conftest.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/test/conftest.py b/test/conftest.py index fe29aa0..a8a6329 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -255,13 +255,15 @@ def conn_db_readwrite(tmp_path: Path) -> ConnDB: @pytest.fixture def async_connection_readonly(tmp_path: Path) -> lb.AsyncConnection: - """Return a cached read-only async connection.""" - global _READONLY_ASYNC_CONNECTION_ - if _READONLY_ASYNC_CONNECTION_ is None: - conn, db = create_conn_db(init_db(tmp_path), read_only=True) - conn.close() - _READONLY_ASYNC_CONNECTION_ = lb.AsyncConnection(db, max_threads_per_query=4) - return _READONLY_ASYNC_CONNECTION_ + """Return a read-only async connection.""" + conn, db = create_conn_db(init_db(tmp_path), read_only=True) + conn.close() + async_conn = lb.AsyncConnection(db, max_threads_per_query=4) + try: + yield async_conn + finally: + async_conn.close() + db.close() @pytest.fixture From 9cee29865caea73b96f7dcf2f81e1cad5be9ae75 Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Thu, 28 May 2026 14:19:31 -0700 Subject: [PATCH 4/4] Prime JSON extension before C API tests --- .github/workflows/ci.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 10d0cb2..5eb9c4a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -121,6 +121,13 @@ jobs: run: | .venv/bin/ruff check src_py test + - name: Smoke test JSON extension install + working-directory: ladybug/tools/python_api + env: + LBUG_PYTHON_BACKEND: capi + run: | + .venv/bin/python -c 'import shutil, tempfile; from pathlib import Path; import ladybug as lb; tmp = Path(tempfile.mkdtemp()); db = lb.Database(tmp / "db.lbdb"); conn = lb.Connection(db); conn.execute("INSTALL json; LOAD json;"); shutil.rmtree(tmp)' + - name: Run pytest (C API backend) working-directory: ladybug/tools/python_api env: