python-arango 8.3.5__tar.gz → 8.3.6__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {python_arango-8.3.5 → python_arango-8.3.6}/.circleci/config.yml +9 -2
- python_arango-8.3.6/.github/workflows/pypi.yaml +66 -0
- python_arango-8.3.6/AGENTS.md +89 -0
- {python_arango-8.3.5/python_arango.egg-info → python_arango-8.3.6}/PKG-INFO +1 -1
- python_arango-8.3.6/arango/version.py +1 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/docs/index.rst +0 -1
- {python_arango-8.3.5 → python_arango-8.3.6}/docs/indexes.rst +6 -3
- {python_arango-8.3.5 → python_arango-8.3.6/python_arango.egg-info}/PKG-INFO +1 -1
- {python_arango-8.3.5 → python_arango-8.3.6}/python_arango.egg-info/SOURCES.txt +2 -2
- {python_arango-8.3.5 → python_arango-8.3.6}/python_arango.egg-info/scm_file_list.json +3 -3
- python_arango-8.3.6/python_arango.egg-info/scm_version.json +8 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/starter.sh +6 -5
- python_arango-8.3.6/todo.md +397 -0
- python_arango-8.3.5/.github/workflows/pypi.yaml +0 -40
- python_arango-8.3.5/CONTRIBUTING.md +0 -28
- python_arango-8.3.5/arango/version.py +0 -1
- python_arango-8.3.5/docs/contributing.rst +0 -99
- python_arango-8.3.5/python_arango.egg-info/scm_version.json +0 -8
- {python_arango-8.3.5 → python_arango-8.3.6}/.github/workflows/codeql.yaml +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/.github/workflows/docs.yaml +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/.gitignore +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/.pre-commit-config.yaml +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/.readthedocs.yaml +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/LICENSE +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/MANIFEST.in +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/README.md +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/arango/__init__.py +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/arango/api.py +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/arango/aql.py +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/arango/backup.py +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/arango/client.py +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/arango/cluster.py +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/arango/collection.py +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/arango/connection.py +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/arango/cursor.py +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/arango/database.py +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/arango/errno.py +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/arango/exceptions.py +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/arango/executor.py +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/arango/formatter.py +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/arango/foxx.py +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/arango/graph.py +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/arango/http.py +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/arango/job.py +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/arango/pregel.py +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/arango/py.typed +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/arango/replication.py +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/arango/request.py +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/arango/resolver.py +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/arango/response.py +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/arango/result.py +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/arango/typings.py +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/arango/utils.py +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/arango/wal.py +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/docs/Makefile +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/docs/admin.rst +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/docs/analyzer.rst +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/docs/aql.rst +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/docs/async.rst +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/docs/auth.rst +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/docs/backup.rst +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/docs/batch.rst +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/docs/certificates.rst +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/docs/cluster.rst +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/docs/collection.rst +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/docs/compression.rst +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/docs/conf.py +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/docs/cursor.rst +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/docs/database.rst +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/docs/document.rst +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/docs/errno.rst +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/docs/errors.rst +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/docs/foxx.rst +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/docs/graph.rst +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/docs/http.rst +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/docs/logging.rst +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/docs/make.bat +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/docs/overload.rst +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/docs/overview.rst +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/docs/pregel.rst +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/docs/replication.rst +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/docs/requirements.txt +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/docs/schema.rst +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/docs/serializer.rst +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/docs/simple.rst +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/docs/specs.rst +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/docs/static/logo.png +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/docs/task.rst +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/docs/threading.rst +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/docs/transaction.rst +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/docs/user.rst +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/docs/view.rst +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/docs/wal.rst +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/pyproject.toml +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/python_arango.egg-info/dependency_links.txt +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/python_arango.egg-info/requires.txt +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/python_arango.egg-info/top_level.txt +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/setup.cfg +0 -0
- {python_arango-8.3.5 → python_arango-8.3.6}/setup.py +0 -0
|
@@ -30,11 +30,18 @@ workflows:
|
|
|
30
30
|
parameters:
|
|
31
31
|
python_version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
|
|
32
32
|
- integration-test:
|
|
33
|
-
name: ArangoDB (enterprise, 3.12 << matrix.arangodb_config >>)
|
|
33
|
+
name: ArangoDB (enterprise, 3.12.10 << matrix.arangodb_config >>)
|
|
34
34
|
matrix:
|
|
35
35
|
parameters:
|
|
36
36
|
arangodb_config: ["single", "cluster"]
|
|
37
|
-
arangodb_image: ["arangodb/enterprise:3.12"]
|
|
37
|
+
arangodb_image: ["arangodb/enterprise:3.12.10"]
|
|
38
|
+
arangodb_conf_version: ["3.12"]
|
|
39
|
+
- integration-test:
|
|
40
|
+
name: ArangoDB (enterprise, 3.12.9 << matrix.arangodb_config >>)
|
|
41
|
+
matrix:
|
|
42
|
+
parameters:
|
|
43
|
+
arangodb_config: ["single", "cluster"]
|
|
44
|
+
arangodb_image: ["arangodb/enterprise:3.12.9"]
|
|
38
45
|
arangodb_conf_version: ["3.12"]
|
|
39
46
|
- integration-test:
|
|
40
47
|
name: ArangoDB (core-preview, 4.0-nightly << matrix.arangodb_config >>)
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
name: Publish
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
build:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
|
|
14
|
+
steps:
|
|
15
|
+
- name: Checkout repository
|
|
16
|
+
uses: actions/checkout@v7
|
|
17
|
+
with:
|
|
18
|
+
fetch-depth: 0
|
|
19
|
+
fetch-tags: true
|
|
20
|
+
persist-credentials: false
|
|
21
|
+
|
|
22
|
+
- uses: actions/setup-python@v7
|
|
23
|
+
with:
|
|
24
|
+
python-version: "3.12"
|
|
25
|
+
|
|
26
|
+
- name: Install dependencies
|
|
27
|
+
run: python -m pip install build
|
|
28
|
+
|
|
29
|
+
- name: Build distribution
|
|
30
|
+
run: python -m build
|
|
31
|
+
|
|
32
|
+
- uses: actions/upload-artifact@v5
|
|
33
|
+
with:
|
|
34
|
+
name: dist
|
|
35
|
+
path: dist/
|
|
36
|
+
if-no-files-found: error
|
|
37
|
+
|
|
38
|
+
testpypi:
|
|
39
|
+
needs: build
|
|
40
|
+
runs-on: ubuntu-latest
|
|
41
|
+
environment: testpypi
|
|
42
|
+
permissions:
|
|
43
|
+
id-token: write
|
|
44
|
+
steps:
|
|
45
|
+
- uses: actions/download-artifact@v6
|
|
46
|
+
with:
|
|
47
|
+
name: dist
|
|
48
|
+
path: dist/
|
|
49
|
+
- name: Publish to TestPyPI
|
|
50
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
51
|
+
with:
|
|
52
|
+
repository-url: https://test.pypi.org/legacy/
|
|
53
|
+
|
|
54
|
+
pypi:
|
|
55
|
+
needs: testpypi
|
|
56
|
+
runs-on: ubuntu-latest
|
|
57
|
+
environment: pypi
|
|
58
|
+
permissions:
|
|
59
|
+
id-token: write
|
|
60
|
+
steps:
|
|
61
|
+
- uses: actions/download-artifact@v6
|
|
62
|
+
with:
|
|
63
|
+
name: dist
|
|
64
|
+
path: dist/
|
|
65
|
+
- name: Publish to PyPI
|
|
66
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Quickstart
|
|
2
|
+
|
|
3
|
+
python-arango is a Python driver for ArangoDB. Run the commands below from the
|
|
4
|
+
repository root.
|
|
5
|
+
|
|
6
|
+
## Repository layout
|
|
7
|
+
|
|
8
|
+
- `arango/`: driver implementation, public APIs, and type annotations.
|
|
9
|
+
- `tests/`: pytest tests; `conftest.py` defines database fixtures and CLI options.
|
|
10
|
+
- `tests/static/`: server configurations and test data used by `starter.sh`.
|
|
11
|
+
- `docs/`: Sphinx documentation in reStructuredText.
|
|
12
|
+
- `pyproject.toml`, `setup.cfg`, `.pre-commit-config.yaml`: packaging and tooling.
|
|
13
|
+
- `.circleci/`, `.github/workflows/`: CI checks, documentation, and publishing.
|
|
14
|
+
|
|
15
|
+
## Development setup
|
|
16
|
+
|
|
17
|
+
Use Python 3.10 or newer. Create a virtual environment, or use an existing one:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
python3 -m venv .venv # Create an isolated Python environment.
|
|
21
|
+
source .venv/bin/activate # Use its interpreter and tools.
|
|
22
|
+
python -m pip install -e '.[dev]' # Install the editable driver and dev tools.
|
|
23
|
+
pre-commit install # Enable checks before each commit.
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Examples use `python` from the activated environment. If it is unavailable on
|
|
27
|
+
PATH, invoke your environment's interpreter directly.
|
|
28
|
+
|
|
29
|
+
## Local cluster and tests
|
|
30
|
+
|
|
31
|
+
The starter requires Docker, Bash, `wget`, and `jq`. To replace an existing test
|
|
32
|
+
container, run `docker stop arango` and `docker rm arango` first.
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
version="latest" # Or pin a supported version, such as 3.12.10.
|
|
36
|
+
./starter.sh cluster enterprise "$version" # Start a local test cluster.
|
|
37
|
+
python -m pytest --cluster # Run the full suite against the cluster.
|
|
38
|
+
# Run one test while developing a document change.
|
|
39
|
+
python -m pytest --cluster tests/test_document.py::test_document_insert
|
|
40
|
+
# Generate an HTML coverage report.
|
|
41
|
+
python -m pytest --cluster --cov=arango --cov-report=html
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Defaults are `127.0.0.1:8529`, user `root`, password `passwd`, and JWT secret
|
|
45
|
+
`secret`, matching the starter configuration. Override them with `--host`,
|
|
46
|
+
`--port`, `--root`, `--password`, and `--secret`. Use a disposable development
|
|
47
|
+
database: tests create and delete databases, users, jobs, and backups. If a
|
|
48
|
+
sandbox blocks localhost access, rerun with the required sandbox permission.
|
|
49
|
+
|
|
50
|
+
For a single server, use `./starter.sh single enterprise "$version"` and omit
|
|
51
|
+
`--cluster`. Import tests can run without ArangoDB:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
python -m pytest tests/test_imports.py --skip-arango-setup # Check imports offline.
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Style and documentation
|
|
58
|
+
|
|
59
|
+
Run the configured hooks for formatting, import ordering, linting, and type
|
|
60
|
+
checks. Build and test documentation separately:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
pre-commit run --all-files # Run hooks; formatters may modify files.
|
|
64
|
+
python -m sphinx -b html docs docs/_build # Build the HTML documentation.
|
|
65
|
+
python -m sphinx -b doctest docs docs/_build # Test documentation examples.
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
The Sphinx doctests require a running ArangoDB server. Open
|
|
69
|
+
`docs/_build/index.html` for the HTML documentation or `htmlcov/index.html` for
|
|
70
|
+
the coverage report.
|
|
71
|
+
|
|
72
|
+
## Changes and pull requests
|
|
73
|
+
|
|
74
|
+
- Agents must work on a branch other than `main`; never commit directly to `main`.
|
|
75
|
+
Check the current branch before editing or committing. If on `main` or a
|
|
76
|
+
detached HEAD, create a branch first:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
git branch --show-current # Check the current branch.
|
|
80
|
+
git switch -c fix/describe-change # Choose a descriptive branch name.
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
- Preserve public API compatibility unless a breaking change is intentional.
|
|
84
|
+
- Follow existing code patterns, type annotations, and Sphinx docstrings.
|
|
85
|
+
- Add regression tests for fixes and tests for new behavior; update user documentation.
|
|
86
|
+
- Run relevant tests and checks; report anything skipped and why.
|
|
87
|
+
- Keep test coverage up and squash changes into one commit for submission.
|
|
88
|
+
- Use present-tense commit messages, such as `Fix cursor retry`.
|
|
89
|
+
- Explain what changed, why, and any compatibility impact in the pull request.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-arango
|
|
3
|
-
Version: 8.3.
|
|
3
|
+
Version: 8.3.6
|
|
4
4
|
Summary: Python Driver for ArangoDB
|
|
5
5
|
Author-email: Joohwan Oh <joohwan.oh@outlook.com>
|
|
6
6
|
Maintainer-email: Joohwan Oh <joohwan.oh@outlook.com>, Alexandru Petenchea <alex.petenchea@gmail.com>, Anthony Mahanna <anthony.mahanna@arangodb.com>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "8.3.6"
|
|
@@ -88,7 +88,7 @@ on fields ``_from`` and ``_to``. For more information on indexes, refer to
|
|
|
88
88
|
},
|
|
89
89
|
})
|
|
90
90
|
|
|
91
|
-
# Index creation may succeed even if
|
|
91
|
+
# Index creation may succeed even if there is insufficient training data.
|
|
92
92
|
if vector_index.get('trainingState') != 'ready':
|
|
93
93
|
raise RuntimeError(
|
|
94
94
|
vector_index.get('errorMessage', 'Vector index is not ready')
|
|
@@ -98,7 +98,10 @@ Omitted or scaling-object ``nLists``, ``numberOfDocsPerCentroid``, factory
|
|
|
98
98
|
placeholders such as ``IVF{},Flat``, and successful-but-unusable creation
|
|
99
99
|
behavior require ArangoDB 3.12.10 or later. A successful creation response
|
|
100
100
|
means that the index exists, but callers should check ``trainingState`` before
|
|
101
|
-
using it. If
|
|
102
|
-
``errorMessage`` describes the failure.
|
|
101
|
+
using it. If there is insufficient data to train the index, the state is
|
|
102
|
+
``"unusable"`` and ``errorMessage`` describes the failure. Invalid index
|
|
103
|
+
definitions, such as an ``nLists`` value that disagrees with the number of
|
|
104
|
+
centroids in the factory string, are rejected during creation with
|
|
105
|
+
``IndexCreateError`` and no index is created.
|
|
103
106
|
|
|
104
107
|
See :ref:`StandardCollection` for API specification.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-arango
|
|
3
|
-
Version: 8.3.
|
|
3
|
+
Version: 8.3.6
|
|
4
4
|
Summary: Python Driver for ArangoDB
|
|
5
5
|
Author-email: Joohwan Oh <joohwan.oh@outlook.com>
|
|
6
6
|
Maintainer-email: Joohwan Oh <joohwan.oh@outlook.com>, Alexandru Petenchea <alex.petenchea@gmail.com>, Anthony Mahanna <anthony.mahanna@arangodb.com>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
.gitignore
|
|
2
2
|
.pre-commit-config.yaml
|
|
3
3
|
.readthedocs.yaml
|
|
4
|
-
|
|
4
|
+
AGENTS.md
|
|
5
5
|
LICENSE
|
|
6
6
|
MANIFEST.in
|
|
7
7
|
README.md
|
|
@@ -9,6 +9,7 @@ pyproject.toml
|
|
|
9
9
|
setup.cfg
|
|
10
10
|
setup.py
|
|
11
11
|
starter.sh
|
|
12
|
+
todo.md
|
|
12
13
|
.circleci/config.yml
|
|
13
14
|
.github/workflows/codeql.yaml
|
|
14
15
|
.github/workflows/docs.yaml
|
|
@@ -55,7 +56,6 @@ docs/cluster.rst
|
|
|
55
56
|
docs/collection.rst
|
|
56
57
|
docs/compression.rst
|
|
57
58
|
docs/conf.py
|
|
58
|
-
docs/contributing.rst
|
|
59
59
|
docs/cursor.rst
|
|
60
60
|
docs/database.rst
|
|
61
61
|
docs/document.rst
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
".gitignore",
|
|
8
8
|
".pre-commit-config.yaml",
|
|
9
9
|
".readthedocs.yaml",
|
|
10
|
-
"
|
|
10
|
+
"AGENTS.md",
|
|
11
11
|
"LICENSE",
|
|
12
12
|
"MANIFEST.in",
|
|
13
13
|
"README.md",
|
|
@@ -53,7 +53,6 @@
|
|
|
53
53
|
"docs/collection.rst",
|
|
54
54
|
"docs/compression.rst",
|
|
55
55
|
"docs/conf.py",
|
|
56
|
-
"docs/contributing.rst",
|
|
57
56
|
"docs/cursor.rst",
|
|
58
57
|
"docs/database.rst",
|
|
59
58
|
"docs/document.rst",
|
|
@@ -124,6 +123,7 @@
|
|
|
124
123
|
"tests/test_transaction.py",
|
|
125
124
|
"tests/test_user.py",
|
|
126
125
|
"tests/test_view.py",
|
|
127
|
-
"tests/test_wal.py"
|
|
126
|
+
"tests/test_wal.py",
|
|
127
|
+
"todo.md"
|
|
128
128
|
]
|
|
129
129
|
}
|
|
@@ -4,15 +4,16 @@
|
|
|
4
4
|
# Useful for testing the python-arango driver against a local ArangoDB setup.
|
|
5
5
|
|
|
6
6
|
# Usage:
|
|
7
|
-
# ./starter.sh [single|cluster] [
|
|
7
|
+
# ./starter.sh [single|cluster] [core-preview|enterprise|enterprise-preview] [version]
|
|
8
8
|
# ./starter.sh [single|cluster] [image[:tag]]
|
|
9
9
|
# Example:
|
|
10
10
|
# ./starter.sh cluster enterprise 3.12.4
|
|
11
11
|
# ./starter.sh single core-preview 4.0-nightly
|
|
12
12
|
# ./starter.sh single arangodb/enterprise-preview:3.12-nightly
|
|
13
|
+
# Defaults: single server, enterprise image, latest version.
|
|
13
14
|
|
|
14
15
|
setup="${1:-single}"
|
|
15
|
-
image="${2:-
|
|
16
|
+
image="${2:-enterprise}"
|
|
16
17
|
version="${3:-latest}"
|
|
17
18
|
|
|
18
19
|
extra_ports=""
|
|
@@ -35,14 +36,14 @@ if [[ "$image" == */* ]]; then
|
|
|
35
36
|
else
|
|
36
37
|
image_ref="$image:$version"
|
|
37
38
|
fi
|
|
38
|
-
elif [ "$image" == "
|
|
39
|
-
image_ref="arangodb/
|
|
39
|
+
elif [ "$image" == "core-preview" ]; then
|
|
40
|
+
image_ref="arangodb/core-preview:$version"
|
|
40
41
|
elif [ "$image" == "enterprise" ]; then
|
|
41
42
|
image_ref="arangodb/enterprise:$version"
|
|
42
43
|
elif [ "$image" == "enterprise-preview" ]; then
|
|
43
44
|
image_ref="arangodb/enterprise-preview:$version"
|
|
44
45
|
else
|
|
45
|
-
echo "Invalid argument. Please provide '
|
|
46
|
+
echo "Invalid argument. Please provide 'core-preview', 'enterprise', 'enterprise-preview', or a full image reference."
|
|
46
47
|
exit 1
|
|
47
48
|
fi
|
|
48
49
|
|
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
# Painpoints to address with the next major release
|
|
2
|
+
|
|
3
|
+
## JWT authentication
|
|
4
|
+
|
|
5
|
+
The driver supports JWTs, but renewal is reactive, unsynchronized, and can fail for expired tokens. Application-managed
|
|
6
|
+
tokens can incorrectly enter credential-based refresh. Reliable renewal needs clearer authentication ownership, while
|
|
7
|
+
changing the Basic authentication default requires a migration path.
|
|
8
|
+
|
|
9
|
+
a. Define disabled, driver-managed, and application-managed authentication modes. Make JWT the default, allow an initial
|
|
10
|
+
JWT alongside credentials in driver-managed mode, and document migration.
|
|
11
|
+
|
|
12
|
+
b. Add proactive renewal with bounded retries and one acquisition shared by concurrent requests. Define renewal worker
|
|
13
|
+
ownership and cleanup.
|
|
14
|
+
|
|
15
|
+
c. Fix expired-token recovery and retry rejected requests once. Reuse newer tokens after delayed 401s, and never refresh
|
|
16
|
+
application-managed tokens using credentials.
|
|
17
|
+
|
|
18
|
+
d. Test expiration, concurrent renewal, failed acquisition, and application-managed replacement. Correct the expiry test
|
|
19
|
+
to update both the token and its recorded expiration.
|
|
20
|
+
|
|
21
|
+
e. Add `db.update_jwt(token)` for application-managed tokens, delegating to the connection's token replacement. Scope
|
|
22
|
+
updates to that authentication context, not the entire ArangoClient: separate database connections can use different
|
|
23
|
+
credentials. Make replacement safe during concurrent requests, without recreating connections or triggering renewal.
|
|
24
|
+
Subsequent requests through the database and its existing collection wrappers must use the replacement token;
|
|
25
|
+
requests already in progress may finish with the previous token. Other authentication contexts remain unaffected.
|
|
26
|
+
|
|
27
|
+
f. Keep renewal state per authentication context. Track contexts created by the client so `client.close()` stops all
|
|
28
|
+
associated renewal activity, including preventing in-progress renewals from scheduling new tasks after shutdown.
|
|
29
|
+
|
|
30
|
+
`alice_db.update_jwt(new_alice_token)` is a proposed public API; the current equivalent is
|
|
31
|
+
`alice_db.conn.set_token(new_alice_token)`. A separate `bob_db` connection remains unaffected, even when both were
|
|
32
|
+
created through the same client. The specification's "root instance" should therefore mean the authentication context
|
|
33
|
+
for this operation, rather than requiring a single client-wide token.
|
|
34
|
+
|
|
35
|
+
## Concurrency
|
|
36
|
+
|
|
37
|
+
Using the driver across threads lacks clear guarantees around shared sessions, mutable connection state, and JWT
|
|
38
|
+
renewal. Both a shared ArangoClient and separate clients per thread should support parallel requests. Stateful cursors
|
|
39
|
+
also need explicit ownership rules to prevent overlapping fetches and inconsistent iteration.
|
|
40
|
+
|
|
41
|
+
a. Support both client usage patterns and document which database and collection wrappers can be shared. Define session
|
|
42
|
+
ownership without serializing all requests.
|
|
43
|
+
|
|
44
|
+
b. Make pool sizing and acquisition timeouts predictable. Verify and fix the suspected pool_timeout wiring issue, then
|
|
45
|
+
test pool exhaustion.
|
|
46
|
+
|
|
47
|
+
c. Synchronize shared resolver and JWT state, and define shutdown behavior during active requests. Keep separate clients
|
|
48
|
+
independent.
|
|
49
|
+
|
|
50
|
+
d. Support independent cursors for concurrent queries. Document each cursor as having one consumer, including iteration,
|
|
51
|
+
fetching, batch access, and closing.
|
|
52
|
+
|
|
53
|
+
e. Test both client usage patterns with overlapping requests, independent cursors, JWT renewal, and shutdown. Check for
|
|
54
|
+
deadlocks and blocked threads after failures.
|
|
55
|
+
|
|
56
|
+
## API versioning
|
|
57
|
+
|
|
58
|
+
Versioned APIs can change accepted parameters, response fields, and endpoint behavior. Supporting them requires more
|
|
59
|
+
than changing URL prefixes: the driver must preserve existing Python calls while exposing incompatible contracts through
|
|
60
|
+
clear method signatures and accurate type hints.
|
|
61
|
+
|
|
62
|
+
a. Add optional API version selection to client.db(), retaining legacy behavior when omitted. Keep the selected policy
|
|
63
|
+
fixed on the connection and propagate it through cursors and execution contexts.
|
|
64
|
+
|
|
65
|
+
b. Group operation-specific request builders and response decoders into adapters selected by each version policy. Reuse
|
|
66
|
+
unchanged adapters and keep authentication, transport, and retries separate.
|
|
67
|
+
|
|
68
|
+
c. Preserve StandardCollection as the legacy interface. Share unchanged methods through a common base and introduce
|
|
69
|
+
sibling version-specific wrappers where signatures or result contracts differ.
|
|
70
|
+
|
|
71
|
+
d. Use Literal overloads to select typed database and collection wrappers, and TypedDict definitions for
|
|
72
|
+
version-specific results. Preserve missing legacy fields only when they can be derived accurately.
|
|
73
|
+
|
|
74
|
+
e. Validate version support and reject unsupported operations explicitly. Test legacy compatibility, version-specific
|
|
75
|
+
requests and results, type inference, and version propagation across execution contexts.
|
|
76
|
+
|
|
77
|
+
### Examples
|
|
78
|
+
|
|
79
|
+
These sketches describe proposed interfaces, not current driver features. The index parameters and result fields are
|
|
80
|
+
hypothetical; omitted implementations use `...`.
|
|
81
|
+
|
|
82
|
+
Existing calls retain their behavior, while callers explicitly opt into a new contract:
|
|
83
|
+
|
|
84
|
+
```python
|
|
85
|
+
legacy = client.db("example", **credentials)
|
|
86
|
+
modern = client.db("example", api_version="v1", **credentials)
|
|
87
|
+
|
|
88
|
+
legacy.collection("docs").index(foo="bar")
|
|
89
|
+
result = modern.collection("docs").index(foo={"bar": "bar"})
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Each policy groups adapters for its contract. Adapters build complete requests and decode successful responses;
|
|
93
|
+
existing response handlers retain operation-specific exceptions and use `_execute()` to preserve execution contexts.
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
legacy_policy = ApiPolicy(
|
|
97
|
+
indexes=LegacyIndexAdapter(),
|
|
98
|
+
aql=LegacyAqlAdapter(),
|
|
99
|
+
cursors=LegacyCursorAdapter(),
|
|
100
|
+
)
|
|
101
|
+
v1_policy = ApiPolicy(
|
|
102
|
+
indexes=V1IndexAdapter(),
|
|
103
|
+
aql=V1AqlAdapter(),
|
|
104
|
+
cursors=V1CursorAdapter(),
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
class V1IndexAdapter:
|
|
108
|
+
def build_create_request(self, collection, definition) -> Request:
|
|
109
|
+
...
|
|
110
|
+
|
|
111
|
+
def decode_create_response(self, body) -> dict:
|
|
112
|
+
...
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Unchanged public methods share a base implementation. Incompatible methods belong to sibling classes, with separate
|
|
116
|
+
parameter and result types. Here, StandardCollection retains the legacy role discussed as V0Collection.
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
from typing import TypedDict
|
|
120
|
+
|
|
121
|
+
from arango.api import ApiGroup
|
|
122
|
+
from arango.result import Result
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
class V1IndexOptions(TypedDict):
|
|
126
|
+
bar: str
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
class V0IndexResult(TypedDict):
|
|
130
|
+
id: str
|
|
131
|
+
legacy_field: str
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
class V1IndexResult(TypedDict):
|
|
135
|
+
id: str
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
class CommonCollection(ApiGroup):
|
|
139
|
+
def count(self) -> Result[int]:
|
|
140
|
+
...
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
class StandardCollection(CommonCollection):
|
|
144
|
+
def index(self, *, foo: str) -> Result[V0IndexResult]:
|
|
145
|
+
...
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
class V1Collection(CommonCollection):
|
|
149
|
+
def index(self, *, foo: V1IndexOptions) -> Result[V1IndexResult]:
|
|
150
|
+
...
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Both collection classes inherit `count()`. Their `index()` implementations delegate to version-specific adapters;
|
|
154
|
+
V1Collection does not override StandardCollection with an incompatible signature. V1IndexResult has no legacy_field.
|
|
155
|
+
|
|
156
|
+
Overloads connect version selection to the returned wrapper type. This sketch abbreviates existing arguments;
|
|
157
|
+
the actual signatures must preserve them and append `api_version` as a keyword-only parameter.
|
|
158
|
+
|
|
159
|
+
```python
|
|
160
|
+
from typing import Literal, overload
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
class ArangoClient:
|
|
164
|
+
@overload
|
|
165
|
+
def db(self, name: str, *, api_version: None = None) -> StandardDatabase: ...
|
|
166
|
+
|
|
167
|
+
@overload
|
|
168
|
+
def db(self, name: str, *, api_version: Literal["v1"]) -> V1Database: ...
|
|
169
|
+
|
|
170
|
+
def db(self, name: str, *, api_version: str | None = None):
|
|
171
|
+
...
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
StandardDatabase.collection() returns StandardCollection; V1Database.collection() returns V1Collection.
|
|
175
|
+
This lets type checkers reject a string passed to the v1 index method without widening both signatures to a union.
|
|
176
|
+
|
|
177
|
+
## Types
|
|
178
|
+
|
|
179
|
+
Generic dictionaries and long parameter lists make driver APIs difficult to discover and check statically. Typed inputs,
|
|
180
|
+
results, and query configuration objects should provide clearer signatures and property access while preserving existing
|
|
181
|
+
dictionary operations, JSON serialization, and method calls.
|
|
182
|
+
|
|
183
|
+
a. Add dictionary-based input and result models with typed constructors and explicit properties. Keep dictionary storage
|
|
184
|
+
authoritative, preserve existing keys, and retain unknown fields where current behavior does.
|
|
185
|
+
|
|
186
|
+
b. Accept typed index definitions alongside existing dictionaries. Return models such as Result[ServerVersion], wrapping
|
|
187
|
+
existing formatted responses and preserving asynchronous and batch execution behavior.
|
|
188
|
+
|
|
189
|
+
c. Add a Query object accepted by AQL.execute() alongside the full existing signature. Normalize both forms through one
|
|
190
|
+
execution path without mutating reusable query configuration.
|
|
191
|
+
|
|
192
|
+
d. Describe both execute() forms with overloads and one runtime implementation. Capture extra arguments to reject mixed
|
|
193
|
+
configuration, preserving existing defaults and positional arguments for string calls.
|
|
194
|
+
|
|
195
|
+
e. Test dictionary operations, properties, JSON serialization, custom serializers, and both query forms. Document
|
|
196
|
+
mutation limits and use opt-in typed responses where exact dictionary types must remain compatible.
|
|
197
|
+
|
|
198
|
+
### Examples
|
|
199
|
+
|
|
200
|
+
These are proposed interfaces and abbreviated implementation sketches. Models are instances passed to methods, not
|
|
201
|
+
classes. The earlier TypedDict examples describe schemas; dictionary subclasses additionally provide runtime accessors.
|
|
202
|
+
|
|
203
|
+
Typed index definitions supplement existing dictionary inputs. Request definitions and returned index descriptions
|
|
204
|
+
should use separate models because their required fields differ.
|
|
205
|
+
|
|
206
|
+
```python
|
|
207
|
+
collection.add_index(VectorIndex(fields=["embedding"], params=vector_params))
|
|
208
|
+
collection.add_index(InvertedIndex(fields=["title"]))
|
|
209
|
+
collection.add_index({"type": "inverted", "fields": ["title"]})
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
A response model keeps property and dictionary access consistent, without storing a second copy of each value:
|
|
213
|
+
|
|
214
|
+
```python
|
|
215
|
+
import json
|
|
216
|
+
from typing import Any, cast
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
class ServerVersion(dict[str, Any]):
|
|
220
|
+
@property
|
|
221
|
+
def version(self) -> str:
|
|
222
|
+
return cast(str, self["version"])
|
|
223
|
+
|
|
224
|
+
@version.setter
|
|
225
|
+
def version(self, value: str) -> None:
|
|
226
|
+
self["version"] = value
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
result = ServerVersion(version="3.12.11", server="arango")
|
|
230
|
+
assert result.version == result["version"]
|
|
231
|
+
result.version = "3.12.12"
|
|
232
|
+
assert result["version"] == "3.12.12"
|
|
233
|
+
plain = dict(result)
|
|
234
|
+
encoded = json.dumps(result)
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
server_version() would return Result[ServerVersion], wrapping format_body(resp.body) in ServerVersion on success.
|
|
238
|
+
Keep existing formatting before wrapping; version adapters select different models when needed.
|
|
239
|
+
|
|
240
|
+
dict(result) makes a shallow copy. Nested values must also be JSON-compatible; a recursive to_dict() can provide plain
|
|
241
|
+
nested dictionaries if required. Unknown keys remain accessible through dictionary syntax.
|
|
242
|
+
|
|
243
|
+
Dictionary subclasses pass isinstance(result, dict), but not type(result) is dict. Custom serializers need compatibility
|
|
244
|
+
checks. Explicit properties avoid collisions with dictionary methods such as items() and keys().
|
|
245
|
+
|
|
246
|
+
cast() provides a static hint, not runtime validation. Direct dictionary mutation can still introduce invalid values or
|
|
247
|
+
remove required fields. Validate typed constructors or provide explicit validation without restricting legacy dictionary
|
|
248
|
+
operations; optional accessors should not insert absent fields into the response.
|
|
249
|
+
|
|
250
|
+
A Query object groups the text, bind variables, and execution options without replacing the existing call form:
|
|
251
|
+
|
|
252
|
+
```python
|
|
253
|
+
text = "FOR doc IN documents FILTER doc.active == @active RETURN doc"
|
|
254
|
+
|
|
255
|
+
cursor = db.aql.execute(text, bind_vars={"active": True}, batch_size=100)
|
|
256
|
+
|
|
257
|
+
query = Query(text=text, bind_vars={"active": True}, batch_size=100)
|
|
258
|
+
cursor = db.aql.execute(query=query)
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
Overloads describe the accepted forms to type checkers. One implementation dispatches on the query type; two ordinary
|
|
262
|
+
execute() definitions would replace one another. This sketch shows only count and batch_size; retain all existing
|
|
263
|
+
parameters in the actual string overload and the helper handling legacy calls.
|
|
264
|
+
|
|
265
|
+
```python
|
|
266
|
+
from typing import overload
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
class AQL:
|
|
270
|
+
@overload
|
|
271
|
+
def execute(self, query: Query) -> Result[Cursor]: ...
|
|
272
|
+
|
|
273
|
+
@overload
|
|
274
|
+
def execute(
|
|
275
|
+
self, query: str, count: bool = False, batch_size: int | None = None
|
|
276
|
+
) -> Result[Cursor]: ...
|
|
277
|
+
|
|
278
|
+
def execute(self, query: str | Query, *args, **kwargs) -> Result[Cursor]:
|
|
279
|
+
if isinstance(query, Query):
|
|
280
|
+
if args or kwargs:
|
|
281
|
+
raise TypeError("A Query object cannot be combined with other arguments")
|
|
282
|
+
return self._execute_query(query)
|
|
283
|
+
return self._execute_legacy(query, *args, **kwargs)
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
The _execute_legacy() helper retains the full existing signature and defaults, then normalizes its arguments into the
|
|
287
|
+
same execution path as _execute_query(). Capturing arguments before defaults are applied distinguishes every explicit
|
|
288
|
+
extra argument, including None and False, without sentinels.
|
|
289
|
+
|
|
290
|
+
```python
|
|
291
|
+
db.aql.execute(query) # Accepted.
|
|
292
|
+
db.aql.execute(query=query) # Accepted.
|
|
293
|
+
db.aql.execute(query, batch_size=None) # TypeError: explicit extra keyword argument.
|
|
294
|
+
db.aql.execute(query, False) # TypeError: explicit extra positional argument.
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
The existing Sphinx autodoc configuration rendered both overloads, including their defaults and type hints, in a
|
|
298
|
+
temporary build with Sphinx 8.2.3. No additional extension or configuration was needed. Keep overloads complete for IDEs
|
|
299
|
+
and generated API documentation; documentation dependencies currently do not pin Sphinx.
|
|
300
|
+
|
|
301
|
+
Runtime inspect.signature() still exposes (self, query, *args, **kwargs). Overloads improve static tooling and this
|
|
302
|
+
project's generated documentation, but do not change runtime argument binding or enforce the mixed-argument rule.
|
|
303
|
+
|
|
304
|
+
The shared execution path must preserve more than the JSON body: allow_dirty_read controls a request header, while
|
|
305
|
+
allow_retry also configures the returned cursor. Keep cursor state separate and snapshot mutable query configuration
|
|
306
|
+
as needed so executing a Query does not change it.
|
|
307
|
+
|
|
308
|
+
## Response format
|
|
309
|
+
|
|
310
|
+
Response formatting inconsistently renames keys, drops unknown fields, and changes values such as index identifiers.
|
|
311
|
+
Disabling formatting does not reliably preserve server data. Responses need predictable dictionary representations and
|
|
312
|
+
stable snake_case properties, with a compatibility mode for applications relying on historical transformations.
|
|
313
|
+
|
|
314
|
+
a. Add fixed server and legacy response formats per database wrapper, independently of API version. Make server the
|
|
315
|
+
next major release's default and retain legacy indefinitely.
|
|
316
|
+
|
|
317
|
+
b. Preserve server resource keys, values, and unknown fields in server mode. Isolate historical transformations in
|
|
318
|
+
legacy adapters; define unchanged server names for new fields without historical mappings.
|
|
319
|
+
|
|
320
|
+
c. Implement response models as dict subclasses with explicit snake_case properties. Store only the selected
|
|
321
|
+
representation, and use sibling legacy implementations where property mappings differ.
|
|
322
|
+
|
|
323
|
+
d. Separate envelope extraction from resource formatting. Avoid mutating input dictionaries or renaming user data;
|
|
324
|
+
document copying, optional properties, and value differences between representations.
|
|
325
|
+
|
|
326
|
+
e. Audit formatter.py and inline cursor transformations. Test both formats, property synchronization, serialization, and
|
|
327
|
+
execution contexts; document migration, existing formatter options, and exact-dict compatibility limits.
|
|
328
|
+
|
|
329
|
+
### Examples
|
|
330
|
+
|
|
331
|
+
These are proposed interfaces. Select the format once; collections, cursors, and asynchronous or batch results inherit
|
|
332
|
+
that selection. API version and response format remain independent choices.
|
|
333
|
+
|
|
334
|
+
```python
|
|
335
|
+
modern = client.db("example", response_format="server", **credentials)
|
|
336
|
+
legacy = client.db("example", response_format="legacy", **credentials)
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
Both representations offer the same snake_case property names. Dictionary access and JSON serialization use the selected
|
|
340
|
+
keys, without storing duplicate aliases. This simplified model illustrates a required field of a TTL index:
|
|
341
|
+
|
|
342
|
+
```python
|
|
343
|
+
import json
|
|
344
|
+
from typing import Any, ClassVar, cast
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
class IndexInfo(dict[str, Any]):
|
|
348
|
+
_expiry_key: ClassVar[str] = "expireAfter"
|
|
349
|
+
|
|
350
|
+
@property
|
|
351
|
+
def expire_after(self) -> int:
|
|
352
|
+
return cast(int, self[self._expiry_key])
|
|
353
|
+
|
|
354
|
+
@expire_after.setter
|
|
355
|
+
def expire_after(self, value: int) -> None:
|
|
356
|
+
self[self._expiry_key] = value
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
class LegacyIndexInfo(IndexInfo):
|
|
360
|
+
_expiry_key = "expiry_time"
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
server = IndexInfo({"expireAfter": 60})
|
|
364
|
+
legacy = LegacyIndexInfo({"expiry_time": 60})
|
|
365
|
+
assert server.expire_after == legacy.expire_after
|
|
366
|
+
|
|
367
|
+
legacy.expire_after = 120
|
|
368
|
+
assert legacy["expiry_time"] == 120
|
|
369
|
+
assert dict(server) == {"expireAfter": 60}
|
|
370
|
+
assert json.loads(json.dumps(legacy)) == {"expiry_time": 120}
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
The response adapter prepares the selected representation and constructs its model. Actual models must reflect the
|
|
374
|
+
field's numeric range and optionality. Properties read dictionary storage directly, including changes made through
|
|
375
|
+
update() or item assignment; unrestricted dictionary mutation still cannot guarantee valid field types.
|
|
376
|
+
|
|
377
|
+
Keep legacy value and structure conversions explicit: shortening an index ID is not a key alias. Document whether
|
|
378
|
+
properties expose the selected stored value or a separately derived value. Do not reconstruct lost information from
|
|
379
|
+
legacy data or retain a second mutable dictionary that can drift out of sync.
|
|
380
|
+
|
|
381
|
+
Use the async driver's JsonWrapper properties as a reference, but inherit standard dictionary behavior instead of
|
|
382
|
+
reimplementing it. Its current wrapper lacks several dictionary methods, cannot be serialized directly by json.dumps(),
|
|
383
|
+
mutates constructor input, and exposes internal storage through to_dict().
|
|
384
|
+
|
|
385
|
+
Copy input mappings during construction. dict(model) and a basic to_dict() should return shallow copies; document nested
|
|
386
|
+
sharing or provide explicit recursive conversion. Envelope removal belongs in endpoint response handling, not the model
|
|
387
|
+
base class. Never apply generic recursive key conversion to documents, bind variables, or user-defined names.
|
|
388
|
+
|
|
389
|
+
Retaining legacy indefinitely requires permanent compatibility tests. Freeze historical mappings and document handling
|
|
390
|
+
of new fields; preserve existing formatter options in legacy mode and reject conflicting options in server mode.
|
|
391
|
+
Dictionary subclasses preserve isinstance(result, dict), but change type(result) is dict; include this and custom
|
|
392
|
+
serializer compatibility in the major-release migration notes.
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
## Documentation tests
|
|
396
|
+
|
|
397
|
+
This could be done better, especially for the async driver.
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
name: Upload to PyPI
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
release:
|
|
5
|
-
types: [published]
|
|
6
|
-
|
|
7
|
-
jobs:
|
|
8
|
-
upload:
|
|
9
|
-
runs-on: ubuntu-latest
|
|
10
|
-
|
|
11
|
-
steps:
|
|
12
|
-
- name: Checkout repository
|
|
13
|
-
uses: actions/checkout@v7
|
|
14
|
-
with:
|
|
15
|
-
fetch-depth: 0
|
|
16
|
-
fetch-tags: true
|
|
17
|
-
|
|
18
|
-
- uses: actions/setup-python@v7
|
|
19
|
-
with:
|
|
20
|
-
python-version: "3.12"
|
|
21
|
-
|
|
22
|
-
- name: Install dependencies
|
|
23
|
-
run: |
|
|
24
|
-
python -m pip install --upgrade pip
|
|
25
|
-
pip install build twine
|
|
26
|
-
|
|
27
|
-
- name: Build distribution
|
|
28
|
-
run: python -m build
|
|
29
|
-
|
|
30
|
-
- name: Publish to PyPI Test
|
|
31
|
-
env:
|
|
32
|
-
TWINE_USERNAME: __token__
|
|
33
|
-
TWINE_PASSWORD: ${{ secrets.PYPI_TEST_TOKEN }}
|
|
34
|
-
run: twine upload --verbose --repository testpypi dist/*
|
|
35
|
-
|
|
36
|
-
- name: Publish to PyPI
|
|
37
|
-
env:
|
|
38
|
-
TWINE_USERNAME: __token__
|
|
39
|
-
TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}
|
|
40
|
-
run: twine upload --verbose --repository pypi dist/*
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
# Contributing
|
|
2
|
-
|
|
3
|
-
Set up dev environment:
|
|
4
|
-
```shell
|
|
5
|
-
cd ~/your/repository/fork # Activate venv if you have one (recommended)
|
|
6
|
-
pip install -e .[dev] # Install dev dependencies (e.g. black, mypy, pre-commit)
|
|
7
|
-
pre-commit install # Install git pre-commit hooks
|
|
8
|
-
```
|
|
9
|
-
|
|
10
|
-
Run unit tests with coverage:
|
|
11
|
-
|
|
12
|
-
```shell
|
|
13
|
-
pytest --cov=arango --cov-report=html # Open htmlcov/index.html in your browser
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
To start and ArangoDB instance locally, run:
|
|
17
|
-
|
|
18
|
-
```shell
|
|
19
|
-
./starter.sh # Requires docker
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
Build and test documentation:
|
|
23
|
-
|
|
24
|
-
```shell
|
|
25
|
-
python -m sphinx docs docs/_build # Open docs/_build/index.html in your browser
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
Thank you for your contribution!
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "8.3.5"
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
Contributing
|
|
2
|
-
------------
|
|
3
|
-
|
|
4
|
-
Requirements
|
|
5
|
-
============
|
|
6
|
-
|
|
7
|
-
Before submitting a pull request on GitHub_, please make sure you meet the
|
|
8
|
-
following requirements:
|
|
9
|
-
|
|
10
|
-
* The pull request points to main_ branch.
|
|
11
|
-
* Changes are squashed into a single commit. I like to use git rebase for this.
|
|
12
|
-
* Commit message is in present tense. For example, "Fix bug" is good while
|
|
13
|
-
"Fixed bug" is not.
|
|
14
|
-
* Sphinx_-compatible docstrings.
|
|
15
|
-
* PEP8_ compliance.
|
|
16
|
-
* No missing docstrings or commented-out lines.
|
|
17
|
-
* Test coverage remains at %100. If a piece of code is trivial and does not
|
|
18
|
-
need unit tests, use this_ to exclude it from coverage.
|
|
19
|
-
* No build failures. Builds automatically trigger on pull
|
|
20
|
-
request submissions.
|
|
21
|
-
* Documentation is kept up-to-date with the new changes (see below).
|
|
22
|
-
|
|
23
|
-
.. warning::
|
|
24
|
-
The dev branch is occasionally rebased, and its commit history may be
|
|
25
|
-
overwritten in the process. Before you begin your feature work, git fetch
|
|
26
|
-
or pull to ensure that your local branch has not diverged. If you see git
|
|
27
|
-
conflicts and want to start with a clean slate, run the following commands:
|
|
28
|
-
|
|
29
|
-
.. code-block:: bash
|
|
30
|
-
|
|
31
|
-
~$ git checkout dev
|
|
32
|
-
~$ git fetch origin
|
|
33
|
-
~$ git reset --hard origin/dev # THIS WILL WIPE ALL LOCAL CHANGES
|
|
34
|
-
|
|
35
|
-
Style
|
|
36
|
-
=====
|
|
37
|
-
|
|
38
|
-
To ensure PEP8_ compliance, run flake8_:
|
|
39
|
-
|
|
40
|
-
.. code-block:: bash
|
|
41
|
-
|
|
42
|
-
~$ pip install flake8
|
|
43
|
-
~$ git clone https://github.com/arangodb/python-arango.git
|
|
44
|
-
~$ cd python-arango
|
|
45
|
-
~$ flake8
|
|
46
|
-
|
|
47
|
-
If there is a good reason to ignore a warning, see here_ on how to exclude it.
|
|
48
|
-
|
|
49
|
-
Testing
|
|
50
|
-
=======
|
|
51
|
-
|
|
52
|
-
To test your changes, you can run the integration test suite that comes with
|
|
53
|
-
**python-arango**. It uses pytest_ and requires an actual ArangoDB instance.
|
|
54
|
-
|
|
55
|
-
To run the test suite (use your own host, port and root password):
|
|
56
|
-
|
|
57
|
-
.. code-block:: bash
|
|
58
|
-
|
|
59
|
-
~$ pip install pytest
|
|
60
|
-
~$ git clone https://github.com/arangodb/python-arango.git
|
|
61
|
-
~$ cd python-arango
|
|
62
|
-
~$ pytest --cluster --host=127.0.0.1 --port=8529 --password=passwd
|
|
63
|
-
|
|
64
|
-
To run the test suite with coverage report:
|
|
65
|
-
|
|
66
|
-
.. code-block:: bash
|
|
67
|
-
|
|
68
|
-
~$ pip install coverage pytest pytest-cov
|
|
69
|
-
~$ git clone https://github.com/arangodb/python-arango.git
|
|
70
|
-
~$ cd python-arango
|
|
71
|
-
~$ pytest --cluster --host=127.0.0.1 --port=8529 --password=passwd --cov=kq
|
|
72
|
-
|
|
73
|
-
As the test suite creates real databases and jobs, it should only be run in
|
|
74
|
-
development environments.
|
|
75
|
-
|
|
76
|
-
Documentation
|
|
77
|
-
=============
|
|
78
|
-
|
|
79
|
-
The documentation including the README is written in reStructuredText_ and uses
|
|
80
|
-
Sphinx_. To build an HTML version on your local machine:
|
|
81
|
-
|
|
82
|
-
.. code-block:: bash
|
|
83
|
-
|
|
84
|
-
~$ pip install sphinx sphinx_rtd_theme
|
|
85
|
-
~$ git clone https://github.com/arangodb/python-arango.git
|
|
86
|
-
~$ cd python-arango
|
|
87
|
-
~$ python -m sphinx -b html -W docs docs/_build/ # Open build/index.html in a browser
|
|
88
|
-
|
|
89
|
-
As always, thank you for your contribution!
|
|
90
|
-
|
|
91
|
-
.. _main: https://github.com/arangodb/python-arango/tree/main
|
|
92
|
-
.. _GitHub: https://github.com/arangodb/python-arango
|
|
93
|
-
.. _PEP8: https://www.python.org/dev/peps/pep-0008/
|
|
94
|
-
.. _this: http://coverage.readthedocs.io/en/latest/excluding.html
|
|
95
|
-
.. _Sphinx: https://github.com/sphinx-doc/sphinx
|
|
96
|
-
.. _flake8: http://flake8.pycqa.org
|
|
97
|
-
.. _here: http://flake8.pycqa.org/en/latest/user/violations.html#in-line-ignoring-errors
|
|
98
|
-
.. _pytest: https://github.com/pytest-dev/pytest
|
|
99
|
-
.. _reStructuredText: https://en.wikipedia.org/wiki/ReStructuredText
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|