mpt-extension-sdk 5.2.0__py3-none-any.whl → 5.2.2__py3-none-any.whl

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.
File without changes
@@ -2,6 +2,6 @@ EVENT_TYPES = "orders"
2
2
  SECURITY_ALGORITHM = "HS256"
3
3
  USER_AGENT = "swo-extensions/1.0"
4
4
  CONSUME_EVENTS_HELP_TEXT = "Consume events from the MPT platform"
5
- DEFAULT_APP_CONFIG_GROUP = "swo.mpt.sdk"
5
+ DEFAULT_APP_CONFIG_GROUP = "swo.mpt.ext"
6
6
  DEFAULT_APP_CONFIG_NAME = "app_config"
7
7
  DJANGO_SETTINGS_MODULE = "mpt_extension_sdk.runtime.djapp.conf.default"
@@ -1,6 +1,5 @@
1
1
  import logging
2
2
  from datetime import date
3
- from enum import Enum
4
3
  from functools import cache
5
4
  from itertools import batched
6
5
 
@@ -11,8 +10,6 @@ from mpt_extension_sdk.mpt_http.wrap_http_error import wrap_mpt_http_error
11
10
 
12
11
  logger = logging.getLogger(__name__)
13
12
 
14
- NotifyCategories = Enum("NotifyCategories", settings.MPT_NOTIFY_CATEGORIES)
15
-
16
13
 
17
14
  def _has_more_pages(page):
18
15
  if not page:
@@ -209,22 +206,6 @@ def get_agreements_by_next_sync(mpt_client, next_sync_parameter):
209
206
  return get_agreements_by_query(mpt_client, rql_query)
210
207
 
211
208
 
212
- def get_agreements_by_3yc_enroll_status(
213
- mpt_client: MPTClient, enroll_statuses: tuple[str], status: str = "Active"
214
- ):
215
- param_condition = (
216
- f"any(parameters.fulfillment,"
217
- f"and(eq(externalId,3YCEnrollStatus),in(displayValue,({",".join(enroll_statuses)}))))"
218
- )
219
- status_condition = f"eq(status,{status})"
220
-
221
- rql_query = (
222
- f"and({status_condition},{param_condition})"
223
- "&select=lines,parameters,subscriptions,product,listing"
224
- )
225
- return get_agreements_by_query(mpt_client, rql_query)
226
-
227
-
228
209
  @wrap_mpt_http_error
229
210
  def update_agreement_subscription(mpt_client, subscription_id, **kwargs):
230
211
  response = mpt_client.put(
@@ -1,21 +1,33 @@
1
1
  from contextlib import nullcontext
2
2
 
3
3
  import click
4
+ from django.core.management import execute_from_command_line
4
5
  from opentelemetry import trace
5
6
 
7
+ from mpt_extension_sdk.constants import (
8
+ DEFAULT_APP_CONFIG_GROUP,
9
+ DEFAULT_APP_CONFIG_NAME,
10
+ DJANGO_SETTINGS_MODULE,
11
+ )
12
+ from mpt_extension_sdk.runtime.initializer import initialize
13
+
6
14
 
7
15
  @click.command(
8
16
  add_help_option=False, context_settings=dict(ignore_unknown_options=True)
9
17
  )
10
18
  @click.argument("management_args", nargs=-1, type=click.UNPROCESSED)
11
19
  @click.pass_context
12
- def django(ctx, management_args):
20
+ def django(ctx, management_args): # pragma: no cover
13
21
  "Execute Django subcommands."
14
- from mpt_extension_sdk.runtime.initializer import initialize
15
-
16
- initialize({})
17
22
  from django.conf import settings
18
- from django.core.management import execute_from_command_line
23
+
24
+ initialize(
25
+ {
26
+ "group": DEFAULT_APP_CONFIG_GROUP,
27
+ "name": DEFAULT_APP_CONFIG_NAME,
28
+ "django_settings_module": DJANGO_SETTINGS_MODULE,
29
+ }
30
+ )
19
31
 
20
32
  if settings.USE_APPLICATIONINSIGHTS:
21
33
  tracer = trace.get_tracer(__name__)
@@ -1,4 +1,6 @@
1
1
  import click
2
+ import debugpy
3
+ from django.conf import settings
2
4
 
3
5
  from mpt_extension_sdk.runtime.master import Master
4
6
 
@@ -25,10 +27,8 @@ def run(component, color, debug, reload, debug_py):
25
27
  """
26
28
 
27
29
  if debug_py:
28
- import debugpy
29
-
30
30
  host, port = debug_py.split(":")
31
- debugpy.listen((host, int(port)))
31
+ debugpy.listen((host, int(port))) # pragma: no cover
32
32
 
33
33
  master = Master(
34
34
  {
@@ -37,5 +37,6 @@ def run(component, color, debug, reload, debug_py):
37
37
  "reload": reload,
38
38
  "component": component,
39
39
  },
40
+ settings=settings,
40
41
  )
41
- master.run()
42
+ master.run() # pragma: no cover
@@ -10,7 +10,6 @@ For the full list of settings and their values, see
10
10
  https://docs.djangoproject.com/en/4.2/ref/settings/
11
11
  """
12
12
 
13
- import json
14
13
  import os
15
14
  from pathlib import Path
16
15
 
@@ -26,6 +25,12 @@ BASE_DIR = Path(__file__).resolve().parent.parent
26
25
  # Quick-start development settings - unsuitable for production
27
26
  # See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/
28
27
 
28
+ # SECURITY WARNING: keep the secret key used in production secret!
29
+ SECRET_KEY = os.getenv(
30
+ "MPT_DJANGO_SECRET_KEY",
31
+ "",
32
+ )
33
+
29
34
  # SECURITY WARNING: don't run with debug turned on in production!
30
35
  DEBUG = True
31
36
 
@@ -128,7 +133,7 @@ APPLICATIONINSIGHTS_CONNECTION_STRING = os.getenv(
128
133
  USE_APPLICATIONINSIGHTS = APPLICATIONINSIGHTS_CONNECTION_STRING != ""
129
134
 
130
135
 
131
- if USE_APPLICATIONINSIGHTS:
136
+ if USE_APPLICATIONINSIGHTS: # pragma: no cover
132
137
  logger_provider = LoggerProvider()
133
138
  set_logger_provider(logger_provider)
134
139
  exporter = AzureMonitorLogExporter(
@@ -208,11 +213,7 @@ MPT_ORDERS_API_POLLING_INTERVAL_SECS = int(
208
213
  os.getenv("MPT_ORDERS_API_POLLING_INTERVAL_SECS", "120")
209
214
  )
210
215
 
211
- # TODO: Should be synced with the initializer.py::initialize function
212
- MPT_NOTIFY_CATEGORIES = json.loads(
213
- os.getenv("MPT_NOTIFY_CATEGORIES", '{"ORDERS": "NTC-0000-0006"}')
214
- )
215
-
216
216
  EXTENSION_CONFIG = {
217
217
  "DUE_DATE_DAYS": "30",
218
+ "ORDER_CREATION_WINDOW_HOURS": os.getenv("EXT_ORDER_CREATION_WINDOW_HOURS", "24"),
218
219
  }
@@ -0,0 +1,10 @@
1
+
2
+ from mpt_extension_sdk.constants import (
3
+ DEFAULT_APP_CONFIG_GROUP,
4
+ DEFAULT_APP_CONFIG_NAME,
5
+ )
6
+ from mpt_extension_sdk.runtime.utils import get_extension, get_urlpatterns
7
+
8
+ extension = get_extension(name=DEFAULT_APP_CONFIG_NAME, group=DEFAULT_APP_CONFIG_GROUP)
9
+
10
+ urlpatterns = get_urlpatterns(extension)
@@ -1,11 +1,13 @@
1
- import signal
2
- from threading import Event
1
+ import signal # pragma: no cover
2
+ from threading import Event # pragma: no cover
3
3
 
4
- from django.core.management.base import BaseCommand
4
+ from django.core.management.base import BaseCommand # pragma: no cover
5
5
 
6
- from mpt_extension_sdk.constants import CONSUME_EVENTS_HELP_TEXT
7
- from mpt_extension_sdk.runtime.events.dispatcher import Dispatcher
8
- from mpt_extension_sdk.runtime.events.producers import OrderEventProducer
6
+ from mpt_extension_sdk.constants import CONSUME_EVENTS_HELP_TEXT # pragma: no cover
7
+ from mpt_extension_sdk.runtime.events.dispatcher import Dispatcher # pragma: no cover
8
+ from mpt_extension_sdk.runtime.events.producers import (
9
+ OrderEventProducer, # pragma: no cover
10
+ )
9
11
 
10
12
 
11
13
  class Command(BaseCommand): # pragma: no cover
@@ -5,6 +5,10 @@ import time
5
5
  from collections import deque
6
6
  from concurrent.futures import ThreadPoolExecutor
7
7
 
8
+ from mpt_extension_sdk.constants import (
9
+ DEFAULT_APP_CONFIG_GROUP,
10
+ DEFAULT_APP_CONFIG_NAME,
11
+ )
8
12
  from mpt_extension_sdk.core.events.dataclasses import Event
9
13
  from mpt_extension_sdk.core.events.registry import EventsRegistry
10
14
  from mpt_extension_sdk.core.utils import setup_client
@@ -24,8 +28,8 @@ def done_callback(futures, key, future): # pragma: no cover
24
28
 
25
29
 
26
30
  class Dispatcher:
27
- def __init__(self):
28
- self.registry: EventsRegistry = get_events_registry()
31
+ def __init__(self, group=DEFAULT_APP_CONFIG_GROUP, name=DEFAULT_APP_CONFIG_NAME):
32
+ self.registry: EventsRegistry = get_events_registry(group=group, name=name)
29
33
  self.queue = deque()
30
34
  self.futures = {}
31
35
  self.executor = ThreadPoolExecutor()
@@ -45,7 +49,7 @@ class Dispatcher:
45
49
  def running(self):
46
50
  return self.running_event.is_set()
47
51
 
48
- def dispatch_event(self, event: Event):
52
+ def dispatch_event(self, event: Event): # pragma: no cover
49
53
  if self.registry.is_event_supported(event.type):
50
54
  logger.info(f"event of type {event.type} with id {event.id} accepted")
51
55
  self.queue.appendleft((event.type, event))
@@ -24,10 +24,8 @@ JSON_EXT_VARIABLES = {
24
24
  }
25
25
 
26
26
 
27
- def initialize(options):
27
+ def initialize(options, group=DEFAULT_APP_CONFIG_GROUP, name=DEFAULT_APP_CONFIG_NAME):
28
28
  rich.reconfigure(theme=Theme({"repr.mpt_id": "bold light_salmon3"}))
29
- group = options.get("app_config_group", DEFAULT_APP_CONFIG_GROUP)
30
- name = options.get("app_config_name", DEFAULT_APP_CONFIG_NAME)
31
29
  django_settings_module = options.get(
32
30
  "django_settings_module", DJANGO_SETTINGS_MODULE
33
31
  )
@@ -18,17 +18,18 @@ HANDLED_SIGNALS = (signal.SIGINT, signal.SIGTERM)
18
18
  PROCESS_CHECK_INTERVAL_SECS = int(os.environ.get("PROCESS_CHECK_INTERVAL_SECS", 5))
19
19
 
20
20
 
21
- def _display_path(path):
21
+ def _display_path(path): # pragma: no cover
22
22
  try:
23
23
  return f'"{path.relative_to(Path.cwd())}"'
24
- except ValueError: # pragma: no cover
24
+ except ValueError:
25
25
  return f'"{path}"'
26
26
 
27
27
 
28
28
  class Master:
29
- def __init__(self, options):
29
+ def __init__(self, options, settings):
30
30
  self.workers = {}
31
31
  self.options = options
32
+ self.settings = settings
32
33
  self.stop_event = threading.Event()
33
34
  self.monitor_event = threading.Event()
34
35
  self.watch_filter = PythonFilter(ignore_paths=None)
@@ -4,6 +4,8 @@ import sys
4
4
  from importlib.metadata import entry_points
5
5
 
6
6
  from django.apps import apps
7
+ from django.contrib import admin
8
+ from django.urls import path
7
9
  from pyfiglet import Figlet
8
10
  from rich.console import Console
9
11
  from rich.text import Text
@@ -105,3 +107,23 @@ def get_extension_variables(json_ext_variables):
105
107
 
106
108
  variables[var[0][4:]] = value
107
109
  return variables
110
+
111
+
112
+ def get_api_url(extension):
113
+ if extension:
114
+ api_url = extension.api.urls
115
+ return api_url
116
+ return None
117
+
118
+
119
+ def get_urlpatterns(extension):
120
+ urlpatterns = [
121
+ path("admin/", admin.site.urls),
122
+ ]
123
+
124
+ api_url = get_api_url(extension)
125
+
126
+ if api_url:
127
+ urlpatterns.append(path("api/", api_url))
128
+
129
+ return urlpatterns
@@ -2,6 +2,10 @@ from django.core.management import call_command
2
2
  from django.core.wsgi import get_wsgi_application
3
3
  from gunicorn.app.base import BaseApplication
4
4
 
5
+ from mpt_extension_sdk.constants import (
6
+ DEFAULT_APP_CONFIG_GROUP,
7
+ DEFAULT_APP_CONFIG_NAME,
8
+ )
5
9
  from mpt_extension_sdk.runtime.initializer import initialize
6
10
 
7
11
 
@@ -29,15 +33,18 @@ def start_event_consumer(options):
29
33
  call_command("consume_events")
30
34
 
31
35
 
32
- def start_gunicorn(options):
33
- initialize(options)
36
+ def start_gunicorn(
37
+ options, group=DEFAULT_APP_CONFIG_GROUP, name=DEFAULT_APP_CONFIG_NAME
38
+ ):
39
+ initialize(options, group=group, name=name)
34
40
 
35
41
  logging_config = {
36
42
  "version": 1,
37
43
  "disable_existing_loggers": False,
38
44
  "formatters": {
39
45
  "verbose": {
40
- "format": "{asctime} {name} {levelname} (pid: {process}) {message}",
46
+ "format":
47
+ "{asctime} {name} {levelname} (pid: {process}, thread: {thread}) {message}",
41
48
  "style": "{",
42
49
  },
43
50
  "rich": {
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mpt-extension-sdk
3
- Version: 5.2.0
3
+ Version: 5.2.2
4
4
  Summary: Extensions SDK for SoftwareONE Marketplace Platform
5
5
  Author: SoftwareOne AG
6
6
  License: Apache-2.0 license
@@ -1,5 +1,6 @@
1
1
  mpt_extension_sdk/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- mpt_extension_sdk/constants.py,sha256=4LyR-sUD9-V226jG4cRXKqXKeqjwAj1euL4XRURSfQw,304
2
+ mpt_extension_sdk/constants.py,sha256=lMXalL_Ac67GroFd6xNS93O9wGze368QZ4EFHxFQKTs,304
3
+ mpt_extension_sdk/airtable/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
4
  mpt_extension_sdk/airtable/wrap_http_error.py,sha256=Shiy4uwpdpgkevooLjhpe1grhgJRj7cV6lUMMCQKogc,1263
4
5
  mpt_extension_sdk/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
6
  mpt_extension_sdk/core/extension.py,sha256=s0QE2s99RMywfKQRZrYqOdWxELQvlFFVZMwm0xo2hhw,266
@@ -15,33 +16,34 @@ mpt_extension_sdk/key_vault/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMp
15
16
  mpt_extension_sdk/key_vault/base.py,sha256=RVG_Wiq-MrPyngJ4gfUd8oxoh1LUop1SvtCM2xdlx8M,3361
16
17
  mpt_extension_sdk/mpt_http/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
18
  mpt_extension_sdk/mpt_http/base.py,sha256=3qgo9BW-uTRAbex26urMvLZU0fwnYnBprDRIJCHvTOk,1284
18
- mpt_extension_sdk/mpt_http/mpt.py,sha256=1RXaqYmcopK2mLKNndDflH6eGkYhRYjcM1IyU32KRd0,13451
19
+ mpt_extension_sdk/mpt_http/mpt.py,sha256=zIojPyOLBp1QJB8DXz2fx4P1c0yqfIuknyBOsKppcBg,12816
19
20
  mpt_extension_sdk/mpt_http/utils.py,sha256=3wJTT84CXYGjZw6FksNDX8tIHijkL3Wcmld9r6Iz0xc,95
20
21
  mpt_extension_sdk/mpt_http/wrap_http_error.py,sha256=j8K6Ddx7NiM-FPRMQi25vuULAW8LXxzZ4EwuIJufxis,1801
21
22
  mpt_extension_sdk/runtime/__init__.py,sha256=PQSAz9qvXHbxrn4KvuXSHB8y-A4Jpgbm6ZV-wPiNPyw,194
22
- mpt_extension_sdk/runtime/initializer.py,sha256=3gX9OAeTp2lsgsP0h3HVzkEUvCTa9fBIsBGVo7E6JFY,2229
23
+ mpt_extension_sdk/runtime/initializer.py,sha256=V8fubCULUJlvCBkYhJM52GUNoHNWVI-siaecmZv3kzk,2154
23
24
  mpt_extension_sdk/runtime/logging.py,sha256=wJ6KyvnuvMZELI1Hd0fYbuHr7YiP3GIXFBvvSdmd7nQ,885
24
- mpt_extension_sdk/runtime/master.py,sha256=1p_tYbhtGls0uO78fqs8CqZghxsBvCvXb7DhsO0r4LU,4532
25
+ mpt_extension_sdk/runtime/master.py,sha256=slwZor9IhIVzQBxbUrLNKmHDmnfl9JVA4FMY1nqm0w8,4575
25
26
  mpt_extension_sdk/runtime/swoext.py,sha256=LS0YZXwQsHDaYjalDGfYQi5cAL3aKQhphf3chrNmNBk,1665
26
- mpt_extension_sdk/runtime/utils.py,sha256=ZnRWIBwYzOerx30KFmBXLUe19qzwE4JFNkNMGVqjuyk,3365
27
- mpt_extension_sdk/runtime/workers.py,sha256=k25jFlh-NdHVqeMV2AgoC6IHIlbRHcDoRB5xqWwMPFg,2411
27
+ mpt_extension_sdk/runtime/utils.py,sha256=I4nhj89LDwGG5ukX5K66RqvKv6lo1drUaa3VbaJtZtA,3781
28
+ mpt_extension_sdk/runtime/workers.py,sha256=qlsFSuAgKotGwdFiU0Tq0HDD3PCIBq66h2_JF17s02c,2644
28
29
  mpt_extension_sdk/runtime/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
29
- mpt_extension_sdk/runtime/commands/django.py,sha256=VHszc3KctzSkhewAqbQMkRBG7cuMPWxzn7dHrRGm8y8,892
30
- mpt_extension_sdk/runtime/commands/run.py,sha256=1Qrqr2Hq1J8JvXtmEdgUNU9u3JLd_92-NR9MKrZOFxo,1052
30
+ mpt_extension_sdk/runtime/commands/django.py,sha256=o3oxOuO1klx1ra9BCkhqHmekMnOAUFah7dPmlcJmLA8,1213
31
+ mpt_extension_sdk/runtime/commands/run.py,sha256=U_tVtMZQn2kstz3b4ANvs45hqDKs-PfLq3-vaukh5kw,1143
31
32
  mpt_extension_sdk/runtime/djapp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
32
33
  mpt_extension_sdk/runtime/djapp/apps.py,sha256=YA1G5HaRqFBS-0DfYQuFpMgzUCYpu5T8x5LEC6MwI_M,1398
33
34
  mpt_extension_sdk/runtime/djapp/middleware.py,sha256=oAA5khXW6xeUjnOV63pNCF4D7QFVD6PayIa_489KRmg,555
34
35
  mpt_extension_sdk/runtime/djapp/conf/__init__.py,sha256=_sHo76rGeXSTH8bW3pacyGFfNYSln8oLRwOSstYOmco,350
35
- mpt_extension_sdk/runtime/djapp/conf/default.py,sha256=vOtxAZkIJ78D1p1mua3Ls6BwmNybW7NZl2G7F3jb33k,6120
36
+ mpt_extension_sdk/runtime/djapp/conf/default.py,sha256=Io-dz0ylmVY_3tpZm0_K5JcxZXHlgeW1RFwAXMchCro,6167
37
+ mpt_extension_sdk/runtime/djapp/conf/urls.py,sha256=x-LDNfqckwvnEqHVFk8DttDZpYWjoF_JbJgu_itJSZE,310
36
38
  mpt_extension_sdk/runtime/djapp/management/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
37
39
  mpt_extension_sdk/runtime/djapp/management/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
- mpt_extension_sdk/runtime/djapp/management/commands/consume_events.py,sha256=1rfldJpnKgpgAhW15wkJ_TLb_TKimkC5hryn1TPEfuk,1100
40
+ mpt_extension_sdk/runtime/djapp/management/commands/consume_events.py,sha256=BVb4sgKI2Ep759bDcOH5Qm1xJEewc5-bNt_snspV2ck,1229
39
41
  mpt_extension_sdk/runtime/events/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
40
- mpt_extension_sdk/runtime/events/dispatcher.py,sha256=GYICBuA9bO38TgDk0FKS_Z9D-8YB-tmNf4O_pUxuomc,2801
42
+ mpt_extension_sdk/runtime/events/dispatcher.py,sha256=ZMswk50vGGfUgKeQ2Cc3k9wtrm63z0OH7EtlKCkWQYM,3008
41
43
  mpt_extension_sdk/runtime/events/producers.py,sha256=dv-PWN9hKOBxT6nyLWezjZxUq6NpPz8Jq-cOiVEcDUY,3604
42
44
  mpt_extension_sdk/runtime/events/utils.py,sha256=bxFo-iQUqEJDqcIotC88Ty3Xt0K2FyYjA9UMWFEyMKI,2663
43
- mpt_extension_sdk-5.2.0.dist-info/METADATA,sha256=W-8wrxSWN6L94bREMEhGYGGRC5UVXYqlTRIoFuAzEGw,1386
44
- mpt_extension_sdk-5.2.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
45
- mpt_extension_sdk-5.2.0.dist-info/entry_points.txt,sha256=N8T9gBssEOm_UeBf9ABbGqtlnethrumfMoL4hNYWVFA,146
46
- mpt_extension_sdk-5.2.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
47
- mpt_extension_sdk-5.2.0.dist-info/RECORD,,
45
+ mpt_extension_sdk-5.2.2.dist-info/METADATA,sha256=BKkSIxFuVCmJaaHIZtwjJbpxajx8RmjlFV4PjIK2BHw,1386
46
+ mpt_extension_sdk-5.2.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
47
+ mpt_extension_sdk-5.2.2.dist-info/entry_points.txt,sha256=N8T9gBssEOm_UeBf9ABbGqtlnethrumfMoL4hNYWVFA,146
48
+ mpt_extension_sdk-5.2.2.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
49
+ mpt_extension_sdk-5.2.2.dist-info/RECORD,,