iris-pex-embedded-python 4.0.1b5__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.
- {iris_pex_embedded_python-4.0.1b5/src/iris_pex_embedded_python.egg-info → iris_pex_embedded_python-4.0.1b7}/PKG-INFO +2 -2
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/README.md +1 -1
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/docs/cookbooks/add-business-operation.md +2 -1
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/docs/cookbooks/add-business-process.md +2 -3
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/docs/cookbooks/add-polling-service.md +1 -1
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/docs/cookbooks/hello-world-production.md +1 -1
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/docs/cookbooks/production-settings-and-targets.md +3 -3
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/docs/getting-started/first-steps.md +2 -2
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/docs/getting-started/register-component.md +2 -2
- iris_pex_embedded_python-4.0.1b7/docs/index.md +68 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/docs/production-graph.md +17 -1
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/docs/python-api.md +21 -2
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/docs/settings.md +5 -5
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/pyproject.toml +2 -1
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/production/component.py +40 -2
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/production/model.py +26 -5
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/production/rendering.py +5 -6
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/production/types.py +2 -2
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/production/validation.py +61 -2
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7/src/iris_pex_embedded_python.egg-info}/PKG-INFO +2 -2
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iris_pex_embedded_python.egg-info/SOURCES.txt +1 -0
- iris_pex_embedded_python-4.0.1b7/src/iris_pex_embedded_python.egg-info/dependency_links.txt +1 -0
- iris_pex_embedded_python-4.0.1b5/docs/index.md +0 -58
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/AGENTS.md +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/LICENSE +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/MANIFEST.in +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/docs/agents-template.md +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/docs/ai-coding.md +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/docs/benchmarks.md +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/docs/changelog.md +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/docs/code-of-conduct.md +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/docs/command-line.md +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/docs/component-interaction.md +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/docs/contributing.md +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/docs/cookbooks/code-index.md +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/docs/cookbooks/fhir-submission-python-client.md +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/docs/cookbooks/hl7v2-native-input.md +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/docs/cookbooks/hl7v2-to-fhir-with-fhir-converter.md +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/docs/cookbooks/index.md +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/docs/cookbooks/remote-migration.md +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/docs/credits.md +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/docs/debug.md +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/docs/dtl.md +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/docs/example.md +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/docs/getting-started/installation.md +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/docs/healthcare-ai-coding.md +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/docs/logging.md +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/docs/prod-settings.md +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/docs/production-change-workflow.md +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/docs/rest-api.md +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/docs/useful-links.md +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/docs/venv.md +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/docs/wrapper.md +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/mkdocs.yml +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/setup.cfg +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/__init__.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/__main__.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/cli/__init__.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/cli/formatting.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/cli/main.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/cli/parser.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/cli/types.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/BusinessOperation.cls +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/BusinessProcess.cls +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/BusinessService.cls +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/Common.cls +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/Director.cls +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/Duplex/Operation.cls +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/Duplex/Process.cls +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/Duplex/Service.cls +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/Generator/Message/Ack.cls +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/Generator/Message/Poll.cls +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/Generator/Message/Start.cls +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/Generator/Message/StartPickle.cls +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/Generator/Message/Stop.cls +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/InboundAdapter.cls +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/Message/JSONSchema.cls +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/Message.cls +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/OutboundAdapter.cls +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/PickleMessage.cls +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/PrivateSession/Duplex.cls +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/PrivateSession/Message/Ack.cls +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/PrivateSession/Message/Poll.cls +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/PrivateSession/Message/Start.cls +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/PrivateSession/Message/Stop.cls +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/Projection.cls +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/Service/Remote/Handler.cls +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/Service/Remote/Rest/v1.cls +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/Test.cls +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/Utils.cls +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/cls/IOP/Wrapper.cls +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/components/__init__.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/components/async_request.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/components/business_host.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/components/business_operation.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/components/business_process.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/components/business_service.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/components/common.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/components/debugpy.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/components/generator_request.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/components/inbound_adapter.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/components/log_manager.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/components/outbound_adapter.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/components/polling_business_service.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/components/private_session_duplex.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/components/private_session_process.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/components/settings.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/messages/__init__.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/messages/base.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/messages/decorators.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/messages/dispatch.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/messages/persistent.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/messages/serialization.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/messages/validation.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/migration/__init__.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/migration/io.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/migration/manifest.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/migration/plans.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/migration/utils.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/production/__init__.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/production/actions.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/production/common.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/production/declarations.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/production/declarative.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/production/diff.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/production/import_.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/production/inspection.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/production/planning.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/production/reconstruction.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/production/runtime.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/production/source_inference.py +0 -0
- /iris_pex_embedded_python-4.0.1b5/src/iris_pex_embedded_python.egg-info/dependency_links.txt → /iris_pex_embedded_python-4.0.1b7/src/iop/py.typed +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/runtime/__init__.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/runtime/director.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/runtime/environment.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/runtime/iris.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/runtime/local.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/runtime/protocol.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/runtime/remote/__init__.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/runtime/remote/client.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/runtime/remote/director.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/runtime/remote/migration.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/runtime/remote/settings.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/runtime/remote/setup.py +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iris_pex_embedded_python.egg-info/entry_points.txt +0 -0
- {iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iris_pex_embedded_python.egg-info/requires.txt +0 -0
- {iris_pex_embedded_python-4.0.1b5 → 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.
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
89
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
55
|
-
|
|
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
|
-
|
|
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
|
-
- `
|
|
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
|
-
|
|
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. `
|
|
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
|
+
[](https://pypi.org/project/iris-pex-embedded-python/)
|
|
4
|
+
[](https://pypi.org/project/iris-pex-embedded-python/)
|
|
5
|
+
[](https://pypi.org/project/iris-pex-embedded-python/)
|
|
6
|
+
[](https://pypi.org/project/iris-pex-embedded-python/)
|
|
7
|
+

|
|
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!
|
{iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/docs/production-graph.md
RENAMED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
`
|
|
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
|
|
@@ -640,6 +653,12 @@ Progressive component methods include `pool()`, `enable()`, `disable()`,
|
|
|
640
653
|
attributes on `ComponentRef`, so their fluent update methods use distinct names
|
|
641
654
|
instead of shadowing those attributes.
|
|
642
655
|
|
|
656
|
+
Declared target settings are available as dynamic `ComponentRef` attributes,
|
|
657
|
+
such as `rest.my_target`, and are exposed through `dir(rest)` for runtime
|
|
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.
|
|
661
|
+
|
|
643
662
|
Python `Production` is the source of truth for Python-authored topology. IRIS
|
|
644
663
|
remains the runtime source of truth. Imported graphs are operational
|
|
645
664
|
reconstructions until metadata persistence makes round-trip fidelity possible.
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
`
|
|
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 `
|
|
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
|
-
|
|
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.
|
|
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"
|
|
@@ -66,6 +66,13 @@ class ComponentRef:
|
|
|
66
66
|
return self.target_setting(name)
|
|
67
67
|
raise AttributeError(name)
|
|
68
68
|
|
|
69
|
+
def __dir__(self) -> list[str]:
|
|
70
|
+
names = set(super().__dir__())
|
|
71
|
+
if self.component_class is not None:
|
|
72
|
+
names.update(_target_setting_names(self.component_class))
|
|
73
|
+
names.update(self.target_setting_names)
|
|
74
|
+
return sorted(names)
|
|
75
|
+
|
|
69
76
|
def target_setting(self, name: str) -> TargetSettingRef:
|
|
70
77
|
self.target_setting_names.add(name)
|
|
71
78
|
return TargetSettingRef(
|
|
@@ -161,7 +168,7 @@ class ComponentRef:
|
|
|
161
168
|
|
|
162
169
|
def connect(
|
|
163
170
|
self,
|
|
164
|
-
target_setting: str | TargetSettingRef,
|
|
171
|
+
target_setting: str | TargetSetting | TargetSettingRef,
|
|
165
172
|
target_component: ComponentRef | str | None = None,
|
|
166
173
|
**kwargs: Any,
|
|
167
174
|
) -> ComponentRef:
|
|
@@ -171,7 +178,7 @@ class ComponentRef:
|
|
|
171
178
|
|
|
172
179
|
def _coerce_target_setting_ref(
|
|
173
180
|
self,
|
|
174
|
-
target_setting: str | TargetSettingRef,
|
|
181
|
+
target_setting: str | TargetSetting | TargetSettingRef,
|
|
175
182
|
) -> TargetSettingRef:
|
|
176
183
|
if isinstance(target_setting, TargetSettingRef):
|
|
177
184
|
if target_setting.production is not self.production:
|
|
@@ -183,6 +190,28 @@ class ComponentRef:
|
|
|
183
190
|
"source target setting belongs to a different component"
|
|
184
191
|
)
|
|
185
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)
|
|
186
215
|
return self.target_setting(str(target_setting))
|
|
187
216
|
|
|
188
217
|
def inspect(self, *, refresh: bool = True) -> dict[str, Any]:
|
|
@@ -232,3 +261,12 @@ class ComponentRef:
|
|
|
232
261
|
item["Setting"] = settings
|
|
233
262
|
|
|
234
263
|
return item
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
def _target_setting_names(component_class: type) -> tuple[str, ...]:
|
|
267
|
+
names: dict[str, None] = {}
|
|
268
|
+
for base in reversed(component_class.__mro__):
|
|
269
|
+
for name, value in base.__dict__.items():
|
|
270
|
+
if isinstance(value, TargetSetting):
|
|
271
|
+
names[name] = None
|
|
272
|
+
return tuple(names)
|
{iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/production/model.py
RENAMED
|
@@ -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
|
|
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(
|
|
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(
|
|
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(
|
|
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"
|
|
477
|
+
f"{source_var}.connect({source_expr}, {variables[valid_targets[0]]})"
|
|
480
478
|
)
|
|
481
479
|
else:
|
|
482
480
|
lines.append(
|
|
483
|
-
f"
|
|
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"
|
|
485
|
+
f"{source_var}.connect({source_expr}, {variables[target]}, "
|
|
486
|
+
"mode='add')"
|
|
488
487
|
)
|
|
489
488
|
|
|
490
489
|
for edge in production.edges:
|
{iris_pex_embedded_python-4.0.1b5 → iris_pex_embedded_python-4.0.1b7}/src/iop/production/types.py
RENAMED
|
@@ -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:
|
|
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:
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
101
|
+
service.connect(HelloService.Output, operation)
|
|
102
102
|
|
|
103
103
|
PRODUCTIONS = [prod]
|
|
104
104
|
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|