iris-pex-embedded-python 4.0.1b6__py3-none-any.whl → 4.0.1b7__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.
@@ -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]:
iop/production/model.py CHANGED
@@ -219,10 +219,10 @@ class Production(_DeclarativeProductionMixin):
219
219
 
220
220
  def _resolve_production_name(self, name: str | object) -> str:
221
221
  if name is not _MISSING:
222
- return name # type: ignore[return-value]
222
+ return str(name)
223
223
  class_name = getattr(type(self), "name", _MISSING)
224
224
  if class_name is not _MISSING:
225
- return class_name
225
+ return str(class_name)
226
226
  return f"{type(self).__module__}.{type(self).__name__}"
227
227
 
228
228
  def _production_default(
@@ -570,7 +570,12 @@ class Production(_DeclarativeProductionMixin):
570
570
  )
571
571
  ]
572
572
 
573
- def service(self, name_or_cls: str | type, cls: type | None = None, **kwargs):
573
+ def service(
574
+ self,
575
+ name_or_cls: str | type,
576
+ cls: type | None = None,
577
+ **kwargs: Any,
578
+ ) -> ComponentRef:
574
579
  """Add a BusinessService item to the production graph.
575
580
 
576
581
  See docs/cookbooks/hello-world-production.md and
@@ -578,14 +583,24 @@ class Production(_DeclarativeProductionMixin):
578
583
  """
579
584
  return self.component(name_or_cls, cls, kind="service", **kwargs)
580
585
 
581
- def process(self, name_or_cls: str | type, cls: type | None = None, **kwargs):
586
+ def process(
587
+ self,
588
+ name_or_cls: str | type,
589
+ cls: type | None = None,
590
+ **kwargs: Any,
591
+ ) -> ComponentRef:
582
592
  """Add a BusinessProcess item to the production graph.
583
593
 
584
594
  See docs/cookbooks/add-business-process.md.
585
595
  """
586
596
  return self.component(name_or_cls, cls, kind="process", **kwargs)
587
597
 
588
- def operation(self, name_or_cls: str | type, cls: type | None = None, **kwargs):
598
+ def operation(
599
+ self,
600
+ name_or_cls: str | type,
601
+ cls: type | None = None,
602
+ **kwargs: Any,
603
+ ) -> ComponentRef:
589
604
  """Add a BusinessOperation item to the production graph.
590
605
 
591
606
  See docs/cookbooks/add-business-operation.md.
@@ -650,6 +665,12 @@ class Production(_DeclarativeProductionMixin):
650
665
  mode: str = "replace",
651
666
  ) -> None:
652
667
  if not isinstance(source, TargetSettingRef):
668
+ if isinstance(source, TargetSetting):
669
+ raise TypeError(
670
+ "source must be bound to a production item. Use "
671
+ "component.connect(ComponentClass.Target, target_component) "
672
+ "or prod.connect(component.Target, target_component)."
673
+ )
653
674
  raise TypeError(
654
675
  "source must be a TargetSettingRef returned from a ComponentRef"
655
676
  )
@@ -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
 
@@ -10,6 +10,7 @@ from .common import (
10
10
  SETTING_NAME_ALIASES,
11
11
  )
12
12
  from .import_ import _as_list, _production_payload, _split_settings
13
+ from .types import TargetSetting
13
14
 
14
15
  _PRODUCTION_PUBLIC_FIELDS = {
15
16
  "name",
@@ -151,6 +152,8 @@ def _build_production_object_report(production: Any) -> ProductionValidationRepo
151
152
  for item in getattr(production, "items", ()):
152
153
  issues.extend(_validate_component_ref(item))
153
154
 
155
+ issues.extend(_validate_target_setting_values(production))
156
+
154
157
  return ProductionValidationReport(production_name, tuple(issues))
155
158
 
156
159
 
@@ -334,9 +337,65 @@ def _local_setting_names(cls: type) -> set[str] | None:
334
337
  if not callable(getter):
335
338
  return None
336
339
  try:
337
- return {str(prop[0]) for prop in getter() if prop}
340
+ properties = getter()
338
341
  except Exception:
339
342
  return None
343
+ if not isinstance(properties, (list, tuple)):
344
+ return None
345
+ names: set[str] = set()
346
+ for prop in properties:
347
+ if isinstance(prop, (list, tuple)) and prop:
348
+ names.add(str(prop[0]))
349
+ return names
350
+
351
+
352
+ def _validate_target_setting_values(production: Any) -> list[ProductionValidationIssue]:
353
+ items = tuple(getattr(production, "items", ()) or ())
354
+ item_names = {str(getattr(item, "name", "")) for item in items}
355
+ issues: list[ProductionValidationIssue] = []
356
+ for item in items:
357
+ item_name = str(getattr(item, "name", ""))
358
+ host_settings = dict(getattr(item, "host_settings", {}) or {})
359
+ for setting_name in _target_setting_names(item):
360
+ if setting_name not in host_settings:
361
+ continue
362
+ for target_name in _target_names(host_settings[setting_name]):
363
+ if target_name in item_names:
364
+ continue
365
+ issues.append(
366
+ ProductionValidationIssue(
367
+ kind="route",
368
+ path=f"items.{item_name}.settings.Host.{setting_name}",
369
+ message=(
370
+ f"Target setting references missing production item "
371
+ f"{target_name!r}."
372
+ ),
373
+ suggestion=(
374
+ f"Add a production item named {target_name!r}, "
375
+ "or update/remove this target setting."
376
+ ),
377
+ )
378
+ )
379
+ return issues
380
+
381
+
382
+ def _target_setting_names(item: Any) -> set[str]:
383
+ names = {str(name) for name in getattr(item, "target_setting_names", set())}
384
+ component_class = getattr(item, "component_class", None)
385
+ if isinstance(component_class, type):
386
+ for base in reversed(component_class.__mro__):
387
+ for name, value in base.__dict__.items():
388
+ if isinstance(value, TargetSetting):
389
+ names.add(str(name))
390
+ return names
391
+
392
+
393
+ def _target_names(value: Any) -> tuple[str, ...]:
394
+ return tuple(
395
+ target
396
+ for target in (part.strip() for part in str(value or "").split(","))
397
+ if target
398
+ )
340
399
 
341
400
 
342
401
  def _validate_names_with_known_set(
@@ -394,7 +453,7 @@ def _adapter_class_name_from_host(host_class_name: str) -> str:
394
453
  return ""
395
454
 
396
455
 
397
- def _iris_module():
456
+ def _iris_module() -> Any:
398
457
  try:
399
458
  import iris # type: ignore
400
459
  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.1b7
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
@@ -65,20 +66,20 @@ 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
68
  iop/production/common.py,sha256=IoUg9jkFzSQwDsHcXvkVAC4qxpWKs3kTfXFm_EP07EU,3091
68
- iop/production/component.py,sha256=3a4z9rtr5DjFVejbY_7gYUCOIfWucrfDbWU19d8a738,8442
69
+ iop/production/component.py,sha256=XalzNEWhCC1RVSZlQZRBpZM3BdRC2TDU-ko3Zn8-Kzo,9475
69
70
  iop/production/declarations.py,sha256=Tb79Q6rwmFMi6xKpzajJa4Aa2_Tk3sD-e8qiuRJX77s,5821
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=3p70HARmvm9bd7rQ9l4lbX_abZj983QxmVk-OF2gWqo,44021
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=yoh3joKyOmuSn3aSYhc-aWOV61s5V5Sd1hLbNXDp12g,16049
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.1b7.dist-info/licenses/LICENSE,sha256=rZSiBFId_sfbJ6RL0GjjPX-InNLkNS9ou7eQsikciI8,1089
96
+ iris_pex_embedded_python-4.0.1b7.dist-info/METADATA,sha256=O2hhJWlDeQ1GJMdbvujQJ3-9EREctqL-1BSe_H3MpGg,5854
97
+ iris_pex_embedded_python-4.0.1b7.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
98
+ iris_pex_embedded_python-4.0.1b7.dist-info/entry_points.txt,sha256=fzS8ZFsPe8cnpEx208X60DNugCPQmuSloPeg4pyyJDY,42
99
+ iris_pex_embedded_python-4.0.1b7.dist-info/top_level.txt,sha256=BM54-OXQ6l2BDtmesWNXckh033s9gcjoO7bfjbwZbxU,4
100
+ iris_pex_embedded_python-4.0.1b7.dist-info/RECORD,,