mpt-extension-sdk 5.2.3__tar.gz → 5.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/PKG-INFO +1 -2
- {mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/mpt_http/mpt.py +21 -14
- {mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/runtime/events/producers.py +4 -2
- mpt_extension_sdk-5.3.0/mpt_extension_sdk/swo_rql/__init__.py +5 -0
- mpt_extension_sdk-5.3.0/mpt_extension_sdk/swo_rql/constants.py +7 -0
- mpt_extension_sdk-5.3.0/mpt_extension_sdk/swo_rql/query_builder.py +392 -0
- {mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/pyproject.toml +2 -3
- {mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/.gitignore +0 -0
- {mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/LICENSE +0 -0
- {mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/README.md +0 -0
- {mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/__init__.py +0 -0
- {mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/airtable/__init__.py +0 -0
- {mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/airtable/wrap_http_error.py +0 -0
- {mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/constants.py +0 -0
- {mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/core/__init__.py +0 -0
- {mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/core/events/__init__.py +0 -0
- {mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/core/events/dataclasses.py +0 -0
- {mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/core/events/registry.py +0 -0
- {mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/core/extension.py +0 -0
- {mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/core/security.py +0 -0
- {mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/core/utils.py +0 -0
- {mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/flows/__init__.py +0 -0
- {mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/flows/context.py +0 -0
- {mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/flows/pipeline.py +0 -0
- {mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/key_vault/__init__.py +0 -0
- {mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/key_vault/base.py +0 -0
- {mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/mpt_http/__init__.py +0 -0
- {mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/mpt_http/base.py +0 -0
- {mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/mpt_http/utils.py +0 -0
- {mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/mpt_http/wrap_http_error.py +0 -0
- {mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/runtime/__init__.py +0 -0
- {mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/runtime/commands/__init__.py +0 -0
- {mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/runtime/commands/django.py +0 -0
- {mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/runtime/commands/run.py +0 -0
- {mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/runtime/djapp/__init__.py +0 -0
- {mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/runtime/djapp/apps.py +0 -0
- {mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/runtime/djapp/conf/__init__.py +0 -0
- {mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/runtime/djapp/conf/default.py +0 -0
- {mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/runtime/djapp/conf/urls.py +0 -0
- {mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/runtime/djapp/management/__init__.py +0 -0
- {mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/runtime/djapp/management/commands/__init__.py +0 -0
- {mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/runtime/djapp/management/commands/consume_events.py +0 -0
- {mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/runtime/djapp/middleware.py +0 -0
- {mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/runtime/events/__init__.py +0 -0
- {mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/runtime/events/dispatcher.py +0 -0
- {mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/runtime/events/utils.py +0 -0
- {mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/runtime/initializer.py +0 -0
- {mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/runtime/logging.py +0 -0
- {mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/runtime/master.py +0 -0
- {mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/runtime/swoext.py +0 -0
- {mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/runtime/utils.py +0 -0
- {mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/runtime/workers.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mpt-extension-sdk
|
|
3
|
-
Version: 5.
|
|
3
|
+
Version: 5.3.0
|
|
4
4
|
Summary: Extensions SDK for SoftwareONE Marketplace Platform
|
|
5
5
|
Author: SoftwareOne AG
|
|
6
6
|
License: Apache-2.0 license
|
|
@@ -9,7 +9,6 @@ Requires-Python: <4,>=3.12
|
|
|
9
9
|
Requires-Dist: azure-identity<2,>=1.21.0
|
|
10
10
|
Requires-Dist: azure-keyvault-secrets<5,>=4.9.0
|
|
11
11
|
Requires-Dist: azure-monitor-opentelemetry-exporter==1.0.0b25
|
|
12
|
-
Requires-Dist: boto3==1.34.*
|
|
13
12
|
Requires-Dist: click==8.1.*
|
|
14
13
|
Requires-Dist: debugpy==1.8.*
|
|
15
14
|
Requires-Dist: django-ninja==1.1.*
|
|
@@ -382,25 +382,12 @@ def notify(
|
|
|
382
382
|
subject: str,
|
|
383
383
|
message_body: str,
|
|
384
384
|
limit: int = 1000,
|
|
385
|
-
):
|
|
385
|
+
) -> None:
|
|
386
386
|
"""
|
|
387
387
|
Sends notifications to multiple recipients in batches for a specific buyer and
|
|
388
388
|
category through the MPTClient service. The function retrieves recipients,
|
|
389
389
|
groups them into manageable batches, and sends notifications using the provided
|
|
390
390
|
message details.
|
|
391
|
-
|
|
392
|
-
Args:
|
|
393
|
-
mpt_client (MPTClient): Client object for interacting with MPT service.
|
|
394
|
-
category_id (str): Identifier for the category of recipients or messages.
|
|
395
|
-
account_id (str): Identifier for the associated account.
|
|
396
|
-
buyer_id (str): Identifier for the buyer related to the notification.
|
|
397
|
-
subject (str): Subject/title of the notification to be sent.
|
|
398
|
-
message_body (str): Content/body of the notification message.
|
|
399
|
-
limit (int): Maximum number of recipients to process per batch. Defaults
|
|
400
|
-
to 1000.
|
|
401
|
-
|
|
402
|
-
Returns:
|
|
403
|
-
None
|
|
404
391
|
"""
|
|
405
392
|
recipients = _paginated(
|
|
406
393
|
mpt_client,
|
|
@@ -424,3 +411,23 @@ def notify(
|
|
|
424
411
|
},
|
|
425
412
|
)
|
|
426
413
|
response.raise_for_status()
|
|
414
|
+
|
|
415
|
+
|
|
416
|
+
@wrap_mpt_http_error
|
|
417
|
+
def terminate_subscription(
|
|
418
|
+
mpt_client: MPTClient, subscription_id: str, reason: str
|
|
419
|
+
) -> dict:
|
|
420
|
+
"""
|
|
421
|
+
Terminates a subscription by calling the MPT API.
|
|
422
|
+
|
|
423
|
+
Raises:
|
|
424
|
+
HTTPError: If the HTTP request fails, an HTTPError is raised with
|
|
425
|
+
information about the issue.
|
|
426
|
+
"""
|
|
427
|
+
response = mpt_client.post(
|
|
428
|
+
f"/commerce/subscriptions/{subscription_id}/terminate",
|
|
429
|
+
json={"description": reason},
|
|
430
|
+
)
|
|
431
|
+
response.raise_for_status()
|
|
432
|
+
|
|
433
|
+
return response.json()
|
{mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/runtime/events/producers.py
RENAMED
|
@@ -9,6 +9,7 @@ from django.conf import settings
|
|
|
9
9
|
|
|
10
10
|
from mpt_extension_sdk.core.events.dataclasses import Event
|
|
11
11
|
from mpt_extension_sdk.core.utils import setup_client
|
|
12
|
+
from mpt_extension_sdk.swo_rql import RQLQuery
|
|
12
13
|
|
|
13
14
|
logger = logging.getLogger(__name__)
|
|
14
15
|
|
|
@@ -73,9 +74,10 @@ class OrderEventProducer(EventProducer):
|
|
|
73
74
|
)
|
|
74
75
|
|
|
75
76
|
def get_processing_orders(self):
|
|
76
|
-
products = ",".join(settings.MPT_PRODUCTS_IDS)
|
|
77
77
|
orders = []
|
|
78
|
-
rql_query =
|
|
78
|
+
rql_query = RQLQuery().agreement.product.id.in_(
|
|
79
|
+
settings.MPT_PRODUCTS_IDS
|
|
80
|
+
) and RQLQuery(status="processing")
|
|
79
81
|
url = (
|
|
80
82
|
f"/commerce/orders?{rql_query}&select=audit,parameters,lines,subscriptions,"
|
|
81
83
|
f"subscriptions.lines,agreement,buyer,seller&order=audit.created.at"
|
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
from mpt_extension_sdk.swo_rql import constants
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def parse_kwargs(query_dict):
|
|
5
|
+
query = []
|
|
6
|
+
for lookup, value in query_dict.items():
|
|
7
|
+
tokens = lookup.split("__")
|
|
8
|
+
if len(tokens) == 1:
|
|
9
|
+
# field=value
|
|
10
|
+
field = tokens[0]
|
|
11
|
+
value = rql_encode("eq", value)
|
|
12
|
+
query.append(f"eq({field},{value})")
|
|
13
|
+
continue
|
|
14
|
+
op = tokens[-1]
|
|
15
|
+
if op not in constants.KEYWORDS:
|
|
16
|
+
# field__nested=value
|
|
17
|
+
field = ".".join(tokens)
|
|
18
|
+
value = rql_encode("eq", value)
|
|
19
|
+
query.append(f"eq({field},{value})")
|
|
20
|
+
continue
|
|
21
|
+
field = ".".join(tokens[:-1])
|
|
22
|
+
if op in constants.COMP or op in constants.SEARCH:
|
|
23
|
+
value = rql_encode(op, value)
|
|
24
|
+
query.append(f"{op}({field},{value})")
|
|
25
|
+
continue
|
|
26
|
+
if op in constants.LIST:
|
|
27
|
+
value = rql_encode(op, value)
|
|
28
|
+
query.append(f"{op}({field},({value}))")
|
|
29
|
+
continue
|
|
30
|
+
|
|
31
|
+
cmpop = "eq" if value is True else "ne"
|
|
32
|
+
expr = "null()" if op == constants.NULL else "empty()"
|
|
33
|
+
query.append(f"{cmpop}({field},{expr})")
|
|
34
|
+
|
|
35
|
+
return query
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def rql_encode(op, value):
|
|
39
|
+
from datetime import date, datetime
|
|
40
|
+
from decimal import Decimal
|
|
41
|
+
|
|
42
|
+
if op not in constants.LIST:
|
|
43
|
+
if isinstance(value, str):
|
|
44
|
+
return value
|
|
45
|
+
if isinstance(value, bool):
|
|
46
|
+
return "true" if value else "false"
|
|
47
|
+
if isinstance(value, int | float | Decimal):
|
|
48
|
+
return str(value)
|
|
49
|
+
if isinstance(value, date | datetime):
|
|
50
|
+
return value.isoformat()
|
|
51
|
+
if op in constants.LIST and isinstance(value, list | tuple):
|
|
52
|
+
return ",".join(value)
|
|
53
|
+
raise TypeError(f"the `{op}` operator doesn't support the {type(value)} type.")
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class RQLQuery:
|
|
57
|
+
"""
|
|
58
|
+
Helper class to construct complex RQL queries.
|
|
59
|
+
|
|
60
|
+
Usage:
|
|
61
|
+
|
|
62
|
+
```py3
|
|
63
|
+
rql = R(field='value', field2__in=('v1', 'v2'), field3__empty=True)
|
|
64
|
+
```
|
|
65
|
+
!!! note
|
|
66
|
+
All the lookups expressed as keyword arguments are combined together with a logical `and`.
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
Using the ``n`` method:
|
|
70
|
+
|
|
71
|
+
```py3
|
|
72
|
+
rql = (
|
|
73
|
+
R().n('field').eq('value')
|
|
74
|
+
& R().n('field2').anyof(('v1', 'v2'))
|
|
75
|
+
& R().n('field3').empty(True)
|
|
76
|
+
)
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
The previous query can be expressed in a more concise form like:
|
|
80
|
+
|
|
81
|
+
```py3
|
|
82
|
+
rql = R().field.eq('value') & R().field2.anyof(('v1', 'v2')) & r.field3.empty(True)
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
```py3
|
|
86
|
+
rql = R("field").eq("value")
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
The R object support the bitwise operators `&`, `|` and `~`.
|
|
90
|
+
|
|
91
|
+
Nested fields can be expressed using dot notation:
|
|
92
|
+
|
|
93
|
+
```py3
|
|
94
|
+
rql = R().n('nested.field').eq('value')
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
or
|
|
98
|
+
|
|
99
|
+
```py3
|
|
100
|
+
rql = R().nested.field.eq('value')
|
|
101
|
+
```
|
|
102
|
+
"""
|
|
103
|
+
|
|
104
|
+
AND = "and"
|
|
105
|
+
OR = "or"
|
|
106
|
+
EXPRESSION = "expr"
|
|
107
|
+
|
|
108
|
+
def __init__(
|
|
109
|
+
self,
|
|
110
|
+
_field=None,
|
|
111
|
+
*,
|
|
112
|
+
_op=EXPRESSION,
|
|
113
|
+
_children=None,
|
|
114
|
+
_negated=False,
|
|
115
|
+
_expr=None,
|
|
116
|
+
**kwargs,
|
|
117
|
+
):
|
|
118
|
+
self.op = _op
|
|
119
|
+
self.children = _children or []
|
|
120
|
+
self.negated = _negated
|
|
121
|
+
self.expr = _expr
|
|
122
|
+
self._path = []
|
|
123
|
+
self._field = None
|
|
124
|
+
if _field:
|
|
125
|
+
self.n(_field)
|
|
126
|
+
if len(kwargs) == 1:
|
|
127
|
+
self.op = self.EXPRESSION
|
|
128
|
+
self.expr = parse_kwargs(kwargs)[0]
|
|
129
|
+
if len(kwargs) > 1:
|
|
130
|
+
self.op = self.AND
|
|
131
|
+
for token in parse_kwargs(kwargs):
|
|
132
|
+
self.children.append(RQLQuery(_expr=token))
|
|
133
|
+
|
|
134
|
+
def __len__(self):
|
|
135
|
+
if self.op == self.EXPRESSION:
|
|
136
|
+
if self.expr:
|
|
137
|
+
return 1
|
|
138
|
+
return 0
|
|
139
|
+
return len(self.children)
|
|
140
|
+
|
|
141
|
+
def __bool__(self):
|
|
142
|
+
return bool(self.children) or bool(self.expr)
|
|
143
|
+
|
|
144
|
+
def __eq__(self, other):
|
|
145
|
+
return (
|
|
146
|
+
self.op == other.op
|
|
147
|
+
and self.children == other.children
|
|
148
|
+
and self.negated == other.negated
|
|
149
|
+
and self.expr == other.expr
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
def __hash__(self):
|
|
153
|
+
return hash(
|
|
154
|
+
(
|
|
155
|
+
self.op,
|
|
156
|
+
self.expr,
|
|
157
|
+
self.negated,
|
|
158
|
+
*(hash(value) for value in self.children),
|
|
159
|
+
),
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
def __repr__(self):
|
|
163
|
+
if self.op == self.EXPRESSION:
|
|
164
|
+
return f"<R({self.op}) {self.expr}>"
|
|
165
|
+
return f"<R({self.op})>"
|
|
166
|
+
|
|
167
|
+
def __and__(self, other):
|
|
168
|
+
return self._join(other, self.AND)
|
|
169
|
+
|
|
170
|
+
def __or__(self, other):
|
|
171
|
+
return self._join(other, self.OR)
|
|
172
|
+
|
|
173
|
+
def __invert__(self):
|
|
174
|
+
query = RQLQuery(_op=self.AND, _expr=self.expr, _negated=True)
|
|
175
|
+
query._append(self)
|
|
176
|
+
return query
|
|
177
|
+
|
|
178
|
+
def __getattr__(self, name):
|
|
179
|
+
return self.n(name)
|
|
180
|
+
|
|
181
|
+
def __str__(self):
|
|
182
|
+
return self._to_string(self)
|
|
183
|
+
|
|
184
|
+
def n(self, name):
|
|
185
|
+
"""
|
|
186
|
+
Set the current field for this `R` object.
|
|
187
|
+
|
|
188
|
+
Args:
|
|
189
|
+
name (str): Name of the field.
|
|
190
|
+
"""
|
|
191
|
+
if self._field:
|
|
192
|
+
raise AttributeError("Already evaluated")
|
|
193
|
+
|
|
194
|
+
self._path.extend(name.split("."))
|
|
195
|
+
return self
|
|
196
|
+
|
|
197
|
+
def ne(self, value):
|
|
198
|
+
"""
|
|
199
|
+
Apply the `ne` operator to the field this `R` object refers to.
|
|
200
|
+
|
|
201
|
+
Args:
|
|
202
|
+
value (str): The value to which compare the field.
|
|
203
|
+
"""
|
|
204
|
+
return self._bin("ne", value)
|
|
205
|
+
|
|
206
|
+
def eq(self, value):
|
|
207
|
+
"""
|
|
208
|
+
Apply the `eq` operator to the field this `R` object refers to.
|
|
209
|
+
|
|
210
|
+
Args:
|
|
211
|
+
value (str): The value to which compare the field.
|
|
212
|
+
"""
|
|
213
|
+
return self._bin("eq", value)
|
|
214
|
+
|
|
215
|
+
def lt(self, value):
|
|
216
|
+
"""
|
|
217
|
+
Apply the `lt` operator to the field this `R` object refers to.
|
|
218
|
+
|
|
219
|
+
Args:
|
|
220
|
+
value (str): The value to which compare the field.
|
|
221
|
+
"""
|
|
222
|
+
return self._bin("lt", value)
|
|
223
|
+
|
|
224
|
+
def le(self, value):
|
|
225
|
+
"""
|
|
226
|
+
Apply the `le` operator to the field this `R` object refers to.
|
|
227
|
+
|
|
228
|
+
Args:
|
|
229
|
+
value (str): The value to which compare the field.
|
|
230
|
+
"""
|
|
231
|
+
return self._bin("le", value)
|
|
232
|
+
|
|
233
|
+
def gt(self, value):
|
|
234
|
+
"""
|
|
235
|
+
Apply the `gt` operator to the field this `R` object refers to.
|
|
236
|
+
|
|
237
|
+
Args:
|
|
238
|
+
value (str): The value to which compare the field.
|
|
239
|
+
"""
|
|
240
|
+
return self._bin("gt", value)
|
|
241
|
+
|
|
242
|
+
def ge(self, value):
|
|
243
|
+
"""
|
|
244
|
+
Apply the `ge` operator to the field this `R` object refers to.
|
|
245
|
+
|
|
246
|
+
Args:
|
|
247
|
+
value (str): The value to which compare the field.
|
|
248
|
+
"""
|
|
249
|
+
return self._bin("ge", value)
|
|
250
|
+
|
|
251
|
+
def out(self, value: list[str]):
|
|
252
|
+
"""
|
|
253
|
+
Apply the `out` operator to the field this `R` object refers to.
|
|
254
|
+
|
|
255
|
+
Args:
|
|
256
|
+
value (list[str]): The list of values to which compare the field.
|
|
257
|
+
"""
|
|
258
|
+
return self._list("out", value)
|
|
259
|
+
|
|
260
|
+
def in_(self, value):
|
|
261
|
+
return self._list("in", value)
|
|
262
|
+
|
|
263
|
+
def oneof(self, value: list[str]):
|
|
264
|
+
"""
|
|
265
|
+
Apply the `in` operator to the field this `R` object refers to.
|
|
266
|
+
|
|
267
|
+
Args:
|
|
268
|
+
value (list[str]): The list of values to which compare the field.
|
|
269
|
+
"""
|
|
270
|
+
return self._list("in", value)
|
|
271
|
+
|
|
272
|
+
def null(self, value: list[str]):
|
|
273
|
+
"""
|
|
274
|
+
Apply the `null` operator to the field this `R` object refers to.
|
|
275
|
+
|
|
276
|
+
Args:
|
|
277
|
+
value (list[str]): The value to which compare the field.
|
|
278
|
+
"""
|
|
279
|
+
return self._bool("null", value)
|
|
280
|
+
|
|
281
|
+
def empty(self, value: bool = True):
|
|
282
|
+
"""
|
|
283
|
+
Apply the `empty` operator to the field this `R` object refers to.
|
|
284
|
+
|
|
285
|
+
Usage: `R().field.empty()
|
|
286
|
+
|
|
287
|
+
For not empty: `R().field.empty(False)` or `R().field.not_empty()`
|
|
288
|
+
"""
|
|
289
|
+
return self._bool("empty", value)
|
|
290
|
+
|
|
291
|
+
def not_empty(self):
|
|
292
|
+
"""
|
|
293
|
+
Apply the `not_empty` operator to the field this `R` object refers to.
|
|
294
|
+
"""
|
|
295
|
+
query = self._bool("empty", False)
|
|
296
|
+
return query
|
|
297
|
+
|
|
298
|
+
def like(self, value: list[str]):
|
|
299
|
+
"""
|
|
300
|
+
Apply the `like` operator to the field this `R` object refers to.
|
|
301
|
+
|
|
302
|
+
Args:
|
|
303
|
+
value (list[str]): The value to which compare the field.
|
|
304
|
+
"""
|
|
305
|
+
return self._bin("like", value)
|
|
306
|
+
|
|
307
|
+
def ilike(self, value: list[str]):
|
|
308
|
+
"""
|
|
309
|
+
Apply the `ilike` operator to the field this `R` object refers to.
|
|
310
|
+
|
|
311
|
+
Args:
|
|
312
|
+
value (list[str]): The value to which compare the field.
|
|
313
|
+
"""
|
|
314
|
+
return self._bin("ilike", value)
|
|
315
|
+
|
|
316
|
+
def _bin(self, op, value):
|
|
317
|
+
self._field = ".".join(self._path)
|
|
318
|
+
value = rql_encode(op, value)
|
|
319
|
+
self.expr = f"{op}({self._field},{value})"
|
|
320
|
+
return self
|
|
321
|
+
|
|
322
|
+
def _list(self, op, value):
|
|
323
|
+
self._field = ".".join(self._path)
|
|
324
|
+
value = rql_encode(op, value)
|
|
325
|
+
self.expr = f"{op}({self._field},({value}))"
|
|
326
|
+
return self
|
|
327
|
+
|
|
328
|
+
def _bool(self, expr, value):
|
|
329
|
+
self._field = ".".join(self._path)
|
|
330
|
+
if bool(value) is False:
|
|
331
|
+
self.expr = f"ne({self._field},{expr}())"
|
|
332
|
+
return self
|
|
333
|
+
self.expr = f"eq({self._field},{expr}())"
|
|
334
|
+
return self
|
|
335
|
+
|
|
336
|
+
def _to_string(self, query):
|
|
337
|
+
tokens = []
|
|
338
|
+
if query.expr:
|
|
339
|
+
if query.negated:
|
|
340
|
+
return f"not({query.expr})"
|
|
341
|
+
return query.expr
|
|
342
|
+
for c in query.children:
|
|
343
|
+
if c.expr:
|
|
344
|
+
if c.negated:
|
|
345
|
+
tokens.append(f"not({c.expr})")
|
|
346
|
+
else:
|
|
347
|
+
tokens.append(c.expr)
|
|
348
|
+
continue
|
|
349
|
+
tokens.append(self._to_string(c))
|
|
350
|
+
|
|
351
|
+
if not tokens:
|
|
352
|
+
return ""
|
|
353
|
+
|
|
354
|
+
if query.negated:
|
|
355
|
+
return f'not({query.op}({",".join(tokens)}))'
|
|
356
|
+
return f'{query.op}({",".join(tokens)})'
|
|
357
|
+
|
|
358
|
+
def _copy(self, other):
|
|
359
|
+
return RQLQuery(
|
|
360
|
+
_op=other.op,
|
|
361
|
+
_children=other.children[:],
|
|
362
|
+
_expr=other.expr,
|
|
363
|
+
)
|
|
364
|
+
|
|
365
|
+
def _join(self, other, op):
|
|
366
|
+
if self == other:
|
|
367
|
+
return self._copy(self)
|
|
368
|
+
if not other:
|
|
369
|
+
return self._copy(self)
|
|
370
|
+
if not self:
|
|
371
|
+
return self._copy(other)
|
|
372
|
+
|
|
373
|
+
query = RQLQuery(_op=op)
|
|
374
|
+
query._append(self)
|
|
375
|
+
query._append(other)
|
|
376
|
+
return query
|
|
377
|
+
|
|
378
|
+
def _append(self, other):
|
|
379
|
+
if other in self.children:
|
|
380
|
+
return other
|
|
381
|
+
|
|
382
|
+
if (
|
|
383
|
+
other.op == self.op or (len(other) == 1 and other.op != self.EXPRESSION)
|
|
384
|
+
) and not other.negated:
|
|
385
|
+
self.children.extend(other.children)
|
|
386
|
+
return self
|
|
387
|
+
|
|
388
|
+
self.children.append(other)
|
|
389
|
+
return self
|
|
390
|
+
|
|
391
|
+
|
|
392
|
+
R = RQLQuery
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "mpt-extension-sdk"
|
|
3
|
-
version = "5.
|
|
3
|
+
version = "5.3.0"
|
|
4
4
|
description = "Extensions SDK for SoftwareONE Marketplace Platform"
|
|
5
5
|
authors = [{ name = "SoftwareOne AG" }]
|
|
6
6
|
requires-python = ">=3.12,<4"
|
|
@@ -10,7 +10,6 @@ dependencies = [
|
|
|
10
10
|
"azure-identity>=1.21.0,<2",
|
|
11
11
|
"azure-keyvault-secrets>=4.9.0,<5",
|
|
12
12
|
"azure-monitor-opentelemetry-exporter==1.0.0b25",
|
|
13
|
-
"boto3==1.34.*",
|
|
14
13
|
"click==8.1.*",
|
|
15
14
|
"debugpy==1.8.*",
|
|
16
15
|
"django==4.2.*",
|
|
@@ -38,7 +37,7 @@ dependencies = [
|
|
|
38
37
|
]
|
|
39
38
|
|
|
40
39
|
[project.scripts]
|
|
41
|
-
|
|
40
|
+
swosdk = "mpt_extension_sdk.runtime.swoext:main"
|
|
42
41
|
|
|
43
42
|
[project.entry-points."swo.mpt.sdk"]
|
|
44
43
|
app_config = "mpt_extension_sdk.runtime.djapp.apps:ExtensionConfig"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/airtable/wrap_http_error.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/core/events/__init__.py
RENAMED
|
File without changes
|
{mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/core/events/dataclasses.py
RENAMED
|
File without changes
|
{mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/core/events/registry.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/mpt_http/wrap_http_error.py
RENAMED
|
File without changes
|
|
File without changes
|
{mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/runtime/commands/__init__.py
RENAMED
|
File without changes
|
{mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/runtime/commands/django.py
RENAMED
|
File without changes
|
{mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/runtime/commands/run.py
RENAMED
|
File without changes
|
{mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/runtime/djapp/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/runtime/djapp/conf/__init__.py
RENAMED
|
File without changes
|
{mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/runtime/djapp/conf/default.py
RENAMED
|
File without changes
|
{mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/runtime/djapp/conf/urls.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/runtime/djapp/middleware.py
RENAMED
|
File without changes
|
{mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/runtime/events/__init__.py
RENAMED
|
File without changes
|
{mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/runtime/events/dispatcher.py
RENAMED
|
File without changes
|
{mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/runtime/events/utils.py
RENAMED
|
File without changes
|
{mpt_extension_sdk-5.2.3 → mpt_extension_sdk-5.3.0}/mpt_extension_sdk/runtime/initializer.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|