iris-pex-embedded-python 3.3.1b1__tar.gz → 3.4.0__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.
Potentially problematic release.
This version of iris-pex-embedded-python might be problematic. Click here for more details.
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/PKG-INFO +4 -4
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/pyproject.toml +5 -3
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/grongier/pex/__init__.py +1 -1
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/iop/__init__.py +3 -2
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/iop/_common.py +50 -16
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/iop/_director.py +0 -2
- iris_pex_embedded_python-3.4.0/src/iop/_dispatch.py +101 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/iop/_log_manager.py +11 -17
- iris_pex_embedded_python-3.4.0/src/iop/_message.py +28 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/iop/_message_validator.py +12 -6
- iris_pex_embedded_python-3.4.0/src/iop/_serialization.py +163 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/iop/_utils.py +12 -4
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/iop/cls/IOP/Common.cls +7 -2
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/iop/cls/IOP/Utils.cls +48 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/iris_pex_embedded_python.egg-info/PKG-INFO +4 -4
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/iris_pex_embedded_python.egg-info/SOURCES.txt +0 -1
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/iris_pex_embedded_python.egg-info/requires.txt +1 -2
- iris_pex_embedded_python-3.3.1b1/src/iop/_dispatch.py +0 -219
- iris_pex_embedded_python-3.3.1b1/src/iop/_message.py +0 -6
- iris_pex_embedded_python-3.3.1b1/src/iop/_pickle_message.py +0 -6
- iris_pex_embedded_python-3.3.1b1/src/iop/_serialization.py +0 -219
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/LICENSE +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/README.md +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/setup.cfg +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/setup.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/grongier/__init__.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/grongier/cls/Grongier/PEX/BusinessOperation.cls +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/grongier/cls/Grongier/PEX/BusinessProcess.cls +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/grongier/cls/Grongier/PEX/BusinessService.cls +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/grongier/cls/Grongier/PEX/Common.cls +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/grongier/cls/Grongier/PEX/Director.cls +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/grongier/cls/Grongier/PEX/Duplex/Operation.cls +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/grongier/cls/Grongier/PEX/Duplex/Process.cls +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/grongier/cls/Grongier/PEX/Duplex/Service.cls +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/grongier/cls/Grongier/PEX/InboundAdapter.cls +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/grongier/cls/Grongier/PEX/Message.cls +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/grongier/cls/Grongier/PEX/OutboundAdapter.cls +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/grongier/cls/Grongier/PEX/PickleMessage.cls +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/grongier/cls/Grongier/PEX/PrivateSession/Duplex.cls +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/grongier/cls/Grongier/PEX/PrivateSession/Message/Ack.cls +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/grongier/cls/Grongier/PEX/PrivateSession/Message/Poll.cls +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/grongier/cls/Grongier/PEX/PrivateSession/Message/Start.cls +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/grongier/cls/Grongier/PEX/PrivateSession/Message/Stop.cls +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/grongier/cls/Grongier/PEX/Test.cls +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/grongier/cls/Grongier/PEX/Utils.cls +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/grongier/cls/Grongier/Service/WSGI.cls +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/grongier/pex/__main__.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/grongier/pex/_business_host.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/grongier/pex/_cli.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/grongier/pex/_common.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/grongier/pex/_director.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/grongier/pex/_utils.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/grongier/pex/wsgi/handlers.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/_BufferReader.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/_BufferWriter.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/_ConnectionInformation.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/_ConnectionParameters.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/_Constant.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/_DBList.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/_Device.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/_GatewayContext.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/_GatewayException.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/_GatewayUtility.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/_IRIS.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/_IRISConnection.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/_IRISEmbedded.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/_IRISGlobalNode.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/_IRISGlobalNodeView.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/_IRISIterator.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/_IRISList.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/_IRISNative.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/_IRISOREF.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/_IRISObject.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/_IRISReference.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/_InStream.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/_LegacyIterator.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/_ListItem.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/_ListReader.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/_ListWriter.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/_LogFileStream.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/_MessageHeader.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/_OutStream.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/_PrintStream.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/_PythonGateway.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/_SharedMemorySocket.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/__init__.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/__main__.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/dbapi/_Column.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/dbapi/_DBAPI.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/dbapi/_Descriptor.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/dbapi/_IRISStream.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/dbapi/_Message.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/dbapi/_Parameter.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/dbapi/_ParameterCollection.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/dbapi/_ResultSetRow.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/dbapi/_SQLType.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/dbapi/__init__.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/dbapi/preparser/_PreParser.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/dbapi/preparser/_Scanner.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/dbapi/preparser/_Token.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/dbapi/preparser/_TokenList.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/dbapi/preparser/__init__.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/pex/_BusinessHost.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/pex/_BusinessOperation.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/pex/_BusinessProcess.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/pex/_BusinessService.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/pex/_Common.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/pex/_Director.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/pex/_IRISBusinessOperation.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/pex/_IRISBusinessService.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/pex/_IRISInboundAdapter.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/pex/_IRISOutboundAdapter.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/pex/_InboundAdapter.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/pex/_Message.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/pex/_OutboundAdapter.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/intersystems_iris/pex/__init__.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/iop/__main__.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/iop/_async_request.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/iop/_business_host.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/iop/_business_operation.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/iop/_business_process.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/iop/_business_service.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/iop/_cli.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/iop/_decorators.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/iop/_inbound_adapter.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/iop/_outbound_adapter.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/iop/_private_session_duplex.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/iop/_private_session_process.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/iop/cls/IOP/BusinessOperation.cls +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/iop/cls/IOP/BusinessProcess.cls +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/iop/cls/IOP/BusinessService.cls +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/iop/cls/IOP/Director.cls +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/iop/cls/IOP/Duplex/Operation.cls +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/iop/cls/IOP/Duplex/Process.cls +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/iop/cls/IOP/Duplex/Service.cls +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/iop/cls/IOP/InboundAdapter.cls +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/iop/cls/IOP/Message/JSONSchema.cls +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/iop/cls/IOP/Message.cls +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/iop/cls/IOP/OutboundAdapter.cls +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/iop/cls/IOP/PickleMessage.cls +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/iop/cls/IOP/PrivateSession/Duplex.cls +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/iop/cls/IOP/PrivateSession/Message/Ack.cls +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/iop/cls/IOP/PrivateSession/Message/Poll.cls +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/iop/cls/IOP/PrivateSession/Message/Start.cls +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/iop/cls/IOP/PrivateSession/Message/Stop.cls +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/iop/cls/IOP/Service/WSGI.cls +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/iop/cls/IOP/Test.cls +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/iop/wsgi/handlers.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/iris_pex_embedded_python.egg-info/dependency_links.txt +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/iris_pex_embedded_python.egg-info/entry_points.txt +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/iris_pex_embedded_python.egg-info/top_level.txt +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/irisnative/_IRISNative.py +0 -0
- {iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/irisnative/__init__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: iris_pex_embedded_python
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.4.0
|
|
4
4
|
Summary: Iris Interoperability based on Embedded Python
|
|
5
5
|
Author-email: grongier <guillaume.rongier@intersystems.com>
|
|
6
6
|
License: MIT License
|
|
@@ -44,12 +44,12 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
44
44
|
Classifier: Topic :: Utilities
|
|
45
45
|
Description-Content-Type: text/markdown
|
|
46
46
|
License-File: LICENSE
|
|
47
|
-
Requires-Dist:
|
|
47
|
+
Requires-Dist: pydantic>=2.0.0
|
|
48
48
|
Requires-Dist: xmltodict>=0.12.0
|
|
49
49
|
Requires-Dist: iris-embedded-python-wrapper>=0.0.6
|
|
50
50
|
Requires-Dist: setuptools>=40.8.0
|
|
51
|
-
Requires-Dist: dc-schema>=0.0.8
|
|
52
51
|
Requires-Dist: jsonpath-ng>=1.7.0
|
|
52
|
+
Dynamic: license-file
|
|
53
53
|
|
|
54
54
|
# IoP (Interoperability On Python)
|
|
55
55
|
|
|
@@ -3,7 +3,7 @@ requires = ["setuptools", "wheel"]
|
|
|
3
3
|
|
|
4
4
|
[project]
|
|
5
5
|
name = "iris_pex_embedded_python"
|
|
6
|
-
version = "3.
|
|
6
|
+
version = "3.4.0"
|
|
7
7
|
description = "Iris Interoperability based on Embedded Python"
|
|
8
8
|
readme = "README.md"
|
|
9
9
|
authors = [
|
|
@@ -27,11 +27,10 @@ classifiers = [
|
|
|
27
27
|
]
|
|
28
28
|
|
|
29
29
|
dependencies = [
|
|
30
|
-
"
|
|
30
|
+
"pydantic>=2.0.0",
|
|
31
31
|
"xmltodict>=0.12.0",
|
|
32
32
|
"iris-embedded-python-wrapper>=0.0.6",
|
|
33
33
|
"setuptools>=40.8.0",
|
|
34
|
-
"dc-schema>=0.0.8",
|
|
35
34
|
"jsonpath-ng>=1.7.0"
|
|
36
35
|
]
|
|
37
36
|
|
|
@@ -52,3 +51,6 @@ exclude = ["tests*"]
|
|
|
52
51
|
|
|
53
52
|
[tool.setuptools.package-data]
|
|
54
53
|
"*" = ["*.cls"]
|
|
54
|
+
|
|
55
|
+
[tool.pytest.ini_options]
|
|
56
|
+
asyncio_default_fixture_loop_scope = "class"
|
{iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/grongier/pex/__init__.py
RENAMED
|
@@ -6,7 +6,7 @@ from iop._business_operation import _BusinessOperation
|
|
|
6
6
|
from iop._inbound_adapter import _InboundAdapter
|
|
7
7
|
from iop._outbound_adapter import _OutboundAdapter
|
|
8
8
|
from iop._message import _Message
|
|
9
|
-
from iop.
|
|
9
|
+
from iop._message import _PickleMessage
|
|
10
10
|
from iop._director import _Director
|
|
11
11
|
from iop._utils import _Utils
|
|
12
12
|
|
|
@@ -3,9 +3,8 @@ from iop._business_process import _BusinessProcess
|
|
|
3
3
|
from iop._business_service import _BusinessService
|
|
4
4
|
from iop._director import _Director
|
|
5
5
|
from iop._inbound_adapter import _InboundAdapter
|
|
6
|
-
from iop._message import _Message
|
|
6
|
+
from iop._message import _Message, _PickleMessage, _PydanticMessage, _PydanticPickleMessage
|
|
7
7
|
from iop._outbound_adapter import _OutboundAdapter
|
|
8
|
-
from iop._pickle_message import _PickleMessage
|
|
9
8
|
from iop._private_session_duplex import _PrivateSessionDuplex
|
|
10
9
|
from iop._private_session_process import _PrivateSessionProcess
|
|
11
10
|
from iop._utils import _Utils
|
|
@@ -21,4 +20,6 @@ class DuplexOperation(_PrivateSessionDuplex): pass
|
|
|
21
20
|
class DuplexProcess(_PrivateSessionProcess): pass
|
|
22
21
|
class Message(_Message): pass
|
|
23
22
|
class PickleMessage(_PickleMessage): pass
|
|
23
|
+
class PydanticMessage(_PydanticMessage): pass
|
|
24
|
+
class PydanticPickleMessage(_PydanticPickleMessage): pass
|
|
24
25
|
class Director(_Director): pass
|
|
@@ -17,7 +17,27 @@ class _Common(metaclass=abc.ABCMeta):
|
|
|
17
17
|
INFO_URL: ClassVar[str]
|
|
18
18
|
ICON_URL: ClassVar[str]
|
|
19
19
|
iris_handle: Any = None
|
|
20
|
-
|
|
20
|
+
_log_to_console: bool = False
|
|
21
|
+
_logger: logging.Logger = None
|
|
22
|
+
|
|
23
|
+
@property
|
|
24
|
+
def logger(self) -> logging.Logger:
|
|
25
|
+
if self._logger is None:
|
|
26
|
+
self._logger = LogManager.get_logger(self.__class__.__name__,self.log_to_console)
|
|
27
|
+
return self._logger
|
|
28
|
+
|
|
29
|
+
@logger.setter
|
|
30
|
+
def logger(self, value: logging.Logger) -> None:
|
|
31
|
+
self._logger = value
|
|
32
|
+
|
|
33
|
+
@property
|
|
34
|
+
def log_to_console(self) -> bool:
|
|
35
|
+
return self._log_to_console
|
|
36
|
+
|
|
37
|
+
@log_to_console.setter
|
|
38
|
+
def log_to_console(self, value: bool) -> None:
|
|
39
|
+
self._log_to_console = value
|
|
40
|
+
self.logger = LogManager.get_logger(self.__class__.__name__,value)
|
|
21
41
|
|
|
22
42
|
# Lifecycle methods
|
|
23
43
|
def on_init(self) -> None:
|
|
@@ -128,7 +148,10 @@ class _Common(metaclass=abc.ABCMeta):
|
|
|
128
148
|
if not member[0].startswith('_'):
|
|
129
149
|
# remove other methods and functions
|
|
130
150
|
if not inspect.ismethod(member[1]) and not inspect.isfunction(member[1]) and not inspect.isclass(member[1]):
|
|
131
|
-
if member[0] not in ('INFO_URL','ICON_URL','PERSISTENT_PROPERTY_LIST'
|
|
151
|
+
if member[0] not in ('INFO_URL','ICON_URL','PERSISTENT_PROPERTY_LIST'
|
|
152
|
+
,'log_to_console','logger','iris_handle'
|
|
153
|
+
,'DISPATCH','adapter','Adapter','buffer'
|
|
154
|
+
,'BusinessHost','business_host','business_host_python'):
|
|
132
155
|
name = member[0]
|
|
133
156
|
req = 0
|
|
134
157
|
cat = "Additional"
|
|
@@ -172,7 +195,7 @@ class _Common(metaclass=abc.ABCMeta):
|
|
|
172
195
|
except:
|
|
173
196
|
pass
|
|
174
197
|
return ret
|
|
175
|
-
|
|
198
|
+
|
|
176
199
|
# Logging methods
|
|
177
200
|
def _log(self) -> Tuple[str, Optional[str]]:
|
|
178
201
|
"""Get class and method name for logging.
|
|
@@ -189,15 +212,27 @@ class _Common(metaclass=abc.ABCMeta):
|
|
|
189
212
|
pass
|
|
190
213
|
return current_class, current_method
|
|
191
214
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
"""Get a logger instance for this component.
|
|
215
|
+
def _logging(self, message: str, level: int, to_console: Optional[bool] = None) -> None:
|
|
216
|
+
"""Write log entry.
|
|
195
217
|
|
|
196
|
-
|
|
197
|
-
|
|
218
|
+
Args:
|
|
219
|
+
message: Message to log
|
|
220
|
+
level: Log level
|
|
221
|
+
to_console: If True, log to console instead of IRIS
|
|
198
222
|
"""
|
|
199
|
-
|
|
200
|
-
|
|
223
|
+
current_class, current_method = self._log()
|
|
224
|
+
if to_console is None:
|
|
225
|
+
to_console = self.log_to_console
|
|
226
|
+
if level == logging.DEBUG:
|
|
227
|
+
self.logger.debug(message, extra={'to_console': to_console, 'class_name': current_class, 'method_name': current_method})
|
|
228
|
+
elif level == logging.INFO:
|
|
229
|
+
self.logger.info(message, extra={'to_console': to_console, 'class_name': current_class, 'method_name': current_method})
|
|
230
|
+
elif level == logging.CRITICAL:
|
|
231
|
+
self.logger.critical(message, extra={'to_console': to_console, 'class_name': current_class, 'method_name': current_method})
|
|
232
|
+
elif level == logging.WARNING:
|
|
233
|
+
self.logger.warning(message, extra={'to_console': to_console, 'class_name': current_class, 'method_name': current_method})
|
|
234
|
+
elif level == logging.ERROR:
|
|
235
|
+
self.logger.error(message, extra={'to_console': to_console, 'class_name': current_class, 'method_name': current_method})
|
|
201
236
|
|
|
202
237
|
def trace(self, message: str, to_console: Optional[bool] = None) -> None:
|
|
203
238
|
"""Write trace log entry.
|
|
@@ -206,8 +241,7 @@ class _Common(metaclass=abc.ABCMeta):
|
|
|
206
241
|
message: Message to log
|
|
207
242
|
to_console: If True, log to console instead of IRIS
|
|
208
243
|
"""
|
|
209
|
-
self.
|
|
210
|
-
|
|
244
|
+
self._logging(message, logging.DEBUG, to_console)
|
|
211
245
|
|
|
212
246
|
def log_info(self, message: str, to_console: Optional[bool] = None) -> None:
|
|
213
247
|
"""Write info log entry.
|
|
@@ -216,7 +250,7 @@ class _Common(metaclass=abc.ABCMeta):
|
|
|
216
250
|
message: Message to log
|
|
217
251
|
to_console: If True, log to console instead of IRIS
|
|
218
252
|
"""
|
|
219
|
-
self.
|
|
253
|
+
self._logging(message, logging.INFO, to_console)
|
|
220
254
|
|
|
221
255
|
def log_alert(self, message: str, to_console: Optional[bool] = None) -> None:
|
|
222
256
|
"""Write alert log entry.
|
|
@@ -225,7 +259,7 @@ class _Common(metaclass=abc.ABCMeta):
|
|
|
225
259
|
message: Message to log
|
|
226
260
|
to_console: If True, log to console instead of IRIS
|
|
227
261
|
"""
|
|
228
|
-
self.
|
|
262
|
+
self._logging(message, logging.CRITICAL, to_console)
|
|
229
263
|
|
|
230
264
|
def log_warning(self, message: str, to_console: Optional[bool] = None) -> None:
|
|
231
265
|
"""Write warning log entry.
|
|
@@ -234,7 +268,7 @@ class _Common(metaclass=abc.ABCMeta):
|
|
|
234
268
|
message: Message to log
|
|
235
269
|
to_console: If True, log to console instead of IRIS
|
|
236
270
|
"""
|
|
237
|
-
self.
|
|
271
|
+
self._logging(message, logging.WARNING, to_console)
|
|
238
272
|
|
|
239
273
|
def log_error(self, message: str, to_console: Optional[bool] = None) -> None:
|
|
240
274
|
"""Write error log entry.
|
|
@@ -243,7 +277,7 @@ class _Common(metaclass=abc.ABCMeta):
|
|
|
243
277
|
message: Message to log
|
|
244
278
|
to_console: If True, log to console instead of IRIS
|
|
245
279
|
"""
|
|
246
|
-
self.
|
|
280
|
+
self._logging(message, logging.ERROR, to_console)
|
|
247
281
|
|
|
248
282
|
def log_assert(self, message: str) -> None:
|
|
249
283
|
"""Write a log entry of type "assert". Log entries can be viewed in the management portal.
|
|
@@ -6,7 +6,6 @@ import intersystems_iris.dbapi._DBAPI as irisdbapi
|
|
|
6
6
|
import signal
|
|
7
7
|
from dataclasses import dataclass
|
|
8
8
|
|
|
9
|
-
from iop._business_host import _BusinessHost
|
|
10
9
|
from iop._dispatch import dispatch_deserializer, dispatch_serializer
|
|
11
10
|
from iop._utils import _Utils
|
|
12
11
|
|
|
@@ -278,7 +277,6 @@ class _Director():
|
|
|
278
277
|
else:
|
|
279
278
|
message.json = _Utils.string_to_stream("{}")
|
|
280
279
|
# serialize the message
|
|
281
|
-
business_host = _BusinessHost()
|
|
282
280
|
serial_message = dispatch_serializer(message)
|
|
283
281
|
response = iris.cls('IOP.Utils').dispatchTestComponent(target,serial_message)
|
|
284
282
|
try:
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
from inspect import signature
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
from iop._serialization import serialize_message, serialize_pickle_message, deserialize_message, deserialize_pickle_message
|
|
5
|
+
from iop._message_validator import is_message_instance, is_pickle_message_instance, is_iris_object_instance
|
|
6
|
+
|
|
7
|
+
def dispatch_serializer(message: Any) -> Any:
|
|
8
|
+
"""Serializes the message based on its type.
|
|
9
|
+
|
|
10
|
+
Args:
|
|
11
|
+
message: The message to serialize
|
|
12
|
+
|
|
13
|
+
Returns:
|
|
14
|
+
The serialized message
|
|
15
|
+
|
|
16
|
+
Raises:
|
|
17
|
+
TypeError: If message is invalid type
|
|
18
|
+
"""
|
|
19
|
+
if message is not None:
|
|
20
|
+
if is_message_instance(message):
|
|
21
|
+
return serialize_message(message)
|
|
22
|
+
elif is_pickle_message_instance(message):
|
|
23
|
+
return serialize_pickle_message(message)
|
|
24
|
+
elif is_iris_object_instance(message):
|
|
25
|
+
return message
|
|
26
|
+
|
|
27
|
+
if message == "" or message is None:
|
|
28
|
+
return message
|
|
29
|
+
|
|
30
|
+
raise TypeError("The message must be an instance of a class that is a subclass of Message or IRISObject %Persistent class.")
|
|
31
|
+
|
|
32
|
+
def dispatch_deserializer(serial: Any) -> Any:
|
|
33
|
+
"""Deserializes the message based on its type.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
serial: The serialized message
|
|
37
|
+
|
|
38
|
+
Returns:
|
|
39
|
+
The deserialized message
|
|
40
|
+
"""
|
|
41
|
+
if (
|
|
42
|
+
serial is not None
|
|
43
|
+
and type(serial).__module__.startswith('iris')
|
|
44
|
+
and (
|
|
45
|
+
serial._IsA("IOP.Message")
|
|
46
|
+
or serial._IsA("Grongier.PEX.Message")
|
|
47
|
+
)
|
|
48
|
+
):
|
|
49
|
+
return deserialize_message(serial)
|
|
50
|
+
elif (
|
|
51
|
+
serial is not None
|
|
52
|
+
and type(serial).__module__.startswith('iris')
|
|
53
|
+
and (
|
|
54
|
+
serial._IsA("IOP.PickleMessage")
|
|
55
|
+
or serial._IsA("Grongier.PEX.PickleMessage")
|
|
56
|
+
)
|
|
57
|
+
):
|
|
58
|
+
return deserialize_pickle_message(serial)
|
|
59
|
+
else:
|
|
60
|
+
return serial
|
|
61
|
+
|
|
62
|
+
def dispach_message(host, request: Any) -> Any:
|
|
63
|
+
"""Dispatches the message to the appropriate method.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
request: The request object
|
|
67
|
+
|
|
68
|
+
Returns:
|
|
69
|
+
The response object
|
|
70
|
+
"""
|
|
71
|
+
call = 'on_message'
|
|
72
|
+
|
|
73
|
+
module = request.__class__.__module__
|
|
74
|
+
classname = request.__class__.__name__
|
|
75
|
+
|
|
76
|
+
for msg, method in host.DISPATCH:
|
|
77
|
+
if msg == module + "." + classname:
|
|
78
|
+
call = method
|
|
79
|
+
|
|
80
|
+
return getattr(host, call)(request)
|
|
81
|
+
|
|
82
|
+
def create_dispatch(host) -> None:
|
|
83
|
+
"""Creates a list of tuples, where each tuple contains the name of a class and the name of a method
|
|
84
|
+
that takes an instance of that class as its only argument.
|
|
85
|
+
"""
|
|
86
|
+
if len(host.DISPATCH) == 0:
|
|
87
|
+
method_list = [func for func in dir(host) if callable(getattr(host, func)) and not func.startswith("_")]
|
|
88
|
+
for method in method_list:
|
|
89
|
+
try:
|
|
90
|
+
param = signature(getattr(host, method)).parameters
|
|
91
|
+
except ValueError as e:
|
|
92
|
+
param = ''
|
|
93
|
+
if (len(param) == 1):
|
|
94
|
+
annotation = str(param[list(param)[0]].annotation)
|
|
95
|
+
i = annotation.find("'")
|
|
96
|
+
j = annotation.rfind("'")
|
|
97
|
+
if j == -1:
|
|
98
|
+
j = None
|
|
99
|
+
classname = annotation[i+1:j]
|
|
100
|
+
host.DISPATCH.append((classname, method))
|
|
101
|
+
return
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import traceback
|
|
1
2
|
import iris
|
|
2
3
|
import logging
|
|
3
4
|
from typing import Optional, Tuple
|
|
@@ -6,7 +7,7 @@ class LogManager:
|
|
|
6
7
|
"""Manages logging integration between Python's logging module and IRIS."""
|
|
7
8
|
|
|
8
9
|
@staticmethod
|
|
9
|
-
def get_logger(class_name: str,
|
|
10
|
+
def get_logger(class_name: str, to_console: bool = False) -> logging.Logger:
|
|
10
11
|
"""Get a logger instance configured for IRIS integration.
|
|
11
12
|
|
|
12
13
|
Args:
|
|
@@ -17,11 +18,11 @@ class LogManager:
|
|
|
17
18
|
Returns:
|
|
18
19
|
Logger instance configured for IRIS integration
|
|
19
20
|
"""
|
|
20
|
-
logger = logging.
|
|
21
|
+
logger = logging.Logger(f"{class_name}")
|
|
21
22
|
|
|
22
23
|
# Only add handler if none exists
|
|
23
24
|
if not logger.handlers:
|
|
24
|
-
handler = IRISLogHandler(
|
|
25
|
+
handler = IRISLogHandler(to_console=to_console)
|
|
25
26
|
formatter = logging.Formatter('%(message)s')
|
|
26
27
|
handler.setFormatter(formatter)
|
|
27
28
|
logger.addHandler(handler)
|
|
@@ -33,17 +34,9 @@ class LogManager:
|
|
|
33
34
|
class IRISLogHandler(logging.Handler):
|
|
34
35
|
"""Custom logging handler that routes Python logs to IRIS logging system."""
|
|
35
36
|
|
|
36
|
-
def __init__(self,
|
|
37
|
-
"""Initialize the
|
|
38
|
-
|
|
39
|
-
Args:
|
|
40
|
-
class_name: Name of the class logging the message
|
|
41
|
-
method_name: Optional name of the method logging the message
|
|
42
|
-
console: If True, log to the console instead of IRIS
|
|
43
|
-
"""
|
|
37
|
+
def __init__(self, to_console: bool = False):
|
|
38
|
+
"""Initialize the IRIS logging handler."""
|
|
44
39
|
super().__init__()
|
|
45
|
-
self.class_name = class_name
|
|
46
|
-
self.method_name = method_name
|
|
47
40
|
self.to_console = to_console
|
|
48
41
|
|
|
49
42
|
# Map Python logging levels to IRIS logging methods
|
|
@@ -80,10 +73,11 @@ class IRISLogHandler(logging.Handler):
|
|
|
80
73
|
Args:
|
|
81
74
|
record: The logging record to emit
|
|
82
75
|
"""
|
|
83
|
-
|
|
84
|
-
|
|
76
|
+
class_name = record.class_name if hasattr(record, "class_name") else record.name
|
|
77
|
+
method_name = record.method_name if hasattr(record, "method_name") else record.funcName
|
|
85
78
|
if self.to_console or (hasattr(record, "to_console") and record.to_console):
|
|
86
79
|
iris.cls("%SYS.System").WriteToConsoleLog(self.format(record),
|
|
87
|
-
0,self.level_map_console.get(record.levelno, 0),
|
|
80
|
+
0,self.level_map_console.get(record.levelno, 0),class_name+"."+method_name)
|
|
88
81
|
else:
|
|
89
|
-
log_func
|
|
82
|
+
log_func = self.level_map.get(record.levelno, iris.cls("Ens.Util.Log").LogInfo)
|
|
83
|
+
log_func(class_name, method_name, self.format(record))
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
from pydantic import BaseModel
|
|
3
|
+
|
|
4
|
+
class _Message:
|
|
5
|
+
""" The abstract class that is the superclass for persistent messages sent from one component to another.
|
|
6
|
+
This class has no properties or methods. Users subclass Message and add properties.
|
|
7
|
+
The IOP framework provides the persistence to objects derived from the Message class.
|
|
8
|
+
"""
|
|
9
|
+
pass
|
|
10
|
+
|
|
11
|
+
class _PickleMessage:
|
|
12
|
+
""" The abstract class that is the superclass for persistent messages sent from one component to another.
|
|
13
|
+
This class has no properties or methods. Users subclass Message and add properties.
|
|
14
|
+
The IOP framework provides the persistence to objects derived from the Message class.
|
|
15
|
+
"""
|
|
16
|
+
pass
|
|
17
|
+
|
|
18
|
+
class _PydanticMessage(BaseModel):
|
|
19
|
+
"""Base class for Pydantic-based messages that can be serialized to IRIS."""
|
|
20
|
+
|
|
21
|
+
def __init__(self, **data: Any):
|
|
22
|
+
super().__init__(**data)
|
|
23
|
+
|
|
24
|
+
class _PydanticPickleMessage(BaseModel):
|
|
25
|
+
"""Base class for Pydantic-based messages that can be serialized to IRIS."""
|
|
26
|
+
|
|
27
|
+
def __init__(self, **data: Any):
|
|
28
|
+
super().__init__(**data)
|
{iris_pex_embedded_python-3.3.1b1 → iris_pex_embedded_python-3.4.0}/src/iop/_message_validator.py
RENAMED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import dataclasses
|
|
2
2
|
from typing import Any, Type
|
|
3
|
+
from iop._message import _Message, _PickleMessage, _PydanticPickleMessage, BaseModel
|
|
3
4
|
|
|
4
5
|
|
|
5
6
|
def is_message_instance(obj: Any) -> bool:
|
|
6
7
|
"""Check if object is a valid Message instance."""
|
|
8
|
+
if isinstance(obj, BaseModel):
|
|
9
|
+
return True
|
|
7
10
|
if is_message_class(type(obj)):
|
|
8
11
|
if not dataclasses.is_dataclass(obj):
|
|
9
12
|
raise TypeError(f"{type(obj).__module__}.{type(obj).__qualname__} must be a dataclass")
|
|
@@ -13,6 +16,8 @@ def is_message_instance(obj: Any) -> bool:
|
|
|
13
16
|
|
|
14
17
|
def is_pickle_message_instance(obj: Any) -> bool:
|
|
15
18
|
"""Check if object is a PickleMessage instance."""
|
|
19
|
+
if isinstance(obj, _PydanticPickleMessage):
|
|
20
|
+
return True
|
|
16
21
|
if is_pickle_message_class(type(obj)):
|
|
17
22
|
return True
|
|
18
23
|
return False
|
|
@@ -27,15 +32,16 @@ def is_iris_object_instance(obj: Any) -> bool:
|
|
|
27
32
|
|
|
28
33
|
def is_message_class(klass: Type) -> bool:
|
|
29
34
|
"""Check if class is a Message type."""
|
|
30
|
-
|
|
31
|
-
if name in ("iop.Message", "grongier.pex.Message"):
|
|
35
|
+
if issubclass(klass, _Message):
|
|
32
36
|
return True
|
|
33
|
-
return
|
|
37
|
+
return False
|
|
38
|
+
|
|
34
39
|
|
|
35
40
|
|
|
36
41
|
def is_pickle_message_class(klass: Type) -> bool:
|
|
37
42
|
"""Check if class is a PickleMessage type."""
|
|
38
|
-
|
|
39
|
-
|
|
43
|
+
if issubclass(klass, _PickleMessage):
|
|
44
|
+
return True
|
|
45
|
+
if issubclass(klass, _PydanticPickleMessage):
|
|
40
46
|
return True
|
|
41
|
-
return
|
|
47
|
+
return False
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
import codecs
|
|
3
|
+
import importlib
|
|
4
|
+
import inspect
|
|
5
|
+
import pickle
|
|
6
|
+
import json
|
|
7
|
+
from dataclasses import asdict, is_dataclass
|
|
8
|
+
from typing import Any, Dict, Type
|
|
9
|
+
|
|
10
|
+
import iris
|
|
11
|
+
from pydantic import BaseModel, TypeAdapter, ValidationError
|
|
12
|
+
|
|
13
|
+
from iop._message import _PydanticPickleMessage
|
|
14
|
+
from iop._utils import _Utils
|
|
15
|
+
|
|
16
|
+
class SerializationError(Exception):
|
|
17
|
+
"""Exception raised for serialization errors."""
|
|
18
|
+
pass
|
|
19
|
+
|
|
20
|
+
class TempPydanticModel(BaseModel):
|
|
21
|
+
model_config = {
|
|
22
|
+
'arbitrary_types_allowed' : True,
|
|
23
|
+
'extra' : 'allow'
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
class MessageSerializer:
|
|
27
|
+
"""Handles message serialization and deserialization."""
|
|
28
|
+
|
|
29
|
+
@staticmethod
|
|
30
|
+
def _convert_to_json_safe(obj: Any) -> Any:
|
|
31
|
+
"""Convert objects to JSON-safe format."""
|
|
32
|
+
if isinstance(obj, BaseModel):
|
|
33
|
+
return obj.model_dump_json()
|
|
34
|
+
elif is_dataclass(obj):
|
|
35
|
+
return TempPydanticModel.model_validate(dataclass_to_dict(obj)).model_dump_json()
|
|
36
|
+
else:
|
|
37
|
+
raise SerializationError(f"Object {obj} must be a Pydantic model or dataclass")
|
|
38
|
+
|
|
39
|
+
@staticmethod
|
|
40
|
+
def serialize(message: Any, use_pickle: bool = False) -> iris.cls:
|
|
41
|
+
"""Serializes a message to IRIS format."""
|
|
42
|
+
if isinstance(message, _PydanticPickleMessage) or use_pickle:
|
|
43
|
+
return MessageSerializer._serialize_pickle(message)
|
|
44
|
+
return MessageSerializer._serialize_json(message)
|
|
45
|
+
|
|
46
|
+
@staticmethod
|
|
47
|
+
def _serialize_json(message: Any) -> iris.cls:
|
|
48
|
+
json_string = MessageSerializer._convert_to_json_safe(message)
|
|
49
|
+
|
|
50
|
+
msg = iris.cls('IOP.Message')._New()
|
|
51
|
+
msg.classname = f"{message.__class__.__module__}.{message.__class__.__name__}"
|
|
52
|
+
|
|
53
|
+
if hasattr(msg, 'buffer') and len(json_string) > msg.buffer:
|
|
54
|
+
msg.json = _Utils.string_to_stream(json_string, msg.buffer)
|
|
55
|
+
else:
|
|
56
|
+
msg.json = json_string
|
|
57
|
+
return msg
|
|
58
|
+
|
|
59
|
+
@staticmethod
|
|
60
|
+
def deserialize(serial: iris.cls, use_pickle: bool = False) -> Any:
|
|
61
|
+
if use_pickle:
|
|
62
|
+
return MessageSerializer._deserialize_pickle(serial)
|
|
63
|
+
return MessageSerializer._deserialize_json(serial)
|
|
64
|
+
|
|
65
|
+
@staticmethod
|
|
66
|
+
def _deserialize_json(serial: iris.cls) -> Any:
|
|
67
|
+
if not serial.classname:
|
|
68
|
+
raise SerializationError("JSON message malformed, must include classname")
|
|
69
|
+
|
|
70
|
+
try:
|
|
71
|
+
module_name, class_name = MessageSerializer._parse_classname(serial.classname)
|
|
72
|
+
module = importlib.import_module(module_name)
|
|
73
|
+
msg_class = getattr(module, class_name)
|
|
74
|
+
except Exception as e:
|
|
75
|
+
raise SerializationError(f"Failed to load class {serial.classname}: {str(e)}")
|
|
76
|
+
|
|
77
|
+
json_string = (_Utils.stream_to_string(serial.json)
|
|
78
|
+
if serial.type == 'Stream' else serial.json)
|
|
79
|
+
|
|
80
|
+
try:
|
|
81
|
+
if issubclass(msg_class, BaseModel):
|
|
82
|
+
return msg_class.model_validate_json(json_string)
|
|
83
|
+
elif is_dataclass(msg_class):
|
|
84
|
+
return dataclass_from_dict(msg_class, json.loads(json_string))
|
|
85
|
+
else:
|
|
86
|
+
raise SerializationError(f"Class {msg_class} must be a Pydantic model or dataclass")
|
|
87
|
+
except Exception as e:
|
|
88
|
+
raise SerializationError(f"Failed to deserialize JSON: {str(e)}")
|
|
89
|
+
|
|
90
|
+
@staticmethod
|
|
91
|
+
def _serialize_pickle(message: Any) -> iris.cls:
|
|
92
|
+
pickle_string = codecs.encode(pickle.dumps(message), "base64").decode()
|
|
93
|
+
msg = iris.cls('IOP.PickleMessage')._New()
|
|
94
|
+
msg.classname = f"{message.__class__.__module__}.{message.__class__.__name__}"
|
|
95
|
+
msg.jstr = _Utils.string_to_stream(pickle_string)
|
|
96
|
+
return msg
|
|
97
|
+
|
|
98
|
+
@staticmethod
|
|
99
|
+
def _deserialize_pickle(serial: iris.cls) -> Any:
|
|
100
|
+
string = _Utils.stream_to_string(serial.jstr)
|
|
101
|
+
return pickle.loads(codecs.decode(string.encode(), "base64"))
|
|
102
|
+
|
|
103
|
+
@staticmethod
|
|
104
|
+
def _parse_classname(classname: str) -> tuple[str, str]:
|
|
105
|
+
j = classname.rindex(".")
|
|
106
|
+
if j <= 0:
|
|
107
|
+
raise SerializationError(f"Classname must include a module: {classname}")
|
|
108
|
+
return classname[:j], classname[j+1:]
|
|
109
|
+
|
|
110
|
+
def dataclass_from_dict(klass: Type, dikt: Dict) -> Any:
|
|
111
|
+
"""Converts a dictionary to a dataclass instance.
|
|
112
|
+
Handles non attended fields and nested dataclasses."""
|
|
113
|
+
|
|
114
|
+
def process_field(value: Any, field_type: Type) -> Any:
|
|
115
|
+
if value is None:
|
|
116
|
+
return None
|
|
117
|
+
if is_dataclass(field_type):
|
|
118
|
+
return dataclass_from_dict(field_type, value)
|
|
119
|
+
if field_type != inspect.Parameter.empty:
|
|
120
|
+
try:
|
|
121
|
+
return TypeAdapter(field_type).validate_python(value)
|
|
122
|
+
except ValidationError:
|
|
123
|
+
return value
|
|
124
|
+
return value
|
|
125
|
+
|
|
126
|
+
# Get field definitions from class signature
|
|
127
|
+
fields = inspect.signature(klass).parameters
|
|
128
|
+
field_dict = {}
|
|
129
|
+
|
|
130
|
+
# Process each field
|
|
131
|
+
for field_name, field_info in fields.items():
|
|
132
|
+
if field_name not in dikt:
|
|
133
|
+
if field_info.default != field_info.empty:
|
|
134
|
+
field_dict[field_name] = field_info.default
|
|
135
|
+
continue
|
|
136
|
+
|
|
137
|
+
field_dict[field_name] = process_field(dikt[field_name], field_info.annotation)
|
|
138
|
+
|
|
139
|
+
# Create instance
|
|
140
|
+
instance = klass(**field_dict)
|
|
141
|
+
|
|
142
|
+
# Add any extra fields not in the dataclass definition
|
|
143
|
+
for key, value in dikt.items():
|
|
144
|
+
if key not in field_dict:
|
|
145
|
+
setattr(instance, key, value)
|
|
146
|
+
|
|
147
|
+
return instance
|
|
148
|
+
|
|
149
|
+
def dataclass_to_dict(instance: Any) -> Dict:
|
|
150
|
+
"""Converts a class instance to a dictionary.
|
|
151
|
+
Handles non attended fields."""
|
|
152
|
+
dikt = asdict(instance)
|
|
153
|
+
# assign any extra fields
|
|
154
|
+
for k, v in vars(instance).items():
|
|
155
|
+
if k not in dikt:
|
|
156
|
+
dikt[k] = v
|
|
157
|
+
return dikt
|
|
158
|
+
|
|
159
|
+
# Maintain backwards compatibility
|
|
160
|
+
serialize_pickle_message = lambda msg: MessageSerializer.serialize(msg, use_pickle=True)
|
|
161
|
+
serialize_message = lambda msg: MessageSerializer.serialize(msg, use_pickle=False)
|
|
162
|
+
deserialize_pickle_message = lambda serial: MessageSerializer.deserialize(serial, use_pickle=True)
|
|
163
|
+
deserialize_message = lambda serial: MessageSerializer.deserialize(serial, use_pickle=False)
|
|
@@ -6,8 +6,10 @@ import inspect
|
|
|
6
6
|
import xmltodict
|
|
7
7
|
import pkg_resources
|
|
8
8
|
import importlib
|
|
9
|
+
import importlib.util
|
|
9
10
|
import json
|
|
10
|
-
from
|
|
11
|
+
from iop._message import _Message, _PydanticMessage
|
|
12
|
+
from pydantic import TypeAdapter
|
|
11
13
|
|
|
12
14
|
class _Utils():
|
|
13
15
|
@staticmethod
|
|
@@ -42,7 +44,13 @@ class _Utils():
|
|
|
42
44
|
|
|
43
45
|
:param cls: The class to register
|
|
44
46
|
"""
|
|
45
|
-
|
|
47
|
+
if issubclass(cls,_PydanticMessage):
|
|
48
|
+
schema = cls.model_json_schema()
|
|
49
|
+
elif issubclass(cls,_Message):
|
|
50
|
+
type_adapter = TypeAdapter(cls)
|
|
51
|
+
schema = type_adapter.json_schema()
|
|
52
|
+
else:
|
|
53
|
+
raise ValueError("The class must be a subclass of _Message or _PydanticMessage")
|
|
46
54
|
schema_name = cls.__module__ + '.' + cls.__name__
|
|
47
55
|
schema_str = json.dumps(schema)
|
|
48
56
|
categories = schema_name
|
|
@@ -234,7 +242,7 @@ class _Utils():
|
|
|
234
242
|
settings = _Utils.import_module_from_path('settings',filename)
|
|
235
243
|
else:
|
|
236
244
|
# import settings from the settings module
|
|
237
|
-
import settings
|
|
245
|
+
import settings # type: ignore
|
|
238
246
|
# get the path of the settings file
|
|
239
247
|
path = os.path.dirname(inspect.getfile(settings))
|
|
240
248
|
try:
|
|
@@ -254,7 +262,7 @@ class _Utils():
|
|
|
254
262
|
except AttributeError:
|
|
255
263
|
print("No schemas to register")
|
|
256
264
|
try:
|
|
257
|
-
sys.path.remove(path)
|
|
265
|
+
sys.path.remove(os.path.normpath(path))
|
|
258
266
|
except ValueError:
|
|
259
267
|
pass
|
|
260
268
|
|