Skip to content

Add describe, delete, and list namespaces (REST) #507

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 17 commits into from
Jun 17, 2025
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions pinecone/db_data/index.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
UpsertResponse,
ListResponse,
SearchRecordsResponse,
ListNamespacesResponse,
NamespaceDescription,
)
from .dataclasses import Vector, SparseValues, FetchResponse, SearchQuery, SearchRerank
from .interfaces import IndexInterface
Expand Down Expand Up @@ -47,6 +49,7 @@
if TYPE_CHECKING:
from pinecone.config import Config, OpenApiConfiguration
from .resources.sync.bulk_import import BulkImportResource
from .resources.sync.namespace import NamespaceResource

from pinecone.core.openapi.db_data.models import (
StartImportResponse,
Expand Down Expand Up @@ -75,6 +78,9 @@ class Index(PluginAware, IndexInterface):
_bulk_import_resource: Optional["BulkImportResource"]
""" :meta private: """

_namespace_resource: Optional["NamespaceResource"]
""" :meta private: """

def __init__(
self,
api_key: str,
Expand Down Expand Up @@ -115,6 +121,9 @@ def __init__(
self._bulk_import_resource = None
""" :meta private: """

self._namespace_resource = None
""" :meta private: """

# Pass the same api_client to the ImportFeatureMixin
super().__init__(api_client=self._api_client)

Expand Down Expand Up @@ -152,6 +161,20 @@ def bulk_import(self) -> "BulkImportResource":
self._bulk_import_resource = BulkImportResource(api_client=self._api_client)
return self._bulk_import_resource

@property
def namespace(self) -> "NamespaceResource":
""":meta private:"""
if self._namespace_resource is None:
from .resources.sync.namespace import NamespaceResource

self._namespace_resource = NamespaceResource(
api_client=self._api_client,
config=self._config,
openapi_config=self._openapi_config,
pool_threads=self._pool_threads,
)
return self._namespace_resource

def _openapi_kwargs(self, kwargs: Dict[str, Any]) -> Dict[str, Any]:
return filter_dict(kwargs, OPENAPI_ENDPOINT_PARAMS)

Expand Down Expand Up @@ -605,3 +628,21 @@ def cancel_import(self, id: str):
id (str): The id of the import operation to cancel.
"""
return self.bulk_import.cancel(id=id)

@validate_and_convert_errors
def describe_namespace(self, namespace: str) -> "NamespaceDescription":
return self.namespace.describe(namespace=namespace)

@validate_and_convert_errors
def delete_namespace(self, namespace: str) -> Dict[str, Any]:
return self.namespace.delete(namespace=namespace)

@validate_and_convert_errors
def list_namespaces(self, **kwargs) -> Iterator[ListNamespacesResponse]:
return self.namespace.list(**kwargs)

@validate_and_convert_errors
def list_namespaces_paginated(
self, limit: Optional[int] = None, pagination_token: Optional[str] = None
) -> ListNamespacesResponse:
return self.namespace.list_paginated(limit=limit, pagination_token=pagination_token)
36 changes: 36 additions & 0 deletions pinecone/db_data/index_asyncio.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
DeleteRequest,
ListResponse,
SearchRecordsResponse,
ListNamespacesResponse,
NamespaceDescription,
)

from ..utils import (
Expand Down Expand Up @@ -50,6 +52,7 @@

if TYPE_CHECKING:
from .resources.asyncio.bulk_import_asyncio import BulkImportResourceAsyncio
from .resources.asyncio.namespace_asyncio import NamespaceResourceAsyncio

from pinecone.core.openapi.db_data.models import (
StartImportResponse,
Expand Down Expand Up @@ -140,6 +143,9 @@ async def main():
_bulk_import_resource: Optional["BulkImportResourceAsyncio"]
""" :meta private: """

_namespace_resource: Optional["NamespaceResourceAsyncio"]
""" :meta private: """

def __init__(
self,
api_key: str,
Expand Down Expand Up @@ -173,6 +179,9 @@ def __init__(
self._bulk_import_resource = None
""" :meta private: """

self._namespace_resource = None
""" :meta private: """

async def __aenter__(self):
return self

Expand Down Expand Up @@ -241,6 +250,15 @@ def bulk_import(self) -> "BulkImportResourceAsyncio":
self._bulk_import_resource = BulkImportResourceAsyncio(api_client=self._api_client)
return self._bulk_import_resource

@property
def namespace(self) -> "NamespaceResourceAsyncio":
""":meta private:"""
if self._namespace_resource is None:
from .resources.asyncio.namespace_asyncio import NamespaceResourceAsyncio

self._namespace_resource = NamespaceResourceAsyncio(api_client=self._api_client)
return self._namespace_resource

@validate_and_convert_errors
async def upsert(
self,
Expand Down Expand Up @@ -650,5 +668,23 @@ async def cancel_import(self, id: str):
"""
return await self.bulk_import.cancel(id=id)

@validate_and_convert_errors
async def describe_namespace(self, namespace: str) -> "NamespaceDescription":
return await self.namespace.describe(namespace=namespace)

@validate_and_convert_errors
async def delete_namespace(self, namespace: str) -> Dict[str, Any]:
return await self.namespace.delete(namespace=namespace)

@validate_and_convert_errors
async def list_namespaces(self, **kwargs) -> AsyncIterator[ListNamespacesResponse]:
async for namespace in self.namespace.list(**kwargs):
yield namespace

@validate_and_convert_errors
async def list_namespaces_paginated(
self, limit: Optional[int] = None, pagination_token: Optional[str] = None
) -> ListNamespacesResponse:
return await self.namespace.list_paginated(limit=limit, pagination_token=pagination_token)

IndexAsyncio = _IndexAsyncio
78 changes: 77 additions & 1 deletion pinecone/db_data/index_asyncio_interface.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from abc import ABC, abstractmethod
from typing import Union, List, Optional, Dict, Any
from typing import Union, List, Optional, Dict, Any, AsyncIterator

from pinecone.core.openapi.db_data.models import (
FetchResponse,
Expand All @@ -10,6 +10,8 @@
ListResponse,
SparseValues,
SearchRecordsResponse,
NamespaceDescription,
ListNamespacesResponse,
)
from .query_results_aggregator import QueryNamespacesResults
from .types import (
Expand Down Expand Up @@ -810,3 +812,77 @@ async def search_records(
) -> SearchRecordsResponse:
"""Alias of the search() method."""
pass

@abstractmethod
async def describe_namespace(
self,
namespace: str
) -> NamespaceDescription:
"""Describe a namespace within an index, showing the vector count within the namespace.

Args:
namespace (str): The namespace to describe

Returns:
NamespaceDescription: Information about the namespace including vector count
"""
pass

@abstractmethod
async def delete_namespace(
self,
namespace: str
) -> Dict[str, Any]:
"""Delete a namespace from an index.

Args:
namespace (str): The namespace to delete

Returns:
Dict[str, Any]: Response from the delete operation
"""
pass

@abstractmethod
async def list_namespaces(
self, **kwargs
) -> AsyncIterator[ListNamespacesResponse]:
"""List all namespaces in an index. This method automatically handles pagination to return all results.

Args:
limit (Optional[int]): The maximum number of namespaces to return. If unspecified, the server will use a default value. [optional]

Returns:
`ListNamespacesResponse`: Object containing the list of namespaces.

Examples:
>>> async for namespace in index.list_namespaces(limit=5):
... print(f"Namespace: {namespace.name}, Vector count: {namespace.vector_count}")
Namespace: namespace1, Vector count: 1000
Namespace: namespace2, Vector count: 2000
"""
pass

@abstractmethod
async def list_namespaces_paginated(
self, limit: Optional[int] = None, pagination_token: Optional[str] = None
) -> ListNamespacesResponse:
"""List all namespaces in an index with pagination support. The response includes pagination information if there are more results available.

Consider using the `list_namespaces` method to avoid having to handle pagination tokens manually.

Args:
limit (Optional[int]): The maximum number of namespaces to return. If unspecified, the server will use a default value. [optional]
pagination_token (Optional[str]): A token needed to fetch the next page of results. This token is returned
in the response if additional results are available. [optional]

Returns:
`ListNamespacesResponse`: Object containing the list of namespaces and pagination information.

Examples:
>>> results = await index.list_namespaces_paginated(limit=5)
>>> results.pagination.next
eyJza2lwX3Bhc3QiOiI5OTMiLCJwcmVmaXgiOiI5OSJ9
>>> next_results = await index.list_namespaces_paginated(limit=5, pagination_token=results.pagination.next)
"""
pass
73 changes: 72 additions & 1 deletion pinecone/db_data/interfaces.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from abc import ABC, abstractmethod
from typing import Union, List, Optional, Dict, Any
from typing import Union, List, Optional, Dict, Any, Iterator

from pinecone.core.openapi.db_data.models import (
FetchResponse,
Expand All @@ -10,6 +10,8 @@
ListResponse,
SparseValues,
SearchRecordsResponse,
NamespaceDescription,
ListNamespacesResponse,
)
from .query_results_aggregator import QueryNamespacesResults
from multiprocessing.pool import ApplyResult
Expand Down Expand Up @@ -790,3 +792,72 @@ def list(self, **kwargs):
namespace (Optional[str]): The namespace to fetch vectors from. If not specified, the default namespace is used. [optional]
"""
pass

@abstractmethod
def describe_namespace(self, namespace: str) -> NamespaceDescription:
"""Describe a namespace within an index, showing the vector count within the namespace.

Args:
namespace (str): The namespace to describe
**kwargs: Additional arguments to pass to the API call

Returns:
NamespaceDescription: Information about the namespace including vector count
"""
pass

@abstractmethod
def delete_namespace(self, namespace: str) -> Dict[str, Any]:
"""Delete a namespace from an index.

Args:
namespace (str): The namespace to delete
**kwargs: Additional arguments to pass to the API call

Returns:
Dict[str, Any]: Response from the delete operation
"""
pass

@abstractmethod
def list_namespaces(self, **kwargs) -> Iterator[ListNamespacesResponse]:
"""List all namespaces in an index. This method automatically handles pagination to return all results.

Args:
limit (Optional[int]): The maximum number of namespaces to return. If unspecified, the server will use a default value. [optional]

Returns:
`ListNamespacesResponse`: Object containing the list of namespaces.

Examples:
>>> results = list(index.list_namespaces(limit=5))
>>> for namespace in results:
... print(f"Namespace: {namespace.name}, Vector count: {namespace.vector_count}")
Namespace: namespace1, Vector count: 1000
Namespace: namespace2, Vector count: 2000
"""
pass

@abstractmethod
def list_namespaces_paginated(
self, limit: Optional[int] = None, pagination_token: Optional[str] = None
) -> ListNamespacesResponse:
"""List all namespaces in an index with pagination support. The response includes pagination information if there are more results available.

Consider using the `list_namespaces` method to avoid having to handle pagination tokens manually.

Args:
limit (Optional[int]): The maximum number of namespaces to return. If unspecified, the server will use a default value. [optional]
pagination_token (Optional[str]): A token needed to fetch the next page of results. This token is returned
in the response if additional results are available. [optional]

Returns:
`ListNamespacesResponse`: Object containing the list of namespaces and pagination information.

Examples:
>>> results = index.list_namespaces_paginated(limit=5)
>>> results.pagination.next
eyJza2lwX3Bhc3QiOiI5OTMiLCJwcmVmaXgiOiI5OSJ9
>>> next_results = index.list_namespaces_paginated(limit=5, pagination_token=results.pagination.next)
"""
pass
Loading