iris-pex-embedded-python 4.0.1b6__py3-none-any.whl → 4.0.1b8__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.
iop/production/common.py CHANGED
@@ -3,6 +3,8 @@ from __future__ import annotations
3
3
  import importlib
4
4
  from typing import Any
5
5
 
6
+ from ..components.settings import Setting
7
+
6
8
  PRODUCTION_SETTING_FIELDS: dict[str, tuple[str, Any]] = {
7
9
  "shutdown_timeout": ("ShutdownTimeout", 120),
8
10
  "update_timeout": ("UpdateTimeout", 10),
@@ -83,11 +85,21 @@ def _adapter_type_from_class_name(class_name: str | None) -> str:
83
85
  return _adapter_type_from_component_class(component_class)
84
86
 
85
87
 
88
+ def _setting_name(name: Any) -> str:
89
+ if isinstance(name, Setting) and name.name:
90
+ return name.name
91
+ return str(name)
92
+
93
+
94
+ def _normalize_settings_mapping(values: Any) -> dict[str, Any]:
95
+ return {_setting_name(key): value for key, value in dict(values or {}).items()}
96
+
97
+
86
98
  def _settings_to_iris(target_name: str, values: dict[str, Any]) -> list[dict[str, str]]:
87
99
  return [
88
100
  {
89
101
  "@Target": target_name,
90
- "@Name": name,
102
+ "@Name": _setting_name(name),
91
103
  "#text": _text_value(value),
92
104
  }
93
105
  for name, value in values.items()
@@ -97,6 +109,7 @@ def _settings_to_iris(target_name: str, values: dict[str, Any]) -> list[dict[str
97
109
  def _apply_settings_update(target: dict[str, Any], updates: Any) -> None:
98
110
  """Merge *updates* into *target*, treating ``None`` values as removals."""
99
111
  for key, value in (updates or {}).items():
112
+ key = _setting_name(key)
100
113
  if value is None:
101
114
  target.pop(key, None)
102
115
  else:
@@ -168,7 +168,7 @@ class ComponentRef:
168
168
 
169
169
  def connect(
170
170
  self,
171
- target_setting: str | TargetSettingRef,
171
+ target_setting: str | TargetSetting | TargetSettingRef,
172
172
  target_component: ComponentRef | str | None = None,
173
173
  **kwargs: Any,
174
174
  ) -> ComponentRef:
@@ -178,7 +178,7 @@ class ComponentRef:
178
178
 
179
179
  def _coerce_target_setting_ref(
180
180
  self,
181
- target_setting: str | TargetSettingRef,
181
+ target_setting: str | TargetSetting | TargetSettingRef,
182
182
  ) -> TargetSettingRef:
183
183
  if isinstance(target_setting, TargetSettingRef):
184
184
  if target_setting.production is not self.production:
@@ -190,6 +190,28 @@ class ComponentRef:
190
190
  "source target setting belongs to a different component"
191
191
  )
192
192
  return target_setting
193
+ if isinstance(target_setting, TargetSetting):
194
+ owner = target_setting.owner
195
+ if owner is None or not target_setting.name:
196
+ raise ValueError(
197
+ "target setting must be declared on a component class"
198
+ )
199
+ if self.component_class is None or not issubclass(
200
+ self.component_class,
201
+ owner,
202
+ ):
203
+ owner_name = f"{owner.__module__}.{owner.__qualname__}"
204
+ component_name = (
205
+ f"{self.component_class.__module__}."
206
+ f"{self.component_class.__qualname__}"
207
+ if self.component_class is not None
208
+ else self.class_name
209
+ )
210
+ raise ValueError(
211
+ f"target setting {target_setting.name!r} belongs to "
212
+ f"{owner_name}, not {component_name}"
213
+ )
214
+ return self.target_setting(target_setting.name)
193
215
  return self.target_setting(str(target_setting))
194
216
 
195
217
  def inspect(self, *, refresh: bool = True) -> dict[str, Any]:
@@ -2,9 +2,9 @@ from __future__ import annotations
2
2
 
3
3
  from collections.abc import Iterable, Mapping
4
4
  from dataclasses import dataclass, field
5
- from typing import Any, ClassVar, Protocol
5
+ from typing import Any, ClassVar, Protocol, cast
6
6
 
7
- from .common import SETTING_NAME_ALIASES
7
+ from .common import SETTING_NAME_ALIASES, _normalize_settings_mapping
8
8
  from .types import TargetSetting
9
9
 
10
10
 
@@ -36,7 +36,9 @@ class Route:
36
36
  targets = (self.targets,)
37
37
  else:
38
38
  try:
39
- targets = tuple(self.targets)
39
+ targets = tuple(
40
+ cast(Iterable[str | _NamedRouteTarget], self.targets)
41
+ )
40
42
  except TypeError as exc:
41
43
  raise TypeError(
42
44
  f"Route {self.target_setting_name!r} targets must be an item name, "
@@ -174,7 +176,7 @@ def _mapping(
174
176
  item_name: str,
175
177
  ) -> dict[str, Any]:
176
178
  try:
177
- return dict(values or {})
179
+ return _normalize_settings_mapping(values)
178
180
  except (TypeError, ValueError) as exc:
179
181
  raise TypeError(
180
182
  f"Production item {item_name!r} {field_name} must be a mapping"
iop/production/model.py CHANGED
@@ -9,6 +9,7 @@ from .common import (
9
9
  _adapter_type_from_component_class,
10
10
  _apply_settings_update,
11
11
  _auto_proxy_class_name,
12
+ _normalize_settings_mapping,
12
13
  )
13
14
  from .component import ComponentRef
14
15
  from .declarative import _DeclarativeProductionMixin
@@ -219,10 +220,10 @@ class Production(_DeclarativeProductionMixin):
219
220
 
220
221
  def _resolve_production_name(self, name: str | object) -> str:
221
222
  if name is not _MISSING:
222
- return name # type: ignore[return-value]
223
+ return str(name)
223
224
  class_name = getattr(type(self), "name", _MISSING)
224
225
  if class_name is not _MISSING:
225
- return class_name
226
+ return str(class_name)
226
227
  return f"{type(self).__module__}.{type(self).__name__}"
227
228
 
228
229
  def _production_default(
@@ -432,8 +433,8 @@ class Production(_DeclarativeProductionMixin):
432
433
  comment=comment,
433
434
  log_trace_events=log_trace_events,
434
435
  schedule=schedule,
435
- host_settings=dict(settings or {}),
436
- adapter_settings=dict(adapter_settings or {}),
436
+ host_settings=_normalize_settings_mapping(settings),
437
+ adapter_settings=_normalize_settings_mapping(adapter_settings),
437
438
  )
438
439
  self._add_item(ref)
439
440
  return ref
@@ -570,7 +571,12 @@ class Production(_DeclarativeProductionMixin):
570
571
  )
571
572
  ]
572
573
 
573
- def service(self, name_or_cls: str | type, cls: type | None = None, **kwargs):
574
+ def service(
575
+ self,
576
+ name_or_cls: str | type,
577
+ cls: type | None = None,
578
+ **kwargs: Any,
579
+ ) -> ComponentRef:
574
580
  """Add a BusinessService item to the production graph.
575
581
 
576
582
  See docs/cookbooks/hello-world-production.md and
@@ -578,14 +584,24 @@ class Production(_DeclarativeProductionMixin):
578
584
  """
579
585
  return self.component(name_or_cls, cls, kind="service", **kwargs)
580
586
 
581
- def process(self, name_or_cls: str | type, cls: type | None = None, **kwargs):
587
+ def process(
588
+ self,
589
+ name_or_cls: str | type,
590
+ cls: type | None = None,
591
+ **kwargs: Any,
592
+ ) -> ComponentRef:
582
593
  """Add a BusinessProcess item to the production graph.
583
594
 
584
595
  See docs/cookbooks/add-business-process.md.
585
596
  """
586
597
  return self.component(name_or_cls, cls, kind="process", **kwargs)
587
598
 
588
- def operation(self, name_or_cls: str | type, cls: type | None = None, **kwargs):
599
+ def operation(
600
+ self,
601
+ name_or_cls: str | type,
602
+ cls: type | None = None,
603
+ **kwargs: Any,
604
+ ) -> ComponentRef:
589
605
  """Add a BusinessOperation item to the production graph.
590
606
 
591
607
  See docs/cookbooks/add-business-operation.md.
@@ -650,6 +666,12 @@ class Production(_DeclarativeProductionMixin):
650
666
  mode: str = "replace",
651
667
  ) -> None:
652
668
  if not isinstance(source, TargetSettingRef):
669
+ if isinstance(source, TargetSetting):
670
+ raise TypeError(
671
+ "source must be bound to a production item. Use "
672
+ "component.connect(ComponentClass.Target, target_component) "
673
+ "or prod.connect(component.Target, target_component)."
674
+ )
653
675
  raise TypeError(
654
676
  "source must be a TargetSettingRef returned from a ComponentRef"
655
677
  )
@@ -465,9 +465,7 @@ def _connection_lines(production, variables: dict[str, str], item_names: set[str
465
465
  for source_item, source_target_setting in sorted(grouped):
466
466
  targets = grouped[(source_item, source_target_setting)]
467
467
  source_var = variables[source_item]
468
- source_expr = (
469
- f"{source_var}.target_setting({_literal(source_target_setting)})"
470
- )
468
+ source_expr = _literal(source_target_setting)
471
469
  valid_targets = [target for target in targets if target in variables]
472
470
  invalid_targets = [target for target in targets if target not in variables]
473
471
  for target in invalid_targets:
@@ -476,15 +474,16 @@ def _connection_lines(production, variables: dict[str, str], item_names: set[str
476
474
  continue
477
475
  if len(valid_targets) == 1:
478
476
  lines.append(
479
- f"prod.connect({source_expr}, {variables[valid_targets[0]]})"
477
+ f"{source_var}.connect({source_expr}, {variables[valid_targets[0]]})"
480
478
  )
481
479
  else:
482
480
  lines.append(
483
- f"prod.connect({source_expr}, {variables[valid_targets[0]]})"
481
+ f"{source_var}.connect({source_expr}, {variables[valid_targets[0]]})"
484
482
  )
485
483
  for target in valid_targets[1:]:
486
484
  lines.append(
487
- f"prod.connect({source_expr}, {variables[target]}, mode='add')"
485
+ f"{source_var}.connect({source_expr}, {variables[target]}, "
486
+ "mode='add')"
488
487
  )
489
488
 
490
489
  for edge in production.edges:
iop/production/types.py CHANGED
@@ -12,7 +12,7 @@ from ..components.settings import Category, Setting, controls
12
12
  class TargetSetting(Setting):
13
13
  """Production target setting descriptor created by target()."""
14
14
 
15
- def __init__(self, default: Any = "", **kwargs: Any):
15
+ def __init__(self, default: str = "", **kwargs: Any):
16
16
  kwargs.setdefault("iris_type", "Ens.DataType.ConfigName")
17
17
  kwargs.setdefault("category", Category.BASIC)
18
18
  kwargs.setdefault("control", controls.production_item())
@@ -34,7 +34,7 @@ class TargetSetting(Setting):
34
34
  return super().__get__(instance, owner)
35
35
 
36
36
 
37
- def target(default: Any = "", **kwargs: Any) -> TargetSetting:
37
+ def target(default: str = "", **kwargs: Any) -> TargetSetting:
38
38
  """Purpose:
39
39
  Declare a configurable outbound target setting on a component class.
40
40
 
@@ -8,8 +8,10 @@ from .common import (
8
8
  PRODUCTION_SETTING_FIELDS_BY_IRIS,
9
9
  PRODUCTION_SETTING_NAMES,
10
10
  SETTING_NAME_ALIASES,
11
+ _normalize_settings_mapping,
11
12
  )
12
13
  from .import_ import _as_list, _production_payload, _split_settings
14
+ from .types import TargetSetting
13
15
 
14
16
  _PRODUCTION_PUBLIC_FIELDS = {
15
17
  "name",
@@ -151,6 +153,8 @@ def _build_production_object_report(production: Any) -> ProductionValidationRepo
151
153
  for item in getattr(production, "items", ()):
152
154
  issues.extend(_validate_component_ref(item))
153
155
 
156
+ issues.extend(_validate_target_setting_values(production))
157
+
154
158
  return ProductionValidationReport(production_name, tuple(issues))
155
159
 
156
160
 
@@ -180,14 +184,18 @@ def _validate_component_ref(item: Any) -> list[ProductionValidationIssue]:
180
184
 
181
185
  issues.extend(
182
186
  _validate_settings(
183
- settings=dict(getattr(item, "host_settings", {}) or {}),
187
+ settings=_normalize_settings_mapping(
188
+ getattr(item, "host_settings", {}) or {}
189
+ ),
184
190
  path_prefix=f"items.{item_name}.settings.Host",
185
191
  local_class=component_class,
186
192
  iris_class_name=class_name,
187
193
  )
188
194
  )
189
195
 
190
- adapter_settings = dict(getattr(item, "adapter_settings", {}) or {})
196
+ adapter_settings = _normalize_settings_mapping(
197
+ getattr(item, "adapter_settings", {}) or {}
198
+ )
191
199
  if str(getattr(item, "kind", "")) == "process" and adapter_settings:
192
200
  issues.append(
193
201
  ProductionValidationIssue(
@@ -334,9 +342,67 @@ def _local_setting_names(cls: type) -> set[str] | None:
334
342
  if not callable(getter):
335
343
  return None
336
344
  try:
337
- return {str(prop[0]) for prop in getter() if prop}
345
+ properties = getter()
338
346
  except Exception:
339
347
  return None
348
+ if not isinstance(properties, (list, tuple)):
349
+ return None
350
+ names: set[str] = set()
351
+ for prop in properties:
352
+ if isinstance(prop, (list, tuple)) and prop:
353
+ names.add(str(prop[0]))
354
+ return names
355
+
356
+
357
+ def _validate_target_setting_values(production: Any) -> list[ProductionValidationIssue]:
358
+ items = tuple(getattr(production, "items", ()) or ())
359
+ item_names = {str(getattr(item, "name", "")) for item in items}
360
+ issues: list[ProductionValidationIssue] = []
361
+ for item in items:
362
+ item_name = str(getattr(item, "name", ""))
363
+ host_settings = _normalize_settings_mapping(
364
+ getattr(item, "host_settings", {}) or {}
365
+ )
366
+ for setting_name in _target_setting_names(item):
367
+ if setting_name not in host_settings:
368
+ continue
369
+ for target_name in _target_names(host_settings[setting_name]):
370
+ if target_name in item_names:
371
+ continue
372
+ issues.append(
373
+ ProductionValidationIssue(
374
+ kind="route",
375
+ path=f"items.{item_name}.settings.Host.{setting_name}",
376
+ message=(
377
+ f"Target setting references missing production item "
378
+ f"{target_name!r}."
379
+ ),
380
+ suggestion=(
381
+ f"Add a production item named {target_name!r}, "
382
+ "or update/remove this target setting."
383
+ ),
384
+ )
385
+ )
386
+ return issues
387
+
388
+
389
+ def _target_setting_names(item: Any) -> set[str]:
390
+ names = {str(name) for name in getattr(item, "target_setting_names", set())}
391
+ component_class = getattr(item, "component_class", None)
392
+ if isinstance(component_class, type):
393
+ for base in reversed(component_class.__mro__):
394
+ for name, value in base.__dict__.items():
395
+ if isinstance(value, TargetSetting):
396
+ names.add(str(name))
397
+ return names
398
+
399
+
400
+ def _target_names(value: Any) -> tuple[str, ...]:
401
+ return tuple(
402
+ target
403
+ for target in (part.strip() for part in str(value or "").split(","))
404
+ if target
405
+ )
340
406
 
341
407
 
342
408
  def _validate_names_with_known_set(
@@ -394,7 +460,7 @@ def _adapter_class_name_from_host(host_class_name: str) -> str:
394
460
  return ""
395
461
 
396
462
 
397
- def _iris_module():
463
+ def _iris_module() -> Any:
398
464
  try:
399
465
  import iris # type: ignore
400
466
  except Exception:
iop/py.typed ADDED
@@ -0,0 +1 @@
1
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: iris_pex_embedded_python
3
- Version: 4.0.1b6
3
+ Version: 4.0.1b8
4
4
  Summary: Iris Interoperability based on Embedded Python
5
5
  Author-email: grongier <guillaume.rongier@intersystems.com>
6
6
  License: MIT License
@@ -98,7 +98,7 @@ class HelloOperation(BusinessOperation):
98
98
  prod = Production("HelloWorld.Production", testing_enabled=True)
99
99
  service = prod.service("HelloService", HelloService)
100
100
  operation = prod.operation("HelloOperation", HelloOperation)
101
- prod.connect(service.Output, operation)
101
+ service.connect(HelloService.Output, operation)
102
102
 
103
103
  PRODUCTIONS = [prod]
104
104
  ```
@@ -1,5 +1,6 @@
1
1
  iop/__init__.py,sha256=bnhSiC7XcOIiS7e51uY8fr9Li7RYjhCnlCyVDzZI6-I,10636
2
2
  iop/__main__.py,sha256=2rUNM7vaYK0W57Jj72rm7GORyIFLMXKwPq3QNLwYBmY,100
3
+ iop/py.typed,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
3
4
  iop/cli/__init__.py,sha256=Y78pBdA-ULzq1c_9xQZsFBlzm3x5xgxSzkvrH5DoM7I,31
4
5
  iop/cli/formatting.py,sha256=OLgHA1d8_paAuINQyKkYgihWMLoBhPn7kSXW5whRlIs,1606
5
6
  iop/cli/main.py,sha256=r3sLZniM4LCXP6u1kuQmUgMLLD0H04NC5gVXKMNY31M,18418
@@ -64,21 +65,21 @@ iop/migration/plans.py,sha256=5kx3aqQiPDJ3F8hU9pp9_mOO1_N6GA0Ps7--G1Iv6z8,2549
64
65
  iop/migration/utils.py,sha256=pOojLPMZes05KXrGN2ap45ffppP5Z4tS4bjJ0gSD5Oc,38183
65
66
  iop/production/__init__.py,sha256=95VmJgC3lWtHpUJijLqyKKxFZa65OcRni8803kb4aHE,2148
66
67
  iop/production/actions.py,sha256=TLVAjPTPq21oLj9c-IG10qMNJ2hvPzueviMy_c1a0ZU,17199
67
- iop/production/common.py,sha256=IoUg9jkFzSQwDsHcXvkVAC4qxpWKs3kTfXFm_EP07EU,3091
68
- iop/production/component.py,sha256=3a4z9rtr5DjFVejbY_7gYUCOIfWucrfDbWU19d8a738,8442
69
- iop/production/declarations.py,sha256=Tb79Q6rwmFMi6xKpzajJa4Aa2_Tk3sD-e8qiuRJX77s,5821
68
+ iop/production/common.py,sha256=L2QyvE2nC1J333sbebYx_6dyoaFL-89ouMO3Kfe4-D8,3465
69
+ iop/production/component.py,sha256=XalzNEWhCC1RVSZlQZRBpZM3BdRC2TDU-ko3Zn8-Kzo,9475
70
+ iop/production/declarations.py,sha256=u1hzgbDchr55R3dEXEIi9-P5JkfMG7C3aiSWhfhifG8,5952
70
71
  iop/production/declarative.py,sha256=IpHYO46mu7k9wnq3DpFreoALPoX1Vi8DrJb-85O_-bQ,7853
71
72
  iop/production/diff.py,sha256=NYpcSVklaGpaZOyl933W8eLsDWcwjlf6Upbp4pVGSMU,9975
72
73
  iop/production/import_.py,sha256=twBra6j2peolFadv8WyDwZZOd9NznzAkPsk2RbOfZQM,10833
73
74
  iop/production/inspection.py,sha256=PPv9DiDS4OrnKROqV7JPbuY8Y0JR-m8syPhap3GgE4g,3363
74
- iop/production/model.py,sha256=RCss8i6jnpP-sNv0eLCwpxU2y2uOaLKJ5qeP4mlwwuQ,43533
75
+ iop/production/model.py,sha256=bEtDo-IwECuCrkKDXJXm1hB5Bmme4srB6l9isc8n3KI,44088
75
76
  iop/production/planning.py,sha256=nCYrXLKlHBlUaQZPzPfqtIERIv62F2sg4gJ0b8mtcKk,23375
76
77
  iop/production/reconstruction.py,sha256=5vVteTEM6IOiQUfpe4AUQg6Nt4oaaIDR61-1l6Vu8hk,12532
77
- iop/production/rendering.py,sha256=UVHLICY4zWEP3W7-99TpB2WeLBNREC2N8rYSnBa_iZM,20240
78
+ iop/production/rendering.py,sha256=gyJyUcWwvgwRWvlvddZbCIhkjJ1DcMZfbL2brIa_k8U,20229
78
79
  iop/production/runtime.py,sha256=6grX1u20OhHnvhzC3yPDTFEoDs_TN4mfs5MxzFzZMls,2637
79
80
  iop/production/source_inference.py,sha256=Wl3E9-1hWb4qxD1jwrrZTLSgqN-0vGhOrJtmzDWPCao,21613
80
- iop/production/types.py,sha256=B5tSmRAwFBoFPxp7oVPmfMW9sxHaeBtonAfv6C06W1g,16889
81
- iop/production/validation.py,sha256=14BfjrLXW1AOuP8AdBrs-CY6zynaDc8_AUD9frsYAIU,13753
81
+ iop/production/types.py,sha256=hzO8rj73z16WqFQBI7YBAznY-1fD8ENyJqzTY-ydFXI,16889
82
+ iop/production/validation.py,sha256=gzRFLCTPGiNMIot1yG1FXG5ab9inpq4rqYYQpefhBYs,16217
82
83
  iop/runtime/__init__.py,sha256=wcyWMRuPCYE_CLd1NmgmI1M-IbFs2Gz2yIj2-EW_2AA,70
83
84
  iop/runtime/director.py,sha256=KW8BvkATK8XuIUPNBD9rMww9r3Zg4K3H54868eOgvl0,12867
84
85
  iop/runtime/environment.py,sha256=0KZ4EoW6NUEbF7FW471emxQ-9FbaiX6ngUHVGihgZXU,1564
@@ -91,9 +92,9 @@ iop/runtime/remote/director.py,sha256=bkie751GrYLgGs7ApRCowHpSnJA8KupxCOrFDQmjyO
91
92
  iop/runtime/remote/migration.py,sha256=Iboz-Ye7i9xif9bn433GazCF-gtD-HJW3wiUwWS5P6w,1831
92
93
  iop/runtime/remote/settings.py,sha256=P1Hsgld5o57HpSZgPVZzobyjlUmxJj6bstiWvR0JXnc,2144
93
94
  iop/runtime/remote/setup.py,sha256=Tr80F3JJTy7oSUso2jyx0iA_KZayd4MYt9vL0BvPpMA,2600
94
- iris_pex_embedded_python-4.0.1b6.dist-info/licenses/LICENSE,sha256=rZSiBFId_sfbJ6RL0GjjPX-InNLkNS9ou7eQsikciI8,1089
95
- iris_pex_embedded_python-4.0.1b6.dist-info/METADATA,sha256=BGtIyGv7zT0llTUrwEHAHc27J-sruyQcOxnWrw812aI,5846
96
- iris_pex_embedded_python-4.0.1b6.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
97
- iris_pex_embedded_python-4.0.1b6.dist-info/entry_points.txt,sha256=fzS8ZFsPe8cnpEx208X60DNugCPQmuSloPeg4pyyJDY,42
98
- iris_pex_embedded_python-4.0.1b6.dist-info/top_level.txt,sha256=BM54-OXQ6l2BDtmesWNXckh033s9gcjoO7bfjbwZbxU,4
99
- iris_pex_embedded_python-4.0.1b6.dist-info/RECORD,,
95
+ iris_pex_embedded_python-4.0.1b8.dist-info/licenses/LICENSE,sha256=rZSiBFId_sfbJ6RL0GjjPX-InNLkNS9ou7eQsikciI8,1089
96
+ iris_pex_embedded_python-4.0.1b8.dist-info/METADATA,sha256=2xgGbmP5t_sp-SvMGjzJp1wkpiU9p32fQ22gWUjG7GE,5854
97
+ iris_pex_embedded_python-4.0.1b8.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
98
+ iris_pex_embedded_python-4.0.1b8.dist-info/entry_points.txt,sha256=fzS8ZFsPe8cnpEx208X60DNugCPQmuSloPeg4pyyJDY,42
99
+ iris_pex_embedded_python-4.0.1b8.dist-info/top_level.txt,sha256=BM54-OXQ6l2BDtmesWNXckh033s9gcjoO7bfjbwZbxU,4
100
+ iris_pex_embedded_python-4.0.1b8.dist-info/RECORD,,