Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/06_vector_search_recommendations.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)


Expand Down
2 changes: 1 addition & 1 deletion examples/07_stackoverflow_tables_oltp.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)


Expand Down
2 changes: 1 addition & 1 deletion examples/08_stackoverflow_tables_olap.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)


Expand Down
2 changes: 1 addition & 1 deletion examples/09_stackoverflow_graph_oltp.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)


Expand Down
2 changes: 1 addition & 1 deletion examples/10_stackoverflow_graph_olap.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)


Expand Down
6 changes: 3 additions & 3 deletions examples/13_stackoverflow_hybrid_queries.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions examples/22_numpy_bulk_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion examples/27_dataframe_arrow_ingest.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
12 changes: 6 additions & 6 deletions examples/download_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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)")
Expand Down Expand Up @@ -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)
Expand Down
6 changes: 3 additions & 3 deletions native/wheel/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,20 @@ 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.

<!-- REMOVE WHEN: the old arcadedb-embedded* shims are retired and two releases have shipped with the two-package layout allow-old-name -->
> 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 <https://github.com/ArcadeData/arcadedb-python/issues> 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 <https://github.com/ArcadeData/arcadedb-python/issues> 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]`.

<!-- REMOVE WHEN: the old arcadedb-embedded* shims are retired and two releases have shipped with the two-package layout allow-old-name -->
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

Expand Down
2 changes: 1 addition & 1 deletion native/wheel/build_wheel.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 <dir>

Steps: copy src/arcadedb to <out>/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 <out>/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
Expand Down
2 changes: 1 addition & 1 deletion src/arcadedb/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
4 changes: 2 additions & 2 deletions src/arcadedb/_dist_conflict.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down Expand Up @@ -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}"
Expand Down
4 changes: 2 additions & 2 deletions src/arcadedb/_native/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
4 changes: 2 additions & 2 deletions src/arcadedb/dataframe.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 4 additions & 5 deletions src/arcadedb/results.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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`.
Expand All @@ -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)

Expand Down
18 changes: 7 additions & 11 deletions tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion tests/test_dataframe_ingest.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
8 changes: 4 additions & 4 deletions tests/test_dist_conflict.py
Original file line number Diff line number Diff line change
@@ -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.
"""
Expand Down Expand Up @@ -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


Expand Down Expand Up @@ -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


Expand All @@ -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
2 changes: 1 addition & 1 deletion tests/test_server_packaging.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Loading