-
Notifications
You must be signed in to change notification settings - Fork 110
Merge release-candidate/2025-10 #562
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## Problem Need to generate files off the updated spec ### Generated code: API updates - Admin API: Enhanced API keys and projects endpoints; added update operations - DB Control API: Updated index management with new read capacity support - DB Data API: Enhanced vector operations, namespace operations, and bulk operations - Inference API: Updated embedding and reranking models - OAuth API: Updated token request/response models ### Test updates - Made a few fixes in wrapper code to account for changes to generated names and shapes - Fixed integration tests for admin, control, and data operations - Updated unit tests for model changes - Fixed namespace-related tests - Updated index configuration tests
# Add Admin API Update Endpoints and Organization Resource
## Summary
This PR implements new update endpoints for the Admin API and adds a new
`OrganizationResource` class to expose organization management
functionality. The changes include:
1. **API Key Updates**: Added `update()` method to `ApiKeyResource` to
support updating API key names and roles
2. **Organization Resource**: Created a new `OrganizationResource` class
attached to the Admin class with full CRUD operations (list, fetch, get,
describe, update)
3. **Integration**: Exposed `OrganizationResource` in the `Admin` class
via `organization` and `organizations` properties
4. **Testing**: Added comprehensive integration tests for all new
functionality
## Changes
### 1. API Key Resource Updates
**File**: `pinecone/admin/resources/api_key.py`
- Added `update()` method to `ApiKeyResource` class
- Supports updating API key `name` and `roles`
- Includes RST-formatted docstrings with examples
- Follows existing patterns from other resource classes
**Example Usage**:
```python
from pinecone import Admin
# When initializing, the Admin class reads creds from PINECONE_CLIENT_ID
and PINECONE_CLIENT_SECRET environment variables
admin = Admin()
# Update API key name
api_key = admin.api_key.update(
api_key_id='my-api-key-id',
name='updated-api-key-name'
)
# Update API key roles
api_key = admin.api_key.update(
api_key_id='my-api-key-id',
roles=['ProjectViewer']
)
```
### 2. Organization Resource
**File**: `pinecone/admin/resources/organization.py` (new file)
Created a new `OrganizationResource` class with the following methods:
- `list()`: List all organizations associated with the account
- `fetch(organization_id)`: Fetch an organization by ID
- `get(organization_id)`: Alias for `fetch()`
- `describe(organization_id)`: Alias for `fetch()`
- `update(organization_id, name)`: Update an organization's name
**Example Usage**:
```python
from pinecone import Admin
admin = Admin()
# List all organizations
organizations = admin.organization.list()
for org in organizations.data:
print(org.name)
# Fetch an organization
org = admin.organization.get(organization_id="my-org-id")
# Update an organization
org = admin.organization.update(
organization_id="my-org-id",
name="updated-name"
)
```
### 3. Integration Tests
**File**: `tests/integration/admin/test_api_key.py`
- Added `test_update_api_key()` test covering:
- Updating API key name only
- Updating API key roles only
- Updating both name and roles
- Verifying changes persist after fetch
- Proper cleanup of created resources
**File**: `tests/integration/admin/test_organization.py` (new file)
Added comprehensive integration tests:
- `test_update_organization()`: Tests updating organization name with
proper cleanup (reverts name changes)
- `test_list_organizations()`: Tests listing organizations, verifies
response structure, field types, and dictionary/get-style access
- `test_fetch_organization()`: Tests fetching an organization by ID,
verifies all fields match list results
- `test_fetch_aliases()`: Tests that `fetch()`, `get()`, and
`describe()` return identical results
All tests include proper error handling and cleanup to avoid resource
waste.
## Implementation Details
- All methods follow existing patterns from `ProjectResource` and
`ApiKeyResource`
- Uses `@require_kwargs` decorator for parameter validation
- Error handling follows existing patterns
- Tests verify both attribute access and dictionary-style access for
compatibility
## Backward Compatibility
✅ All changes are backward compatible. No existing functionality is
modified or removed.
## Related
- Implements update endpoints found in `pinecone/core/openapi/admin/`
(generated OpenAPI code)
- Follows workspace rules for RST docstrings and integration testing
## Problem The Pinecone Python client is currently using protobuf version `^5.29`, which includes vulnerable versions that are affected by [GHSA-8qvm-5x2c-j2w7](GHSA-8qvm-5x2c-j2w7). This vulnerability involves uncontrolled recursion in Protobuf's pure-Python backend, which could lead to Denial of Service (DoS) attacks. ## Solution Updated the protobuf dependency constraint from `^5.29` to `^5.29.5` to ensure we're using the patched version that addresses this security vulnerability. The changes include: - Updated `pyproject.toml`: Changed protobuf version constraint from `^5.29` to `^5.29.5` - Updated `testing-dependency-grpc.yaml`: Updated protobuf version from `5.29.1` to `5.29.5` in all three dependency testing matrix configurations - Verified that `poetry.lock` already contains protobuf 5.29.5, so no additional lock file updates were needed This is a patch version update, so no breaking changes are expected. The protobuf dependency is optional and only installed when the `grpc` extra is requested. **Note:** This is a security patch release to address the immediate vulnerability for existing users. A future release will include a comprehensive update to protobuf 6.x, which may include breaking changes and will require more extensive testing and migration planning. ## Type of Change - [X] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) - [ ] This change requires a documentation update - [ ] Infrastructure change (CI configs, etc) - [ ] Non-code change (docs, etc) - [ ] None of the above: (explain here) ## Test Plan - Verified protobuf 5.29.5 is already installed and working - Updated CI/CD pipeline to test with the new version - No breaking changes expected as this is a patch version update
…ess Indexes (#528) # Add Support for Read Capacity and Metadata Schema Configuration for Serverless Indexes ## Summary This PR adds support for configuring `read_capacity` and `schema` (metadata schema) for serverless indexes in the Pinecone Python client. These features allow users to: - Configure dedicated read capacity nodes for better performance and cost predictability - Limit metadata indexing to specific fields for improved performance - Configure these settings both at index creation and after creation (for `read_capacity`) ## Features Added ### 1. Read Capacity Configuration Serverless indexes can now be configured with either **OnDemand** (default) or **Dedicated** read capacity modes. Dedicated mode allocates dedicated read nodes for your workload, providing more predictable performance and costs. ### 2. Metadata Schema Configuration Users can now specify which metadata fields are filterable, limiting metadata indexing to only the fields needed for query filtering. This improves index building and query performance when dealing with large amounts of metadata. ## Code Examples ### Creating a Serverless Index with Dedicated Read Capacity ```python from pinecone import Pinecone, ServerlessSpec, CloudProvider, GcpRegion, Metric pc = Pinecone(api_key='YOUR_API_KEY') # Create an index with dedicated read capacity pc.create_index( name='my-index', dimension=1536, metric=Metric.COSINE, spec=ServerlessSpec( cloud=CloudProvider.GCP, region=GcpRegion.US_CENTRAL1, read_capacity={ "mode": "Dedicated", "dedicated": { "node_type": "t1", "scaling": "Manual", "manual": { "shards": 2, "replicas": 2 } } } ) ) ``` ### Creating a Serverless Index with Metadata Schema ```python from pinecone import Pinecone, ServerlessSpec, CloudProvider, AwsRegion, Metric pc = Pinecone(api_key='YOUR_API_KEY') # Create an index with metadata schema configuration pc.create_index( name='my-index', dimension=1536, metric=Metric.COSINE, spec=ServerlessSpec( cloud=CloudProvider.AWS, region=AwsRegion.US_WEST_2, schema={ "genre": {"filterable": True}, "year": {"filterable": True}, "description": {"filterable": True} } ) ) ``` ### Creating an Index for Model with Read Capacity and Schema ```python from pinecone import Pinecone, CloudProvider, AwsRegion, EmbedModel pc = Pinecone(api_key='YOUR_API_KEY') # Create an index for a model with dedicated read capacity and schema pc.create_index_for_model( name='my-index', cloud=CloudProvider.AWS, region=AwsRegion.US_EAST_1, embed={ "model": EmbedModel.Multilingual_E5_Large, "field_map": {"text": "my-sample-text"} }, read_capacity={ "mode": "Dedicated", "dedicated": { "node_type": "t1", "scaling": "Manual", "manual": {"shards": 1, "replicas": 1} } }, schema={ "category": {"filterable": True}, "tags": {"filterable": True} } ) ``` ### Configuring Read Capacity on an Existing Index ```python from pinecone import Pinecone pc = Pinecone(api_key='YOUR_API_KEY') # Switch to OnDemand read capacity pc.configure_index( name='my-index', read_capacity={"mode": "OnDemand"} ) # Switch to Dedicated read capacity with manual scaling pc.configure_index( name='my-index', read_capacity={ "mode": "Dedicated", "dedicated": { "node_type": "t1", "scaling": "Manual", "manual": { "shards": 3, "replicas": 2 } } } ) # Scale up by increasing shards and replicas pc.configure_index( name='my-index', read_capacity={ "mode": "Dedicated", "dedicated": { "node_type": "t1", "scaling": "Manual", "manual": { "shards": 4, "replicas": 3 } } } ) # Verify the configuration was applied desc = pc.describe_index("my-index") assert desc.spec.serverless.read_capacity.mode == "Dedicated" ``` ### Async Examples All functionality is also available in the async client: ```python import asyncio from pinecone import PineconeAsyncio, ServerlessSpec, CloudProvider, AwsRegion, Metric async def main(): async with PineconeAsyncio(api_key='YOUR_API_KEY') as pc: # Create index with dedicated read capacity await pc.create_index( name='my-index', dimension=1536, metric=Metric.COSINE, spec=ServerlessSpec( cloud=CloudProvider.AWS, region=AwsRegion.US_EAST_1, read_capacity={ "mode": "Dedicated", "dedicated": { "node_type": "t1", "scaling": "Manual", "manual": {"shards": 2, "replicas": 2} } } ) ) # Configure read capacity later await pc.configure_index( name='my-index', read_capacity={ "mode": "Dedicated", "dedicated": { "node_type": "t1", "scaling": "Manual", "manual": {"shards": 3, "replicas": 2} } } ) asyncio.run(main()) ``` ## Type Safety Improvements This PR also improves type hints throughout the codebase by replacing `Any` types with specific TypedDict and OpenAPI model types for better IDE support and type checking. The following types are now exported from the top-level package: - `ReadCapacityDict` - `ReadCapacityOnDemandDict` - `ReadCapacityDedicatedDict` - `ReadCapacityDedicatedConfigDict` - `ScalingConfigManualDict` - `MetadataSchemaFieldConfig` ## Changes ### Core Functionality - Added `read_capacity` and `schema` parameters to `ServerlessSpec` class - Extended `create_index` to support `read_capacity` and `schema` via `ServerlessSpec` - Extended `create_index_for_model` to support `read_capacity` and `schema` - Extended `configure_index` to support `read_capacity` for serverless indexes - Added helper methods `__parse_read_capacity` and `__parse_schema` in request factory - Improved type hints throughout the codebase (replacing `Any` with specific types) ### Documentation - Updated `create_index` docstrings in both sync and async interfaces - Updated `create_index_for_model` docstrings in both sync and async interfaces - Updated `configure_index` docstrings in both sync and async interfaces - Added comprehensive examples in `docs/db_control/serverless-indexes.md` - Added code examples showing how to configure read capacity ### Testing - Added integration tests for `create_index` with `read_capacity` and `schema` - Added integration tests for `create_index_for_model` with `read_capacity` and `schema` - Added integration tests for `configure_index` with `read_capacity` - Tests cover both sync and async clients - Tests cover edge cases including transitions between read capacity modes ## Breaking Changes None. All changes are additive and backward compatible.
# Implement `fetch_by_metadata` for Index and IndexAsyncio
This PR adds the `fetch_by_metadata` method to both synchronous and
asynchronous Pinecone index clients, allowing users to retrieve vectors
based on metadata filters rather than requiring explicit vector IDs.
## Overview
The `fetch_by_metadata` operation enables querying vectors by their
metadata attributes, similar to how `query` works but without requiring
a query vector. This is particularly useful for:
- Retrieving all vectors matching specific metadata criteria
- Building data pipelines that filter by metadata
- Implementing metadata-based data retrieval workflows
## Usage Examples
### Basic Usage (Synchronous)
```python
from pinecone import Pinecone
pc = Pinecone(api_key='your-api-key')
index = pc.Index(host='your-index-host')
# Fetch vectors with simple metadata filter
result = index.fetch_by_metadata(
filter={"genre": "action"},
namespace="movies"
)
# Iterate over results
for vec_id, vector in result.vectors.items():
print(f"ID: {vector.id}, Metadata: {vector.metadata}")
```
### Complex Filtering
```python
# Using multiple filter conditions
result = index.fetch_by_metadata(
filter={
"genre": {"$in": ["comedy", "drama"]},
"year": {"$gte": 2020},
"rating": {"$gt": 7.5}
},
namespace="movies",
limit=100
)
```
### Pagination
```python
# First page
result = index.fetch_by_metadata(
filter={"status": "active"},
namespace="products",
limit=50
)
# Continue to next page if available
if result.pagination and result.pagination.next:
next_page = index.fetch_by_metadata(
filter={"status": "active"},
namespace="products",
limit=50,
pagination_token=result.pagination.next
)
```
### Asynchronous Usage
```python
import asyncio
from pinecone import Pinecone
async def main():
pc = Pinecone(api_key='your-api-key')
async with pc.IndexAsyncio(host='your-index-host') as index:
result = await index.fetch_by_metadata(
filter={"category": "electronics", "in_stock": True},
namespace="inventory",
limit=100
)
for vec_id, vector in result.vectors.items():
print(f"Product {vector.id}: {vector.metadata}")
asyncio.run(main())
```
### gRPC Usage
```python
from pinecone.grpc import PineconeGRPC
pc = PineconeGRPC(api_key='your-api-key')
index = pc.Index(host='your-index-host')
# Synchronous gRPC call
result = index.fetch_by_metadata(
filter={"tag": "featured"},
namespace="articles"
)
# Asynchronous gRPC call (returns future)
future = index.fetch_by_metadata(
filter={"tag": "featured"},
namespace="articles",
async_req=True
)
# Wait for result
result = future.result()
```
### Filter Operators
The `fetch_by_metadata` method supports all standard Pinecone metadata
filter operators:
```python
# Equality
filter={"status": "active"}
# Comparison operators
filter={"price": {"$gt": 100}}
filter={"age": {"$gte": 18}}
filter={"score": {"$lt": 0.5}}
filter={"count": {"$lte": 10}}
# Array operators
filter={"tags": {"$in": ["red", "blue", "green"]}}
filter={"categories": {"$nin": ["deprecated"]}}
# Existence check
filter={"description": {"$exists": True}}
# Logical operators
filter={
"$and": [
{"status": "active"},
{"price": {"$lt": 50}}
]
}
filter={
"$or": [
{"category": "electronics"},
{"category": "computers"}
]
}
```
## Response Structure
The method returns a `FetchByMetadataResponse` object containing:
```python
class FetchByMetadataResponse:
namespace: str # The namespace queried
vectors: Dict[str, Vector] # Dictionary of vector ID to Vector objects
usage: Usage # API usage information
pagination: Optional[Pagination] # Pagination token for next page (if available)
```
## Technical Changes
### Core Implementation
- Added `fetch_by_metadata` method to `Index` (sync) and `_IndexAsyncio`
(async) classes
- Added `fetch_by_metadata` method to `GRPCIndex` with support for
`async_req`
- Created `FetchByMetadataResponse` dataclass with pagination support
- Added request factory method
`IndexRequestFactory.fetch_by_metadata_request`
- Added gRPC response parser `parse_fetch_by_metadata_response`
### Protobuf Migration
- Migrated from `db_data_2025_04` protobuf stubs to `db_data_2025_10`
stubs
- Updated all gRPC-related imports and references
- Removed deprecated 2025-04 stub files
### Testing
- Added comprehensive integration tests for sync
(`test_fetch_by_metadata.py`)
- Added comprehensive integration tests for async
(`test_fetch_by_metadata.py`)
- Added gRPC futures tests (`test_fetch_by_metadata_future.py`)
- Added unit tests for request factory (`test_request_factory.py`)
- Added unit tests for Index class (`test_index.py`)
- Updated all unit test files to use 2025-10 protobuf stubs
### Documentation
- Added usage examples to `docs/db_data/index-usage-byov.md`
- Updated interface docstrings with examples
## Breaking Changes
None. This is a new feature addition.
## Migration Notes
No migration required. This is a new feature that doesn't affect
existing functionality.
# Add support for `match_terms` parameter in search operations
## Summary
This PR adds support for the `match_terms` parameter in the `search` and
`search_records` methods for both `Pinecone` and `PineconeAsyncio`
clients. The `match_terms` feature allows users to specify which terms
must be present in the text of each search hit based on a specified
strategy.
## Changes
### Core Implementation
- **Type Definitions**
(`pinecone/db_data/types/search_query_typed_dict.py`):
- Added `match_terms` field to `SearchQueryTypedDict` with comprehensive
docstring including limitations
- **Dataclass** (`pinecone/db_data/dataclasses/search_query.py`):
- Added `match_terms: Optional[Dict[str, Any]]` field to `SearchQuery`
dataclass
- Updated `as_dict()` method to include `match_terms` when present
- **Request Factory** (`pinecone/db_data/request_factory.py`):
- Updated `_parse_search_query()` to convert `match_terms` dictionary to
`SearchMatchTerms` OpenAPI model
- Added proper type conversion to ensure API compatibility
- **Interfaces**:
- Updated `IndexInterface.search()` and
`IndexInterface.search_records()` docstrings in
`pinecone/db_data/interfaces.py`
- Updated `IndexAsyncioInterface.search()` and
`IndexAsyncioInterface.search_records()` docstrings in
`pinecone/db_data/index_asyncio_interface.py`
- Added documentation explaining `match_terms` usage and limitations
### Testing
Added integration tests for both synchronous and asynchronous clients:
- `tests/integration/data/test_search_and_upsert_records.py`:
- `test_search_with_match_terms_dict`: Tests `match_terms` using
dictionary input
- `test_search_with_match_terms_searchquery`: Tests `match_terms` using
`SearchQuery` dataclass
- `tests/integration/data_asyncio/test_search_and_upsert_records.py`:
- `test_search_with_match_terms_dict`: Async version with dictionary
input
- `test_search_with_match_terms_searchquery`: Async version with
`SearchQuery` dataclass
All tests handle the expected API limitation where `match_terms` is only
supported for specific model configurations.
## Usage
Users can now pass `match_terms` in their search queries:
```python
from pinecone import Pinecone
pc = Pinecone()
index = pc.Index("my-index")
# Using dictionary
query = {
"inputs": {"text": "Apple corporation"},
"top_k": 3,
"match_terms": {"strategy": "all", "terms": ["Apple", "corporation"]}
}
results = index.search(namespace="my-namespace", query=query)
# Using SearchQuery dataclass
from pinecone.db_data.dataclasses.search_query import SearchQuery
query = SearchQuery(
inputs={"text": "Apple corporation"},
top_k=3,
match_terms={"strategy": "all", "terms": ["Apple", "corporation"]}
)
results = index.search(namespace="my-namespace", query=query)
```
## Limitations
**Important:** `match_terms` is only supported for sparse indexes with
integrated embedding configured to use the `pinecone-sparse-english-v0`
model. This limitation is documented in all relevant docstrings and
interface methods.
The implementation gracefully handles API errors when `match_terms` is
used with unsupported models, ensuring the parameter is correctly passed
to the API even when the model configuration doesn't support it.
## API Compatibility
This implementation follows the OpenAPI specification in
`pinecone/core/openapi/db_data/model/search_records_request_query.py`,
which defines `match_terms` as part of `SearchRecordsRequestQuery` (used
by `search` and `search_records` methods). Note that `match_terms` is
not available for the `query` method, which uses `QueryRequest`.
## Testing
- ✅ All integration tests pass for both sync and async clients
- ✅ Tests verify correct parameter passing and error handling
- ✅ Linter checks pass with no errors
- ✅ Type hints verified with mypy
# Add FilterBuilder for Metadata Filter Construction
## Summary
Introduces a `FilterBuilder` class that provides a fluent, type-safe API
for constructing Pinecone metadata filters. This helps prevent common
filter construction errors such as misspelled operator names or invalid
filter structures.
## Changes
### New Features
- **FilterBuilder class** (`pinecone/db_data/filter_builder.py`):
- Fluent builder API for all Pinecone filter operators (`eq`, `ne`,
`gt`, `gte`, `lt`, `lte`, `in_`, `nin`, `exists`)
- Operator overloading: `&` for AND, `|` for OR
- Supports nested logical combinations
- Full type hints (no `Any` types)
- RST-formatted docstrings with examples
- **Updated filter types** (`pinecone/db_data/types/query_filter.py`):
- Added `$or` support (`OrFilter`)
- Added `$exists` support (`ExistsFilter`)
- Updated `FilterTypedDict` to include both
- **Package exports**:
- `FilterBuilder` exported from main `pinecone` package for easy access
- **Unit tests** (`tests/unit/data/test_filter_builder.py`):
- Coverage for all operators
- Operator overloading tests
- Complex nested filter tests
- Edge cases and error conditions
## Usage Examples
### Simple Filters
```python
from pinecone import FilterBuilder
# Simple equality
filter = FilterBuilder().eq("genre", "drama").build()
# Returns: {"genre": "drama"}
# Using operators
filter = FilterBuilder().gt("year", 2020).build()
# Returns: {"year": {"$gt": 2020}}
filter = FilterBuilder().in_("genre", ["comedy", "drama"]).build()
# Returns: {"genre": {"$in": ["comedy", "drama"]}}
```
### Complex Filters with Operator Overloading
```python
# Multiple conditions with AND using & operator
filter = (FilterBuilder().eq("genre", "drama") &
FilterBuilder().gt("year", 2020)).build()
# Returns: {"$and": [{"genre": "drama"}, {"year": {"$gt": 2020}}]}
# Multiple conditions with OR using | operator
filter = (FilterBuilder().eq("genre", "comedy") |
FilterBuilder().eq("genre", "drama")).build()
# Returns: {"$or": [{"genre": "comedy"}, {"genre": "drama"}]}
# Complex nested conditions
filter = ((FilterBuilder().eq("genre", "drama") &
FilterBuilder().gt("year", 2020)) |
(FilterBuilder().eq("genre", "comedy") &
FilterBuilder().lt("year", 2000))).build()
```
### Using with Query Methods
```python
from pinecone import FilterBuilder
# In query
index.query(
vector=embedding,
top_k=10,
filter=FilterBuilder().eq("genre", "drama").build()
)
# In fetch_by_metadata
filter = (FilterBuilder().in_("genre", ["comedy", "drama"]) &
FilterBuilder().eq("year", 2019)).build()
index.fetch_by_metadata(filter=filter, namespace='my_namespace')
```
## Benefits
1. **Type safety**: Prevents misspelled operator names (e.g., `$eq` vs
`$equals`)
2. **Structure validation**: Prevents invalid filter structures (e.g.,
multiple operators as siblings without `$and`/`$or`)
3. **Better ergonomics**: Operator overloading makes complex filters
more readable
4. **Consistency**: Method names match Pinecone API operators (`$in` →
`in_()`, `$nin` → `nin()`, etc.)
5. **Backward compatible**: Users can still use raw dicts; FilterBuilder
is optional
## Testing
- 40+ unit tests covering all operators, operator overloading, nested
filters, and edge cases
- All tests pass with comprehensive coverage of the FilterBuilder API
## Backward Compatibility
This change is fully backward compatible. Existing code using raw filter
dictionaries continues to work unchanged. FilterBuilder is an optional
helper that users can adopt at their own pace.
# Add `create_namespace` method to Index and IndexAsyncio
## Summary
This PR adds the `create_namespace` method to both synchronous and
asynchronous Index clients, as well as the GRPC implementation. The
method allows users to create namespaces in serverless indexes with
optional schema configuration.
## Changes
### REST API Implementation (Sync & Async)
- **Request Factory**
(`pinecone/db_data/resources/sync/namespace_request_factory.py`):
- Added `CreateNamespaceArgs` TypedDict
- Added `create_namespace_args` method with validation for namespace
name and optional schema handling
- **Resource Classes**:
- `NamespaceResource.create()` - Synchronous implementation
- `NamespaceResourceAsyncio.create()` - Asynchronous implementation
- Both methods accept `name` and optional `schema` (as dictionary)
parameters
- **Interface Definitions**:
- Added `create_namespace()` abstract method to `IndexInterface`
- Added `create_namespace()` abstract method to `IndexAsyncioInterface`
- Both include comprehensive RST docstrings with examples
- **Class Implementations**:
- `Index.create_namespace()` - Delegates to namespace resource
- `IndexAsyncio.create_namespace()` - Delegates to namespace resource
with async support
### GRPC Implementation
- **GRPCIndex** (`pinecone/grpc/index_grpc.py`):
- Added `create_namespace()` method with `async_req` support for GRPC
futures
- Handles schema conversion from dictionary to `MetadataSchema` proto
object
- Supports both synchronous and asynchronous (future-based) execution
### Testing
- **Unit Tests** (`tests/unit_grpc/test_grpc_index_namespace.py`):
- `test_create_namespace` - Basic functionality
- `test_create_namespace_with_timeout` - Timeout handling
- `test_create_namespace_with_schema` - Schema conversion validation
- **Integration Tests** (`tests/integration/data/test_namespace.py`):
- `test_create_namespace` - Successful namespace creation
- `test_create_namespace_duplicate` - Error handling for duplicate
namespaces
- **Integration Tests**
(`tests/integration/data_asyncio/test_namespace_asyncio.py`):
- `test_create_namespace` - Async successful namespace creation
- `test_create_namespace_duplicate` - Async error handling for duplicate
namespaces
- **GRPC Futures Integration Tests**
(`tests/integration/data_grpc_futures/test_namespace_future.py`):
- `test_create_namespace_future` - Creating namespace with
`async_req=True`
- `test_create_namespace_future_duplicate` - Error handling with futures
- `test_create_namespace_future_multiple` - Concurrent namespace
creation
## API Design
The `create_namespace` method signature is consistent across all
implementations:
```python
def create_namespace(
self,
name: str,
schema: Optional[Dict[str, Any]] = None,
**kwargs
) -> NamespaceDescription
```
- **Public API**: Uses `Optional[Dict[str, Any]]` for schema to avoid
exposing OpenAPI types
- **Schema Format**: Accepts a dictionary with `fields` key containing
field definitions
- **Returns**: `NamespaceDescription` object containing namespace
information
## Examples
### REST API (Synchronous)
```python
from pinecone import Pinecone
pc = Pinecone()
index = pc.Index(host="example-index.svc.pinecone.io")
# Create namespace without schema
namespace = index.create_namespace(name="my-namespace")
# Create namespace with schema
schema = {
"fields": {
"field1": {"filterable": True},
"field2": {"filterable": False}
}
}
namespace = index.create_namespace(name="my-namespace", schema=schema)
```
### REST API (Asynchronous)
```python
import asyncio
from pinecone import Pinecone
async def main():
pc = Pinecone()
async with pc.IndexAsyncio(host="example-index.svc.pinecone.io") as index:
namespace = await index.create_namespace(name="my-namespace")
print(f"Created namespace: {namespace.name}")
asyncio.run(main())
```
### GRPC (Synchronous)
```python
from pinecone.grpc import PineconeGRPC
pc = PineconeGRPC()
index = pc.Index(host="example-index.svc.pinecone.io")
namespace = index.create_namespace(name="my-namespace")
```
### GRPC (Asynchronous/Futures)
```python
from pinecone.grpc import PineconeGRPC
from concurrent.futures import as_completed
pc = PineconeGRPC()
index = pc.Index(host="example-index.svc.pinecone.io")
# Create namespace asynchronously
future = index.create_namespace(name="my-namespace", async_req=True)
namespace = future.result(timeout=30)
# Create multiple namespaces concurrently
futures = [
index.create_namespace(name=f"ns-{i}", async_req=True)
for i in range(3)
]
for future in as_completed(futures):
namespace = future.result()
print(f"Created: {namespace.name}")
```
## Type Hints
- Public-facing methods use `Optional[Dict[str, Any]]` for schema
parameter
- Internal resource methods handle conversion from dict to OpenAPI
models
- GRPC implementation converts dict to `MetadataSchema` proto object
## Error Handling
- Validates that namespace name is a non-empty string
- Raises `PineconeApiException` for REST API errors
- Raises `PineconeException` for GRPC errors
- Properly handles duplicate namespace creation attempts
## Documentation
All methods include comprehensive RST docstrings with:
- Parameter descriptions
- Return value descriptions
- Usage examples
- Links to relevant documentation
## Testing Status
✅ All unit tests passing
✅ All integration tests passing (REST sync/async)
✅ All GRPC futures integration tests passing
## Notes
- This operation is only supported for serverless indexes
- Namespaces must have unique names within an index
- Schema configuration is optional and can be added when creating the
namespace or later
# Update Pinecone Assistant Plugin to v3.0.0 ## Summary This PR updates the `pinecone-plugin-assistant` dependency from `^1.6.0` to `3.0.0`. ## Changes - Updated `pinecone-plugin-assistant` version constraint in `pyproject.toml` from `^1.6.0` to `3.0.0` - Updated `poetry.lock` to reflect the new dependency version and resolved sub-dependencies ## Breaking Changes None - This is a dependency version update only.
# Intelligent CI Test Selection for PRs ## Summary This PR implements intelligent test selection for pull requests, automatically determining which integration test suites to run based on changed files. This reduces CI time and costs by running only relevant tests while maintaining safety through fallback mechanisms. ## Problem Previously, all integration test suites ran on every PR regardless of what code changed. This resulted in: - Unnecessary CI execution time and costs - Slower feedback cycles for developers - Resource waste when only a small portion of the codebase changed ## Solution The implementation analyzes changed files in PRs and maps them to specific test suites. It includes: - **Automatic test selection**: Runs only test suites relevant to changed code paths - **Safety fallbacks**: Runs all tests when changes touch critical infrastructure or when analysis fails - **Manual override**: Option to force running all tests via workflow dispatch ## Changes ### 1. Test Suite Mapping Script (`.github/scripts/determine-test-suites.py`) - Analyzes git diff to identify changed files - Maps code paths to test suites: - `pinecone/db_control/` → control tests (serverless, resources/index, resources/collections, asyncio variants) - `pinecone/db_data/` → data tests (sync, asyncio, gRPC) - `pinecone/inference/` → inference tests (sync, asyncio) - `pinecone/admin/` → admin tests - `pinecone/grpc/` → gRPC-specific tests - Plugin-related files → plugin tests - Identifies critical paths that require full test suite: - `pinecone/config/`, `pinecone/core/`, `pinecone/openapi_support/` - `pinecone/utils/`, `pinecone/exceptions/` - Core interface files (`pinecone.py`, `pinecone_asyncio.py`, etc.) - Falls back to running all tests if: - Script execution fails - No files match any mapping - Critical paths are touched ### 2. Updated PR Workflow (`.github/workflows/on-pr.yaml`) - Added `determine-test-suites` job that runs before integration tests - Added `run_all_tests` input parameter for manual override via workflow dispatch - Passes selected test suites to integration test workflow - Includes error handling and validation ### 3. Updated Integration Test Workflow (`.github/workflows/testing-integration.yaml`) - Added optional inputs for each job type's test suites: - `rest_sync_suites_json` - `rest_asyncio_suites_json` - `grpc_sync_suites_json` - `admin_suites_json` - Filters test matrix based on provided suites - Skips jobs when their test suite array is empty - Maintains backward compatibility (runs all tests when inputs not provided) ## Usage ### Automatic (Default) On every PR, the workflow automatically: 1. Analyzes changed files 2. Determines relevant test suites 3. Runs only those test suites ### Manual Override To force running all tests on a PR: 1. Go to Actions → "Testing (PR)" workflow 2. Click "Run workflow" 3. Check "Run all integration tests regardless of changes" 4. Run the workflow ## Safety Features 1. **Critical path detection**: Changes to core infrastructure (config, utils, exceptions, etc.) trigger full test suite 2. **Fallback on failure**: If the analysis script fails, falls back to running all tests 3. **Empty result handling**: If no tests match, runs all tests as a safety measure 4. **Main branch unchanged**: Main branch workflows continue to run all tests ## Example Scenarios ### Scenario 1: Change only `pinecone/db_data/index.py` - **Runs**: `data`, `data_asyncio`, `data_grpc_futures` test suites - **Skips**: `control/*`, `inference/*`, `admin`, `plugins` test suites - **Result**: ~70% reduction in test execution ### Scenario 2: Change `pinecone/config/pinecone_config.py` - **Runs**: All test suites (critical path) - **Reason**: Configuration changes affect all functionality ### Scenario 3: Change `pinecone/inference/inference.py` - **Runs**: `inference/sync`, `inference/asyncio` test suites - **Skips**: Other test suites - **Result**: ~85% reduction in test execution ## Testing The implementation has been tested with: - ✅ YAML syntax validation - ✅ Python script syntax validation - ✅ Test suite mapping logic verification - ✅ Edge case handling (empty arrays, failures, etc.) ## Benefits - **Cost savings**: Reduce CI costs by running only relevant tests - **Faster feedback**: Developers get test results faster when only subset runs - **Better resource utilization**: CI runners are used more efficiently - **Maintainability**: Easy to update mappings as codebase evolves ## Backward Compatibility - Main branch workflows unchanged (still run all tests) - PR workflows backward compatible (can manually trigger full suite) - Existing test suite structure unchanged - No changes to test code itself ## Future Improvements Potential enhancements for future PRs: - Track test execution time savings - Add metrics/logging for test selection decisions - Fine-tune mappings based on actual usage patterns - Consider test dependencies (e.g., if A changes, also run B)
# Expose LSN Header Information in API Responses
## Overview
This PR implements exposure of LSN (Log Sequence Number) header
information from Pinecone API responses through a new `_response_info`
attribute on response objects. This enables faster test suite execution
by using LSN-based freshness checks instead of polling
`describe_index_stats()`.
## Motivation
Integration tests currently rely on polling `describe_index_stats()` to
verify data freshness, which is slow and inefficient. The Pinecone API
includes LSN headers in responses that can be used to determine data
freshness more efficiently:
- `x-pinecone-request-lsn`: Committed LSN from write operations (upsert,
delete)
- `x-pinecone-max-indexed-lsn`: Reconciled LSN from read operations
(query)
By extracting and exposing these headers, tests can use LSN-based
polling to reduce test execution time significantly. Testing so far
shows this will cut the time needed to run db data plane integration
times down by half or more.
## Changes
### Core Implementation
#### Response Info Module
- Created `pinecone/utils/response_info.py` with:
- `ResponseInfo` TypedDict for structured response metadata
- `extract_response_info()` function to extract and normalize raw
headers
- Fields: `raw_headers` (dictionary of all response headers normalized
to lowercase)
- Case-insensitive header matching
- LSN extraction is handled by test utilities (`lsn_utils`) rather than
in `ResponseInfo`
#### REST API Client Integration
- Updated `api_client.py` and `asyncio_api_client.py` to automatically
attach `_response_info` to db data plane response objects
- Always attaches `_response_info` to ensure `raw_headers` are always
available, even when LSN fields are not present
#### gRPC Integration
- Updated `grpc_runner.py` to capture initial metadata from gRPC calls
- Modified all parser functions in `grpc/utils.py` to accept optional
`initial_metadata` parameter
- Updated `index_grpc.py` to pass initial metadata to parser functions
- Updated `future.py` to extract initial metadata from gRPC futures
#### Response Dataclasses
- Created `QueryResponse` and `UpsertResponse` dataclasses in
`pinecone/db_data/dataclasses/`
- Added `_response_info` field to `FetchResponse`,
`FetchByMetadataResponse`, `QueryResponse`, and `UpsertResponse`
- All response dataclasses inherit from `DictLike` for dictionary-style
access
- `_response_info` is a required field (always present) with default
`{"raw_headers": {}}`
#### Index Classes
- Updated `index.py` and `index_asyncio.py` to:
- Convert OpenAPI responses to dataclasses with `_response_info`
attached
- Handle `async_req=True` with `ApplyResult` wrapper for proper
dataclass conversion
- Extract `_response_info` from `upsert_records()` responses
### Test Infrastructure
#### LSN Utilities
- Created `tests/integration/helpers/lsn_utils.py` with helper functions
for extracting LSN values
- Created compatibility shim `pinecone/utils/lsn_utils.py` (deprecated)
#### Polling Helpers
- Updated `poll_until_lsn_reconciled()` to use query operations for
LSN-based freshness checks
- Added `poll_until_lsn_reconciled_async()` for async tests
- Falls back to old polling methods when LSN not available
#### Integration Test Updates
- Updated multiple integration tests to use LSN-based polling:
- `test_query.py`, `test_upsert_dense.py`,
`test_search_and_upsert_records.py`
- `test_fetch.py`, `test_fetch_by_metadata.py`, `test_upsert_hybrid.py`
- `test_query_namespaces.py`, `seed.py`
- Async versions: `test_query.py` (async)
- Added assertions to verify `_response_info` is present when expected
### Documentation
- Created `docs/maintainers/lsn-headers-discovery.md` documenting
discovered headers
- Created `scripts/inspect_lsn_headers.py` for header discovery
## Usage Examples
### Accessing Response Info
The `_response_info` attribute is always available on all Index response
objects:
```python
from pinecone import Pinecone
pc = Pinecone(api_key="your-api-key")
index = pc.Index("my-index")
# Upsert operation - get committed LSN
upsert_response = index.upsert(
vectors=[("id1", [0.1, 0.2, 0.3]), ("id2", [0.4, 0.5, 0.6])]
)
# Access raw headers (always present, contains all response headers)
raw_headers = upsert_response._response_info.get("raw_headers")
print(f"Raw headers: {raw_headers}")
# Example output: Raw headers: {
# 'x-pinecone-request-lsn': '12345',
# 'x-pinecone-api-version': '2025-10',
# 'content-type': 'application/json',
# 'server': 'envoy',
# ...
# }
# Extract LSN from raw headers using test utilities (for testing/polling)
from tests.integration.helpers.lsn_utils import extract_lsn_committed
lsn_committed = extract_lsn_committed(raw_headers)
print(f"Committed LSN: {lsn_committed}")
# Example output: Committed LSN: 12345
# Query operation
query_response = index.query(
vector=[0.1, 0.2, 0.3],
top_k=10
)
# Access raw headers
raw_headers = query_response._response_info.get("raw_headers")
print(f"Raw headers: {raw_headers}")
# Example output: Raw headers: {
# 'x-pinecone-max-indexed-lsn': '12345',
# 'x-pinecone-api-version': '2025-10',
# 'content-type': 'application/json',
# ...
# }
# Extract LSN from raw headers using test utilities
from tests.integration.helpers.lsn_utils import extract_lsn_reconciled
lsn_reconciled = extract_lsn_reconciled(raw_headers)
print(f"Reconciled LSN: {lsn_reconciled}")
# Example output: Reconciled LSN: 12345
# Fetch operation - response info always available
fetch_response = index.fetch(ids=["id1", "id2"])
print(f"Response info: {fetch_response._response_info}")
# Example output:
# Response info: {
# 'raw_headers': {
# 'x-pinecone-max-indexed-lsn': '12345',
# 'x-pinecone-api-version': '2025-10',
# 'content-type': 'application/json',
# ...
# }
# }
```
### Dictionary-Style Access
All response dataclasses inherit from `DictLike`, enabling
dictionary-style access:
```python
query_response = index.query(vector=[...], top_k=10)
# Attribute access (existing)
matches = query_response.matches
# Dictionary-style access (new)
matches = query_response["matches"]
# Response info access
response_info = query_response._response_info
# Example: {'raw_headers': {'x-pinecone-max-indexed-lsn': '12345', 'x-pinecone-api-version': '2025-10', 'content-type': 'application/json', ...}}
```
## Technical Details
### Response Info Flow
1. **REST API**:
- HTTP headers → `api_client.py` extracts → attaches `_response_info` to
OpenAPI model → Index classes convert to dataclasses
2. **gRPC**:
- Initial metadata → `grpc_runner.py` captures → parser functions
extract → attach `_response_info` to response objects
### Backward Compatibility
- All existing method signatures remain unchanged
- `_response_info` is always present on response objects (required
field)
- `raw_headers` in `_response_info` always contains response headers
(may be empty dict if no headers)
- Test utilities (`poll_until_lsn_reconciled`,
`poll_until_lsn_reconciled_async`) accept `_response_info` directly and
extract LSN internally
- Response objects maintain all existing attributes and behavior
### Type Safety
- Added proper type hints for `_response_info` fields
- Updated return type annotations to reflect dataclass usage
- Added `type: ignore` comments where necessary (e.g., `ApplyResult`
wrapping)
### Dataclass Enhancements
- All response dataclasses now inherit from `DictLike` for
dictionary-style access
- `QueryResponse` and `UpsertResponse` are new dataclasses replacing
OpenAPI models
- `_response_info` field: `ResponseInfo = field(default_factory=lambda:
cast(ResponseInfo, {"raw_headers": {}}), repr=True, compare=False)`
- Always present (required field)
- `repr=True` for all response dataclasses to aid debugging
- `raw_headers` always contains response headers (may be empty dict)
- `ResponseInfo` only contains `raw_headers`
## Testing
### Unit Tests
- ✅ All gRPC upsert tests pass (32/32)
- ✅ All unit tests pass (340+ passed)
- ✅ Created unit tests for `extract_response_info()` function
- ✅ Created unit tests for LSN utility functions
### Integration Tests
- ✅ Updated integration tests to use LSN-based polling
- ✅ 38 integration tests pass
- ✅ LSN-based polling working correctly (faster test execution)
- ✅ `_response_info` assertions added to verify LSN data is present
## Breaking Changes
**None** - This is a backward-compatible enhancement.
### Response Type Changes
- `QueryResponse` and `UpsertResponse` are now dataclasses instead of
OpenAPI models
- **Impact**: Minimal - dataclasses are compatible for attribute access
and dictionary-style access (via `DictLike`)
- **Mitigation**: Public API exports remain the same (`from pinecone
import QueryResponse, UpsertResponse`)
- **Note**: If users were doing `isinstance()` checks against OpenAPI
models, they should still work when importing from `pinecone`
### New Attribute
- `_response_info` is added to all Index response objects
(`QueryResponse`, `UpsertResponse`, `FetchResponse`,
`FetchByMetadataResponse`)
- **Impact**: Minimal - it's a required attribute with underscore prefix
(indicates internal use)
- **Mitigation**: Underscore prefix indicates it's not part of the
public API contract
- **Note**: `_response_info` is always present and contains
`raw_headers`.
### Compatibility Notes
- All response dataclasses inherit from `DictLike`, enabling
dictionary-style access (`response['matches']`)
- Attribute access remains unchanged (`response.matches`,
`response.namespace`, etc.)
- OpenAPI-specific methods like `to_dict()` were not part of the public
API
## Related Issues
- Enables faster test suite execution through LSN-based polling
- Provides foundation for future LSN-based features
## Summary
This PR implements a custom pytest plugin for test sharding, allowing
tests to be automatically distributed across multiple CI jobs for
parallel execution. This replaces the previous manual directory-based
test splitting approach with a more flexible, hash-based distribution
system. Additionally, integration tests have been reorganized into
top-level folders that group tests by the client type and setup
requirements needed.
This should bring down the total CI runtime to ~8 minutes or less.
## Changes
### Core Implementation
- **New pytest plugin** (`tests/pytest_shard.py`):
- Implements `pytest_addoption` hook to add `--splits` and `--group`
command-line options
- Implements `pytest_collection_modifyitems` hook to filter tests based
on shard assignment
- Uses hash-based distribution (MD5 hash of test node ID) for
deterministic test assignment
- Supports environment variables `PYTEST_SPLITS` and `PYTEST_GROUP` as
alternatives to command-line options
- Includes validation for shard parameters with helpful error messages
- **Plugin registration** (`tests/conftest.py`):
- Registers the plugin globally so it's available for all test runs
- Plugin is automatically loaded when running pytest
### CI Workflow Updates
- **Updated `.github/workflows/testing-integration.yaml`**:
- Replaced manual directory-based test splitting with automatic sharding
- `rest_sync` tests: Now uses 8 shards (was manually split by directory)
- `rest_asyncio` tests: Now uses 5 shards (was manually split by
directory)
- `grpc` tests: No sharding (runs all tests in single job, including
`tests/integration/rest_sync/db/data` with `USE_GRPC='true'`)
- **Updated `.github/actions/run-integration-test/action.yaml`**:
- Added `pytest_splits` and `pytest_group` input parameters
- Updated test execution to pass sharding arguments when provided
### Test Reorganization
- **Integration tests reorganized by client type**
(`tests/integration/`):
- **`rest_sync/`**: Tests using the synchronous REST client
(`Pinecone()`)
- Uses standard `Index()` objects for database operations
- Supports optional GRPC mode via `USE_GRPC='true'` environment variable
- Contains subdirectories for `db/` (control and data operations),
`inference/`, and `admin/` tests
- **`rest_asyncio/`**: Tests using the asynchronous REST client
(`Pinecone().IndexAsyncio()`)
- Uses async fixtures and `IndexAsyncio()` objects
- Requires `pytest-asyncio` for async test execution
- Contains subdirectories for `db/` (control and data operations) and
`inference/` tests
- **`grpc/`**: Tests using the GRPC client (`PineconeGRPC()`)
- Uses `PineconeGRPC()` client and `GRPCIndex` objects
- Contains `db/data/` tests for GRPC-specific functionality
- This organization makes it clear which client type each test requires
and simplifies fixture setup
### Bug Fixes
- **Fixed race condition in test cleanup**
(`tests/integration/rest_sync/db/control/pod/conftest.py`):
- Added `NotFoundException` handling in `attempt_delete_index` function
- Prevents teardown errors when index is deleted between `has_index`
check and `describe_index` call
### Testing
- **Unit tests** (`tests/unit/test_pytest_shard.py`):
- Tests for hash-based distribution logic
- Tests for validation and error handling
- Tests for deterministic shard assignment
- Tests for edge cases (single shard, environment variables, etc.)
- Tests gracefully handle `testdir` limitations (plugin loading in
isolated environments)
### Documentation
- **Updated `docs/maintainers/testing-guide.md`**:
- Added "Test Sharding" section with usage examples
- Documented command-line options and environment variables
- Explained how sharding works and its use in CI
- Documented actual shard counts used in CI workflows
- Fixed broken link to `testing-integration.yaml`
## Benefits
1. **Automatic test distribution**: Tests are automatically distributed
across shards using a deterministic hash algorithm, eliminating the need
to manually maintain directory-based splits
2. **Better load balancing**: Hash-based distribution ensures more even
test distribution across shards compared to directory-based splitting
3. **Easier maintenance**: No need to manually update CI workflows when
test files are added, removed, or reorganized
4. **Flexibility**: Shard counts can be easily adjusted in CI workflows
without code changes
5. **Deterministic**: Same test always goes to the same shard, making
debugging easier
6. **Clear test organization**: Tests are grouped by client type, making
it immediately clear which setup and fixtures are needed for each test
7. **Simplified fixture management**: Each client type has its own
`conftest.py` with appropriate fixtures, reducing complexity and
potential conflicts
## Usage
### Command-line
```sh
pytest tests/integration/rest_sync --splits=8 --group=1
```
### Environment variables
```sh
export PYTEST_SPLITS=8
export PYTEST_GROUP=1
pytest tests/integration/rest_sync
```
## Testing
- Plugin works correctly in real pytest environment
- CI workflows updated and ready for use
## Notes
- The plugin is automatically available when running pytest (no
installation needed)
- Shard counts in CI can be adjusted based on test suite size and CI
capacity
# Update OpenAPI Models for Namespace
## Summary
This PR updates the codebase to align with the latest OpenAPI
specification changes for namespace-related models. The API
specification has been updated to:
- Add `total_count` field to `ListNamespacesResponse`
- Replace `total_count` field in `NamespaceDescription` with
`indexed_fields` field
The wrapper code has been updated to properly parse and populate these
new fields when using the gRPC client.
## Changes
### Code Generator Updates
- **Updated `codegen/apis` submodule** to latest commit
(`bbad89bd51d792534a9ba06a44ed1f2259f7f89f`)
- **Updated
`pinecone/core/openapi/db_data/model/list_namespaces_response.py`**:
- Added `total_count` (int) field to `ListNamespacesResponse`
- Field represents the total number of namespaces in the index matching
the prefix
- **Updated
`pinecone/core/openapi/db_data/model/namespace_description.py`**:
- Removed `total_count` field (moved to `ListNamespacesResponse`)
- Added `indexed_fields` field of type
`NamespaceDescriptionIndexedFields`
- Field contains a list of all indexed metadata fields in the namespace
- **Added new model
`pinecone/core/openapi/db_data/model/namespace_description_indexed_fields.py`**:
- New model class `NamespaceDescriptionIndexedFields` with `fields`
property (list of strings)
- Represents the indexed metadata fields for a namespace
- **Updated `pinecone/core/openapi/db_data/models/__init__.py`**:
- Added export for `NamespaceDescriptionIndexedFields`
- **Updated `pinecone/openapi_support/api_version.py`**:
- Updated API version SHA to reflect latest specification
### Wrapper Code Updates
- **Updated `pinecone/grpc/utils.py`**:
- **`parse_list_namespaces_response` function**:
- Now extracts `total_count` from gRPC response (`totalCount` in JSON)
- Extracts `indexedFields` for each namespace in the list
- Creates `NamespaceDescriptionIndexedFields` objects when present
- Includes both fields when constructing `ListNamespacesResponse`
- **`parse_namespace_description` function**:
- Now extracts `indexedFields` from gRPC response (if present)
- Creates `NamespaceDescriptionIndexedFields` object with the `fields`
array
- Includes `indexed_fields` when constructing `NamespaceDescription`
- **Added import** for `NamespaceDescriptionIndexedFields` model
## Technical Details
### Field Changes
1. **`ListNamespacesResponse.total_count`** (new):
- Type: `int`
- Optional: Yes
- Description: The total number of namespaces in the index matching the
prefix
- Source: Extracted from `totalCount` in gRPC JSON response
2. **`NamespaceDescription.indexed_fields`** (new):
- Type: `NamespaceDescriptionIndexedFields`
- Optional: Yes
- Description: A list of all indexed metadata fields in the namespace
- Source: Extracted from `indexedFields.fields` in gRPC JSON response
3. **`NamespaceDescription.total_count`** (removed):
- This field has been moved to `ListNamespacesResponse` where it is more
semantically appropriate
### Backward Compatibility
- All new fields are optional, so existing code will continue to work
- Existing tests should continue to pass as they only check required
fields
- The gRPC parsing functions handle missing fields gracefully by setting
them to `None`
## Testing
- Type checking with mypy passes for updated files
- Existing integration tests should continue to work (they only verify
required fields)
- The parsing functions handle optional fields correctly when they are
absent from responses
## Notes
- REST API clients will automatically receive these fields when the API
returns them (handled by OpenAPI models)
- gRPC clients now properly parse and populate these fields from
protobuf responses
- Both `total_count` and `indexed_fields` are optional fields, so
backward compatibility is maintained
# Migrate from Poetry to uv ## Summary This PR migrates the project from Poetry to [uv](https://docs.astral.sh/uv/), a fast Python package and project manager written in Rust. This migration improves CI/CD performance and provides a more modern dependency management experience while maintaining full compatibility with existing workflows. This change should shave about 90 seconds off our total CI runtime since the setup-poetry action being replaced took about 25 seconds longer to run each time. ## Changes ### Core Configuration - **`pyproject.toml`**: Converted from Poetry format to PEP 621 standard format - Converted `[tool.poetry]` to `[project]` - Moved dependencies to `[project.dependencies]` and `[project.optional-dependencies]` - Updated build system from `poetry-core` to `hatchling` - Converted Poetry groups (`dev`, `types`) and extras (`grpc`, `asyncio`) to uv's optional-dependencies format - Preserved all version constraints and Python version requirements - **`uv.lock`**: Generated new lock file (replaces `poetry.lock`) ### Makefile Updates All Poetry commands replaced with uv equivalents: - `poetry install -E grpc` → `uv sync --extra grpc` - `poetry run <command>` → `uv run <command>` - `poetry build` → `uv build` - `poetry publish` → `uv publish` - `poetry version` → custom script to read version from pyproject.toml ### CI/CD Updates - **New action**: `.github/actions/setup-uv/action.yml` - Uses `astral-sh/setup-uv@v4` for automatic caching - Supports `enable_cache` parameter (mapped to `save-cache`) to disable caching for dependency tests - Cache suffix includes extras configuration for proper cache isolation - **Updated workflows**: - `testing-unit.yaml` - Updated to use setup-uv action - `testing-integration.yaml` - Updated to use setup-uv action - `publish-to-pypi.yaml` - Updated version bumping logic (replaces `poetry version` with Python script) - `on-merge.yaml` - Updated package check to use `uv build` - **Updated composite actions**: - `run-integration-test/action.yaml` - Replaced `poetry run pytest` with `uv run pytest` - `build-docs/action.yml` - Updated to use setup-uv and `uv run sphinx-build` - `test-dependency-rest/action.yaml` - Updated to use `uv add` and `uv run pytest` - `test-dependency-grpc/action.yaml` - Updated to use `uv add` and `uv run pytest` - `test-dependency-asyncio-rest/action.yaml` - Updated to use `uv add` and `uv run pytest` ### Scripts - `codegen/build-oas.sh` - Replaced `poetry run ruff format` with `uv run ruff format` ### Documentation Updated all documentation to reflect uv usage: - `docs/maintainers/testing-guide.md` - All `poetry run` commands → `uv run` - `docs/maintainers/debugging.md` - Updated command examples - `MAINTAINERS.md` - Updated setup instructions and commands - `CONTRIBUTING.md` - Updated development workflow from Poetry to uv - `README.md` - Already had uv instructions, kept Poetry as alternative for users ## Benefits 1. **Performance**: uv is significantly faster than Poetry for dependency resolution and installation 2. **CI/CD improvements**: Faster CI runs due to uv's optimized caching and dependency resolution 3. **Modern tooling**: uv is actively maintained and provides a better developer experience 4. **Compatibility**: Full backward compatibility with existing workflows and functionality ## Migration Notes ### For Developers 1. **Install uv**: Follow instructions at https://docs.astral.sh/uv/ 2. **Install dependencies**: Run `uv sync --extra grpc --extra asyncio` (replaces `poetry install -E grpc -E asyncio`) 3. **Run commands**: Use `uv run <command>` instead of `poetry run <command>` 4. **REPL**: Use `uv run repl` instead of `poetry run repl` ### Command Equivalents | Poetry Command | uv Equivalent | |----------------|---------------| | `poetry install` | `uv sync` | | `poetry install -E grpc` | `uv sync --extra grpc` | | `poetry install --with types` | `uv sync --extra types` | | `poetry install --without dev` | `uv sync --no-group dev` (or omit `--extra dev`) | | `poetry run <cmd>` | `uv run <cmd>` | | `poetry add <pkg>` | `uv add <pkg>` | | `poetry build` | `uv build` | | `poetry publish` | `uv publish` | ## Testing - [x] Verified `uv sync` works with all extras - [x] Verified `uv run repl` works correctly - [x] Verified `make version` works - [x] Verified `make package` works - [x] Verified `uv run mypy pinecone` works - [x] Tested locally with all extras: `uv sync --extra grpc --extra asyncio --extra types` ## Breaking Changes None. All functionality is preserved, only the tooling has changed. ## Next Steps 1. Generate `uv.lock` by running `uv sync` locally (already done in this PR) 2. Test CI workflows in a branch to ensure everything works correctly 3. Update any team-specific documentation or scripts that reference Poetry ## Files Changed - `pyproject.toml` - Converted to uv format - `Makefile` - Updated all commands - `.github/actions/setup-uv/action.yml` - New action (replaces setup-poetry) - `.github/workflows/*.yaml` - Updated workflows - `.github/actions/*/action.yaml` - Updated composite actions - `codegen/build-oas.sh` - Updated script - Documentation files - Updated command examples # Migrate from Poetry to uv ## Summary This PR migrates the project from Poetry to [uv](https://docs.astral.sh/uv/), a fast Python package and project manager written in Rust. This migration improves CI/CD performance and provides a more modern dependency management experience while maintaining full compatibility with existing workflows. ## Changes ### Core Configuration - **`pyproject.toml`**: Converted from Poetry format to PEP 621 standard format - Converted `[tool.poetry]` to `[project]` - Moved dependencies to `[project.dependencies]` and `[project.optional-dependencies]` - Updated build system from `poetry-core` to `hatchling` - Converted Poetry groups (`dev`, `types`) and extras (`grpc`, `asyncio`) to uv's optional-dependencies format - Preserved all version constraints and Python version requirements - **`uv.lock`**: Generated new lock file (replaces `poetry.lock`) ### Makefile Updates All Poetry commands replaced with uv equivalents: - `poetry install -E grpc` → `uv sync --extra grpc` - `poetry run <command>` → `uv run <command>` - `poetry build` → `uv build` - `poetry publish` → `uv publish` - `poetry version` → custom script to read version from pyproject.toml ### CI/CD Updates - **New action**: `.github/actions/setup-uv/action.yml` - Uses `astral-sh/setup-uv@v4` for automatic caching - Supports `enable_cache` parameter (mapped to `save-cache`) to disable caching for dependency tests - Cache suffix includes extras configuration for proper cache isolation - **Updated workflows**: - `testing-unit.yaml` - Updated to use setup-uv action - `testing-integration.yaml` - Updated to use setup-uv action - `publish-to-pypi.yaml` - Updated version bumping logic (replaces `poetry version` with Python script) - `on-merge.yaml` - Updated package check to use `uv build` - **Updated composite actions**: - `run-integration-test/action.yaml` - Replaced `poetry run pytest` with `uv run pytest` - `build-docs/action.yml` - Updated to use setup-uv and `uv run sphinx-build` - `test-dependency-rest/action.yaml` - Updated to use `uv add` and `uv run pytest` - `test-dependency-grpc/action.yaml` - Updated to use `uv add` and `uv run pytest` - `test-dependency-asyncio-rest/action.yaml` - Updated to use `uv add` and `uv run pytest` ### Scripts - `codegen/build-oas.sh` - Replaced `poetry run ruff format` with `uv run ruff format` ### Documentation Updated all documentation to reflect uv usage: - `docs/maintainers/testing-guide.md` - All `poetry run` commands → `uv run` - `docs/maintainers/debugging.md` - Updated command examples - `MAINTAINERS.md` - Updated setup instructions and commands - `CONTRIBUTING.md` - Updated development workflow from Poetry to uv - `README.md` - Already had uv instructions, kept Poetry as alternative for users ## Benefits 1. **Performance**: uv is significantly faster than Poetry for dependency resolution and installation 2. **CI/CD improvements**: Faster CI runs due to uv's optimized caching and dependency resolution 3. **Modern tooling**: uv is actively maintained and provides a better developer experience 4. **Compatibility**: Full backward compatibility with existing workflows and functionality ## Migration Notes ### For Developers 1. **Install uv**: Follow instructions at https://docs.astral.sh/uv/ 2. **Install dependencies**: Run `uv sync --extra grpc --extra asyncio` (replaces `poetry install -E grpc -E asyncio`) 3. **Run commands**: Use `uv run <command>` instead of `poetry run <command>` 4. **REPL**: Use `uv run repl` instead of `poetry run repl` ### Command Equivalents | Poetry Command | uv Equivalent | |----------------|---------------| | `poetry install` | `uv sync` | | `poetry install -E grpc` | `uv sync --extra grpc` | | `poetry install --with types` | `uv sync --extra types` | | `poetry install --without dev` | `uv sync --no-group dev` (or omit `--extra dev`) | | `poetry run <cmd>` | `uv run <cmd>` | | `poetry add <pkg>` | `uv add <pkg>` | | `poetry build` | `uv build` | | `poetry publish` | `uv publish` | ## Testing - [x] Verified `uv sync` works with all extras - [x] Verified `uv run repl` works correctly - [x] Verified `make version` works - [x] Verified `make package` works - [x] Verified `uv run mypy pinecone` works - [x] Tested locally with all extras: `uv sync --extra grpc --extra asyncio --extra types` ## Breaking Changes None. All functionality is preserved, only the tooling has changed. ## Next Steps 1. Generate `uv.lock` by running `uv sync` locally (already done in this PR) 2. Test CI workflows in a branch to ensure everything works correctly 3. Update any team-specific documentation or scripts that reference Poetry ## Files Changed - `pyproject.toml` - Converted to uv format - `Makefile` - Updated all commands - `.github/actions/setup-uv/action.yml` - New action (replaces setup-poetry) - `.github/workflows/*.yaml` - Updated workflows - `.github/actions/*/action.yaml` - Updated composite actions - `codegen/build-oas.sh` - Updated script - Documentation files - Updated command examples
# Expose delete organization function
## Summary
Exposes the `delete_organization` endpoint through the public
`OrganizationResource` interface. This endpoint was available in the
generated OpenAPI client but was not accessible through the public SDK
API.
## Changes
### Implementation
- Added `delete()` method to `OrganizationResource` class in
`pinecone/admin/resources/organization.py`
- Method follows the same pattern as `ApiKeyResource.delete()` and
`ProjectResource.delete()`
- Includes `@require_kwargs` decorator for parameter validation
- Added RST-formatted docstring with warning about permanent deletion
- Updated class docstring to mention delete functionality
### Testing
Added comprehensive unit tests in
`tests/unit/admin/test_organization.py`:
- **Request verification**: Tests verify that `delete()` correctly calls
the underlying API method with the correct `organization_id` parameter
- **Parameter validation**: Tests verify that `@require_kwargs` enforces
the required `organization_id` parameter
- **Edge cases**: Tests with different `organization_id` values to
ensure proper parameter passing
All tests use mocks to verify request building without making real API
calls.
## Usage Example
```python
from pinecone import Admin
admin = Admin()
# Delete an organization
admin.organization.delete(
organization_id="42ca341d-43bf-47cb-9f27-e645dbfabea6"
)
```
## Backward Compatibility
✅ Fully backward compatible. This is a new method addition that does not
modify existing functionality.
## Files Changed
- `pinecone/admin/resources/organization.py` - Added `delete()` method
- `tests/unit/admin/test_organization.py` - New file with unit tests
- `tests/unit/admin/__init__.py` - New file for package structure
## Related
This addresses the gap identified in
`ENDPOINT_COVERAGE_AUDIT_RESULTS.md` where `delete_organization` was
marked as missing from the public interface. The endpoint was available
in `pinecone/core/openapi/admin/api/organizations_api.py` but not
exposed through `OrganizationResource`.
) # Add filter parameter to update() method for metadata-based bulk updates ## Summary Adds the `filter` parameter to the `update()` method across the SDK, enabling bulk updates by metadata filter. This exposes the existing backend capability that was previously unavailable in the public API. Additionally, makes the `id` parameter optional to support filter-only bulk updates. ## Changes ### Implementation - Added `filter: Optional[FilterTypedDict] = None` parameter to: - `IndexInterface.update()` and `IndexAsyncioInterface.update()` (interfaces) - `Index.update()` and `IndexAsyncio.update()` (REST implementations) - `GRPCIndex.update()` (GRPC implementation) - `IndexRequestFactory.update_request()` (request factory) - Made `id` parameter optional (`id: Optional[str] = None`) to support filter-only bulk updates - Added validation to ensure exactly one of `id` or `filter` is provided (not both, not neither) - Updated docstrings with comprehensive explanations of two update modes: - **Single vector update by ID**: Update a specific vector by providing `id` - **Bulk update by metadata filter**: Update all matching vectors by providing `filter` - Fixed return value documentation to accurately describe `UpdateResponse` with `matched_records` field - For GRPC implementation, filter dicts are converted to protobuf Struct using `dict_to_proto_struct()` ### Testing Added comprehensive unit tests covering: - **Request factory**: 12 tests for `update_request()` including filter-only, id-only, and various filter combinations - **REST Index**: 7 tests verifying `update()` calls including filter-only updates and validation - **GRPC Index**: 6 tests verifying filter conversion to proto struct and validation Test coverage includes: - Filter-only updates (bulk updates without id) - Id-only updates (backward compatibility) - Filter with other parameters (values, set_metadata, namespace, sparse_values) - Various filter operators ($eq, $in, $gte, $lte, $ne) - Complex nested filters ($and, $or) - Validation: error when neither id nor filter provided - Validation: error when both id and filter provided ## Usage Examples **Single vector update by ID:** ```python # Update a specific vector index.update( id='id1', set_metadata={'status': 'active'}, namespace='my_namespace' ) ``` **Bulk update by metadata filter:** ```python # Update all vectors matching the filter response = index.update( set_metadata={'status': 'active'}, filter={'genre': {'$eq': 'drama'}}, namespace='my_namespace' ) print(f"Updated {response.matched_records} vectors") ``` ## Backward Compatibility ✅ Fully backward compatible. Existing code that provides `id` continues to work without any changes. The `id` parameter is now optional, but all existing calls that provide `id` will continue to function as before. ## Files Changed - `pinecone/db_data/interfaces.py` - `pinecone/db_data/index_asyncio_interface.py` - `pinecone/db_data/request_factory.py` - `pinecone/db_data/index.py` - `pinecone/db_data/index_asyncio.py` - `pinecone/grpc/index_grpc.py` - `tests/unit/data/test_request_factory.py` - `tests/unit/test_index.py` - `tests/unit_grpc/test_grpc_index_update.py` ## Related This addresses the gap identified in the endpoint coverage audit where `update_vector` supported a `filter` parameter in the generated OpenAPI code, but it wasn't exposed in the public SDK interface.
## Summary Removes support for Python 3.9, which has reached end-of-life, and updates all configuration and documentation to reflect Python 3.10+ as the minimum supported version. This simplifies dependency constraints and aligns with current Python support lifecycle. ## Changes ### Configuration Updates - Updated `pyproject.toml`: - Changed `requires-python` from `">=3.9"` to `">=3.10"` - Removed `"Programming Language :: Python :: 3.9"` trove classifier - Updated Ruff `target-version` from `"py39"` to `"py310"` - Updated Black `target-version` from `["py39"]` to `["py310"]` - Simplified dependency constraints by removing Python 3.9-specific conditions: - `pandas-stubs`: Removed Python 3.8-3.9 fallback, now uses single version constraint - `numpy`: Removed Python 3.8-3.9 fallback, now uses single version constraint - `pytest-benchmark`: Simplified condition from `python_version>='3.9' and python_version<'4.0'` to `python_version<'4.0'` - `sphinx`: Simplified condition from `python_version>='3.9' and python_version<'3.11'` to `python_version<'3.11'` - `myst-parser`: Removed Python 3.9-3.10 fallback, now uses single version constraint - `grpcio`: Simplified condition from `python_version>='3.8' and python_version<'3.11'` to `python_version<'3.11'` - `pandas`: Simplified condition from `python_version>='3.9' and python_version<'3.13'` to `python_version<'3.13'` ### Documentation Updates - Updated `README.md`: Changed prerequisites from "Python 3.9 and greater" to "Python 3.10 and greater", and updated tested versions from "3.9 to 3.13" to "3.10 to 3.13" - Updated `docs/index.rst`: Changed prerequisites from "Python 3.9 and greater" to "Python 3.10 and greater", and updated tested versions from "3.9 to 3.13" to "3.10 to 3.13" - Updated `docs/upgrading.md`: Added breaking change note in the 7.x section documenting the removal of Python 3.9 support ## Breaking Changes⚠️ **Python 3.9 is no longer supported.** Users must upgrade to Python 3.10 or later to use this version of the SDK. ## Impact - **Users on Python 3.9**: Must upgrade to Python 3.10+ to continue using the SDK - **Dependency resolution**: Simplified constraints may allow newer package versions to be installed - **CI/CD**: No changes needed as workflows already use parameterized Python versions (3.10, 3.11, 3.12, 3.13) ## Rationale Python 3.9 reached end-of-life on October 2, 2025. Dropping support allows us to: - Simplify dependency management by removing version-specific constraints - Take advantage of Python 3.10+ features and improvements - Reduce maintenance burden by focusing on actively supported Python versions - Align with the Python community's support lifecycle ## Files Changed - `pyproject.toml` - `README.md` - `docs/index.rst` - `docs/upgrading.md`
# Comprehensive Type Hints Implementation ## Summary This PR implements comprehensive type hints throughout the Pinecone Python SDK, addressing customer requests for better type safety and IDE support. The changes include type annotations for all public methods, decorators, helper functions, and generated code templates, while adopting modern Python 3.10+ type syntax. ## Problem The SDK lacked comprehensive type hints, making it difficult for: - IDEs to provide accurate autocomplete and type checking - Static type checkers (like mypy) to validate code correctness - Developers to understand expected parameter and return types - Customers who rely on type hints for better development experience ## Solution Implemented comprehensive type hints across the entire SDK, including: - Return type annotations for all public methods in `Pinecone`, `PineconeAsyncio`, `Index`, `IndexAsyncio`, and `IndexGRPC` - Type hints for decorators using `ParamSpec` and `TypeVar` for proper signature preservation - Context manager type hints (`__enter__`, `__exit__`, `__aenter__`, `__aexit__`) - Generator and async generator return types - Helper function type annotations - Modern Python 3.10+ syntax (`X | Y` instead of `Union[X, Y]`, `X | None` instead of `Optional[X]`) - Improved OpenAPI code generation templates with return type annotations and better type inference ## Key Changes ### Core Client Classes - **`pinecone/pinecone.py`**: Added return types to all methods (`create_index`, `delete_index`, `list_indexes`, etc.) - **`pinecone/pinecone_asyncio.py`**: Added return types to all async methods and context manager support - **`pinecone/db_data/index.py`**: Added return types to all data operations (upsert, query, fetch, delete, etc.) - **`pinecone/db_data/index_asyncio.py`**: Added return types to all async data operations - **`pinecone/grpc/index_grpc.py`**: Added return types to all gRPC operations ### Decorators - **`pinecone/utils/require_kwargs.py`**: Added `ParamSpec` and `TypeVar` for proper type preservation - **`pinecone/utils/error_handling.py`**: Added `ParamSpec` and `TypeVar` with proper signature handling ### Factory Methods - **`pinecone/db_data/request_factory.py`**: Added explicit type annotations to all factory methods - **`pinecone/db_data/vector_factory.py`**: Added type annotations and support for `VectorTupleWithMetadata` - **`pinecone/db_data/sparse_values_factory.py`**: Added type annotations to helper methods - **`pinecone/db_data/resources/sync/bulk_import_request_factory.py`**: Added type annotations ### Helper Functions - **`pinecone/utils/check_kwargs.py`**: Added type annotations (`Callable[..., Any]`, `set[str]`, `None`) - **`pinecone/db_data/sparse_values_factory.py`**: Added type annotations to `_convert_to_list` and `_validate_list_items_type` - **`pinecone/db_data/request_factory.py`**: Added type annotations to `vec_builder`, `_parse_search_rerank`, and `upsert_records_args` ### Modern Type Syntax - Replaced `Union[X, Y]` with `X | Y` syntax (PEP 604) - Replaced `Optional[X]` with `X | None` syntax - Added `from __future__ import annotations` to support deferred evaluation for Python 3.9 compatibility ### Type Configuration - **`mypy.ini`**: Configured mypy with gradual strictness settings - Added `ignore_missing_imports` for optional dependencies (grpc, aiohttp, aiohttp_retry, urllib3, tqdm) - Removed unnecessary `ignore_errors` and `ignore_missing_imports` settings after fixing underlying type issues - All `pinecone.openapi_support.*` modules now pass mypy without ignores ### Interface Alignment - Updated `pinecone/db_data/index_asyncio_interface.py` to match implementation signatures - Updated `pinecone/db_data/interfaces.py` to use modern type syntax and correct types - Fixed method signature mismatches between interfaces and implementations - Aligned `AsyncIterator` imports between interface and implementation (`collections.abc` vs `typing`) ### OpenAPI Support Module Improvements - **`pinecone/openapi_support/model_utils.py`**: - Fixed `get_possible_classes()` to handle `Any` (typing special form, not a class) - Fixed `get_required_type_classes()` to handle typing generics (`Dict[str, Any]`, `List[T]`, `Tuple[T, ...]`) - Added `is_valid_type()` check for `Any` to accept any type when `Any` is in valid classes - Fixed type validation for nested dict values with `Any` types - Added proper handling of typing generics by normalizing to built-in types - **`pinecone/openapi_support/serializer.py`**: Fixed return type handling for file data - **`pinecone/openapi_support/api_client_utils.py`**: Fixed type annotations for multipart parameters - **`pinecone/openapi_support/rest_urllib3.py`**: Added explicit type for `request_body` - **`pinecone/openapi_support/asyncio_api_client.py`**: Fixed `_check_type` parameter handling and dynamic attribute assignment - **`pinecone/openapi_support/api_client.py`**: Fixed `_check_type` parameter handling and dynamic attribute assignment - **`pinecone/openapi_support/endpoint_utils.py`**: Fixed type annotation for `validations` parameter ### Data Class Improvements - **`pinecone/db_data/dataclasses/fetch_response.py`**: Changed `usage` from `Dict[str, int]` to `Optional[Usage]` to align with OpenAPI model - **`pinecone/db_data/dataclasses/fetch_by_metadata_response.py`**: Changed `usage` from `Dict[str, int]` to `Optional[Usage]` for consistency - **`pinecone/grpc/utils.py`**: Updated parsing functions to pass `Usage` object directly instead of converting to dict ## User-Facing Impact ### Benefits - **Better IDE Support**: IDEs can now provide accurate autocomplete, parameter hints, and type checking - **Static Type Checking**: Developers can use mypy or other type checkers to catch type errors before runtime - **Improved Documentation**: Type hints serve as inline documentation for expected types - **Better Developer Experience**: Clearer understanding of API contracts and expected types ### Breaking Changes **None** - All changes are additive. Existing code continues to work without modification. ### Migration Guide No migration required. The type hints are purely additive and don't change runtime behavior. ## Technical Details ### Type Inference Improvements - Added explicit type annotations to factory methods to help mypy infer return types from OpenAPI model constructors - Improved `Deserializer.deserialize()` with generic typing for better type inference - Added `__new__` method to generated models for better constructor type inference ### Type Safety - All public methods now have return type annotations - Context managers properly typed for `with` and `async with` statements - Generators and async generators have proper return types - Decorators preserve function signatures using `ParamSpec` ### Compatibility - Runtime requires Python 3.10+ (as per existing requirements) - All type hints are forward-compatible and don't affect runtime performance ## Testing - All existing tests pass (388 unit tests) - Mypy type checking passes with comprehensive coverage ## Files Changed - **182 files changed**: Core client classes, data operations, gRPC operations, utilities, generated code templates, and configuration files - **2,313 insertions, 600 deletions**: Net addition of comprehensive type annotations ## Technical Achievements ### Reduced `Any` Usage - Eliminated `Any` return types from generated API methods by adding explicit return type annotations - Reduced casting needed in client code through better type inference in generated models - Fixed "Returning Any" errors by adding explicit type annotations to factory methods and helper functions ### Code Generation Quality - Generated code now includes proper return type annotations for all API methods - Post-processing steps ensure generated code passes mypy without manual fixes - Template improvements reduce the need for manual type annotations in client code ## Future Work - Continue reducing `Any` usage in edge cases - Consider adding runtime type validation for critical paths (optional, behind a flag) - Monitor and improve type coverage as the codebase evolves
## Summary Removes SDK-imposed default values for the `namespace` parameter in GRPC methods, ensuring the SDK doesn't override API defaults. This change allows the API to handle namespace defaults appropriately as it moves toward `"__default__"` as the default namespace value. ## Changes ### GRPC Method Updates - Updated `pinecone/grpc/resources/vector_grpc.py`: Changed `upsert_from_dataframe` method signature from `namespace: str = ""` to `namespace: Optional[str] = None` - Updated `pinecone/grpc/index_grpc.py`: Changed `upsert_from_dataframe` method signature from `namespace: str = ""` to `namespace: Optional[str] = None` ### Behavior Verification - All REST API methods already correctly use `Optional[str] = None` for namespace parameters - When `namespace=None`: Parameter is omitted from request bodies (via `parse_non_empty_args`), allowing the API to apply its default - When `namespace=""`: Parameter is included as empty string in request (explicit user choice, passed through unmodified) - When `namespace="some_namespace"`: Parameter is included in request as expected ## Impact - **GRPC `upsert_from_dataframe` methods**: Now default to `None` instead of `""`, allowing the API to handle namespace defaults - **Backward compatibility**: No breaking changes - methods still accept all the same values, but default behavior now defers to the API - **API flexibility**: The API can now apply its own default namespace handling (e.g., `"__default__"`) without SDK interference ## Rationale The API is moving toward `"__default__"` as the default namespace value. By removing SDK-imposed defaults (empty string), we ensure: - The SDK doesn't override API defaults - When users don't specify a namespace, the API can apply its own default handling - Explicit empty string values from users are still passed through as intended - The SDK remains neutral regarding namespace defaults, allowing the API to evolve its default behavior ## Testing - All db data integration tests pass (104 passed, 18 skipped) - Verified that `namespace=None` omits the parameter from requests - Verified that `namespace=""` passes through as empty string - Verified that explicit namespace values work correctly ## Files Changed - `pinecone/grpc/resources/vector_grpc.py` - `pinecone/grpc/index_grpc.py`
# Migrate to Python 3.10+ Type Syntax
## Summary
This PR modernizes the Pinecone Python SDK's type annotations by
migrating from legacy `typing` module syntax to Python 3.10+ built-in
type syntax. All `Union[X, Y]` usages are replaced with `X | Y`, all
`Optional[X]` usages are replaced with `X | None`, and deprecated typing
aliases (`Dict`, `Tuple`) are replaced with built-in types (`dict`,
`tuple`).
## Problem
The SDK was using legacy type annotation syntax that has been superseded
by cleaner, more readable Python 3.10+ syntax:
- `Union[X, Y]` is verbose and less readable than `X | Y`
- `Optional[X]` is redundant when `X | None` is more explicit
- `Dict` and `Tuple` from `typing` are deprecated in favor of built-in
`dict` and `tuple` (PEP 585)
Since the SDK already requires Python 3.10+, we can take advantage of
these modern syntax improvements.
## Solution
Migrated all type annotations throughout the codebase to use Python
3.10+ syntax:
- Replaced `Union[X, Y]` with `X | Y` syntax
- Replaced `Optional[X]` with `X | None` syntax
- Replaced `Dict` with `dict` and `Tuple` with `tuple` in non-generated
code
- Added `from __future__ import annotations` where needed for forward
references
- Used `List` from `typing` only where necessary to avoid conflicts with
methods named `list`
## User-Facing Impact
### Benefits
- **Cleaner, More Readable Code**: Modern type syntax is more concise
and easier to read
- **Better IDE Support**: IDEs better understand the modern syntax and
provide improved autocomplete
- **Future-Proof**: Aligns with Python's direction and best practices
for Python 3.10+
- **No Breaking Changes**: All changes are purely syntactic - runtime
behavior is unchanged
### Breaking Changes
**None** - This is a purely syntactic change. All existing code
continues to work without modification.
### Migration Guide
No migration required for users. The changes are internal to the SDK and
transparent to users.
## Example Usage
The changes are internal, but here's how the improved type annotations
look:
### Before
```python
from typing import Union, Optional, Dict, List
def search(
query: Union[str, Dict[str, Any]],
top_k: int,
filter: Optional[Dict[str, Any]] = None,
namespace: Optional[str] = None
) -> Dict[str, List[ScoredVector]]:
...
```
### After
```python
from typing import List # Only needed where 'list' method conflicts
def search(
query: str | dict[str, Any],
top_k: int,
filter: dict[str, Any] | None = None,
namespace: str | None = None
) -> dict[str, List[ScoredVector]]:
...
```
## Technical Details
### Type Alias Handling
For type aliases that reference forward-declared types, we use
`TypeAlias` with proper `TYPE_CHECKING` guards to ensure mypy can
resolve types correctly while maintaining runtime compatibility.
### Naming Conflicts
In classes with methods named `list`, we continue to use `List` from
`typing` to avoid shadowing the built-in type. This affects:
- `ApiKeyResource.list()` method
- `IndexAsyncioInterface.list()` method
- `_IndexAsyncio.list()` method
- `GRPCIndex.list()` method
### Generated Code
Generated files in `pinecone/core/` are not modified, as they are
automatically generated from OpenAPI specifications. These will be
updated when the code generation templates are updated in a future PR.
## Testing
- All existing tests pass (414 unit tests, 4 skipped)
- Mypy type checking passes with no errors (353 source files checked)
- All files compile successfully
## Compatibility
- **Python Version**: Requires Python 3.10+ (already a requirement)
- **Backward Compatibility**: Fully backward compatible - no API changes
- **Type Checkers**: Compatible with mypy, pyright, and other modern
type checkers
# Improve IDE Tab-Completion and Type Hinting Support
## Summary
This PR enhances IDE tab-completion and type hinting support for the
Pinecone Python SDK by ensuring complete type coverage. It adds missing
return type annotations, class-level attribute type annotations,
completes the type stub file, and ensures the `py.typed` marker file is
included in package distribution.
## Problem
Some areas of the codebase lacked complete type annotations, which
limited IDE tab-completion and type checking capabilities:
- Some methods were missing return type annotations (e.g.,
`UpsertResponseTransformer.get()`, `__getattr__()`)
- Instance attributes lacked class-level type annotations, making it
difficult for IDEs to infer types
- The `__init__.pyi` stub file was incomplete, missing several exported
types including deprecated functions, the `Admin` class, `__version__`,
and various lazy-loaded types
- The `py.typed` marker file wasn't explicitly configured in the build
system, potentially causing issues with type checker discovery
## Solution
Enhanced IDE support and type checking by:
- **Ensured `py.typed` marker file is included**: Added explicit
configuration in `pyproject.toml` to guarantee the PEP 561 marker file
is packaged
- **Added missing return type annotations**: Added return types to
`UpsertResponseTransformer.get()` (returns `UpsertResponse`) and
`__getattr__()` (returns `Any`)
- **Added class-level type annotations**: Added type annotations for
instance attributes in:
- `PluginAware._plugins_loaded`
- `UpsertResponseTransformer._apply_result`
- `Index` class attributes (`_config`, `_openapi_config`,
`_pool_threads`, `_vector_api`, `_api_client`)
- `IndexAsyncio` class attributes (`config`, `_openapi_config`,
`_vector_api`, `_api_client`)
- **Completed `__init__.pyi` stub file**: Added all missing exported
types including:
- Deprecated top-level functions (init, create_index, delete_index,
etc.)
- `Admin` class
- `__version__`
- Missing lazy-loaded types (FilterBuilder, ByocSpec, BackupModel,
RestoreJobModel, RestoreJobList, BackupList, and all ReadCapacity and
MetadataSchema types)
- **Fixed type annotation**: Replaced `Optional[str]` with `str | None`
in `vector_grpc.py` for consistency
## User-Facing Impact
### Benefits
- **Enhanced IDE Support**: Complete type annotations enable better
autocomplete, tab-completion, and inline type hints in IDEs like VS
Code, PyCharm, and others
- **Better Type Checking**: More complete type coverage improves static
type checking with mypy, pyright, and other tools
- **Improved Developer Experience**: Developers get better IntelliSense
and can catch type errors earlier in their development workflow
- **No Breaking Changes**: All changes are purely additive - runtime
behavior is unchanged
### Breaking Changes
**None** - This is a purely additive change. All existing code continues
to work without modification.
### Migration Guide
No migration required for users. The changes are internal to the SDK and
transparent to users. Users will automatically benefit from improved IDE
support when they update to this version.
## Example Usage
The improvements are transparent to users, but developers will notice
better IDE support:
```python
from pinecone import Pinecone
pc = Pinecone(api_key="your-api-key")
index = pc.Index("my-index")
# IDE now provides better autocomplete and type hints for:
# - index.upsert() method parameters and return type
# - index.query() method parameters and return type
# - All exported types from pinecone package
```
## Technical Details
### Type Stub File Completion
The `__init__.pyi` stub file now includes all exports from
`__init__.py`, ensuring type checkers and IDEs have complete information
about what's available in the package. This includes:
- All lazy-loaded types that are dynamically imported
- Deprecated functions that raise helpful error messages
- All enum types, model classes, and dataclasses
### Class-Level Attribute Annotations
Adding class-level type annotations for instance attributes (PEP 526)
allows IDEs to:
- Provide autocomplete for instance attributes
- Show type information in hover tooltips
- Perform type checking on attribute access
### PEP 561 Compliance
Explicitly including `py.typed` in the package distribution ensures type
checkers can discover that the package contains type information,
following PEP 561 guidelines.
## Testing
- All existing tests pass
- Mypy type checking passes with no errors (192 source files checked,
excluding generated code)
- Verified `py.typed` is included in package distribution
- Verified `__init__.pyi` stub file matches all exports from
`__init__.py`
- All files compile successfully
## Compatibility
- **Python Version**: Requires Python 3.10+ (already a requirement)
- **Backward Compatibility**: Fully backward compatible - no API changes
- **Type Checkers**: Compatible with mypy, pyright, and other modern
type checkers
# Improve Docstring Documentation and Remove Redundant Interface
## Summary
This PR comprehensively reviews and updates all method docstrings in the
`Pinecone` class and underlying interface classes to ensure they use
proper RST syntax, include code-block usage examples, and have correct
whitespace formatting for Sphinx rendering. Additionally, this PR
removes the redundant `LegacyPineconeDBControlInterface` class that was
creating maintenance overhead and sync risks.
## Problem
1. **Incomplete Documentation**: Many methods in the `Pinecone` class
lacked comprehensive docstrings with usage examples, making it difficult
for users to understand how to use the SDK effectively.
2. **Inconsistent Formatting**: Some docstrings used different formats
(e.g., `Args:` vs `:param:`), and code-block examples lacked proper
whitespace formatting required for Sphinx to render correctly.
3. **Redundant Interface**: The `LegacyPineconeDBControlInterface` class
served primarily as a docstring container, creating duplication and the
risk of documentation falling out of sync with implementations.
4. **Unrealistic Examples**: Some code examples (particularly in the
`inference` property) used placeholder content that didn't demonstrate
real-world usage patterns.
## Solution
1. **Added Comprehensive Docstrings**: Added complete RST-formatted
docstrings with code-block examples to all `Pinecone` class methods that
were missing them, including:
- Index management methods (`create_index`, `delete_index`,
`list_indexes`, `describe_index`, `has_index`, `configure_index`)
- Collection methods (`create_collection`, `list_collections`,
`delete_collection`, `describe_collection`)
- Backup and restore job methods (`create_backup`, `list_backups`,
`describe_backup`, `delete_backup`, `list_restore_jobs`,
`describe_restore_job`)
- Index instantiation methods (`Index`, `IndexAsyncio`)
- Properties (`inference`, `db`)
2. **Standardized RST Format**: Converted all docstrings to use
consistent RST syntax with `:param:` and `:type:` directives instead of
mixed formats.
3. **Fixed Code-Block Formatting**: Ensured all code-block examples have
proper whitespace (empty line after code blocks) for correct Sphinx
rendering.
4. **Improved Examples**: Updated examples to be more realistic and
demonstrate actual usage patterns, including:
- Updated the `inference` property example to show realistic embedding
and reranking operations with actual document content
- Fixed syntax errors in import statements within docstring examples
- Added multiple usage patterns where appropriate (e.g., different ways
to create indexes)
5. **Removed Redundant Interface**: Deleted
`LegacyPineconeDBControlInterface` since:
- All docstrings now live in the `Pinecone` class implementation (single
source of truth)
- The interface was only used by `Pinecone` and provided no additional
value
- Eliminates the risk of documentation falling out of sync
6. **Updated Interface Classes**: Enhanced docstrings in
`IndexInterface` with proper RST formatting and added missing code-block
examples (e.g., `upsert_from_dataframe`).
## User-Facing Impact
### Positive Changes
- **Better Documentation**: Users now have comprehensive, well-formatted
documentation with realistic examples for all `Pinecone` class methods
- **Improved IDE Experience**: Better docstrings improve autocomplete
and inline help in IDEs
- **Consistent Formatting**: All documentation follows the same RST
format, making it easier to read and understand
- **Real-World Examples**: Code examples now demonstrate actual usage
patterns that users can directly adapt
### Breaking Changes
**None** - This is a documentation-only change. All method signatures
and behavior remain unchanged.
## Usage Examples
### Before
```python
# Minimal or missing docstrings
pc = Pinecone()
pc.create_index(...) # No clear guidance on usage
```
### After
```python
# Comprehensive documentation with examples
from pinecone import Pinecone, ServerlessSpec, CloudProvider, AwsRegion, Metric
pc = Pinecone()
# Clear examples showing different ways to create indexes
pc.create_index(
name="my_index",
dimension=512,
metric=Metric.COSINE,
spec=ServerlessSpec(
cloud=CloudProvider.AWS,
region=AwsRegion.US_WEST_2
)
)
```
### Improved Inference Example
The `inference` property now shows realistic usage:
```python
from pinecone import Pinecone
pc = Pinecone(api_key="your-api-key")
# Generate embeddings for text
embeddings = pc.inference.embed(
model="multilingual-e5-large",
inputs=["Disease prevention", "Immune system health"]
)
# Rerank documents based on query relevance
reranked = pc.inference.rerank(
model="bge-reranker-v2-m3",
query="Disease prevention",
documents=[
"Rich in vitamin C and other antioxidants, apples contribute to immune health...",
"The high fiber content in apples can also help regulate blood sugar levels...",
# ... more realistic examples
],
top_n=2,
rank_fields=["text"]
)
```
## Technical Details
- All docstrings now use RST syntax consistently
- Code-block examples include proper whitespace formatting (empty line
after code blocks)
- Fixed syntax errors in docstring examples (e.g., import statements)
- Removed `LegacyPineconeDBControlInterface` class and its file
- Updated `Pinecone` class to no longer inherit from the removed
interface
- Enhanced `IndexInterface` docstrings with proper formatting and
examples
# Improve Admin API Documentation
## Summary
This PR comprehensively reviews and updates all docstrings in the Admin
class and its child resource classes (ProjectResource, ApiKeyResource,
OrganizationResource) to ensure they follow RST formatting standards and
include comprehensive code-block usage examples. All docstrings now have
proper whitespace formatting around code blocks to ensure Sphinx renders
them correctly.
## Problem
The Admin API documentation had several issues:
- Some methods were missing code-block usage examples
- Alias methods (`get`, `describe`) lacked examples showing how to use
them
- Code blocks were missing empty lines after them, which can cause
Sphinx rendering issues
- Some examples had syntax errors (missing commas)
- The `__init__` method lacked usage examples showing different
initialization patterns
## Solution
- **Added comprehensive examples**: All methods now include code-block
examples demonstrating different ways to use each function
- **Fixed formatting**: Added empty lines after all code blocks to
ensure proper Sphinx rendering
- **Enhanced alias methods**: Added examples to `get()` and `describe()`
methods in all resource classes
- **Fixed syntax errors**: Corrected missing comma in project creation
example
- **Improved initialization docs**: Added examples showing environment
variable usage, explicit credentials, and additional headers
## User-Facing Impact
Users will now have:
- **Better discoverability**: Clear examples for every Admin API method,
including aliases
- **Multiple usage patterns**: Examples showing different ways to
accomplish the same task (e.g., using `project_id` vs `name`)
- **Properly rendered docs**: Code blocks will render correctly in
Sphinx-generated documentation
- **Complete coverage**: No methods are left without examples, making
the API easier to learn and use
## Usage Examples
### Before
```python
# Alias methods had no examples
admin.project.get(project_id="...") # No documentation example
```
### After
```python
# Now includes comprehensive examples
admin.project.get(project_id="42ca341d-43bf-47cb-9f27-e645dbfabea6")
# Shows both project_id and name usage patterns
```
### Initialization Examples
```python
# Environment variables
admin = Admin() # Reads from PINECONE_CLIENT_ID and PINECONE_CLIENT_SECRET
# Explicit credentials
admin = Admin(
client_id="your-client-id",
client_secret="your-client-secret"
)
# With additional headers
admin = Admin(
client_id="your-client-id",
client_secret="your-client-secret",
additional_headers={"X-Custom-Header": "value"}
)
```
## Breaking Changes
None. This is a documentation-only change that does not affect any API
functionality or behavior.
…de examples (#552) ## Summary This PR updates all docstrings for methods in the `Index` class and the underlying `IndexInterface` class to use proper RST syntax with comprehensive code-block examples. ## Changes - **Updated all Index class method docstrings** with: - Proper RST formatting using Args/Returns/Examples sections - Comprehensive code-block examples showing different usage patterns - Proper whitespace formatting (empty lines after code blocks for Sphinx rendering) - **Updated IndexInterface class docstrings** to: - Match the Index class style and formatting - Use consistent RST formatting throughout - Include code-block examples for all methods - Remove old `:param:` and `:type:` syntax in favor of Args sections ## Methods Updated All methods in both classes now have complete, up-to-date docstrings: - `upsert`, `upsert_from_dataframe`, `upsert_records` - `search`, `search_records` - `delete`, `fetch`, `fetch_by_metadata` - `query`, `query_namespaces` - `update`, `describe_index_stats` - `list`, `list_paginated` - `create_namespace`, `describe_namespace`, `delete_namespace` - `list_namespaces`, `list_namespaces_paginated` - Import-related methods (`start_import`, `list_imports`, etc.) ## Impact - Improved documentation quality and consistency - Better IDE support with comprehensive examples - Proper Sphinx rendering with correct whitespace formatting - All docstrings now follow RST best practices
## Problem The current implementation uses `json_format.MessageToDict` to convert entire protobuf messages to dictionaries when parsing gRPC responses. This is a significant CPU bottleneck when processing large numbers of vectors, as reported in PR #537 where users experienced ~100 vectors/second throughput. The `MessageToDict` conversion is expensive because it: 1. Serializes the entire protobuf message to JSON 2. Deserializes it back into a Python dictionary 3. Does this for every field, even when we only need specific fields Additionally, several other performance issues were identified: - Metadata conversion using `MessageToDict` on `Struct` messages - Inefficient list construction (append vs pre-allocation) - Unnecessary dict creation for `SparseValues` parsing - Response header processing overhead ## Solution Optimized all gRPC response parsing functions in `pinecone/grpc/utils.py` to directly access protobuf fields instead of converting entire messages to dictionaries. This approach: 1. **Directly accesses protobuf fields**: Uses `response.vectors`, `response.matches`, `response.namespace`, etc. directly 2. **Optimized metadata conversion**: Created `_struct_to_dict()` helper that directly accesses `Struct` fields (~1.5-2x faster than `MessageToDict`) 3. **Pre-allocates lists**: Uses `[None] * len()` for known-size lists (~6.5% improvement) 4. **Direct SparseValues creation**: Creates `SparseValues` objects directly instead of going through dict conversion (~410x faster) 5. **Caches protobuf attributes**: Stores repeated attribute accesses in local variables 6. **Optimized response info extraction**: Improved `extract_response_info()` performance with module-level constants and early returns 7. **Maintains backward compatibility**: Output format remains identical to the previous implementation ## Performance Impact Performance testing of the response parsing functions show significant improvements across all optimized functions. ## Changes ### Modified Files - `pinecone/grpc/utils.py`: Optimized 9 response parsing functions with direct protobuf field access - Added `_struct_to_dict()` helper for optimized metadata conversion (~1.5-2x faster) - Pre-allocated lists where size is known (~6.5% improvement) - Direct `SparseValues` creation (removed dict conversion overhead) - Cached protobuf message attributes - Removed dead code paths (dict fallback in `parse_usage`) - `pinecone/grpc/index_grpc.py`: Updated to pass protobuf messages directly to parse functions - `pinecone/grpc/resources/vector_grpc.py`: Updated to pass protobuf messages directly to parse functions - `pinecone/utils/response_info.py`: Optimized `extract_response_info()` with module-level constants and early returns - `tests/perf/test_fetch_response_optimization.py`: New performance tests for fetch response parsing - `tests/perf/test_query_response_optimization.py`: New performance tests for query response parsing - `tests/perf/test_other_parse_methods.py`: New performance tests for all other parse methods - `tests/perf/test_grpc_parsing_perf.py`: Extended with additional benchmarks ### Technical Details **Core Optimizations**: 1. **`_struct_to_dict()` Helper Function**: - Directly accesses protobuf `Struct` and `Value` fields - Handles all value types (null, number, string, bool, struct, list) - Recursively processes nested structures - ~1.5-2x faster than `json_format.MessageToDict` for metadata conversion 2. **List Pre-allocation**: - `parse_query_response`: Pre-allocates `matches` list with `[None] * len(matches_proto)` - `parse_list_namespaces_response`: Pre-allocates `namespaces` list - ~6.5% performance improvement over append-based construction 3. **Direct SparseValues Creation**: - Replaced `parse_sparse_values(dict)` with direct `SparseValues(indices=..., values=...)` creation - ~410x faster (avoids dict creation and conversion overhead) ## Testing - All existing unit tests pass (224 tests in `tests/unit_grpc`) - Comprehensive pytest benchmark tests added for all optimized functions: - `test_fetch_response_optimization.py`: Tests for fetch response with varying metadata sizes - `test_query_response_optimization.py`: Tests for query response with varying match counts, dimensions, metadata sizes, and sparse vectors - `test_other_parse_methods.py`: Tests for all other parse methods (fetch_by_metadata, list_namespaces, stats, upsert, update, namespace_description) - Mypy type checking passes with and without grpc extras (with types extras) - No breaking changes - output format remains identical ## Related This addresses the performance issue reported in PR #537, implementing a similar optimization approach but adapted for the current codebase structure. All parse methods have been optimized with comprehensive performance testing to verify improvements.
# Adopt orjson for JSON Performance Optimization
## Problem
The Pinecone Python client uses Python's standard library `json` module
for serializing and deserializing JSON in REST API requests and
responses. This can be a performance bottleneck, especially for
applications making many API calls or handling large payloads.
## Solution
Replace the standard library `json` module with `orjson`, a fast JSON
library written in Rust. `orjson` provides significant performance
improvements for both serialization (`dumps`) and deserialization
(`loads`) operations.
## Changes
### Dependency Addition
- Added `orjson>=3.0.0` to `pyproject.toml` dependencies with a loose
version constraint to avoid conflicts with other applications
### Code Updates
- **Synchronous REST client** (`rest_urllib3.py`): Replaced
`json.dumps()` with `orjson.dumps()` for request serialization
- **Asynchronous REST client** (`rest_aiohttp.py`): Replaced
`json.dumps()` with `orjson.dumps()` and pre-serialize requests (using
`data` parameter instead of `json=` parameter) for better performance
- **Response deserializer** (`deserializer.py`): Replaced `json.loads()`
with `orjson.loads()` for response parsing
- **Multipart encoding** (`api_client_utils.py`,
`asyncio_api_client.py`): Replaced `json.dumps()` with `orjson.dumps()`
for multipart form data
- **Query response parsing** (`vector.py`, `vector_asyncio.py`):
Replaced `json.loads()` with `orjson.loads()` for parsing query
responses
### Test Updates
- Updated `test_bulk_import.py` to compare parsed JSON dicts instead of
JSON strings, since orjson produces more compact JSON (no spaces after
colons/commas)
## Performance Improvements
Benchmark results show significant performance improvements across all
tested scenarios:
### Serialization (dumps)
- **Small payloads (10 vectors, 128 dim)**: ~14-23x faster
- **Medium payloads (100 vectors, 128 dim)**: ~10-12x faster
- **Large payloads (100 vectors, 512 dim)**: ~20x faster
- **Query responses (1000 matches)**: ~11x faster
### Deserialization (loads)
- **Small payloads (10 vectors, 128 dim)**: ~6-7x faster
- **Medium payloads (100 vectors, 128 dim)**: ~5-6x faster
- **Large payloads (100 vectors, 512 dim)**: ~6x faster
- **Query responses (1000 matches)**: ~4-5x faster
### Round-trip (dumps + loads)
- **Small payloads**: ~8x faster
- **Medium payloads**: ~8-9x faster
These improvements are especially beneficial for:
- High-throughput applications making many API calls
- Applications handling large vector payloads
- Real-time applications where latency matters
## Usage Example
No changes required for users - the API remains the same:
```python
from pinecone import Pinecone
pc = Pinecone(api_key="your-api-key")
index = pc.Index("my-index")
# These operations now benefit from orjson performance improvements
index.upsert(vectors=[...]) # Faster serialization
results = index.query(vector=[...]) # Faster deserialization
```
## Testing
- All existing unit tests pass (316+ tests)
- Performance tests added in `tests/perf/test_orjson_performance.py` to
measure improvements
- Test suite updated to handle orjson's compact JSON output format
## Breaking Changes
None. This is a transparent performance improvement with no API changes.
# Add Missing Method Documentation ## Problem Several methods implemented in the codebase were missing from the Sphinx documentation files (`rest.rst`, `grpc.rst`, and `asyncio.rst`). This made it difficult for users to discover available functionality through the generated documentation. ## Solution Added documentation entries for all missing methods across all three documentation files, ensuring complete coverage of the API surface. ## Changes ### `docs/rest.rst` (Pinecone and Index classes) - **Vectors section**: Added `fetch_by_metadata`, `update`, `upsert_from_dataframe` - **Records section**: Added `upsert_records` (was previously missing) - **Namespaces section** (new): Added `create_namespace`, `describe_namespace`, `delete_namespace`, `list_namespaces`, `list_namespaces_paginated` ### `docs/grpc.rst` (PineconeGRPC and GRPCIndex classes) - **PineconeGRPC**: Added `Index` method documentation - **GRPCIndex Vectors section**: Added `fetch_by_metadata`, `update`, `upsert_from_dataframe` - **GRPCIndex Namespaces section**: Added `create_namespace` and reordered namespace methods for consistency ### `docs/asyncio.rst` (PineconeAsyncio and IndexAsyncio classes) - **PineconeAsyncio**: Added `IndexAsyncio` and `close` method documentation - **IndexAsyncio Vectors section**: Added `fetch_by_metadata`, `update`, `upsert_from_dataframe` - **IndexAsyncio Bulk Import section** (new): Added `start_import`, `list_imports`, `list_imports_paginated`, `describe_import`, `cancel_import` - **IndexAsyncio Records section**: Added `upsert_records` (was previously missing) - **IndexAsyncio Namespaces section** (new): Added `create_namespace`, `describe_namespace`, `delete_namespace`, `list_namespaces`, `list_namespaces_paginated` ## Impact Users can now discover all available methods through the generated Sphinx documentation. The documentation is now complete and accurately reflects the full API surface across all client implementations (REST, gRPC, and asyncio). ## Breaking Changes None. This is a documentation-only change that adds missing entries without modifying any code or existing documentation.
## Problem
Response headers were being filtered to exclude timing-dependent headers
(`x-envoy-upstream-service-time`, `date`, `x-request-id`) to avoid test
flakiness. However, these headers can be useful for debugging,
monitoring, and understanding request behavior in production
environments.
Additionally, the `extract_response_info` function was importing modules
on every request and performing unnecessary checks, creating performance
overhead for a function that runs on every API call.
## Solution
Remove header filtering so all response headers are preserved in
`_response_info` for REST, asyncio, and gRPC requests. This provides
complete header information while maintaining correct equality
comparisons (response dataclasses already exclude `_response_info` from
equality checks).
Also optimize `extract_response_info` performance by moving imports to
module level and removing unnecessary conditional checks.
## Changes
### Response Info Extraction (`response_info.py`)
- Removed filtering of timing-dependent headers
(`x-envoy-upstream-service-time`, `date`, `x-request-id`)
- Optimized value conversion to check string type first (most common
case)
- Updated documentation to reflect that all headers are now included
### REST API Clients (`api_client.py`, `asyncio_api_client.py`)
- Moved `extract_response_info` import to module level to eliminate
import overhead on every request
- Removed unnecessary `if response_info:` check since the function
always returns a dict
## Performance Improvements
- Eliminated import overhead by moving imports to module level
- Removed unnecessary conditional checks
- Optimized type checking order for header value conversion (check
string type first)
These optimizations are especially beneficial for high-throughput
applications making many API calls.
## Usage Example
No changes required for users - the API remains the same:
```python
from pinecone import Pinecone
pc = Pinecone(api_key="your-api-key")
index = pc.Index("my-index")
# All response headers are now available in _response_info
upsert_response = index.upsert(vectors=[...])
print(upsert_response._response_info["raw_headers"])
# Now includes all headers: date, x-envoy-upstream-service-time,
# x-request-id, x-pinecone-request-lsn, etc.
query_response = index.query(vector=[...])
print(query_response._response_info["raw_headers"])
# Includes all headers from query response
```
## Testing
- All existing unit tests pass (414+ tests)
- Integration tests verify response info functionality with all headers
included
- LSN header extraction tests confirm all headers are preserved
- Tests access headers flexibly using `.get("raw_headers", {})`, so they
continue to work with additional headers
## Breaking Changes
None. This is a transparent improvement with no API changes. Response
object equality comparisons are unaffected since `_response_info`
already has `compare=False` in all response dataclasses
(`QueryResponse`, `UpsertResponse`, `UpdateResponse`, `FetchResponse`,
`FetchByMetadataResponse`).
## Problem The SDK was pinned to `pinecone-plugin-assistant==3.0.0`, which prevents automatic updates to compatible patch and minor versions (e.g., 3.0.1, 3.0.2, 3.1.0). ## Solution Updated the dependency specification to use a version range (`>=3.0.1,<4.0.0`) instead of an exact pin. This allows the SDK to automatically pick up compatible future versions while maintaining API compatibility within the 3.x series. ## Changes - **`pyproject.toml`**: Changed `pinecone-plugin-assistant==3.0.0` to `pinecone-plugin-assistant>=3.0.1,<4.0.0` - **`uv.lock`**: Regenerated lock file to resolve to version 3.0.1 ## Impact Users will automatically receive compatible updates to the assistant plugin (3.0.1, 3.0.2, 3.1.0, etc.) when installing or updating the SDK, without requiring a new SDK release. The version range ensures compatibility within the 3.x major version while preventing breaking changes from 4.0.0+. ## Breaking Changes None. This change maintains backward compatibility and only affects how future compatible versions are resolved.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Problem
In preparation for shipping the release, I need to merge the release-candidate branch.
Below you will find a summary of the changes in this upcoming release.
Breaking Changes
namespaceparameter in GRPC methods. Whennamespace=None, the parameter is omitted from requests, allowing the API to handle namespace defaults appropriately. This change affectsupsert_from_dataframemethods in GRPC clients. The API is moving toward"__default__"as the default namespace value, and this change ensures the SDK doesn't override API defaults.Note: The official SDK package was renamed last year from
pinecone-clienttopineconebeginning in version 5.1.0. Please removepinecone-clientfrom your project dependencies and addpineconeinstead to get the latest updates if upgrading from earlier versions.What's new in
8.xDedicated Read Capacity for Serverless Indexes
You can now configure dedicated read nodes for your serverless indexes, giving you more control over query performance and capacity planning. By default, serverless indexes use OnDemand read capacity, which automatically scales based on demand. With dedicated read capacity, you can allocate specific read nodes with manual scaling control.
Create an index with dedicated read capacity:
Configure read capacity on an existing index:
You can switch between OnDemand and Dedicated modes, or adjust the number of shards and replicas for dedicated read capacity:
When you change read capacity configuration, the index will transition to the new configuration. You can use
describe_indexto check the status of the transition.See PR #528 for details.
Fetch and Update Vectors by Metadata
Fetch vectors by metadata filter
You can now fetch vectors using metadata filters instead of vector IDs. This is especially useful when you need to retrieve vectors based on their metadata properties.
Pagination support:
When fetching large numbers of vectors, you can use pagination tokens to retrieve results in batches:
Update vectors by metadata filter
The update method used to require a vector id to be passed, but now you have the option to pass a metadata filter instead. This is useful for bulk metadata updates across many vectors.
There is also a dry_run option that allows you to preview the number of vectors that would be changed by the update before performing the operation.
FilterBuilder for fluent filter construction
A new
FilterBuilderutility class provides a type-safe, fluent interface for constructing metadata filters. While perhaps a bit verbose, it can help prevent common errors like misspelled operator names and provides better IDE support.When you chain
.build()onto theFilterBuilderit will emit a python dictionary representing the filter. Methods that take metadata filters as arguments will continue to accept dictionaries as before.The FilterBuilder supports all Pinecone filter operators:
eq,ne,gt,gte,lt,lte,in_,nin, andexists. Compound expressions are build with and&and or|.See PR #529 for
fetch_by_metadata, PR #544 forupdate()with filter, and PR #531 for FilterBuilder.Other New Features
Create namespaces programmatically
You can now create namespaces in serverless indexes directly from the SDK:
Note: This operation is not supported for pod-based indexes.
See PR #532 for details.
Match terms in search operations
For sparse indexes with integrated embedding configured to use the
pinecone-sparse-english-v0model, you can now specify which terms must be present in search results:The
match_termsparameter ensures that all specified terms must be present in the text of each search hit. Terms are normalized and tokenized before matching, and order does not matter.See PR #530 for details.
Admin API enhancements
Update API keys, projects, and organizations:
Delete organizations:
See PR #527 and PR #543 for details.
Metadata schema configuration
You can now configure which metadata fields are filterable when creating serverless indexes. This helps optimize performance by only indexing metadata fields that you plan to use for filtering:
When using schemas, only fields marked as
filterable: Truein the schema can be used in metadata filters.See PR #528 for details.
Response header information
The SDK now exposes header information from API responses. This information is available in response objects via the
_response_infoattribute and can be useful for debugging and monitoring.See PR #539 for details.
Performance Improvements
orjson for faster JSON processing
We've replaced Python's standard library
jsonmodule withorjson, a fast JSON library written in Rust. This provides significant performance improvements for both serialization and deserialization of request payloads:These improvements are especially beneficial for:
No code changes are required - the API remains the same, and you'll automatically benefit from these performance improvements.
See PR #556 for details.
Optimized gRPC response parsing
We've optimized gRPC response parsing by replacing
json_format.MessageToDictwith direct protobuf field access. This optimization provides approximately 2x faster response parsing for gRPC operations.See PR #553 for details.
Other Improvements
pinecone-plugin-assistantto version 3.0.1.