pyvastbase 0.2.2__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 (106) hide show
  1. pyvastbase-0.2.2/CLAUDE.md +111 -0
  2. pyvastbase-0.2.2/CONTEXT.md +79 -0
  3. pyvastbase-0.2.2/MANIFEST.in +22 -0
  4. pyvastbase-0.2.2/PKG-INFO +584 -0
  5. pyvastbase-0.2.2/README.md +550 -0
  6. pyvastbase-0.2.2/README_en.md +547 -0
  7. pyvastbase-0.2.2/__init__.py +364 -0
  8. pyvastbase-0.2.2/async_impl/__init__.py +159 -0
  9. pyvastbase-0.2.2/async_impl/collection.py +1367 -0
  10. pyvastbase-0.2.2/async_impl/connections.py +561 -0
  11. pyvastbase-0.2.2/async_impl/index_builder.py +299 -0
  12. pyvastbase-0.2.2/async_impl/search_builder.py +338 -0
  13. pyvastbase-0.2.2/async_impl/utility.py +814 -0
  14. pyvastbase-0.2.2/client.py +611 -0
  15. pyvastbase-0.2.2/collection.py +1053 -0
  16. pyvastbase-0.2.2/core/__init__.py +1 -0
  17. pyvastbase-0.2.2/core/collection_core.py +902 -0
  18. pyvastbase-0.2.2/core/connections.py +443 -0
  19. pyvastbase-0.2.2/core/constants.py +202 -0
  20. pyvastbase-0.2.2/core/exceptions.py +166 -0
  21. pyvastbase-0.2.2/core/executor.py +115 -0
  22. pyvastbase-0.2.2/core/mutation_result.py +143 -0
  23. pyvastbase-0.2.2/core/schema.py +610 -0
  24. pyvastbase-0.2.2/core/search_result.py +138 -0
  25. pyvastbase-0.2.2/core/vector_types.py +224 -0
  26. pyvastbase-0.2.2/executor/__init__.py +1 -0
  27. pyvastbase-0.2.2/executor/async_impl.py +144 -0
  28. pyvastbase-0.2.2/executor/sync.py +119 -0
  29. pyvastbase-0.2.2/index/__init__.py +1 -0
  30. pyvastbase-0.2.2/index/index_builder.py +485 -0
  31. pyvastbase-0.2.2/operations/__init__.py +130 -0
  32. pyvastbase-0.2.2/operations/admin.py +256 -0
  33. pyvastbase-0.2.2/operations/ddl.py +75 -0
  34. pyvastbase-0.2.2/operations/delete.py +44 -0
  35. pyvastbase-0.2.2/operations/index.py +170 -0
  36. pyvastbase-0.2.2/operations/insert.py +131 -0
  37. pyvastbase-0.2.2/operations/query.py +94 -0
  38. pyvastbase-0.2.2/operations/result.py +35 -0
  39. pyvastbase-0.2.2/operations/schema_reflect.py +106 -0
  40. pyvastbase-0.2.2/operations/search.py +40 -0
  41. pyvastbase-0.2.2/operations/search_result.py +54 -0
  42. pyvastbase-0.2.2/operations/upsert.py +34 -0
  43. pyvastbase-0.2.2/orm/__init__.py +66 -0
  44. pyvastbase-0.2.2/orm/base.py +711 -0
  45. pyvastbase-0.2.2/orm/fields.py +280 -0
  46. pyvastbase-0.2.2/pyproject.toml +89 -0
  47. pyvastbase-0.2.2/pyvastbase.egg-info/SOURCES.txt +153 -0
  48. pyvastbase-0.2.2/search/__init__.py +1 -0
  49. pyvastbase-0.2.2/search/search_builder.py +691 -0
  50. pyvastbase-0.2.2/setup.cfg +4 -0
  51. pyvastbase-0.2.2/test_conn.py +17 -0
  52. pyvastbase-0.2.2/tests/__init__.py +1 -0
  53. pyvastbase-0.2.2/tests/conftest.py +437 -0
  54. pyvastbase-0.2.2/tests/helpers.py +38 -0
  55. pyvastbase-0.2.2/tests/test_async.py +2020 -0
  56. pyvastbase-0.2.2/tests/test_async_alignment.py +94 -0
  57. pyvastbase-0.2.2/tests/test_async_executor.py +186 -0
  58. pyvastbase-0.2.2/tests/test_async_integration.py +415 -0
  59. pyvastbase-0.2.2/tests/test_async_with_executor.py +135 -0
  60. pyvastbase-0.2.2/tests/test_client_compat.py +244 -0
  61. pyvastbase-0.2.2/tests/test_collection.py +756 -0
  62. pyvastbase-0.2.2/tests/test_collection_adapter.py +87 -0
  63. pyvastbase-0.2.2/tests/test_collection_core.py +877 -0
  64. pyvastbase-0.2.2/tests/test_collection_integration.py +700 -0
  65. pyvastbase-0.2.2/tests/test_collection_properties.py +133 -0
  66. pyvastbase-0.2.2/tests/test_collection_signatures.py +166 -0
  67. pyvastbase-0.2.2/tests/test_connection_alignment.py +50 -0
  68. pyvastbase-0.2.2/tests/test_connection_provider.py +71 -0
  69. pyvastbase-0.2.2/tests/test_connections.py +391 -0
  70. pyvastbase-0.2.2/tests/test_constants.py +111 -0
  71. pyvastbase-0.2.2/tests/test_datatype_compat.py +45 -0
  72. pyvastbase-0.2.2/tests/test_datatype_intenum.py +96 -0
  73. pyvastbase-0.2.2/tests/test_datatype_mapping.py +109 -0
  74. pyvastbase-0.2.2/tests/test_exception_aliases.py +44 -0
  75. pyvastbase-0.2.2/tests/test_exceptions.py +232 -0
  76. pyvastbase-0.2.2/tests/test_executor.py +196 -0
  77. pyvastbase-0.2.2/tests/test_exports.py +79 -0
  78. pyvastbase-0.2.2/tests/test_hybrid_search.py +376 -0
  79. pyvastbase-0.2.2/tests/test_index_builder.py +303 -0
  80. pyvastbase-0.2.2/tests/test_integration.py +369 -0
  81. pyvastbase-0.2.2/tests/test_mutation_result.py +123 -0
  82. pyvastbase-0.2.2/tests/test_operations.py +177 -0
  83. pyvastbase-0.2.2/tests/test_operations_compat.py +145 -0
  84. pyvastbase-0.2.2/tests/test_orm.py +809 -0
  85. pyvastbase-0.2.2/tests/test_packaging.py +148 -0
  86. pyvastbase-0.2.2/tests/test_parameter_unification.py +84 -0
  87. pyvastbase-0.2.2/tests/test_return_type_rename.py +115 -0
  88. pyvastbase-0.2.2/tests/test_schema.py +496 -0
  89. pyvastbase-0.2.2/tests/test_schema_alignment.py +152 -0
  90. pyvastbase-0.2.2/tests/test_search_builder.py +471 -0
  91. pyvastbase-0.2.2/tests/test_type_alignment.py +70 -0
  92. pyvastbase-0.2.2/tests/test_utility.py +395 -0
  93. pyvastbase-0.2.2/tests/test_utility_compat.py +304 -0
  94. pyvastbase-0.2.2/tests/test_utility_integration.py +422 -0
  95. pyvastbase-0.2.2/tests/test_utils.py +2476 -0
  96. pyvastbase-0.2.2/tests/test_vastbase_client.py +107 -0
  97. pyvastbase-0.2.2/tests/test_vector_types.py +136 -0
  98. pyvastbase-0.2.2/tests/test_with_executor.py +246 -0
  99. pyvastbase-0.2.2/utility.py +2677 -0
  100. pyvastbase-0.2.2/utils/__init__.py +163 -0
  101. pyvastbase-0.2.2/utils/distance_utils.py +531 -0
  102. pyvastbase-0.2.2/utils/filter_utils.py +333 -0
  103. pyvastbase-0.2.2/utils/index_utils.py +387 -0
  104. pyvastbase-0.2.2/utils/result_utils.py +435 -0
  105. pyvastbase-0.2.2/utils/sql_utils.py +230 -0
  106. pyvastbase-0.2.2/utils/vector_utils.py +708 -0
@@ -0,0 +1,111 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Language
6
+
7
+ 回复时请使用简体中文(Simplified Chinese)。
8
+
9
+ ## Project Overview
10
+
11
+ pyvastbase is a Python SDK for Vastbase V3 vector database — a PyMilvus-style API wrapping Vastbase (PostgreSQL fork with vector extensions). Single dependency: `psycopg[binary]`.
12
+
13
+ ## Commands
14
+
15
+ ```bash
16
+ # Install dev dependencies
17
+ pip install -e ".[dev]"
18
+
19
+ # Run all tests (unit; integration skipped without VASTBASE_HOST)
20
+ pytest
21
+
22
+ # Run integration tests (requires real Vastbase instance)
23
+ VASTBASE_HOST=192.168.253.128 VASTBASE_PORT=18000 VASTBASE_USER=zzj \
24
+ VASTBASE_PASSWORD=Aa123456 VASTBASE_DATABASE=milvus pytest -m integration
25
+
26
+ # Run a single test file
27
+ pytest tests/test_collection.py
28
+
29
+ # Run a single test function
30
+ pytest tests/test_collection.py::test_insert
31
+
32
+ # Run with coverage
33
+ pytest --cov=pyvastbase --cov-report=term-missing
34
+
35
+ # Format
36
+ black . --line-length 100
37
+ isort . --profile black
38
+
39
+ # Type check
40
+ mypy .
41
+ ```
42
+
43
+ ## Architecture
44
+
45
+ Two-layer design — every module has a synchronous implementation and a parallel `async_impl/` counterpart:
46
+
47
+ | Layer | Files | DB Driver |
48
+ |-------|-------|-----------|
49
+ | Sync | `core/`, `collection.py`, `utility.py`, `index/`, `search/`, `orm/` | psycopg 3 |
50
+ | Async | `async_impl/` (collection, connections, index_builder, search_builder, utility) | psycopg 3 async |
51
+
52
+ ### Core modules (`core/`)
53
+
54
+ - [constants.py](core/constants.py) — Enums for IndexType, DistanceType, QuantizerType; version tuples; default index/query params; vector operator mapping
55
+ - [connections.py](core/connections.py) — `ConnectionConfig` dataclass, `Connections` singleton (thread-safe alias-based connection registry), `VastbaseConnection` wrapper with optional connection pool and version caching
56
+ - [schema.py](core/schema.py) — `DataType` class (scalar + vector type constants including FLOAT16_VECTOR, INT8_VECTOR, SPARSE_FLOAT_VECTOR), `FieldSchema` dataclass, `CollectionSchema` that generates CREATE TABLE SQL
57
+ - [exceptions.py](core/exceptions.py) — 19 exception classes rooted at `VastbaseException` (18 concrete + 1 base), each carrying domain-specific attributes (e.g., `VectorDimensionError.expected/.actual`, `CollectionNotExistsError.collection_name`)
58
+ - [mutation_result.py](core/mutation_result.py) — `MutationResult` with typed fields (insert_count, upsert_count, delete_count, primary_keys) and `MutationResultWrapper` providing backward-compatible list-like access
59
+
60
+ ### Key files
61
+
62
+ - [collection.py](collection.py) (74KB) — Sync `Collection` class: full CRUD, insert/upsert/delete, vector/hybrid search, query/get, index lifecycle, pagination (`SearchIterator`, `QueryIterator`)
63
+ - [utility.py](utility.py) (73KB) — 50+ module-level functions: connection management, server info, user/DB/privilege management, collection lifecycle, flush/compact, search highlight, buffer inspection
64
+ - [client.py](client.py) — `VastbaseClient` (aliased as `MilvusClient`): pymilvus-compatible high-level entry point. 40+ implemented methods delegating to Collection/utility, plus ~30 NotSupportedError stubs for PG-incompatible features (partition, role, replica, etc.). New pymilvus compat methods: `hybrid_search`, `query_iterator`, `search_iterator`, `describe_index`, `describe_database`, `describe_user`, `update_password`, `list_aliases`, `describe_alias`, `alter_index_properties`, `drop_index_properties`, `alter_collection_properties`, `drop_collection_properties`, `add_collection_field`, `flush_all`, `get_flush_all_state`
65
+ - [operations/](operations/) — Pure SQL generation layer used by both sync and async paths. Each function returns `(sql, params)` tuple. Modules: admin (user/privilege/database SQL), ddl (drop/truncate/refresh/alter_table/add_column), index (drop/list/get/describe/alter_index), insert, delete, query, result, schema_reflect, search_result
66
+ - [orm/](orm/) — Django-style ORM: `Entity` base class, `Model` decorator, `Field`/`VectorField` descriptors, field validators. Generates `CollectionSchema` from decorated classes.
67
+
68
+ ### Supporting modules
69
+
70
+ - [index/index_builder.py](index/index_builder.py) — `IndexParams` with 3 factory methods (graph_index, hybrid_index, fulltext_index), `IndexBuilder` with matching fluent methods + convenience `create_vector_index`/`create_fulltext_index`
71
+ - [search/search_builder.py](search/search_builder.py) — `SearchParams`, `SearchResult`/`SearchResults`, `SearchQueryBuilder`, `FulltextSearchBuilder`
72
+ - [utils/](utils/) — Internal SQL generation, vector serialization, distance calculation, filter expression building, result parsing
73
+
74
+ ### Version detection & feature gating
75
+
76
+ Vastbase exposes version via `SELECT vb_version()`, which returns both a Build number and a patch level (e.g., `version:V3.0 (Build 9)` + `patch:1`). Feature gating for 3.0.9+ features checks **both** `build >= 9 AND patch_level >= 1`. Version is cached per connection (one query, reused). New vector types (int8vector, halfvector, sparsevector), BM25 highlight, and auto-quantization all gate on this dual check. See [core/connections.py:219](core/connections.py#L219) `require_version()`.
77
+
78
+ ### Test conventions
79
+
80
+ - Unit tests: `tests/test_*.py`, run with plain `pytest`
81
+ - Integration tests: marked `@pytest.mark.integration`, auto-skipped unless `VASTBASE_HOST` env var is set
82
+ - Fixtures in `tests/conftest.py` provide `vastbase_conn` (async) and `vastbase_sync_conn` (sync) connection fixtures that auto-cleanup
83
+ - `tests/conftest_integration.py` is alternative config using `VASTBASE_HOST/PORT/USER/PASSWORD/DATABASE` env vars
84
+ - Async test mode: `asyncio_mode = "auto"` in pyproject.toml
85
+
86
+ ### Module-level config
87
+
88
+ - `configure(**kwargs)` sets global defaults: `timeout`, `pool_size`, `max_overflow`, `default_connection`
89
+ - `get_config()` returns a copy of current settings
90
+
91
+ ### Code style
92
+
93
+ - Python >= 3.9, black (line-length=100), isort (black profile), mypy
94
+ - Type annotations on all public function signatures
95
+ - dataclass/NamedTuple for immutable data objects
96
+ - Sparse vectors use dict format: `{"indices": [0, 5, 100], "values": [0.5, 0.8, 0.3]}`
97
+ - Async module renamed to `async_impl` (avoids Python keyword collision)
98
+
99
+ ## Agent skills
100
+
101
+ ### Issue tracker
102
+
103
+ Issues live as local markdown files under `.scratch/<feature-slug>/`. See `docs/agents/issue-tracker.md`.
104
+
105
+ ### Triage labels
106
+
107
+ Default canonical labels: `needs-triage`, `needs-info`, `ready-for-agent`, `ready-for-human`, `wontfix`. See `docs/agents/triage-labels.md`.
108
+
109
+ ### Domain docs
110
+
111
+ Single-context layout: `CONTEXT.md` + `docs/adr/` at repo root. See `docs/agents/domain.md`.
@@ -0,0 +1,79 @@
1
+ # Domain Glossary
2
+
3
+ ## Collection
4
+
5
+ A named set of data organized by a schema. Maps to a PostgreSQL table. Composed of scalar fields and vector fields. Created, queried, and mutated via the `Collection` module.
6
+
7
+ ## DataType
8
+
9
+ An IntEnum holding the type of a field. Members carry both the Python-facing enum value and the PostgreSQL column type string via the `.pg_type` property. Example: `DataType.FLOAT_VECTOR` (value=101) maps to `floatvector`. The IntEnum design supports pymilvus-compatible `if dtype == DataType.INT64` comparisons while retaining PG type mapping for DDL generation. Aliases exist for backward compatibility (`DataType.INT64 == DataType.INT64`).
10
+
11
+ ## MetricType
12
+
13
+ An alias for `DistanceType`. Used in pymilvus-style API: `MetricType.L2`, `MetricType.COSINE`, `MetricType.IP`. Delegates directly to the corresponding `DistanceType` enum values.
14
+
15
+ ## Vector Type
16
+
17
+ A data type that holds multi-dimensional numerical data for similarity search. Four registered types: `floatvector` (4-byte float), `int8vector` (1-byte signed int), `halfvector` (2-byte fp16), `sparsevector` (sparse float). Each type carries metadata: dimension range, distance operators, index operator classes, SQL literal format, minimum Vastbase version. All type metadata is registered in a `VectorTypeRegistry` — the single source of truth queried by schema validation, SQL generation, and version gating.
18
+
19
+ ## Index
20
+
21
+ A database-side structure that accelerates vector similarity search. Types include: `graph_index` (HNSW), `hybridann` (vector-scalar hybrid), `ivfflat`, `ivfpq`, `diskann`, `fulltext` (BM25). Each index type has its own dimension limits and configuration parameters. Note: `GRAPH_INDEX` is the SQL-level operator class name for HNSW indexes in Vastbase; `IndexType.HNSW` is the pymilvus-compatible alias. Both `GRAPH_INDEX` and `HNSW` refer to the same underlying HNSW implementation.
22
+
23
+ ## Distance Metric
24
+
25
+ The mathematical measure used to compare vector similarity: L2 (Euclidean `<->`), Cosine (`<=>`), IP (Inner Product `<#>`). Stored as metadata on each vector type entry.
26
+
27
+ ## Executor
28
+
29
+ An abstraction over the database driver that executes SQL and returns rows. The **sole seam** to the database — all SQL execution crosses this interface, not the underlying VastbaseConnection directly. Implementations: `SyncExecutor` (psycopg 3, returns `list[dict]`), `AsyncExecutor` (psycopg 3 async, returns `list[dict]`), `FakeExecutor` (sync in-memory test double), `FakeAsyncExecutor` (async in-memory test double). Utility functions access an Executor via `@with_executor` (sync) or `@async_with_executor` (async) decorators; Collection delegates to CollectionCore (sync) or uses `_executor.execute()` directly (async). Only two operations (`create_database`, `drop_database`) bypass this seam to toggle psycopg's autocommit mode — they receive both `_executor` and `_conn` from the decorator. AsyncCollection properties (`num_entities`, `index_params_async`) use `_executor.execute()` directly, not through CollectionCore (Core is sync-only). VastbaseConnection methods `execute/fetch_one/fetch_all` are private (`_execute/_fetch_one/_fetch_all`) — callers must cross the Executor seam. AsyncVastbaseConnection follows the same pattern.
30
+
31
+ ## Transaction
32
+
33
+ A unit of work that groups multiple SQL executions. Managed as a context manager by the `Executor`. On exit without commit, the transaction is rolled back automatically.
34
+
35
+ ## Adapter
36
+
37
+ A concrete module that satisfies an interface at a seam. In this codebase, `SyncCollection` and `AsyncCollection` are adapters — thin modules (~50 lines each) that provide connection management and an `Executor` implementation, delegating all business logic to `CollectionCore`.
38
+
39
+ ## Schema
40
+
41
+ The structural definition of a Collection: field names, data types, vector dimensions, primary keys, and nullability constraints. Represented by `CollectionSchema` (a list of `FieldSchema` objects). Generates `CREATE TABLE` SQL.
42
+
43
+ ## Entity
44
+
45
+ A single record in a Collection. Represented as a `dict[str, Any]` where keys are field names and values are typed data (scalars, vectors, or JSON). The ORM layer wraps entities in `Model`-decorated classes.
46
+
47
+ ## Mutation
48
+
49
+ A write operation that changes Collection data: insert, upsert, or delete. Returns a `MutationResult` carrying affected primary keys and counts.
50
+
51
+ ## hybrid_search (SDK-layer multi-way recall)
52
+
53
+ Performs multi-way vector recall with reranking across multiple `AnnSearchRequest` objects. Unlike pymilvus (where Milvus server executes multi-vector ANN + reranking in a single gRPC call), pyvastbase implements this at the SDK layer: issues multiple independent ANN search SQL queries (one per vector field), then merges results using a reranking strategy. Returns `SearchResult` — same type as single-field `search()`, with `distance` holding the merged score. Reranking strategies: `RRFRanker` (reciprocal rank fusion), `WeightedRRFRanker` (weighted RRF), `WeightedRanker` (weighted distance with arctan normalization per metric type). Execution model: parallel by default (asyncio.gather / thread pool), serial optional. Two distinct `hybrid_*` methods coexist with different semantics — `hybrid_search` (multi-vector recall + rerank) vs `hybrid_ann_search` (single-vector + scalar filtering via HybridANN index).
54
+
55
+ ## hybrid_ann_search (Vastbase-native vector + scalar filtering)
56
+
57
+ Single-vector-field ANN search with scalar field filtering, using Vastbase's HybridANN index. Not multi-way recall — queries one vector field and applies WHERE-style conditions on scalar fields. The Vastbase-native counterpart to pymilvus filtered search, not to pymilvus `hybrid_search`. Confirmed distinct from `hybrid_search` by database inspection: Vastbase V3.0 Build 9 has no native multi-way recall functions (no `rrf`, `fusion`, `rerank` functions registered in `pg_proc`).
58
+
59
+ ## VastbaseClient
60
+
61
+ High-level pymilvus `MilvusClient`-compatible entry point. Delegates all operations to existing `Collection` and `utility` module functions. Aliased as `MilvusClient` for import compatibility. Connects via `uri` (PostgreSQL connection string) or individual host/port parameters.
62
+
63
+ **Implemented methods** (delegating to Collection/utility with `using` parameter):
64
+ - Collection CRUD: `create_collection`, `drop_collection`, `has_collection`, `list_collections`, `describe_collection`, `rename_collection`, `truncate_collection`
65
+ - Data: `insert`, `upsert`, `delete`, `search`, `query`, `get`
66
+ - High-level query: `hybrid_search`, `query_iterator`, `search_iterator`
67
+ - Index: `create_index`, `drop_index`, `list_indexes`, `describe_index`, `alter_index_properties`, `drop_index_properties`
68
+ - Collection property: `alter_collection_properties`, `drop_collection_properties`, `add_collection_field`
69
+ - Alias: `create_alias`, `drop_alias`, `alter_alias`, `list_aliases`, `describe_alias`
70
+ - User/DB: `create_user`, `drop_user`, `reset_password`, `update_password`, `list_users`, `describe_user`, `create_database`, `drop_database`, `list_databases`, `describe_database`
71
+ - Flush/Load: `flush`, `flush_all`, `get_flush_all_state`, `compact`, `load_collection`, `release_collection`, `get_load_state`, `get_collection_stats`
72
+ - Server: `get_server_version`
73
+ - Connection: `close`
74
+
75
+ **NotSupportedError stubs** (PG architecture fundamentally different): partition, role, privilege_group, resource_group, replica, bulk_insert, snapshot, analyzer, optimize, collection_function, segments, compaction_plans
76
+
77
+ ## Connection Provider
78
+
79
+ A module that supplies database connections by alias. The `ConnectionProvider` protocol defines a single method `get_connection(alias) -> VastbaseConnection`. The default implementation (`VastbaseConnections`) holds a registry of named connection configurations. Consumers (Collection, utility functions) accept an optional `_connection_provider` parameter, defaulting to the global singleton instance. VastbaseConnection is an internal implementation detail of SyncExecutor/AsyncExecutor — callers should not use `_execute/_fetch_one/_fetch_all` directly; they cross the Executor seam instead.
@@ -0,0 +1,22 @@
1
+ include *.py
2
+ include *.md
3
+ include *.toml
4
+ include MANIFEST.in
5
+ graft core
6
+ graft utils
7
+ graft orm
8
+ graft index
9
+ graft search
10
+ graft async_impl
11
+ graft operations
12
+ graft tests
13
+ prune pyvastbase.egg-info
14
+ recursive-exclude pyvastbase.egg-info *
15
+ prune dist
16
+ prune .pytest_cache
17
+ prune .ruff_cache
18
+ prune .coverage
19
+ prune .claude
20
+ prune .scratch
21
+ global-exclude *.pyc
22
+ global-exclude __pycache__