iris-pex-embedded-python 3.7.2b2__py3-none-any.whl → 4.0.0__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.
Files changed (119) hide show
  1. iop/__init__.py +276 -18
  2. iop/__main__.py +3 -3
  3. iop/cli/__init__.py +1 -0
  4. iop/cli/formatting.py +45 -0
  5. iop/{_cli.py → cli/main.py} +238 -216
  6. iop/cli/parser.py +165 -0
  7. iop/cli/types.py +73 -0
  8. iop/cls/IOP/Common.cls +11 -2
  9. iop/cls/IOP/PrivateSession/Duplex.cls +1 -1
  10. iop/cls/IOP/Service/Remote/Rest/v1.cls +152 -5
  11. iop/cls/IOP/Utils.cls +814 -7
  12. iop/cls/IOP/Wrapper.cls +1 -1
  13. iop/components/__init__.py +16 -0
  14. iop/{_async_request.py → components/async_request.py} +7 -7
  15. iop/components/business_host.py +363 -0
  16. iop/components/business_operation.py +84 -0
  17. iop/{_business_process.py → components/business_process.py} +145 -125
  18. iop/components/business_service.py +106 -0
  19. iop/{_common.py → components/common.py} +160 -164
  20. iop/{_debugpy.py → components/debugpy.py} +11 -11
  21. iop/{_generator_request.py → components/generator_request.py} +4 -4
  22. iop/{_inbound_adapter.py → components/inbound_adapter.py} +10 -18
  23. iop/{_log_manager.py → components/log_manager.py} +1 -1
  24. iop/{_outbound_adapter.py → components/outbound_adapter.py} +1 -1
  25. iop/components/polling_business_service.py +48 -0
  26. iop/{_private_session_duplex.py → components/private_session_duplex.py} +7 -9
  27. iop/{_private_session_process.py → components/private_session_process.py} +2 -2
  28. iop/{_settings.py → components/settings.py} +23 -3
  29. iop/messages/__init__.py +7 -0
  30. iop/messages/base.py +61 -0
  31. iop/{_decorators.py → messages/decorators.py} +8 -2
  32. iop/messages/dispatch.py +351 -0
  33. iop/{_persistent_message.py → messages/persistent.py} +24 -19
  34. iop/{_serialization.py → messages/serialization.py} +34 -21
  35. iop/{_message_validator.py → messages/validation.py} +15 -13
  36. iop/migration/__init__.py +1 -0
  37. iop/migration/io.py +61 -0
  38. iop/migration/manifest.py +534 -0
  39. iop/migration/plans.py +80 -0
  40. iop/migration/utils.py +1126 -0
  41. iop/production/__init__.py +55 -0
  42. iop/production/actions.py +525 -0
  43. iop/production/common.py +103 -0
  44. iop/production/component.py +234 -0
  45. iop/production/declarations.py +190 -0
  46. iop/production/declarative.py +214 -0
  47. iop/production/diff.py +327 -0
  48. iop/production/import_.py +296 -0
  49. iop/production/inspection.py +92 -0
  50. iop/production/model.py +1143 -0
  51. iop/production/planning.py +678 -0
  52. iop/production/reconstruction.py +341 -0
  53. iop/production/rendering.py +610 -0
  54. iop/production/runtime.py +91 -0
  55. iop/production/source_inference.py +729 -0
  56. iop/production/types.py +546 -0
  57. iop/production/validation.py +452 -0
  58. iop/runtime/__init__.py +1 -0
  59. iop/runtime/director.py +415 -0
  60. iop/runtime/environment.py +59 -0
  61. iop/{_iris.py → runtime/iris.py} +2 -2
  62. iop/runtime/local.py +145 -0
  63. iop/{_director_protocol.py → runtime/protocol.py} +25 -8
  64. iop/runtime/remote/__init__.py +12 -0
  65. iop/runtime/remote/client.py +90 -0
  66. iop/runtime/remote/director.py +283 -0
  67. iop/runtime/remote/migration.py +57 -0
  68. iop/runtime/remote/settings.py +69 -0
  69. iop/runtime/remote/setup.py +72 -0
  70. {iris_pex_embedded_python-3.7.2b2.dist-info → iris_pex_embedded_python-4.0.0.dist-info}/METADATA +11 -2
  71. iris_pex_embedded_python-4.0.0.dist-info/RECORD +99 -0
  72. iris_pex_embedded_python-4.0.0.dist-info/entry_points.txt +2 -0
  73. iris_pex_embedded_python-4.0.0.dist-info/top_level.txt +1 -0
  74. grongier/__init__.py +0 -0
  75. grongier/cls/Grongier/PEX/BusinessOperation.cls +0 -8
  76. grongier/cls/Grongier/PEX/BusinessProcess.cls +0 -13
  77. grongier/cls/Grongier/PEX/BusinessService.cls +0 -8
  78. grongier/cls/Grongier/PEX/Common.cls +0 -10
  79. grongier/cls/Grongier/PEX/Director.cls +0 -10
  80. grongier/cls/Grongier/PEX/Duplex/Operation.cls +0 -4
  81. grongier/cls/Grongier/PEX/Duplex/Process.cls +0 -13
  82. grongier/cls/Grongier/PEX/Duplex/Service.cls +0 -4
  83. grongier/cls/Grongier/PEX/InboundAdapter.cls +0 -8
  84. grongier/cls/Grongier/PEX/Message.cls +0 -13
  85. grongier/cls/Grongier/PEX/OutboundAdapter.cls +0 -8
  86. grongier/cls/Grongier/PEX/PickleMessage.cls +0 -13
  87. grongier/cls/Grongier/PEX/PrivateSession/Duplex.cls +0 -8
  88. grongier/cls/Grongier/PEX/PrivateSession/Message/Ack.cls +0 -14
  89. grongier/cls/Grongier/PEX/PrivateSession/Message/Poll.cls +0 -14
  90. grongier/cls/Grongier/PEX/PrivateSession/Message/Start.cls +0 -14
  91. grongier/cls/Grongier/PEX/PrivateSession/Message/Stop.cls +0 -14
  92. grongier/cls/Grongier/PEX/Test.cls +0 -10
  93. grongier/cls/Grongier/PEX/Utils.cls +0 -10
  94. grongier/cls/Grongier/Service/WSGI.cls +0 -4
  95. grongier/pex/__init__.py +0 -75
  96. grongier/pex/__main__.py +0 -4
  97. grongier/pex/_business_host.py +0 -1
  98. grongier/pex/_cli.py +0 -4
  99. grongier/pex/_common.py +0 -1
  100. grongier/pex/_director.py +0 -1
  101. grongier/pex/_utils.py +0 -1
  102. grongier/pex/wsgi/handlers.py +0 -104
  103. iop/_business_host.py +0 -322
  104. iop/_business_operation.py +0 -77
  105. iop/_business_service.py +0 -67
  106. iop/_director.py +0 -333
  107. iop/_dispatch.py +0 -194
  108. iop/_local.py +0 -106
  109. iop/_message.py +0 -45
  110. iop/_polling_business_service.py +0 -6
  111. iop/_remote.py +0 -473
  112. iop/_utils.py +0 -912
  113. iop/cls/IOP/Service/WSGI.cls +0 -310
  114. iop/wsgi/handlers.py +0 -112
  115. iris_pex_embedded_python-3.7.2b2.dist-info/RECORD +0 -96
  116. iris_pex_embedded_python-3.7.2b2.dist-info/entry_points.txt +0 -2
  117. iris_pex_embedded_python-3.7.2b2.dist-info/top_level.txt +0 -2
  118. {iris_pex_embedded_python-3.7.2b2.dist-info → iris_pex_embedded_python-4.0.0.dist-info}/WHEEL +0 -0
  119. {iris_pex_embedded_python-3.7.2b2.dist-info → iris_pex_embedded_python-4.0.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,341 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any
4
+
5
+ from .component import ComponentRef
6
+ from .import_ import (
7
+ _as_list,
8
+ _is_internal_runtime_target,
9
+ _matching_host_setting,
10
+ _normalize_connections,
11
+ _normalize_queue_info,
12
+ _normalize_runtime_item_metadata,
13
+ _production_payload,
14
+ _setting_targets,
15
+ _split_production_settings,
16
+ _split_settings,
17
+ )
18
+ from .source_inference import infer_source_connections
19
+ from .types import GraphEdge
20
+
21
+
22
+ def production_from_dict(
23
+ production_cls,
24
+ data: dict[str, Any],
25
+ *,
26
+ connections: Any = None,
27
+ queue_info: Any = None,
28
+ namespace: str | None = None,
29
+ director: Any = None,
30
+ ):
31
+ production_name, production_data = _production_payload(data)
32
+ production_settings = _split_production_settings(production_data.get("Setting"))
33
+ production = production_cls._new_unhydrated(
34
+ production_name,
35
+ testing_enabled=production_data.get("@TestingEnabled", False),
36
+ log_general_trace_events=production_data.get("@LogGeneralTraceEvents", False),
37
+ actor_pool_size=production_data.get("ActorPoolSize", 2),
38
+ description=production_data.get("Description", ""),
39
+ shutdown_timeout=production_settings.get("shutdown_timeout", 120),
40
+ update_timeout=production_settings.get("update_timeout", 10),
41
+ alert_notification_manager=production_settings.get(
42
+ "alert_notification_manager", ""
43
+ ),
44
+ alert_notification_operation=production_settings.get(
45
+ "alert_notification_operation", ""
46
+ ),
47
+ alert_notification_recipients=production_settings.get(
48
+ "alert_notification_recipients", ""
49
+ ),
50
+ alert_action_window=production_settings.get("alert_action_window", 60),
51
+ namespace=namespace,
52
+ director=director,
53
+ )
54
+
55
+ _add_imported_items(production, production_data)
56
+ _apply_queue_info(production, queue_info)
57
+ _apply_runtime_item_metadata(production, connections)
58
+ runtime_sources, runtime_sources_with_targets = _apply_runtime_connections(
59
+ production, connections
60
+ )
61
+ _infer_connections_from_host_settings(
62
+ production,
63
+ runtime_sources=runtime_sources,
64
+ runtime_sources_with_targets=runtime_sources_with_targets,
65
+ )
66
+ _infer_connections_from_source(production)
67
+ return production
68
+
69
+
70
+ def _add_imported_items(production, production_data: dict[str, Any]) -> None:
71
+ for item_data in _as_list(production_data.get("Item", [])):
72
+ if not isinstance(item_data, dict):
73
+ continue
74
+ host_settings, adapter_settings, other_settings = _split_settings(
75
+ item_data.get("Setting", [])
76
+ )
77
+ ref = ComponentRef(
78
+ production=production,
79
+ name=item_data.get("@Name", ""),
80
+ class_name=item_data.get("@ClassName", ""),
81
+ adapter_class_name=(
82
+ item_data.get("@AdapterClassName") or item_data.get("@Adapter") or ""
83
+ ),
84
+ kind=_component_kind(item_data),
85
+ category=item_data.get("@Category", ""),
86
+ pool_size=item_data.get("@PoolSize", 1),
87
+ enabled=item_data.get("@Enabled", True),
88
+ foreground=item_data.get("@Foreground", False),
89
+ comment=item_data.get("@Comment", ""),
90
+ log_trace_events=item_data.get("@LogTraceEvents", False),
91
+ schedule=item_data.get("@Schedule", ""),
92
+ host_settings=host_settings,
93
+ adapter_settings=adapter_settings,
94
+ other_settings=other_settings,
95
+ )
96
+ production._add_item(ref)
97
+
98
+
99
+ def _apply_queue_info(production, queue_info: Any) -> None:
100
+ queue_map, queue_warnings = _normalize_queue_info(queue_info)
101
+ production._graph_warnings.extend(queue_warnings)
102
+ for item_name, info in queue_map.items():
103
+ if item_name not in production._items_by_name:
104
+ production._graph_warnings.append(f"Queue info item does not exist: {item_name}")
105
+ continue
106
+ production._queue_info[item_name] = dict(info)
107
+
108
+
109
+ def _apply_runtime_item_metadata(production, connections: Any) -> None:
110
+ runtime_item_metadata = _normalize_runtime_item_metadata(connections)
111
+ for item_name, metadata in runtime_item_metadata.items():
112
+ ref = production._items_by_name.get(item_name)
113
+ if ref is None:
114
+ continue
115
+ adapter_class_name = metadata.get("adapter_class_name", "")
116
+ if adapter_class_name and not ref.adapter_class_name:
117
+ ref.adapter_class_name = adapter_class_name
118
+ kind = _normalize_component_kind(metadata.get("kind", ""))
119
+ if kind:
120
+ ref.kind = kind
121
+ if "iop" in metadata:
122
+ ref.runtime_metadata["iop"] = metadata["iop"]
123
+ for setting_name in ("%module", "%classname", "%classpaths"):
124
+ setting_value = metadata.get(setting_name, "")
125
+ if setting_value and setting_name not in ref.host_settings:
126
+ ref.host_settings[setting_name] = setting_value
127
+
128
+
129
+ def _apply_runtime_connections(production, connections: Any) -> tuple[set[str], set[str]]:
130
+ connection_map, runtime_sources, warnings = _normalize_connections(connections)
131
+ production._graph_warnings.extend(warnings)
132
+ runtime_sources_with_targets: set[str] = set()
133
+
134
+ for source_item, targets in connection_map.items():
135
+ if source_item not in production._items_by_name:
136
+ production._graph_warnings.append(
137
+ f"Runtime connection source does not exist: {source_item}"
138
+ )
139
+ continue
140
+ ref = production._items_by_name[source_item]
141
+ for target in targets:
142
+ target_name = target.get("target", "")
143
+ if not target_name:
144
+ continue
145
+ source_target_setting = target.get(
146
+ "source_target_setting",
147
+ "",
148
+ ) or _matching_host_setting(ref, target_name)
149
+ if source_target_setting:
150
+ ref.target_setting_names.add(source_target_setting)
151
+ if target_name not in production._items_by_name:
152
+ if _is_internal_runtime_target(target_name):
153
+ continue
154
+ production._graph_warnings.append(
155
+ f"Runtime connection target does not exist: "
156
+ f"{source_item} -> {target_name}"
157
+ )
158
+ runtime_sources_with_targets.add(source_item)
159
+ production._register_connection(
160
+ source_item,
161
+ source_target_setting,
162
+ target_name,
163
+ origin="runtime",
164
+ interaction=target.get("interaction", "request"),
165
+ metadata=target.get("metadata", {}),
166
+ validate_target=False,
167
+ )
168
+ return runtime_sources, runtime_sources_with_targets
169
+
170
+
171
+ def _component_kind(item_data: dict[str, Any]) -> str:
172
+ explicit_kind = _normalize_component_kind(
173
+ item_data.get("@Kind")
174
+ or item_data.get("@kind")
175
+ or item_data.get("kind")
176
+ or item_data.get("type")
177
+ or item_data.get("role")
178
+ or ""
179
+ )
180
+ if explicit_kind:
181
+ return explicit_kind
182
+ return _component_kind_from_class_name(str(item_data.get("@ClassName", "")))
183
+
184
+
185
+ def _component_kind_from_class_name(class_name: str) -> str:
186
+ class_name = str(class_name or "")
187
+ if not class_name.startswith(("Python.", "Ens.", "EnsLib.", "IOP.")):
188
+ return "component"
189
+ last_part = class_name.rpartition(".")[2].lower()
190
+ if not last_part:
191
+ return "component"
192
+ if last_part.endswith("service"):
193
+ return "service"
194
+ if last_part.endswith("process"):
195
+ return "process"
196
+ if last_part.endswith("operation"):
197
+ return "operation"
198
+ return "component"
199
+
200
+
201
+ def _normalize_component_kind(kind: Any) -> str:
202
+ normalized = str(kind or "").strip().lower()
203
+ if normalized in {"service", "businessservice"}:
204
+ return "service"
205
+ if normalized in {"process", "businessprocess"}:
206
+ return "process"
207
+ if normalized in {"operation", "businessoperation"}:
208
+ return "operation"
209
+ if normalized in {"component", "host", "businesshost"}:
210
+ return "component"
211
+ return ""
212
+
213
+
214
+ def _infer_connections_from_host_settings(
215
+ production,
216
+ *,
217
+ runtime_sources: set[str],
218
+ runtime_sources_with_targets: set[str],
219
+ ) -> None:
220
+ for ref in production._items:
221
+ for setting_name, value in ref.host_settings.items():
222
+ if str(setting_name).startswith("%"):
223
+ continue
224
+ has_runtime_targets = ref.name in runtime_sources_with_targets
225
+ if has_runtime_targets and not _is_target_config_setting(setting_name):
226
+ continue
227
+ for target_name in _setting_targets(value):
228
+ if target_name not in production._items_by_name:
229
+ continue
230
+ if _has_connection(production, ref.name, setting_name, target_name):
231
+ continue
232
+ ref.target_setting_names.add(setting_name)
233
+ metadata = {"source": "Host setting fallback"}
234
+ if has_runtime_targets:
235
+ metadata["reason"] = (
236
+ "runtime discovery did not report this target setting"
237
+ )
238
+ elif ref.name in runtime_sources:
239
+ metadata["reason"] = "runtime discovery returned no targets"
240
+ production._register_connection(
241
+ ref.name,
242
+ setting_name,
243
+ target_name,
244
+ origin="inferred",
245
+ metadata=metadata,
246
+ validate_target=False,
247
+ )
248
+
249
+
250
+ def _is_target_config_setting(setting_name: Any) -> bool:
251
+ normalized = str(setting_name or "").strip().lower()
252
+ return normalized.endswith("targetconfigname") or normalized.endswith(
253
+ "targetconfignames"
254
+ )
255
+
256
+
257
+ def _has_connection(
258
+ production,
259
+ source_item: str,
260
+ source_target_setting: str,
261
+ target_name: str,
262
+ ) -> bool:
263
+ return any(
264
+ edge.source_item == source_item
265
+ and edge.source_target_setting == source_target_setting
266
+ and edge.target == target_name
267
+ for edge in production._edges
268
+ )
269
+
270
+
271
+ def _infer_connections_from_source(production) -> None:
272
+ existing = {
273
+ (edge.source_item, edge.target): edge
274
+ for edge in production._edges
275
+ }
276
+ for ref in production._items:
277
+ for connection in infer_source_connections(
278
+ ref.class_name,
279
+ ref.host_settings,
280
+ iop=_truthy(ref.runtime_metadata.get("iop")),
281
+ ):
282
+ target_name = connection.target
283
+ if target_name not in production._items_by_name:
284
+ continue
285
+ key = (ref.name, target_name)
286
+ if key in existing:
287
+ existing[key] = _apply_source_connection_interaction(
288
+ production,
289
+ existing[key],
290
+ connection,
291
+ )
292
+ continue
293
+ metadata = {"source": connection.source}
294
+ if connection.detail:
295
+ metadata["detail"] = connection.detail
296
+ production._register_connection(
297
+ ref.name,
298
+ "",
299
+ target_name,
300
+ origin="inferred",
301
+ interaction=connection.interaction,
302
+ metadata=metadata,
303
+ validate_target=False,
304
+ )
305
+ existing[key] = production._edges[-1]
306
+
307
+
308
+ def _apply_source_connection_interaction(
309
+ production,
310
+ edge: GraphEdge,
311
+ connection,
312
+ ) -> GraphEdge:
313
+ if connection.interaction in ("", "request"):
314
+ return edge
315
+ if edge.interaction not in ("", "request", "unknown"):
316
+ return edge
317
+
318
+ metadata = dict(edge.metadata)
319
+ metadata.setdefault("source", connection.source)
320
+ if connection.detail:
321
+ metadata.setdefault("detail", connection.detail)
322
+
323
+ updated = GraphEdge(
324
+ source_item=edge.source_item,
325
+ source_target_setting=edge.source_target_setting,
326
+ target=edge.target,
327
+ origin=edge.origin,
328
+ interaction=connection.interaction,
329
+ metadata=metadata,
330
+ )
331
+ production._edges = [
332
+ updated if existing is edge else existing
333
+ for existing in production._edges
334
+ ]
335
+ return updated
336
+
337
+
338
+ def _truthy(value: Any) -> bool:
339
+ if isinstance(value, bool):
340
+ return value
341
+ return str(value or "").strip().lower() in {"1", "true", "yes", "on"}