diff --git a/README.md b/README.md index 2f31ccf2..1432ced6 100644 --- a/README.md +++ b/README.md @@ -118,15 +118,24 @@ Once that is saved to a file, you can run it with `uv run script.py` where ### Agents extra dependencies -When using the agents related feature it is required to add the `agents` extra dependencies. This can be added when +When using the agents related feature it is required to add the `agents` extra dependencies. This can be added when installing the package: ```bash -pip install "mistralai[agents]" +uv add "mistralai[agents]" ``` > Note: These features require Python 3.10+ (the SDK minimum). +### Namespace Sub-packages + +`mistralai` uses [PEP 420](https://peps.python.org/pep-0420/) implicit namespace packages. Separate PyPI packages (e.g. `mistralai-workflows`) install under the shared `mistralai` namespace with no `__init__.py` at the top level. Install them directly: + +```bash +uv add mistralai-workflows # core +uv add "mistralai-workflows[mistralai]" # core + plugin +``` + ## SDK Example Usage @@ -410,7 +419,7 @@ gcloud auth application-default login Install the extras dependencies specific to Google Cloud: ```bash -pip install mistralai[gcp] +uv add "mistralai[gcp]" ``` **Step 2: Example Usage** diff --git a/pyproject.toml b/pyproject.toml index 7209c64c..5802feaa 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,7 +16,7 @@ dependencies = [ "opentelemetry-sdk (>=1.33.1,<2.0.0)", "opentelemetry-api (>=1.33.1,<2.0.0)", "opentelemetry-exporter-otlp-proto-http (>=1.37.0,<2.0.0)", - "opentelemetry-semantic-conventions (>=0.59b0,<0.60)", + "opentelemetry-semantic-conventions (>=0.59b0,<0.61)", ] [project.optional-dependencies] diff --git a/scripts/test_namespace.sh b/scripts/test_namespace.sh new file mode 100755 index 00000000..82d6bf29 --- /dev/null +++ b/scripts/test_namespace.sh @@ -0,0 +1,57 @@ +#!/usr/bin/env bash +set -euo pipefail + +CLIENT_WHL="${1:?Usage: $0 }" +WORKFLOWS_WHL="${2:?Usage: $0 }" +VENV="/tmp/test-pep420-ns" +PYTHON="${PYTHON:-python3.12}" + +cleanup() { rm -rf "$VENV"; } +trap cleanup EXIT + +echo "=== Creating clean venv ($PYTHON) ===" +"$PYTHON" -m venv "$VENV" +source "$VENV/bin/activate" + +echo "" +echo "=== Test 1: Client only ===" +pip install --quiet "$CLIENT_WHL" +python -c "from mistralai.client import Mistral; print(' client import: OK')" +python -c " +try: + from mistralai.workflows import workflow + print(' FAIL: workflows should not be importable') + exit(1) +except ImportError: + print(' workflows not importable (expected): OK') +" + +echo "" +echo "=== Test 2: No __init__.py at namespace level ===" +python -c " +import pathlib, sysconfig +ns = pathlib.Path(sysconfig.get_path('purelib')) / 'mistralai' / '__init__.py' +if ns.exists(): + print(' FAIL: mistralai/__init__.py exists (breaks PEP 420)') + exit(1) +else: + print(' no mistralai/__init__.py: OK') +" + +echo "" +echo "=== Test 3: Client + workflows ===" +pip install --quiet "$WORKFLOWS_WHL" +python -c "from mistralai.client import Mistral; print(' client import: OK')" +python -c "from mistralai.workflows import workflow; print(' workflows import: OK')" + +echo "" +echo "=== Test 4: Namespace directory listing ===" +python -c " +import pathlib, sysconfig +ns = pathlib.Path(sysconfig.get_path('purelib')) / 'mistralai' +for p in sorted(ns.iterdir()): + print(f' {p.name}/') +" + +echo "" +echo "=== All tests passed ==="