Skip to content

Commit 2c10349

Browse files
committed
MPT-12552 RQLQuery add operations all and any
1 parent c2704a7 commit 2c10349

File tree

8 files changed

+69
-32
lines changed

8 files changed

+69
-32
lines changed

mpt_api_client/mpt.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ def __init__(
1313
registry: Registry | None = None,
1414
mpt_client: MPTClient | None = None,
1515
):
16-
1716
self.mpt_client = mpt_client or MPTClient(base_url=base_url, api_token=api_key)
1817
self.registry: Registry = registry or Registry()
1918

mpt_api_client/rql/query_builder.py

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -142,16 +142,18 @@ class RQLQuery: # noqa: WPS214
142142
rql = RQLQuery().nested.field.eq('value')
143143
"""
144144

145-
AND = "and" # noqa: WPS115
146-
OR = "or" # noqa: WPS115
147-
EXPRESSION = "expr" # noqa: WPS115
145+
OP_AND = "and" # noqa: WPS115
146+
OP_OR = "or" # noqa: WPS115
147+
OP_ANY = "any" # noqa: WPS115
148+
OP_ALL = "all" # noqa: WPS115
149+
OP_EXPRESSION = "expr" # noqa: WPS115
148150

149151
def __init__( # noqa: WPS211
150152
self,
151153
namespace_: str | None = None, # noqa: WPS120
152154
**kwargs: QueryValue,
153155
) -> None:
154-
self.op: str = self.EXPRESSION
156+
self.op: str = self.OP_EXPRESSION
155157
self.children: list[RQLQuery] = []
156158
self.negated: bool = False
157159
self.expr: str | None = None
@@ -160,10 +162,10 @@ def __init__( # noqa: WPS211
160162
if namespace_:
161163
self.n(namespace_)
162164
if len(kwargs) == 1:
163-
self.op = self.EXPRESSION
165+
self.op = self.OP_EXPRESSION
164166
self.expr = parse_kwargs(kwargs)[0]
165167
if len(kwargs) > 1:
166-
self.op = self.AND
168+
self.op = self.OP_AND
167169
for token in parse_kwargs(kwargs):
168170
self.children.append(self.new(expr=token))
169171

@@ -180,14 +182,14 @@ def new(
180182
if isinstance(children, set):
181183
children = list(children)
182184
query = cls()
183-
query.op = op or cls.EXPRESSION
185+
query.op = op or cls.OP_EXPRESSION
184186
query.children = children or []
185187
query.negated = negated
186188
query.expr = expr
187189
return query
188190

189191
def __len__(self) -> int:
190-
if self.op == self.EXPRESSION:
192+
if self.op == self.OP_EXPRESSION:
191193
if self.expr:
192194
return 1
193195
return 0
@@ -220,23 +222,23 @@ def __hash__(self) -> int:
220222

221223
@override
222224
def __repr__(self) -> str:
223-
if self.op == self.EXPRESSION:
225+
if self.op == self.OP_EXPRESSION:
224226
return f"<RQLQuery({self.op}) {self.expr}>"
225227
return f"<RQLQuery({self.op})>"
226228

227229
def __and__(self, other: object) -> Self:
228230
if not isinstance(other, type(self)):
229231
return NotImplemented
230-
return self._join(other, self.AND)
232+
return self._join(other, self.OP_AND)
231233

232234
def __or__(self, other: object) -> Self:
233235
if not isinstance(other, type(self)):
234236
return NotImplemented
235-
return self._join(other, self.OR)
237+
return self._join(other, self.OP_OR)
236238

237239
def __invert__(self) -> Self:
238240
inverted_query = self.new(
239-
op=self.AND,
241+
op=self.OP_AND,
240242
expr=self.expr,
241243
negated=True,
242244
)
@@ -250,6 +252,29 @@ def __getattr__(self, name: str) -> Self:
250252
def __str__(self) -> str:
251253
return self._to_string(self)
252254

255+
def any(self) -> Self:
256+
"""Any nested objects have to match the filter condition.
257+
258+
Returns:
259+
RQLQuery: RQLQuery with new condition
260+
261+
Examples:
262+
RQLQuery(saleDetails__orderQty__gt=11).any()
263+
will result: any(saleDetails,orderQty=11)
264+
"""
265+
return self.new(op=self.OP_ANY, children=[self])
266+
267+
def all(self) -> Self:
268+
"""All nested objects have to match the filter condition.
269+
270+
Returns:
271+
RQLQuery: RQLQuery with new condition
272+
273+
Example:
274+
RQLQuery(saleDetails__orderQty__gt=1).all()
275+
"""
276+
return self.new(op=self.OP_ALL, children=[self])
277+
253278
def n(self, name: str) -> Self: # noqa: WPS111
254279
"""Set the current field for this `RQLQuery` object.
255280
@@ -485,7 +510,7 @@ def _join(self, other: "RQLQuery", op: str) -> Self:
485510
def _append(self, query: "RQLQuery") -> "RQLQuery" | Self:
486511
if query in self.children:
487512
return query
488-
single_operation = len(query) == 1 and query.op != self.EXPRESSION
513+
single_operation = len(query) == 1 and query.op != self.OP_EXPRESSION
489514
if (query.op == self.op or single_operation) and not query.negated:
490515
self.children.extend(query.children)
491516
return self

tests/modules/test_order.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
from mpt_api_client.modules.order import Order, OrderCollectionClient
32

43

tests/rql/query_builder/test_create_rql.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
def test_create():
55
query = RQLQuery()
66

7-
assert query.op == RQLQuery.EXPRESSION
7+
assert query.op == RQLQuery.OP_EXPRESSION
88
assert query.children == []
99
assert query.negated is False
1010

@@ -14,14 +14,14 @@ def test_create_with_field():
1414

1515
query.eq("value")
1616

17-
assert query.op == RQLQuery.EXPRESSION
17+
assert query.op == RQLQuery.OP_EXPRESSION
1818
assert str(query) == "eq(field,value)"
1919

2020

2121
def test_create_single_kwarg():
2222
query = RQLQuery(id="ID")
2323

24-
assert query.op == RQLQuery.EXPRESSION
24+
assert query.op == RQLQuery.OP_EXPRESSION
2525
assert str(query) == "eq(id,ID)"
2626
assert query.children == []
2727
assert query.negated is False
@@ -30,24 +30,24 @@ def test_create_single_kwarg():
3030
def test_create_multiple_kwargs(): # noqa: WPS218
3131
query = RQLQuery(id="ID", status__in=("a", "b"), ok=True)
3232

33-
assert query.op == RQLQuery.AND
33+
assert query.op == RQLQuery.OP_AND
3434
assert str(query) == "and(eq(id,ID),in(status,(a,b)),eq(ok,true))"
3535
assert len(query.children) == 3
36-
assert query.children[0].op == RQLQuery.EXPRESSION
36+
assert query.children[0].op == RQLQuery.OP_EXPRESSION
3737
assert query.children[0].children == []
3838
assert str(query.children[0]) == "eq(id,ID)"
39-
assert query.children[1].op == RQLQuery.EXPRESSION
39+
assert query.children[1].op == RQLQuery.OP_EXPRESSION
4040
assert query.children[1].children == []
4141
assert str(query.children[1]) == "in(status,(a,b))"
42-
assert query.children[2].op == RQLQuery.EXPRESSION
42+
assert query.children[2].op == RQLQuery.OP_EXPRESSION
4343
assert query.children[2].children == []
4444
assert str(query.children[2]) == "eq(ok,true)"
4545

4646

4747
def test_new_empty():
4848
query = RQLQuery.new()
4949

50-
assert query.op == RQLQuery.EXPRESSION
50+
assert query.op == RQLQuery.OP_EXPRESSION
5151
assert query.children == []
5252
assert query.negated is False
5353

@@ -57,7 +57,7 @@ def test_new_with_parameters():
5757
status_not_done = RQLQuery.new("status=done", negated=True)
5858

5959
query = RQLQuery.new(
60-
op=RQLQuery.AND,
60+
op=RQLQuery.OP_AND,
6161
children=[project_rql, status_not_done],
6262
)
6363

@@ -69,7 +69,7 @@ def test_new_with_set():
6969
status_not_done = RQLQuery.new("status=done", negated=True)
7070

7171
query = RQLQuery.new(
72-
op=RQLQuery.AND,
72+
op=RQLQuery.OP_AND,
7373
children={project_rql, status_not_done},
7474
)
7575

tests/rql/query_builder/test_multiple_ops.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ def test_and_or(): # noqa: WPS218 WPS473
1010

1111
r5 = r1 & r2 & (r3 | r4)
1212

13-
assert r5.op == RQLQuery.AND
13+
assert r5.op == RQLQuery.OP_AND
1414
assert str(r5) == "and(eq(id,ID),eq(field,value),or(eq(other,value2),in(inop,(a,b))))" # noqa: WPS204
1515

1616
r5 = r1 & r2 | r3
@@ -43,6 +43,6 @@ def test_and_merge(): # noqa: WPS210
4343

4444
and3 = and1 & and2
4545

46-
assert and3.op == RQLQuery.AND
46+
assert and3.op == RQLQuery.OP_AND
4747
assert len(and3.children) == 4
4848
assert [r1, r2, r3, r4] == and3.children
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
from mpt_api_client.rql import RQLQuery
2+
3+
4+
def test_all():
5+
query = RQLQuery(saleDetails__orderQty__gt=1).all()
6+
7+
rql = str(query)
8+
assert rql == "all(gt(saleDetails.orderQty,1))"
9+
10+
11+
def test_any():
12+
query = RQLQuery(saleDetails__orderQty__gt=1).any()
13+
rql = str(query)
14+
assert rql == "any(gt(saleDetails.orderQty,1))"

tests/rql/query_builder/test_rql_and.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ def test_and_different():
4141

4242
assert r3 != r1
4343
assert r3 != r2
44-
assert r3.op == RQLQuery.AND
44+
assert r3.op == RQLQuery.OP_AND
4545
assert r1 in r3.children
4646
assert r2 in r3.children
4747

@@ -60,5 +60,5 @@ def test_and_triple():
6060
r3 = r1 & r2 & r2
6161

6262
assert len(r3) == 2
63-
assert r3.op == RQLQuery.AND
63+
assert r3.op == RQLQuery.OP_AND
6464
assert [r1, r2] == r3.children

tests/rql/query_builder/test_rql_or.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ def test_or_not_equals():
4242
assert r3 != r1
4343
assert r3 != r2
4444

45-
assert r3.op == RQLQuery.OR
45+
assert r3.op == RQLQuery.OP_OR
4646
assert r1 in r3.children
4747
assert r2 in r3.children
4848

@@ -65,7 +65,7 @@ def test_or_merge(): # noqa: WPS210
6565
or2 = r3 | r4
6666
or3 = or1 | or2
6767

68-
assert or3.op == RQLQuery.OR
68+
assert or3.op == RQLQuery.OP_OR
6969
assert len(or3.children) == 4
7070
assert [r1, r2, r3, r4] == or3.children
7171

@@ -77,5 +77,5 @@ def test_or_merge_duplicates():
7777
r3 = r1 | r2 | r2
7878

7979
assert len(r3) == 2
80-
assert r3.op == RQLQuery.OR
80+
assert r3.op == RQLQuery.OP_OR
8181
assert [r1, r2] == r3.children

0 commit comments

Comments
 (0)