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

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions pinecone/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
"QueryResponse": ("pinecone.db_data.models", "QueryResponse"),
"UpsertResponse": ("pinecone.db_data.models", "UpsertResponse"),
"UpdateRequest": ("pinecone.db_data.models", "UpdateRequest"),
"NamespaceDescription": ("pinecone.core.openapi.db_data.models", "NamespaceDescription"),
"ImportErrorMode": ("pinecone.db_data.resources.sync.bulk_import", "ImportErrorMode"),
"VectorDictionaryMissingKeysError": (
"pinecone.db_data.errors",
Expand Down
2 changes: 2 additions & 0 deletions pinecone/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ from pinecone.db_data.models import (
UpsertResponse,
UpdateRequest,
)
from pinecone.core.openapi.db_data.models import NamespaceDescription
from pinecone.db_data.resources.sync.bulk_import import ImportErrorMode
from pinecone.db_data.errors import (
VectorDictionaryMissingKeysError,
Expand Down Expand Up @@ -130,6 +131,7 @@ __all__ = [
"QueryResponse",
"UpsertResponse",
"UpdateRequest",
"NamespaceDescription",
"ImportErrorMode",
# Error classes
"VectorDictionaryMissingKeysError",
Expand Down
48 changes: 48 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 All @@ -35,6 +37,7 @@
validate_and_convert_errors,
filter_dict,
PluginAware,
require_kwargs,
)
from .query_results_aggregator import QueryResultsAggregator, QueryNamespacesResults
from pinecone.openapi_support import OPENAPI_ENDPOINT_PARAMS
Expand All @@ -47,6 +50,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 +79,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 +122,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 +162,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 +629,27 @@ 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
@require_kwargs
def describe_namespace(self, namespace: str) -> "NamespaceDescription":
return self.namespace.describe(namespace=namespace)

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

@validate_and_convert_errors
@require_kwargs
def list_namespaces(
self, limit: Optional[int] = None, **kwargs
) -> Iterator[ListNamespacesResponse]:
return self.namespace.list(limit=limit, **kwargs)

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

from ..utils import (
setup_async_openapi_client,
parse_non_empty_args,
validate_and_convert_errors,
filter_dict,
require_kwargs,
)
from .types import (
SparseVectorTypedDict,
Expand All @@ -50,6 +53,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 +144,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 +180,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 +251,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 +669,29 @@ async def cancel_import(self, id: str):
"""
return await self.bulk_import.cancel(id=id)

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

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

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

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

IndexAsyncio = _IndexAsyncio
85 changes: 84 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 All @@ -23,6 +25,7 @@
SearchRerankTypedDict,
)
from .dataclasses import SearchQuery, SearchRerank
from pinecone.utils import require_kwargs


class IndexAsyncioInterface(ABC):
Expand Down Expand Up @@ -810,3 +813,83 @@ async def search_records(
) -> SearchRecordsResponse:
"""Alias of the search() method."""
pass

@abstractmethod
@require_kwargs
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
@require_kwargs
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
@require_kwargs
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:
.. code-block:: python
>>> 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
@require_kwargs
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:
.. code-block:: python
>>> 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
Loading