iris-pex-embedded-python 4.0.1b6__tar.gz → 4.0.1b7__tar.gz

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 (147) hide show
  1. {iris_pex_embedded_python-4.0.1b6/src/iris_pex_embedded_python.egg-info → iris_pex_embedded_python-4.0.1b7}/PKG-INFO +2 -2
  2. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/README.md +1 -1
  3. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/docs/cookbooks/add-business-operation.md +2 -1
  4. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/docs/cookbooks/add-business-process.md +2 -3
  5. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/docs/cookbooks/add-polling-service.md +1 -1
  6. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/docs/cookbooks/hello-world-production.md +1 -1
  7. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/docs/cookbooks/production-settings-and-targets.md +3 -3
  8. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/docs/getting-started/first-steps.md +2 -2
  9. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/docs/getting-started/register-component.md +2 -2
  10. iris_pex_embedded_python-4.0.1b7/docs/index.md +68 -0
  11. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/docs/production-graph.md +17 -1
  12. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/docs/python-api.md +18 -3
  13. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/docs/settings.md +5 -5
  14. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/pyproject.toml +2 -1
  15. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/production/component.py +24 -2
  16. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/production/model.py +26 -5
  17. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/production/rendering.py +5 -6
  18. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/production/types.py +2 -2
  19. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/production/validation.py +61 -2
  20. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7/src/iris_pex_embedded_python.egg-info}/PKG-INFO +2 -2
  21. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iris_pex_embedded_python.egg-info/SOURCES.txt +1 -0
  22. iris_pex_embedded_python-4.0.1b7/src/iris_pex_embedded_python.egg-info/dependency_links.txt +1 -0
  23. iris_pex_embedded_python-4.0.1b6/docs/index.md +0 -58
  24. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/AGENTS.md +0 -0
  25. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/LICENSE +0 -0
  26. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/MANIFEST.in +0 -0
  27. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/docs/agents-template.md +0 -0
  28. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/docs/ai-coding.md +0 -0
  29. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/docs/benchmarks.md +0 -0
  30. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/docs/changelog.md +0 -0
  31. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/docs/code-of-conduct.md +0 -0
  32. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/docs/command-line.md +0 -0
  33. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/docs/component-interaction.md +0 -0
  34. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/docs/contributing.md +0 -0
  35. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/docs/cookbooks/code-index.md +0 -0
  36. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/docs/cookbooks/fhir-submission-python-client.md +0 -0
  37. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/docs/cookbooks/hl7v2-native-input.md +0 -0
  38. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/docs/cookbooks/hl7v2-to-fhir-with-fhir-converter.md +0 -0
  39. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/docs/cookbooks/index.md +0 -0
  40. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/docs/cookbooks/remote-migration.md +0 -0
  41. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/docs/credits.md +0 -0
  42. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/docs/debug.md +0 -0
  43. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/docs/dtl.md +0 -0
  44. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/docs/example.md +0 -0
  45. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/docs/getting-started/installation.md +0 -0
  46. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/docs/healthcare-ai-coding.md +0 -0
  47. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/docs/logging.md +0 -0
  48. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/docs/prod-settings.md +0 -0
  49. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/docs/production-change-workflow.md +0 -0
  50. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/docs/rest-api.md +0 -0
  51. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/docs/useful-links.md +0 -0
  52. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/docs/venv.md +0 -0
  53. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/docs/wrapper.md +0 -0
  54. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/mkdocs.yml +0 -0
  55. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/setup.cfg +0 -0
  56. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/__init__.py +0 -0
  57. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/__main__.py +0 -0
  58. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/cli/__init__.py +0 -0
  59. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/cli/formatting.py +0 -0
  60. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/cli/main.py +0 -0
  61. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/cli/parser.py +0 -0
  62. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/cli/types.py +0 -0
  63. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/BusinessOperation.cls +0 -0
  64. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/BusinessProcess.cls +0 -0
  65. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/BusinessService.cls +0 -0
  66. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/Common.cls +0 -0
  67. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/Director.cls +0 -0
  68. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/Duplex/Operation.cls +0 -0
  69. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/Duplex/Process.cls +0 -0
  70. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/Duplex/Service.cls +0 -0
  71. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/Generator/Message/Ack.cls +0 -0
  72. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/Generator/Message/Poll.cls +0 -0
  73. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/Generator/Message/Start.cls +0 -0
  74. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/Generator/Message/StartPickle.cls +0 -0
  75. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/Generator/Message/Stop.cls +0 -0
  76. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/InboundAdapter.cls +0 -0
  77. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/Message/JSONSchema.cls +0 -0
  78. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/Message.cls +0 -0
  79. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/OutboundAdapter.cls +0 -0
  80. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/PickleMessage.cls +0 -0
  81. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/PrivateSession/Duplex.cls +0 -0
  82. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/PrivateSession/Message/Ack.cls +0 -0
  83. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/PrivateSession/Message/Poll.cls +0 -0
  84. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/PrivateSession/Message/Start.cls +0 -0
  85. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/PrivateSession/Message/Stop.cls +0 -0
  86. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/Projection.cls +0 -0
  87. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/Service/Remote/Handler.cls +0 -0
  88. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/Service/Remote/Rest/v1.cls +0 -0
  89. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/Test.cls +0 -0
  90. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/Utils.cls +0 -0
  91. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/Wrapper.cls +0 -0
  92. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/components/__init__.py +0 -0
  93. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/components/async_request.py +0 -0
  94. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/components/business_host.py +0 -0
  95. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/components/business_operation.py +0 -0
  96. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/components/business_process.py +0 -0
  97. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/components/business_service.py +0 -0
  98. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/components/common.py +0 -0
  99. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/components/debugpy.py +0 -0
  100. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/components/generator_request.py +0 -0
  101. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/components/inbound_adapter.py +0 -0
  102. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/components/log_manager.py +0 -0
  103. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/components/outbound_adapter.py +0 -0
  104. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/components/polling_business_service.py +0 -0
  105. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/components/private_session_duplex.py +0 -0
  106. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/components/private_session_process.py +0 -0
  107. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/components/settings.py +0 -0
  108. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/messages/__init__.py +0 -0
  109. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/messages/base.py +0 -0
  110. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/messages/decorators.py +0 -0
  111. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/messages/dispatch.py +0 -0
  112. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/messages/persistent.py +0 -0
  113. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/messages/serialization.py +0 -0
  114. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/messages/validation.py +0 -0
  115. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/migration/__init__.py +0 -0
  116. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/migration/io.py +0 -0
  117. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/migration/manifest.py +0 -0
  118. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/migration/plans.py +0 -0
  119. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/migration/utils.py +0 -0
  120. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/production/__init__.py +0 -0
  121. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/production/actions.py +0 -0
  122. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/production/common.py +0 -0
  123. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/production/declarations.py +0 -0
  124. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/production/declarative.py +0 -0
  125. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/production/diff.py +0 -0
  126. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/production/import_.py +0 -0
  127. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/production/inspection.py +0 -0
  128. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/production/planning.py +0 -0
  129. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/production/reconstruction.py +0 -0
  130. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/production/runtime.py +0 -0
  131. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/production/source_inference.py +0 -0
  132. /iris_pex_embedded_python-4.0.1b6/src/iris_pex_embedded_python.egg-info/dependency_links.txt → /iris_pex_embedded_python-4.0.1b7/src/iop/py.typed +0 -0
  133. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/runtime/__init__.py +0 -0
  134. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/runtime/director.py +0 -0
  135. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/runtime/environment.py +0 -0
  136. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/runtime/iris.py +0 -0
  137. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/runtime/local.py +0 -0
  138. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/runtime/protocol.py +0 -0
  139. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/runtime/remote/__init__.py +0 -0
  140. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/runtime/remote/client.py +0 -0
  141. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/runtime/remote/director.py +0 -0
  142. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/runtime/remote/migration.py +0 -0
  143. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/runtime/remote/settings.py +0 -0
  144. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iop/runtime/remote/setup.py +0 -0
  145. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iris_pex_embedded_python.egg-info/entry_points.txt +0 -0
  146. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iris_pex_embedded_python.egg-info/requires.txt +0 -0
  147. {iris_pex_embedded_python-4.0.1b6 → iris_pex_embedded_python-4.0.1b7}/src/iris_pex_embedded_python.egg-info/top_level.txt +0 -0
@@ -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
  ```
@@ -44,7 +44,7 @@ class HelloOperation(BusinessOperation):
44
44
  prod = Production("HelloWorld.Production", testing_enabled=True)
45
45
  service = prod.service("HelloService", HelloService)
46
46
  operation = prod.operation("HelloOperation", HelloOperation)
47
- prod.connect(service.Output, operation)
47
+ service.connect(HelloService.Output, operation)
48
48
 
49
49
  PRODUCTIONS = [prod]
50
50
  ```
@@ -93,7 +93,8 @@ If another component sends to the operation, declare a `target()` setting on the
93
93
  sender and connect it:
94
94
 
95
95
  ```python
96
- prod.connect(process.Orders, operation)
96
+ process = prod.process("OrderProcess", OrderProcess)
97
+ process.connect(OrderProcess.Orders, operation)
97
98
  ```
98
99
 
99
100
  ## Migration Command
@@ -85,8 +85,8 @@ process = prod.process("OrderProcess", OrderProcess)
85
85
  accepted = prod.operation("AcceptedOperation", AcceptedOperation)
86
86
  rejected = prod.operation("RejectedOperation", RejectedOperation)
87
87
 
88
- prod.connect(process.Accepted, accepted)
89
- prod.connect(process.Rejected, rejected)
88
+ process.connect(OrderProcess.Accepted, accepted)
89
+ process.connect(OrderProcess.Rejected, rejected)
90
90
  ```
91
91
 
92
92
  ## Migration Command
@@ -113,4 +113,3 @@ iop --migrate settings.py
113
113
  intended precedence explicit.
114
114
  - Calling a downstream component directly instead of sending a production
115
115
  message through a target.
116
-
@@ -55,7 +55,7 @@ In `settings.py`:
55
55
  ```python
56
56
  service = prod.service("FilePollService", FilePollService)
57
57
  operation = prod.operation("TargetOperation", TargetOperation)
58
- prod.connect(service.Output, operation)
58
+ service.connect(FilePollService.Output, operation)
59
59
  ```
60
60
 
61
61
  ## Migration Command
@@ -74,7 +74,7 @@ prod = Production("HelloWorld.Production", testing_enabled=True)
74
74
 
75
75
  service = prod.service("HelloService", HelloService)
76
76
  operation = prod.operation("HelloOperation", HelloOperation)
77
- prod.connect(service.Output, operation)
77
+ service.connect(HelloService.Output, operation)
78
78
 
79
79
  PRODUCTIONS = [prod]
80
80
  ```
@@ -24,7 +24,7 @@ Implementation requirements:
24
24
  - Add services with prod.service(...), processes with prod.process(...), and
25
25
  operations with prod.operation(...).
26
26
  - Use target() attributes on component classes for outbound routing.
27
- - Use prod.connect(source.TargetName, destination) for graph edges.
27
+ - Use component.connect(ComponentClass.TargetName, destination) for graph edges.
28
28
  - Keep PRODUCTIONS = [prod] as the migration entrypoint.
29
29
  - Do not add raw CLASSES entries for components already declared in the
30
30
  Production graph.
@@ -51,8 +51,8 @@ process = prod.process("RouteProcess", RouteProcess)
51
51
  accepted = prod.operation("AcceptedOperation", AcceptedOperation)
52
52
  rejected = prod.operation("RejectedOperation", RejectedOperation)
53
53
 
54
- prod.connect(process.Accepted, accepted)
55
- prod.connect(process.Rejected, rejected)
54
+ process.connect(RouteProcess.Accepted, accepted)
55
+ process.connect(RouteProcess.Rejected, rejected)
56
56
  ```
57
57
 
58
58
  When a route should have a conventional default, pass the target item name to
@@ -126,7 +126,7 @@ prod = Production("HelloWorld.Production", testing_enabled=True)
126
126
 
127
127
  service = prod.service("HelloService", HelloService)
128
128
  operation = prod.operation("HelloOperation", HelloOperation)
129
- prod.connect(service.Output, operation)
129
+ service.connect(HelloService.Output, operation)
130
130
 
131
131
  PRODUCTIONS = [prod]
132
132
  ```
@@ -136,7 +136,7 @@ In this production:
136
136
  - `Production("HelloWorld.Production")` declares the IRIS production class.
137
137
  - `prod.service("HelloService", HelloService)` adds one service item.
138
138
  - `prod.operation("HelloOperation", HelloOperation)` adds one operation item.
139
- - `prod.connect(service.Output, operation)` sets the service `Output` target to `HelloOperation` and records the production graph edge.
139
+ - `service.connect(HelloService.Output, operation)` sets the service `Output` target to `HelloOperation` and records the production graph edge.
140
140
  - `PRODUCTIONS = [prod]` tells IoP what to migrate.
141
141
 
142
142
  You do not need a separate `CLASSES` dictionary for these production components. IoP registers Python component classes from the `Production` graph during migration.
@@ -40,7 +40,7 @@ class OrderOperation(BusinessOperation):
40
40
  prod = Production("Demo.Production", testing_enabled=True)
41
41
  file = prod.service("FileInput", FileService)
42
42
  orders = prod.operation("OrderOperation", OrderOperation)
43
- prod.connect(file.Output, orders)
43
+ file.connect(FileService.Output, orders)
44
44
 
45
45
  PRODUCTIONS = [prod]
46
46
  ```
@@ -55,7 +55,7 @@ Migration registers the generated IRIS proxy classes for `FileService` and
55
55
  `OrderOperation`, then saves `Demo.Production`.
56
56
 
57
57
  `target()` declares a configurable outbound target setting on the component
58
- class. `prod.connect(file.Output, orders)` sets that setting to the destination
58
+ class. `file.connect(FileService.Output, orders)` sets that setting to the destination
59
59
  component and records the production graph edge.
60
60
 
61
61
  When you need to test `FileService` at runtime, do not use `iop --test`.
@@ -0,0 +1,68 @@
1
+ # IoP (Interoperability On Python)
2
+
3
+ [![PyPI - Status](https://img.shields.io/pypi/status/iris-pex-embedded-python)](https://pypi.org/project/iris-pex-embedded-python/)
4
+ [![PyPI](https://img.shields.io/pypi/v/iris-pex-embedded-python)](https://pypi.org/project/iris-pex-embedded-python/)
5
+ [![PyPI - Downloads](https://img.shields.io/pypi/dm/iris-pex-embedded-python)](https://pypi.org/project/iris-pex-embedded-python/)
6
+ [![PyPI - License](https://img.shields.io/pypi/l/iris-pex-embedded-python)](https://pypi.org/project/iris-pex-embedded-python/)
7
+ ![GitHub last commit](https://img.shields.io/github/last-commit/grongierisc/interoperability-embedded-python)
8
+
9
+ Welcome to the **Interoperability On Python (IoP)** proof of concept! This project demonstrates how the **IRIS Interoperability Framework** can be utilized with a **Python-first approach**.
10
+
11
+ Documentation can be found [here](https://grongierisc.github.io/interoperability-embedded-python/).
12
+ For prompt-driven workflows, see [AI-assisted coding with IoP](https://grongierisc.github.io/interoperability-embedded-python/ai-coding/).
13
+ For task-oriented examples, see the [IoP cookbooks](https://grongierisc.github.io/interoperability-embedded-python/cookbooks/).
14
+ For application repositories, start from the [reusable AGENTS.md template](https://grongierisc.github.io/interoperability-embedded-python/agents-template/).
15
+
16
+ ## Example
17
+
18
+ Here's a tiny Python-authored production:
19
+
20
+ ```python
21
+ from dataclasses import dataclass
22
+
23
+ from iop import BusinessOperation, Message, PollingBusinessService, Production, target
24
+
25
+
26
+ @dataclass
27
+ class HelloRequest(Message):
28
+ text: str = "Hello World"
29
+
30
+
31
+ class HelloService(PollingBusinessService):
32
+ Output = target()
33
+
34
+ def on_poll(self):
35
+ self.send_request_async(self.Output, HelloRequest())
36
+
37
+
38
+ class HelloOperation(BusinessOperation):
39
+ def on_message(self, request: HelloRequest):
40
+ self.log_info(request.text)
41
+ return request
42
+
43
+
44
+ prod = Production("HelloWorld.Production", testing_enabled=True)
45
+ service = prod.service("HelloService", HelloService)
46
+ operation = prod.operation("HelloOperation", HelloOperation)
47
+ service.connect(HelloService.Output, operation)
48
+
49
+ PRODUCTIONS = [prod]
50
+ ```
51
+
52
+ ## Installation
53
+
54
+ To start using this proof of concept, install it using pip:
55
+
56
+ ```bash
57
+ pip install iris-pex-embedded-python
58
+ ```
59
+
60
+ ## Getting Started
61
+
62
+ If you're new to this project, begin by reading the [installation guide](https://grongierisc.github.io/interoperability-embedded-python/getting-started/installation). Then, follow the [first steps](https://grongierisc.github.io/interoperability-embedded-python/getting-started/first-steps) to create your first Python-authored production.
63
+
64
+ If you are using an AI coding assistant, start with [AI-assisted coding with IoP](https://grongierisc.github.io/interoperability-embedded-python/ai-coding/).
65
+ For concrete workflows, use the [IoP cookbooks](https://grongierisc.github.io/interoperability-embedded-python/cookbooks/).
66
+ For healthcare productions, also see [Healthcare AI-assisted coding](https://grongierisc.github.io/interoperability-embedded-python/healthcare-ai-coding/).
67
+
68
+ Happy coding!
@@ -145,9 +145,25 @@ Python-authored components use Python classes:
145
145
  prod = Production("Demo.Production")
146
146
  file = prod.service("FileInput", FileService)
147
147
  orders = prod.operation(OrderOperation)
148
- prod.connect(file.Output, orders)
148
+ file.connect(FileService.Output, orders)
149
149
  ```
150
150
 
151
+ For static autocomplete, bind through the component ref and pass the descriptor
152
+ from the component class:
153
+
154
+ ```python
155
+ first = prod.service("FirstInput", FileService)
156
+ second = prod.service("SecondInput", FileService)
157
+ orders = prod.operation(OrderOperation)
158
+
159
+ first.connect(FileService.Output, orders)
160
+ second.connect(FileService.Output, orders)
161
+ ```
162
+
163
+ The left-side `ComponentRef` selects the production item instance, so both
164
+ connections bind the same class-declared target setting to different configured
165
+ items.
166
+
151
167
  For a conventional route, the target can be defaulted on the component class:
152
168
 
153
169
  ```python
@@ -504,7 +504,7 @@ class OrderOperation(BusinessOperation):
504
504
  prod = Production("Demo.Production")
505
505
  file = prod.service("FileInput", FileService)
506
506
  orders = prod.operation(OrderOperation)
507
- prod.connect(file.Output, orders)
507
+ file.connect(FileService.Output, orders)
508
508
  ```
509
509
 
510
510
  The same topology can be declared as a production subclass. Instantiating the
@@ -561,7 +561,7 @@ class FileProduction(Production):
561
561
  `target()` declares a configurable outbound target setting on `FileService`.
562
562
  `Route(FileService.Output, ORDER_OPERATION)` wires that setting to a production
563
563
  item. This separation mirrors the instance-style form:
564
- `prod.connect(file.Output, orders)`.
564
+ `file.connect(FileService.Output, orders)`.
565
565
 
566
566
  For Python component classes, prefer passing the descriptor
567
567
  (`FileService.Output`) to `Route`. For built-in IRIS or ObjectScript classes,
@@ -615,6 +615,19 @@ file = (
615
615
  )
616
616
  ```
617
617
 
618
+ For Python components, `ComponentRef.connect(...)` also accepts the `target()`
619
+ descriptor from the component class. This keeps the left-side production item
620
+ instance explicit while giving static tools autocomplete on the class:
621
+
622
+ ```python
623
+ first = prod.service("FirstInput", FileService)
624
+ second = prod.service("SecondInput", FileService)
625
+ orders = prod.operation(OrderOperation)
626
+
627
+ first.connect(FileService.Output, orders)
628
+ second.connect(FileService.Output, orders)
629
+ ```
630
+
618
631
  For ObjectScript or built-in IRIS components, use manual target setting names:
619
632
 
620
633
  ```python
@@ -642,7 +655,9 @@ instead of shadowing those attributes.
642
655
 
643
656
  Declared target settings are available as dynamic `ComponentRef` attributes,
644
657
  such as `rest.my_target`, and are exposed through `dir(rest)` for runtime
645
- autocomplete.
658
+ autocomplete. For Pylance, mypy, and other static tools, prefer
659
+ `rest.connect(Rest.my_target, operation)` because completion happens on the
660
+ component class.
646
661
 
647
662
  Python `Production` is the source of truth for Python-authored topology. IRIS
648
663
  remains the runtime source of truth. Imported graphs are operational
@@ -41,7 +41,7 @@ class HelloOperation(BusinessOperation):
41
41
  prod = Production("Demo.Production", testing_enabled=True)
42
42
  service = prod.service("HelloService", HelloService)
43
43
  operation = prod.operation("HelloOperation", HelloOperation)
44
- prod.connect(service.Output, operation)
44
+ service.connect(HelloService.Output, operation)
45
45
 
46
46
  PRODUCTIONS = [prod]
47
47
  ```
@@ -201,13 +201,13 @@ class OrderOperation(BusinessOperation):
201
201
  prod = Production("Demo.Production", testing_enabled=True)
202
202
  file = prod.service("FileInput", FileService)
203
203
  orders = prod.operation(OrderOperation)
204
- prod.connect(file.Output, orders)
204
+ file.connect(FileService.Output, orders)
205
205
 
206
206
  PRODUCTIONS = [prod]
207
207
  ```
208
208
 
209
209
  `target()` declares an outbound target setting on the component class.
210
- `prod.connect()` sets that setting to the destination component and
210
+ `component.connect(ComponentClass.Target, destination)` sets that setting to the destination component and
211
211
  records graph edges available to Python.
212
212
 
213
213
  Pass a production item name as the first `target()` argument when a route should
@@ -310,7 +310,7 @@ PRODUCTIONS = [FileProduction()]
310
310
 
311
311
  `target()` declares the outbound target setting on the Python component class.
312
312
  `Route(FileService.Output, ORDER_OPERATION)` wires that setting to a production
313
- item. This is the class-style equivalent of `prod.connect(file.Output, orders)`.
313
+ item. This is the class-style equivalent of `file.connect(FileService.Output, orders)`.
314
314
 
315
315
  For Python component classes, prefer the descriptor form
316
316
  `Route(FileService.Output, ...)`. For existing IRIS classes, use the IRIS
@@ -617,7 +617,7 @@ feed = (
617
617
  .host_setting("Limit", int(os.environ.get("REDDIT_LIMIT", "10")))
618
618
  )
619
619
  exporter = prod.operation("FileExporter", FileOperation)
620
- prod.connect(feed.Output, exporter)
620
+ feed.connect(RedditService.Output, exporter)
621
621
 
622
622
  PRODUCTIONS = [prod]
623
623
  ```
@@ -3,7 +3,7 @@ requires = ["setuptools", "wheel"]
3
3
 
4
4
  [project]
5
5
  name = "iris_pex_embedded_python"
6
- version = "4.0.1b6"
6
+ version = "4.0.1b7"
7
7
  description = "Iris Interoperability based on Embedded Python"
8
8
  readme = "README.md"
9
9
  requires-python = ">=3.10"
@@ -53,6 +53,7 @@ exclude = ["tests*"]
53
53
 
54
54
  [tool.setuptools.package-data]
55
55
  "*" = ["*.cls", "cls/**/*.cls"]
56
+ "iop" = ["py.typed"]
56
57
 
57
58
  [tool.pytest.ini_options]
58
59
  asyncio_default_fixture_loop_scope = "class"
@@ -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]:
@@ -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:
@@ -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:
@@ -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
  ```
@@ -44,6 +44,7 @@ docs/getting-started/installation.md
44
44
  docs/getting-started/register-component.md
45
45
  src/iop/__init__.py
46
46
  src/iop/__main__.py
47
+ src/iop/py.typed
47
48
  src/iop/cli/__init__.py
48
49
  src/iop/cli/formatting.py
49
50
  src/iop/cli/main.py