python-arango-async 1.2.4__tar.gz → 1.2.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.
Files changed (116) hide show
  1. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/.circleci/config.yml +27 -13
  2. python_arango_async-1.2.6/.github/workflows/pypi.yaml +66 -0
  3. python_arango_async-1.2.6/AGENTS.md +91 -0
  4. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/PKG-INFO +2 -2
  5. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/arangoasync/typings.py +12 -0
  6. python_arango_async-1.2.6/arangoasync/version.py +1 -0
  7. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/docs/indexes.rst +42 -0
  8. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/pyproject.toml +1 -1
  9. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/python_arango_async.egg-info/PKG-INFO +2 -2
  10. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/python_arango_async.egg-info/SOURCES.txt +1 -1
  11. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/python_arango_async.egg-info/requires.txt +1 -1
  12. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/python_arango_async.egg-info/scm_file_list.json +1 -1
  13. python_arango_async-1.2.6/python_arango_async.egg-info/scm_version.json +8 -0
  14. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/starter.sh +3 -2
  15. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/tests/test_collection.py +126 -8
  16. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/tests/test_typings.py +26 -0
  17. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/tests/test_user.py +9 -0
  18. python_arango_async-1.2.4/.github/workflows/pypi.yaml +0 -40
  19. python_arango_async-1.2.4/CONTRIBUTING.md +0 -28
  20. python_arango_async-1.2.4/arangoasync/version.py +0 -1
  21. python_arango_async-1.2.4/python_arango_async.egg-info/scm_version.json +0 -8
  22. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/.github/workflows/codeql.yaml +0 -0
  23. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/.github/workflows/docs.yaml +0 -0
  24. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/.gitignore +0 -0
  25. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/.pre-commit-config.yaml +0 -0
  26. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/.readthedocs.yaml +0 -0
  27. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/LICENSE +0 -0
  28. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/README.md +0 -0
  29. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/arangoasync/__init__.py +0 -0
  30. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/arangoasync/aql.py +0 -0
  31. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/arangoasync/auth.py +0 -0
  32. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/arangoasync/backup.py +0 -0
  33. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/arangoasync/client.py +0 -0
  34. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/arangoasync/cluster.py +0 -0
  35. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/arangoasync/collection.py +0 -0
  36. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/arangoasync/compression.py +0 -0
  37. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/arangoasync/connection.py +0 -0
  38. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/arangoasync/cursor.py +0 -0
  39. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/arangoasync/database.py +0 -0
  40. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/arangoasync/errno.py +0 -0
  41. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/arangoasync/exceptions.py +0 -0
  42. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/arangoasync/executor.py +0 -0
  43. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/arangoasync/foxx.py +0 -0
  44. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/arangoasync/graph.py +0 -0
  45. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/arangoasync/http.py +0 -0
  46. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/arangoasync/job.py +0 -0
  47. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/arangoasync/logger.py +0 -0
  48. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/arangoasync/replication.py +0 -0
  49. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/arangoasync/request.py +0 -0
  50. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/arangoasync/resolver.py +0 -0
  51. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/arangoasync/response.py +0 -0
  52. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/arangoasync/result.py +0 -0
  53. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/arangoasync/serialization.py +0 -0
  54. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/docs/admin.rst +0 -0
  55. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/docs/analyzer.rst +0 -0
  56. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/docs/aql.rst +0 -0
  57. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/docs/async.rst +0 -0
  58. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/docs/authentication.rst +0 -0
  59. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/docs/backup.rst +0 -0
  60. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/docs/certificates.rst +0 -0
  61. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/docs/cluster.rst +0 -0
  62. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/docs/collection.rst +0 -0
  63. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/docs/compression.rst +0 -0
  64. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/docs/conf.py +0 -0
  65. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/docs/cursor.rst +0 -0
  66. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/docs/database.rst +0 -0
  67. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/docs/document.rst +0 -0
  68. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/docs/errno.rst +0 -0
  69. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/docs/errors.rst +0 -0
  70. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/docs/foxx.rst +0 -0
  71. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/docs/graph.rst +0 -0
  72. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/docs/helpers.rst +0 -0
  73. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/docs/http.rst +0 -0
  74. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/docs/index.rst +0 -0
  75. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/docs/logging.rst +0 -0
  76. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/docs/migration.rst +0 -0
  77. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/docs/overview.rst +0 -0
  78. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/docs/serialization.rst +0 -0
  79. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/docs/specs.rst +0 -0
  80. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/docs/static/logo.png +0 -0
  81. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/docs/task.rst +0 -0
  82. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/docs/transaction.rst +0 -0
  83. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/docs/user.rst +0 -0
  84. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/docs/view.rst +0 -0
  85. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/python_arango_async.egg-info/dependency_links.txt +0 -0
  86. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/python_arango_async.egg-info/top_level.txt +0 -0
  87. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/setup.cfg +0 -0
  88. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/setup.py +0 -0
  89. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/tests/__init__.py +0 -0
  90. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/tests/conftest.py +0 -0
  91. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/tests/helpers.py +0 -0
  92. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/tests/static/cluster-3.12.conf +0 -0
  93. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/tests/static/cluster-4.0.conf +0 -0
  94. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/tests/static/keyfile +0 -0
  95. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/tests/static/service.zip +0 -0
  96. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/tests/static/single-3.12.conf +0 -0
  97. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/tests/static/single-4.0.conf +0 -0
  98. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/tests/test_analyzer.py +0 -0
  99. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/tests/test_aql.py +0 -0
  100. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/tests/test_async.py +0 -0
  101. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/tests/test_backup.py +0 -0
  102. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/tests/test_client.py +0 -0
  103. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/tests/test_cluster.py +0 -0
  104. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/tests/test_compression.py +0 -0
  105. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/tests/test_connection.py +0 -0
  106. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/tests/test_cursor.py +0 -0
  107. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/tests/test_database.py +0 -0
  108. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/tests/test_document.py +0 -0
  109. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/tests/test_foxx.py +0 -0
  110. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/tests/test_graph.py +0 -0
  111. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/tests/test_http.py +0 -0
  112. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/tests/test_imports.py +0 -0
  113. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/tests/test_resolver.py +0 -0
  114. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/tests/test_task.py +0 -0
  115. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/tests/test_transaction.py +0 -0
  116. {python_arango_async-1.2.4 → python_arango_async-1.2.6}/tests/test_view.py +0 -0
@@ -30,19 +30,33 @@ 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
38
  arangodb_conf_version: ["3.12"]
39
39
  - integration-test:
40
- name: ArangoDB (enterprise-preview, 4.0-nightly << matrix.arangodb_config >>)
40
+ name: ArangoDB (enterprise, 3.12.9 << matrix.arangodb_config >>)
41
41
  matrix:
42
42
  parameters:
43
43
  arangodb_config: ["single", "cluster"]
44
- arangodb_image: ["arangodb/enterprise-preview:4.0-nightly"]
45
- arangodb_conf_version: ["4.0"]
44
+ arangodb_image: ["arangodb/enterprise:3.12.9"]
45
+ arangodb_conf_version: ["3.12"]
46
+ - integration-test:
47
+ name: ArangoDB (core-preview, 4.0-nightly << matrix.arangodb_config >>)
48
+ matrix:
49
+ parameters:
50
+ arangodb_config: [ "single", "cluster" ]
51
+ arangodb_image: [ "arangodb/core-preview:4.0-nightly" ]
52
+ arangodb_conf_version: [ "4.0" ]
53
+ - integration-test:
54
+ name: ArangoDB (enterprise-preview, 3.12-nightly << matrix.arangodb_config >>)
55
+ matrix:
56
+ parameters:
57
+ arangodb_config: ["single", "cluster"]
58
+ arangodb_image: ["arangodb/enterprise-preview:3.12-nightly"]
59
+ arangodb_conf_version: ["3.12"]
46
60
 
47
61
  jobs:
48
62
  lint:
@@ -53,8 +67,8 @@ jobs:
53
67
  name: Install Dependencies
54
68
  command: python -m pip install .[dev]
55
69
  - run:
56
- name: Run black
57
- command: black --check --verbose --diff --color --config=pyproject.toml ./arangoasync ./tests/
70
+ name: Run black
71
+ command: black --check --verbose --diff --color --config=pyproject.toml ./arangoasync ./tests/
58
72
  - run:
59
73
  name: Run flake8
60
74
  command: flake8 ./arangoasync ./tests
@@ -83,12 +97,12 @@ jobs:
83
97
  command: python -m pytest tests/test_imports.py --skip-arango-setup --color=yes --code-highlight=yes
84
98
  integration-test:
85
99
  parameters:
86
- arangodb_config:
87
- type: string
88
- arangodb_image:
89
- type: string
90
- arangodb_conf_version:
91
- type: string
100
+ arangodb_config:
101
+ type: string
102
+ arangodb_image:
103
+ type: string
104
+ arangodb_conf_version:
105
+ type: string
92
106
  executor:
93
107
  name: arangodb-container
94
108
  arangodb_image: << parameters.arangodb_image >>
@@ -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,91 @@
1
+ # Quickstart
2
+
3
+ python-arango-async is an async Python driver for ArangoDB. Run the commands below from the
4
+ repository root.
5
+
6
+ ## Repository layout
7
+
8
+ - `arangoasync/`: 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. In this workspace, use
28
+ `/home/apetenchea/programs/pyenv/ida/bin/python` and run tests from
29
+ `/home/apetenchea/arangodb/python-arango-async`, so they exercise this driver.
30
+
31
+ ## Local cluster and tests
32
+
33
+ The starter requires Docker, Bash, `wget`, and `jq`. To replace an existing test
34
+ container, run `docker stop arango` and `docker rm arango` first.
35
+
36
+ ```bash
37
+ version="latest" # Or pin a supported version, such as 3.12.10.
38
+ ./starter.sh cluster enterprise "$version" # Start a local test cluster.
39
+ python -m pytest --cluster # Run the full suite against the cluster.
40
+ # Run one test while developing a document change.
41
+ python -m pytest --cluster tests/test_document.py::test_document_insert
42
+ # Generate an HTML coverage report.
43
+ python -m pytest --cluster --cov=arangoasync --cov-report=html
44
+ ```
45
+
46
+ Defaults are `127.0.0.1:8529`, user `root`, password `passwd`, and JWT secret
47
+ `secret`, matching the starter configuration. Override them with `--host`,
48
+ `--port`, `--root`, `--password`, and `--secret`. Use a disposable development
49
+ database: tests create and delete databases, users, jobs, and backups. If a
50
+ sandbox blocks localhost access, rerun with the required sandbox permission.
51
+
52
+ For a single server, use `./starter.sh single enterprise "$version"` and omit
53
+ `--cluster`. Import tests can run without ArangoDB:
54
+
55
+ ```bash
56
+ python -m pytest tests/test_imports.py --skip-arango-setup # Check imports offline.
57
+ ```
58
+
59
+ ## Style and documentation
60
+
61
+ Run the configured hooks for formatting, import ordering, linting, and type
62
+ checks. Build and test documentation separately:
63
+
64
+ ```bash
65
+ pre-commit run --all-files # Run hooks; formatters may modify files.
66
+ python -m sphinx -b html docs docs/_build # Build the HTML documentation.
67
+ python -m sphinx -b doctest docs docs/_build # Test documentation examples.
68
+ ```
69
+
70
+ The Sphinx doctests require a running ArangoDB server. Open
71
+ `docs/_build/index.html` for the HTML documentation or `htmlcov/index.html` for
72
+ the coverage report.
73
+
74
+ ## Changes and pull requests
75
+
76
+ - Agents must work on a branch other than `main`; never commit directly to `main`.
77
+ Check the current branch before editing or committing. If on `main` or a
78
+ detached HEAD, create a branch first:
79
+
80
+ ```bash
81
+ git branch --show-current # Check the current branch.
82
+ git switch -c fix/describe-change # Choose a descriptive branch name.
83
+ ```
84
+
85
+ - Preserve public API compatibility unless a breaking change is intentional.
86
+ - Follow existing code patterns, type annotations, and Sphinx docstrings.
87
+ - Add regression tests for fixes and tests for new behavior; update user documentation.
88
+ - Run relevant tests and checks; report anything skipped and why.
89
+ - Keep test coverage up and squash changes into one commit for submission.
90
+ - Use present-tense commit messages, such as `Fix cursor retry`.
91
+ - 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-async
3
- Version: 1.2.4
3
+ Version: 1.2.6
4
4
  Summary: Async Python Driver for ArangoDB
5
5
  Author-email: Alexandru Petenchea <alexandru.petenchea@arangodb.com>, Anthony Mahanna <anthony.mahanna@arangodb.com>
6
6
  Maintainer-email: Alexandru Petenchea <alexandru.petenchea@arangodb.com>, Anthony Mahanna <anthony.mahanna@arangodb.com>
@@ -26,7 +26,7 @@ Requires-Dist: multidict>=6.0
26
26
  Requires-Dist: pyjwt>=2.10.0
27
27
  Provides-Extra: dev
28
28
  Requires-Dist: aiofiles>=24.1.0; extra == "dev"
29
- Requires-Dist: black==26.3.1; extra == "dev"
29
+ Requires-Dist: black==26.5.1; extra == "dev"
30
30
  Requires-Dist: flake8==7.3.0; extra == "dev"
31
31
  Requires-Dist: isort>=5.10.1; extra == "dev"
32
32
  Requires-Dist: mypy==1.15.0; extra == "dev"
@@ -1060,6 +1060,10 @@ class IndexProperties(JsonWrapper):
1060
1060
  def legacy_polygons(self) -> Optional[bool]:
1061
1061
  return self._data.get("legacyPolygons")
1062
1062
 
1063
+ @property
1064
+ def figures(self) -> Optional[Json]:
1065
+ return self._data.get("figures")
1066
+
1063
1067
  @property
1064
1068
  def estimates(self) -> Optional[bool]:
1065
1069
  return self._data.get("estimates")
@@ -1140,6 +1144,10 @@ class IndexProperties(JsonWrapper):
1140
1144
  def training_state(self) -> Optional[str]:
1141
1145
  return self._data.get("trainingState")
1142
1146
 
1147
+ @property
1148
+ def shards(self) -> Optional[Json]:
1149
+ return self._data.get("shards")
1150
+
1143
1151
  @staticmethod
1144
1152
  def compatibility_formatter(data: Json) -> Json:
1145
1153
  """python-arango compatibility formatter."""
@@ -1170,6 +1178,8 @@ class IndexProperties(JsonWrapper):
1170
1178
  result["storedValues"] = data["storedValues"]
1171
1179
  if "legacyPolygons" in data:
1172
1180
  result["legacyPolygons"] = data["legacyPolygons"]
1181
+ if "figures" in data:
1182
+ result["figures"] = data["figures"]
1173
1183
  if "estimates" in data:
1174
1184
  result["estimates"] = data["estimates"]
1175
1185
  if "analyzer" in data:
@@ -1202,6 +1212,8 @@ class IndexProperties(JsonWrapper):
1202
1212
  result["error_message"] = data["errorMessage"]
1203
1213
  if "trainingState" in data:
1204
1214
  result["training_state"] = data["trainingState"]
1215
+ if "shards" in data:
1216
+ result["shards"] = data["shards"]
1205
1217
  return result
1206
1218
 
1207
1219
  def format(self, formatter: Optional[Formatter] = None) -> Json:
@@ -0,0 +1 @@
1
+ __version__ = "1.2.6"
@@ -50,4 +50,46 @@ on fields ``_from`` and ``_to``. For more information on indexes, refer to
50
50
  # Delete the last index from the collection.
51
51
  await cities.delete_index(index["id"])
52
52
 
53
+ # Insert documents with vector embeddings.
54
+ await cities.insert_many([
55
+ {
56
+ "_key": f"city{i}",
57
+ "continent": f"continent{i}",
58
+ "country": f"country{i}",
59
+ "population": i,
60
+ "coordinates": [float(i % 180), float(i % 90)],
61
+ "embedding": [float(i), float(i % 7), float(i % 11), 1.0],
62
+ }
63
+ for i in range(100)
64
+ ])
65
+
66
+ # Let ArangoDB determine the number of vector-index centroids.
67
+ vector_index = await cities.add_index(
68
+ type="vector",
69
+ fields=["embedding"],
70
+ options={
71
+ "name": "vector_index",
72
+ "params": {
73
+ "metric": "cosine",
74
+ "dimension": 4,
75
+ },
76
+ },
77
+ )
78
+
79
+ # Index creation may succeed even if there is insufficient training data.
80
+ if vector_index.training_state != "ready":
81
+ raise RuntimeError(
82
+ vector_index.error_message or "Vector index is not ready"
83
+ )
84
+
85
+ Omitted or scaling-object ``nLists``, ``numberOfDocsPerCentroid``, factory
86
+ placeholders such as ``IVF{},Flat``, and successful-but-unusable creation
87
+ behavior require ArangoDB 3.12.10 or later. A successful creation response
88
+ means that the index exists, but callers should check ``training_state`` before
89
+ using it. If there is insufficient data to train the index, the state is
90
+ ``"unusable"`` and ``error_message`` describes the failure. Invalid index
91
+ definitions, such as an ``nLists`` value that disagrees with the number of
92
+ centroids in the factory string, are rejected during creation with
93
+ ``IndexCreateError`` and no index is created.
94
+
53
95
  See :class:`arangoasync.collection.StandardCollection` for API specification.
@@ -49,7 +49,7 @@ version = { attr = "arangoasync.version.__version__" }
49
49
  [project.optional-dependencies]
50
50
  dev = [
51
51
  "aiofiles>=24.1.0",
52
- "black==26.3.1",
52
+ "black==26.5.1",
53
53
  "flake8==7.3.0",
54
54
  "isort>=5.10.1",
55
55
  "mypy==1.15.0",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-arango-async
3
- Version: 1.2.4
3
+ Version: 1.2.6
4
4
  Summary: Async Python Driver for ArangoDB
5
5
  Author-email: Alexandru Petenchea <alexandru.petenchea@arangodb.com>, Anthony Mahanna <anthony.mahanna@arangodb.com>
6
6
  Maintainer-email: Alexandru Petenchea <alexandru.petenchea@arangodb.com>, Anthony Mahanna <anthony.mahanna@arangodb.com>
@@ -26,7 +26,7 @@ Requires-Dist: multidict>=6.0
26
26
  Requires-Dist: pyjwt>=2.10.0
27
27
  Provides-Extra: dev
28
28
  Requires-Dist: aiofiles>=24.1.0; extra == "dev"
29
- Requires-Dist: black==26.3.1; extra == "dev"
29
+ Requires-Dist: black==26.5.1; extra == "dev"
30
30
  Requires-Dist: flake8==7.3.0; extra == "dev"
31
31
  Requires-Dist: isort>=5.10.1; extra == "dev"
32
32
  Requires-Dist: mypy==1.15.0; extra == "dev"
@@ -1,7 +1,7 @@
1
1
  .gitignore
2
2
  .pre-commit-config.yaml
3
3
  .readthedocs.yaml
4
- CONTRIBUTING.md
4
+ AGENTS.md
5
5
  LICENSE
6
6
  README.md
7
7
  pyproject.toml
@@ -5,7 +5,7 @@ pyjwt>=2.10.0
5
5
 
6
6
  [dev]
7
7
  aiofiles>=24.1.0
8
- black==26.3.1
8
+ black==26.5.1
9
9
  flake8==7.3.0
10
10
  isort>=5.10.1
11
11
  mypy==1.15.0
@@ -7,7 +7,7 @@
7
7
  ".gitignore",
8
8
  ".pre-commit-config.yaml",
9
9
  ".readthedocs.yaml",
10
- "CONTRIBUTING.md",
10
+ "AGENTS.md",
11
11
  "LICENSE",
12
12
  "README.md",
13
13
  "arangoasync/__init__.py",
@@ -0,0 +1,8 @@
1
+ {
2
+ "tag": "1.2.6",
3
+ "distance": 0,
4
+ "node": "gf4076da6dfc241bee1192e250dbb352edcc276ba",
5
+ "dirty": false,
6
+ "branch": "HEAD",
7
+ "node_date": "2026-10-04"
8
+ }
@@ -1,7 +1,7 @@
1
1
  #!/bin/bash
2
2
 
3
3
  # Starts a local ArangoDB server or cluster (community or enterprise).
4
- # Useful for testing the python-arango driver against a local ArangoDB setup.
4
+ # Useful for testing the python-arango-async driver against a local ArangoDB setup.
5
5
 
6
6
  # Usage:
7
7
  # ./starter.sh [single|cluster] [community|enterprise|enterprise-preview] [version]
@@ -10,9 +10,10 @@
10
10
  # ./starter.sh cluster enterprise 3.12.4
11
11
  # ./starter.sh single enterprise-preview 4.0-nightly
12
12
  # ./starter.sh single arangodb/enterprise-preview:4.0-nightly
13
+ # Defaults: single server, enterprise image, latest version.
13
14
 
14
15
  setup="${1:-single}"
15
- image="${2:-community}"
16
+ image="${2:-enterprise}"
16
17
  version="${3:-latest}"
17
18
 
18
19
  extra_ports=""
@@ -1,6 +1,7 @@
1
1
  import asyncio
2
2
 
3
3
  import pytest
4
+ from packaging import version
4
5
 
5
6
  from arangoasync.errno import DATA_SOURCE_NOT_FOUND, INDEX_NOT_FOUND
6
7
  from arangoasync.exceptions import (
@@ -113,11 +114,11 @@ async def test_collection_rename(cluster, db, bad_col, docs):
113
114
  doc = await col.insert(docs[0])
114
115
  assert col.get_col_name(doc) == new_name
115
116
  finally:
116
- db.delete_collection(new_name, ignore_missing=True)
117
+ await db.delete_collection(new_name, ignore_missing=True)
117
118
 
118
119
 
119
120
  @pytest.mark.asyncio
120
- async def test_collection_index(doc_col, bad_col, cluster):
121
+ async def test_collection_index(doc_col, bad_col, cluster, db_version):
121
122
  # Create indexes
122
123
  idx1 = await doc_col.add_index(
123
124
  type="persistent",
@@ -228,16 +229,22 @@ async def test_collection_index(doc_col, bad_col, cluster):
228
229
  await bad_col.load_indexes()
229
230
  assert err.value.error_code == DATA_SOURCE_NOT_FOUND
230
231
 
231
- # Create a vector index
232
+ # Create vector indexes using the fixed nLists format supported by older servers.
232
233
  docs = []
233
234
  for key in range(100):
234
- docs.append({"_key": f"key_{key}", "embedding": [1] * 128})
235
+ docs.append(
236
+ {
237
+ "_key": f"key_{key}",
238
+ "embedding1": [1] * 128,
239
+ "embedding2": [1] * 128,
240
+ }
241
+ )
235
242
  await doc_col.insert_many(docs)
236
243
  idx4 = await doc_col.add_index(
237
244
  "vector",
238
- ["embedding"],
245
+ ["embedding1"],
239
246
  {
240
- "name": "vector_index",
247
+ "name": "vector_index_1",
241
248
  "params": {
242
249
  "metric": "cosine",
243
250
  "dimension": 128,
@@ -245,19 +252,106 @@ async def test_collection_index(doc_col, bad_col, cluster):
245
252
  },
246
253
  },
247
254
  )
248
- assert idx4.name == "vector_index"
255
+ idx5 = await doc_col.add_index(
256
+ "vector",
257
+ ["embedding2"],
258
+ {
259
+ "name": "vector_index_2",
260
+ "params": {
261
+ "metric": "cosine",
262
+ "dimension": 128,
263
+ "nLists": 3,
264
+ },
265
+ },
266
+ )
267
+ assert idx4.name == "vector_index_1"
268
+ assert idx5.name == "vector_index_2"
269
+
270
+ if db_version >= version.parse("3.12.10"):
271
+ # Hidden listing details expose resolved vector-index settings per shard.
272
+ indexes = {idx.id: idx for idx in await doc_col.indexes(with_hidden=True)}
273
+ for index in (idx4, idx5):
274
+ shards = indexes[index.id].shards
275
+ assert shards is not None
276
+ for status in shards.values():
277
+ assert {
278
+ "trainingState",
279
+ "error",
280
+ "resolvedNLists",
281
+ } <= status.keys()
282
+ assert isinstance(status["resolvedNLists"], int)
249
283
 
250
284
  # Delete indexes
251
- del1, del2, del3, del4 = await asyncio.gather(
285
+ del1, del2, del3, del4, del5 = await asyncio.gather(
252
286
  doc_col.delete_index(idx1.id),
253
287
  doc_col.delete_index(idx2.numeric_id),
254
288
  doc_col.delete_index(str(idx3.numeric_id)),
255
289
  doc_col.delete_index(idx4.id),
290
+ doc_col.delete_index(idx5.id),
256
291
  )
257
292
  assert del1 is True
258
293
  assert del2 is True
259
294
  assert del3 is True
260
295
  assert del4 is True
296
+ assert del5 is True
297
+
298
+ if db_version >= version.parse("3.12.10"):
299
+ # Let the server choose nLists, then supply an explicit scaling object.
300
+ scaling_n_lists = {
301
+ "strategy": "autoSqrt",
302
+ "multiplier": 1,
303
+ "minNLists": 2,
304
+ "tiers": [],
305
+ }
306
+ default_index = await doc_col.add_index(
307
+ "vector",
308
+ ["embedding1"],
309
+ {
310
+ "name": "vector_index_default",
311
+ "params": {"metric": "cosine", "dimension": 128},
312
+ },
313
+ )
314
+ scaling_index = await doc_col.add_index(
315
+ "vector",
316
+ ["embedding2"],
317
+ {
318
+ "name": "vector_index_scaling",
319
+ "params": {
320
+ "metric": "cosine",
321
+ "dimension": 128,
322
+ "nLists": scaling_n_lists,
323
+ "numberOfDocsPerCentroid": 10,
324
+ "factory": "IVF{},Flat",
325
+ },
326
+ },
327
+ )
328
+
329
+ default_n_lists = default_index["params"]["nLists"]
330
+ assert default_n_lists["strategy"] == "autoSqrt"
331
+ assert default_n_lists["multiplier"] == 4
332
+ assert default_n_lists["minNLists"] == 2
333
+ assert scaling_index["params"]["nLists"] == scaling_n_lists
334
+ assert scaling_index["params"]["numberOfDocsPerCentroid"] == 10
335
+ assert scaling_index["params"]["factory"] == "IVF{},Flat"
336
+
337
+ await doc_col.delete_index(default_index.id)
338
+ await doc_col.delete_index(scaling_index.id)
339
+
340
+ # Invalid requests continue to fail at the HTTP layer.
341
+ with pytest.raises(IndexCreateError) as err:
342
+ await doc_col.add_index(
343
+ "vector",
344
+ ["embedding1"],
345
+ {
346
+ "name": "vector_index_invalid",
347
+ "params": {
348
+ "metric": "cosine",
349
+ "dimension": 128,
350
+ "nLists": 0,
351
+ },
352
+ },
353
+ )
354
+ assert err.value.http_code == 400
261
355
 
262
356
  # Now, the indexes should be gone
263
357
  with pytest.raises(IndexDeleteError) as err:
@@ -266,6 +360,30 @@ async def test_collection_index(doc_col, bad_col, cluster):
266
360
  assert await doc_col.delete_index(idx2.id, ignore_missing=True) is False
267
361
 
268
362
 
363
+ @pytest.mark.asyncio
364
+ async def test_unusable_vector_index(doc_col, db_version):
365
+ if db_version < version.parse("3.12.10"):
366
+ pytest.skip("Unusable vector index test requires ArangoDB 3.12.10+")
367
+
368
+ # One training vector is insufficient for two centroids.
369
+ await doc_col.insert({"embedding": [1.0, 1.0]})
370
+ index = await doc_col.add_index(
371
+ "vector",
372
+ ["embedding"],
373
+ {
374
+ "name": "vector_index_unusable",
375
+ "params": {
376
+ "metric": "cosine",
377
+ "dimension": 2,
378
+ "nLists": 2,
379
+ },
380
+ },
381
+ )
382
+ assert index.training_state == "unusable"
383
+ assert index.error_message
384
+ await doc_col.delete_index(index.id)
385
+
386
+
269
387
  @pytest.mark.asyncio
270
388
  async def test_collection_truncate_count(docs, doc_col, bad_col):
271
389
  # Test errors
@@ -9,6 +9,7 @@ from arangoasync.typings import (
9
9
  EdgeDefinitionOptions,
10
10
  GraphOptions,
11
11
  GraphProperties,
12
+ IndexProperties,
12
13
  JsonWrapper,
13
14
  KeyOptions,
14
15
  QueryCacheProperties,
@@ -449,6 +450,31 @@ def test_CollectionStatistics():
449
450
  assert stats.object_id == "69124"
450
451
 
451
452
 
453
+ def test_IndexProperties_hidden_details():
454
+ shards = {
455
+ "s1001": {
456
+ "trainingState": "ready",
457
+ "error": False,
458
+ "resolvedNLists": 4,
459
+ }
460
+ }
461
+ figures = {"memory": 4096}
462
+ properties = IndexProperties(
463
+ {
464
+ "id": "products/123",
465
+ "fields": ["embedding"],
466
+ "type": "vector",
467
+ "figures": figures,
468
+ "shards": shards,
469
+ }
470
+ )
471
+
472
+ assert properties.figures == figures
473
+ assert properties.shards == shards
474
+ assert properties.format()["figures"] == figures
475
+ assert properties.format()["shards"] == shards
476
+
477
+
452
478
  def test_AccessToken():
453
479
  data = {
454
480
  "active": True,
@@ -4,6 +4,7 @@ from arangoasync.auth import Auth
4
4
  from arangoasync.errno import USER_NOT_FOUND
5
5
  from arangoasync.exceptions import (
6
6
  CollectionCreateError,
7
+ CollectionListError,
7
8
  DocumentInsertError,
8
9
  PermissionResetError,
9
10
  PermissionUpdateError,
@@ -176,6 +177,14 @@ async def test_user_change_permissions(sys_db, arango_client, db):
176
177
  with pytest.raises(PermissionResetError):
177
178
  await db.reset_permission(username, db.name)
178
179
  await sys_db.reset_permission(username, db.name)
180
+ assert await sys_db.permission(username, db.name) == "none"
181
+ # ArangoDB 4.0 returns 403 where earlier versions returned 401.
182
+ with pytest.raises(CollectionCreateError) as err:
183
+ await db2.create_collection(generate_col_name())
184
+ assert err.value.http_code in {401, 403}
185
+ with pytest.raises(CollectionListError) as err:
186
+ await db2.collections()
187
+ assert err.value.http_code in {401, 403}
179
188
  with pytest.raises(DocumentInsertError):
180
189
  await col.insert({"_key": "test"})
181
190
 
@@ -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 build dependencies
23
- run: |
24
- python -m pip install --upgrade pip
25
- pip install build twine
26
-
27
- - name: Build package
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 --cluster --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__ = "1.2.4"
@@ -1,8 +0,0 @@
1
- {
2
- "tag": "1.2.4",
3
- "distance": 0,
4
- "node": "gd2c85b0dbb7f6071b7b8711c42d4d26898ffff1f",
5
- "dirty": false,
6
- "branch": "HEAD",
7
- "node_date": "2026-08-25"
8
- }