Skip to content

Commit

Permalink
remove all 'unsupported' clutter; implement find_one (a/sync) (#235)
Browse files Browse the repository at this point in the history
* remove all 'unsupported' clutter; implement find_one (a/sync)

* dotenv example in readme
  • Loading branch information
hemidactylus committed Mar 5, 2024
1 parent 89209de commit 37c94df
Show file tree
Hide file tree
Showing 13 changed files with 255 additions and 418 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -384,18 +384,19 @@ poetry run black --check tests && poetry run ruff tests && poetry run mypy tests

### Testing

Ensure you provide all required environment variables (you can do so by editing `tests/.env` after `tests/.env.template`):
Ensure you provide all required environment variables (you can start from `tests/.env.template`):

```bash
export ASTRA_DB_APPLICATION_TOKEN="..."
export ASTRA_DB_API_ENDPOINT="..."
export ASTRA_DB_KEYSPACE="..." # Optional
export ASTRA_DB_SECONDARY_KEYSPACE="..." # Optional, enables cross-ns testing

export ASTRA_DB_ID="..." # For the Ops testing only
export ASTRA_DB_OPS_APPLICATION_TOKEN="..." # Ops-only, falls back to the other token
```

then you can run:
then you can source the `.env` you created and finally run:

```bash
poetry run pytest
Expand Down
234 changes: 46 additions & 188 deletions astrapy/idiomatic/collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@
from __future__ import annotations

import json
from typing import Any, Dict, Iterable, List, Optional
from typing import Any, Dict, Iterable, List, Optional, Union

from astrapy.db import AstraDBCollection, AsyncAstraDBCollection
from astrapy.idiomatic.types import DocumentType, ProjectionType
from astrapy.idiomatic.utils import raise_unsupported_parameter, unsupported
from astrapy.idiomatic.database import AsyncDatabase, Database
from astrapy.idiomatic.results import DeleteResult, InsertManyResult, InsertOneResult
from astrapy.idiomatic.cursors import AsyncCursor, Cursor


INSERT_MANY_CONCURRENCY = 20


Expand Down Expand Up @@ -115,15 +115,7 @@ def set_caller(
def insert_one(
self,
document: DocumentType,
*,
bypass_document_validation: Optional[bool] = None,
) -> InsertOneResult:
if bypass_document_validation:
raise_unsupported_parameter(
class_name=self.__class__.__name__,
method_name="insert_one",
parameter_name="bypass_document_validation",
)
io_response = self._astra_db_collection.insert_one(document)
if "insertedIds" in io_response.get("status", {}):
if io_response["status"]["insertedIds"]:
Expand All @@ -147,14 +139,7 @@ def insert_many(
documents: Iterable[DocumentType],
*,
ordered: bool = True,
bypass_document_validation: Optional[bool] = None,
) -> InsertManyResult:
if bypass_document_validation:
raise_unsupported_parameter(
class_name=self.__class__.__name__,
method_name="insert_many",
parameter_name="bypass_document_validation",
)
if ordered:
cim_responses = self._astra_db_collection.chunked_insert_many(
documents=list(documents),
Expand Down Expand Up @@ -210,6 +195,28 @@ def find(
.sort(sort)
)

def find_one(
self,
filter: Optional[Dict[str, Any]] = None,
*,
projection: Optional[ProjectionType] = None,
skip: Optional[int] = None,
limit: Optional[int] = None,
sort: Optional[Dict[str, Any]] = None,
) -> Union[DocumentType, None]:
fo_cursor = self.find(
filter=filter,
projection=projection,
skip=skip,
limit=limit,
sort=sort,
)
try:
document = fo_cursor.__next__()
return document
except StopIteration:
return None

def distinct(
self,
key: str,
Expand All @@ -223,22 +230,7 @@ def distinct(
def count_documents(
self,
filter: Dict[str, Any],
*,
skip: Optional[int] = None,
limit: Optional[int] = None,
) -> int:
if skip:
raise_unsupported_parameter(
class_name=self.__class__.__name__,
method_name="count_documents",
parameter_name="skip",
)
if limit:
raise_unsupported_parameter(
class_name=self.__class__.__name__,
method_name="count_documents",
parameter_name="limit",
)
cd_response = self._astra_db_collection.count_documents(filter=filter)
if "count" in cd_response.get("status", {}):
return cd_response["status"]["count"] # type: ignore[no-any-return]
Expand All @@ -251,15 +243,7 @@ def count_documents(
def delete_one(
self,
filter: Dict[str, Any],
*,
let: Optional[int] = None,
) -> DeleteResult:
if let:
raise_unsupported_parameter(
class_name=self.__class__.__name__,
method_name="delete_one",
parameter_name="let",
)
do_response = self._astra_db_collection.delete_one_by_predicate(filter=filter)
if "deletedCount" in do_response.get("status", {}):
deleted_count = do_response["status"]["deletedCount"]
Expand All @@ -283,15 +267,7 @@ def delete_one(
def delete_many(
self,
filter: Dict[str, Any],
*,
let: Optional[int] = None,
) -> DeleteResult:
if let:
raise_unsupported_parameter(
class_name=self.__class__.__name__,
method_name="delete_many",
parameter_name="let",
)
dm_response = self._astra_db_collection.delete_many(filter=filter)
if "deletedCount" in dm_response.get("status", {}):
deleted_count = dm_response["status"]["deletedCount"]
Expand All @@ -312,54 +288,6 @@ def delete_many(
f"(gotten '${json.dumps(dm_response)}')"
)

@unsupported
def find_raw_batches(*pargs: Any, **kwargs: Any) -> Any: ...

@unsupported
def aggregate(*pargs: Any, **kwargs: Any) -> Any: ...

@unsupported
def aggregate_raw_batches(*pargs: Any, **kwargs: Any) -> Any: ...

@unsupported
def watch(*pargs: Any, **kwargs: Any) -> Any: ...

@unsupported
def rename(*pargs: Any, **kwargs: Any) -> Any: ...

@unsupported
def create_index(*pargs: Any, **kwargs: Any) -> Any: ...

@unsupported
def create_indexes(*pargs: Any, **kwargs: Any) -> Any: ...

@unsupported
def drop_index(*pargs: Any, **kwargs: Any) -> Any: ...

@unsupported
def drop_indexes(*pargs: Any, **kwargs: Any) -> Any: ...

@unsupported
def list_indexes(*pargs: Any, **kwargs: Any) -> Any: ...

@unsupported
def index_information(*pargs: Any, **kwargs: Any) -> Any: ...

@unsupported
def create_search_index(*pargs: Any, **kwargs: Any) -> Any: ...

@unsupported
def create_search_indexes(*pargs: Any, **kwargs: Any) -> Any: ...

@unsupported
def drop_search_index(*pargs: Any, **kwargs: Any) -> Any: ...

@unsupported
def list_search_indexes(*pargs: Any, **kwargs: Any) -> Any: ...

@unsupported
def update_search_index(*pargs: Any, **kwargs: Any) -> Any: ...


class AsyncCollection:
def __init__(
Expand Down Expand Up @@ -449,15 +377,7 @@ def set_caller(
async def insert_one(
self,
document: DocumentType,
*,
bypass_document_validation: Optional[bool] = None,
) -> InsertOneResult:
if bypass_document_validation:
raise_unsupported_parameter(
class_name=self.__class__.__name__,
method_name="insert_one",
parameter_name="bypass_document_validation",
)
io_response = await self._astra_db_collection.insert_one(document)
if "insertedIds" in io_response.get("status", {}):
if io_response["status"]["insertedIds"]:
Expand All @@ -481,14 +401,7 @@ async def insert_many(
documents: Iterable[DocumentType],
*,
ordered: bool = True,
bypass_document_validation: Optional[bool] = None,
) -> InsertManyResult:
if bypass_document_validation:
raise_unsupported_parameter(
class_name=self.__class__.__name__,
method_name="insert_many",
parameter_name="bypass_document_validation",
)
if ordered:
cim_responses = await self._astra_db_collection.chunked_insert_many(
documents=list(documents),
Expand Down Expand Up @@ -544,6 +457,28 @@ def find(
.sort(sort)
)

async def find_one(
self,
filter: Optional[Dict[str, Any]] = None,
*,
projection: Optional[ProjectionType] = None,
skip: Optional[int] = None,
limit: Optional[int] = None,
sort: Optional[Dict[str, Any]] = None,
) -> Union[DocumentType, None]:
fo_cursor = self.find(
filter=filter,
projection=projection,
skip=skip,
limit=limit,
sort=sort,
)
try:
document = await fo_cursor.__anext__()
return document
except StopAsyncIteration:
return None

async def distinct(
self,
key: str,
Expand All @@ -558,22 +493,7 @@ async def distinct(
async def count_documents(
self,
filter: Dict[str, Any],
*,
skip: Optional[int] = None,
limit: Optional[int] = None,
) -> int:
if skip:
raise_unsupported_parameter(
class_name=self.__class__.__name__,
method_name="count_documents",
parameter_name="skip",
)
if limit:
raise_unsupported_parameter(
class_name=self.__class__.__name__,
method_name="count_documents",
parameter_name="limit",
)
cd_response = await self._astra_db_collection.count_documents(filter=filter)
if "count" in cd_response.get("status", {}):
return cd_response["status"]["count"] # type: ignore[no-any-return]
Expand All @@ -586,15 +506,7 @@ async def count_documents(
async def delete_one(
self,
filter: Dict[str, Any],
*,
let: Optional[int] = None,
) -> DeleteResult:
if let:
raise_unsupported_parameter(
class_name=self.__class__.__name__,
method_name="delete_one",
parameter_name="let",
)
do_response = await self._astra_db_collection.delete_one_by_predicate(
filter=filter
)
Expand Down Expand Up @@ -623,12 +535,6 @@ async def delete_many(
*,
let: Optional[int] = None,
) -> DeleteResult:
if let:
raise_unsupported_parameter(
class_name=self.__class__.__name__,
method_name="delete_many",
parameter_name="let",
)
dm_response = await self._astra_db_collection.delete_many(filter=filter)
if "deletedCount" in dm_response.get("status", {}):
deleted_count = dm_response["status"]["deletedCount"]
Expand All @@ -648,51 +554,3 @@ async def delete_many(
"Could not complete a delete_many operation. "
f"(gotten '${json.dumps(dm_response)}')"
)

@unsupported
async def find_raw_batches(*pargs: Any, **kwargs: Any) -> Any: ...

@unsupported
async def aggregate(*pargs: Any, **kwargs: Any) -> Any: ...

@unsupported
async def aggregate_raw_batches(*pargs: Any, **kwargs: Any) -> Any: ...

@unsupported
async def watch(*pargs: Any, **kwargs: Any) -> Any: ...

@unsupported
async def rename(*pargs: Any, **kwargs: Any) -> Any: ...

@unsupported
async def create_index(*pargs: Any, **kwargs: Any) -> Any: ...

@unsupported
async def create_indexes(*pargs: Any, **kwargs: Any) -> Any: ...

@unsupported
async def drop_index(*pargs: Any, **kwargs: Any) -> Any: ...

@unsupported
async def drop_indexes(*pargs: Any, **kwargs: Any) -> Any: ...

@unsupported
async def list_indexes(*pargs: Any, **kwargs: Any) -> Any: ...

@unsupported
async def index_information(*pargs: Any, **kwargs: Any) -> Any: ...

@unsupported
async def create_search_index(*pargs: Any, **kwargs: Any) -> Any: ...

@unsupported
async def create_search_indexes(*pargs: Any, **kwargs: Any) -> Any: ...

@unsupported
async def drop_search_index(*pargs: Any, **kwargs: Any) -> Any: ...

@unsupported
async def list_search_indexes(*pargs: Any, **kwargs: Any) -> Any: ...

@unsupported
async def update_search_index(*pargs: Any, **kwargs: Any) -> Any: ...
Loading

0 comments on commit 37c94df

Please sign in to comment.