iris-pex-embedded-python 4.0.2b1__tar.gz → 4.1.0b1__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.2b1/src/iris_pex_embedded_python.egg-info → iris_pex_embedded_python-4.1.0b1}/PKG-INFO +41 -5
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/README.md +21 -2
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/docs/contributing.md +3 -2
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/docs/debug.md +1 -2
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/docs/index.md +2 -2
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/docs/python-api.md +4 -1
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/pyproject.toml +26 -3
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/cli/formatting.py +2 -2
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/cli/main.py +2 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/components/async_request.py +36 -25
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/components/debugpy.py +8 -2
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/messages/persistent.py +146 -44
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/messages/serialization.py +3 -0
- iris_pex_embedded_python-4.0.2b1/src/iop/migration/io.py → iris_pex_embedded_python-4.1.0b1/src/iop/migration/_conversion.py +0 -3
- iris_pex_embedded_python-4.1.0b1/src/iop/migration/_production_io.py +82 -0
- iris_pex_embedded_python-4.1.0b1/src/iop/migration/_registration.py +78 -0
- iris_pex_embedded_python-4.1.0b1/src/iop/migration/_settings.py +47 -0
- iris_pex_embedded_python-4.1.0b1/src/iop/migration/io.py +7 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/migration/manifest.py +2 -2
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/migration/utils.py +40 -174
- iris_pex_embedded_python-4.1.0b1/src/iop/production/_authoring_methods.py +182 -0
- iris_pex_embedded_python-4.1.0b1/src/iop/production/_runtime_methods.py +159 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/production/actions.py +1 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/production/model.py +12 -313
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/production/planning.py +4 -4
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/runtime/director.py +2 -1
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/runtime/remote/director.py +6 -1
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1/src/iris_pex_embedded_python.egg-info}/PKG-INFO +41 -5
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iris_pex_embedded_python.egg-info/SOURCES.txt +6 -0
- iris_pex_embedded_python-4.1.0b1/src/iris_pex_embedded_python.egg-info/requires.txt +26 -0
- iris_pex_embedded_python-4.0.2b1/src/iris_pex_embedded_python.egg-info/requires.txt +0 -7
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/AGENTS.md +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/LICENSE +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/MANIFEST.in +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/docs/agents-template.md +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/docs/ai-coding.md +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/docs/benchmarks.md +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/docs/changelog.md +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/docs/code-of-conduct.md +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/docs/command-line.md +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/docs/component-interaction.md +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/docs/cookbooks/add-business-operation.md +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/docs/cookbooks/add-business-process.md +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/docs/cookbooks/add-polling-service.md +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/docs/cookbooks/code-index.md +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/docs/cookbooks/fhir-submission-python-client.md +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/docs/cookbooks/hello-world-production.md +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/docs/cookbooks/hl7v2-native-input.md +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/docs/cookbooks/hl7v2-to-fhir-with-fhir-converter.md +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/docs/cookbooks/index.md +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/docs/cookbooks/production-settings-and-targets.md +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/docs/cookbooks/remote-migration.md +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/docs/credits.md +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/docs/dtl.md +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/docs/example.md +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/docs/getting-started/first-steps.md +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/docs/getting-started/installation.md +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/docs/getting-started/register-component.md +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/docs/healthcare-ai-coding.md +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/docs/logging.md +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/docs/prod-settings.md +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/docs/production-change-workflow.md +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/docs/production-graph.md +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/docs/rest-api.md +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/docs/settings.md +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/docs/useful-links.md +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/docs/venv.md +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/docs/wrapper.md +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/mkdocs.yml +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/setup.cfg +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/__init__.py +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/__main__.py +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/cli/__init__.py +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/cli/parser.py +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/cli/types.py +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/cls/IOP/BusinessOperation.cls +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/cls/IOP/BusinessProcess.cls +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/cls/IOP/BusinessService.cls +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/cls/IOP/Common.cls +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/cls/IOP/Director.cls +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/cls/IOP/Duplex/Operation.cls +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/cls/IOP/Duplex/Process.cls +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/cls/IOP/Duplex/Service.cls +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/cls/IOP/Generator/Message/Ack.cls +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/cls/IOP/Generator/Message/Poll.cls +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/cls/IOP/Generator/Message/Start.cls +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/cls/IOP/Generator/Message/StartPickle.cls +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/cls/IOP/Generator/Message/Stop.cls +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/cls/IOP/InboundAdapter.cls +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/cls/IOP/Message/JSONSchema.cls +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/cls/IOP/Message.cls +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/cls/IOP/OutboundAdapter.cls +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/cls/IOP/PickleMessage.cls +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/cls/IOP/PrivateSession/Duplex.cls +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/cls/IOP/PrivateSession/Message/Ack.cls +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/cls/IOP/PrivateSession/Message/Poll.cls +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/cls/IOP/PrivateSession/Message/Start.cls +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/cls/IOP/PrivateSession/Message/Stop.cls +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/cls/IOP/Projection.cls +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/cls/IOP/Service/Remote/Handler.cls +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/cls/IOP/Service/Remote/Rest/v1.cls +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/cls/IOP/Test.cls +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/cls/IOP/Utils.cls +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/cls/IOP/Wrapper.cls +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/components/__init__.py +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/components/business_host.py +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/components/business_operation.py +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/components/business_process.py +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/components/business_service.py +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/components/common.py +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/components/generator_request.py +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/components/inbound_adapter.py +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/components/log_manager.py +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/components/outbound_adapter.py +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/components/polling_business_service.py +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/components/private_session_duplex.py +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/components/private_session_process.py +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/components/settings.py +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/messages/__init__.py +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/messages/base.py +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/messages/decorators.py +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/messages/dispatch.py +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/messages/validation.py +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/migration/__init__.py +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/migration/plans.py +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/production/__init__.py +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/production/common.py +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/production/component.py +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/production/declarations.py +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/production/declarative.py +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/production/diff.py +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/production/import_.py +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/production/inspection.py +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/production/reconstruction.py +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/production/rendering.py +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/production/runtime.py +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/production/source_inference.py +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/production/types.py +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/production/validation.py +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/py.typed +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/runtime/__init__.py +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/runtime/environment.py +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/runtime/iris.py +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/runtime/local.py +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/runtime/protocol.py +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/runtime/remote/__init__.py +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/runtime/remote/client.py +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/runtime/remote/migration.py +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/runtime/remote/settings.py +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/runtime/remote/setup.py +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iris_pex_embedded_python.egg-info/dependency_links.txt +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iris_pex_embedded_python.egg-info/entry_points.txt +0 -0
- {iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/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.
|
|
3
|
+
Version: 4.1.0b1
|
|
4
4
|
Summary: Iris Interoperability based on Embedded Python
|
|
5
5
|
Author-email: grongier <guillaume.rongier@intersystems.com>
|
|
6
6
|
License: MIT License
|
|
@@ -46,10 +46,27 @@ License-File: LICENSE
|
|
|
46
46
|
Requires-Dist: pydantic>=2.0.0
|
|
47
47
|
Requires-Dist: xmltodict>=0.12.0
|
|
48
48
|
Requires-Dist: iris-embedded-python-wrapper>=0.5.0
|
|
49
|
-
Requires-Dist: iris-persistence>=0.
|
|
49
|
+
Requires-Dist: iris-persistence>=0.3.0
|
|
50
50
|
Requires-Dist: jsonpath-ng>=1.7.0
|
|
51
|
-
Requires-Dist: debugpy>=1.8.0
|
|
52
51
|
Requires-Dist: requests>=2.24.0
|
|
52
|
+
Provides-Extra: debug
|
|
53
|
+
Requires-Dist: debugpy>=1.8.0; extra == "debug"
|
|
54
|
+
Provides-Extra: dev
|
|
55
|
+
Requires-Dist: build; extra == "dev"
|
|
56
|
+
Requires-Dist: dataclasses-json; extra == "dev"
|
|
57
|
+
Requires-Dist: intersystems-irispython; extra == "dev"
|
|
58
|
+
Requires-Dist: mkdocs; extra == "dev"
|
|
59
|
+
Requires-Dist: mkdocs-gen-files; extra == "dev"
|
|
60
|
+
Requires-Dist: pymdown-extensions; extra == "dev"
|
|
61
|
+
Requires-Dist: pyright; extra == "dev"
|
|
62
|
+
Requires-Dist: pytest; extra == "dev"
|
|
63
|
+
Requires-Dist: pytest-asyncio; extra == "dev"
|
|
64
|
+
Requires-Dist: python-dotenv; extra == "dev"
|
|
65
|
+
Requires-Dist: ruff; extra == "dev"
|
|
66
|
+
Requires-Dist: tox>=4; extra == "dev"
|
|
67
|
+
Requires-Dist: twine; extra == "dev"
|
|
68
|
+
Requires-Dist: wheel; extra == "dev"
|
|
69
|
+
Requires-Dist: debugpy>=1.8.0; extra == "dev"
|
|
53
70
|
Dynamic: license-file
|
|
54
71
|
|
|
55
72
|
# IoP (Interoperability On Python)
|
|
@@ -60,7 +77,7 @@ Dynamic: license-file
|
|
|
60
77
|
[](https://pypi.org/project/iris-pex-embedded-python/)
|
|
61
78
|

|
|
62
79
|
|
|
63
|
-
Welcome to
|
|
80
|
+
Welcome to **Interoperability On Python (IoP)**, a production-stable Python-first toolkit for building on the **IRIS Interoperability Framework**.
|
|
64
81
|
|
|
65
82
|
Documentation can be found [here](https://grongierisc.github.io/interoperability-embedded-python/).
|
|
66
83
|
For prompt-driven workflows, see [AI-assisted coding with IoP](https://grongierisc.github.io/interoperability-embedded-python/ai-coding/).
|
|
@@ -105,7 +122,7 @@ PRODUCTIONS = [prod]
|
|
|
105
122
|
|
|
106
123
|
## Installation
|
|
107
124
|
|
|
108
|
-
|
|
125
|
+
Install the production-stable package using pip:
|
|
109
126
|
|
|
110
127
|
```bash
|
|
111
128
|
pip install iris-pex-embedded-python
|
|
@@ -120,3 +137,22 @@ For concrete workflows, use the [IoP cookbooks](https://grongierisc.github.io/in
|
|
|
120
137
|
For healthcare productions, also see [Healthcare AI-assisted coding](https://grongierisc.github.io/interoperability-embedded-python/healthcare-ai-coding/).
|
|
121
138
|
|
|
122
139
|
Happy coding!
|
|
140
|
+
|
|
141
|
+
## Compatibility and support
|
|
142
|
+
|
|
143
|
+
IoP supports Python 3.10 through 3.14 and InterSystems IRIS 2021.2 or newer.
|
|
144
|
+
Changes follow semantic versioning:
|
|
145
|
+
backward-compatible features and deprecations ship in minor releases, while
|
|
146
|
+
removals are reserved for major releases and are announced in the changelog.
|
|
147
|
+
IRIS compatibility is continuously checked against the latest Community image;
|
|
148
|
+
the preview image is tested nightly to identify upcoming incompatibilities.
|
|
149
|
+
|
|
150
|
+
## Contributing
|
|
151
|
+
|
|
152
|
+
Create a Python 3.10 or newer virtual environment, then install and verify the
|
|
153
|
+
development environment with:
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
python -m pip install -e ".[dev]"
|
|
157
|
+
tox
|
|
158
|
+
```
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
[](https://pypi.org/project/iris-pex-embedded-python/)
|
|
7
7
|

|
|
8
8
|
|
|
9
|
-
Welcome to
|
|
9
|
+
Welcome to **Interoperability On Python (IoP)**, a production-stable Python-first toolkit for building on the **IRIS Interoperability Framework**.
|
|
10
10
|
|
|
11
11
|
Documentation can be found [here](https://grongierisc.github.io/interoperability-embedded-python/).
|
|
12
12
|
For prompt-driven workflows, see [AI-assisted coding with IoP](https://grongierisc.github.io/interoperability-embedded-python/ai-coding/).
|
|
@@ -51,7 +51,7 @@ PRODUCTIONS = [prod]
|
|
|
51
51
|
|
|
52
52
|
## Installation
|
|
53
53
|
|
|
54
|
-
|
|
54
|
+
Install the production-stable package using pip:
|
|
55
55
|
|
|
56
56
|
```bash
|
|
57
57
|
pip install iris-pex-embedded-python
|
|
@@ -66,3 +66,22 @@ For concrete workflows, use the [IoP cookbooks](https://grongierisc.github.io/in
|
|
|
66
66
|
For healthcare productions, also see [Healthcare AI-assisted coding](https://grongierisc.github.io/interoperability-embedded-python/healthcare-ai-coding/).
|
|
67
67
|
|
|
68
68
|
Happy coding!
|
|
69
|
+
|
|
70
|
+
## Compatibility and support
|
|
71
|
+
|
|
72
|
+
IoP supports Python 3.10 through 3.14 and InterSystems IRIS 2021.2 or newer.
|
|
73
|
+
Changes follow semantic versioning:
|
|
74
|
+
backward-compatible features and deprecations ship in minor releases, while
|
|
75
|
+
removals are reserved for major releases and are announced in the changelog.
|
|
76
|
+
IRIS compatibility is continuously checked against the latest Community image;
|
|
77
|
+
the preview image is tested nightly to identify upcoming incompatibilities.
|
|
78
|
+
|
|
79
|
+
## Contributing
|
|
80
|
+
|
|
81
|
+
Create a Python 3.10 or newer virtual environment, then install and verify the
|
|
82
|
+
development environment with:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
python -m pip install -e ".[dev]"
|
|
86
|
+
tox
|
|
87
|
+
```
|
|
@@ -14,7 +14,8 @@ source .venv/bin/activate
|
|
|
14
14
|
### Install the dependencies.
|
|
15
15
|
|
|
16
16
|
```bash
|
|
17
|
-
pip install -
|
|
17
|
+
python -m pip install -e ".[dev]"
|
|
18
|
+
tox
|
|
18
19
|
```
|
|
19
20
|
|
|
20
21
|
### Have a running IRIS instance.
|
|
@@ -45,7 +46,7 @@ ln -s <your_git_dir>/src/iop $IRISINSTALLDIR/python/iop
|
|
|
45
46
|
##### Run the unit tests.
|
|
46
47
|
|
|
47
48
|
```bash
|
|
48
|
-
|
|
49
|
+
tox -e py
|
|
49
50
|
```
|
|
50
51
|
|
|
51
52
|
#### Docker installation of IRIS
|
|
@@ -153,7 +153,7 @@ And select the virtual environment in VsCode.
|
|
|
153
153
|
4. Install the dependencies.
|
|
154
154
|
|
|
155
155
|
```bash
|
|
156
|
-
pip install -
|
|
156
|
+
python -m pip install -e ".[debug]"
|
|
157
157
|
```
|
|
158
158
|
|
|
159
159
|
5. Run the code in debug mode.
|
|
@@ -219,4 +219,3 @@ With tracebacks enabled:
|
|
|
219
219
|
With tracebacks disabled:
|
|
220
220
|
|
|
221
221
|

|
|
222
|
-
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
[](https://pypi.org/project/iris-pex-embedded-python/)
|
|
7
7
|

|
|
8
8
|
|
|
9
|
-
Welcome to
|
|
9
|
+
Welcome to **Interoperability On Python (IoP)**, a production-stable Python-first toolkit for building on the **IRIS Interoperability Framework**.
|
|
10
10
|
|
|
11
11
|
Documentation can be found [here](https://grongierisc.github.io/interoperability-embedded-python/).
|
|
12
12
|
For prompt-driven workflows, see [AI-assisted coding with IoP](https://grongierisc.github.io/interoperability-embedded-python/ai-coding/).
|
|
@@ -51,7 +51,7 @@ PRODUCTIONS = [prod]
|
|
|
51
51
|
|
|
52
52
|
## Installation
|
|
53
53
|
|
|
54
|
-
|
|
54
|
+
Install the production-stable package using pip:
|
|
55
55
|
|
|
56
56
|
```bash
|
|
57
57
|
pip install iris-pex-embedded-python
|
|
@@ -35,7 +35,10 @@ class MyRequest(PydanticMessage):
|
|
|
35
35
|
|
|
36
36
|
Base class for native IRIS message body classes backed by `iris-persistence`. Fields are declared directly on the Python class.
|
|
37
37
|
|
|
38
|
-
By default, a `PersistentMessage` generates an IRIS class that extends
|
|
38
|
+
By default, a `PersistentMessage` generates an IRIS class that extends
|
|
39
|
+
`Ens.MessageBody`, uses schema mode `managed`, and enables runtime auto-sync in
|
|
40
|
+
managed mode. This is the replacement for the `extend` mode removed in
|
|
41
|
+
`iris-persistence` 0.3.
|
|
39
42
|
|
|
40
43
|
**Example:**
|
|
41
44
|
```python
|
|
@@ -3,7 +3,7 @@ requires = ["setuptools", "wheel"]
|
|
|
3
3
|
|
|
4
4
|
[project]
|
|
5
5
|
name = "iris_pex_embedded_python"
|
|
6
|
-
version = "4.
|
|
6
|
+
version = "4.1.0b1"
|
|
7
7
|
description = "Iris Interoperability based on Embedded Python"
|
|
8
8
|
readme = "README.md"
|
|
9
9
|
requires-python = ">=3.10"
|
|
@@ -29,14 +29,35 @@ dependencies = [
|
|
|
29
29
|
"pydantic>=2.0.0",
|
|
30
30
|
"xmltodict>=0.12.0",
|
|
31
31
|
"iris-embedded-python-wrapper>=0.5.0",
|
|
32
|
-
"iris-persistence>=0.
|
|
32
|
+
"iris-persistence>=0.3.0",
|
|
33
33
|
"jsonpath-ng>=1.7.0",
|
|
34
|
-
"debugpy>=1.8.0",
|
|
35
34
|
"requests>=2.24.0"
|
|
36
35
|
]
|
|
37
36
|
|
|
38
37
|
license = { file = "LICENSE" }
|
|
39
38
|
|
|
39
|
+
[project.optional-dependencies]
|
|
40
|
+
debug = [
|
|
41
|
+
"debugpy>=1.8.0",
|
|
42
|
+
]
|
|
43
|
+
dev = [
|
|
44
|
+
"build",
|
|
45
|
+
"dataclasses-json",
|
|
46
|
+
"intersystems-irispython",
|
|
47
|
+
"mkdocs",
|
|
48
|
+
"mkdocs-gen-files",
|
|
49
|
+
"pymdown-extensions",
|
|
50
|
+
"pyright",
|
|
51
|
+
"pytest",
|
|
52
|
+
"pytest-asyncio",
|
|
53
|
+
"python-dotenv",
|
|
54
|
+
"ruff",
|
|
55
|
+
"tox>=4",
|
|
56
|
+
"twine",
|
|
57
|
+
"wheel",
|
|
58
|
+
"debugpy>=1.8.0",
|
|
59
|
+
]
|
|
60
|
+
|
|
40
61
|
[project.urls]
|
|
41
62
|
homepage = "https://github.com/grongierisc/interoperability-embedded-python"
|
|
42
63
|
documentation = "https://github.com/grongierisc/interoperability-embedded-python/blob/master/README.md"
|
|
@@ -66,10 +87,12 @@ markers = [
|
|
|
66
87
|
|
|
67
88
|
[tool.pyright]
|
|
68
89
|
pythonVersion = "3.10"
|
|
90
|
+
include = ["src/iop"]
|
|
69
91
|
|
|
70
92
|
[tool.ruff]
|
|
71
93
|
target-version = "py310"
|
|
72
94
|
line-length = 88
|
|
95
|
+
exclude = ["src/tests"]
|
|
73
96
|
|
|
74
97
|
[tool.ruff.lint]
|
|
75
98
|
select = ["E", "F", "I", "B", "UP"]
|
{iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/cli/formatting.py
RENAMED
|
@@ -2,7 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import dataclasses
|
|
4
4
|
import json
|
|
5
|
-
from typing import Any
|
|
5
|
+
from typing import Any, cast
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
def format_test_response(response: Any) -> str:
|
|
@@ -41,5 +41,5 @@ def format_test_response(response: Any) -> str:
|
|
|
41
41
|
return response
|
|
42
42
|
|
|
43
43
|
if dataclasses.is_dataclass(response):
|
|
44
|
-
return json.dumps(dataclasses.asdict(response), indent=4)
|
|
44
|
+
return json.dumps(dataclasses.asdict(cast(Any, response)), indent=4)
|
|
45
45
|
return str(response)
|
|
@@ -241,6 +241,8 @@ class Command:
|
|
|
241
241
|
if self.args.export == "not_set"
|
|
242
242
|
else self.args.export
|
|
243
243
|
)
|
|
244
|
+
if not export_name:
|
|
245
|
+
raise ValueError("No production name was provided or configured.")
|
|
244
246
|
export_format = self.args.export_format or "json"
|
|
245
247
|
if export_format == "json":
|
|
246
248
|
print(json.dumps(self.director.export_production(export_name), indent=4))
|
|
@@ -30,37 +30,48 @@ class AsyncRequest(asyncio.Future):
|
|
|
30
30
|
if host is None:
|
|
31
31
|
raise ValueError("host parameter cannot be None")
|
|
32
32
|
self._iris_handle = host.iris_handle
|
|
33
|
-
|
|
33
|
+
self._message_header_id = 0
|
|
34
|
+
self._queue_name = ""
|
|
35
|
+
self._end_time = 0
|
|
36
|
+
self._response = None
|
|
37
|
+
self._done = False
|
|
38
|
+
self._send_task = asyncio.create_task(self.send())
|
|
34
39
|
|
|
35
40
|
async def send(self) -> None:
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
41
|
+
try:
|
|
42
|
+
iris = _iris.get_iris()
|
|
43
|
+
message_header_id = iris.ref()
|
|
44
|
+
queue_name = iris.ref()
|
|
45
|
+
end_time = iris.ref()
|
|
46
|
+
request = dispatch_serializer(self.request)
|
|
42
47
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
)
|
|
48
|
+
self._iris_handle.dispatchSendRequestAsyncNG(
|
|
49
|
+
self.target,
|
|
50
|
+
request,
|
|
51
|
+
self.timeout,
|
|
52
|
+
self.description,
|
|
53
|
+
message_header_id,
|
|
54
|
+
queue_name,
|
|
55
|
+
end_time,
|
|
56
|
+
)
|
|
53
57
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
self._end_time = end_time.value
|
|
58
|
+
self._message_header_id = message_header_id.value
|
|
59
|
+
self._queue_name = queue_name.value
|
|
60
|
+
self._end_time = end_time.value
|
|
58
61
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
+
while not self._done:
|
|
63
|
+
await asyncio.sleep(0.1)
|
|
64
|
+
self.is_done()
|
|
62
65
|
|
|
63
|
-
|
|
66
|
+
if not self.done():
|
|
67
|
+
self.set_result(self._response)
|
|
68
|
+
except asyncio.CancelledError:
|
|
69
|
+
if not self.done():
|
|
70
|
+
self.cancel()
|
|
71
|
+
raise
|
|
72
|
+
except Exception as exc:
|
|
73
|
+
if not self.done():
|
|
74
|
+
self.set_exception(exc)
|
|
64
75
|
|
|
65
76
|
def is_done(self) -> None:
|
|
66
77
|
iris = _iris.get_iris()
|
{iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/components/debugpy.py
RENAMED
|
@@ -127,7 +127,10 @@ def debugpython(self, host_object: Any) -> None:
|
|
|
127
127
|
return
|
|
128
128
|
|
|
129
129
|
if not is_debugpy_installed():
|
|
130
|
-
self.log_alert(
|
|
130
|
+
self.log_alert(
|
|
131
|
+
"Debugpy is not installed. Install iris-pex-embedded-python[debug] "
|
|
132
|
+
"to enable remote debugging."
|
|
133
|
+
)
|
|
131
134
|
return
|
|
132
135
|
|
|
133
136
|
# Configure Python interpreter
|
|
@@ -167,7 +170,10 @@ def debugpy_in_iris(iris_dir, port) -> bool:
|
|
|
167
170
|
os.__file__ = __file__
|
|
168
171
|
|
|
169
172
|
if not is_debugpy_installed():
|
|
170
|
-
print(
|
|
173
|
+
print(
|
|
174
|
+
"debugpy is not installed. Install iris-pex-embedded-python[debug] "
|
|
175
|
+
"to enable remote debugging."
|
|
176
|
+
)
|
|
171
177
|
return False
|
|
172
178
|
if not iris_dir:
|
|
173
179
|
print("IRIS directory is not specified.")
|
{iris_pex_embedded_python-4.0.2b1 → iris_pex_embedded_python-4.1.0b1}/src/iop/messages/persistent.py
RENAMED
|
@@ -4,18 +4,19 @@ import importlib
|
|
|
4
4
|
import inspect
|
|
5
5
|
import os
|
|
6
6
|
import sys
|
|
7
|
+
from dataclasses import dataclass
|
|
8
|
+
from enum import Enum
|
|
7
9
|
from typing import Any
|
|
8
10
|
|
|
9
|
-
import iris_persistence
|
|
10
11
|
from iris_persistence import Field as Field
|
|
11
|
-
from iris_persistence import Model
|
|
12
|
+
from iris_persistence import Model as _PersistenceModel
|
|
12
13
|
from iris_persistence.models import ModelMeta
|
|
13
14
|
from iris_persistence.runtime import get_runtime
|
|
14
15
|
|
|
15
16
|
from ..runtime.environment import prepend_sys_path
|
|
16
17
|
|
|
17
18
|
DEFAULT_SUPERCLASS = "Ens.MessageBody"
|
|
18
|
-
DEFAULT_SYNC_MODE = "
|
|
19
|
+
DEFAULT_SYNC_MODE = "managed"
|
|
19
20
|
MESSAGE_KIND_PARAMETER = "IOP_MESSAGE_KIND"
|
|
20
21
|
MESSAGE_KIND_VALUE = "PersistentMessage"
|
|
21
22
|
PYTHON_CLASS_PARAMETER = "IOP_PYTHON_CLASS"
|
|
@@ -28,13 +29,46 @@ _IRIS_TO_PYTHON_STRICT_CACHE: dict[str, bool] = {}
|
|
|
28
29
|
_IRIS_TO_MESSAGE_CLASS_CACHE: dict[str, type] = {}
|
|
29
30
|
_IRIS_PARAMETER_CACHE: dict[tuple[str, str], str | None] = {}
|
|
30
31
|
_AUTO_SYNCED: set[tuple[type, str]] = set()
|
|
32
|
+
_CACHE_VALUE_UNSET = object()
|
|
31
33
|
|
|
32
34
|
|
|
33
35
|
class PersistentMessageError(Exception):
|
|
34
36
|
"""Raised when a native persistent message cannot be materialized."""
|
|
35
37
|
|
|
36
38
|
|
|
37
|
-
class
|
|
39
|
+
class _PersistentMessageResolutionState(Enum):
|
|
40
|
+
UNMAPPED = "unmapped"
|
|
41
|
+
RESOLVED = "resolved"
|
|
42
|
+
INVALID = "invalid"
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@dataclass(frozen=True)
|
|
46
|
+
class _PersistentMessageResolution:
|
|
47
|
+
state: _PersistentMessageResolutionState
|
|
48
|
+
message_class: type | None = None
|
|
49
|
+
error: PersistentMessageError | None = None
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _materialize_deferred_annotations(namespace: dict) -> None:
|
|
53
|
+
"""Expose Python 3.14 deferred annotations to iris-persistence."""
|
|
54
|
+
if "__annotations__" in namespace:
|
|
55
|
+
return
|
|
56
|
+
annotate = namespace.get("__annotate_func__")
|
|
57
|
+
if annotate is not None:
|
|
58
|
+
namespace["__annotations__"] = annotate(1)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class _ModelMeta(ModelMeta):
|
|
62
|
+
def __new__(mcs, name: str, bases: tuple, namespace: dict, **kwargs: Any):
|
|
63
|
+
_materialize_deferred_annotations(namespace)
|
|
64
|
+
return super().__new__(mcs, name, bases, namespace, **kwargs)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class Model(_PersistenceModel, metaclass=_ModelMeta):
|
|
68
|
+
"""Python 3.10–3.14 compatible public persistence model base."""
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class _PersistentMessageMeta(_ModelMeta):
|
|
38
72
|
def __init__(cls, name: str, bases: tuple, namespace: dict, **kwargs: Any):
|
|
39
73
|
super().__init__(name, bases, namespace, **kwargs)
|
|
40
74
|
|
|
@@ -199,8 +233,7 @@ def serialize_persistent_message(
|
|
|
199
233
|
iris_classname = resolve_iris_classname(msg_cls)
|
|
200
234
|
_ensure_schema(msg_cls, iris_classname)
|
|
201
235
|
|
|
202
|
-
iris_obj =
|
|
203
|
-
message,
|
|
236
|
+
iris_obj = message.to_iris(
|
|
204
237
|
auto_sync=False,
|
|
205
238
|
validate=False,
|
|
206
239
|
)
|
|
@@ -215,36 +248,14 @@ def deserialize_persistent_message(
|
|
|
215
248
|
if not iris_classname:
|
|
216
249
|
return serial
|
|
217
250
|
|
|
218
|
-
|
|
219
|
-
if
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
try:
|
|
227
|
-
msg_cls = load_python_class(python_classname, python_classpath)
|
|
228
|
-
except (AttributeError, ModuleNotFoundError, PersistentMessageError) as exc:
|
|
229
|
-
if strict:
|
|
230
|
-
raise PersistentMessageError(
|
|
231
|
-
f"IRIS class {iris_classname!r} is marked as a PersistentMessage for "
|
|
232
|
-
f"Python class {python_classname!r}, but that Python class could not "
|
|
233
|
-
"be imported. Ensure the message class is importable, or register it "
|
|
234
|
-
"through CLASSES so migration writes IOP_PYTHON_CLASSPATH."
|
|
235
|
-
) from exc
|
|
236
|
-
return serial
|
|
237
|
-
|
|
238
|
-
if not is_persistent_message_class(msg_cls):
|
|
239
|
-
if strict:
|
|
240
|
-
raise PersistentMessageError(
|
|
241
|
-
f"IRIS class {iris_classname!r} maps to {python_classname!r}, "
|
|
242
|
-
"but that class is not a PersistentMessage subclass."
|
|
243
|
-
)
|
|
244
|
-
return serial
|
|
245
|
-
|
|
246
|
-
_prepare_message_class(msg_cls, iris_classname, registered=False)
|
|
247
|
-
_IRIS_TO_MESSAGE_CLASS_CACHE[iris_classname] = msg_cls
|
|
251
|
+
resolution = _resolve_persistent_message_class(iris_classname)
|
|
252
|
+
if resolution.state is _PersistentMessageResolutionState.UNMAPPED:
|
|
253
|
+
return serial
|
|
254
|
+
if resolution.state is _PersistentMessageResolutionState.INVALID:
|
|
255
|
+
assert resolution.error is not None
|
|
256
|
+
raise resolution.error
|
|
257
|
+
msg_cls = resolution.message_class
|
|
258
|
+
assert msg_cls is not None
|
|
248
259
|
|
|
249
260
|
known_pk = _safe_get_object_id(serial)
|
|
250
261
|
return msg_cls.from_iris(serial, known_pk=known_pk or "")
|
|
@@ -353,7 +364,7 @@ def _ensure_schema(msg_cls: type, iris_classname: str) -> None:
|
|
|
353
364
|
raise PersistentMessageError(
|
|
354
365
|
f"{get_python_classname(msg_cls)} has auto_sync=True but mode="
|
|
355
366
|
f"{getattr(msg_cls, '_sync_mode', None)!r}. Runtime auto-sync is only allowed "
|
|
356
|
-
"with mode='
|
|
367
|
+
"with mode='managed'."
|
|
357
368
|
)
|
|
358
369
|
|
|
359
370
|
_prepare_message_class(msg_cls, iris_classname, registered=False)
|
|
@@ -372,8 +383,12 @@ def _prepare_message_class(
|
|
|
372
383
|
if registered:
|
|
373
384
|
msg_cls._iop_registered_classname = iris_classname
|
|
374
385
|
_set_message_parameters(msg_cls)
|
|
375
|
-
_cache_mapping(
|
|
376
|
-
|
|
386
|
+
_cache_mapping(
|
|
387
|
+
get_python_classname(msg_cls),
|
|
388
|
+
iris_classname,
|
|
389
|
+
python_classpath=get_python_classpath(msg_cls),
|
|
390
|
+
message_class=msg_cls,
|
|
391
|
+
)
|
|
377
392
|
|
|
378
393
|
|
|
379
394
|
def _set_message_parameters(msg_cls: type) -> None:
|
|
@@ -388,10 +403,37 @@ def _set_message_parameters(msg_cls: type) -> None:
|
|
|
388
403
|
msg_cls._parameters = parameters
|
|
389
404
|
|
|
390
405
|
|
|
391
|
-
def _cache_mapping(
|
|
406
|
+
def _cache_mapping(
|
|
407
|
+
python_classname: str,
|
|
408
|
+
iris_classname: str,
|
|
409
|
+
*,
|
|
410
|
+
python_classpath: str | None | object = _CACHE_VALUE_UNSET,
|
|
411
|
+
strict: bool = True,
|
|
412
|
+
message_class: type | None = None,
|
|
413
|
+
) -> None:
|
|
414
|
+
previous_iris = _PYTHON_TO_IRIS_CACHE.get(python_classname)
|
|
415
|
+
if previous_iris and previous_iris != iris_classname:
|
|
416
|
+
_IRIS_TO_PYTHON_CACHE.pop(previous_iris, None)
|
|
417
|
+
_IRIS_TO_PYTHON_CLASSPATH_CACHE.pop(previous_iris, None)
|
|
418
|
+
_IRIS_TO_PYTHON_STRICT_CACHE.pop(previous_iris, None)
|
|
419
|
+
_IRIS_TO_MESSAGE_CLASS_CACHE.pop(previous_iris, None)
|
|
420
|
+
|
|
421
|
+
previous_python = _IRIS_TO_PYTHON_CACHE.get(iris_classname)
|
|
422
|
+
if previous_python and previous_python != python_classname:
|
|
423
|
+
if _PYTHON_TO_IRIS_CACHE.get(previous_python) == iris_classname:
|
|
424
|
+
_PYTHON_TO_IRIS_CACHE.pop(previous_python, None)
|
|
425
|
+
_IRIS_TO_MESSAGE_CLASS_CACHE.pop(iris_classname, None)
|
|
426
|
+
|
|
392
427
|
_PYTHON_TO_IRIS_CACHE[python_classname] = iris_classname
|
|
393
428
|
_IRIS_TO_PYTHON_CACHE[iris_classname] = python_classname
|
|
394
|
-
_IRIS_TO_PYTHON_STRICT_CACHE[iris_classname] =
|
|
429
|
+
_IRIS_TO_PYTHON_STRICT_CACHE[iris_classname] = strict
|
|
430
|
+
if python_classpath is not _CACHE_VALUE_UNSET:
|
|
431
|
+
if python_classpath:
|
|
432
|
+
_IRIS_TO_PYTHON_CLASSPATH_CACHE[iris_classname] = str(python_classpath)
|
|
433
|
+
else:
|
|
434
|
+
_IRIS_TO_PYTHON_CLASSPATH_CACHE.pop(iris_classname, None)
|
|
435
|
+
if message_class is not None:
|
|
436
|
+
_IRIS_TO_MESSAGE_CLASS_CACHE[iris_classname] = message_class
|
|
395
437
|
|
|
396
438
|
|
|
397
439
|
def _resolve_python_message_metadata(
|
|
@@ -416,13 +458,73 @@ def _resolve_python_message_metadata(
|
|
|
416
458
|
python_classname = iris_classname_to_python_classname(iris_classname)
|
|
417
459
|
|
|
418
460
|
if python_classname and strict:
|
|
419
|
-
_cache_mapping(
|
|
420
|
-
|
|
421
|
-
|
|
461
|
+
_cache_mapping(
|
|
462
|
+
python_classname,
|
|
463
|
+
iris_classname,
|
|
464
|
+
python_classpath=python_classpath,
|
|
465
|
+
strict=strict,
|
|
466
|
+
)
|
|
422
467
|
|
|
423
468
|
return python_classname, python_classpath, strict
|
|
424
469
|
|
|
425
470
|
|
|
471
|
+
def _resolve_persistent_message_class(
|
|
472
|
+
iris_classname: str,
|
|
473
|
+
) -> _PersistentMessageResolution:
|
|
474
|
+
cached = _IRIS_TO_MESSAGE_CLASS_CACHE.get(iris_classname)
|
|
475
|
+
if cached is not None:
|
|
476
|
+
return _PersistentMessageResolution(
|
|
477
|
+
_PersistentMessageResolutionState.RESOLVED,
|
|
478
|
+
message_class=cached,
|
|
479
|
+
)
|
|
480
|
+
|
|
481
|
+
python_classname, python_classpath, strict = _resolve_python_message_metadata(
|
|
482
|
+
iris_classname
|
|
483
|
+
)
|
|
484
|
+
if not python_classname:
|
|
485
|
+
return _PersistentMessageResolution(
|
|
486
|
+
_PersistentMessageResolutionState.UNMAPPED
|
|
487
|
+
)
|
|
488
|
+
|
|
489
|
+
try:
|
|
490
|
+
msg_cls = load_python_class(python_classname, python_classpath)
|
|
491
|
+
except (AttributeError, ModuleNotFoundError, PersistentMessageError) as exc:
|
|
492
|
+
if not strict:
|
|
493
|
+
return _PersistentMessageResolution(
|
|
494
|
+
_PersistentMessageResolutionState.UNMAPPED
|
|
495
|
+
)
|
|
496
|
+
error = PersistentMessageError(
|
|
497
|
+
f"IRIS class {iris_classname!r} is marked as a PersistentMessage for "
|
|
498
|
+
f"Python class {python_classname!r}, but that Python class could not "
|
|
499
|
+
"be imported. Ensure the message class is importable, or register it "
|
|
500
|
+
"through CLASSES so migration writes IOP_PYTHON_CLASSPATH."
|
|
501
|
+
)
|
|
502
|
+
error.__cause__ = exc
|
|
503
|
+
return _PersistentMessageResolution(
|
|
504
|
+
_PersistentMessageResolutionState.INVALID,
|
|
505
|
+
error=error,
|
|
506
|
+
)
|
|
507
|
+
|
|
508
|
+
if not is_persistent_message_class(msg_cls):
|
|
509
|
+
if not strict:
|
|
510
|
+
return _PersistentMessageResolution(
|
|
511
|
+
_PersistentMessageResolutionState.UNMAPPED
|
|
512
|
+
)
|
|
513
|
+
return _PersistentMessageResolution(
|
|
514
|
+
_PersistentMessageResolutionState.INVALID,
|
|
515
|
+
error=PersistentMessageError(
|
|
516
|
+
f"IRIS class {iris_classname!r} maps to {python_classname!r}, "
|
|
517
|
+
"but that class is not a PersistentMessage subclass."
|
|
518
|
+
),
|
|
519
|
+
)
|
|
520
|
+
|
|
521
|
+
_prepare_message_class(msg_cls, iris_classname, registered=False)
|
|
522
|
+
return _PersistentMessageResolution(
|
|
523
|
+
_PersistentMessageResolutionState.RESOLVED,
|
|
524
|
+
message_class=msg_cls,
|
|
525
|
+
)
|
|
526
|
+
|
|
527
|
+
|
|
426
528
|
def get_iris_class_parameter(
|
|
427
529
|
iris_classname: str,
|
|
428
530
|
parameter_name: str,
|
|
@@ -104,6 +104,9 @@ class MessageSerializer:
|
|
|
104
104
|
f"Failed to load class {serial.classname}: {str(e)}"
|
|
105
105
|
) from e
|
|
106
106
|
|
|
107
|
+
if not isinstance(msg_class, type):
|
|
108
|
+
raise SerializationError(f"Class {msg_class} must be a class")
|
|
109
|
+
|
|
107
110
|
if is_dataclass(msg_class) and issubclass(msg_class, BaseModel):
|
|
108
111
|
raise SerializationError(
|
|
109
112
|
f"Class '{msg_class.__name__}' combines @dataclass with PydanticMessage, which are incompatible. "
|
|
@@ -14,8 +14,6 @@ def dict_to_xml(data: dict[str, Any]) -> str:
|
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
def xml_to_json(xml_string: str) -> str:
|
|
17
|
-
"""Convert an XML production export to the JSON shape used by Production."""
|
|
18
|
-
|
|
19
17
|
def postprocessor(path, key, value):
|
|
20
18
|
return key, "" if value is None else value
|
|
21
19
|
|
|
@@ -44,7 +42,6 @@ def string_to_stream(iris, string: str, buffer=1000000):
|
|
|
44
42
|
|
|
45
43
|
|
|
46
44
|
def guess_path(module: str, path: str) -> str:
|
|
47
|
-
"""Determine the full file path for a module name under a base path."""
|
|
48
45
|
if not module:
|
|
49
46
|
raise ValueError("Module name cannot be empty")
|
|
50
47
|
|