orchestrator-core 4.5.0a4__py3-none-any.whl → 4.5.0a6__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.
orchestrator/__init__.py CHANGED
@@ -13,7 +13,7 @@
13
13
 
14
14
  """This is the orchestrator workflow engine."""
15
15
 
16
- __version__ = "4.5.0a4"
16
+ __version__ = "4.5.0a6"
17
17
 
18
18
 
19
19
  from structlog import get_logger
@@ -244,6 +244,8 @@ def continue_awaiting_process_endpoint(
244
244
  continue_awaiting_process(process, token=token, input_data=json_data, broadcast_func=broadcast_func)
245
245
  except AssertionError as e:
246
246
  raise_status(HTTPStatus.NOT_FOUND, str(e))
247
+ except ValueError as e:
248
+ raise_status(HTTPStatus.BAD_REQUEST, str(e))
247
249
 
248
250
 
249
251
  @router.post(
@@ -614,9 +614,7 @@ class ProductBlockModel(DomainModel):
614
614
  product_blocks_in_model = cls._get_depends_on_product_block_types()
615
615
  product_blocks_types_in_model = get_depends_on_product_block_type_list(product_blocks_in_model)
616
616
 
617
- product_blocks_in_model = set(
618
- flatten(map(attrgetter("__names__"), product_blocks_types_in_model))
619
- ) # type: ignore
617
+ product_blocks_in_model = set(flatten(map(attrgetter("__names__"), product_blocks_types_in_model))) # type: ignore
620
618
 
621
619
  missing_product_blocks_in_db = product_blocks_in_model - product_blocks_in_db # type: ignore
622
620
  missing_product_blocks_in_model = product_blocks_in_db - product_blocks_in_model # type: ignore
@@ -1084,9 +1082,7 @@ class SubscriptionModel(DomainModel):
1084
1082
  product_blocks_in_model = cls._get_depends_on_product_block_types()
1085
1083
  product_blocks_types_in_model = get_depends_on_product_block_type_list(product_blocks_in_model)
1086
1084
 
1087
- product_blocks_in_model = set(
1088
- flatten(map(attrgetter("__names__"), product_blocks_types_in_model))
1089
- ) # type: ignore
1085
+ product_blocks_in_model = set(flatten(map(attrgetter("__names__"), product_blocks_types_in_model))) # type: ignore
1090
1086
 
1091
1087
  missing_product_blocks_in_db = product_blocks_in_model - product_blocks_in_db # type: ignore
1092
1088
  missing_product_blocks_in_model = product_blocks_in_db - product_blocks_in_model # type: ignore
@@ -1294,7 +1290,6 @@ class SubscriptionModel(DomainModel):
1294
1290
  # Some common functions shared by from_other_product and from_subscription
1295
1291
  @classmethod
1296
1292
  def _get_subscription(cls: type[S], subscription_id: UUID | UUIDstr) -> SubscriptionTable | None:
1297
-
1298
1293
  if not isinstance(subscription_id, UUID | UUIDstr):
1299
1294
  raise TypeError(f"subscription_id is of type {type(subscription_id)} instead of UUID | UUIDstr")
1300
1295
 
@@ -16,11 +16,16 @@ from typing import TYPE_CHECKING, TypeVar
16
16
  import strawberry
17
17
  import structlog
18
18
 
19
+ from orchestrator.settings import LifecycleValidationMode, app_settings
19
20
  from orchestrator.types import SubscriptionLifecycle
20
21
  from pydantic_forms.types import strEnum
21
22
 
22
23
  if TYPE_CHECKING:
23
- from orchestrator.domain.base import DomainModel
24
+ from orchestrator.domain.base import DomainModel, SubscriptionModel
25
+ else:
26
+ SubscriptionModel = None
27
+ DomainModel = None
28
+ T = TypeVar("T", bound=SubscriptionModel)
24
29
 
25
30
  logger = structlog.get_logger(__name__)
26
31
 
@@ -71,9 +76,21 @@ def validate_lifecycle_status(
71
76
  )
72
77
 
73
78
 
74
- if TYPE_CHECKING:
75
- from orchestrator.domain.base import DomainModel, SubscriptionModel
76
- else:
77
- SubscriptionModel = None
78
- DomainModel = None
79
- T = TypeVar("T", bound=SubscriptionModel)
79
+ def validate_subscription_model_product_type(
80
+ subscription: SubscriptionModel,
81
+ validation_mode: LifecycleValidationMode = app_settings.LIFECYCLE_VALIDATION_MODE,
82
+ ) -> None:
83
+ """Validate that a subscription model has been instantiated with the correct product type class for its lifecycle status."""
84
+
85
+ actual_class = subscription.__class__
86
+ expected_class = lookup_specialized_type(actual_class, subscription.status)
87
+
88
+ if actual_class != expected_class:
89
+ msg = f"Subscription of type {actual_class} should use {expected_class} for lifecycle status '{subscription.status}'"
90
+ if validation_mode == LifecycleValidationMode.STRICT:
91
+ logger.error(msg)
92
+ raise ValueError(msg)
93
+ if validation_mode == LifecycleValidationMode.LOOSE:
94
+ logger.warning(msg)
95
+ elif validation_mode == LifecycleValidationMode.IGNORED:
96
+ pass
@@ -166,12 +166,16 @@ def create_workflow(conn: sa.engine.Connection, workflow: dict) -> None:
166
166
  "is_task": False,
167
167
  "description": "workflow description",
168
168
  "product_type": "product_type",
169
+ "product_tag": "product_tag",
169
170
  }
170
171
  >>> create_workflow(conn, workflow)
171
172
  """
172
173
  if not workflow.get("is_task", False):
173
174
  workflow["is_task"] = False
174
175
 
176
+ if not workflow.get("product_tag"):
177
+ workflow["product_tag"] = None
178
+
175
179
  if has_table_column(table_name="workflows", column_name="is_task", conn=conn):
176
180
  query = """
177
181
  WITH new_workflow AS (
@@ -186,6 +190,7 @@ def create_workflow(conn: sa.engine.Connection, workflow: dict) -> None:
186
190
  FROM products AS p
187
191
  CROSS JOIN new_workflow AS nw
188
192
  WHERE p.product_type = :product_type
193
+ AND (:product_tag IS NULL OR p.tag = :product_tag)
189
194
  ON CONFLICT DO NOTHING
190
195
  """
191
196
  else:
@@ -203,6 +208,7 @@ def create_workflow(conn: sa.engine.Connection, workflow: dict) -> None:
203
208
  FROM products AS p
204
209
  CROSS JOIN new_workflow AS nw
205
210
  WHERE p.product_type = :product_type
211
+ AND (:product_tag IS NULL OR p.tag = :product_tag)
206
212
  ON CONFLICT DO NOTHING
207
213
  """
208
214
 
@@ -524,6 +524,7 @@ def restart_process(
524
524
  RESUMABLE_STATUSES = (
525
525
  ProcessStatus.SUSPENDED, # Can be resumed
526
526
  ProcessStatus.WAITING, # Can be retried
527
+ ProcessStatus.AWAITING_CALLBACK, # Can be resumed
527
528
  ProcessStatus.FAILED, # Can be retried
528
529
  ProcessStatus.API_UNAVAILABLE, # subtype of FAILED
529
530
  ProcessStatus.INCONSISTENT_DATA, # subtype of FAILED
orchestrator/settings.py CHANGED
@@ -30,6 +30,12 @@ class ExecutorType(strEnum):
30
30
  THREADPOOL = "threadpool"
31
31
 
32
32
 
33
+ class LifecycleValidationMode(strEnum):
34
+ STRICT = "strict"
35
+ LOOSE = "loose"
36
+ IGNORED = "ignored"
37
+
38
+
33
39
  class AppSettings(BaseSettings):
34
40
  TESTING: bool = True
35
41
  SESSION_SECRET: OrchSecretStr = "".join(secrets.choice(string.ascii_letters) for i in range(16)) # type: ignore
@@ -91,6 +97,7 @@ class AppSettings(BaseSettings):
91
97
  FILTER_BY_MODE: Literal["partial", "exact"] = "exact"
92
98
  EXPOSE_SETTINGS: bool = False
93
99
  EXPOSE_OAUTH_SETTINGS: bool = False
100
+ LIFECYCLE_VALIDATION_MODE: LifecycleValidationMode = LifecycleValidationMode.LOOSE
94
101
 
95
102
 
96
103
  app_settings = AppSettings()
@@ -19,6 +19,7 @@ from typing import Any, cast, get_args
19
19
  from uuid import UUID
20
20
 
21
21
  from orchestrator.domain.base import SubscriptionModel
22
+ from orchestrator.domain.lifecycle import validate_subscription_model_product_type
22
23
  from orchestrator.types import StepFunc, is_list_type, is_optional_type
23
24
  from orchestrator.utils.functional import logger
24
25
  from pydantic_forms.types import (
@@ -135,7 +136,7 @@ def _save_models(state: State) -> None:
135
136
  def _build_arguments(func: StepFunc | InputStepFunc, state: State) -> list: # noqa: C901
136
137
  """Build actual arguments based on step function signature and state.
137
138
 
138
- What the step function requests in its function signature it what this function retrieves from the state or DB.
139
+ What the step function requests in its function signature is what this function retrieves from the state or DB.
139
140
  Domain models are retrieved from the DB (after `subscription_id` lookup in the state). Everything else is
140
141
  retrieved from the state.
141
142
 
@@ -186,6 +187,7 @@ def _build_arguments(func: StepFunc | InputStepFunc, state: State) -> list: # n
186
187
  subscription_id = _get_sub_id(state.get(name))
187
188
  if subscription_id:
188
189
  sub_mod = param.annotation.from_subscription(subscription_id)
190
+ validate_subscription_model_product_type(sub_mod)
189
191
  arguments.append(sub_mod)
190
192
  else:
191
193
  logger.error("Could not find key in state.", key=name, state=state)
@@ -198,12 +200,15 @@ def _build_arguments(func: StepFunc | InputStepFunc, state: State) -> list: # n
198
200
  f"Step function argument '{param.name}' cannot be serialized from database with type 'Any'"
199
201
  )
200
202
  subscriptions = [actual_type.from_subscription(subscription_id) for subscription_id in subscription_ids]
203
+ for sub_mod in subscriptions:
204
+ validate_subscription_model_product_type(sub_mod)
201
205
  arguments.append(subscriptions)
202
206
  elif is_optional_type(param.annotation, SubscriptionModel):
203
207
  subscription_id = _get_sub_id(state.get(name))
204
208
  if subscription_id:
205
209
  # Actual type is first argument from optional type
206
210
  sub_mod = get_args(param.annotation)[0].from_subscription(subscription_id)
211
+ validate_subscription_model_product_type(sub_mod)
207
212
  arguments.append(sub_mod)
208
213
  else:
209
214
  arguments.append(None)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: orchestrator-core
3
- Version: 4.5.0a4
3
+ Version: 4.5.0a6
4
4
  Summary: This is the orchestrator workflow engine.
5
5
  Author-email: SURF <automation-beheer@surf.nl>
6
6
  Requires-Python: >=3.11,<3.14
@@ -79,7 +79,7 @@ Provides-Extra: llm
79
79
  [![codecov](https://codecov.io/gh/workfloworchestrator/orchestrator-core/branch/main/graph/badge.svg?token=5ANQFI2DHS)](https://codecov.io/gh/workfloworchestrator/orchestrator-core)
80
80
  [![pypi_version](https://img.shields.io/pypi/v/orchestrator-core?color=%2334D058&label=pypi%20package)](https://pypi.org/project/orchestrator-core)
81
81
  [![Supported python versions](https://img.shields.io/pypi/pyversions/orchestrator-core.svg?color=%2334D058)](https://pypi.org/project/orchestrator-core)
82
- ![Discord](https://img.shields.io/discord/1295834294270558280?style=flat&logo=discord&label=discord&link=https%3A%2F%2Fdiscord.gg%2FKNgF6gE8)
82
+ ![Discord](https://img.shields.io/discord/1295834294270558280?style=flat&logo=discord&label=discord&link=https%3A%2F%2Fdiscord.gg%fQkQn5ajFR)
83
83
 
84
84
  <p style="text-align: center"><em>Production ready Orchestration Framework to manage product lifecycle and workflows. Easy to use, built on top of FastAPI and Pydantic</em></p>
85
85
 
@@ -1,4 +1,4 @@
1
- orchestrator/__init__.py,sha256=gq8astkBpaXLyuRcNaKMx-qGkG8YOvUJ3A6-yBFBfDo,1732
1
+ orchestrator/__init__.py,sha256=F2rD2p-hLcFjUslWKOUIoLQwd-MMglQNUA3EPCszEdk,1732
2
2
  orchestrator/agentic_app.py,sha256=bBMuH9Ub42nb8oFG0U00SzW_uQqnAayUX2tNs6yz1BM,2810
3
3
  orchestrator/app.py,sha256=UPKQuDpg8MWNC6r3SRRbp6l9RBzwb00IMIaGRk-jbCU,13203
4
4
  orchestrator/exception_handlers.py,sha256=UsW3dw8q0QQlNLcV359bIotah8DYjMsj2Ts1LfX4ClY,1268
@@ -6,7 +6,7 @@ orchestrator/llm_settings.py,sha256=PJ3vf5aEugVigHFU7iw9haQon_bC7Y268GTFhfFaQHs,
6
6
  orchestrator/log_config.py,sha256=1cPl_OXT4tEUyNxG8cwIWXrmadUm1E81vq0mdtrV-v4,1912
7
7
  orchestrator/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
8
  orchestrator/security.py,sha256=iXFxGxab54aav7oHEKLAVkTgrQMJGHy6IYLojEnD7gI,2422
9
- orchestrator/settings.py,sha256=30iYKd_wNtjIO12DZ4LrH9w9OJgtmQ2AFEOSnrVTsRg,4365
9
+ orchestrator/settings.py,sha256=Xl6bXd2VtosBTOuv4PClgVv9KoVDItThYkhDzf4IYxc,4560
10
10
  orchestrator/targets.py,sha256=d7Fyh_mWIWPivA_E7DTNFpZID3xFW_K0JlZ5nksVX7k,830
11
11
  orchestrator/types.py,sha256=qzs7xx5AYRmKbpYRyJJP3wuDb0W0bcAzefCN0RWLAco,15459
12
12
  orchestrator/version.py,sha256=b58e08lxs47wUNXv0jXFO_ykpksmytuzEXD4La4W-NQ,1366
@@ -19,7 +19,7 @@ orchestrator/api/api_v1/__init__.py,sha256=GyHNfEFCGKQwRiN6rQmvSRH2iYX7npjMZn97n
19
19
  orchestrator/api/api_v1/api.py,sha256=7_alDkK-UfqCauCSCFfQzDIwZHVI_CrRvLCMuCR0408,3276
20
20
  orchestrator/api/api_v1/endpoints/__init__.py,sha256=GyHNfEFCGKQwRiN6rQmvSRH2iYX7npjMZn97n8XzmLU,571
21
21
  orchestrator/api/api_v1/endpoints/health.py,sha256=iaxs1XX1_250_gKNsspuULCV2GEMBjbtjsmfQTOvMAI,1284
22
- orchestrator/api/api_v1/endpoints/processes.py,sha256=238Bydgj4ILNyMU_7j_Q7a0WGlfIvKv5ypP7lESU32w,16188
22
+ orchestrator/api/api_v1/endpoints/processes.py,sha256=OVbt6FgFnJ4aHaYGIg0cPoim8mxDpdzJ4TGAyfB_kPw,16269
23
23
  orchestrator/api/api_v1/endpoints/product_blocks.py,sha256=kZ6ywIOsS_S2qGq7RvZ4KzjvaS1LmwbGWR37AKRvWOw,2146
24
24
  orchestrator/api/api_v1/endpoints/products.py,sha256=BfFtwu9dZXEQbtKxYj9icc73GKGvAGMR5ytyf41nQlQ,3081
25
25
  orchestrator/api/api_v1/endpoints/resource_types.py,sha256=gGyuaDyOD0TAVoeFGaGmjDGnQ8eQQArOxKrrk4MaDzA,2145
@@ -149,11 +149,11 @@ orchestrator/distlock/managers/__init__.py,sha256=ImIkNsrXcyE7-NgRWqEhUXUuUzda9K
149
149
  orchestrator/distlock/managers/memory_distlock_manager.py,sha256=HWQafcVKBF-Cka_wukZZ1GM69AWPVOpJPje3quIebQ8,3114
150
150
  orchestrator/distlock/managers/redis_distlock_manager.py,sha256=DXtMhC8qtxiFO6xU9qYXHZQnCLjlmGBpeyfLA0vbRP0,3369
151
151
  orchestrator/domain/__init__.py,sha256=20DhXQPKY0g3rTgCkRlNDY58sLviToOVF8NPoex9WJc,936
152
- orchestrator/domain/base.py,sha256=jjMxJvt0GyaTff_z490lmkqDCtitkh0oA4GygB60n4s,69939
152
+ orchestrator/domain/base.py,sha256=8_f4zmaKHIy4JtyY_QgLoF8_-llgW9-7QOfqAJgacEw,69894
153
153
  orchestrator/domain/context_cache.py,sha256=vT1a01MBSBIaokoShK9KwjItd7abNmz7cXaF67VRZK8,2508
154
154
  orchestrator/domain/customer_description.py,sha256=RU_pcgCIZjjFfDsY45lfV0z6ATlS1NXtB0E7eH3UcYQ,3190
155
155
  orchestrator/domain/helpers.py,sha256=D9O2duhCAZGmm39u-9ggvU-X2JsCbIS607kF77-r8QM,2549
156
- orchestrator/domain/lifecycle.py,sha256=kGR0AFVOSUBlzdhgRr11CUnF26wbBYIjz8uKb_qPCg0,2922
156
+ orchestrator/domain/lifecycle.py,sha256=FO31mhgtHbq5H3Qr9vzA36PxSLu_icJqcuqFex0PQnk,3823
157
157
  orchestrator/domain/subscription_instance_transform.py,sha256=j_d49dFcSss0dl-BHS-ev2faLbE0y8hLvCfrzui6C74,4360
158
158
  orchestrator/forms/__init__.py,sha256=bw_1238HKy_T0gvfA5oEjJFwkALzvWU4O_VJ0xE8UyU,1168
159
159
  orchestrator/forms/validators/__init__.py,sha256=2T7w429dQhChsAbnQDeyp2BrM_iKj6-nkNrz27RZatY,1906
@@ -220,7 +220,7 @@ orchestrator/migrations/README,sha256=heMzebYwlGhnE8_4CWJ4LS74WoEZjBy-S-mIJRxAEK
220
220
  orchestrator/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
221
221
  orchestrator/migrations/alembic.ini,sha256=kMoADqhGeubU8xanILNaqm4oixLy9m4ngYtdGpZcc7I,873
222
222
  orchestrator/migrations/env.py,sha256=M_cPoAL2axuuup5fvMy8I_WTPHEw0RbPEHkhZ3QEGoE,3740
223
- orchestrator/migrations/helpers.py,sha256=g3G8P5IQ1OI4kmlNP8L0v9nzWvekzXwilXLdEvbN9ZI,47992
223
+ orchestrator/migrations/helpers.py,sha256=sgSNZzQFHGT9_nboxwp_ryP2CWQZsSqEg_0i4giIM2k,48248
224
224
  orchestrator/migrations/script.py.mako,sha256=607Zrgp-Z-m9WGLt4wewN1QDOmHeifxcePUdADkSZyM,510
225
225
  orchestrator/migrations/templates/alembic.ini.j2,sha256=8v7UbKvOiWEbEKQa-Au3uONKUuYx6aflulYanZX6r2I,883
226
226
  orchestrator/migrations/templates/env.py.j2,sha256=LIt0ildZTZvNEx3imhy4GNzfFi_rPZg-8H7rGgrBOP8,2717
@@ -319,7 +319,7 @@ orchestrator/services/__init__.py,sha256=GyHNfEFCGKQwRiN6rQmvSRH2iYX7npjMZn97n8X
319
319
  orchestrator/services/fixed_inputs.py,sha256=kyz7s2HLzyDulvcq-ZqefTw1om86COvyvTjz0_5CmgI,876
320
320
  orchestrator/services/input_state.py,sha256=6BZOpb3cHpO18K-XG-3QUIV9pIM25_ufdODrp5CmXG4,2390
321
321
  orchestrator/services/process_broadcast_thread.py,sha256=D44YbjF8mRqGuznkRUV4SoRn1J0lfy_x1H508GnSVlU,4649
322
- orchestrator/services/processes.py,sha256=NfzdtH4eZK_wYuSmFtUX69qDvoeI8J7sJ2fFyY_VYaM,30544
322
+ orchestrator/services/processes.py,sha256=V-BHR8-9qw5cFHRuBJK8UkRQgCwQxFQbOnnwpKzJm0o,30599
323
323
  orchestrator/services/products.py,sha256=BP4KyE8zO-8z7Trrs5T6zKBOw53S9BfBJnHWI3p6u5Y,1943
324
324
  orchestrator/services/resource_types.py,sha256=_QBy_JOW_X3aSTqH0CuLrq4zBJL0p7Q-UDJUcuK2_qc,884
325
325
  orchestrator/services/settings.py,sha256=HEWfFulgoEDwgfxGEO__QTr5fDiwNBEj1UhAeTAdbLQ,3159
@@ -350,7 +350,7 @@ orchestrator/utils/json.py,sha256=7386sdqkrKYyy4sbn5NscwctH_v1hLyw5172P__rU3g,83
350
350
  orchestrator/utils/redis.py,sha256=BjUNmrKx8YVyJIucl2mhXubK6WV-49OnAU6rPMOZpM0,4469
351
351
  orchestrator/utils/redis_client.py,sha256=9rhsvedjK_CyClAjUicQyge0mVIViATqKFGZyjBY3XA,1384
352
352
  orchestrator/utils/search_query.py,sha256=ji5LHtrzohGz6b1IG41cnPdpWXzLEzz4SGWgHly_yfU,16205
353
- orchestrator/utils/state.py,sha256=RYKVlvKDBfsBdDk9wHjZKBTlQJbV4SqtCotAlTA2-bI,14021
353
+ orchestrator/utils/state.py,sha256=ELH08cxvpmpnJg_ae0sMi9m_QX6SqHxNzOFaJgyW9gM,14344
354
354
  orchestrator/utils/strings.py,sha256=N0gWjmQaMjE9_99VtRvRaU8IBLTKMgBKSXcTZ9TpWAg,1077
355
355
  orchestrator/utils/validate_data_version.py,sha256=3Eioy2wE2EWKSgkyMKcEKrkCAfUIAq-eb73iRcpgppw,184
356
356
  orchestrator/websocket/__init__.py,sha256=V79jskk1z3uPIYgu0Gt6JLzuqr7NGfNeAZ-hbBqoUv4,5745
@@ -368,7 +368,7 @@ orchestrator/workflows/tasks/resume_workflows.py,sha256=T3iobSJjVgiupe0rClD34kUZ
368
368
  orchestrator/workflows/tasks/validate_product_type.py,sha256=paG-NAY1bdde3Adt8zItkcBKf5Pxw6f5ngGW6an6dYU,3192
369
369
  orchestrator/workflows/tasks/validate_products.py,sha256=kXBGZTkobfYH8e_crhdErT-ypdouH0a3_WLImmbKXcE,8523
370
370
  orchestrator/workflows/translations/en-GB.json,sha256=ST53HxkphFLTMjFHonykDBOZ7-P_KxksktZU3GbxLt0,846
371
- orchestrator_core-4.5.0a4.dist-info/licenses/LICENSE,sha256=b-aA5OZQuuBATmLKo_mln8CQrDPPhg3ghLzjPjLn4Tg,11409
372
- orchestrator_core-4.5.0a4.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
373
- orchestrator_core-4.5.0a4.dist-info/METADATA,sha256=nBP_0HuGT9zaSzcgUuBYsokJLEXmTCoFON0VPm_ISpY,6170
374
- orchestrator_core-4.5.0a4.dist-info/RECORD,,
371
+ orchestrator_core-4.5.0a6.dist-info/licenses/LICENSE,sha256=b-aA5OZQuuBATmLKo_mln8CQrDPPhg3ghLzjPjLn4Tg,11409
372
+ orchestrator_core-4.5.0a6.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
373
+ orchestrator_core-4.5.0a6.dist-info/METADATA,sha256=o1E60Zu0I3TwNWdQqrZPeRrhiwtTmsIkHSAq0jeKsSM,6170
374
+ orchestrator_core-4.5.0a6.dist-info/RECORD,,