iris-devtester 1.9.3__tar.gz → 1.10.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.
Files changed (241) hide show
  1. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/PKG-INFO +42 -3
  2. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/README.md +41 -2
  3. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/SKILL.md +1 -1
  4. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/__init__.py +1 -1
  5. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/cli/container.py +184 -10
  6. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/config/container_config.py +10 -4
  7. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/containers/iris_container.py +88 -6
  8. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester.egg-info/PKG-INFO +42 -3
  9. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/pyproject.toml +1 -1
  10. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/unit/config/test_container_config.py +13 -2
  11. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/unit/test_iris_container.py +47 -3
  12. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/unit/utils/test_iris_container_adapter.py +1 -1
  13. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/AGENTS.md +0 -0
  14. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/CLAUDE.md +0 -0
  15. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/CONSTITUTION.md +0 -0
  16. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/LICENSE +0 -0
  17. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/MANIFEST.in +0 -0
  18. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/GETTING_STARTED.md +0 -0
  19. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/LANGCHAIN_INTEGRATION_QUICKSTART.md +0 -0
  20. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/ROADMAP.md +0 -0
  21. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/SQL_VS_OBJECTSCRIPT.md +0 -0
  22. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/TROUBLESHOOTING.md +0 -0
  23. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/WHATS_NEW_v1.4.0.md +0 -0
  24. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/archive/AGENTIC_SANDBOX_ENHANCEMENT_REPORT.md +0 -0
  25. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/archive/IMPACT_ANALYSIS.md +0 -0
  26. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/archive/IRIS_DEVTESTER_POSITIONING_REPORT.md +0 -0
  27. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/archive/LANGCHAIN_INTEGRATION_STRATEGY.md +0 -0
  28. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/archive/LANGCHAIN_INTEGRATION_TEST_RESULTS.md +0 -0
  29. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/archive/PHASE_2_PLAN.md +0 -0
  30. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/archive/RAG_TEMPLATES_ANALYSIS.md +0 -0
  31. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/archive/README.md +0 -0
  32. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/archive/STRATEGIC_ROADMAP_SUMMARY.md +0 -0
  33. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/archive/feature-009-refactor-plan.md +0 -0
  34. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/development/BUG_REPORT.md +0 -0
  35. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/development/EXTRACTION_SUMMARY.md +0 -0
  36. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/development/FEATURE_006_SUMMARY.md +0 -0
  37. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/development/PHASE2_RESULTS.md +0 -0
  38. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/development/PRE_PUBLISH_REVIEW.md +0 -0
  39. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/development/PROGRESS.md +0 -0
  40. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/development/PYPI_READINESS.md +0 -0
  41. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/development/SESSION-INTEGRATION-TESTS.md +0 -0
  42. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/development/SESSION-SUMMARY.md +0 -0
  43. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/development/STATUS-002-PIVOTED.md +0 -0
  44. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/development/STATUS-003-COMPLETE.md +0 -0
  45. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/development/STATUS.md +0 -0
  46. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/development/V1_COMPLETION_PLAN.md +0 -0
  47. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/development/V1_RELEASE_SUMMARY.md +0 -0
  48. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/features/WSGI-ASGI-SERVER-SETUP.md +0 -0
  49. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/features/agent-skills.md +0 -0
  50. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/features/dat-fixtures.md +0 -0
  51. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/features/docker-compose.md +0 -0
  52. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/features/performance-monitoring.md +0 -0
  53. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/features/testcontainers.md +0 -0
  54. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/learnings/api-contract-synchronization.md +0 -0
  55. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/learnings/callin-service-requirement.md +0 -0
  56. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/learnings/cpf-merge-and-container-restarts.md +0 -0
  57. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/learnings/dat-fixtures-docker-exec-pattern.md +0 -0
  58. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/learnings/dat-restore-database-isolation-problem.md +0 -0
  59. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/learnings/dbapi-bulk-insert-performance-issue.md +0 -0
  60. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/learnings/dbapi-objectscript-limitation.md +0 -0
  61. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/learnings/dbapi-password-reset-limitation.md +0 -0
  62. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/learnings/dbapi-private-module-myth.md +0 -0
  63. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/learnings/docker-hub-image-naming.md +0 -0
  64. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/learnings/embedded-python-considerations.md +0 -0
  65. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/learnings/feature-002-pivot-summary.md +0 -0
  66. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/learnings/integration-test-dbapi-limitation.md +0 -0
  67. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/learnings/iris-backup-patterns.md +0 -0
  68. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/learnings/iris-container-performance.md +0 -0
  69. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/learnings/iris-container-readiness.md +0 -0
  70. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/learnings/iris-docker-sdk-environment-variables.md +0 -0
  71. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/learnings/iris-performance-monitoring-landscape.md +0 -0
  72. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/learnings/iris-security-users-api.md +0 -0
  73. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/learnings/password-reset-changeflag-fix.md +0 -0
  74. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/learnings/rag-templates-production-patterns.md +0 -0
  75. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/learnings/sql-task-manager-operations.md +0 -0
  76. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/learnings/test-isolation-fix-summary.md +0 -0
  77. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/learnings/test-isolation-investigation.md +0 -0
  78. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/docs/learnings/testcontainers-ryuk-lifecycle.md +0 -0
  79. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/examples/01_quickstart.py +0 -0
  80. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/examples/02_connection_management.py +0 -0
  81. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/examples/04_pytest_fixtures.py +0 -0
  82. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/examples/05_ci_cd.py +0 -0
  83. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/examples/08_auto_discovery.py +0 -0
  84. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/examples/09_enterprise.py +0 -0
  85. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/examples/10_docker_compose_integration.py +0 -0
  86. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/examples/langchain_integration_example.py +0 -0
  87. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/cli/__init__.py +0 -0
  88. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/cli/__main__.py +0 -0
  89. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/cli/connection_commands.py +0 -0
  90. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/cli/container_commands.py +0 -0
  91. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/cli/fixture_commands.py +0 -0
  92. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/config/__init__.py +0 -0
  93. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/config/auto_discovery.py +0 -0
  94. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/config/container_state.py +0 -0
  95. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/config/defaults.py +0 -0
  96. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/config/discovery.py +0 -0
  97. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/config/models.py +0 -0
  98. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/config/presets.py +0 -0
  99. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/config/yaml_loader.py +0 -0
  100. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/connections/__init__.py +0 -0
  101. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/connections/auto_discovery.py +0 -0
  102. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/connections/connection.py +0 -0
  103. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/connections/dbapi.py +0 -0
  104. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/connections/jdbc.py +0 -0
  105. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/connections/manager.py +0 -0
  106. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/connections/models.py +0 -0
  107. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/connections/retry.py +0 -0
  108. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/containers/__init__.py +0 -0
  109. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/containers/cpf_manager.py +0 -0
  110. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/containers/models.py +0 -0
  111. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/containers/monitor_utils.py +0 -0
  112. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/containers/monitoring.py +0 -0
  113. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/containers/performance.py +0 -0
  114. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/containers/validation.py +0 -0
  115. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/containers/wait_strategies.py +0 -0
  116. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/fixtures/__init__.py +0 -0
  117. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/fixtures/creator.py +0 -0
  118. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/fixtures/loader.py +0 -0
  119. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/fixtures/manifest.py +0 -0
  120. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/fixtures/obj_export.py +0 -0
  121. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/fixtures/validator.py +0 -0
  122. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/integrations/__init__.py +0 -0
  123. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/integrations/langchain.py +0 -0
  124. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/ports/__init__.py +0 -0
  125. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/ports/assignment.py +0 -0
  126. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/ports/exceptions.py +0 -0
  127. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/ports/registry.py +0 -0
  128. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/testing/__init__.py +0 -0
  129. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/testing/fixtures.py +0 -0
  130. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/testing/helpers.py +0 -0
  131. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/testing/models.py +0 -0
  132. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/testing/schema_reset.py +0 -0
  133. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/utils/__init__.py +0 -0
  134. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/utils/container_port.py +0 -0
  135. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/utils/container_status.py +0 -0
  136. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/utils/dbapi_compat.py +0 -0
  137. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/utils/enable_callin.py +0 -0
  138. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/utils/health_checks.py +0 -0
  139. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/utils/iris_container_adapter.py +0 -0
  140. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/utils/password.py +0 -0
  141. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/utils/progress.py +0 -0
  142. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester/utils/test_connection.py +0 -0
  143. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester.egg-info/SOURCES.txt +0 -0
  144. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester.egg-info/dependency_links.txt +0 -0
  145. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester.egg-info/entry_points.txt +0 -0
  146. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester.egg-info/requires.txt +0 -0
  147. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/iris_devtester.egg-info/top_level.txt +0 -0
  148. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/setup.cfg +0 -0
  149. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/__init__.py +0 -0
  150. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/conftest.py +0 -0
  151. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/contract/__init__.py +0 -0
  152. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/contract/cli/test_container_logs_contract.py +0 -0
  153. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/contract/cli/test_container_remove_contract.py +0 -0
  154. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/contract/cli/test_container_restart_contract.py +0 -0
  155. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/contract/cli/test_container_start_contract.py +0 -0
  156. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/contract/cli/test_container_status_contract.py +0 -0
  157. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/contract/cli/test_container_stop_contract.py +0 -0
  158. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/contract/cli/test_container_up_contract.py +0 -0
  159. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/contract/test_agent_skills.py +0 -0
  160. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/contract/test_cli_container_commands.py +0 -0
  161. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/contract/test_cli_fixture_commands.py +0 -0
  162. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/contract/test_connection_api.py +0 -0
  163. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/contract/test_container_api.py +0 -0
  164. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/contract/test_container_integration_contract.py +0 -0
  165. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/contract/test_container_status_api.py +0 -0
  166. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/contract/test_container_validation_api.py +0 -0
  167. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/contract/test_enable_callin_api.py +0 -0
  168. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/contract/test_fixture_creator_api.py +0 -0
  169. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/contract/test_fixture_loader_api.py +0 -0
  170. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/contract/test_fixture_validator_api.py +0 -0
  171. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/contract/test_iriscontainer_attach.py +0 -0
  172. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/contract/test_legacy_package_contract.py +0 -0
  173. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/contract/test_modern_package_contract.py +0 -0
  174. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/contract/test_monitoring_config_api.py +0 -0
  175. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/contract/test_package_detection.py +0 -0
  176. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/contract/test_port_registry_contract.py +0 -0
  177. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/contract/test_preconfig_contract.py +0 -0
  178. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/contract/test_reset_verification_contract.py +0 -0
  179. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/contract/test_resource_monitoring_api.py +0 -0
  180. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/contract/test_retry_logic_contract.py +0 -0
  181. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/contract/test_task_manager_api.py +0 -0
  182. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/contract/test_test_connection_api.py +0 -0
  183. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/contract/test_testing_fixtures_api.py +0 -0
  184. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/e2e/__init__.py +0 -0
  185. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/e2e/test_skill_workflow.py +0 -0
  186. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/integration/__init__.py +0 -0
  187. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/integration/conftest.py +0 -0
  188. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/integration/ports/__init__.py +0 -0
  189. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/integration/ports/test_manual_port_override.py +0 -0
  190. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/integration/ports/test_multi_project_isolation.py +0 -0
  191. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/integration/ports/test_port_exhaustion.py +0 -0
  192. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/integration/ports/test_port_persistence.py +0 -0
  193. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/integration/ports/test_stale_cleanup.py +0 -0
  194. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/integration/test_bug_fixes.py +0 -0
  195. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/integration/test_bug_fixes_011.py +0 -0
  196. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/integration/test_cli_container_integration.py +0 -0
  197. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/integration/test_connection_integration.py +0 -0
  198. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/integration/test_container_health_monitor.py +0 -0
  199. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/integration/test_container_status_integration.py +0 -0
  200. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/integration/test_container_validation.py +0 -0
  201. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/integration/test_cpf_merge.py +0 -0
  202. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/integration/test_cpf_presets.py +0 -0
  203. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/integration/test_cpf_security.py +0 -0
  204. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/integration/test_custom_user_remediation.py +0 -0
  205. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/integration/test_dat_fixtures_integration.py +0 -0
  206. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/integration/test_enable_callin_integration.py +0 -0
  207. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/integration/test_fixture_export_patterns.py +0 -0
  208. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/integration/test_fixture_performance.py +0 -0
  209. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/integration/test_fixture_refresh.py +0 -0
  210. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/integration/test_iriscontainer_attach_integration.py +0 -0
  211. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/integration/test_monitor_utils_integration.py +0 -0
  212. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/integration/test_monitoring_integration.py +0 -0
  213. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/integration/test_password_preconfig_integration.py +0 -0
  214. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/integration/test_password_reset_both_editions.py +0 -0
  215. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/integration/test_password_reset_integration.py +0 -0
  216. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/integration/test_password_reset_macos.py +0 -0
  217. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/integration/test_password_reset_timing.py +0 -0
  218. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/integration/test_password_reset_validation.py +0 -0
  219. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/integration/test_proactive_password_reset.py +0 -0
  220. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/integration/test_real_world_problems.py +0 -0
  221. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/integration/test_reliable_password_reset.py +0 -0
  222. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/integration/test_test_connection_integration.py +0 -0
  223. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/unit/__init__.py +0 -0
  224. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/unit/config/test_config_hierarchy.py +0 -0
  225. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/unit/config/test_yaml_loader.py +0 -0
  226. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/unit/test_auto_discovery.py +0 -0
  227. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/unit/test_config_discovery.py +0 -0
  228. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/unit/test_connection_fallback.py +0 -0
  229. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/unit/test_connection_info.py +0 -0
  230. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/unit/test_cpf_manager.py +0 -0
  231. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/unit/test_iris_config.py +0 -0
  232. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/unit/test_manifest.py +0 -0
  233. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/unit/test_monitoring_policy.py +0 -0
  234. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/unit/test_password_preconfig.py +0 -0
  235. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/unit/test_password_preconfig_unit.py +0 -0
  236. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/unit/test_performance_metrics.py +0 -0
  237. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/unit/test_resource_thresholds.py +0 -0
  238. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/unit/test_retry.py +0 -0
  239. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/unit/test_schema_models.py +0 -0
  240. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/unit/test_validation_results.py +0 -0
  241. {iris_devtester-1.9.3 → iris_devtester-1.10.0}/tests/unit/test_wait_strategies.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: iris-devtester
3
- Version: 1.9.3
3
+ Version: 1.10.0
4
4
  Summary: Battle-tested InterSystems IRIS infrastructure utilities for Python development
5
5
  Author-email: InterSystems Community <community@intersystems.com>
6
6
  Maintainer-email: Thomas Dyar <thomas.dyar@intersystems.com>
@@ -107,9 +107,17 @@ def test_connection():
107
107
  assert cursor.fetchone()[0] == 1
108
108
  ```
109
109
 
110
- ## Container API
110
+ ## Container Editions
111
111
 
112
- ### Basic Usage
112
+ Three canonical container editions are available:
113
+
114
+ | Edition | Size | Use Case | Image |
115
+ |---------|------|----------|-------|
116
+ | **Community** | ~972MB | Development, testing | `intersystemsdc/iris-community` |
117
+ | **Enterprise** | ~1GB+ | Production testing | `containers.intersystems.com/intersystems/iris` |
118
+ | **Light** | **~580MB** | CI/CD pipelines | `caretdev/iris-community-light` |
119
+
120
+ ### Python API
113
121
  ```python
114
122
  from iris_devtester.containers import IRISContainer
115
123
 
@@ -117,11 +125,42 @@ from iris_devtester.containers import IRISContainer
117
125
  with IRISContainer.community() as iris:
118
126
  conn = iris.get_connection()
119
127
 
128
+ # Light Edition (85% smaller, for CI/CD)
129
+ with IRISContainer.light() as iris:
130
+ conn = iris.get_connection()
131
+
120
132
  # Enterprise Edition (requires license)
121
133
  with IRISContainer.enterprise(license_key="/path/to/iris.key") as iris:
122
134
  conn = iris.get_connection()
135
+
136
+ # Specify version
137
+ with IRISContainer.community(version="2025.1") as iris:
138
+ conn = iris.get_connection()
139
+ ```
140
+
141
+ ### CLI Usage
142
+ ```bash
143
+ # Community (default)
144
+ iris-devtester container up
145
+
146
+ # Light edition for CI/CD
147
+ iris-devtester container up --edition light
148
+
149
+ # Enterprise edition with license
150
+ iris-devtester container up --edition enterprise --license /path/to/iris.key
151
+
152
+ # List running IRIS containers
153
+ iris-devtester container list
123
154
  ```
124
155
 
156
+ ### Light Edition Details
157
+
158
+ The Light edition removes components unnecessary for SQL-only workloads:
159
+ - **Removed**: Interoperability/Ensemble, Management Portal, DeepSee/BI, CSP/REST
160
+ - **Kept**: SQL engine, DBAPI, JDBC, ODBC, SQLAlchemy-IRIS support
161
+
162
+ Perfect for microservices, automated testing, and Python/SQL pipelines.
163
+
125
164
  ### Builder Methods
126
165
  ```python
127
166
  # Set a custom container name (for debugging, logs, multiple containers)
@@ -43,9 +43,17 @@ def test_connection():
43
43
  assert cursor.fetchone()[0] == 1
44
44
  ```
45
45
 
46
- ## Container API
46
+ ## Container Editions
47
47
 
48
- ### Basic Usage
48
+ Three canonical container editions are available:
49
+
50
+ | Edition | Size | Use Case | Image |
51
+ |---------|------|----------|-------|
52
+ | **Community** | ~972MB | Development, testing | `intersystemsdc/iris-community` |
53
+ | **Enterprise** | ~1GB+ | Production testing | `containers.intersystems.com/intersystems/iris` |
54
+ | **Light** | **~580MB** | CI/CD pipelines | `caretdev/iris-community-light` |
55
+
56
+ ### Python API
49
57
  ```python
50
58
  from iris_devtester.containers import IRISContainer
51
59
 
@@ -53,11 +61,42 @@ from iris_devtester.containers import IRISContainer
53
61
  with IRISContainer.community() as iris:
54
62
  conn = iris.get_connection()
55
63
 
64
+ # Light Edition (85% smaller, for CI/CD)
65
+ with IRISContainer.light() as iris:
66
+ conn = iris.get_connection()
67
+
56
68
  # Enterprise Edition (requires license)
57
69
  with IRISContainer.enterprise(license_key="/path/to/iris.key") as iris:
58
70
  conn = iris.get_connection()
71
+
72
+ # Specify version
73
+ with IRISContainer.community(version="2025.1") as iris:
74
+ conn = iris.get_connection()
75
+ ```
76
+
77
+ ### CLI Usage
78
+ ```bash
79
+ # Community (default)
80
+ iris-devtester container up
81
+
82
+ # Light edition for CI/CD
83
+ iris-devtester container up --edition light
84
+
85
+ # Enterprise edition with license
86
+ iris-devtester container up --edition enterprise --license /path/to/iris.key
87
+
88
+ # List running IRIS containers
89
+ iris-devtester container list
59
90
  ```
60
91
 
92
+ ### Light Edition Details
93
+
94
+ The Light edition removes components unnecessary for SQL-only workloads:
95
+ - **Removed**: Interoperability/Ensemble, Management Portal, DeepSee/BI, CSP/REST
96
+ - **Kept**: SQL engine, DBAPI, JDBC, ODBC, SQLAlchemy-IRIS support
97
+
98
+ Perfect for microservices, automated testing, and Python/SQL pipelines.
99
+
61
100
  ### Builder Methods
62
101
  ```python
63
102
  # Set a custom container name (for debugging, logs, multiple containers)
@@ -3,7 +3,7 @@ name: iris-devtester
3
3
  description: Battle-tested InterSystems IRIS infrastructure utilities for Python database testing.
4
4
  triggers: [iris, database, testing, container, fixture, gof, connection, remediation]
5
5
  metadata:
6
- version: 1.9.3
6
+ version: 1.10.0
7
7
  author: InterSystems Community
8
8
  principles: [library-first, dbapi-first, isolation-by-default, fail-fast]
9
9
  ---
@@ -26,7 +26,7 @@ LangChain Integration:
26
26
  ... # Build your RAG app...
27
27
  """
28
28
 
29
- __version__ = "1.9.3"
29
+ __version__ = "1.10.0"
30
30
  __author__ = "InterSystems Community"
31
31
  __license__ = "MIT"
32
32
 
@@ -37,6 +37,19 @@ def container_group(ctx):
37
37
  default=None,
38
38
  help="Container name (default: iris_db)",
39
39
  )
40
+ @click.option(
41
+ "--edition",
42
+ type=click.Choice(["community", "enterprise", "light"], case_sensitive=False),
43
+ default="community",
44
+ help="IRIS edition: community (default), enterprise (requires license), light (minimal for CI/CD)",
45
+ )
46
+ @click.option(
47
+ "--license",
48
+ "license_key",
49
+ type=click.Path(exists=True),
50
+ default=None,
51
+ help="Path to iris.key license file (required for enterprise edition)",
52
+ )
40
53
  @click.option(
41
54
  "--detach/--no-detach",
42
55
  default=True,
@@ -47,7 +60,7 @@ def container_group(ctx):
47
60
  )
48
61
  @click.option("--cpf", help="Path to CPF merge file or raw CPF content")
49
62
  @click.pass_context
50
- def up(ctx, config, name, detach, timeout, cpf):
63
+ def up(ctx, config, name, edition, license_key, detach, timeout, cpf):
51
64
  """
52
65
  Create and start IRIS container from configuration.
53
66
 
@@ -64,18 +77,18 @@ def up(ctx, config, name, detach, timeout, cpf):
64
77
  # Zero-config (uses Community edition defaults)
65
78
  iris-devtester container up
66
79
 
80
+ # Light edition for CI/CD (85% smaller, faster startup)
81
+ iris-devtester container up --edition light
82
+
83
+ # Enterprise edition with license
84
+ iris-devtester container up --edition enterprise --license /path/to/iris.key
85
+
67
86
  # With custom container name
68
87
  iris-devtester container up --name my-test-db
69
88
 
70
89
  # With custom configuration including volumes
71
90
  iris-devtester container up --config iris-config.yml
72
91
 
73
- # Example iris-config.yml with volumes:
74
- # edition: community
75
- # volumes:
76
- # - ./workspace:/external/workspace
77
- # - ./config:/opt/config:ro
78
-
79
92
  # Foreground mode (see logs)
80
93
  iris-devtester container up --no-detach
81
94
  """
@@ -99,6 +112,32 @@ def up(ctx, config, name, detach, timeout, cpf):
99
112
  container_config.container_name = name
100
113
  click.echo(f" → Container name: {name}")
101
114
 
115
+ # Override edition if provided via --edition
116
+ if edition:
117
+ edition_lower = edition.lower()
118
+ container_config.edition = edition_lower
119
+
120
+ # Set appropriate image based on edition
121
+ if edition_lower == "light":
122
+ # Light edition: caretdev/iris-community-light (85% smaller)
123
+ container_config.image_tag = "latest-em"
124
+ click.echo(
125
+ click.style(f" → Edition: light", fg="cyan")
126
+ + " (minimal for CI/CD, ~580MB vs ~3.5GB)"
127
+ )
128
+ elif edition_lower == "enterprise":
129
+ if not license_key:
130
+ raise click.ClickException(
131
+ "Enterprise edition requires --license option.\n"
132
+ "\n"
133
+ "Usage: iris-devtester container up --edition enterprise --license /path/to/iris.key"
134
+ )
135
+ container_config.license_key = license_key
136
+ click.echo(f" → Edition: enterprise")
137
+ click.echo(f" → License: {license_key}")
138
+ else:
139
+ click.echo(f" → Edition: community")
140
+
102
141
  if cpf:
103
142
  container_config.cpf_merge = cpf
104
143
  click.echo(f" → CPF Merge: {cpf[:50]}...")
@@ -272,6 +311,141 @@ def up(ctx, config, name, detach, timeout, cpf):
272
311
  ctx.exit(1)
273
312
 
274
313
 
314
+ @container_group.command(name="list")
315
+ @click.option(
316
+ "--all", "-a", "show_all", is_flag=True, help="Show all containers (including stopped)"
317
+ )
318
+ @click.option(
319
+ "--format",
320
+ "output_format",
321
+ type=click.Choice(["table", "json"], case_sensitive=False),
322
+ default="table",
323
+ help="Output format (default: table)",
324
+ )
325
+ @click.pass_context
326
+ def list_containers(ctx, show_all, output_format):
327
+ """
328
+ List IRIS containers.
329
+
330
+ Shows all IRIS containers managed by iris-devtester, with their status,
331
+ edition, ports, and age.
332
+
333
+ \b
334
+ Examples:
335
+ # List running containers
336
+ iris-devtester container list
337
+
338
+ # List all containers (including stopped)
339
+ iris-devtester container list --all
340
+
341
+ # JSON output for scripting
342
+ iris-devtester container list --format json
343
+ """
344
+ from datetime import datetime
345
+
346
+ import docker
347
+
348
+ try:
349
+ client = docker.from_env()
350
+
351
+ # Find IRIS containers (by image name patterns)
352
+ iris_patterns = [
353
+ "iris-community",
354
+ "intersystems/iris",
355
+ "caretdev/iris",
356
+ "intersystemsdc/iris",
357
+ ]
358
+
359
+ containers = client.containers.list(all=show_all)
360
+ iris_containers = []
361
+
362
+ for container in containers:
363
+ image_name = (
364
+ container.image.tags[0] if container.image.tags else str(container.image.id)[:12]
365
+ )
366
+
367
+ # Check if this is an IRIS container
368
+ is_iris = any(pattern in image_name.lower() for pattern in iris_patterns)
369
+ if not is_iris:
370
+ continue
371
+
372
+ # Determine edition from image name
373
+ if "light" in image_name.lower():
374
+ edition = "light"
375
+ elif "community" in image_name.lower():
376
+ edition = "community"
377
+ else:
378
+ edition = "enterprise"
379
+
380
+ # Get port mappings
381
+ ports = container.attrs.get("NetworkSettings", {}).get("Ports", {})
382
+ port_str = "-"
383
+ if ports and ports.get("1972/tcp"):
384
+ host_port = ports["1972/tcp"][0]["HostPort"]
385
+ port_str = f"{host_port}->1972"
386
+
387
+ # Calculate age
388
+ created = container.attrs.get("Created", "")
389
+ age_str = "unknown"
390
+ if created:
391
+ try:
392
+ # Parse ISO format timestamp
393
+ created_dt = datetime.fromisoformat(created.replace("Z", "+00:00"))
394
+ now = datetime.now(created_dt.tzinfo)
395
+ delta = now - created_dt
396
+ if delta.days > 0:
397
+ age_str = f"{delta.days}d"
398
+ elif delta.seconds > 3600:
399
+ age_str = f"{delta.seconds // 3600}h"
400
+ else:
401
+ age_str = f"{delta.seconds // 60}m"
402
+ except Exception:
403
+ pass
404
+
405
+ iris_containers.append(
406
+ {
407
+ "name": container.name,
408
+ "edition": edition,
409
+ "status": container.status,
410
+ "ports": port_str,
411
+ "age": age_str,
412
+ "image": image_name,
413
+ }
414
+ )
415
+
416
+ if output_format == "json":
417
+ import json as json_module
418
+
419
+ click.echo(json_module.dumps(iris_containers, indent=2))
420
+ else:
421
+ # Table format
422
+ if not iris_containers:
423
+ click.echo("No IRIS containers found.")
424
+ if not show_all:
425
+ click.echo("Use --all to include stopped containers.")
426
+ else:
427
+ # Print header
428
+ click.echo(f"{'NAME':<20} {'EDITION':<12} {'STATUS':<10} {'PORTS':<15} {'AGE':<6}")
429
+ click.echo("-" * 65)
430
+
431
+ for c in iris_containers:
432
+ status_color = "green" if c["status"] == "running" else "yellow"
433
+ click.echo(
434
+ f"{c['name']:<20} "
435
+ f"{c['edition']:<12} "
436
+ f"{click.style(c['status'], fg=status_color):<19} "
437
+ f"{c['ports']:<15} "
438
+ f"{c['age']:<6}"
439
+ )
440
+
441
+ except docker.errors.DockerException as e:
442
+ progress.print_error(f"Docker error: {e}")
443
+ ctx.exit(1)
444
+ except Exception as e:
445
+ progress.print_error(f"Error listing containers: {e}")
446
+ ctx.exit(1)
447
+
448
+
275
449
  @container_group.command(name="start")
276
450
  @click.argument("container_name", required=False, default="iris_db")
277
451
  @click.option(
@@ -657,7 +831,7 @@ def remove(ctx, container_name, force, volumes):
657
831
 
658
832
 
659
833
  @container_group.command(name="reset-password")
660
- @click.argument("container_name")
834
+ @click.argument("container_name", required=False, default="iris_db")
661
835
  @click.option("--user", default="_SYSTEM", help="Username to reset password for (default: _SYSTEM)")
662
836
  @click.option("--password", default="SYS", help="New password (default: SYS)")
663
837
  @click.option(
@@ -723,7 +897,7 @@ def reset_password_cmd(ctx, container_name, user, password, port):
723
897
 
724
898
 
725
899
  @container_group.command(name="test-connection")
726
- @click.argument("container_name")
900
+ @click.argument("container_name", required=False, default="iris_db")
727
901
  @click.option(
728
902
  "--namespace", default="USER", help="IRIS namespace to test connection to (default: USER)"
729
903
  )
@@ -812,7 +986,7 @@ def test_connection_cmd(ctx, container_name, namespace, username, password):
812
986
 
813
987
 
814
988
  @container_group.command(name="enable-callin")
815
- @click.argument("container_name")
989
+ @click.argument("container_name", required=False, default="iris_db")
816
990
  @click.option(
817
991
  "--timeout", type=int, default=30, help="Timeout in seconds for docker commands (default: 30)"
818
992
  )
@@ -51,7 +51,7 @@ class ContainerConfig(BaseModel):
51
51
  ... )
52
52
  """
53
53
 
54
- edition: Literal["community", "enterprise"] = Field(
54
+ edition: Literal["community", "enterprise", "light"] = Field(
55
55
  default="community", description="IRIS edition to use"
56
56
  )
57
57
  container_name: str = Field(
@@ -245,15 +245,21 @@ class ContainerConfig(BaseModel):
245
245
  return cls()
246
246
 
247
247
  def get_image_name(self) -> str:
248
+ """Get the Docker image name based on edition and configuration."""
248
249
  if self.image:
249
250
  return self.image
250
251
 
251
252
  if self.edition == "community":
252
-
253
- # Bug Fix #1: Community images use 'intersystemsdc/' prefix on Docker Hub
253
+ # Community images use 'intersystemsdc/' prefix on Docker Hub
254
254
  return f"intersystemsdc/iris-community:{self.image_tag}"
255
+ elif self.edition == "light":
256
+ # Light edition: caretdev/iris-community-light (85% smaller)
257
+ # Use latest-em for LTS stability
258
+ tag = self.image_tag if self.image_tag != "latest" else "latest-em"
259
+ return f"caretdev/iris-community-light:{tag}"
255
260
  else:
256
- return f"intersystems/iris:{self.image_tag}"
261
+ # Enterprise edition
262
+ return f"containers.intersystems.com/intersystems/iris:{self.image_tag}"
257
263
 
258
264
  def validate_volume_paths(self) -> List[str]:
259
265
  """
@@ -94,25 +94,107 @@ class IRISContainer(IRISBase):
94
94
  self._preconfigure_username: Optional[str] = None
95
95
 
96
96
  @classmethod
97
- def community(cls, image: Optional[str] = None, **kwargs) -> "IRISContainer":
98
- """Create a Community Edition container."""
97
+ def community(
98
+ cls, image: Optional[str] = None, version: str = "latest", **kwargs
99
+ ) -> "IRISContainer":
100
+ """
101
+ Create a Community Edition container.
102
+
103
+ Auto-detects architecture (ARM64 vs x86) and pulls the appropriate image.
104
+
105
+ Args:
106
+ image: Docker image to use. If None, auto-detects based on architecture.
107
+ version: Image version tag. Options: 'latest', '2025.1', '2025.2', etc.
108
+ """
99
109
  if image is None:
100
110
  import platform as platform_module
101
111
 
102
112
  if platform_module.machine() == "arm64":
103
- image = "containers.intersystems.com/intersystems/iris-community:2025.1"
113
+ # ARM64 (Apple Silicon) - use official InterSystems registry
114
+ tag = version if version != "latest" else "2025.1"
115
+ image = f"containers.intersystems.com/intersystems/iris-community:{tag}"
104
116
  else:
105
- image = "intersystemsdc/iris-community:latest"
117
+ # x86_64 - use Docker Hub community image
118
+ image = f"intersystemsdc/iris-community:{version}"
106
119
  return cls(image=image, **kwargs)
107
120
 
108
121
  @classmethod
109
- def enterprise(cls, license_key: str, image: Optional[str] = None, **kwargs) -> "IRISContainer":
110
- """Create an Enterprise Edition container."""
122
+ def enterprise(
123
+ cls, license_key: Optional[str] = None, image: Optional[str] = None, **kwargs
124
+ ) -> "IRISContainer":
125
+ """
126
+ Create an Enterprise Edition container.
127
+
128
+ Args:
129
+ license_key: Path to iris.key file. If None, checks IRIS_LICENSE_KEY env var.
130
+ image: Docker image to use. Defaults to containers.intersystems.com/intersystems/iris:latest
131
+
132
+ Raises:
133
+ ValueError: If no license key is provided or found in environment.
134
+ """
135
+ import os
136
+
137
+ if license_key is None:
138
+ license_key = os.environ.get("IRIS_LICENSE_KEY")
139
+
140
+ if license_key is None:
141
+ raise ValueError(
142
+ "Enterprise edition requires a license key.\n"
143
+ "\n"
144
+ "Provide license_key parameter or set IRIS_LICENSE_KEY environment variable:\n"
145
+ " IRISContainer.enterprise(license_key='/path/to/iris.key')\n"
146
+ " # or\n"
147
+ " export IRIS_LICENSE_KEY=/path/to/iris.key"
148
+ )
149
+
150
+ if not os.path.exists(license_key):
151
+ raise ValueError(
152
+ f"License key file not found: {license_key}\n"
153
+ "\n"
154
+ "Verify the license key path exists and is readable."
155
+ )
156
+
111
157
  if image is None:
112
158
  image = "containers.intersystems.com/intersystems/iris:latest"
159
+
113
160
  container = cls(image=image, **kwargs)
161
+ # Mount license key into container
162
+ container._license_key_path = license_key
114
163
  return container
115
164
 
165
+ @classmethod
166
+ def light(
167
+ cls, image: Optional[str] = None, version: str = "latest", **kwargs
168
+ ) -> "IRISContainer":
169
+ """
170
+ Create a Light Edition container optimized for CI/CD.
171
+
172
+ Light edition is ~85% smaller than full Community edition (~580MB vs ~3.5GB).
173
+ It removes Interoperability, Management Portal, DeepSee, and web components.
174
+ DBAPI, JDBC, and ODBC connectivity are fully supported.
175
+
176
+ Args:
177
+ image: Docker image to use. Defaults to caretdev/iris-community-light.
178
+ version: Image version tag. Options: 'latest', 'latest-em' (LTS), '2025.1', etc.
179
+
180
+ Best for:
181
+ - CI/CD pipelines
182
+ - Microservices
183
+ - Automated testing
184
+ - SQL-only workloads
185
+
186
+ Not supported:
187
+ - Interoperability/Ensemble
188
+ - Management Portal
189
+ - DeepSee/BI
190
+ - CSP/REST web framework
191
+ """
192
+ if image is None:
193
+ # Use latest-em for LTS stability, or allow version override
194
+ tag = version if version != "latest" else "latest-em"
195
+ image = f"caretdev/iris-community-light:{tag}"
196
+ return cls(image=image, **kwargs)
197
+
116
198
  def with_name(self, name: str) -> "IRISContainer":
117
199
  """Set the container name."""
118
200
  self._container_name = name
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: iris-devtester
3
- Version: 1.9.3
3
+ Version: 1.10.0
4
4
  Summary: Battle-tested InterSystems IRIS infrastructure utilities for Python development
5
5
  Author-email: InterSystems Community <community@intersystems.com>
6
6
  Maintainer-email: Thomas Dyar <thomas.dyar@intersystems.com>
@@ -107,9 +107,17 @@ def test_connection():
107
107
  assert cursor.fetchone()[0] == 1
108
108
  ```
109
109
 
110
- ## Container API
110
+ ## Container Editions
111
111
 
112
- ### Basic Usage
112
+ Three canonical container editions are available:
113
+
114
+ | Edition | Size | Use Case | Image |
115
+ |---------|------|----------|-------|
116
+ | **Community** | ~972MB | Development, testing | `intersystemsdc/iris-community` |
117
+ | **Enterprise** | ~1GB+ | Production testing | `containers.intersystems.com/intersystems/iris` |
118
+ | **Light** | **~580MB** | CI/CD pipelines | `caretdev/iris-community-light` |
119
+
120
+ ### Python API
113
121
  ```python
114
122
  from iris_devtester.containers import IRISContainer
115
123
 
@@ -117,11 +125,42 @@ from iris_devtester.containers import IRISContainer
117
125
  with IRISContainer.community() as iris:
118
126
  conn = iris.get_connection()
119
127
 
128
+ # Light Edition (85% smaller, for CI/CD)
129
+ with IRISContainer.light() as iris:
130
+ conn = iris.get_connection()
131
+
120
132
  # Enterprise Edition (requires license)
121
133
  with IRISContainer.enterprise(license_key="/path/to/iris.key") as iris:
122
134
  conn = iris.get_connection()
135
+
136
+ # Specify version
137
+ with IRISContainer.community(version="2025.1") as iris:
138
+ conn = iris.get_connection()
139
+ ```
140
+
141
+ ### CLI Usage
142
+ ```bash
143
+ # Community (default)
144
+ iris-devtester container up
145
+
146
+ # Light edition for CI/CD
147
+ iris-devtester container up --edition light
148
+
149
+ # Enterprise edition with license
150
+ iris-devtester container up --edition enterprise --license /path/to/iris.key
151
+
152
+ # List running IRIS containers
153
+ iris-devtester container list
123
154
  ```
124
155
 
156
+ ### Light Edition Details
157
+
158
+ The Light edition removes components unnecessary for SQL-only workloads:
159
+ - **Removed**: Interoperability/Ensemble, Management Portal, DeepSee/BI, CSP/REST
160
+ - **Kept**: SQL engine, DBAPI, JDBC, ODBC, SQLAlchemy-IRIS support
161
+
162
+ Perfect for microservices, automated testing, and Python/SQL pipelines.
163
+
125
164
  ### Builder Methods
126
165
  ```python
127
166
  # Set a custom container name (for debugging, logs, multiple containers)
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "iris-devtester"
7
- version = "1.9.3"
7
+ version = "1.10.0"
8
8
  description = "Battle-tested InterSystems IRIS infrastructure utilities for Python development"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -379,12 +379,23 @@ class TestContainerConfigImageName:
379
379
  def test_get_image_name_enterprise_latest(self):
380
380
  """Test image name for enterprise edition with latest tag."""
381
381
  config = ContainerConfig(edition="enterprise", license_key="TEST-KEY", image_tag="latest")
382
- assert config.get_image_name() == "intersystems/iris:latest"
382
+ assert config.get_image_name() == "containers.intersystems.com/intersystems/iris:latest"
383
383
 
384
384
  def test_get_image_name_enterprise_specific_tag(self):
385
385
  """Test image name for enterprise edition with specific tag."""
386
386
  config = ContainerConfig(edition="enterprise", license_key="TEST-KEY", image_tag="2024.1")
387
- assert config.get_image_name() == "intersystems/iris:2024.1"
387
+ assert config.get_image_name() == "containers.intersystems.com/intersystems/iris:2024.1"
388
+
389
+ def test_get_image_name_light_latest(self):
390
+ """Test image name for light edition with latest tag."""
391
+ config = ContainerConfig(edition="light", image_tag="latest")
392
+ # Light uses latest-em for LTS stability
393
+ assert config.get_image_name() == "caretdev/iris-community-light:latest-em"
394
+
395
+ def test_get_image_name_light_specific_tag(self):
396
+ """Test image name for light edition with specific tag."""
397
+ config = ContainerConfig(edition="light", image_tag="2025.1")
398
+ assert config.get_image_name() == "caretdev/iris-community-light:2025.1"
388
399
 
389
400
 
390
401
  class TestContainerConfigVolumeValidation: