diff --git a/examples/06_vector_search_recommendations.py b/examples/06_vector_search_recommendations.py index 88d07f2..0001f3f 100644 --- a/examples/06_vector_search_recommendations.py +++ b/examples/06_vector_search_recommendations.py @@ -65,7 +65,7 @@ def check_dependencies(): if not HAS_TRANSFORMERS: print("ERROR: sentence-transformers not installed.") print("Please install it to run this example:") - print(" pip install sentence-transformers") + print(" uv add sentence-transformers") sys.exit(1) diff --git a/examples/07_stackoverflow_tables_oltp.py b/examples/07_stackoverflow_tables_oltp.py index 3d0fa3e..24ff90c 100644 --- a/examples/07_stackoverflow_tables_oltp.py +++ b/examples/07_stackoverflow_tables_oltp.py @@ -31,7 +31,7 @@ from lxml import etree except ImportError: print("Missing dependency: lxml") - print("Install with: pip install lxml") + print("Install with: uv add lxml") sys.exit(1) diff --git a/examples/08_stackoverflow_tables_olap.py b/examples/08_stackoverflow_tables_olap.py index d693d97..93f0ef2 100644 --- a/examples/08_stackoverflow_tables_olap.py +++ b/examples/08_stackoverflow_tables_olap.py @@ -27,7 +27,7 @@ from lxml import etree except ImportError: print("Missing dependency: lxml") - print("Install with: pip install lxml") + print("Install with: uv add lxml") sys.exit(1) diff --git a/examples/09_stackoverflow_graph_oltp.py b/examples/09_stackoverflow_graph_oltp.py index 0042366..d59ccee 100644 --- a/examples/09_stackoverflow_graph_oltp.py +++ b/examples/09_stackoverflow_graph_oltp.py @@ -33,7 +33,7 @@ from lxml import etree except ImportError: print("Missing dependency: lxml") - print("Install with: pip install lxml") + print("Install with: uv add lxml") sys.exit(1) diff --git a/examples/10_stackoverflow_graph_olap.py b/examples/10_stackoverflow_graph_olap.py index 1eb4dff..99d9341 100644 --- a/examples/10_stackoverflow_graph_olap.py +++ b/examples/10_stackoverflow_graph_olap.py @@ -29,7 +29,7 @@ from lxml import etree except ImportError: print("Missing dependency: lxml") - print("Install with: pip install lxml") + print("Install with: uv add lxml") sys.exit(1) diff --git a/examples/13_stackoverflow_hybrid_queries.py b/examples/13_stackoverflow_hybrid_queries.py index fe7ca4a..00bb0f4 100644 --- a/examples/13_stackoverflow_hybrid_queries.py +++ b/examples/13_stackoverflow_hybrid_queries.py @@ -39,7 +39,7 @@ from lxml import etree except ImportError: print("Missing dependency: lxml") - print("Install with: pip install lxml") + print("Install with: uv add lxml") sys.exit(1) EXPECTED_DATASETS = { @@ -2280,13 +2280,13 @@ def main() -> None: arcadedb = get_arcadedb_module() if arcadedb is None: print("Missing dependency: arcadedb") - print("Install with: pip install arcadedb") + print("Install with: uv add arcadedb") sys.exit(1) SentenceTransformer = get_sentence_transformer_class() if SentenceTransformer is None: print("Missing dependency: sentence-transformers") - print("Install with: pip install sentence-transformers") + print("Install with: uv add sentence-transformers") sys.exit(1) data_dir = Path(__file__).parent / "data" / args.dataset diff --git a/examples/22_numpy_bulk_io.py b/examples/22_numpy_bulk_io.py index 36cd334..e419a91 100644 --- a/examples/22_numpy_bulk_io.py +++ b/examples/22_numpy_bulk_io.py @@ -20,9 +20,9 @@ widening a nullable INTEGER to float64/NaN the way numpy must Requirements: -- numpy (pip install numpy) +- numpy (uv add numpy) - pyarrow, optional, only for the to_arrow section - (pip install 'arcadedb-jvm[arrow]') + (uv add 'arcadedb-jvm[arrow]') """ from __future__ import annotations @@ -167,7 +167,7 @@ def nulls_to_arrow(db, n_rows: int) -> None: if table is None: print( "to_arrow : pyarrow not installed, skipping " - "(pip install 'arcadedb-jvm[arrow]')" + "(uv add 'arcadedb-jvm[arrow]')" ) return diff --git a/examples/27_dataframe_arrow_ingest.py b/examples/27_dataframe_arrow_ingest.py index cccfc05..df61e44 100644 --- a/examples/27_dataframe_arrow_ingest.py +++ b/examples/27_dataframe_arrow_ingest.py @@ -17,7 +17,7 @@ Requirements: - pandas, polars and pyarrow - (pip install 'arcadedb-jvm[pandas,polars]') + (uv add 'arcadedb-jvm[pandas,polars]') """ from __future__ import annotations diff --git a/examples/README.md b/examples/README.md index ad806fd..aa9273a 100644 --- a/examples/README.md +++ b/examples/README.md @@ -400,7 +400,7 @@ DataFrames and Arrow tables loaded straight into a type, and a result back out a column refused before a row is written - `to_polars()` on the result - synthetic data; flags: `--rows` (default 100,000) and `--db-path` -- requires `pip install 'arcadedb-jvm[pandas,polars]'` +- requires `uv add 'arcadedb-jvm[pandas,polars]'` **Learn:** How a DataFrame becomes documents or vertices without a row loop, and what each Arrow type is stored as diff --git a/examples/download_data.py b/examples/download_data.py index b8d88bf..847538f 100644 --- a/examples/download_data.py +++ b/examples/download_data.py @@ -7,7 +7,7 @@ injects NULL values for comprehensive testing. Features: -- Progress bars for all long-running operations (requires tqdm: pip install tqdm) +- Progress bars for all long-running operations (requires tqdm: uv add tqdm) - Timing measurements for performance monitoring - Memory-efficient streaming for large files - Smart sampling for fast verification (100K rows) @@ -829,7 +829,7 @@ def has_required_xml_files(dataset_dir: Path) -> bool: import py7zr except ImportError: print("[ERROR] Missing dependency: py7zr") - print(" Install with: pip install py7zr") + print(" Install with: uv add py7zr") raise # Dataset configurations (pinned to 2024-06-30 for reproducibility) @@ -1279,7 +1279,7 @@ def embed_stackoverflow_vectors( except ImportError as exc: raise RuntimeError( "Missing dependencies for Stack Overflow embeddings. " - "Install with: pip install sentence-transformers torch numpy" + "Install with: uv add sentence-transformers torch numpy" ) from exc device = "cuda" if torch.cuda.is_available() else "cpu" @@ -1876,7 +1876,7 @@ def convert_msmarco_parquet_to_shards( except ImportError as exc: raise RuntimeError( "Missing dependencies for MSMARCO conversion. " - "Install with: pip install numpy pyarrow" + "Install with: uv add numpy pyarrow" ) from exc def fmt_secs(secs: float | None) -> str: @@ -2107,7 +2107,7 @@ def download_msmarco(count: int, data_dir: Path) -> Path: if shutil.which("hf") is None: raise RuntimeError( - "Missing Hugging Face CLI. Install with: pip install huggingface_hub" + "Missing Hugging Face CLI. Install with: uv add huggingface_hub" ) print("[DOWNLOAD] MSMARCO v2.1 parquet parts (Hugging Face)") @@ -2483,7 +2483,7 @@ def main(): python download_data.py ldbc-snb-sf100 Note: Stack Exchange datasets require py7zr library: - pip install py7zr + uv add py7zr NULL Handling: MovieLens (CSV): NULL injection enabled by default (use --no-nulls to skip) diff --git a/native/wheel/README.md b/native/wheel/README.md index 0e8c4e9..af4e7b9 100644 --- a/native/wheel/README.md +++ b/native/wheel/README.md @@ -5,12 +5,12 @@ This is `arcadedb`, the native build of the ArcadeDB Python bindings, and the de ArcadeDB (SQL, openCypher, document, graph, vector, time series) runs in your Python process **without a JVM and without JPype**. The engine is compiled ahead of time with GraalVM Community Edition into a shared library (`libarcadedb.so`, `.dylib` or `.dll`), and Python loads it with `ctypes`. It starts in milliseconds and has a small memory footprint. -> Transition note: the first release of this layout is 26.11.1. Until `arcadedb` passes its readiness bar, it may appear only as pre-releases, `26.11.1.devN`. Install those with `pip install --pre arcadedb`. Report problems at and say that you use the native build. +> Transition note: the first release of this layout is 26.11.1. Until `arcadedb` passes its readiness bar, it may appear only as pre-releases, `26.11.1.devN`. Install those with `uv add --prerelease allow arcadedb`. Report problems at and say that you use the native build. ## Install ```bash -pip install arcadedb # or: uv add arcadedb +uv add arcadedb ``` Optional extras for the columnar helpers: `[numpy]`, `[arrow]`, `[pandas]`, `[polars]`. @@ -18,7 +18,7 @@ Optional extras for the columnar helpers: `[numpy]`, `[arrow]`, `[pandas]`, `[po Old names: this package was formerly `arcadedb-embedded-native`, imported as `arcadedb_native`. The old project is archived on PyPI: it gets no new releases and no shim. A last release of the JVM project `arcadedb-embedded` will install this package. -If `arcadedb-jvm` is installed in the same environment, `import arcadedb` raises an `ImportError` that names both packages. Run `pip uninstall arcadedb arcadedb-jvm`, then install the one you want. +If `arcadedb-jvm` is installed in the same environment, `import arcadedb` raises an `ImportError` that names both packages. Run `uv remove arcadedb arcadedb-jvm`, then install the one you want. ## Use diff --git a/native/wheel/build_wheel.py b/native/wheel/build_wheel.py index 81624c5..faf6e55 100644 --- a/native/wheel/build_wheel.py +++ b/native/wheel/build_wheel.py @@ -3,7 +3,7 @@ python native/wheel/build_wheel.py --lib-dir native/target/lib --version 26.11.1.dev0 --engine 26.10.2 --out -Steps: copy src/arcadedb to /stage/src/arcadedb (the shared tree is not duplicated in git; only the pip hints of the extras are renamed from arcadedb-jvm[...] to arcadedb[...]); +Steps: copy src/arcadedb to /stage/src/arcadedb (the shared tree is not duplicated in git; only the install hints of the extras are renamed from arcadedb-jvm[...] to arcadedb[...]); rewrite `import jpype` to the bundled stub; flip the default backend to native; add the library of the build platform (libarcadedb.so on Linux, libarcadedb.dylib on macOS, libarcadedb.dll on Windows; on Linux x86-64 also libjvector-x86_64.so, jvector's Highway library: no other platform ships it); add LICENSE/NOTICE/GraalVM licence texts; check THIRD_PARTY_NOTICES.md against gen_notices.py (fails on drift); compute the platform tag from the library diff --git a/src/arcadedb/__init__.py b/src/arcadedb/__init__.py index 348fffd..7451794 100644 --- a/src/arcadedb/__init__.py +++ b/src/arcadedb/__init__.py @@ -17,7 +17,7 @@ _DISTRIBUTION_BACKEND = _native_backend.distribution_backend() __backend__ = "native" if _native_backend.enabled() else "jvm" -# Both distributions install a package named arcadedb into the same directory; pip overwrites one with the other +# Both distributions install a package named arcadedb into the same directory; the installer overwrites one with the other # silently. Refuse to import when the other one is installed too, before anything else runs. _check_distributions(_DISTRIBUTION_BACKEND) diff --git a/src/arcadedb/_dist_conflict.py b/src/arcadedb/_dist_conflict.py index 0b253b0..3668a4f 100644 --- a/src/arcadedb/_dist_conflict.py +++ b/src/arcadedb/_dist_conflict.py @@ -3,7 +3,7 @@ This repository builds two distributions. `arcadedb` is the native build (the engine as a GraalVM native-image library, loaded with ctypes) and `arcadedb-jvm` is the JVM build (the Java engine in-process through JPype). Both put a package named `arcadedb` into the same site-packages directory, so installing one after the other -overwrites files of the first with files of the second, and pip says nothing. What would be imported is a mix +overwrites files of the first with files of the second, and the installer says nothing. What would be imported is a mix of two builds. Package metadata still lists both, so this module looks there and raises an ImportError that names both packages and says how to fix it, instead of letting the mix run. @@ -60,7 +60,7 @@ def message(backend: str) -> str: f"({kind[other_backend(backend)]} build) is installed. " f"Both provide the Python package 'arcadedb', so each install overwrote files of the other " f"without a message, and what you would import is a mix of the two builds. " - f"Keep one: run 'pip uninstall {DISTRIBUTIONS['native']} {DISTRIBUTIONS['jvm']}', then install " + f"Keep one: run 'uv remove {DISTRIBUTIONS['native']} {DISTRIBUTIONS['jvm']}', then install " f"'{DISTRIBUTIONS['native']}' (native, the default for most embedded use) or " f"'{DISTRIBUTIONS['jvm']}' (JVM, for heavy long-running loads). " f"Which one to pick: {DOCS_URL}" diff --git a/src/arcadedb/_native/database.py b/src/arcadedb/_native/database.py index 9770f1a..5322ab9 100644 --- a/src/arcadedb/_native/database.py +++ b/src/arcadedb/_native/database.py @@ -333,13 +333,13 @@ def to_polars(self, batch_size: int = 25_000, columns=None): except ImportError as exc: raise ImportError( "polars is required for to_polars(). " - "Install with: pip install 'arcadedb[polars]'" + "Install with: uv add 'arcadedb[polars]'" ) from exc table = self.to_arrow(batch_size, columns) if table is None: raise ImportError( "to_polars() reads through Arrow, which needs pyarrow and numpy. " - "Install with: pip install 'arcadedb[polars]'" + "Install with: uv add 'arcadedb[polars]'" ) return pl.from_arrow(table) diff --git a/src/arcadedb/dataframe.py b/src/arcadedb/dataframe.py index 0e4e9b9..25738b1 100644 --- a/src/arcadedb/dataframe.py +++ b/src/arcadedb/dataframe.py @@ -26,8 +26,8 @@ from .exceptions import ArcadeDBError _PYARROW_HINT = ( - "pyarrow is required for {what}. Install with: pip install pyarrow " - "(or pip install 'arcadedb-jvm[arrow]')" + "pyarrow is required for {what}. Install with: uv add pyarrow " + "(or uv add 'arcadedb-jvm[arrow]')" ) # Declared property types (the engine's Type names) that an Arrow column kind diff --git a/src/arcadedb/results.py b/src/arcadedb/results.py index 9c09dba..41ec46a 100644 --- a/src/arcadedb/results.py +++ b/src/arcadedb/results.py @@ -631,8 +631,7 @@ def to_dataframe(self, convert_types: bool = True): import pandas as pd except ImportError as exc: raise ImportError( - "pandas is required for to_dataframe(). " - "Install with: pip install pandas" + "pandas is required for to_dataframe(). Install with: uv add pandas" ) from exc if convert_types: @@ -660,7 +659,7 @@ def to_polars( Reads :meth:`to_arrow` and hands the table to Polars, so nulls keep their type (a nullable integer stays an integer column) and a DECIMAL column is a Polars ``Decimal``. Requires polars and pyarrow - (``pip install 'arcadedb-jvm[polars]'``). + (``uv add 'arcadedb-jvm[polars]'``). Args: batch_size: Rows per bridge crossing, as in :meth:`to_arrow`. @@ -682,14 +681,14 @@ def to_polars( except ImportError as exc: raise ImportError( "polars is required for to_polars(). " - "Install with: pip install 'arcadedb-jvm[polars]'" + "Install with: uv add 'arcadedb-jvm[polars]'" ) from exc table = self.to_arrow(batch_size=batch_size, columns=columns) if table is None: raise ImportError( "to_polars() reads through Arrow, which needs pyarrow and numpy " "and the bundled bridge jar. " - "Install with: pip install 'arcadedb-jvm[polars]'" + "Install with: uv add 'arcadedb-jvm[polars]'" ) return pl.from_arrow(table) diff --git a/tests/README.md b/tests/README.md index 4453ebb..6d2bc8a 100644 --- a/tests/README.md +++ b/tests/README.md @@ -7,25 +7,21 @@ Test suite for the ArcadeDB Python bindings. It runs against the built wheel, so ## Running Tests ```bash -# Once -uv venv - -# After each build: the wheel and its test extra into .venv. --reinstall-package, -# as a rebuild keeps the version (26.11.1.dev0) -uv pip install --reinstall-package arcadedb "$(ls dist/*.whl | head -1)[test]" +# The wheel and its test extra go into a throwaway environment on every run, so there is no +# environment to create. --reinstall-package, as a rebuild keeps the version (26.11.1.dev0) # Run all tests -uv run pytest +uv run --no-project --reinstall-package arcadedb-jvm --with "$(ls dist/*.whl | head -1)[test]" python -m pytest # Run specific file -uv run pytest tests/test_core.py -v +uv run --no-project --reinstall-package arcadedb-jvm --with "$(ls dist/*.whl | head -1)[test]" python -m pytest tests/test_core.py -v # Run matching keyword -uv run pytest -k "transaction" -v +uv run --no-project --reinstall-package arcadedb-jvm --with "$(ls dist/*.whl | head -1)[test]" python -m pytest -k "transaction" -v # Only the server tests, or everything except them (they start a real HTTP listener) -uv run pytest -m server -v -uv run pytest -m "not server" +uv run --no-project --reinstall-package arcadedb-jvm --with "$(ls dist/*.whl | head -1)[test]" python -m pytest -m server -v +uv run --no-project --reinstall-package arcadedb-jvm --with "$(ls dist/*.whl | head -1)[test]" python -m pytest -m "not server" ``` ## Tests that send SIGINT to their own process diff --git a/tests/test_dataframe_ingest.py b/tests/test_dataframe_ingest.py index 5f14ff1..449e6d7 100644 --- a/tests/test_dataframe_ingest.py +++ b/tests/test_dataframe_ingest.py @@ -487,7 +487,7 @@ def test_missing_pyarrow_is_an_import_error_with_the_fix( ): temp_db.command("sql", "CREATE DOCUMENT TYPE NoArrow") monkeypatch.setitem(sys.modules, "pyarrow", None) - with pytest.raises(ImportError, match=r"pip install pyarrow"): + with pytest.raises(ImportError, match=r"uv add pyarrow"): temp_db.insert_dataframe("NoArrow", pd.DataFrame({"a": [1]})) def test_closed_database_is_refused(self, temp_db): diff --git a/tests/test_dist_conflict.py b/tests/test_dist_conflict.py index b0db7d9..8fd6c69 100644 --- a/tests/test_dist_conflict.py +++ b/tests/test_dist_conflict.py @@ -1,6 +1,6 @@ """The `arcadedb` (native) and `arcadedb-jvm` (JVM) distributions both import as `arcadedb`. -pip overwrites one with the other without a message, so each build refuses to import when the metadata of +The installer overwrites one with the other without a message, so each build refuses to import when the metadata of the other distribution is installed. `arcadedb.__backend__` says which build is running. These tests need no engine and no JVM. """ @@ -48,7 +48,7 @@ def test_the_other_distribution_installed_refuses_the_import(backend, own, other text = str(info.value) # names both packages, how to fix it, and where to read more assert f"'{own}'" in text and f"'{other}'" in text - assert "pip uninstall arcadedb arcadedb-jvm" in text + assert "uv remove arcadedb arcadedb-jvm" in text assert "which-package" in text @@ -115,7 +115,7 @@ def test_import_fails_when_the_other_distribution_is_installed_too(tmp_path): result = import_arcadedb(site) assert result.returncode != 0 assert "DistributionConflictError" in result.stderr - assert "pip uninstall arcadedb arcadedb-jvm" in result.stderr + assert "uv remove arcadedb arcadedb-jvm" in result.stderr assert "'arcadedb'" in result.stderr and "'arcadedb-jvm'" in result.stderr @@ -124,4 +124,4 @@ def test_import_is_silent_when_only_this_distribution_is_installed(tmp_path): fake_dist_info(site, _dist_conflict.DISTRIBUTIONS[own_backend()], "26.11.1") result = import_arcadedb(site) assert result.returncode == 0, result.stderr - assert "pip uninstall" not in result.stderr + assert "uv remove" not in result.stderr diff --git a/tests/test_server_packaging.py b/tests/test_server_packaging.py index d7a017b..4e4d5a1 100644 --- a/tests/test_server_packaging.py +++ b/tests/test_server_packaging.py @@ -107,7 +107,7 @@ def test_no_apexcharts_in_the_package(): engine 26.11.1 replaced it with Apache ECharts (ArcadeData/arcadedb#10627). This package is Apache-2.0, so a Studio jar from an older engine must not be installed. scripts/verify_wheel_licences.py guards the wheel at build time; this checks what - pip actually installed. + the installer actually installed. """ from arcadedb.jvm import get_jar_path