-
Notifications
You must be signed in to change notification settings - Fork 238
test(sqlite): add more test to cover sqlite backend #81
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
Changes from all commits
Commits
Show all changes
43 commits
Select commit
Hold shift + click to select a range
ae41e6d
test(sqlite): add more test to cover sqlite backend
hanxiao b208bc4
fix: adapt embedding setters for storage backends
alaeddine-13 863d864
test: cover embeddings setter
alaeddine-13 c8c0c99
fix: texts setter
alaeddine-13 26b5edc
fix: tensors and blob setters
alaeddine-13 8683901
fix: linting
alaeddine-13 a3ca29f
fix: embed for sqlite backend
alaeddine-13 aef8979
refactor: delegate to __setitem__ in content setters
alaeddine-13 8bae8d5
fix: linting
alaeddine-13 be13b62
test: cover set attributes with size 1
alaeddine-13 bb97b2a
fix: fix set attributes with size 1
alaeddine-13 caa2b9d
feat: add batching by id
davidbp bf0e769
feat: add batching by id
davidbp bccd9ab
fix: change protocol to protobuf in sqlite
davidbp 99da09f
fix: fix setter by sequences
alaeddine-13 be82921
test: text type should be string not integer
alaeddine-13 ceebf56
test: cover ellipsis getter
alaeddine-13 728dc56
feat: raise index error when mask size is not equal to length
alaeddine-13 bfcf784
fix: setitem raise IndexError properly
alaeddine-13 ec6e642
test: cover mask with incorrect length
alaeddine-13 83c5428
test: cover setting docs by mask
alaeddine-13 5d71a0b
test: cover ValueError raised on wrong number of elements
alaeddine-13 93b377d
refactor: remove unreachable code
alaeddine-13 19a673e
test: fix test_single_boolean_and_padding
alaeddine-13 8abfca0
chore: remove unused method
alaeddine-13 b0c2631
fix: merge conflicts
alaeddine-13 14b025f
Merge branch 'main' into tests-sqlite
alaeddine-13 a7a8efa
refactor: refactor setitem
alaeddine-13 f1e07b9
test: fix tests
alaeddine-13 9b8bd3c
test: fix tests
alaeddine-13 7a8abd3
feat: handle set traversal paths
alaeddine-13 8712de6
test: fix tests
alaeddine-13 b1cad20
test: fix tests
alaeddine-13 883139f
test: fix tests
alaeddine-13 71b8102
test: fix tests
alaeddine-13 8b92a1f
refactor: remove _default_protocol
alaeddine-13 7b380f4
chore: apply suggestions
alaeddine-13 c45a632
fix: protobuf-array as default protocol for sqlite
alaeddine-13 75eecad
chore: apply suggestions
alaeddine-13 00f2ee5
fix: fix _set_doc_value_pairs and empty chunks after flatten
alaeddine-13 7be25b7
fix: use separate method _set_doc_value_pairs_nested
alaeddine-13 30ee9a8
fix: add flattened flag to DocumentArray after flattening
alaeddine-13 459b6c8
feat: do not allow setting by traversal paths with diff ID
alaeddine-13 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
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
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
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -68,135 +68,28 @@ def __setitem__( | |||||||||||||||||||||||||||
| self._set_doc_by_offset(int(index), value) | ||||||||||||||||||||||||||||
| elif isinstance(index, str): | ||||||||||||||||||||||||||||
| if index.startswith('@'): | ||||||||||||||||||||||||||||
| self._set_doc_value_pairs(self.traverse_flat(index[1:]), value) | ||||||||||||||||||||||||||||
| self._set_doc_value_pairs_nested(self.traverse_flat(index[1:]), value) | ||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||
| self._set_doc_by_id(index, value) | ||||||||||||||||||||||||||||
| elif isinstance(index, slice): | ||||||||||||||||||||||||||||
| self._set_docs_by_slice(index, value) | ||||||||||||||||||||||||||||
| elif index is Ellipsis: | ||||||||||||||||||||||||||||
| self._set_doc_value_pairs(self.flatten(), value) | ||||||||||||||||||||||||||||
| elif isinstance(index, Sequence): | ||||||||||||||||||||||||||||
| if ( | ||||||||||||||||||||||||||||
| isinstance(index, tuple) | ||||||||||||||||||||||||||||
| and len(index) == 2 | ||||||||||||||||||||||||||||
| and ( | ||||||||||||||||||||||||||||
| isinstance(index[0], (slice, Sequence, str, int)) | ||||||||||||||||||||||||||||
| or index[0] is Ellipsis | ||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||
| and isinstance(index[1], (str, Sequence)) | ||||||||||||||||||||||||||||
| ): | ||||||||||||||||||||||||||||
| # TODO: this is added because we are still trying to figure out the proper way | ||||||||||||||||||||||||||||
| # to set attribute and to get test_path_syntax_indexing_set to pass. | ||||||||||||||||||||||||||||
| # we may have to refactor the following logic | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| # NOTE: this check is not proper way to handle, but a temporary hack. | ||||||||||||||||||||||||||||
| # writing it this way to minimize effect on other docarray classs and | ||||||||||||||||||||||||||||
| # to make it easier to remove/refactor the following block | ||||||||||||||||||||||||||||
| if self.__class__.__name__ in { | ||||||||||||||||||||||||||||
| 'DocumentArrayWeaviate', | ||||||||||||||||||||||||||||
| 'DocumentArrayInMemory', | ||||||||||||||||||||||||||||
| }: | ||||||||||||||||||||||||||||
| from ..memory import DocumentArrayInMemory | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| if index[1] in self: | ||||||||||||||||||||||||||||
| # we first handle the case when second item in index is an id not attr | ||||||||||||||||||||||||||||
| _docs = DocumentArrayInMemory( | ||||||||||||||||||||||||||||
| self[index[0]] | ||||||||||||||||||||||||||||
| ) + DocumentArrayInMemory(self[index[1]]) | ||||||||||||||||||||||||||||
| self._set_doc_value_pairs(_docs, value) | ||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| _docs = self[index[0]] | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| if not _docs: | ||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| if isinstance(_docs, Document): | ||||||||||||||||||||||||||||
| _docs = DocumentArrayInMemory(_docs) | ||||||||||||||||||||||||||||
| # because we've augmented docs dimension, we do the same for value | ||||||||||||||||||||||||||||
| value = (value,) | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| attrs = index[1] | ||||||||||||||||||||||||||||
| if isinstance(attrs, str): | ||||||||||||||||||||||||||||
| attrs = (attrs,) | ||||||||||||||||||||||||||||
| # because we've augmented attrs dimension, we do the same for value | ||||||||||||||||||||||||||||
| value = (value,) | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| for attr in attrs: | ||||||||||||||||||||||||||||
| if not hasattr(_docs[0], attr): | ||||||||||||||||||||||||||||
| raise ValueError( | ||||||||||||||||||||||||||||
| f'`{attr}` is neither a valid id nor attribute name' | ||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| for _a, _v in zip(attrs, value): | ||||||||||||||||||||||||||||
| self._set_docs_attrs(_docs, _a, _v) | ||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| if isinstance(index[0], str) and isinstance(index[1], str): | ||||||||||||||||||||||||||||
| # ambiguity only comes from the second string | ||||||||||||||||||||||||||||
| if index[1] in self: | ||||||||||||||||||||||||||||
| self._set_doc_value_pairs( | ||||||||||||||||||||||||||||
| (self[index[0]], self[index[1]]), value | ||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||
| elif hasattr(self[index[0]], index[1]): | ||||||||||||||||||||||||||||
| self._set_doc_attr_by_id(index[0], index[1], value) | ||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||
| # to avoid accidentally add new unsupport attribute | ||||||||||||||||||||||||||||
| raise ValueError( | ||||||||||||||||||||||||||||
| f'`{index[1]}` is neither a valid id nor attribute name' | ||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||
| elif isinstance(index[0], (slice, Sequence)): | ||||||||||||||||||||||||||||
| _attrs = index[1] | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| if isinstance(_attrs, str): | ||||||||||||||||||||||||||||
| # a -> [a] | ||||||||||||||||||||||||||||
| # [a, a] -> [a, a] | ||||||||||||||||||||||||||||
| _attrs = (index[1],) | ||||||||||||||||||||||||||||
| if isinstance(value, (list, tuple)) and not any( | ||||||||||||||||||||||||||||
| isinstance(el, (tuple, list)) for el in value | ||||||||||||||||||||||||||||
| ): | ||||||||||||||||||||||||||||
| # [x] -> [[x]] | ||||||||||||||||||||||||||||
| # [[x], [y]] -> [[x], [y]] | ||||||||||||||||||||||||||||
| value = (value,) | ||||||||||||||||||||||||||||
| if not isinstance(value, (list, tuple)): | ||||||||||||||||||||||||||||
| # x -> [x] | ||||||||||||||||||||||||||||
| value = (value,) | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| _docs = self[index[0]] | ||||||||||||||||||||||||||||
| for _a, _v in zip(_attrs, value): | ||||||||||||||||||||||||||||
| if _a in ('tensor', 'embedding'): | ||||||||||||||||||||||||||||
| if _a == 'tensor': | ||||||||||||||||||||||||||||
| _docs.tensors = _v | ||||||||||||||||||||||||||||
| elif _a == 'embedding': | ||||||||||||||||||||||||||||
| _docs.embeddings = _v | ||||||||||||||||||||||||||||
| for _d in _docs: | ||||||||||||||||||||||||||||
| self._set_doc_by_id(_d.id, _d) | ||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||
| if len(_docs) == 1: | ||||||||||||||||||||||||||||
| self._set_doc_attr_by_id(_docs[0].id, _a, _v) | ||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||
| for _d, _vv in zip(_docs, _v): | ||||||||||||||||||||||||||||
| self._set_doc_attr_by_id(_d.id, _a, _vv) | ||||||||||||||||||||||||||||
| if isinstance(index, tuple) and len(index) == 2: | ||||||||||||||||||||||||||||
| self._set_by_pair(index[0], index[1], value) | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| elif isinstance(index[0], bool): | ||||||||||||||||||||||||||||
| if len(index) != len(self): | ||||||||||||||||||||||||||||
| raise IndexError( | ||||||||||||||||||||||||||||
| f'Boolean mask index is required to have the same length as {len(self._data)}, ' | ||||||||||||||||||||||||||||
| f'but receiving {len(index)}' | ||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||
| _selected = itertools.compress(self, index) | ||||||||||||||||||||||||||||
| self._set_doc_value_pairs(_selected, value) | ||||||||||||||||||||||||||||
| self._set_by_mask(index, value) | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| elif isinstance(index[0], (int, str)): | ||||||||||||||||||||||||||||
| if not isinstance(value, Sequence) or len(index) != len(value): | ||||||||||||||||||||||||||||
| raise ValueError( | ||||||||||||||||||||||||||||
| f'Number of elements for assigning must be ' | ||||||||||||||||||||||||||||
| f'the same as the index length: {len(index)}' | ||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||
| if isinstance(value, Document): | ||||||||||||||||||||||||||||
| for si in index: | ||||||||||||||||||||||||||||
| self[si] = value # leverage existing setter | ||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||
| for si, _val in zip(index, value): | ||||||||||||||||||||||||||||
| self[si] = _val # leverage existing setter | ||||||||||||||||||||||||||||
| for si, _val in zip(index, value): | ||||||||||||||||||||||||||||
| self[si] = _val # leverage existing setter | ||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||
| raise IndexError( | ||||||||||||||||||||||||||||
| f'{index} should be either a sequence of bool, int or str' | ||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| elif isinstance(index, np.ndarray): | ||||||||||||||||||||||||||||
| index = index.squeeze() | ||||||||||||||||||||||||||||
| if index.ndim == 1: | ||||||||||||||||||||||||||||
|
|
@@ -207,3 +100,103 @@ def __setitem__( | |||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||
| raise IndexError(f'Unsupported index type {typename(index)}: {index}') | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| def _set_by_pair(self, idx1, idx2, value): | ||||||||||||||||||||||||||||
| if isinstance(idx1, str) and not idx1.startswith('@'): | ||||||||||||||||||||||||||||
| # second is an ID | ||||||||||||||||||||||||||||
| if isinstance(idx2, str) and idx2 in self: | ||||||||||||||||||||||||||||
| self._set_doc_value_pairs((self[idx1], self[idx2]), value) | ||||||||||||||||||||||||||||
| # second is an attribute | ||||||||||||||||||||||||||||
| elif isinstance(idx2, str) and hasattr(self[idx1], idx2): | ||||||||||||||||||||||||||||
| self._set_doc_attr_by_id(idx1, idx2, value) | ||||||||||||||||||||||||||||
| # second is a list of attributes: | ||||||||||||||||||||||||||||
| elif ( | ||||||||||||||||||||||||||||
| isinstance(idx2, Sequence) | ||||||||||||||||||||||||||||
| and all(isinstance(attr, str) for attr in idx2) | ||||||||||||||||||||||||||||
| and all(hasattr(self[idx1], attr) for attr in idx2) | ||||||||||||||||||||||||||||
| ): | ||||||||||||||||||||||||||||
| for attr, _v in zip(idx2, value): | ||||||||||||||||||||||||||||
| self._set_doc_attr_by_id(idx1, attr, _v) | ||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||
| raise IndexError(f'`{idx2}` is neither a valid id nor attribute name') | ||||||||||||||||||||||||||||
| elif isinstance(idx1, int): | ||||||||||||||||||||||||||||
| # second is an offset | ||||||||||||||||||||||||||||
| if isinstance(idx2, int): | ||||||||||||||||||||||||||||
| self._set_doc_value_pairs((self[idx1], self[idx2]), value) | ||||||||||||||||||||||||||||
| # second is an attribute | ||||||||||||||||||||||||||||
| elif isinstance(idx2, str) and hasattr(self[idx1], idx2): | ||||||||||||||||||||||||||||
| self._set_doc_attr_by_offset(idx1, idx2, value) | ||||||||||||||||||||||||||||
| # second is a list of attributes: | ||||||||||||||||||||||||||||
| elif ( | ||||||||||||||||||||||||||||
| isinstance(idx2, Sequence) | ||||||||||||||||||||||||||||
| and all(isinstance(attr, str) for attr in idx2) | ||||||||||||||||||||||||||||
| and all(hasattr(self[idx1], attr) for attr in idx2) | ||||||||||||||||||||||||||||
| ): | ||||||||||||||||||||||||||||
| for attr, _v in zip(idx2, value): | ||||||||||||||||||||||||||||
| self._set_doc_attr_by_id(idx1, attr, _v) | ||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||
| raise IndexError(f'`{idx2}` must be an attribute or list of attributes') | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| elif ( | ||||||||||||||||||||||||||||
| isinstance(idx1, (slice, Sequence)) | ||||||||||||||||||||||||||||
| or idx1 is Ellipsis | ||||||||||||||||||||||||||||
| or (isinstance(idx1, str) and idx1.startswith('@')) | ||||||||||||||||||||||||||||
| ): | ||||||||||||||||||||||||||||
| self._set_docs_attributes(idx1, idx2, value) | ||||||||||||||||||||||||||||
| # TODO: else raise error | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| def _set_by_mask(self, mask: List[bool], value): | ||||||||||||||||||||||||||||
| _selected = itertools.compress(self, mask) | ||||||||||||||||||||||||||||
| self._set_doc_value_pairs(_selected, value) | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| def _set_docs_attributes(self, index, attributes, value): | ||||||||||||||||||||||||||||
| # TODO: handle index is Ellipsis | ||||||||||||||||||||||||||||
| if isinstance(attributes, str): | ||||||||||||||||||||||||||||
| # a -> [a] | ||||||||||||||||||||||||||||
| # [a, a] -> [a, a] | ||||||||||||||||||||||||||||
| attributes = (attributes,) | ||||||||||||||||||||||||||||
| value = (value,) | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| if isinstance(index, str) and index.startswith('@'): | ||||||||||||||||||||||||||||
| self._set_docs_attributes_traversal_paths(index, attributes, value) | ||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||
| _docs = self[index] | ||||||||||||||||||||||||||||
| if not _docs: | ||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| for _a, _v in zip(attributes, value): | ||||||||||||||||||||||||||||
| if _a in ('tensor', 'embedding'): | ||||||||||||||||||||||||||||
| if _a == 'tensor': | ||||||||||||||||||||||||||||
| _docs.tensors = _v | ||||||||||||||||||||||||||||
| elif _a == 'embedding': | ||||||||||||||||||||||||||||
| _docs.embeddings = _v | ||||||||||||||||||||||||||||
| for _d in _docs: | ||||||||||||||||||||||||||||
| self._set_doc_by_id(_d.id, _d) | ||||||||||||||||||||||||||||
|
Comment on lines
+168
to
+174
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should be common to both branches |
||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||
| if not isinstance(_v, (list, tuple)): | ||||||||||||||||||||||||||||
| for _d in _docs: | ||||||||||||||||||||||||||||
| self._set_doc_attr_by_id(_d.id, _a, _v) | ||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||
| for _d, _vv in zip(_docs, _v): | ||||||||||||||||||||||||||||
| self._set_doc_attr_by_id(_d.id, _a, _vv) | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| def _set_docs_attributes_traversal_paths( | ||||||||||||||||||||||||||||
| self, traversal_paths: str, attributes, value | ||||||||||||||||||||||||||||
| ): | ||||||||||||||||||||||||||||
| _docs = self[traversal_paths] | ||||||||||||||||||||||||||||
| if not _docs: | ||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| for _a, _v in zip(attributes, value): | ||||||||||||||||||||||||||||
| if _a == 'tensor': | ||||||||||||||||||||||||||||
| _docs.tensors = _v | ||||||||||||||||||||||||||||
| elif _a == 'embedding': | ||||||||||||||||||||||||||||
| _docs.embeddings = _v | ||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||
| if not isinstance(_v, (list, tuple)): | ||||||||||||||||||||||||||||
| for _d in _docs: | ||||||||||||||||||||||||||||
| setattr(_d, _a, _v) | ||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||
| for _d, _vv in zip(_docs, _v): | ||||||||||||||||||||||||||||
| setattr(_d, _a, _vv) | ||||||||||||||||||||||||||||
| self._set_doc_value_pairs_nested(_docs, _docs) | ||||||||||||||||||||||||||||
Oops, something went wrong.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Invalid types in the sequence should be caught and not fail silently; particularly things like da[1.0, 2.0] coming from np or torch might be a pitfall.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
single quote btw
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oups not used to it yet 😕
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed