iris-devtester 1.19.2__tar.gz → 1.19.3__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 (271) hide show
  1. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/CHANGELOG.md +6 -0
  2. {iris_devtester-1.19.2/iris_devtester.egg-info → iris_devtester-1.19.3}/PKG-INFO +1 -1
  3. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/__init__.py +1 -1
  4. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/containers/cpf_manager.py +6 -3
  5. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/containers/iris_container.py +33 -7
  6. {iris_devtester-1.19.2 → iris_devtester-1.19.3/iris_devtester.egg-info}/PKG-INFO +1 -1
  7. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/pyproject.toml +1 -1
  8. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/unit/test_cpf_manager.py +4 -2
  9. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/unit/test_iris_container.py +79 -35
  10. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/unit/test_wait_strategies.py +1 -34
  11. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/unit/utils/test_dbapi_compat.py +1 -1
  12. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/AGENTS.md +0 -0
  13. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/CLAUDE.md +0 -0
  14. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/CONSTITUTION.md +0 -0
  15. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/LICENSE +0 -0
  16. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/MANIFEST.in +0 -0
  17. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/README.md +0 -0
  18. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/GETTING_STARTED.md +0 -0
  19. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/LANGCHAIN_INTEGRATION_QUICKSTART.md +0 -0
  20. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/ROADMAP.md +0 -0
  21. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/SQL_VS_OBJECTSCRIPT.md +0 -0
  22. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/TROUBLESHOOTING.md +0 -0
  23. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/WHATS_NEW_v1.4.0.md +0 -0
  24. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/archive/AGENTIC_SANDBOX_ENHANCEMENT_REPORT.md +0 -0
  25. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/archive/IMPACT_ANALYSIS.md +0 -0
  26. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/archive/IRIS_DEVTESTER_POSITIONING_REPORT.md +0 -0
  27. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/archive/LANGCHAIN_INTEGRATION_STRATEGY.md +0 -0
  28. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/archive/LANGCHAIN_INTEGRATION_TEST_RESULTS.md +0 -0
  29. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/archive/PHASE_2_PLAN.md +0 -0
  30. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/archive/RAG_TEMPLATES_ANALYSIS.md +0 -0
  31. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/archive/README.md +0 -0
  32. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/archive/STRATEGIC_ROADMAP_SUMMARY.md +0 -0
  33. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/archive/feature-009-refactor-plan.md +0 -0
  34. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/development/BUG_REPORT.md +0 -0
  35. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/development/EXTRACTION_SUMMARY.md +0 -0
  36. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/development/FEATURE_006_SUMMARY.md +0 -0
  37. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/development/PHASE2_RESULTS.md +0 -0
  38. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/development/PRE_PUBLISH_REVIEW.md +0 -0
  39. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/development/PROGRESS.md +0 -0
  40. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/development/PYPI_READINESS.md +0 -0
  41. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/development/SESSION-INTEGRATION-TESTS.md +0 -0
  42. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/development/SESSION-SUMMARY.md +0 -0
  43. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/development/STATUS-002-PIVOTED.md +0 -0
  44. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/development/STATUS-003-COMPLETE.md +0 -0
  45. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/development/STATUS.md +0 -0
  46. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/development/V1_COMPLETION_PLAN.md +0 -0
  47. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/development/V1_RELEASE_SUMMARY.md +0 -0
  48. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/features/WSGI-ASGI-SERVER-SETUP.md +0 -0
  49. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/features/agent-skills.md +0 -0
  50. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/features/dat-fixtures.md +0 -0
  51. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/features/docker-compose.md +0 -0
  52. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/features/performance-monitoring.md +0 -0
  53. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/features/testcontainers.md +0 -0
  54. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/learnings/api-contract-synchronization.md +0 -0
  55. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/learnings/callin-service-requirement.md +0 -0
  56. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/learnings/cpf-merge-and-container-restarts.md +0 -0
  57. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/learnings/dat-fixtures-docker-exec-pattern.md +0 -0
  58. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/learnings/dat-restore-database-isolation-problem.md +0 -0
  59. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/learnings/dbapi-bulk-insert-performance-issue.md +0 -0
  60. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/learnings/dbapi-objectscript-limitation.md +0 -0
  61. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/learnings/dbapi-password-reset-limitation.md +0 -0
  62. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/learnings/dbapi-private-module-myth.md +0 -0
  63. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/learnings/docker-hub-image-naming.md +0 -0
  64. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/learnings/embedded-python-considerations.md +0 -0
  65. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/learnings/feature-002-pivot-summary.md +0 -0
  66. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/learnings/integration-test-dbapi-limitation.md +0 -0
  67. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/learnings/iris-backup-patterns.md +0 -0
  68. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/learnings/iris-connection-access-denied-bug.md +0 -0
  69. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/learnings/iris-container-dind-port-mapping.md +0 -0
  70. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/learnings/iris-container-graceful-shutdown.md +0 -0
  71. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/learnings/iris-container-performance.md +0 -0
  72. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/learnings/iris-container-readiness.md +0 -0
  73. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/learnings/iris-container-volume-permissions.md +0 -0
  74. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/learnings/iris-docker-sdk-environment-variables.md +0 -0
  75. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/learnings/iris-performance-monitoring-landscape.md +0 -0
  76. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/learnings/iris-security-users-api.md +0 -0
  77. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/learnings/irishealth-editions.md +0 -0
  78. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/learnings/namespace-sql-vs-iris-connect.md +0 -0
  79. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/learnings/password-reset-changeflag-fix.md +0 -0
  80. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/learnings/rag-templates-production-patterns.md +0 -0
  81. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/learnings/sql-task-manager-operations.md +0 -0
  82. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/learnings/test-isolation-fix-summary.md +0 -0
  83. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/learnings/test-isolation-investigation.md +0 -0
  84. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/learnings/testcontainers-ryuk-lifecycle.md +0 -0
  85. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/docs/troubleshooting/table-not-found.md +0 -0
  86. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/examples/01_quickstart.py +0 -0
  87. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/examples/02_connection_management.py +0 -0
  88. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/examples/04_pytest_fixtures.py +0 -0
  89. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/examples/05_ci_cd.py +0 -0
  90. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/examples/08_auto_discovery.py +0 -0
  91. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/examples/09_enterprise.py +0 -0
  92. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/examples/10_docker_compose_integration.py +0 -0
  93. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/examples/langchain_integration_example.py +0 -0
  94. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/__main__.py +0 -0
  95. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/cli/__init__.py +0 -0
  96. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/cli/__main__.py +0 -0
  97. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/cli/connection_commands.py +0 -0
  98. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/cli/container.py +0 -0
  99. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/cli/container_commands.py +0 -0
  100. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/cli/dev_commands.py +0 -0
  101. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/cli/fixture_commands.py +0 -0
  102. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/config/__init__.py +0 -0
  103. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/config/auto_discovery.py +0 -0
  104. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/config/container_config.py +0 -0
  105. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/config/container_state.py +0 -0
  106. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/config/defaults.py +0 -0
  107. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/config/discovery.py +0 -0
  108. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/config/models.py +0 -0
  109. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/config/presets.py +0 -0
  110. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/config/yaml_loader.py +0 -0
  111. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/connections/__init__.py +0 -0
  112. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/connections/auto_discovery.py +0 -0
  113. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/connections/connection.py +0 -0
  114. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/connections/cursor_wrapper.py +0 -0
  115. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/connections/dbapi.py +0 -0
  116. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/connections/jdbc.py +0 -0
  117. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/connections/manager.py +0 -0
  118. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/connections/models.py +0 -0
  119. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/connections/retry.py +0 -0
  120. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/containers/__init__.py +0 -0
  121. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/containers/connection_info.py +0 -0
  122. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/containers/dev_instance.py +0 -0
  123. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/containers/models.py +0 -0
  124. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/containers/monitor_utils.py +0 -0
  125. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/containers/monitoring.py +0 -0
  126. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/containers/performance.py +0 -0
  127. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/containers/validation.py +0 -0
  128. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/containers/wait_strategies.py +0 -0
  129. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/diagnostics.py +0 -0
  130. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/fixtures/__init__.py +0 -0
  131. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/fixtures/creator.py +0 -0
  132. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/fixtures/loader.py +0 -0
  133. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/fixtures/manifest.py +0 -0
  134. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/fixtures/obj_export.py +0 -0
  135. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/fixtures/validator.py +0 -0
  136. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/integrations/__init__.py +0 -0
  137. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/integrations/langchain.py +0 -0
  138. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/ports/__init__.py +0 -0
  139. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/ports/assignment.py +0 -0
  140. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/ports/exceptions.py +0 -0
  141. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/ports/registry.py +0 -0
  142. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/testing/__init__.py +0 -0
  143. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/testing/fixtures.py +0 -0
  144. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/testing/helpers.py +0 -0
  145. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/testing/models.py +0 -0
  146. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/testing/schema_reset.py +0 -0
  147. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/utils/__init__.py +0 -0
  148. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/utils/container_port.py +0 -0
  149. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/utils/container_status.py +0 -0
  150. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/utils/dbapi_compat.py +0 -0
  151. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/utils/enable_callin.py +0 -0
  152. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/utils/health_checks.py +0 -0
  153. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/utils/iris_container_adapter.py +0 -0
  154. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/utils/namespace.py +0 -0
  155. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/utils/password.py +0 -0
  156. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/utils/progress.py +0 -0
  157. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester/utils/test_connection.py +0 -0
  158. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester.egg-info/SOURCES.txt +0 -0
  159. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester.egg-info/dependency_links.txt +0 -0
  160. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester.egg-info/entry_points.txt +0 -0
  161. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester.egg-info/requires.txt +0 -0
  162. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/iris_devtester.egg-info/top_level.txt +0 -0
  163. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/setup.cfg +0 -0
  164. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/__init__.py +0 -0
  165. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/conftest.py +0 -0
  166. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/contract/__init__.py +0 -0
  167. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/contract/cli/test_container_logs_contract.py +0 -0
  168. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/contract/cli/test_container_remove_contract.py +0 -0
  169. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/contract/cli/test_container_restart_contract.py +0 -0
  170. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/contract/cli/test_container_start_contract.py +0 -0
  171. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/contract/cli/test_container_status_contract.py +0 -0
  172. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/contract/cli/test_container_stop_contract.py +0 -0
  173. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/contract/cli/test_container_up_contract.py +0 -0
  174. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/contract/test_031_diagnostics.py +0 -0
  175. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/contract/test_032_health_check.py +0 -0
  176. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/contract/test_033_health_editions.py +0 -0
  177. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/contract/test_034_cpf_password.py +0 -0
  178. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/contract/test_035_graceful_shutdown.py +0 -0
  179. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/contract/test_agent_skills.py +0 -0
  180. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/contract/test_cli_container_commands.py +0 -0
  181. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/contract/test_cli_fixture_commands.py +0 -0
  182. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/contract/test_cli_ux_contract.py +0 -0
  183. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/contract/test_connection_api.py +0 -0
  184. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/contract/test_container_api.py +0 -0
  185. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/contract/test_container_integration_contract.py +0 -0
  186. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/contract/test_container_status_api.py +0 -0
  187. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/contract/test_container_validation_api.py +0 -0
  188. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/contract/test_dind_port_mapping.py +0 -0
  189. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/contract/test_enable_callin_api.py +0 -0
  190. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/contract/test_fixture_creator_api.py +0 -0
  191. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/contract/test_fixture_loader_api.py +0 -0
  192. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/contract/test_fixture_validator_api.py +0 -0
  193. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/contract/test_iriscontainer_attach.py +0 -0
  194. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/contract/test_legacy_package_contract.py +0 -0
  195. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/contract/test_modern_package_contract.py +0 -0
  196. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/contract/test_monitoring_config_api.py +0 -0
  197. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/contract/test_package_detection.py +0 -0
  198. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/contract/test_port_registry_contract.py +0 -0
  199. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/contract/test_preconfig_contract.py +0 -0
  200. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/contract/test_reset_verification_contract.py +0 -0
  201. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/contract/test_resource_monitoring_api.py +0 -0
  202. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/contract/test_retry_logic_contract.py +0 -0
  203. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/contract/test_task_manager_api.py +0 -0
  204. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/contract/test_test_connection_api.py +0 -0
  205. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/contract/test_testing_fixtures_api.py +0 -0
  206. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/e2e/__init__.py +0 -0
  207. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/e2e/test_port_registry_e2e.py +0 -0
  208. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/e2e/test_skill_workflow.py +0 -0
  209. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/integration/__init__.py +0 -0
  210. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/integration/conftest.py +0 -0
  211. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/integration/ports/__init__.py +0 -0
  212. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/integration/ports/test_manual_port_override.py +0 -0
  213. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/integration/ports/test_multi_project_isolation.py +0 -0
  214. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/integration/ports/test_port_exhaustion.py +0 -0
  215. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/integration/ports/test_port_persistence.py +0 -0
  216. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/integration/ports/test_stale_cleanup.py +0 -0
  217. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/integration/test_bug_fixes.py +0 -0
  218. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/integration/test_bug_fixes_011.py +0 -0
  219. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/integration/test_cli_container_integration.py +0 -0
  220. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/integration/test_connection_info_integration.py +0 -0
  221. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/integration/test_connection_integration.py +0 -0
  222. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/integration/test_container_health_monitor.py +0 -0
  223. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/integration/test_container_status_integration.py +0 -0
  224. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/integration/test_container_validation.py +0 -0
  225. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/integration/test_cpf_merge.py +0 -0
  226. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/integration/test_cpf_presets.py +0 -0
  227. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/integration/test_cpf_security.py +0 -0
  228. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/integration/test_custom_user_remediation.py +0 -0
  229. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/integration/test_dev_instance.py +0 -0
  230. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/integration/test_enable_callin_integration.py +0 -0
  231. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/integration/test_fixture_export_patterns.py +0 -0
  232. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/integration/test_fixture_performance.py +0 -0
  233. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/integration/test_fixture_refresh.py +0 -0
  234. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/integration/test_fixtures_integration.py +0 -0
  235. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/integration/test_implicit_namespace.py +0 -0
  236. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/integration/test_iriscontainer_attach_integration.py +0 -0
  237. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/integration/test_monitor_utils_integration.py +0 -0
  238. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/integration/test_monitoring_integration.py +0 -0
  239. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/integration/test_password_preconfig_integration.py +0 -0
  240. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/integration/test_password_reset_both_editions.py +0 -0
  241. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/integration/test_password_reset_integration.py +0 -0
  242. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/integration/test_password_reset_macos.py +0 -0
  243. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/integration/test_password_reset_timing.py +0 -0
  244. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/integration/test_password_reset_validation.py +0 -0
  245. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/integration/test_proactive_password_reset.py +0 -0
  246. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/integration/test_real_world_problems.py +0 -0
  247. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/integration/test_reliable_password_reset.py +0 -0
  248. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/integration/test_test_connection_integration.py +0 -0
  249. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/unit/__init__.py +0 -0
  250. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/unit/config/test_config_hierarchy.py +0 -0
  251. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/unit/config/test_container_config.py +0 -0
  252. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/unit/config/test_yaml_loader.py +0 -0
  253. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/unit/test_auto_discovery.py +0 -0
  254. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/unit/test_config_discovery.py +0 -0
  255. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/unit/test_connection_fallback.py +0 -0
  256. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/unit/test_connection_info.py +0 -0
  257. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/unit/test_dev_instance_logic.py +0 -0
  258. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/unit/test_iris_config.py +0 -0
  259. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/unit/test_iris_connection_info.py +0 -0
  260. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/unit/test_manifest.py +0 -0
  261. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/unit/test_monitoring_policy.py +0 -0
  262. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/unit/test_namespace_utils.py +0 -0
  263. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/unit/test_password_preconfig.py +0 -0
  264. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/unit/test_password_preconfig_unit.py +0 -0
  265. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/unit/test_performance_metrics.py +0 -0
  266. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/unit/test_resource_thresholds.py +0 -0
  267. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/unit/test_retry.py +0 -0
  268. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/unit/test_schema_models.py +0 -0
  269. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/unit/test_schema_reset_logic.py +0 -0
  270. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/unit/test_validation_results.py +0 -0
  271. {iris_devtester-1.19.2 → iris_devtester-1.19.3}/tests/unit/utils/test_iris_container_adapter.py +0 -0
@@ -5,6 +5,12 @@ 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.19.3] - 2026-08-02 - Fix attach() ignoring explicit port override
9
+
10
+ ### Fixed
11
+
12
+ - **`IRISContainer.attach()` ignores explicit port, always uses docker port lookup** (`containers/iris_container.py`): `attach()` had no port parameter. It always derived the host-side SuperServer port from `docker port <container> 1972/tcp`, which fails on macOS Docker Desktop with irishealth enterprise: Docker Desktop NAT rewrites the source IP from `127.0.0.1` to a bridge address, so IRIS RSTs the connection even though the port binding exists. The user-supplied `IVG_PORT=31971` was silently ignored. Added `port: Optional[int]` to `attach()`; when supplied, `_mapped_port` is pinned immediately so `get_mapped_port(1972)` returns it without calling `get_exposed_port()`. Also reads `IVG_PORT` and `IRIS_PORT` env vars as fallbacks when `port=` is not passed explicitly.
13
+
8
14
  ## [1.19.2] - 2026-07-30 - Fix connect_function ImportError when module absent from sys.modules
9
15
 
10
16
  ### Fixed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: iris-devtester
3
- Version: 1.19.2
3
+ Version: 1.19.3
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.19.2"
29
+ __version__ = "1.19.3"
30
30
  __author__ = "InterSystems Community"
31
31
  __license__ = "MIT"
32
32
 
@@ -40,15 +40,18 @@ class TempCPFManager:
40
40
  file_path = os.path.abspath(tmp.name)
41
41
  self._temp_files.add(file_path)
42
42
 
43
- # Register for automatic cleanup
44
- weakref.finalize(self, self._delete_file, file_path)
43
+ # Register for automatic cleanup.
44
+ # Must use the unbound method — passing self._delete_file would hold
45
+ # a strong reference to self through the bound method, preventing GC.
46
+ weakref.finalize(self, TempCPFManager._delete_file, file_path)
45
47
 
46
48
  logger.debug(f"Created temporary CPF file: {file_path}")
47
49
  return file_path
48
50
  finally:
49
51
  tmp.close()
50
52
 
51
- def _delete_file(self, file_path: str):
53
+ @staticmethod
54
+ def _delete_file(file_path: str):
52
55
  """Internal helper to safely delete a file."""
53
56
  try:
54
57
  if os.path.exists(file_path):
@@ -350,7 +350,7 @@ class IRISContainer(IRISBase):
350
350
  return container
351
351
 
352
352
  @classmethod
353
- def attach(cls, container_name: str, **kwargs) -> "IRISContainer":
353
+ def attach(cls, container_name: str, port: Optional[int] = None, **kwargs) -> "IRISContainer":
354
354
  """
355
355
  Attach to an existing IRIS container by name.
356
356
 
@@ -360,18 +360,43 @@ class IRISContainer(IRISBase):
360
360
 
361
361
  Args:
362
362
  container_name: Name of the existing Docker container.
363
+ port: Host-side SuperServer port to use instead of the Docker-inspected
364
+ binding. Required when Docker Desktop NAT rewrites the source IP and
365
+ IRIS rejects the connection (macOS Docker Desktop with irishealth
366
+ enterprise). When supplied, the docker port lookup is skipped entirely.
367
+ Also honoured via ``IVG_PORT`` or ``IRIS_PORT`` environment variables
368
+ when ``port`` is not provided explicitly.
363
369
  **kwargs: Additional configuration (username, password, namespace).
364
370
 
365
371
  Returns:
366
372
  An IRISContainer instance attached to the existing container.
367
373
  """
374
+ import os
375
+
368
376
  if not container_name:
369
377
  raise ValueError("container_name must be a non-empty string")
370
378
 
379
+ # Resolve explicit port override: parameter > IVG_PORT > IRIS_PORT
380
+ if port is None:
381
+ for env_var in ("IVG_PORT", "IRIS_PORT"):
382
+ env_val = os.environ.get(env_var)
383
+ if env_val:
384
+ try:
385
+ port = int(env_val)
386
+ except ValueError:
387
+ pass
388
+ else:
389
+ break
390
+
371
391
  instance = cls(image="", name=container_name, **kwargs)
372
392
  instance._is_attached = True
373
393
  instance._container_name = container_name
374
394
 
395
+ # Pin the mapped port immediately so get_mapped_port(1972) never falls
396
+ # through to the docker port lookup, regardless of which code path below runs.
397
+ if port is not None:
398
+ instance._mapped_port = port
399
+
375
400
  try:
376
401
  import docker
377
402
 
@@ -379,15 +404,16 @@ class IRISContainer(IRISBase):
379
404
  container = client.containers.get(container_name)
380
405
  instance._container = container
381
406
 
382
- # If it's a mock container, we need to set these manually
383
407
  if not HAS_TESTCONTAINERS:
384
408
  instance.host = "localhost"
385
- # Try to find port from container ports
386
- ports = container.attrs.get("NetworkSettings", {}).get("Ports", {})
387
- if "1972/tcp" in ports and ports["1972/tcp"]:
388
- instance._mapped_port = int(ports["1972/tcp"][0]["HostPort"])
409
+ # Only read docker port binding when no explicit port was given
410
+ if port is None:
411
+ ports = container.attrs.get("NetworkSettings", {}).get("Ports", {})
412
+ if "1972/tcp" in ports and ports["1972/tcp"]:
413
+ instance._mapped_port = int(ports["1972/tcp"][0]["HostPort"])
389
414
  else:
390
- # testcontainers will handle discovery via get_config()
415
+ # testcontainers will handle host/port discovery via get_config(),
416
+ # but _mapped_port is already pinned above if port was supplied.
391
417
  instance.get_config()
392
418
 
393
419
  except Exception as e:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: iris-devtester
3
- Version: 1.19.2
3
+ Version: 1.19.3
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>
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "iris-devtester"
7
- version = "1.19.2"
7
+ version = "1.19.3"
8
8
  description = "Battle-tested InterSystems IRIS infrastructure utilities for Python development"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -36,5 +36,7 @@ def test_temp_cpf_cleanup_on_garbage_collection():
36
36
 
37
37
  gc.collect()
38
38
 
39
- if os.path.exists(file_path):
40
- os.unlink(file_path)
39
+ # If __del__ cleanup is broken, the file survives — assert before any manual fallback
40
+ assert not os.path.exists(file_path), (
41
+ f"TempCPFManager.__del__ did not clean up {file_path} after GC"
42
+ )
@@ -80,14 +80,13 @@ class TestIRISContainer:
80
80
  """Test that get_connection() method exists."""
81
81
  from iris_devtester.containers import IRISContainer
82
82
 
83
- # Check that class has this method
84
- assert hasattr(IRISContainer, "get_connection") or "get_connection" in dir(IRISContainer)
83
+ assert hasattr(IRISContainer, "get_connection") and callable(IRISContainer.get_connection)
85
84
 
86
85
  def test_wait_for_ready_method_exists(self):
87
86
  """Test that wait_for_ready() method exists."""
88
87
  from iris_devtester.containers import IRISContainer
89
88
 
90
- assert hasattr(IRISContainer, "wait_for_ready") or "wait_for_ready" in dir(IRISContainer)
89
+ assert hasattr(IRISContainer, "wait_for_ready") and callable(IRISContainer.wait_for_ready)
91
90
 
92
91
  def test_with_preconfigured_password_method_exists(self):
93
92
  """Test that with_preconfigured_password() method exists for password pre-configuration."""
@@ -107,22 +106,12 @@ class TestIRISContainer:
107
106
  """Test that get_config() method returns IRISConfig."""
108
107
  from iris_devtester.containers import IRISContainer
109
108
 
110
- # Should have method to get config
111
- assert hasattr(IRISContainer, "get_config") or "get_config" in dir(IRISContainer)
109
+ assert hasattr(IRISContainer, "get_config") and callable(IRISContainer.get_config)
112
110
 
113
111
 
114
112
  class TestIRISContainerIntegration:
115
113
  """Test IRIS container integration with other components."""
116
114
 
117
- @patch("iris_devtester.containers.iris_container.get_connection")
118
- def test_get_connection_uses_connection_manager(self, mock_get_connection):
119
- """Test that get_connection() integrates with connection manager."""
120
- from iris_devtester.containers import IRISContainer
121
-
122
- # This tests integration - actual implementation will vary
123
- # The key is that IRISContainer should use the connection manager
124
- assert mock_get_connection is not None
125
-
126
115
  def test_password_preconfig_sets_env_vars(self):
127
116
  """Test that password pre-configuration works via env vars."""
128
117
  from iris_devtester.containers import IRISContainer
@@ -135,25 +124,89 @@ class TestIRISContainerIntegration:
135
124
  assert container._preconfigure_password == "TestPass123"
136
125
  assert container._password == "TestPass123"
137
126
 
138
- def test_container_provides_connection_info(self):
139
- """Test that container can provide connection information."""
127
+ class TestAttachPortOverride:
128
+ """attach(port=) must skip docker port lookup and use the supplied port directly."""
129
+
130
+ def _make_mock_container(self, host_port: int = 31972):
131
+ """Return a mock Docker container whose port binding reports host_port."""
132
+ mock_container = MagicMock()
133
+ mock_container.attrs = {
134
+ "NetworkSettings": {
135
+ "Ports": {"1972/tcp": [{"HostPort": str(host_port)}]},
136
+ "Networks": {},
137
+ }
138
+ }
139
+ mock_container.name = "ivg-iris-enterprise"
140
+ # get_container_host_ip() is called by get_config() in the testcontainers path
141
+ mock_container.get_container_host_ip = MagicMock(return_value="localhost")
142
+ mock_container.get_exposed_port = MagicMock(return_value=host_port)
143
+ return mock_container
144
+
145
+ @patch("iris_devtester.containers.iris_container.IRISContainer.get_config")
146
+ @patch("docker.from_env")
147
+ def test_explicit_port_skips_docker_lookup(self, mock_docker, mock_get_config):
148
+ """When port= is supplied, _mapped_port must equal that port, not the docker binding."""
140
149
  from iris_devtester.containers import IRISContainer
141
150
 
142
- # Container should be able to provide host, port, namespace
143
- # This might be via get_config() or individual methods
144
- assert IRISContainer is not None
151
+ mock_client = MagicMock()
152
+ mock_docker.return_value = mock_client
153
+ mock_client.containers.get.return_value = self._make_mock_container(host_port=31972)
145
154
 
155
+ iris = IRISContainer.attach("ivg-iris-enterprise", port=31971)
146
156
 
147
- class TestIRISContainerConfiguration:
148
- """Test IRIS container configuration options."""
157
+ assert iris._mapped_port == 31971, (
158
+ f"Expected _mapped_port=31971 (explicit), got {iris._mapped_port}"
159
+ )
149
160
 
150
- def test_community_accepts_namespace_parameter(self):
151
- """Test that community() accepts namespace parameter."""
161
+ @patch("iris_devtester.containers.iris_container.IRISContainer.get_config")
162
+ @patch("docker.from_env")
163
+ def test_explicit_port_used_by_get_mapped_port(self, mock_docker, mock_get_config):
164
+ """get_mapped_port(1972) must return the explicit port, not the docker-inspected one."""
152
165
  from iris_devtester.containers import IRISContainer
153
166
 
154
- # Should accept namespace in some form
155
- # (might be via .with_namespace() or direct parameter)
156
- assert IRISContainer.community is not None
167
+ mock_client = MagicMock()
168
+ mock_docker.return_value = mock_client
169
+ mock_client.containers.get.return_value = self._make_mock_container(host_port=31972)
170
+
171
+ iris = IRISContainer.attach("ivg-iris-enterprise", port=31971)
172
+
173
+ assert iris.get_mapped_port(1972) == 31971
174
+
175
+ @patch("iris_devtester.containers.iris_container.IRISContainer.get_config")
176
+ @patch("docker.from_env")
177
+ def test_without_port_does_not_pin_mapped_port(self, mock_docker, mock_get_config):
178
+ """Without port=, _mapped_port is not pinned by attach() — port discovery deferred to get_config()."""
179
+ from iris_devtester.containers import IRISContainer
180
+
181
+ mock_client = MagicMock()
182
+ mock_docker.return_value = mock_client
183
+ mock_client.containers.get.return_value = self._make_mock_container(host_port=31972)
184
+
185
+ iris = IRISContainer.attach("ivg-iris-enterprise")
186
+
187
+ # No explicit port: _mapped_port is not set by attach itself (get_config handles discovery)
188
+ assert iris._mapped_port is None
189
+
190
+ @patch.dict("os.environ", {"IVG_PORT": "31971"})
191
+ @patch("iris_devtester.containers.iris_container.IRISContainer.get_config")
192
+ @patch("docker.from_env")
193
+ def test_ivg_port_env_var_respected(self, mock_docker, mock_get_config):
194
+ """IVG_PORT env var must be honoured as a port override in attach()."""
195
+ from iris_devtester.containers import IRISContainer
196
+
197
+ mock_client = MagicMock()
198
+ mock_docker.return_value = mock_client
199
+ mock_client.containers.get.return_value = self._make_mock_container(host_port=31972)
200
+
201
+ iris = IRISContainer.attach("ivg-iris-enterprise")
202
+
203
+ assert iris._mapped_port == 31971, (
204
+ f"IVG_PORT=31971 should override docker binding 31972, got {iris._mapped_port}"
205
+ )
206
+
207
+
208
+ class TestIRISContainerConfiguration:
209
+ """Test IRIS container configuration options."""
157
210
 
158
211
  def test_enterprise_requires_license_key(self):
159
212
  """Test that enterprise() raises error without license key."""
@@ -174,14 +227,5 @@ class TestIRISContainerConfiguration:
174
227
  with pytest.raises(ValueError, match="License key file not found"):
175
228
  IRISContainer.enterprise(license_key="/nonexistent/path/iris.key")
176
229
 
177
- def test_container_supports_custom_image(self):
178
- """Test that container supports custom IRIS images."""
179
- from iris_devtester.containers import IRISContainer
180
-
181
- # Should be able to specify custom image
182
- # (implementation may use .with_image() or similar)
183
- assert IRISContainer is not None
184
-
185
-
186
230
  if __name__ == "__main__":
187
231
  pytest.main([__file__, "-v"])
@@ -42,15 +42,6 @@ class TestIRISReadyWaitStrategy:
42
42
  # Should have method to check IRIS process
43
43
  assert hasattr(strategy, "check_iris_running") or hasattr(strategy, "wait_until_ready")
44
44
 
45
- def test_wait_strategy_checks_database_ready(self):
46
- """Test that wait strategy verifies database accepts queries."""
47
- from iris_devtester.containers.wait_strategies import IRISReadyWaitStrategy
48
-
49
- strategy = IRISReadyWaitStrategy()
50
-
51
- # Should be able to test database readiness
52
- assert strategy is not None
53
-
54
45
  def test_wait_strategy_timeout(self):
55
46
  """Test that wait strategy respects timeout."""
56
47
  from iris_devtester.containers.wait_strategies import IRISReadyWaitStrategy
@@ -60,29 +51,6 @@ class TestIRISReadyWaitStrategy:
60
51
  # Should have timeout attribute
61
52
  assert hasattr(strategy, "timeout") or hasattr(strategy, "_timeout")
62
53
 
63
- @patch("time.time")
64
- def test_wait_strategy_timeout_raises(self, mock_time):
65
- """Test that wait strategy raises on timeout."""
66
- from iris_devtester.containers.wait_strategies import IRISReadyWaitStrategy
67
-
68
- # Mock time to simulate timeout
69
- mock_time.side_effect = [0, 0, 100] # Start, check, timeout
70
-
71
- strategy = IRISReadyWaitStrategy(timeout=1)
72
-
73
- # Should implement timeout logic
74
- assert strategy is not None
75
-
76
- def test_wait_strategy_default_timeout(self):
77
- """Test that wait strategy has reasonable default timeout."""
78
- from iris_devtester.containers.wait_strategies import IRISReadyWaitStrategy
79
-
80
- strategy = IRISReadyWaitStrategy()
81
-
82
- # Should have a timeout (either attribute or parameter)
83
- assert strategy is not None
84
-
85
-
86
54
  class TestWaitForIRISReady:
87
55
  """Test convenience function for waiting for IRIS."""
88
56
 
@@ -103,8 +71,7 @@ class TestWaitForIRISReady:
103
71
 
104
72
  result = wait_for_iris_ready(host="localhost", port=1972, timeout=1)
105
73
 
106
- # Should attempt to connect to port
107
- assert isinstance(result, bool) or result is None
74
+ assert isinstance(result, bool), f"wait_for_iris_ready must return bool, got {type(result)}"
108
75
 
109
76
  def test_wait_function_with_timeout(self):
110
77
  """Test wait function respects timeout parameter."""
@@ -108,7 +108,7 @@ class TestSingletonPoisoning:
108
108
  assert not isinstance(info_after.connect_function, MagicMock), (
109
109
  "Singleton poisoning: connect_function is still a MagicMock after patch exited"
110
110
  )
111
- except Exception:
111
+ except (ImportError, dc.DBAPIPackageNotFoundError):
112
112
  # Package not installed in test env — that's fine, not the bug we're testing
113
113
  pass
114
114
 
File without changes