iris-devtester 1.12.3__tar.gz → 1.12.4__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 (252) hide show
  1. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/CHANGELOG.md +12 -0
  2. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/PKG-INFO +1 -1
  3. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/__init__.py +1 -1
  4. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/cli/container.py +36 -8
  5. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/ports/registry.py +42 -9
  6. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester.egg-info/PKG-INFO +1 -1
  7. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester.egg-info/SOURCES.txt +1 -0
  8. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/pyproject.toml +1 -1
  9. iris_devtester-1.12.4/tests/e2e/test_port_registry_e2e.py +96 -0
  10. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/AGENTS.md +0 -0
  11. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/CLAUDE.md +0 -0
  12. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/CONSTITUTION.md +0 -0
  13. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/LICENSE +0 -0
  14. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/MANIFEST.in +0 -0
  15. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/README.md +0 -0
  16. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/SKILL.md +0 -0
  17. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/GETTING_STARTED.md +0 -0
  18. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/LANGCHAIN_INTEGRATION_QUICKSTART.md +0 -0
  19. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/ROADMAP.md +0 -0
  20. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/SQL_VS_OBJECTSCRIPT.md +0 -0
  21. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/TROUBLESHOOTING.md +0 -0
  22. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/WHATS_NEW_v1.4.0.md +0 -0
  23. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/archive/AGENTIC_SANDBOX_ENHANCEMENT_REPORT.md +0 -0
  24. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/archive/IMPACT_ANALYSIS.md +0 -0
  25. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/archive/IRIS_DEVTESTER_POSITIONING_REPORT.md +0 -0
  26. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/archive/LANGCHAIN_INTEGRATION_STRATEGY.md +0 -0
  27. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/archive/LANGCHAIN_INTEGRATION_TEST_RESULTS.md +0 -0
  28. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/archive/PHASE_2_PLAN.md +0 -0
  29. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/archive/RAG_TEMPLATES_ANALYSIS.md +0 -0
  30. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/archive/README.md +0 -0
  31. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/archive/STRATEGIC_ROADMAP_SUMMARY.md +0 -0
  32. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/archive/feature-009-refactor-plan.md +0 -0
  33. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/development/BUG_REPORT.md +0 -0
  34. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/development/EXTRACTION_SUMMARY.md +0 -0
  35. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/development/FEATURE_006_SUMMARY.md +0 -0
  36. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/development/PHASE2_RESULTS.md +0 -0
  37. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/development/PRE_PUBLISH_REVIEW.md +0 -0
  38. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/development/PROGRESS.md +0 -0
  39. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/development/PYPI_READINESS.md +0 -0
  40. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/development/SESSION-INTEGRATION-TESTS.md +0 -0
  41. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/development/SESSION-SUMMARY.md +0 -0
  42. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/development/STATUS-002-PIVOTED.md +0 -0
  43. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/development/STATUS-003-COMPLETE.md +0 -0
  44. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/development/STATUS.md +0 -0
  45. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/development/V1_COMPLETION_PLAN.md +0 -0
  46. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/development/V1_RELEASE_SUMMARY.md +0 -0
  47. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/features/WSGI-ASGI-SERVER-SETUP.md +0 -0
  48. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/features/agent-skills.md +0 -0
  49. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/features/dat-fixtures.md +0 -0
  50. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/features/docker-compose.md +0 -0
  51. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/features/performance-monitoring.md +0 -0
  52. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/features/testcontainers.md +0 -0
  53. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/learnings/api-contract-synchronization.md +0 -0
  54. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/learnings/callin-service-requirement.md +0 -0
  55. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/learnings/cpf-merge-and-container-restarts.md +0 -0
  56. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/learnings/dat-fixtures-docker-exec-pattern.md +0 -0
  57. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/learnings/dat-restore-database-isolation-problem.md +0 -0
  58. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/learnings/dbapi-bulk-insert-performance-issue.md +0 -0
  59. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/learnings/dbapi-objectscript-limitation.md +0 -0
  60. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/learnings/dbapi-password-reset-limitation.md +0 -0
  61. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/learnings/dbapi-private-module-myth.md +0 -0
  62. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/learnings/docker-hub-image-naming.md +0 -0
  63. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/learnings/embedded-python-considerations.md +0 -0
  64. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/learnings/feature-002-pivot-summary.md +0 -0
  65. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/learnings/integration-test-dbapi-limitation.md +0 -0
  66. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/learnings/iris-backup-patterns.md +0 -0
  67. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/learnings/iris-connection-access-denied-bug.md +0 -0
  68. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/learnings/iris-container-performance.md +0 -0
  69. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/learnings/iris-container-readiness.md +0 -0
  70. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/learnings/iris-docker-sdk-environment-variables.md +0 -0
  71. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/learnings/iris-performance-monitoring-landscape.md +0 -0
  72. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/learnings/iris-security-users-api.md +0 -0
  73. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/learnings/password-reset-changeflag-fix.md +0 -0
  74. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/learnings/rag-templates-production-patterns.md +0 -0
  75. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/learnings/sql-task-manager-operations.md +0 -0
  76. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/learnings/test-isolation-fix-summary.md +0 -0
  77. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/learnings/test-isolation-investigation.md +0 -0
  78. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/docs/learnings/testcontainers-ryuk-lifecycle.md +0 -0
  79. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/examples/01_quickstart.py +0 -0
  80. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/examples/02_connection_management.py +0 -0
  81. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/examples/04_pytest_fixtures.py +0 -0
  82. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/examples/05_ci_cd.py +0 -0
  83. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/examples/08_auto_discovery.py +0 -0
  84. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/examples/09_enterprise.py +0 -0
  85. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/examples/10_docker_compose_integration.py +0 -0
  86. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/examples/langchain_integration_example.py +0 -0
  87. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/__main__.py +0 -0
  88. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/cli/__init__.py +0 -0
  89. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/cli/__main__.py +0 -0
  90. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/cli/connection_commands.py +0 -0
  91. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/cli/container_commands.py +0 -0
  92. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/cli/dev_commands.py +0 -0
  93. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/cli/fixture_commands.py +0 -0
  94. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/config/__init__.py +0 -0
  95. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/config/auto_discovery.py +0 -0
  96. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/config/container_config.py +0 -0
  97. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/config/container_state.py +0 -0
  98. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/config/defaults.py +0 -0
  99. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/config/discovery.py +0 -0
  100. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/config/models.py +0 -0
  101. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/config/presets.py +0 -0
  102. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/config/yaml_loader.py +0 -0
  103. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/connections/__init__.py +0 -0
  104. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/connections/auto_discovery.py +0 -0
  105. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/connections/connection.py +0 -0
  106. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/connections/dbapi.py +0 -0
  107. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/connections/jdbc.py +0 -0
  108. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/connections/manager.py +0 -0
  109. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/connections/models.py +0 -0
  110. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/connections/retry.py +0 -0
  111. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/containers/__init__.py +0 -0
  112. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/containers/cpf_manager.py +0 -0
  113. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/containers/dev_instance.py +0 -0
  114. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/containers/iris_container.py +0 -0
  115. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/containers/models.py +0 -0
  116. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/containers/monitor_utils.py +0 -0
  117. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/containers/monitoring.py +0 -0
  118. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/containers/performance.py +0 -0
  119. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/containers/validation.py +0 -0
  120. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/containers/wait_strategies.py +0 -0
  121. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/fixtures/__init__.py +0 -0
  122. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/fixtures/creator.py +0 -0
  123. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/fixtures/loader.py +0 -0
  124. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/fixtures/manifest.py +0 -0
  125. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/fixtures/obj_export.py +0 -0
  126. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/fixtures/validator.py +0 -0
  127. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/integrations/__init__.py +0 -0
  128. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/integrations/langchain.py +0 -0
  129. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/ports/__init__.py +0 -0
  130. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/ports/assignment.py +0 -0
  131. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/ports/exceptions.py +0 -0
  132. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/testing/__init__.py +0 -0
  133. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/testing/fixtures.py +0 -0
  134. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/testing/helpers.py +0 -0
  135. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/testing/models.py +0 -0
  136. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/testing/schema_reset.py +0 -0
  137. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/utils/__init__.py +0 -0
  138. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/utils/container_port.py +0 -0
  139. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/utils/container_status.py +0 -0
  140. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/utils/dbapi_compat.py +0 -0
  141. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/utils/enable_callin.py +0 -0
  142. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/utils/health_checks.py +0 -0
  143. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/utils/iris_container_adapter.py +0 -0
  144. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/utils/namespace.py +0 -0
  145. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/utils/password.py +0 -0
  146. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/utils/progress.py +0 -0
  147. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester/utils/test_connection.py +0 -0
  148. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester.egg-info/dependency_links.txt +0 -0
  149. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester.egg-info/entry_points.txt +0 -0
  150. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester.egg-info/requires.txt +0 -0
  151. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/iris_devtester.egg-info/top_level.txt +0 -0
  152. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/setup.cfg +0 -0
  153. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/__init__.py +0 -0
  154. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/conftest.py +0 -0
  155. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/contract/__init__.py +0 -0
  156. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/contract/cli/test_container_logs_contract.py +0 -0
  157. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/contract/cli/test_container_remove_contract.py +0 -0
  158. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/contract/cli/test_container_restart_contract.py +0 -0
  159. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/contract/cli/test_container_start_contract.py +0 -0
  160. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/contract/cli/test_container_status_contract.py +0 -0
  161. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/contract/cli/test_container_stop_contract.py +0 -0
  162. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/contract/cli/test_container_up_contract.py +0 -0
  163. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/contract/test_agent_skills.py +0 -0
  164. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/contract/test_cli_container_commands.py +0 -0
  165. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/contract/test_cli_fixture_commands.py +0 -0
  166. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/contract/test_connection_api.py +0 -0
  167. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/contract/test_container_api.py +0 -0
  168. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/contract/test_container_integration_contract.py +0 -0
  169. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/contract/test_container_status_api.py +0 -0
  170. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/contract/test_container_validation_api.py +0 -0
  171. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/contract/test_enable_callin_api.py +0 -0
  172. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/contract/test_fixture_creator_api.py +0 -0
  173. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/contract/test_fixture_loader_api.py +0 -0
  174. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/contract/test_fixture_validator_api.py +0 -0
  175. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/contract/test_iriscontainer_attach.py +0 -0
  176. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/contract/test_legacy_package_contract.py +0 -0
  177. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/contract/test_modern_package_contract.py +0 -0
  178. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/contract/test_monitoring_config_api.py +0 -0
  179. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/contract/test_package_detection.py +0 -0
  180. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/contract/test_port_registry_contract.py +0 -0
  181. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/contract/test_preconfig_contract.py +0 -0
  182. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/contract/test_reset_verification_contract.py +0 -0
  183. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/contract/test_resource_monitoring_api.py +0 -0
  184. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/contract/test_retry_logic_contract.py +0 -0
  185. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/contract/test_task_manager_api.py +0 -0
  186. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/contract/test_test_connection_api.py +0 -0
  187. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/contract/test_testing_fixtures_api.py +0 -0
  188. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/e2e/__init__.py +0 -0
  189. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/e2e/test_skill_workflow.py +0 -0
  190. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/integration/__init__.py +0 -0
  191. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/integration/conftest.py +0 -0
  192. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/integration/ports/__init__.py +0 -0
  193. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/integration/ports/test_manual_port_override.py +0 -0
  194. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/integration/ports/test_multi_project_isolation.py +0 -0
  195. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/integration/ports/test_port_exhaustion.py +0 -0
  196. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/integration/ports/test_port_persistence.py +0 -0
  197. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/integration/ports/test_stale_cleanup.py +0 -0
  198. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/integration/test_bug_fixes.py +0 -0
  199. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/integration/test_bug_fixes_011.py +0 -0
  200. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/integration/test_cli_container_integration.py +0 -0
  201. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/integration/test_connection_integration.py +0 -0
  202. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/integration/test_container_health_monitor.py +0 -0
  203. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/integration/test_container_status_integration.py +0 -0
  204. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/integration/test_container_validation.py +0 -0
  205. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/integration/test_cpf_merge.py +0 -0
  206. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/integration/test_cpf_presets.py +0 -0
  207. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/integration/test_cpf_security.py +0 -0
  208. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/integration/test_custom_user_remediation.py +0 -0
  209. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/integration/test_dev_instance.py +0 -0
  210. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/integration/test_enable_callin_integration.py +0 -0
  211. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/integration/test_fixture_export_patterns.py +0 -0
  212. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/integration/test_fixture_performance.py +0 -0
  213. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/integration/test_fixture_refresh.py +0 -0
  214. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/integration/test_fixtures_integration.py +0 -0
  215. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/integration/test_implicit_namespace.py +0 -0
  216. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/integration/test_iriscontainer_attach_integration.py +0 -0
  217. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/integration/test_monitor_utils_integration.py +0 -0
  218. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/integration/test_monitoring_integration.py +0 -0
  219. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/integration/test_password_preconfig_integration.py +0 -0
  220. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/integration/test_password_reset_both_editions.py +0 -0
  221. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/integration/test_password_reset_integration.py +0 -0
  222. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/integration/test_password_reset_macos.py +0 -0
  223. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/integration/test_password_reset_timing.py +0 -0
  224. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/integration/test_password_reset_validation.py +0 -0
  225. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/integration/test_proactive_password_reset.py +0 -0
  226. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/integration/test_real_world_problems.py +0 -0
  227. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/integration/test_reliable_password_reset.py +0 -0
  228. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/integration/test_test_connection_integration.py +0 -0
  229. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/unit/__init__.py +0 -0
  230. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/unit/config/test_config_hierarchy.py +0 -0
  231. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/unit/config/test_container_config.py +0 -0
  232. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/unit/config/test_yaml_loader.py +0 -0
  233. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/unit/test_auto_discovery.py +0 -0
  234. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/unit/test_config_discovery.py +0 -0
  235. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/unit/test_connection_fallback.py +0 -0
  236. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/unit/test_connection_info.py +0 -0
  237. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/unit/test_cpf_manager.py +0 -0
  238. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/unit/test_dev_instance_logic.py +0 -0
  239. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/unit/test_iris_config.py +0 -0
  240. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/unit/test_iris_container.py +0 -0
  241. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/unit/test_manifest.py +0 -0
  242. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/unit/test_monitoring_policy.py +0 -0
  243. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/unit/test_namespace_utils.py +0 -0
  244. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/unit/test_password_preconfig.py +0 -0
  245. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/unit/test_password_preconfig_unit.py +0 -0
  246. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/unit/test_performance_metrics.py +0 -0
  247. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/unit/test_resource_thresholds.py +0 -0
  248. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/unit/test_retry.py +0 -0
  249. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/unit/test_schema_models.py +0 -0
  250. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/unit/test_validation_results.py +0 -0
  251. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/unit/test_wait_strategies.py +0 -0
  252. {iris_devtester-1.12.3 → iris_devtester-1.12.4}/tests/unit/utils/test_iris_container_adapter.py +0 -0
@@ -5,6 +5,18 @@ All notable changes to iris-devtester will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.12.4] - 2026-02-15 - Port Management Reliability
9
+
10
+ ### Fixed
11
+
12
+ - **Host Port Availability**: Enhanced `PortRegistry` to perform live TCP socket checks on the host. This prevents `idt` from assigning ports that are occupied by non-Docker processes.
13
+ - **Auto-Port Fallback**: Improved CLI logic to correctly trigger auto-assignment when the default port (1972) is taken, even if it's the configured default.
14
+ - **Web Port Scaling**: Fixed logic for proportional adjustment of the WebServer port when the SuperServer port is shifted.
15
+
16
+ ### Added
17
+
18
+ - **E2E Coverage**: Added full end-to-end coverage for port conflict scenarios in `tests/e2e/test_port_registry_e2e.py`.
19
+
8
20
  ## [1.12.3] - 2026-02-15 - Documentation Sync
9
21
 
10
22
  ### Changed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: iris-devtester
3
- Version: 1.12.3
3
+ Version: 1.12.4
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>
@@ -26,7 +26,7 @@ LangChain Integration:
26
26
  ... # Build your RAG app...
27
27
  """
28
28
 
29
- __version__ = "1.12.3"
29
+ __version__ = "1.12.4"
30
30
  __author__ = "InterSystems Community"
31
31
  __license__ = "MIT"
32
32
 
@@ -172,24 +172,37 @@ def up(ctx, config, name, edition, image, license_key, detach, timeout, cpf, aut
172
172
  project_path = str(Path.cwd().absolute())
173
173
 
174
174
  click.echo(f"⏳ Engaging port registry for project: {project_path}")
175
- # Use current config port as preferred
176
- preferred = container_config.superserver_port
177
- assignment = registry.assign_port(project_path, preferred_port=preferred)
175
+
176
+ # Use current config port as preferred ONLY if it's NOT the default 1972
177
+ preferred = container_config.superserver_port if container_config.superserver_port != 1972 else None
178
+
179
+ assignment = registry.assign_port(
180
+ project_path, preferred_port=preferred, allow_fallback=True
181
+ )
178
182
 
179
- if assignment.port != preferred:
183
+ if assignment.port != preferred and preferred is not None:
180
184
  click.echo(
181
185
  click.style(
182
186
  f"⚠️ Port {preferred} was unavailable. Assigned {assignment.port} instead.",
183
187
  fg="yellow",
184
188
  )
185
189
  )
190
+ elif assignment.assignment_type == "auto" and preferred is None:
191
+ if assignment.port != 1972:
192
+ click.echo(
193
+ click.style(
194
+ f"⚠️ Default port 1972 was unavailable. Assigned {assignment.port} instead.",
195
+ fg="yellow",
196
+ )
197
+ )
198
+ else:
199
+ click.echo(f"✓ Port {assignment.port} assigned and verified.")
186
200
  else:
187
201
  click.echo(f"✓ Port {assignment.port} assigned and verified.")
188
202
 
189
203
  container_config.superserver_port = assignment.port
190
204
  # Update web port proportionally if it's the default
191
205
  if container_config.webserver_port == 52773:
192
- # Simple logic: if superserver shifted by N, shift webserver by N
193
206
  offset = assignment.port - 1972
194
207
  if offset > 0:
195
208
  container_config.webserver_port = 52773 + offset
@@ -565,16 +578,31 @@ def start(ctx, container_name, config, timeout, auto_port):
565
578
  project_path = str(Path.cwd().absolute())
566
579
 
567
580
  click.echo(f"⏳ Engaging port registry for project: {project_path}")
568
- preferred = container_config.superserver_port
569
- assignment = registry.assign_port(project_path, preferred_port=preferred)
581
+
582
+ # Use current config port as preferred ONLY if it's NOT the default 1972
583
+ preferred = container_config.superserver_port if container_config.superserver_port != 1972 else None
584
+
585
+ assignment = registry.assign_port(
586
+ project_path, preferred_port=preferred, allow_fallback=True
587
+ )
570
588
 
571
- if assignment.port != preferred:
589
+ if assignment.port != preferred and preferred is not None:
572
590
  click.echo(
573
591
  click.style(
574
592
  f"⚠️ Port {preferred} was unavailable. Assigned {assignment.port} instead.",
575
593
  fg="yellow",
576
594
  )
577
595
  )
596
+ elif assignment.assignment_type == "auto" and preferred is None:
597
+ if assignment.port != 1972:
598
+ click.echo(
599
+ click.style(
600
+ f"⚠️ Default port 1972 was unavailable. Assigned {assignment.port} instead.",
601
+ fg="yellow",
602
+ )
603
+ )
604
+ else:
605
+ click.echo(f"✓ Port {assignment.port} assigned and verified.")
578
606
  else:
579
607
  click.echo(f"✓ Port {assignment.port} assigned and verified.")
580
608
 
@@ -5,6 +5,7 @@ Provides atomic file-based persistence with file locking for concurrent safety.
5
5
  """
6
6
 
7
7
  import json
8
+ import socket as _socket
8
9
  from datetime import datetime
9
10
  from pathlib import Path
10
11
  from typing import List, Literal, Optional
@@ -56,6 +57,7 @@ class PortRegistry:
56
57
  self,
57
58
  project_path: str,
58
59
  preferred_port: Optional[int] = None,
60
+ allow_fallback: bool = False,
59
61
  ) -> PortAssignment:
60
62
  """
61
63
  Assign port to project (idempotent - returns existing if already assigned).
@@ -63,13 +65,14 @@ class PortRegistry:
63
65
  Args:
64
66
  project_path: Absolute path to project directory
65
67
  preferred_port: Optional manual port override
68
+ allow_fallback: If True and preferred_port is occupied, fall back to auto-assignment
66
69
 
67
70
  Returns:
68
71
  PortAssignment with assigned port
69
72
 
70
73
  Raises:
71
74
  PortExhaustedError: All ports in range are in use
72
- PortConflictError: preferred_port already assigned to different project
75
+ PortConflictError: preferred_port already assigned to different project (and fallback disabled)
73
76
  PortAssignmentTimeoutError: File lock timeout (>5 seconds)
74
77
  """
75
78
  lock = FileLock(self.lock_path, timeout=5)
@@ -85,11 +88,21 @@ class PortRegistry:
85
88
  return existing
86
89
 
87
90
  # Determine port to assign
91
+ port = None
92
+ assignment_type: Literal["auto", "manual"] = "auto"
93
+
88
94
  if preferred_port is not None:
89
- # Manual port assignment
90
- self._validate_port_available(assignments, preferred_port, project_path)
91
- port = preferred_port
92
- assignment_type: Literal["auto", "manual"] = "manual"
95
+ try:
96
+ # Manual port assignment
97
+ self._validate_port_available(assignments, preferred_port, project_path)
98
+ port = preferred_port
99
+ assignment_type = "manual"
100
+ except PortConflictError:
101
+ if not allow_fallback:
102
+ raise
103
+ # Fallback to auto-assignment
104
+ port = self._find_available_port(assignments)
105
+ assignment_type = "auto"
93
106
  else:
94
107
  # Auto-assignment
95
108
  port = self._find_available_port(assignments)
@@ -283,8 +296,8 @@ class PortRegistry:
283
296
  """
284
297
  Find first available port in range.
285
298
 
286
- Checks both registry assignments AND actual Docker port bindings
287
- to avoid conflicts with external containers.
299
+ Checks registry assignments, actual Docker port bindings, AND
300
+ live host port availability via socket.
288
301
 
289
302
  Raises:
290
303
  PortExhaustedError: All ports in range are in use
@@ -298,11 +311,20 @@ class PortRegistry:
298
311
 
299
312
  for port in range(self.min_port, self.max_port + 1):
300
313
  if port not in used_ports:
301
- return port
314
+ # FINAL CHECK: Is the port actually free on the host?
315
+ if self._is_host_port_free(port):
316
+ return port
302
317
 
303
318
  # All ports exhausted
304
319
  raise PortExhaustedError(port_range=self.port_range, current_assignments=assignments)
305
320
 
321
+ def _is_host_port_free(self, port: int) -> bool:
322
+ """Check if a port is actually free on the host using a socket."""
323
+ with _socket.socket(_socket.AF_INET, _socket.SOCK_STREAM) as s:
324
+ s.settimeout(0.1)
325
+ # connect_ex returns 0 if connection succeeded (port is in use)
326
+ return s.connect_ex(("localhost", port)) != 0
327
+
306
328
  def _get_docker_bound_ports(self) -> set:
307
329
  """
308
330
  Get ports currently bound by Docker containers.
@@ -352,8 +374,9 @@ class PortRegistry:
352
374
  Validate that preferred port is available.
353
375
 
354
376
  Raises:
355
- PortConflictError: Port already assigned to different project
377
+ PortConflictError: Port already assigned to different project or occupied on host
356
378
  """
379
+ # 1. Check registry assignments
357
380
  for assignment in assignments:
358
381
  if assignment.port == port and assignment.status == "active":
359
382
  raise PortConflictError(
@@ -363,3 +386,13 @@ class PortRegistry:
363
386
  existing_assignment_type=assignment.assignment_type,
364
387
  existing_status=assignment.status,
365
388
  )
389
+
390
+ # 2. Check live host availability
391
+ if not self._is_host_port_free(port):
392
+ raise PortConflictError(
393
+ requested_port=port,
394
+ requested_project=requesting_project,
395
+ existing_project="Unknown (Occupied by non-Docker process on host)",
396
+ existing_assignment_type="manual",
397
+ existing_status="active",
398
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: iris-devtester
3
- Version: 1.12.3
3
+ Version: 1.12.4
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>
@@ -183,6 +183,7 @@ tests/contract/cli/test_container_status_contract.py
183
183
  tests/contract/cli/test_container_stop_contract.py
184
184
  tests/contract/cli/test_container_up_contract.py
185
185
  tests/e2e/__init__.py
186
+ tests/e2e/test_port_registry_e2e.py
186
187
  tests/e2e/test_skill_workflow.py
187
188
  tests/integration/__init__.py
188
189
  tests/integration/conftest.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "iris-devtester"
7
- version = "1.12.3"
7
+ version = "1.12.4"
8
8
  description = "Battle-tested InterSystems IRIS infrastructure utilities for Python development"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -0,0 +1,96 @@
1
+ """End-to-end coverage for the port registry auto-port fallback."""
2
+
3
+ import re
4
+ import socket
5
+ import uuid
6
+ from pathlib import Path
7
+
8
+ import pytest
9
+ from click.testing import CliRunner
10
+
11
+ from iris_devtester.cli import main
12
+ from iris_devtester.config import IRISConfig
13
+ from iris_devtester.connections import get_connection
14
+ from iris_devtester.ports.registry import PortRegistry
15
+ from iris_devtester.utils.iris_container_adapter import IRISContainerManager
16
+
17
+
18
+ @pytest.mark.e2e
19
+ @pytest.mark.integration
20
+ def test_port_registry_auto_port_fallback():
21
+ """Ensure CLI falls back to a different port when 1972 is occupied."""
22
+
23
+ container_name = f"e2e-port-test-{uuid.uuid4().hex[:8]}"
24
+ project_path = str(Path.cwd().absolute())
25
+ runner = CliRunner()
26
+
27
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
28
+ sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
29
+ sock.bind(("127.0.0.1", 1972))
30
+ sock.listen(1)
31
+
32
+ assigned_port = None
33
+
34
+ try:
35
+ result = runner.invoke(
36
+ main,
37
+ ["container", "up", "--auto-port", "--name", container_name],
38
+ catch_exceptions=False,
39
+ )
40
+
41
+ assert result.exit_code == 0, f"CLI failed:\n{result.output}"
42
+
43
+ # Check for conflict warning
44
+ assert "unavailable" in result.output.lower(), "Conflict warning missing"
45
+ assert "Assigned" in result.output, "Assignment message missing"
46
+
47
+ assigned_match = re.search(r"Assigned (\d+) instead", result.output)
48
+ assert assigned_match, "Assigned port not reported"
49
+
50
+ assigned_port = int(assigned_match.group(1))
51
+ assert assigned_port != 1972
52
+
53
+ superserver_match = re.search(
54
+ r"SuperServer: localhost:(\d+)", result.output
55
+ )
56
+ assert superserver_match, "Connection info missing superserver port"
57
+ assert assigned_port == int(superserver_match.group(1))
58
+
59
+ config = IRISConfig(
60
+ host="localhost",
61
+ port=assigned_port,
62
+ namespace="USER",
63
+ username="_SYSTEM",
64
+ password="SYS",
65
+ container_name=container_name,
66
+ )
67
+
68
+ conn = get_connection(config=config)
69
+ cursor = conn.cursor()
70
+ try:
71
+ cursor.execute("SELECT $NAMESPACE AS namespace")
72
+ assert cursor.fetchone() is not None
73
+ finally:
74
+ cursor.close()
75
+ conn.close()
76
+
77
+ finally:
78
+ sock.close()
79
+
80
+ container = IRISContainerManager.get_existing(container_name)
81
+ if container:
82
+ try:
83
+ container.stop(timeout=5)
84
+ except Exception:
85
+ pass
86
+ try:
87
+ container.remove(force=True)
88
+ except Exception:
89
+ pass
90
+
91
+ try:
92
+ PortRegistry().release_port(project_path)
93
+ except KeyError:
94
+ pass
95
+ except Exception:
96
+ pass
File without changes