Skip to content

Commit ecd7ebc

Browse files
author
Gerit Wagner
committed
validate query children
commit e9e0ca7 Author: Gerit Wagner <gerit.wagner@uni-bamberg.de> Date: Sat May 31 07:52:38 2025 +0200 setters > OrQuery, AndQuery, ... commit afb9d76 Author: Gerit Wagner <gerit.wagner@uni-bamberg.de> Date: Sat May 31 07:46:46 2025 +0200 setter validation + tests
1 parent 9675736 commit ecd7ebc

File tree

7 files changed

+214
-2
lines changed

7 files changed

+214
-2
lines changed

search_query/query.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,9 +223,15 @@ def children(self) -> typing.List[Query]:
223223

224224
@children.setter
225225
def children(self, children: typing.List[Query]) -> None:
226-
"""Set the children of this query node, updating parent pointers."""
226+
"""Set the children of the query, updating parent pointers."""
227227
# Clear existing children and reset parent links (if necessary)
228228
self._children.clear()
229+
if not isinstance(children, list):
230+
raise TypeError("children must be a list of Query instances or strings")
231+
232+
# Note: OrQuery, AndQuery, NearQuery, NotQuery, RANGEQuery offeride the setter
233+
# with specific validation.
234+
229235
# Add each new child using add_child (ensures parent is set)
230236
for child in children or []:
231237
self.add_child(child)
@@ -241,6 +247,8 @@ def add_child(self, child: typing.Union[str, Query]) -> Query:
241247
search_field=self.search_field,
242248
platform=self.platform,
243249
)
250+
if not isinstance(child, Query):
251+
raise TypeError("Child must be a Query instance or a string")
244252
child._set_parent(self) # pylint: disable=protected-access
245253
self._children.append(child)
246254
return child

search_query/query_and.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,23 @@ def __init__(
3737
position=position,
3838
platform=platform,
3939
)
40+
41+
@property
42+
def children(self) -> typing.List[Query]:
43+
"""Children property."""
44+
return self._children
45+
46+
@children.setter
47+
def children(self, children: typing.List[Query]) -> None:
48+
"""Set the children of AND query, updating parent pointers."""
49+
# Clear existing children and reset parent links (if necessary)
50+
self._children.clear()
51+
if not isinstance(children, list):
52+
raise TypeError("children must be a list of Query instances or strings")
53+
54+
if len(children) < 2:
55+
raise ValueError("An AND query must have two children")
56+
57+
# Add each new child using add_child (ensures parent is set)
58+
for child in children or []:
59+
self.add_child(child)

search_query/query_near.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,23 @@ def __init__(
4141
distance=distance,
4242
platform=platform,
4343
)
44+
45+
@property
46+
def children(self) -> typing.List[Query]:
47+
"""Children property."""
48+
return self._children
49+
50+
@children.setter
51+
def children(self, children: typing.List[Query]) -> None:
52+
"""Set the children of NEAR query, updating parent pointers."""
53+
# Clear existing children and reset parent links (if necessary)
54+
self._children.clear()
55+
if not isinstance(children, list):
56+
raise TypeError("children must be a list of Query instances or strings")
57+
58+
if len(children) != 2:
59+
raise ValueError("A NEAR query must have two children")
60+
61+
# Add each new child using add_child (ensures parent is set)
62+
for child in children or []:
63+
self.add_child(child)

search_query/query_not.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,23 @@ def __init__(
3737
position=position,
3838
platform=platform,
3939
)
40+
41+
@property
42+
def children(self) -> typing.List[Query]:
43+
"""Children property."""
44+
return self._children
45+
46+
@children.setter
47+
def children(self, children: typing.List[Query]) -> None:
48+
"""Set the children of NOT query, updating parent pointers."""
49+
# Clear existing children and reset parent links (if necessary)
50+
self._children.clear()
51+
if not isinstance(children, list):
52+
raise TypeError("children must be a list of Query instances or strings")
53+
54+
if len(children) != 2:
55+
raise ValueError("A NOT query must have two children")
56+
57+
# Add each new child using add_child (ensures parent is set)
58+
for child in children or []:
59+
self.add_child(child)

search_query/query_or.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,23 @@ def __init__(
3838
position=position,
3939
platform=platform,
4040
)
41+
42+
@property
43+
def children(self) -> typing.List[Query]:
44+
"""Children property."""
45+
return self._children
46+
47+
@children.setter
48+
def children(self, children: typing.List[Query]) -> None:
49+
"""Set the children of OR query, updating parent pointers."""
50+
# Clear existing children and reset parent links (if necessary)
51+
self._children.clear()
52+
if not isinstance(children, list):
53+
raise TypeError("children must be a list of Query instances or strings")
54+
55+
if len(children) < 2:
56+
raise ValueError("An OR query must have two children")
57+
58+
# Add each new child using add_child (ensures parent is set)
59+
for child in children or []:
60+
self.add_child(child)

search_query/query_range.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def __init__(
2525
nested queries: queries whose roots are appended to the query
2626
search field: search field to which the query should be applied
2727
"""
28-
assert len(children) == 2, "RangeQuery must have exactly two children"
28+
2929
super().__init__(
3030
value=Operators.RANGE,
3131
children=children,
@@ -37,3 +37,23 @@ def __init__(
3737
position=position,
3838
platform=platform,
3939
)
40+
41+
@property
42+
def children(self) -> typing.List[Query]:
43+
"""Children property."""
44+
return self._children
45+
46+
@children.setter
47+
def children(self, children: typing.List[Query]) -> None:
48+
"""Set the children of RANGE query, updating parent pointers."""
49+
# Clear existing children and reset parent links (if necessary)
50+
self._children.clear()
51+
if not isinstance(children, list):
52+
raise TypeError("children must be a list of Query instances or strings")
53+
54+
if len(children) != 2:
55+
raise ValueError("A RANGE query must have two children")
56+
57+
# Add each new child using add_child (ensures parent is set)
58+
for child in children or []:
59+
self.add_child(child)

test/test_query.py

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@
88
from search_query.query import SearchField
99
from search_query.query_and import AndQuery
1010
from search_query.query_near import NEARQuery
11+
from search_query.query_not import NotQuery
1112
from search_query.query_or import OrQuery
13+
from search_query.query_range import RangeQuery
1214
from search_query.utils import format_query_string_positions
1315

1416
# pylint: disable=line-too-long
@@ -174,3 +176,105 @@ def test_value_setter() -> None:
174176
ethics.operator = "non_operators" # type: ignore
175177

176178
ethics.value = "NEAR"
179+
180+
181+
def test_children_setter() -> None:
182+
"""Test children setter."""
183+
# Test for OrQuery ---------------------------------------------
184+
or_query = OrQuery(
185+
["ethics", "morality"],
186+
search_field="abstract",
187+
)
188+
assert or_query.children[0].value == "ethics"
189+
assert or_query.children[1].value == "morality"
190+
191+
with pytest.raises(TypeError):
192+
or_query.children = "not_a_list" # type: ignore
193+
194+
with pytest.raises(TypeError):
195+
or_query.children = ["valid", 123] # type: ignore
196+
197+
with pytest.raises(ValueError):
198+
or_query.children = ["new_child"] # type: ignore
199+
200+
or_query.children = ["new_child", "another_child", "third_child"] # type: ignore
201+
202+
# Test for AndQuery ---------------------------------------------
203+
and_query = AndQuery(
204+
["ethics", "morality"],
205+
search_field="abstract",
206+
)
207+
assert and_query.children[0].value == "ethics"
208+
assert and_query.children[1].value == "morality"
209+
210+
with pytest.raises(TypeError):
211+
and_query.children = "not_a_list" # type: ignore
212+
213+
with pytest.raises(TypeError):
214+
and_query.children = ["valid", 123] # type: ignore
215+
216+
with pytest.raises(ValueError):
217+
and_query.children = ["new_child"] # type: ignore
218+
219+
and_query.children = ["new_child", "another_child", "third_child"] # type: ignore
220+
221+
# Test for NotQuery ---------------------------------------------
222+
not_query = NotQuery(
223+
["ethics"],
224+
search_field="abstract",
225+
)
226+
assert not_query.children[0].value == "ethics"
227+
228+
with pytest.raises(TypeError):
229+
not_query.children = "not_a_list" # type: ignore
230+
231+
with pytest.raises(TypeError):
232+
not_query.children = ["valid", 123] # type: ignore
233+
234+
with pytest.raises(ValueError):
235+
not_query.children = ["new_child", "another_child", "third_child"] # type: ignore
236+
237+
with pytest.raises(ValueError):
238+
not_query.children = ["new_child"] # type: ignore
239+
240+
# Test for NEARQuery ---------------------------------------------
241+
near_query = NEARQuery(
242+
"NEAR",
243+
distance=5,
244+
children=["ethics", "morality"],
245+
search_field="abstract",
246+
)
247+
assert near_query.children[0].value == "ethics"
248+
assert near_query.children[1].value == "morality"
249+
250+
with pytest.raises(TypeError):
251+
near_query.children = "not_a_list" # type: ignore
252+
253+
with pytest.raises(TypeError):
254+
near_query.children = ["valid", 123] # type: ignore
255+
256+
with pytest.raises(ValueError):
257+
near_query.children = ["new_child"] # type: ignore
258+
259+
with pytest.raises(ValueError):
260+
near_query.children = ["new_child", "another_child", "third_child"] # type: ignore
261+
262+
# Test for RangeQuery ---------------------------------------------
263+
range_query = RangeQuery(
264+
children=["2010", "2020"],
265+
search_field="year-publication",
266+
)
267+
assert range_query.children[0].value == "2010"
268+
assert range_query.children[1].value == "2020"
269+
270+
with pytest.raises(TypeError):
271+
range_query.children = "not_a_list" # type: ignore
272+
273+
with pytest.raises(TypeError):
274+
range_query.children = ["valid", 123] # type: ignore
275+
276+
with pytest.raises(ValueError):
277+
range_query.children = ["new_child"] # type: ignore
278+
279+
with pytest.raises(ValueError):
280+
range_query.children = ["new_child", "another_child", "third_child"] # type: ignore

0 commit comments

Comments
 (0)