mirror of
https://github.com/deepset-ai/haystack.git
synced 2025-11-11 15:23:41 +00:00
Add Store class factory (#5530)
* Add Store class factory * Add release notes
This commit is contained in:
parent
ff86af576a
commit
83fce1bd72
0
haystack/preview/testing/__init__.py
Normal file
0
haystack/preview/testing/__init__.py
Normal file
114
haystack/preview/testing/factory.py
Normal file
114
haystack/preview/testing/factory.py
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
from typing import Any, Dict, Optional, Tuple, Type, List
|
||||||
|
|
||||||
|
from haystack.preview.dataclasses import Document
|
||||||
|
from haystack.preview.document_stores import store, Store, DuplicatePolicy
|
||||||
|
|
||||||
|
|
||||||
|
def store_class(
|
||||||
|
name: str,
|
||||||
|
documents: Optional[List[Document]] = None,
|
||||||
|
documents_count: Optional[int] = None,
|
||||||
|
bases: Optional[Tuple[type, ...]] = None,
|
||||||
|
extra_fields: Optional[Dict[str, Any]] = None,
|
||||||
|
) -> Type[Store]:
|
||||||
|
"""
|
||||||
|
Utility function to create a Store class with the given name and list of documents.
|
||||||
|
|
||||||
|
If `documents` is set but `documents_count` is not, `documents_count` will be the length
|
||||||
|
of `documents`.
|
||||||
|
If both are set explicitly they don't influence each other.
|
||||||
|
|
||||||
|
`write_documents()` and `delete_documents()` are no-op.
|
||||||
|
You can override them using `extra_fields`.
|
||||||
|
|
||||||
|
### Usage
|
||||||
|
|
||||||
|
Create a store class that returns no documents:
|
||||||
|
```python
|
||||||
|
MyFakeStore = store_class("MyFakeComponent")
|
||||||
|
store = MyFakeStore()
|
||||||
|
assert store.documents_count() == 0
|
||||||
|
assert store.filter_documents() == []
|
||||||
|
```
|
||||||
|
|
||||||
|
Create a store class that returns a single document:
|
||||||
|
```python
|
||||||
|
doc = Document(id="fake_id", content="Fake content")
|
||||||
|
MyFakeStore = store_class("MyFakeComponent", documents=[doc])
|
||||||
|
store = MyFakeStore()
|
||||||
|
assert store.documents_count() == 1
|
||||||
|
assert store.filter_documents() == [doc]
|
||||||
|
```
|
||||||
|
|
||||||
|
Create a store class that returns no document but returns a custom count:
|
||||||
|
```python
|
||||||
|
MyFakeStore = store_class("MyFakeComponent", documents_count=100)
|
||||||
|
store = MyFakeStore()
|
||||||
|
assert store.documents_count() == 100
|
||||||
|
assert store.filter_documents() == []
|
||||||
|
```
|
||||||
|
|
||||||
|
Create a store class that returns a document and a custom count:
|
||||||
|
```python
|
||||||
|
doc = Document(id="fake_id", content="Fake content")
|
||||||
|
MyFakeStore = store_class("MyFakeComponent", documents=[doc], documents_count=100)
|
||||||
|
store = MyFakeStore()
|
||||||
|
assert store.documents_count() == 100
|
||||||
|
assert store.filter_documents() == [doc]
|
||||||
|
```
|
||||||
|
|
||||||
|
Create a store class with a custom base class:
|
||||||
|
```python
|
||||||
|
MyFakeStore = store_class(
|
||||||
|
"MyFakeStore",
|
||||||
|
bases=(MyBaseClass,)
|
||||||
|
)
|
||||||
|
store = MyFakeStore()
|
||||||
|
assert isinstance(store, MyBaseClass)
|
||||||
|
```
|
||||||
|
|
||||||
|
Create a store class with an extra field `my_field`:
|
||||||
|
```python
|
||||||
|
MyFakeStore = store_class(
|
||||||
|
"MyFakeStore",
|
||||||
|
extra_fields={"my_field": 10}
|
||||||
|
)
|
||||||
|
store = MyFakeStore()
|
||||||
|
assert store.my_field == 10
|
||||||
|
```
|
||||||
|
"""
|
||||||
|
|
||||||
|
if documents is not None and documents_count is None:
|
||||||
|
documents_count = len(documents)
|
||||||
|
elif documents_count is None:
|
||||||
|
documents_count = 0
|
||||||
|
|
||||||
|
def count_documents(self) -> int:
|
||||||
|
return documents_count
|
||||||
|
|
||||||
|
def filter_documents(self, filters: Optional[Dict[str, Any]] = None) -> List[Document]:
|
||||||
|
if documents is not None:
|
||||||
|
return documents
|
||||||
|
return []
|
||||||
|
|
||||||
|
def write_documents(self, documents: List[Document], policy: DuplicatePolicy = DuplicatePolicy.FAIL) -> None:
|
||||||
|
return
|
||||||
|
|
||||||
|
def delete_documents(self, document_ids: List[str]) -> None:
|
||||||
|
return
|
||||||
|
|
||||||
|
fields = {
|
||||||
|
"count_documents": count_documents,
|
||||||
|
"filter_documents": filter_documents,
|
||||||
|
"write_documents": write_documents,
|
||||||
|
"delete_documents": delete_documents,
|
||||||
|
}
|
||||||
|
|
||||||
|
if extra_fields is not None:
|
||||||
|
fields = {**fields, **extra_fields}
|
||||||
|
|
||||||
|
if bases is None:
|
||||||
|
bases = (object,)
|
||||||
|
|
||||||
|
cls = type(name, bases, fields)
|
||||||
|
return store(cls)
|
||||||
4
releasenotes/notes/store-factory-91e7da46aeb7ff21.yaml
Normal file
4
releasenotes/notes/store-factory-91e7da46aeb7ff21.yaml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Add utility function `store_class` factory to create `Store`s for testing purposes.
|
||||||
61
test/preview/testing/test_factory.py
Normal file
61
test/preview/testing/test_factory.py
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
import pytest
|
||||||
|
|
||||||
|
from haystack.preview.dataclasses import Document
|
||||||
|
from haystack.preview.testing.factory import store_class
|
||||||
|
from haystack.preview.document_stores.decorator import store
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.unit
|
||||||
|
def test_store_class_default():
|
||||||
|
MyStore = store_class("MyStore")
|
||||||
|
store = MyStore()
|
||||||
|
assert store.count_documents() == 0
|
||||||
|
assert store.filter_documents() == []
|
||||||
|
assert store.write_documents([]) is None
|
||||||
|
assert store.delete_documents([]) is None
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.unit
|
||||||
|
def test_store_class_is_registered():
|
||||||
|
MyStore = store_class("MyStore")
|
||||||
|
assert store.registry["MyStore"] == MyStore
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.unit
|
||||||
|
def test_store_class_with_documents():
|
||||||
|
doc = Document(id="fake_id", content="This is a document")
|
||||||
|
MyStore = store_class("MyStore", documents=[doc])
|
||||||
|
store = MyStore()
|
||||||
|
assert store.count_documents() == 1
|
||||||
|
assert store.filter_documents() == [doc]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.unit
|
||||||
|
def test_store_class_with_documents_count():
|
||||||
|
MyStore = store_class("MyStore", documents_count=100)
|
||||||
|
store = MyStore()
|
||||||
|
assert store.count_documents() == 100
|
||||||
|
assert store.filter_documents() == []
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.unit
|
||||||
|
def test_store_class_with_documents_and_documents_count():
|
||||||
|
doc = Document(id="fake_id", content="This is a document")
|
||||||
|
MyStore = store_class("MyStore", documents=[doc], documents_count=100)
|
||||||
|
store = MyStore()
|
||||||
|
assert store.count_documents() == 100
|
||||||
|
assert store.filter_documents() == [doc]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.unit
|
||||||
|
def test_store_class_with_bases():
|
||||||
|
MyStore = store_class("MyStore", bases=(Exception,))
|
||||||
|
store = MyStore()
|
||||||
|
assert isinstance(store, Exception)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.unit
|
||||||
|
def test_store_class_with_extra_fields():
|
||||||
|
MyStore = store_class("MyStore", extra_fields={"my_field": 10})
|
||||||
|
store = MyStore()
|
||||||
|
assert store.my_field == 10
|
||||||
Loading…
x
Reference in New Issue
Block a user