iris-pex-embedded-python 3.7.2b2__tar.gz → 4.0.0b2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. {iris_pex_embedded_python-3.7.2b2/src/iris_pex_embedded_python.egg-info → iris_pex_embedded_python-4.0.0b2}/PKG-INFO +3 -1
  2. {iris_pex_embedded_python-3.7.2b2 → iris_pex_embedded_python-4.0.0b2}/pyproject.toml +13 -2
  3. iris_pex_embedded_python-4.0.0b2/src/iop/__init__.py +138 -0
  4. iris_pex_embedded_python-4.0.0b2/src/iop/__main__.py +5 -0
  5. iris_pex_embedded_python-4.0.0b2/src/iop/cli/__init__.py +1 -0
  6. iris_pex_embedded_python-4.0.0b2/src/iop/cli/formatting.py +45 -0
  7. iris_pex_embedded_python-3.7.2b2/src/iop/_cli.py → iris_pex_embedded_python-4.0.0b2/src/iop/cli/main.py +80 -216
  8. iris_pex_embedded_python-4.0.0b2/src/iop/cli/parser.py +128 -0
  9. iris_pex_embedded_python-4.0.0b2/src/iop/cli/types.py +57 -0
  10. {iris_pex_embedded_python-3.7.2b2 → iris_pex_embedded_python-4.0.0b2}/src/iop/cls/IOP/Service/Remote/Rest/v1.cls +151 -5
  11. {iris_pex_embedded_python-3.7.2b2 → iris_pex_embedded_python-4.0.0b2}/src/iop/cls/IOP/Utils.cls +392 -7
  12. {iris_pex_embedded_python-3.7.2b2 → iris_pex_embedded_python-4.0.0b2}/src/iop/cls/IOP/Wrapper.cls +1 -1
  13. iris_pex_embedded_python-4.0.0b2/src/iop/components/__init__.py +16 -0
  14. iris_pex_embedded_python-3.7.2b2/src/iop/_async_request.py → iris_pex_embedded_python-4.0.0b2/src/iop/components/async_request.py +7 -7
  15. iris_pex_embedded_python-4.0.0b2/src/iop/components/business_host.py +319 -0
  16. iris_pex_embedded_python-3.7.2b2/src/iop/_business_operation.py → iris_pex_embedded_python-4.0.0b2/src/iop/components/business_operation.py +30 -39
  17. iris_pex_embedded_python-3.7.2b2/src/iop/_business_process.py → iris_pex_embedded_python-4.0.0b2/src/iop/components/business_process.py +28 -71
  18. iris_pex_embedded_python-3.7.2b2/src/iop/_business_service.py → iris_pex_embedded_python-4.0.0b2/src/iop/components/business_service.py +61 -44
  19. iris_pex_embedded_python-3.7.2b2/src/iop/_common.py → iris_pex_embedded_python-4.0.0b2/src/iop/components/common.py +71 -151
  20. iris_pex_embedded_python-3.7.2b2/src/iop/_debugpy.py → iris_pex_embedded_python-4.0.0b2/src/iop/components/debugpy.py +11 -11
  21. iris_pex_embedded_python-3.7.2b2/src/iop/_generator_request.py → iris_pex_embedded_python-4.0.0b2/src/iop/components/generator_request.py +4 -4
  22. iris_pex_embedded_python-3.7.2b2/src/iop/_inbound_adapter.py → iris_pex_embedded_python-4.0.0b2/src/iop/components/inbound_adapter.py +10 -18
  23. iris_pex_embedded_python-3.7.2b2/src/iop/_log_manager.py → iris_pex_embedded_python-4.0.0b2/src/iop/components/log_manager.py +1 -1
  24. iris_pex_embedded_python-3.7.2b2/src/iop/_outbound_adapter.py → iris_pex_embedded_python-4.0.0b2/src/iop/components/outbound_adapter.py +1 -1
  25. iris_pex_embedded_python-4.0.0b2/src/iop/components/polling_business_service.py +28 -0
  26. iris_pex_embedded_python-3.7.2b2/src/iop/_private_session_duplex.py → iris_pex_embedded_python-4.0.0b2/src/iop/components/private_session_duplex.py +7 -9
  27. iris_pex_embedded_python-3.7.2b2/src/iop/_private_session_process.py → iris_pex_embedded_python-4.0.0b2/src/iop/components/private_session_process.py +2 -2
  28. iris_pex_embedded_python-3.7.2b2/src/iop/_settings.py → iris_pex_embedded_python-4.0.0b2/src/iop/components/settings.py +0 -1
  29. iris_pex_embedded_python-4.0.0b2/src/iop/messages/__init__.py +7 -0
  30. iris_pex_embedded_python-3.7.2b2/src/iop/_message.py → iris_pex_embedded_python-4.0.0b2/src/iop/messages/base.py +15 -15
  31. iris_pex_embedded_python-3.7.2b2/src/iop/_decorators.py → iris_pex_embedded_python-4.0.0b2/src/iop/messages/decorators.py +3 -2
  32. iris_pex_embedded_python-3.7.2b2/src/iop/_dispatch.py → iris_pex_embedded_python-4.0.0b2/src/iop/messages/dispatch.py +19 -22
  33. iris_pex_embedded_python-3.7.2b2/src/iop/_persistent_message.py → iris_pex_embedded_python-4.0.0b2/src/iop/messages/persistent.py +16 -19
  34. iris_pex_embedded_python-3.7.2b2/src/iop/_serialization.py → iris_pex_embedded_python-4.0.0b2/src/iop/messages/serialization.py +21 -17
  35. iris_pex_embedded_python-3.7.2b2/src/iop/_message_validator.py → iris_pex_embedded_python-4.0.0b2/src/iop/messages/validation.py +4 -4
  36. iris_pex_embedded_python-4.0.0b2/src/iop/migration/__init__.py +1 -0
  37. iris_pex_embedded_python-4.0.0b2/src/iop/migration/io.py +61 -0
  38. iris_pex_embedded_python-4.0.0b2/src/iop/migration/plans.py +159 -0
  39. iris_pex_embedded_python-4.0.0b2/src/iop/migration/utils.py +1135 -0
  40. iris_pex_embedded_python-4.0.0b2/src/iop/production/__init__.py +29 -0
  41. iris_pex_embedded_python-4.0.0b2/src/iop/production/actions.py +228 -0
  42. iris_pex_embedded_python-4.0.0b2/src/iop/production/common.py +79 -0
  43. iris_pex_embedded_python-4.0.0b2/src/iop/production/component.py +240 -0
  44. iris_pex_embedded_python-4.0.0b2/src/iop/production/diff.py +321 -0
  45. iris_pex_embedded_python-4.0.0b2/src/iop/production/import_.py +259 -0
  46. iris_pex_embedded_python-4.0.0b2/src/iop/production/inspection.py +92 -0
  47. iris_pex_embedded_python-4.0.0b2/src/iop/production/model.py +783 -0
  48. iris_pex_embedded_python-4.0.0b2/src/iop/production/reconstruction.py +169 -0
  49. iris_pex_embedded_python-4.0.0b2/src/iop/production/rendering.py +289 -0
  50. iris_pex_embedded_python-4.0.0b2/src/iop/production/runtime.py +76 -0
  51. iris_pex_embedded_python-4.0.0b2/src/iop/production/types.py +301 -0
  52. iris_pex_embedded_python-4.0.0b2/src/iop/runtime/__init__.py +1 -0
  53. iris_pex_embedded_python-4.0.0b2/src/iop/runtime/director.py +405 -0
  54. iris_pex_embedded_python-4.0.0b2/src/iop/runtime/environment.py +59 -0
  55. iris_pex_embedded_python-3.7.2b2/src/iop/_iris.py → iris_pex_embedded_python-4.0.0b2/src/iop/runtime/iris.py +2 -2
  56. iris_pex_embedded_python-4.0.0b2/src/iop/runtime/local.py +126 -0
  57. iris_pex_embedded_python-3.7.2b2/src/iop/_director_protocol.py → iris_pex_embedded_python-4.0.0b2/src/iop/runtime/protocol.py +15 -7
  58. iris_pex_embedded_python-4.0.0b2/src/iop/runtime/remote/__init__.py +12 -0
  59. iris_pex_embedded_python-4.0.0b2/src/iop/runtime/remote/client.py +90 -0
  60. iris_pex_embedded_python-4.0.0b2/src/iop/runtime/remote/director.py +265 -0
  61. iris_pex_embedded_python-4.0.0b2/src/iop/runtime/remote/migration.py +51 -0
  62. iris_pex_embedded_python-4.0.0b2/src/iop/runtime/remote/settings.py +69 -0
  63. iris_pex_embedded_python-4.0.0b2/src/iop/runtime/remote/setup.py +72 -0
  64. {iris_pex_embedded_python-3.7.2b2 → iris_pex_embedded_python-4.0.0b2/src/iris_pex_embedded_python.egg-info}/PKG-INFO +3 -1
  65. iris_pex_embedded_python-4.0.0b2/src/iris_pex_embedded_python.egg-info/SOURCES.txt +96 -0
  66. iris_pex_embedded_python-4.0.0b2/src/iris_pex_embedded_python.egg-info/entry_points.txt +2 -0
  67. iris_pex_embedded_python-4.0.0b2/src/iris_pex_embedded_python.egg-info/top_level.txt +1 -0
  68. iris_pex_embedded_python-3.7.2b2/setup.py +0 -3
  69. iris_pex_embedded_python-3.7.2b2/src/grongier/__init__.py +0 -0
  70. iris_pex_embedded_python-3.7.2b2/src/grongier/cls/Grongier/PEX/BusinessOperation.cls +0 -8
  71. iris_pex_embedded_python-3.7.2b2/src/grongier/cls/Grongier/PEX/BusinessProcess.cls +0 -13
  72. iris_pex_embedded_python-3.7.2b2/src/grongier/cls/Grongier/PEX/BusinessService.cls +0 -8
  73. iris_pex_embedded_python-3.7.2b2/src/grongier/cls/Grongier/PEX/Common.cls +0 -10
  74. iris_pex_embedded_python-3.7.2b2/src/grongier/cls/Grongier/PEX/Director.cls +0 -10
  75. iris_pex_embedded_python-3.7.2b2/src/grongier/cls/Grongier/PEX/Duplex/Operation.cls +0 -4
  76. iris_pex_embedded_python-3.7.2b2/src/grongier/cls/Grongier/PEX/Duplex/Process.cls +0 -13
  77. iris_pex_embedded_python-3.7.2b2/src/grongier/cls/Grongier/PEX/Duplex/Service.cls +0 -4
  78. iris_pex_embedded_python-3.7.2b2/src/grongier/cls/Grongier/PEX/InboundAdapter.cls +0 -8
  79. iris_pex_embedded_python-3.7.2b2/src/grongier/cls/Grongier/PEX/Message.cls +0 -13
  80. iris_pex_embedded_python-3.7.2b2/src/grongier/cls/Grongier/PEX/OutboundAdapter.cls +0 -8
  81. iris_pex_embedded_python-3.7.2b2/src/grongier/cls/Grongier/PEX/PickleMessage.cls +0 -13
  82. iris_pex_embedded_python-3.7.2b2/src/grongier/cls/Grongier/PEX/PrivateSession/Duplex.cls +0 -8
  83. iris_pex_embedded_python-3.7.2b2/src/grongier/cls/Grongier/PEX/PrivateSession/Message/Ack.cls +0 -14
  84. iris_pex_embedded_python-3.7.2b2/src/grongier/cls/Grongier/PEX/PrivateSession/Message/Poll.cls +0 -14
  85. iris_pex_embedded_python-3.7.2b2/src/grongier/cls/Grongier/PEX/PrivateSession/Message/Start.cls +0 -14
  86. iris_pex_embedded_python-3.7.2b2/src/grongier/cls/Grongier/PEX/PrivateSession/Message/Stop.cls +0 -14
  87. iris_pex_embedded_python-3.7.2b2/src/grongier/cls/Grongier/PEX/Test.cls +0 -10
  88. iris_pex_embedded_python-3.7.2b2/src/grongier/cls/Grongier/PEX/Utils.cls +0 -10
  89. iris_pex_embedded_python-3.7.2b2/src/grongier/cls/Grongier/Service/WSGI.cls +0 -4
  90. iris_pex_embedded_python-3.7.2b2/src/grongier/pex/__init__.py +0 -75
  91. iris_pex_embedded_python-3.7.2b2/src/grongier/pex/__main__.py +0 -4
  92. iris_pex_embedded_python-3.7.2b2/src/grongier/pex/_business_host.py +0 -1
  93. iris_pex_embedded_python-3.7.2b2/src/grongier/pex/_cli.py +0 -4
  94. iris_pex_embedded_python-3.7.2b2/src/grongier/pex/_common.py +0 -1
  95. iris_pex_embedded_python-3.7.2b2/src/grongier/pex/_director.py +0 -1
  96. iris_pex_embedded_python-3.7.2b2/src/grongier/pex/_utils.py +0 -1
  97. iris_pex_embedded_python-3.7.2b2/src/grongier/pex/wsgi/handlers.py +0 -104
  98. iris_pex_embedded_python-3.7.2b2/src/iop/__init__.py +0 -87
  99. iris_pex_embedded_python-3.7.2b2/src/iop/__main__.py +0 -5
  100. iris_pex_embedded_python-3.7.2b2/src/iop/_business_host.py +0 -322
  101. iris_pex_embedded_python-3.7.2b2/src/iop/_director.py +0 -333
  102. iris_pex_embedded_python-3.7.2b2/src/iop/_local.py +0 -106
  103. iris_pex_embedded_python-3.7.2b2/src/iop/_polling_business_service.py +0 -6
  104. iris_pex_embedded_python-3.7.2b2/src/iop/_remote.py +0 -473
  105. iris_pex_embedded_python-3.7.2b2/src/iop/_utils.py +0 -912
  106. iris_pex_embedded_python-3.7.2b2/src/iop/cls/IOP/Service/WSGI.cls +0 -310
  107. iris_pex_embedded_python-3.7.2b2/src/iop/wsgi/handlers.py +0 -112
  108. iris_pex_embedded_python-3.7.2b2/src/iris_pex_embedded_python.egg-info/SOURCES.txt +0 -100
  109. iris_pex_embedded_python-3.7.2b2/src/iris_pex_embedded_python.egg-info/entry_points.txt +0 -2
  110. iris_pex_embedded_python-3.7.2b2/src/iris_pex_embedded_python.egg-info/top_level.txt +0 -2
  111. {iris_pex_embedded_python-3.7.2b2 → iris_pex_embedded_python-4.0.0b2}/LICENSE +0 -0
  112. {iris_pex_embedded_python-3.7.2b2 → iris_pex_embedded_python-4.0.0b2}/README.md +0 -0
  113. {iris_pex_embedded_python-3.7.2b2 → iris_pex_embedded_python-4.0.0b2}/setup.cfg +0 -0
  114. {iris_pex_embedded_python-3.7.2b2 → iris_pex_embedded_python-4.0.0b2}/src/iop/cls/IOP/BusinessOperation.cls +0 -0
  115. {iris_pex_embedded_python-3.7.2b2 → iris_pex_embedded_python-4.0.0b2}/src/iop/cls/IOP/BusinessProcess.cls +0 -0
  116. {iris_pex_embedded_python-3.7.2b2 → iris_pex_embedded_python-4.0.0b2}/src/iop/cls/IOP/BusinessService.cls +0 -0
  117. {iris_pex_embedded_python-3.7.2b2 → iris_pex_embedded_python-4.0.0b2}/src/iop/cls/IOP/Common.cls +0 -0
  118. {iris_pex_embedded_python-3.7.2b2 → iris_pex_embedded_python-4.0.0b2}/src/iop/cls/IOP/Director.cls +0 -0
  119. {iris_pex_embedded_python-3.7.2b2 → iris_pex_embedded_python-4.0.0b2}/src/iop/cls/IOP/Duplex/Operation.cls +0 -0
  120. {iris_pex_embedded_python-3.7.2b2 → iris_pex_embedded_python-4.0.0b2}/src/iop/cls/IOP/Duplex/Process.cls +0 -0
  121. {iris_pex_embedded_python-3.7.2b2 → iris_pex_embedded_python-4.0.0b2}/src/iop/cls/IOP/Duplex/Service.cls +0 -0
  122. {iris_pex_embedded_python-3.7.2b2 → iris_pex_embedded_python-4.0.0b2}/src/iop/cls/IOP/Generator/Message/Ack.cls +0 -0
  123. {iris_pex_embedded_python-3.7.2b2 → iris_pex_embedded_python-4.0.0b2}/src/iop/cls/IOP/Generator/Message/Poll.cls +0 -0
  124. {iris_pex_embedded_python-3.7.2b2 → iris_pex_embedded_python-4.0.0b2}/src/iop/cls/IOP/Generator/Message/Start.cls +0 -0
  125. {iris_pex_embedded_python-3.7.2b2 → iris_pex_embedded_python-4.0.0b2}/src/iop/cls/IOP/Generator/Message/StartPickle.cls +0 -0
  126. {iris_pex_embedded_python-3.7.2b2 → iris_pex_embedded_python-4.0.0b2}/src/iop/cls/IOP/Generator/Message/Stop.cls +0 -0
  127. {iris_pex_embedded_python-3.7.2b2 → iris_pex_embedded_python-4.0.0b2}/src/iop/cls/IOP/InboundAdapter.cls +0 -0
  128. {iris_pex_embedded_python-3.7.2b2 → iris_pex_embedded_python-4.0.0b2}/src/iop/cls/IOP/Message/JSONSchema.cls +0 -0
  129. {iris_pex_embedded_python-3.7.2b2 → iris_pex_embedded_python-4.0.0b2}/src/iop/cls/IOP/Message.cls +0 -0
  130. {iris_pex_embedded_python-3.7.2b2 → iris_pex_embedded_python-4.0.0b2}/src/iop/cls/IOP/OutboundAdapter.cls +0 -0
  131. {iris_pex_embedded_python-3.7.2b2 → iris_pex_embedded_python-4.0.0b2}/src/iop/cls/IOP/PickleMessage.cls +0 -0
  132. {iris_pex_embedded_python-3.7.2b2 → iris_pex_embedded_python-4.0.0b2}/src/iop/cls/IOP/PrivateSession/Duplex.cls +0 -0
  133. {iris_pex_embedded_python-3.7.2b2 → iris_pex_embedded_python-4.0.0b2}/src/iop/cls/IOP/PrivateSession/Message/Ack.cls +0 -0
  134. {iris_pex_embedded_python-3.7.2b2 → iris_pex_embedded_python-4.0.0b2}/src/iop/cls/IOP/PrivateSession/Message/Poll.cls +0 -0
  135. {iris_pex_embedded_python-3.7.2b2 → iris_pex_embedded_python-4.0.0b2}/src/iop/cls/IOP/PrivateSession/Message/Start.cls +0 -0
  136. {iris_pex_embedded_python-3.7.2b2 → iris_pex_embedded_python-4.0.0b2}/src/iop/cls/IOP/PrivateSession/Message/Stop.cls +0 -0
  137. {iris_pex_embedded_python-3.7.2b2 → iris_pex_embedded_python-4.0.0b2}/src/iop/cls/IOP/Projection.cls +0 -0
  138. {iris_pex_embedded_python-3.7.2b2 → iris_pex_embedded_python-4.0.0b2}/src/iop/cls/IOP/Service/Remote/Handler.cls +0 -0
  139. {iris_pex_embedded_python-3.7.2b2 → iris_pex_embedded_python-4.0.0b2}/src/iop/cls/IOP/Test.cls +0 -0
  140. {iris_pex_embedded_python-3.7.2b2 → iris_pex_embedded_python-4.0.0b2}/src/iris_pex_embedded_python.egg-info/dependency_links.txt +0 -0
  141. {iris_pex_embedded_python-3.7.2b2 → iris_pex_embedded_python-4.0.0b2}/src/iris_pex_embedded_python.egg-info/requires.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: iris_pex_embedded_python
3
- Version: 3.7.2b2
3
+ Version: 4.0.0b2
4
4
  Summary: Iris Interoperability based on Embedded Python
5
5
  Author-email: grongier <guillaume.rongier@intersystems.com>
6
6
  License: MIT License
@@ -37,6 +37,8 @@ Classifier: Operating System :: OS Independent
37
37
  Classifier: Programming Language :: Python :: 3.10
38
38
  Classifier: Programming Language :: Python :: 3.11
39
39
  Classifier: Programming Language :: Python :: 3.12
40
+ Classifier: Programming Language :: Python :: 3.13
41
+ Classifier: Programming Language :: Python :: 3.14
40
42
  Classifier: Topic :: Utilities
41
43
  Requires-Python: >=3.10
42
44
  Description-Content-Type: text/markdown
@@ -3,7 +3,7 @@ requires = ["setuptools", "wheel"]
3
3
 
4
4
  [project]
5
5
  name = "iris_pex_embedded_python"
6
- version = "3.7.2b2"
6
+ version = "4.0.0b2"
7
7
  description = "Iris Interoperability based on Embedded Python"
8
8
  readme = "README.md"
9
9
  requires-python = ">=3.10"
@@ -20,6 +20,8 @@ classifiers = [
20
20
  "Programming Language :: Python :: 3.10",
21
21
  "Programming Language :: Python :: 3.11",
22
22
  "Programming Language :: Python :: 3.12",
23
+ "Programming Language :: Python :: 3.13",
24
+ "Programming Language :: Python :: 3.14",
23
25
  "Topic :: Utilities"
24
26
  ]
25
27
 
@@ -42,10 +44,11 @@ repository = "https://github.com/grongierisc/interoperability-embedded-python"
42
44
  issues = "https://github.com/grongierisc/interoperability-embedded-python/issues"
43
45
 
44
46
  [project.scripts]
45
- iop = "iop._cli:main"
47
+ iop = "iop.cli.main:main"
46
48
 
47
49
  [tool.setuptools.packages.find]
48
50
  where = ["src"]
51
+ include = ["iop*"]
49
52
  exclude = ["tests*"]
50
53
 
51
54
  [tool.setuptools.package-data]
@@ -59,3 +62,11 @@ markers = [
59
62
  "e2e_local: end-to-end test requiring a local IRIS instance",
60
63
  "e2e_remote: end-to-end test requiring a remote IRIS instance via REST API",
61
64
  ]
65
+
66
+ [tool.ruff]
67
+ target-version = "py310"
68
+ line-length = 88
69
+
70
+ [tool.ruff.lint]
71
+ select = ["E", "F", "I", "B", "UP"]
72
+ ignore = ["E501"]
@@ -0,0 +1,138 @@
1
+ from iop.components.business_operation import _BusinessOperation
2
+ from iop.components.business_process import _BusinessProcess
3
+ from iop.components.business_service import _BusinessService
4
+ from iop.components.inbound_adapter import _InboundAdapter
5
+ from iop.components.outbound_adapter import _OutboundAdapter
6
+ from iop.components.polling_business_service import _PollingBusinessServiceMixin
7
+ from iop.components.private_session_duplex import _PrivateSessionDuplex
8
+ from iop.components.private_session_process import _PrivateSessionProcess
9
+ from iop.components.settings import Category as Category
10
+ from iop.components.settings import Setting as Setting
11
+ from iop.components.settings import controls as controls
12
+ from iop.components.settings import setting as setting
13
+ from iop.messages.base import (
14
+ _Message,
15
+ _PickleMessage,
16
+ _PydanticMessage,
17
+ _PydanticPickleMessage,
18
+ )
19
+ from iop.messages.persistent import Field as Field
20
+ from iop.messages.persistent import Model as Model
21
+ from iop.messages.persistent import _PersistentMessage
22
+ from iop.migration.utils import _Utils
23
+ from iop.migration.utils import bind_component as bind_component
24
+ from iop.migration.utils import list_bindings as list_bindings
25
+ from iop.migration.utils import register_component as register_component
26
+ from iop.migration.utils import unbind_component as unbind_component
27
+ from iop.migration.utils import unregister_component as unregister_component
28
+ from iop.production import ComponentRef as ComponentRef
29
+ from iop.production import Port as Port
30
+ from iop.production import Production as Production
31
+ from iop.production import ProductionDiff as ProductionDiff
32
+ from iop.production import ProductionDiffEntry as ProductionDiffEntry
33
+ from iop.production import ProductionGraph as ProductionGraph
34
+ from iop.production import target as target
35
+ from iop.runtime.director import _Director
36
+ from iop.runtime.protocol import DirectorProtocol as DirectorProtocol
37
+
38
+ __all__ = [
39
+ "BusinessOperation",
40
+ "BusinessProcess",
41
+ "BusinessService",
42
+ "Category",
43
+ "ComponentRef",
44
+ "Director",
45
+ "DirectorProtocol",
46
+ "DuplexOperation",
47
+ "DuplexProcess",
48
+ "DuplexService",
49
+ "Field",
50
+ "InboundAdapter",
51
+ "Message",
52
+ "Model",
53
+ "OutboundAdapter",
54
+ "PersistentMessage",
55
+ "PickleMessage",
56
+ "PollingBusinessService",
57
+ "Port",
58
+ "Production",
59
+ "ProductionDiff",
60
+ "ProductionDiffEntry",
61
+ "ProductionGraph",
62
+ "PydanticMessage",
63
+ "PydanticPickleMessage",
64
+ "Setting",
65
+ "Utils",
66
+ "bind_component",
67
+ "controls",
68
+ "list_bindings",
69
+ "register_component",
70
+ "setting",
71
+ "target",
72
+ "unbind_component",
73
+ "unregister_component",
74
+ ]
75
+
76
+
77
+ class Utils(_Utils):
78
+ pass
79
+
80
+
81
+ class InboundAdapter(_InboundAdapter):
82
+ pass
83
+
84
+
85
+ class OutboundAdapter(_OutboundAdapter):
86
+ pass
87
+
88
+
89
+ class BusinessService(_BusinessService):
90
+ pass
91
+
92
+
93
+ class PollingBusinessService(_PollingBusinessServiceMixin, BusinessService):
94
+ pass
95
+
96
+
97
+ class BusinessOperation(_BusinessOperation):
98
+ pass
99
+
100
+
101
+ class BusinessProcess(_BusinessProcess):
102
+ pass
103
+
104
+
105
+ class DuplexService(_PrivateSessionDuplex):
106
+ pass
107
+
108
+
109
+ class DuplexOperation(_PrivateSessionDuplex):
110
+ pass
111
+
112
+
113
+ class DuplexProcess(_PrivateSessionProcess):
114
+ pass
115
+
116
+
117
+ class Message(_Message):
118
+ pass
119
+
120
+
121
+ class PickleMessage(_PickleMessage):
122
+ pass
123
+
124
+
125
+ class PydanticMessage(_PydanticMessage):
126
+ pass
127
+
128
+
129
+ class PydanticPickleMessage(_PydanticPickleMessage):
130
+ pass
131
+
132
+
133
+ class PersistentMessage(_PersistentMessage):
134
+ _iop_persistent_message_abstract = True
135
+
136
+
137
+ class Director(_Director):
138
+ pass
@@ -0,0 +1,5 @@
1
+ # main entry is cli.main()
2
+ if __name__ == "__main__":
3
+ from iop.cli.main import main
4
+
5
+ main()
@@ -0,0 +1 @@
1
+ from .main import main as main
@@ -0,0 +1,45 @@
1
+ from __future__ import annotations
2
+
3
+ import dataclasses
4
+ import json
5
+ from typing import Any
6
+
7
+
8
+ def format_test_response(response: Any) -> str:
9
+ """Pretty-print any test_component() return value."""
10
+ if isinstance(response, dict):
11
+ parts = []
12
+ if response.get("error"):
13
+ return f"Error: {response['error']}"
14
+ if response.get("classname"):
15
+ parts.append(f"classname: {response['classname']}")
16
+ body = response.get("body", "")
17
+ if body:
18
+ try:
19
+ parsed = json.loads(body)
20
+ parts.append("body:\n" + json.dumps(parsed, indent=4))
21
+ except (json.JSONDecodeError, TypeError):
22
+ parts.append(f"body: {body}")
23
+ if response.get("truncated"):
24
+ parts.append("(response body was truncated)")
25
+ return "\n".join(parts) if parts else str(response)
26
+
27
+ if isinstance(response, str):
28
+ if " : " in response:
29
+ classname_part, _, body_part = response.partition(" : ")
30
+ try:
31
+ parsed = json.loads(body_part)
32
+ return (
33
+ f"classname: {classname_part.strip()}\n"
34
+ f"body:\n{json.dumps(parsed, indent=4)}"
35
+ )
36
+ except (json.JSONDecodeError, TypeError):
37
+ pass
38
+ try:
39
+ return json.dumps(json.loads(response), indent=4)
40
+ except (json.JSONDecodeError, TypeError):
41
+ return response
42
+
43
+ if dataclasses.is_dataclass(response):
44
+ return json.dumps(dataclasses.asdict(response), indent=4)
45
+ return str(response)
@@ -1,64 +1,23 @@
1
1
  from __future__ import annotations
2
- import argparse
2
+
3
3
  import json
4
4
  import logging
5
- import requests
6
5
  import os
7
- from dataclasses import dataclass
8
- from enum import Enum, auto
9
6
  import sys
10
- from typing import Optional
11
7
  from importlib.metadata import version
12
8
 
13
- from ._local import _LocalDirector
14
- from ._remote import _RemoteDirector, get_remote_settings
15
- from ._director_protocol import DirectorProtocol
16
- from ._utils import _Utils
17
-
18
-
19
- class CommandType(Enum):
20
- DEFAULT = auto()
21
- LIST = auto()
22
- START = auto()
23
- STOP = auto()
24
- KILL = auto()
25
- RESTART = auto()
26
- STATUS = auto()
27
- TEST = auto()
28
- VERSION = auto()
29
- EXPORT = auto()
30
- MIGRATE = auto()
31
- LOG = auto()
32
- INIT = auto()
33
- HELP = auto()
34
- UPDATE = auto()
35
-
36
-
37
- @dataclass
38
- class CommandArgs:
39
- """Container for parsed command arguments"""
40
-
41
- default: Optional[str] = None
42
- list: bool = False
43
- start: Optional[str] = None
44
- detach: bool = False
45
- stop: bool = False
46
- kill: bool = False
47
- restart: bool = False
48
- status: bool = False
49
- migrate: Optional[str] = None
50
- export: Optional[str] = None
51
- version: bool = False
52
- log: Optional[str] = None
53
- init: Optional[str] = None
54
- test: Optional[str] = None
55
- classname: Optional[str] = None
56
- body: Optional[str] = None
57
- namespace: Optional[str] = None
58
- force_local: bool = False
59
- remote_settings: Optional[str] = None
60
- update: bool = False
61
- migration_plan: bool = False
9
+ import requests
10
+
11
+ from ..migration import utils as migration_utils
12
+ from ..production import Production
13
+ from ..runtime.local import _LocalDirector
14
+ from ..runtime.protocol import DirectorProtocol
15
+ from ..runtime.remote import _RemoteDirector, get_remote_settings
16
+ from .formatting import format_test_response
17
+ from .parser import create_parser
18
+ from .types import CommandArgs, CommandType
19
+
20
+ _format_test_response = format_test_response
62
21
 
63
22
 
64
23
  class Command:
@@ -114,12 +73,18 @@ class Command:
114
73
  self.args.export,
115
74
  self.args.migrate,
116
75
  self.args.log,
76
+ self.args.queue,
117
77
  self.args.init,
78
+ self.args.bindings,
79
+ self.args.unbind is not None,
118
80
  self.args.update,
119
81
  ]
120
82
  )
121
83
 
122
84
  def execute(self) -> None:
85
+ if self.args.unused and not self.args.bindings:
86
+ raise ValueError("--unused can only be used with --bindings.")
87
+
123
88
  if self.args.namespace == "not_set" and not self._has_primary_command():
124
89
  print(os.getenv("IRISNAMESPACE", "not set"))
125
90
  return
@@ -138,7 +103,10 @@ class Command:
138
103
  CommandType.EXPORT: self._handle_export,
139
104
  CommandType.MIGRATE: self._handle_migrate,
140
105
  CommandType.LOG: self._handle_log,
106
+ CommandType.QUEUE: self._handle_queue,
141
107
  CommandType.INIT: self._handle_init,
108
+ CommandType.BINDINGS: self._handle_bindings,
109
+ CommandType.UNBIND: self._handle_unbind,
142
110
  CommandType.HELP: self._handle_help,
143
111
  CommandType.UPDATE: self._handle_update,
144
112
  }
@@ -171,8 +139,14 @@ class Command:
171
139
  return CommandType.MIGRATE
172
140
  if self.args.log:
173
141
  return CommandType.LOG
142
+ if self.args.queue:
143
+ return CommandType.QUEUE
174
144
  if self.args.init:
175
145
  return CommandType.INIT
146
+ if self.args.bindings:
147
+ return CommandType.BINDINGS
148
+ if self.args.unbind is not None:
149
+ return CommandType.UNBIND
176
150
  if self.args.update:
177
151
  return CommandType.UPDATE
178
152
  return CommandType.HELP
@@ -230,13 +204,13 @@ class Command:
230
204
  filepath = body[1:]
231
205
  if not os.path.isabs(filepath):
232
206
  filepath = os.path.join(os.getcwd(), filepath)
233
- with open(filepath, "r", encoding="utf-8") as fh:
207
+ with open(filepath, encoding="utf-8") as fh:
234
208
  body = fh.read()
235
209
 
236
210
  response = self.director.test_component(
237
211
  test_name, classname=classname, body=body
238
212
  )
239
- print(_format_test_response(response))
213
+ print(format_test_response(response))
240
214
 
241
215
  def _handle_version(self) -> None:
242
216
  print(version("iris-pex-embedded-python"))
@@ -247,7 +221,19 @@ class Command:
247
221
  if self.args.export == "not_set"
248
222
  else self.args.export
249
223
  )
250
- print(json.dumps(self.director.export_production(export_name), indent=4))
224
+ export_format = self.args.export_format or "json"
225
+ if export_format == "json":
226
+ print(json.dumps(self.director.export_production(export_name), indent=4))
227
+ return
228
+
229
+ production = Production.from_iris(export_name, director=self.director)
230
+ if export_format == "python":
231
+ print(production.to_python(), end="")
232
+ return
233
+ if export_format == "graph":
234
+ print(production.graph())
235
+ return
236
+ raise ValueError(f"Unsupported export format: {export_format}")
251
237
 
252
238
  def _handle_migrate(self) -> None:
253
239
  migrate_path = self.args.migrate
@@ -257,21 +243,21 @@ class Command:
257
243
  mode = "REMOTE" if self._is_remote else "LOCAL"
258
244
  if self.args.migration_plan:
259
245
  print(
260
- _Utils.explain_migration(
246
+ migration_utils.explain_migration(
261
247
  migrate_path, mode=mode, namespace=self.director.namespace
262
248
  )
263
249
  )
264
250
  return
265
251
  if self._is_remote:
266
252
  print(
267
- _Utils.explain_migration(
253
+ migration_utils.explain_migration(
268
254
  migrate_path, mode=mode, namespace=self.director.namespace
269
255
  )
270
256
  )
271
257
  self.director.migrate(migrate_path)
272
258
  if self._is_remote:
273
259
  print(
274
- _Utils.format_migration_success(
260
+ migration_utils.format_migration_success(
275
261
  migrate_path, namespace=self.director.namespace
276
262
  )
277
263
  )
@@ -282,10 +268,43 @@ class Command:
282
268
  elif self.args.log is not None:
283
269
  self.director.log_production_top(int(self.args.log))
284
270
 
271
+ def _handle_queue(self) -> None:
272
+ production_name = (
273
+ self.director.get_default_production()
274
+ if self.args.queue == "not_set"
275
+ else self.args.queue
276
+ )
277
+ if not production_name or production_name == "Not defined":
278
+ print(
279
+ "Error: no production name provided and no default production is defined.",
280
+ file=sys.stderr,
281
+ )
282
+ sys.exit(1)
283
+ print(
284
+ json.dumps(
285
+ self.director.export_production_queue_info(production_name),
286
+ indent=4,
287
+ )
288
+ )
289
+
285
290
  def _handle_init(self) -> None:
286
291
  path = None if self.args.init == "not_set" else self.args.init
287
292
  self.director.setup(path)
288
293
 
294
+ def _handle_bindings(self) -> None:
295
+ print(
296
+ json.dumps(
297
+ self.director.list_bindings(unused_only=self.args.unused),
298
+ indent=4,
299
+ )
300
+ )
301
+
302
+ def _handle_unbind(self) -> None:
303
+ if not self.args.unbind:
304
+ raise ValueError("IRIS class name is required.")
305
+ self.director.unbind_component(self.args.unbind)
306
+ print(f"Removed binding {self.args.unbind}.")
307
+
289
308
  def _handle_help(self) -> None:
290
309
  create_parser().print_help()
291
310
  if self._is_remote:
@@ -297,161 +316,6 @@ class Command:
297
316
  logging.warning("Could not retrieve default production.")
298
317
 
299
318
 
300
- def _format_test_response(response) -> str:
301
- """Pretty-print any test_component() return value.
302
-
303
- Handles three cases:
304
- - dict : remote response with ``classname`` / ``body`` keys
305
- - str : local response in ``"ClassName : {json}"`` format
306
- - other : Python dataclass / object returned by the local director
307
- """
308
- if isinstance(response, dict):
309
- parts = []
310
- if response.get("error"):
311
- return f"Error: {response['error']}"
312
- if response.get("classname"):
313
- parts.append(f"classname: {response['classname']}")
314
- body = response.get("body", "")
315
- if body:
316
- try:
317
- parsed = json.loads(body)
318
- parts.append("body:\n" + json.dumps(parsed, indent=4))
319
- except (json.JSONDecodeError, TypeError):
320
- parts.append(f"body: {body}")
321
- if response.get("truncated"):
322
- parts.append("(response body was truncated)")
323
- return "\n".join(parts) if parts else str(response)
324
-
325
- if isinstance(response, str):
326
- # Try to detect the "ClassName : {json_body}" pattern from local mode
327
- if " : " in response:
328
- classname_part, _, body_part = response.partition(" : ")
329
- try:
330
- parsed = json.loads(body_part)
331
- return (
332
- f"classname: {classname_part.strip()}\n"
333
- f"body:\n{json.dumps(parsed, indent=4)}"
334
- )
335
- except (json.JSONDecodeError, TypeError):
336
- pass
337
- # Plain string — try JSON pretty-print
338
- try:
339
- return json.dumps(json.loads(response), indent=4)
340
- except (json.JSONDecodeError, TypeError):
341
- return response
342
-
343
- # Python dataclass / arbitrary object
344
- try:
345
- import dataclasses
346
-
347
- if dataclasses.is_dataclass(response):
348
- return json.dumps(dataclasses.asdict(response), indent=4)
349
- except Exception:
350
- pass
351
- return str(response)
352
-
353
-
354
- def create_parser() -> argparse.ArgumentParser:
355
- """Create and configure argument parser"""
356
- main_parser = argparse.ArgumentParser(
357
- epilog=(
358
- "Remote mode: set IOP_URL (e.g. http://localhost:8080) to run all commands\n"
359
- "against a remote IRIS instance via its REST API. Optional env vars:\n"
360
- " IOP_USERNAME, IOP_PASSWORD, IOP_NAMESPACE (default: USER),\n"
361
- " IOP_VERIFY_SSL (set to 0 to disable TLS verification).\n"
362
- "Alternatively use -R /path/to/settings.py or set IOP_SETTINGS=\n"
363
- "(file must contain a REMOTE_SETTINGS dict with at least 'url').\n"
364
- "Use --force-local to suppress remote mode entirely."
365
- ),
366
- formatter_class=argparse.RawDescriptionHelpFormatter,
367
- )
368
- parser = main_parser.add_mutually_exclusive_group()
369
-
370
- # Main commands
371
- parser.add_argument(
372
- "-d", "--default", help="set the default production", nargs="?", const="not_set"
373
- )
374
- parser.add_argument("-l", "--list", help="list productions", action="store_true")
375
- parser.add_argument(
376
- "-s", "--start", help="start a production", nargs="?", const="not_set"
377
- )
378
- parser.add_argument("-S", "--stop", help="stop a production", action="store_true")
379
- parser.add_argument("-k", "--kill", help="kill a production", action="store_true")
380
- parser.add_argument(
381
- "-r", "--restart", help="restart a production", action="store_true"
382
- )
383
- parser.add_argument(
384
- "-x", "--status", help="status a production", action="store_true"
385
- )
386
- parser.add_argument(
387
- "-m",
388
- "-M",
389
- "--migrate",
390
- help="migrate production and classes with settings file",
391
- )
392
- parser.add_argument(
393
- "-e", "--export", help="export a production", nargs="?", const="not_set"
394
- )
395
- parser.add_argument("-v", "--version", help="display version", action="store_true")
396
- parser.add_argument("-L", "--log", help="display log", nargs="?", const="not_set")
397
- parser.add_argument(
398
- "-i", "--init", help="init the pex module in iris", nargs="?", const="not_set"
399
- )
400
- parser.add_argument(
401
- "-t", "--test", help="test the pex module in iris", nargs="?", const="not_set"
402
- )
403
- parser.add_argument(
404
- "-u", "--update", help="update a production", action="store_true"
405
- )
406
-
407
- # Command groups
408
- start = main_parser.add_argument_group("start arguments")
409
- start.add_argument(
410
- "-D", "--detach", help="start a production in detach mode", action="store_true"
411
- )
412
-
413
- test = main_parser.add_argument_group("test arguments")
414
- test.add_argument(
415
- "-C", "--classname", help="test classname", nargs="?", const="not_set"
416
- )
417
- test.add_argument(
418
- "-B",
419
- "--body",
420
- help="test body (JSON string or @path/to/file.json)",
421
- nargs="?",
422
- const="not_set",
423
- )
424
-
425
- migrate = main_parser.add_argument_group("migrate arguments")
426
- migrate.add_argument(
427
- "--force-local",
428
- help="force local mode, skip remote even if REMOTE_SETTINGS or IOP_URL is present",
429
- action="store_true",
430
- )
431
- migrate.add_argument(
432
- "--dry-run",
433
- "--explain",
434
- dest="migration_plan",
435
- help="show the migration plan and validation messages without writing to IRIS",
436
- action="store_true",
437
- )
438
-
439
- remote = main_parser.add_argument_group("remote arguments")
440
- remote.add_argument(
441
- "-R",
442
- "--remote-settings",
443
- help="path to a settings.py containing REMOTE_SETTINGS (overrides IOP_SETTINGS env var)",
444
- metavar="FILE",
445
- )
446
-
447
- namespace = main_parser.add_argument_group("namespace arguments")
448
- namespace.add_argument(
449
- "-n", "--namespace", help="set namespace", nargs="?", const="not_set"
450
- )
451
-
452
- return main_parser
453
-
454
-
455
319
  def main(argv=None) -> None:
456
320
  parser = create_parser()
457
321
  args = parser.parse_args(argv)
@@ -472,7 +336,7 @@ def main(argv=None) -> None:
472
336
  except requests.exceptions.HTTPError as exc:
473
337
  print(f"Error: {exc}", file=sys.stderr)
474
338
  sys.exit(1)
475
- except RuntimeError as exc:
339
+ except (RuntimeError, ValueError) as exc:
476
340
  print(f"Error: {exc}", file=sys.stderr)
477
341
  sys.exit(1)
478
342
  sys.exit(0)