mpt-extension-sdk 5.2.2__tar.gz → 5.2.4__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.2 → mpt_extension_sdk-5.2.4}/PKG-INFO +1 -2
- {mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/mpt_http/mpt.py +0 -16
- {mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/runtime/djapp/conf/default.py +8 -2
- {mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/runtime/djapp/conf/urls.py +0 -1
- {mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/runtime/events/producers.py +5 -3
- mpt_extension_sdk-5.2.4/mpt_extension_sdk/swo_rql/__init__.py +5 -0
- mpt_extension_sdk-5.2.4/mpt_extension_sdk/swo_rql/constants.py +7 -0
- mpt_extension_sdk-5.2.4/mpt_extension_sdk/swo_rql/query_builder.py +392 -0
- {mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/pyproject.toml +2 -3
- {mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/.gitignore +0 -0
- {mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/LICENSE +0 -0
- {mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/README.md +0 -0
- {mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/__init__.py +0 -0
- {mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/airtable/__init__.py +0 -0
- {mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/airtable/wrap_http_error.py +0 -0
- {mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/constants.py +0 -0
- {mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/core/__init__.py +0 -0
- {mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/core/events/__init__.py +0 -0
- {mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/core/events/dataclasses.py +0 -0
- {mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/core/events/registry.py +0 -0
- {mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/core/extension.py +0 -0
- {mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/core/security.py +0 -0
- {mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/core/utils.py +0 -0
- {mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/flows/__init__.py +0 -0
- {mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/flows/context.py +0 -0
- {mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/flows/pipeline.py +0 -0
- {mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/key_vault/__init__.py +0 -0
- {mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/key_vault/base.py +0 -0
- {mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/mpt_http/__init__.py +0 -0
- {mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/mpt_http/base.py +0 -0
- {mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/mpt_http/utils.py +0 -0
- {mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/mpt_http/wrap_http_error.py +0 -0
- {mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/runtime/__init__.py +0 -0
- {mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/runtime/commands/__init__.py +0 -0
- {mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/runtime/commands/django.py +0 -0
- {mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/runtime/commands/run.py +0 -0
- {mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/runtime/djapp/__init__.py +0 -0
- {mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/runtime/djapp/apps.py +0 -0
- {mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/runtime/djapp/conf/__init__.py +0 -0
- {mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/runtime/djapp/management/__init__.py +0 -0
- {mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/runtime/djapp/management/commands/__init__.py +0 -0
- {mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/runtime/djapp/management/commands/consume_events.py +0 -0
- {mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/runtime/djapp/middleware.py +0 -0
- {mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/runtime/events/__init__.py +0 -0
- {mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/runtime/events/dispatcher.py +0 -0
- {mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/runtime/events/utils.py +0 -0
- {mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/runtime/initializer.py +0 -0
- {mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/runtime/logging.py +0 -0
- {mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/runtime/master.py +0 -0
- {mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/runtime/swoext.py +0 -0
- {mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/runtime/utils.py +0 -0
- {mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/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.2.
|
|
3
|
+
Version: 5.2.4
|
|
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.*
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import logging
|
|
2
|
-
from datetime import date
|
|
3
2
|
from functools import cache
|
|
4
3
|
from itertools import batched
|
|
5
4
|
|
|
@@ -191,21 +190,6 @@ def get_subscriptions_by_query(
|
|
|
191
190
|
return _paginated(mpt_client, url, limit=limit)
|
|
192
191
|
|
|
193
192
|
|
|
194
|
-
def get_agreements_by_next_sync(mpt_client, next_sync_parameter):
|
|
195
|
-
today = date.today().isoformat()
|
|
196
|
-
param_condition = (
|
|
197
|
-
f"any(parameters.fulfillment,and(eq(externalId,{next_sync_parameter})"
|
|
198
|
-
f",lt(displayValue,{today})))"
|
|
199
|
-
)
|
|
200
|
-
status_condition = "eq(status,Active)"
|
|
201
|
-
|
|
202
|
-
rql_query = (
|
|
203
|
-
f"and({status_condition},{param_condition})"
|
|
204
|
-
"&select=lines,parameters,subscriptions,product,listing"
|
|
205
|
-
)
|
|
206
|
-
return get_agreements_by_query(mpt_client, rql_query)
|
|
207
|
-
|
|
208
|
-
|
|
209
193
|
@wrap_mpt_http_error
|
|
210
194
|
def update_agreement_subscription(mpt_client, subscription_id, **kwargs):
|
|
211
195
|
response = mpt_client.put(
|
{mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/runtime/djapp/conf/default.py
RENAMED
|
@@ -146,7 +146,7 @@ LOGGING = {
|
|
|
146
146
|
"disable_existing_loggers": False,
|
|
147
147
|
"formatters": {
|
|
148
148
|
"verbose": {
|
|
149
|
-
"format": "{asctime} {name} {levelname} (pid: {process}) {message}",
|
|
149
|
+
"format": "{asctime} {name} {levelname} (pid: {process}, thread: {thread}) {message}",
|
|
150
150
|
"style": "{",
|
|
151
151
|
},
|
|
152
152
|
"rich": {
|
|
@@ -154,7 +154,7 @@ LOGGING = {
|
|
|
154
154
|
"style": "{",
|
|
155
155
|
},
|
|
156
156
|
"opentelemetry": {
|
|
157
|
-
"format": "(pid: {process}) {message}",
|
|
157
|
+
"format": "(pid: {process}, thread: {thread}) {message}",
|
|
158
158
|
"style": "{",
|
|
159
159
|
},
|
|
160
160
|
},
|
|
@@ -208,6 +208,7 @@ MPT_API_TOKEN = os.getenv("MPT_API_TOKEN", "change-me!")
|
|
|
208
208
|
MPT_API_TOKEN_OPERATIONS = os.getenv("MPT_API_TOKEN_OPERATIONS", "change-me!")
|
|
209
209
|
MPT_PRODUCTS_IDS = os.getenv("MPT_PRODUCTS_IDS", "PRD-1111-1111")
|
|
210
210
|
MPT_PORTAL_BASE_URL = os.getenv("MPT_PORTAL_BASE_URL", "https://portal.s1.show")
|
|
211
|
+
MPT_KEY_VAULT_NAME = os.getenv("MPT_KEY_VAULT_NAME", "mpt-key-vault")
|
|
211
212
|
|
|
212
213
|
MPT_ORDERS_API_POLLING_INTERVAL_SECS = int(
|
|
213
214
|
os.getenv("MPT_ORDERS_API_POLLING_INTERVAL_SECS", "120")
|
|
@@ -217,3 +218,8 @@ EXTENSION_CONFIG = {
|
|
|
217
218
|
"DUE_DATE_DAYS": "30",
|
|
218
219
|
"ORDER_CREATION_WINDOW_HOURS": os.getenv("EXT_ORDER_CREATION_WINDOW_HOURS", "24"),
|
|
219
220
|
}
|
|
221
|
+
|
|
222
|
+
MPT_SETUP_CONTEXTS_FUNC = os.getenv(
|
|
223
|
+
"MPT_SETUP_CONTEXTS_FUNC",
|
|
224
|
+
"mpt_extension_sdk.runtime.events.utils.setup_contexts",
|
|
225
|
+
)
|
{mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/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,12 +74,13 @@ 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
|
-
f"subscriptions.lines,agreement,buyer&order=audit.created.at"
|
|
83
|
+
f"subscriptions.lines,agreement,buyer,seller&order=audit.created.at"
|
|
82
84
|
)
|
|
83
85
|
page = None
|
|
84
86
|
limit = 10
|
|
@@ -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.2.
|
|
3
|
+
version = "5.2.4"
|
|
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.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/airtable/wrap_http_error.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/core/events/__init__.py
RENAMED
|
File without changes
|
{mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/core/events/dataclasses.py
RENAMED
|
File without changes
|
{mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/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.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/mpt_http/wrap_http_error.py
RENAMED
|
File without changes
|
|
File without changes
|
{mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/runtime/commands/__init__.py
RENAMED
|
File without changes
|
{mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/runtime/commands/django.py
RENAMED
|
File without changes
|
{mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/runtime/commands/run.py
RENAMED
|
File without changes
|
{mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/runtime/djapp/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/runtime/djapp/conf/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/runtime/djapp/middleware.py
RENAMED
|
File without changes
|
{mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/runtime/events/__init__.py
RENAMED
|
File without changes
|
{mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/runtime/events/dispatcher.py
RENAMED
|
File without changes
|
{mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/mpt_extension_sdk/runtime/events/utils.py
RENAMED
|
File without changes
|
{mpt_extension_sdk-5.2.2 → mpt_extension_sdk-5.2.4}/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
|