iris-devtester 1.19.0__tar.gz → 1.19.2__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.
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/CHANGELOG.md +18 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/CLAUDE.md +16 -0
- {iris_devtester-1.19.0/iris_devtester.egg-info → iris_devtester-1.19.2}/PKG-INFO +1 -1
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/__init__.py +1 -1
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/utils/dbapi_compat.py +40 -7
- {iris_devtester-1.19.0 → iris_devtester-1.19.2/iris_devtester.egg-info}/PKG-INFO +1 -1
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester.egg-info/SOURCES.txt +1 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/pyproject.toml +1 -1
- iris_devtester-1.19.2/tests/unit/utils/test_dbapi_compat.py +183 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/AGENTS.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/CONSTITUTION.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/LICENSE +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/MANIFEST.in +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/README.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/GETTING_STARTED.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/LANGCHAIN_INTEGRATION_QUICKSTART.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/ROADMAP.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/SQL_VS_OBJECTSCRIPT.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/TROUBLESHOOTING.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/WHATS_NEW_v1.4.0.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/archive/AGENTIC_SANDBOX_ENHANCEMENT_REPORT.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/archive/IMPACT_ANALYSIS.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/archive/IRIS_DEVTESTER_POSITIONING_REPORT.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/archive/LANGCHAIN_INTEGRATION_STRATEGY.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/archive/LANGCHAIN_INTEGRATION_TEST_RESULTS.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/archive/PHASE_2_PLAN.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/archive/RAG_TEMPLATES_ANALYSIS.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/archive/README.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/archive/STRATEGIC_ROADMAP_SUMMARY.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/archive/feature-009-refactor-plan.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/development/BUG_REPORT.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/development/EXTRACTION_SUMMARY.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/development/FEATURE_006_SUMMARY.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/development/PHASE2_RESULTS.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/development/PRE_PUBLISH_REVIEW.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/development/PROGRESS.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/development/PYPI_READINESS.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/development/SESSION-INTEGRATION-TESTS.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/development/SESSION-SUMMARY.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/development/STATUS-002-PIVOTED.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/development/STATUS-003-COMPLETE.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/development/STATUS.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/development/V1_COMPLETION_PLAN.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/development/V1_RELEASE_SUMMARY.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/features/WSGI-ASGI-SERVER-SETUP.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/features/agent-skills.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/features/dat-fixtures.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/features/docker-compose.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/features/performance-monitoring.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/features/testcontainers.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/api-contract-synchronization.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/callin-service-requirement.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/cpf-merge-and-container-restarts.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/dat-fixtures-docker-exec-pattern.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/dat-restore-database-isolation-problem.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/dbapi-bulk-insert-performance-issue.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/dbapi-objectscript-limitation.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/dbapi-password-reset-limitation.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/dbapi-private-module-myth.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/docker-hub-image-naming.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/embedded-python-considerations.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/feature-002-pivot-summary.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/integration-test-dbapi-limitation.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/iris-backup-patterns.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/iris-connection-access-denied-bug.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/iris-container-dind-port-mapping.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/iris-container-graceful-shutdown.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/iris-container-performance.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/iris-container-readiness.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/iris-container-volume-permissions.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/iris-docker-sdk-environment-variables.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/iris-performance-monitoring-landscape.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/iris-security-users-api.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/irishealth-editions.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/namespace-sql-vs-iris-connect.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/password-reset-changeflag-fix.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/rag-templates-production-patterns.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/sql-task-manager-operations.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/test-isolation-fix-summary.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/test-isolation-investigation.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/testcontainers-ryuk-lifecycle.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/troubleshooting/table-not-found.md +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/examples/01_quickstart.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/examples/02_connection_management.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/examples/04_pytest_fixtures.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/examples/05_ci_cd.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/examples/08_auto_discovery.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/examples/09_enterprise.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/examples/10_docker_compose_integration.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/examples/langchain_integration_example.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/__main__.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/cli/__init__.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/cli/__main__.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/cli/connection_commands.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/cli/container.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/cli/container_commands.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/cli/dev_commands.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/cli/fixture_commands.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/config/__init__.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/config/auto_discovery.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/config/container_config.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/config/container_state.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/config/defaults.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/config/discovery.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/config/models.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/config/presets.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/config/yaml_loader.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/connections/__init__.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/connections/auto_discovery.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/connections/connection.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/connections/cursor_wrapper.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/connections/dbapi.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/connections/jdbc.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/connections/manager.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/connections/models.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/connections/retry.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/containers/__init__.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/containers/connection_info.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/containers/cpf_manager.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/containers/dev_instance.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/containers/iris_container.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/containers/models.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/containers/monitor_utils.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/containers/monitoring.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/containers/performance.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/containers/validation.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/containers/wait_strategies.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/diagnostics.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/fixtures/__init__.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/fixtures/creator.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/fixtures/loader.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/fixtures/manifest.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/fixtures/obj_export.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/fixtures/validator.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/integrations/__init__.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/integrations/langchain.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/ports/__init__.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/ports/assignment.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/ports/exceptions.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/ports/registry.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/testing/__init__.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/testing/fixtures.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/testing/helpers.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/testing/models.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/testing/schema_reset.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/utils/__init__.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/utils/container_port.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/utils/container_status.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/utils/enable_callin.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/utils/health_checks.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/utils/iris_container_adapter.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/utils/namespace.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/utils/password.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/utils/progress.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester/utils/test_connection.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester.egg-info/dependency_links.txt +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester.egg-info/entry_points.txt +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester.egg-info/requires.txt +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/iris_devtester.egg-info/top_level.txt +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/setup.cfg +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/__init__.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/conftest.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/contract/__init__.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/contract/cli/test_container_logs_contract.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/contract/cli/test_container_remove_contract.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/contract/cli/test_container_restart_contract.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/contract/cli/test_container_start_contract.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/contract/cli/test_container_status_contract.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/contract/cli/test_container_stop_contract.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/contract/cli/test_container_up_contract.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/contract/test_031_diagnostics.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/contract/test_032_health_check.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/contract/test_033_health_editions.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/contract/test_034_cpf_password.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/contract/test_035_graceful_shutdown.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/contract/test_agent_skills.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/contract/test_cli_container_commands.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/contract/test_cli_fixture_commands.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/contract/test_cli_ux_contract.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/contract/test_connection_api.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/contract/test_container_api.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/contract/test_container_integration_contract.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/contract/test_container_status_api.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/contract/test_container_validation_api.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/contract/test_dind_port_mapping.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/contract/test_enable_callin_api.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/contract/test_fixture_creator_api.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/contract/test_fixture_loader_api.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/contract/test_fixture_validator_api.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/contract/test_iriscontainer_attach.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/contract/test_legacy_package_contract.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/contract/test_modern_package_contract.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/contract/test_monitoring_config_api.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/contract/test_package_detection.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/contract/test_port_registry_contract.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/contract/test_preconfig_contract.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/contract/test_reset_verification_contract.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/contract/test_resource_monitoring_api.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/contract/test_retry_logic_contract.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/contract/test_task_manager_api.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/contract/test_test_connection_api.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/contract/test_testing_fixtures_api.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/e2e/__init__.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/e2e/test_port_registry_e2e.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/e2e/test_skill_workflow.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/integration/__init__.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/integration/conftest.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/integration/ports/__init__.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/integration/ports/test_manual_port_override.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/integration/ports/test_multi_project_isolation.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/integration/ports/test_port_exhaustion.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/integration/ports/test_port_persistence.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/integration/ports/test_stale_cleanup.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/integration/test_bug_fixes.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/integration/test_bug_fixes_011.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/integration/test_cli_container_integration.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/integration/test_connection_info_integration.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/integration/test_connection_integration.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/integration/test_container_health_monitor.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/integration/test_container_status_integration.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/integration/test_container_validation.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/integration/test_cpf_merge.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/integration/test_cpf_presets.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/integration/test_cpf_security.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/integration/test_custom_user_remediation.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/integration/test_dev_instance.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/integration/test_enable_callin_integration.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/integration/test_fixture_export_patterns.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/integration/test_fixture_performance.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/integration/test_fixture_refresh.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/integration/test_fixtures_integration.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/integration/test_implicit_namespace.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/integration/test_iriscontainer_attach_integration.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/integration/test_monitor_utils_integration.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/integration/test_monitoring_integration.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/integration/test_password_preconfig_integration.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/integration/test_password_reset_both_editions.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/integration/test_password_reset_integration.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/integration/test_password_reset_macos.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/integration/test_password_reset_timing.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/integration/test_password_reset_validation.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/integration/test_proactive_password_reset.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/integration/test_real_world_problems.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/integration/test_reliable_password_reset.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/integration/test_test_connection_integration.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/unit/__init__.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/unit/config/test_config_hierarchy.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/unit/config/test_container_config.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/unit/config/test_yaml_loader.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/unit/test_auto_discovery.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/unit/test_config_discovery.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/unit/test_connection_fallback.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/unit/test_connection_info.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/unit/test_cpf_manager.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/unit/test_dev_instance_logic.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/unit/test_iris_config.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/unit/test_iris_connection_info.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/unit/test_iris_container.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/unit/test_manifest.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/unit/test_monitoring_policy.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/unit/test_namespace_utils.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/unit/test_password_preconfig.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/unit/test_password_preconfig_unit.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/unit/test_performance_metrics.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/unit/test_resource_thresholds.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/unit/test_retry.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/unit/test_schema_models.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/unit/test_schema_reset_logic.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/unit/test_validation_results.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/unit/test_wait_strategies.py +0 -0
- {iris_devtester-1.19.0 → iris_devtester-1.19.2}/tests/unit/utils/test_iris_container_adapter.py +0 -0
|
@@ -5,6 +5,22 @@ 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.2] - 2026-07-30 - Fix connect_function ImportError when module absent from sys.modules
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- **`DBAPIPackageInfo.connect_function` raises after `patch.dict` exit** (`utils/dbapi_compat.py`): `patch.dict(sys.modules, ...)` deletes keys that were absent before the patch when it exits — the common case for unit tests that mock `intersystems_iris` before it has been imported. The 1.19.1 `@property` resolved the MagicMock poisoning but left `sys.modules.get()` returning `None` in this scenario, raising `ImportError: IRIS DBAPI module 'intersystems_iris' is no longer in sys.modules`. The module was importable the whole time. Fixed by falling back to `importlib.import_module(import_path)` when `sys.modules.get()` returns `None`.
|
|
13
|
+
|
|
14
|
+
## [1.19.1] - 2026-07-30 - Fix dbapi_compat singleton poisoning under test mocks
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
|
|
18
|
+
- **`DBAPIConnectionAdapter` singleton mock poisoning** (`utils/dbapi_compat.py`): when a test patched `intersystems_iris` via `patch.dict(sys.modules, ...)` and the adapter singleton was first built during that patch, the adapter held a reference to the mock's `connect` function for the rest of the process — after `sys.modules` was fully restored. Downstream tests then silently operated against a `MagicMock` connection. Fixed by making `DBAPIPackageInfo.connect_function` a `@property` that resolves the function from `sys.modules` on every call instead of binding it at detection time. The per-call cost is a single `sys.modules` lookup and `getattr` — negligible against opening a socket.
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
|
|
22
|
+
- **`dbapi_compat.reset_adapter()`**: public function to clear the singleton so tests can force re-detection after their patch exits. Previously the only workaround was reaching into the private `_adapter` global from `conftest.py`. Added to `__all__`.
|
|
23
|
+
|
|
8
24
|
## [1.19.0] - 2026-07-19 - iris-agentic-dev Handoff Contract + Discrete Skills
|
|
9
25
|
|
|
10
26
|
### Added
|
|
@@ -983,6 +999,7 @@ v1.4.3 added connection-based verification with retry logic, which is valuable f
|
|
|
983
999
|
- `iris_devtester/utils/iris_container_adapter.py` (Docker SDK volume application)
|
|
984
1000
|
- `iris_devtester/config/container_config.py` (validate_volume_paths method)
|
|
985
1001
|
- **Example**:
|
|
1002
|
+
|
|
986
1003
|
```yaml
|
|
987
1004
|
volumes:
|
|
988
1005
|
- ./workspace:/external/workspace # Read-write
|
|
@@ -1087,6 +1104,7 @@ v1.4.3 added connection-based verification with retry logic, which is valuable f
|
|
|
1087
1104
|
- **Impact**: Configuration-defined volumes now work correctly (previously ignored)
|
|
1088
1105
|
- **Location**: `iris_devtester/utils/iris_container_adapter.py:52-58`
|
|
1089
1106
|
- **Example**:
|
|
1107
|
+
|
|
1090
1108
|
```yaml
|
|
1091
1109
|
volumes:
|
|
1092
1110
|
- ./data:/external # Read-write mount
|
|
@@ -123,3 +123,19 @@ reset), 033 (health/ai_hub editions), 034 (CPF-first password strategy).
|
|
|
123
123
|
|
|
124
124
|
`~/ws/rag-templates/` contains original production code this was extracted from. Consult
|
|
125
125
|
it when the current implementation is unclear — especially `common/iris_connection_manager.py`.
|
|
126
|
+
|
|
127
|
+
<!-- codebase-memory-mcp: Code Discovery Protocol -->
|
|
128
|
+
## Code Discovery Protocol (codebase-memory-mcp)
|
|
129
|
+
|
|
130
|
+
**ALWAYS use `codebase-memory-mcp` tools FIRST for any code exploration:**
|
|
131
|
+
|
|
132
|
+
- `search_graph(name_pattern/label/qn_pattern)` — find functions, classes, routes
|
|
133
|
+
- `trace_path(function_name, mode=calls|data_flow|cross_service)` — call chains
|
|
134
|
+
- `get_code_snippet(qualified_name)` — exact symbol source with precise line ranges
|
|
135
|
+
- `query_graph(query)` — complex Cypher patterns across the codebase graph
|
|
136
|
+
- `get_architecture(aspects)` — project structure overview
|
|
137
|
+
- `search_code(pattern)` — graph-augmented text search
|
|
138
|
+
|
|
139
|
+
Use `Grep`/`Glob`/`Read` freely for text, configs, and non-code files, and always
|
|
140
|
+
`Read` a file before editing it. If the project is not indexed yet, run
|
|
141
|
+
`index_repository` first.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: iris-devtester
|
|
3
|
-
Version: 1.19.
|
|
3
|
+
Version: 1.19.2
|
|
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>
|
|
@@ -29,9 +29,10 @@ Logging Levels:
|
|
|
29
29
|
|
|
30
30
|
import importlib.metadata
|
|
31
31
|
import logging
|
|
32
|
+
import sys
|
|
32
33
|
import time
|
|
33
34
|
from dataclasses import dataclass
|
|
34
|
-
from typing import Any,
|
|
35
|
+
from typing import Any, Optional
|
|
35
36
|
|
|
36
37
|
from packaging import version
|
|
37
38
|
|
|
@@ -45,18 +46,38 @@ class DBAPIPackageInfo:
|
|
|
45
46
|
|
|
46
47
|
Attributes:
|
|
47
48
|
package_name: One of "intersystems-irispython" or "intersystems-iris"
|
|
48
|
-
import_path: Module import path (e.g., "intersystems_iris
|
|
49
|
+
import_path: Module import path (e.g., "intersystems_iris")
|
|
49
50
|
version: Package version (e.g., "5.3.0")
|
|
50
|
-
|
|
51
|
+
connect_attr: Attribute name of the connect function on the module (usually "connect")
|
|
51
52
|
detection_time_ms: Time taken to detect package in milliseconds
|
|
52
53
|
"""
|
|
53
54
|
|
|
54
55
|
package_name: str
|
|
55
56
|
import_path: str
|
|
56
57
|
version: str
|
|
57
|
-
|
|
58
|
+
connect_attr: str
|
|
58
59
|
detection_time_ms: float
|
|
59
60
|
|
|
61
|
+
@property
|
|
62
|
+
def connect_function(self) -> Any:
|
|
63
|
+
"""Resolve connect function live from sys.modules on every access.
|
|
64
|
+
|
|
65
|
+
Resolving at call time (not at detection time) ensures that test patches
|
|
66
|
+
applied via patch.dict(sys.modules, ...) take effect for exactly the
|
|
67
|
+
duration of the patch and do not poison the singleton after the patch exits.
|
|
68
|
+
|
|
69
|
+
patch.dict removes keys that were absent before the patch, so after exit
|
|
70
|
+
the module may be gone from sys.modules even though it is importable.
|
|
71
|
+
Fall back to importlib.import_module() in that case rather than raising.
|
|
72
|
+
See IDT-BUG-dbapi-adapter-singleton.md.
|
|
73
|
+
"""
|
|
74
|
+
import importlib
|
|
75
|
+
|
|
76
|
+
module = sys.modules.get(self.import_path)
|
|
77
|
+
if module is None:
|
|
78
|
+
module = importlib.import_module(self.import_path)
|
|
79
|
+
return getattr(module, self.connect_attr)
|
|
80
|
+
|
|
60
81
|
|
|
61
82
|
def validate_package_version(package_name: str, installed_version: str, min_version: str) -> None:
|
|
62
83
|
"""Validate that installed package meets minimum version requirement.
|
|
@@ -154,7 +175,7 @@ def detect_dbapi_package() -> DBAPIPackageInfo:
|
|
|
154
175
|
package_name="intersystems-irispython",
|
|
155
176
|
import_path="intersystems_iris",
|
|
156
177
|
version=pkg_version,
|
|
157
|
-
|
|
178
|
+
connect_attr="connect",
|
|
158
179
|
detection_time_ms=elapsed_ms,
|
|
159
180
|
)
|
|
160
181
|
except (ImportError, importlib.metadata.PackageNotFoundError):
|
|
@@ -220,7 +241,7 @@ def detect_dbapi_package() -> DBAPIPackageInfo:
|
|
|
220
241
|
package_name="intersystems-irispython",
|
|
221
242
|
import_path="iris",
|
|
222
243
|
version=pkg_version,
|
|
223
|
-
|
|
244
|
+
connect_attr="connect",
|
|
224
245
|
detection_time_ms=elapsed_ms,
|
|
225
246
|
)
|
|
226
247
|
|
|
@@ -239,7 +260,7 @@ def detect_dbapi_package() -> DBAPIPackageInfo:
|
|
|
239
260
|
package_name="intersystems-iris",
|
|
240
261
|
import_path="iris.irissdk",
|
|
241
262
|
version=pkg_version,
|
|
242
|
-
|
|
263
|
+
connect_attr="connect",
|
|
243
264
|
detection_time_ms=elapsed_ms,
|
|
244
265
|
)
|
|
245
266
|
except ImportError:
|
|
@@ -314,6 +335,17 @@ def _get_adapter() -> DBAPIConnectionAdapter:
|
|
|
314
335
|
return _adapter
|
|
315
336
|
|
|
316
337
|
|
|
338
|
+
def reset_adapter() -> None:
|
|
339
|
+
"""Clear the singleton adapter so it is re-detected on next use.
|
|
340
|
+
|
|
341
|
+
Intended for test teardown. Allows tests that patch sys.modules to restore
|
|
342
|
+
a clean adapter after their patch exits, without reaching into private globals.
|
|
343
|
+
See IDT-BUG-dbapi-adapter-singleton.md.
|
|
344
|
+
"""
|
|
345
|
+
global _adapter
|
|
346
|
+
_adapter = None
|
|
347
|
+
|
|
348
|
+
|
|
317
349
|
def get_connection(*args, **kwargs) -> Any:
|
|
318
350
|
"""Get DBAPI connection using detected package.
|
|
319
351
|
|
|
@@ -354,4 +386,5 @@ __all__ = [
|
|
|
354
386
|
"DBAPIConnectionAdapter",
|
|
355
387
|
"get_connection",
|
|
356
388
|
"get_package_info",
|
|
389
|
+
"reset_adapter",
|
|
357
390
|
]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: iris-devtester
|
|
3
|
-
Version: 1.19.
|
|
3
|
+
Version: 1.19.2
|
|
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>
|
|
@@ -265,4 +265,5 @@ tests/unit/test_wait_strategies.py
|
|
|
265
265
|
tests/unit/config/test_config_hierarchy.py
|
|
266
266
|
tests/unit/config/test_container_config.py
|
|
267
267
|
tests/unit/config/test_yaml_loader.py
|
|
268
|
+
tests/unit/utils/test_dbapi_compat.py
|
|
268
269
|
tests/unit/utils/test_iris_container_adapter.py
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "iris-devtester"
|
|
7
|
-
version = "1.19.
|
|
7
|
+
version = "1.19.2"
|
|
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,183 @@
|
|
|
1
|
+
"""Tests for dbapi_compat singleton-poisoning fix.
|
|
2
|
+
|
|
3
|
+
Verifies that mocking intersystems_iris does not permanently poison the
|
|
4
|
+
DBAPIConnectionAdapter singleton — the core defect reported in
|
|
5
|
+
IDT-BUG-dbapi-adapter-singleton.md.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import sys
|
|
9
|
+
from unittest.mock import MagicMock, patch
|
|
10
|
+
|
|
11
|
+
import pytest
|
|
12
|
+
|
|
13
|
+
import iris_devtester.utils.dbapi_compat as dc
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@pytest.fixture(autouse=True)
|
|
17
|
+
def reset_adapter():
|
|
18
|
+
"""Ensure each test starts with a clean adapter."""
|
|
19
|
+
dc.reset_adapter()
|
|
20
|
+
yield
|
|
21
|
+
dc.reset_adapter()
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class TestModuleAbsentAfterPatch:
|
|
25
|
+
"""patch.dict removes keys that were absent before the patch on exit.
|
|
26
|
+
|
|
27
|
+
The module is importable but not in sys.modules. connect_function must
|
|
28
|
+
import it rather than raising ImportError.
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
def test_connect_function_importable_when_absent_from_sys_modules(self):
|
|
32
|
+
"""If import_path was absent pre-patch, it's deleted post-patch; must still resolve."""
|
|
33
|
+
import importlib
|
|
34
|
+
|
|
35
|
+
# Ensure the module is absent from sys.modules, then mock it
|
|
36
|
+
real_module = sys.modules.pop("intersystems_iris", None)
|
|
37
|
+
fake = MagicMock()
|
|
38
|
+
fake.connect = object() # sentinel
|
|
39
|
+
|
|
40
|
+
try:
|
|
41
|
+
assert "intersystems_iris" not in sys.modules, "pre-condition: key must be absent"
|
|
42
|
+
with patch.dict(sys.modules, {"intersystems_iris": fake}):
|
|
43
|
+
dc.reset_adapter()
|
|
44
|
+
dc.get_package_info() # singleton built while mock is present
|
|
45
|
+
|
|
46
|
+
# After patch.dict exit the key is gone (was absent before)
|
|
47
|
+
assert "intersystems_iris" not in sys.modules
|
|
48
|
+
|
|
49
|
+
# connect_function must import the real module, not raise
|
|
50
|
+
info = dc.get_package_info()
|
|
51
|
+
# Should not raise; real module is importable
|
|
52
|
+
fn = info.connect_function
|
|
53
|
+
assert not isinstance(fn, MagicMock), (
|
|
54
|
+
"connect_function returned MagicMock after patch exit with absent key"
|
|
55
|
+
)
|
|
56
|
+
finally:
|
|
57
|
+
# Restore original state
|
|
58
|
+
if real_module is not None:
|
|
59
|
+
sys.modules["intersystems_iris"] = real_module
|
|
60
|
+
elif "intersystems_iris" in sys.modules:
|
|
61
|
+
del sys.modules["intersystems_iris"]
|
|
62
|
+
|
|
63
|
+
def test_connect_function_does_not_raise_when_module_absent_from_sys_modules(self):
|
|
64
|
+
"""connect_function must not raise ImportError when module absent but importable."""
|
|
65
|
+
import importlib
|
|
66
|
+
|
|
67
|
+
real_module = sys.modules.pop("intersystems_iris", None)
|
|
68
|
+
fake = MagicMock()
|
|
69
|
+
fake.connect = MagicMock()
|
|
70
|
+
|
|
71
|
+
try:
|
|
72
|
+
with patch.dict(sys.modules, {"intersystems_iris": fake}):
|
|
73
|
+
dc.reset_adapter()
|
|
74
|
+
info = dc.get_package_info()
|
|
75
|
+
|
|
76
|
+
assert "intersystems_iris" not in sys.modules
|
|
77
|
+
|
|
78
|
+
# Must not raise
|
|
79
|
+
dc.reset_adapter()
|
|
80
|
+
try:
|
|
81
|
+
info2 = dc.get_package_info()
|
|
82
|
+
_ = info2.connect_function
|
|
83
|
+
except ImportError as e:
|
|
84
|
+
pytest.fail(f"connect_function raised ImportError for importable module: {e}")
|
|
85
|
+
finally:
|
|
86
|
+
if real_module is not None:
|
|
87
|
+
sys.modules["intersystems_iris"] = real_module
|
|
88
|
+
elif "intersystems_iris" in sys.modules:
|
|
89
|
+
del sys.modules["intersystems_iris"]
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class TestSingletonPoisoning:
|
|
93
|
+
"""Fix #1: connect resolved at call time, not detection time."""
|
|
94
|
+
|
|
95
|
+
def test_mock_does_not_poison_after_patch_exits(self):
|
|
96
|
+
"""After patch context exits, get_connection must use real connect, not MagicMock."""
|
|
97
|
+
fake = MagicMock()
|
|
98
|
+
with patch.dict(sys.modules, {"intersystems_iris": fake}):
|
|
99
|
+
dc.reset_adapter() # force re-detection while mock is active
|
|
100
|
+
info_inside = dc.get_package_info()
|
|
101
|
+
assert isinstance(info_inside.connect_function, MagicMock)
|
|
102
|
+
|
|
103
|
+
# sys.modules restored — real module back
|
|
104
|
+
dc.reset_adapter()
|
|
105
|
+
try:
|
|
106
|
+
info_after = dc.get_package_info()
|
|
107
|
+
# connect_function must now be the real one, not the MagicMock
|
|
108
|
+
assert not isinstance(info_after.connect_function, MagicMock), (
|
|
109
|
+
"Singleton poisoning: connect_function is still a MagicMock after patch exited"
|
|
110
|
+
)
|
|
111
|
+
except Exception:
|
|
112
|
+
# Package not installed in test env — that's fine, not the bug we're testing
|
|
113
|
+
pass
|
|
114
|
+
|
|
115
|
+
def test_connect_function_is_live_attr_not_bound_at_detection(self):
|
|
116
|
+
"""connect_function property must return current module attribute, not cached ref."""
|
|
117
|
+
fake_module = MagicMock()
|
|
118
|
+
real_connect = object() # sentinel
|
|
119
|
+
fake_module.connect = real_connect
|
|
120
|
+
|
|
121
|
+
with patch.dict(sys.modules, {"intersystems_iris": fake_module}):
|
|
122
|
+
dc.reset_adapter()
|
|
123
|
+
info = dc.get_package_info()
|
|
124
|
+
assert info.connect_function is real_connect
|
|
125
|
+
|
|
126
|
+
# Swap the connect on the live module — info.connect_function must follow
|
|
127
|
+
new_connect = object()
|
|
128
|
+
fake_module.connect = new_connect
|
|
129
|
+
assert info.connect_function is new_connect, (
|
|
130
|
+
"connect_function is bound at detection time instead of being resolved live"
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
class TestResetAdapter:
|
|
135
|
+
"""Fix #2: public reset_adapter() lets consumers manage the singleton cleanly."""
|
|
136
|
+
|
|
137
|
+
def test_reset_adapter_clears_singleton(self):
|
|
138
|
+
fake = MagicMock()
|
|
139
|
+
with patch.dict(sys.modules, {"intersystems_iris": fake}):
|
|
140
|
+
dc.reset_adapter()
|
|
141
|
+
_ = dc.get_package_info() # builds singleton with mock
|
|
142
|
+
# Private global should be None after reset
|
|
143
|
+
dc.reset_adapter()
|
|
144
|
+
assert dc._adapter is None
|
|
145
|
+
|
|
146
|
+
def test_reset_adapter_exported(self):
|
|
147
|
+
assert "reset_adapter" in dc.__all__
|
|
148
|
+
|
|
149
|
+
def test_reset_adapter_idempotent(self):
|
|
150
|
+
dc.reset_adapter()
|
|
151
|
+
dc.reset_adapter() # must not raise
|
|
152
|
+
assert dc._adapter is None
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
class TestDBAPIPackageInfo:
|
|
156
|
+
"""connect_function must be a live property, not a stored Callable."""
|
|
157
|
+
|
|
158
|
+
def test_connect_function_property_returns_current_module_attr(self):
|
|
159
|
+
fake = MagicMock()
|
|
160
|
+
sentinel_1 = object()
|
|
161
|
+
sentinel_2 = object()
|
|
162
|
+
fake.connect = sentinel_1
|
|
163
|
+
|
|
164
|
+
with patch.dict(sys.modules, {"intersystems_iris": fake}):
|
|
165
|
+
dc.reset_adapter()
|
|
166
|
+
info = dc.get_package_info()
|
|
167
|
+
assert info.connect_function is sentinel_1
|
|
168
|
+
|
|
169
|
+
fake.connect = sentinel_2
|
|
170
|
+
assert info.connect_function is sentinel_2
|
|
171
|
+
|
|
172
|
+
def test_package_info_still_has_package_name_and_version(self):
|
|
173
|
+
fake = MagicMock()
|
|
174
|
+
fake.connect = MagicMock()
|
|
175
|
+
|
|
176
|
+
with patch.dict(sys.modules, {"intersystems_iris": fake}), patch(
|
|
177
|
+
"importlib.metadata.version", return_value="5.2.0"
|
|
178
|
+
):
|
|
179
|
+
dc.reset_adapter()
|
|
180
|
+
info = dc.get_package_info()
|
|
181
|
+
assert info.package_name == "intersystems-irispython"
|
|
182
|
+
assert info.version == "5.2.0"
|
|
183
|
+
assert info.import_path == "intersystems_iris"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/archive/AGENTIC_SANDBOX_ENHANCEMENT_REPORT.md
RENAMED
|
File without changes
|
|
File without changes
|
{iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/archive/IRIS_DEVTESTER_POSITIONING_REPORT.md
RENAMED
|
File without changes
|
{iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/archive/LANGCHAIN_INTEGRATION_STRATEGY.md
RENAMED
|
File without changes
|
{iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/archive/LANGCHAIN_INTEGRATION_TEST_RESULTS.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/development/SESSION-INTEGRATION-TESTS.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/api-contract-synchronization.md
RENAMED
|
File without changes
|
{iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/callin-service-requirement.md
RENAMED
|
File without changes
|
{iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/cpf-merge-and-container-restarts.md
RENAMED
|
File without changes
|
{iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/dat-fixtures-docker-exec-pattern.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/dbapi-objectscript-limitation.md
RENAMED
|
File without changes
|
{iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/dbapi-password-reset-limitation.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/embedded-python-considerations.md
RENAMED
|
File without changes
|
|
File without changes
|
{iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/integration-test-dbapi-limitation.md
RENAMED
|
File without changes
|
|
File without changes
|
{iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/iris-connection-access-denied-bug.md
RENAMED
|
File without changes
|
{iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/iris-container-dind-port-mapping.md
RENAMED
|
File without changes
|
{iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/iris-container-graceful-shutdown.md
RENAMED
|
File without changes
|
{iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/iris-container-performance.md
RENAMED
|
File without changes
|
|
File without changes
|
{iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/iris-container-volume-permissions.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/namespace-sql-vs-iris-connect.md
RENAMED
|
File without changes
|
{iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/password-reset-changeflag-fix.md
RENAMED
|
File without changes
|
{iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/rag-templates-production-patterns.md
RENAMED
|
File without changes
|
{iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/sql-task-manager-operations.md
RENAMED
|
File without changes
|
{iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/test-isolation-fix-summary.md
RENAMED
|
File without changes
|
{iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/test-isolation-investigation.md
RENAMED
|
File without changes
|
{iris_devtester-1.19.0 → iris_devtester-1.19.2}/docs/learnings/testcontainers-ryuk-lifecycle.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|