iris-devtester 1.10.2__tar.gz → 1.10.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/CLAUDE.md +2 -2
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/CONSTITUTION.md +43 -11
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/LICENSE +1 -1
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/PKG-INFO +2 -2
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/README.md +1 -1
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/TROUBLESHOOTING.md +4 -4
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/__init__.py +1 -1
- iris_devtester-1.10.4/iris_devtester/__main__.py +8 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/config/defaults.py +2 -2
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/config/models.py +4 -3
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/connections/models.py +1 -1
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/containers/iris_container.py +47 -2
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/containers/wait_strategies.py +2 -2
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/fixtures/creator.py +2 -2
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/fixtures/loader.py +6 -2
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/integrations/langchain.py +2 -2
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/utils/dbapi_compat.py +27 -7
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/utils/enable_callin.py +4 -2
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/utils/password.py +5 -1
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/utils/test_connection.py +5 -3
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester.egg-info/PKG-INFO +2 -2
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester.egg-info/SOURCES.txt +1 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester.egg-info/entry_points.txt +1 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/pyproject.toml +2 -1
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/conftest.py +1 -1
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/contract/test_reset_verification_contract.py +3 -3
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/contract/test_retry_logic_contract.py +7 -7
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/integration/test_custom_user_remediation.py +2 -2
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/integration/test_password_preconfig_integration.py +1 -1
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/integration/test_password_reset_both_editions.py +4 -4
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/integration/test_password_reset_macos.py +8 -8
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/integration/test_password_reset_timing.py +6 -6
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/integration/test_password_reset_validation.py +7 -7
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/integration/test_proactive_password_reset.py +1 -1
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/unit/test_connection_info.py +3 -3
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/unit/test_iris_config.py +1 -1
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/AGENTS.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/MANIFEST.in +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/SKILL.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/GETTING_STARTED.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/LANGCHAIN_INTEGRATION_QUICKSTART.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/ROADMAP.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/SQL_VS_OBJECTSCRIPT.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/WHATS_NEW_v1.4.0.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/archive/AGENTIC_SANDBOX_ENHANCEMENT_REPORT.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/archive/IMPACT_ANALYSIS.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/archive/IRIS_DEVTESTER_POSITIONING_REPORT.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/archive/LANGCHAIN_INTEGRATION_STRATEGY.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/archive/LANGCHAIN_INTEGRATION_TEST_RESULTS.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/archive/PHASE_2_PLAN.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/archive/RAG_TEMPLATES_ANALYSIS.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/archive/README.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/archive/STRATEGIC_ROADMAP_SUMMARY.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/archive/feature-009-refactor-plan.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/development/BUG_REPORT.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/development/EXTRACTION_SUMMARY.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/development/FEATURE_006_SUMMARY.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/development/PHASE2_RESULTS.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/development/PRE_PUBLISH_REVIEW.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/development/PROGRESS.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/development/PYPI_READINESS.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/development/SESSION-INTEGRATION-TESTS.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/development/SESSION-SUMMARY.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/development/STATUS-002-PIVOTED.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/development/STATUS-003-COMPLETE.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/development/STATUS.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/development/V1_COMPLETION_PLAN.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/development/V1_RELEASE_SUMMARY.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/features/WSGI-ASGI-SERVER-SETUP.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/features/agent-skills.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/features/dat-fixtures.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/features/docker-compose.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/features/performance-monitoring.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/features/testcontainers.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/learnings/api-contract-synchronization.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/learnings/callin-service-requirement.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/learnings/cpf-merge-and-container-restarts.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/learnings/dat-fixtures-docker-exec-pattern.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/learnings/dat-restore-database-isolation-problem.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/learnings/dbapi-bulk-insert-performance-issue.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/learnings/dbapi-objectscript-limitation.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/learnings/dbapi-password-reset-limitation.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/learnings/dbapi-private-module-myth.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/learnings/docker-hub-image-naming.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/learnings/embedded-python-considerations.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/learnings/feature-002-pivot-summary.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/learnings/integration-test-dbapi-limitation.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/learnings/iris-backup-patterns.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/learnings/iris-container-performance.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/learnings/iris-container-readiness.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/learnings/iris-docker-sdk-environment-variables.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/learnings/iris-performance-monitoring-landscape.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/learnings/iris-security-users-api.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/learnings/password-reset-changeflag-fix.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/learnings/rag-templates-production-patterns.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/learnings/sql-task-manager-operations.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/learnings/test-isolation-fix-summary.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/learnings/test-isolation-investigation.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/docs/learnings/testcontainers-ryuk-lifecycle.md +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/examples/01_quickstart.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/examples/02_connection_management.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/examples/04_pytest_fixtures.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/examples/05_ci_cd.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/examples/08_auto_discovery.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/examples/09_enterprise.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/examples/10_docker_compose_integration.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/examples/langchain_integration_example.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/cli/__init__.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/cli/__main__.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/cli/connection_commands.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/cli/container.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/cli/container_commands.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/cli/fixture_commands.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/config/__init__.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/config/auto_discovery.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/config/container_config.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/config/container_state.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/config/discovery.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/config/presets.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/config/yaml_loader.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/connections/__init__.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/connections/auto_discovery.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/connections/connection.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/connections/dbapi.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/connections/jdbc.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/connections/manager.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/connections/retry.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/containers/__init__.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/containers/cpf_manager.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/containers/models.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/containers/monitor_utils.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/containers/monitoring.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/containers/performance.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/containers/validation.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/fixtures/__init__.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/fixtures/manifest.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/fixtures/obj_export.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/fixtures/validator.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/integrations/__init__.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/ports/__init__.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/ports/assignment.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/ports/exceptions.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/ports/registry.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/testing/__init__.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/testing/fixtures.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/testing/helpers.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/testing/models.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/testing/schema_reset.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/utils/__init__.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/utils/container_port.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/utils/container_status.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/utils/health_checks.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/utils/iris_container_adapter.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/utils/progress.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester.egg-info/dependency_links.txt +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester.egg-info/requires.txt +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester.egg-info/top_level.txt +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/setup.cfg +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/__init__.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/contract/__init__.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/contract/cli/test_container_logs_contract.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/contract/cli/test_container_remove_contract.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/contract/cli/test_container_restart_contract.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/contract/cli/test_container_start_contract.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/contract/cli/test_container_status_contract.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/contract/cli/test_container_stop_contract.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/contract/cli/test_container_up_contract.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/contract/test_agent_skills.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/contract/test_cli_container_commands.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/contract/test_cli_fixture_commands.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/contract/test_connection_api.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/contract/test_container_api.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/contract/test_container_integration_contract.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/contract/test_container_status_api.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/contract/test_container_validation_api.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/contract/test_enable_callin_api.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/contract/test_fixture_creator_api.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/contract/test_fixture_loader_api.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/contract/test_fixture_validator_api.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/contract/test_iriscontainer_attach.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/contract/test_legacy_package_contract.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/contract/test_modern_package_contract.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/contract/test_monitoring_config_api.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/contract/test_package_detection.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/contract/test_port_registry_contract.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/contract/test_preconfig_contract.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/contract/test_resource_monitoring_api.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/contract/test_task_manager_api.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/contract/test_test_connection_api.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/contract/test_testing_fixtures_api.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/e2e/__init__.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/e2e/test_skill_workflow.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/integration/__init__.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/integration/conftest.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/integration/ports/__init__.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/integration/ports/test_manual_port_override.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/integration/ports/test_multi_project_isolation.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/integration/ports/test_port_exhaustion.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/integration/ports/test_port_persistence.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/integration/ports/test_stale_cleanup.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/integration/test_bug_fixes.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/integration/test_bug_fixes_011.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/integration/test_cli_container_integration.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/integration/test_connection_integration.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/integration/test_container_health_monitor.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/integration/test_container_status_integration.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/integration/test_container_validation.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/integration/test_cpf_merge.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/integration/test_cpf_presets.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/integration/test_cpf_security.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/integration/test_enable_callin_integration.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/integration/test_fixture_export_patterns.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/integration/test_fixture_performance.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/integration/test_fixture_refresh.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/integration/test_fixtures_integration.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/integration/test_iriscontainer_attach_integration.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/integration/test_monitor_utils_integration.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/integration/test_monitoring_integration.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/integration/test_password_reset_integration.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/integration/test_real_world_problems.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/integration/test_reliable_password_reset.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/integration/test_test_connection_integration.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/unit/__init__.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/unit/config/test_config_hierarchy.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/unit/config/test_container_config.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/unit/config/test_yaml_loader.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/unit/test_auto_discovery.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/unit/test_config_discovery.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/unit/test_connection_fallback.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/unit/test_cpf_manager.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/unit/test_iris_container.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/unit/test_manifest.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/unit/test_monitoring_policy.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/unit/test_password_preconfig.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/unit/test_password_preconfig_unit.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/unit/test_performance_metrics.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/unit/test_resource_thresholds.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/unit/test_retry.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/unit/test_schema_models.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/unit/test_validation_results.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/unit/test_wait_strategies.py +0 -0
- {iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/unit/utils/test_iris_container_adapter.py +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# CLAUDE.md -
|
|
1
|
+
# CLAUDE.md - iris-devtester
|
|
2
2
|
|
|
3
3
|
**Purpose**: Provides Claude Code with project-specific context, patterns, and conventions.
|
|
4
4
|
|
|
@@ -11,7 +11,7 @@ This file provides guidance to Claude Code when working with this repository.
|
|
|
11
11
|
|
|
12
12
|
## Project Overview
|
|
13
13
|
|
|
14
|
-
**
|
|
14
|
+
**iris-devtester** is a battle-tested Python package providing automatic, reliable infrastructure for InterSystems IRIS development. This is being extracted from production code in the `rag-templates` project.
|
|
15
15
|
|
|
16
16
|
## Source Material
|
|
17
17
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
#
|
|
1
|
+
# iris-devtester Constitution
|
|
2
2
|
|
|
3
|
-
**Version**: 1.
|
|
3
|
+
**Version**: 1.2.0
|
|
4
4
|
**Status**: Foundational
|
|
5
|
-
**Last Updated**:
|
|
5
|
+
**Last Updated**: 2026-02-06
|
|
6
6
|
|
|
7
7
|
## Preamble
|
|
8
8
|
|
|
@@ -391,7 +391,38 @@ hasattr(iris, 'connect') # True in BOTH versions!
|
|
|
391
391
|
|
|
392
392
|
**Reference**: See hipporag2-pipeline CONSTITUTION.md Principle 9 for detailed empirical testing results.
|
|
393
393
|
|
|
394
|
-
### 9.
|
|
394
|
+
### 9. SQLITE-LEVEL ERGONOMICS (THE NORTH STAR)
|
|
395
|
+
|
|
396
|
+
**The Principle**: IRIS setup and connectivity should be invisible. A developer should go from "nothing" to "connected" with zero manual configuration.
|
|
397
|
+
|
|
398
|
+
**Why It Matters**:
|
|
399
|
+
- SQLite is the benchmark for "zero-friction" development
|
|
400
|
+
- Infrastructure setup is a major barrier to IRIS adoption
|
|
401
|
+
- Developer "flow" is interrupted by infrastructure management
|
|
402
|
+
- If a user has to think about ports, passwords, or container lifecycles, we have more work to do.
|
|
403
|
+
|
|
404
|
+
**Implementation Requirements**:
|
|
405
|
+
- ✅ `get_connection()` with zero-config auto-discovery
|
|
406
|
+
- ✅ Automatic container lifecycle management (transparent to the user)
|
|
407
|
+
- ✅ Standardized default credentials (`_SYSTEM`/`SYS`)
|
|
408
|
+
- ✅ Proactive remediation of all connectivity hurdles (service enablement, password reset)
|
|
409
|
+
- ✅ Silent infrastructure: infrastructure "noise" (logs, status) is hidden unless an error occurs
|
|
410
|
+
|
|
411
|
+
**Forbidden**:
|
|
412
|
+
- ❌ Requiring manual Docker commands for basic connectivity
|
|
413
|
+
- ❌ Mandatory configuration files for local dev
|
|
414
|
+
- ❌ Exposing infrastructure complexity in the primary API
|
|
415
|
+
|
|
416
|
+
**Example**:
|
|
417
|
+
```python
|
|
418
|
+
# THE NORTH STAR EXPERIENCE
|
|
419
|
+
from iris_devtester import IRISContainer
|
|
420
|
+
|
|
421
|
+
# One line to everything: startup, auth, service enablement, connection
|
|
422
|
+
conn = IRISContainer.community().get_connection()
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
### 10. DOCUMENT THE BLIND ALLEYS
|
|
395
426
|
|
|
396
427
|
**The Principle**: Failed approaches must be documented to prevent repetition.
|
|
397
428
|
|
|
@@ -401,18 +432,13 @@ hasattr(iris, 'connect') # True in BOTH versions!
|
|
|
401
432
|
- Context for design decisions is valuable
|
|
402
433
|
- Prevents regression to worse solutions
|
|
403
434
|
|
|
404
|
-
**Implementation Requirements**:
|
|
405
|
-
- ✅ `docs/learnings/` directory for deep-dives
|
|
406
|
-
- ✅ "Why not X?" sections in documentation
|
|
407
|
-
- ✅ ADR (Architecture Decision Records) for major choices
|
|
408
|
-
- ✅ Performance comparisons
|
|
409
|
-
- ✅ Case studies from production
|
|
410
|
-
|
|
411
435
|
**Documented Blind Alleys**:
|
|
412
436
|
- **Why not JDBC-only?** → DBAPI is 3x faster, see benchmark
|
|
413
437
|
- **Why not shared test databases?** → Data pollution, see case study
|
|
414
438
|
- **Why not manual password resets?** → CI/CD breaks, see incident report
|
|
415
439
|
- **Why not port 1972 hardcoded?** → Conflicts in parallel tests, see issue #42
|
|
440
|
+
- **Why not prefer `iris.connect()`?** → In `intersystems-irispython` 5.3.1+, `iris.connect` uses the `_elsdk_` driver which has a critical `SIGSEGV` bug with `FETCH FIRST N ROWS ONLY` syntax. Prefer `intersystems_iris.connect` (the stable `_IRISNative` path) instead.
|
|
441
|
+
|
|
416
442
|
|
|
417
443
|
**Example Documentation**:
|
|
418
444
|
```markdown
|
|
@@ -471,6 +497,12 @@ Principles may be amended when:
|
|
|
471
497
|
|
|
472
498
|
## Version History
|
|
473
499
|
|
|
500
|
+
### v1.2.0 (2026-02-06)
|
|
501
|
+
- Added Principle 9: SQLite-Level Ergonomics (The North Star)
|
|
502
|
+
- Renumbered Principle 9 "Document the Blind Alleys" → Principle 10
|
|
503
|
+
- Standardized on `_SYSTEM` as the default toolkit username
|
|
504
|
+
- Renamed project to `iris-devtester` consistently across documentation
|
|
505
|
+
|
|
474
506
|
### v1.1.0 (2025-11-23)
|
|
475
507
|
- Added Principle 8: Use Official IRIS Python API (No Private Attributes)
|
|
476
508
|
- Documents empirically tested fact that `_DBAPI` does NOT exist in intersystems-irispython v5.1.2 or v5.3.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c) 2025
|
|
3
|
+
Copyright (c) 2025-2026 iris-devtester Contributors
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: iris-devtester
|
|
3
|
-
Version: 1.10.
|
|
3
|
+
Version: 1.10.4
|
|
4
4
|
Summary: Battle-tested InterSystems IRIS infrastructure utilities for Python development
|
|
5
5
|
Author-email: InterSystems Community <community@intersystems.com>
|
|
6
6
|
Maintainer-email: Thomas Dyar <thomas.dyar@intersystems.com>
|
|
@@ -183,7 +183,7 @@ with IRISContainer.community() \
|
|
|
183
183
|
```python
|
|
184
184
|
IRISContainer(
|
|
185
185
|
image="intersystemsdc/iris-community:latest", # Docker image
|
|
186
|
-
username="
|
|
186
|
+
username="_SYSTEM", # Default username
|
|
187
187
|
password="SYS", # Default password
|
|
188
188
|
namespace="USER", # Default namespace
|
|
189
189
|
name="my-container", # Container name (alternative to with_name)
|
|
@@ -119,7 +119,7 @@ with IRISContainer.community() \
|
|
|
119
119
|
```python
|
|
120
120
|
IRISContainer(
|
|
121
121
|
image="intersystemsdc/iris-community:latest", # Docker image
|
|
122
|
-
username="
|
|
122
|
+
username="_SYSTEM", # Default username
|
|
123
123
|
password="SYS", # Default password
|
|
124
124
|
namespace="USER", # Default namespace
|
|
125
125
|
name="my-container", # Container name (alternative to with_name)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Troubleshooting Guide
|
|
2
2
|
|
|
3
|
-
This guide covers the most common issues you might encounter when using
|
|
3
|
+
This guide covers the most common issues you might encounter when using iris-devtester and how to resolve them.
|
|
4
4
|
|
|
5
5
|
## Top 5 Issues
|
|
6
6
|
|
|
@@ -43,10 +43,10 @@ sudo usermod -aG docker $USER
|
|
|
43
43
|
```
|
|
44
44
|
|
|
45
45
|
**Diagnosis:**
|
|
46
|
-
IRIS requires password change on first login, but
|
|
46
|
+
IRIS requires password change on first login, but iris-devtester should auto-remediate this. If you see this error, auto-remediation failed.
|
|
47
47
|
|
|
48
48
|
**Solution:**
|
|
49
|
-
|
|
49
|
+
iris-devtester automatically handles this, but if you encounter the error:
|
|
50
50
|
|
|
51
51
|
```python
|
|
52
52
|
# The library should automatically reset the password
|
|
@@ -314,4 +314,4 @@ docker info | grep -E "CPUs|Total Memory"
|
|
|
314
314
|
|
|
315
315
|
---
|
|
316
316
|
|
|
317
|
-
**Remember**:
|
|
317
|
+
**Remember**: iris-devtester is designed to handle most issues automatically. If you encounter consistent errors, please [report them](https://github.com/intersystems-community/iris-devtester/issues/new?template=bug_report.yml) so we can improve auto-remediation.
|
|
@@ -20,8 +20,8 @@ DEFAULT_PORT = 1972
|
|
|
20
20
|
DEFAULT_NAMESPACE = "USER"
|
|
21
21
|
"""Default IRIS namespace (USER is the default workspace)"""
|
|
22
22
|
|
|
23
|
-
DEFAULT_USERNAME = "
|
|
24
|
-
"""Default IRIS username (
|
|
23
|
+
DEFAULT_USERNAME = "_SYSTEM"
|
|
24
|
+
"""Default IRIS username (_SYSTEM has full access)"""
|
|
25
25
|
|
|
26
26
|
DEFAULT_PASSWORD = "SYS"
|
|
27
27
|
"""Default IRIS password (SYS is the default for containers)"""
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"""
|
|
2
|
-
Configuration models for
|
|
2
|
+
Configuration models for iris-devtester.
|
|
3
3
|
|
|
4
4
|
Provides IRISConfig dataclass for database connection configuration.
|
|
5
5
|
"""
|
|
@@ -20,11 +20,12 @@ class IRISConfig:
|
|
|
20
20
|
host: Database host (default: "localhost")
|
|
21
21
|
port: Database port (default: 1972)
|
|
22
22
|
namespace: IRIS namespace (default: "USER")
|
|
23
|
-
username: Database username (default: "
|
|
23
|
+
username: Database username (default: "_SYSTEM")
|
|
24
24
|
password: Database password (default: "SYS")
|
|
25
25
|
driver: Preferred driver type (default: "auto")
|
|
26
26
|
connection_string: Optional override connection string
|
|
27
27
|
timeout: Connection timeout in seconds (default: 30)
|
|
28
|
+
container_name: Optional name of the IRIS container (used for password reset)
|
|
28
29
|
|
|
29
30
|
Raises:
|
|
30
31
|
ValueError: If validation fails (invalid port, empty namespace, etc.)
|
|
@@ -46,7 +47,7 @@ class IRISConfig:
|
|
|
46
47
|
host: str = "localhost"
|
|
47
48
|
port: int = 1972
|
|
48
49
|
namespace: str = "USER"
|
|
49
|
-
username: str = "
|
|
50
|
+
username: str = "_SYSTEM"
|
|
50
51
|
password: str = "SYS"
|
|
51
52
|
driver: Literal["dbapi", "jdbc", "auto"] = "auto"
|
|
52
53
|
connection_string: Optional[str] = None
|
|
@@ -66,7 +66,7 @@ class IRISContainer(IRISBase):
|
|
|
66
66
|
def __init__(
|
|
67
67
|
self,
|
|
68
68
|
image: str = "intersystemsdc/iris-community:latest",
|
|
69
|
-
username: str = "
|
|
69
|
+
username: str = "_SYSTEM",
|
|
70
70
|
password: str = "SYS",
|
|
71
71
|
namespace: str = "USER",
|
|
72
72
|
**kwargs,
|
|
@@ -205,6 +205,51 @@ class IRISContainer(IRISBase):
|
|
|
205
205
|
image = f"caretdev/iris-community-light:{tag}"
|
|
206
206
|
return cls(image=image, **kwargs)
|
|
207
207
|
|
|
208
|
+
@classmethod
|
|
209
|
+
def attach(cls, container_name: str, **kwargs) -> "IRISContainer":
|
|
210
|
+
"""
|
|
211
|
+
Attach to an existing IRIS container by name.
|
|
212
|
+
|
|
213
|
+
This allows using persistent containers (e.g. from docker-compose)
|
|
214
|
+
instead of starting a new one via testcontainers.
|
|
215
|
+
|
|
216
|
+
Args:
|
|
217
|
+
container_name: Name of the existing Docker container.
|
|
218
|
+
**kwargs: Additional configuration (username, password, namespace).
|
|
219
|
+
|
|
220
|
+
Returns:
|
|
221
|
+
An IRISContainer instance attached to the existing container.
|
|
222
|
+
"""
|
|
223
|
+
instance = cls(image="", name=container_name, **kwargs)
|
|
224
|
+
instance._is_attached = True
|
|
225
|
+
instance._container_name = container_name
|
|
226
|
+
|
|
227
|
+
try:
|
|
228
|
+
import docker
|
|
229
|
+
|
|
230
|
+
client = docker.from_env()
|
|
231
|
+
container = client.containers.get(container_name)
|
|
232
|
+
instance._container = container
|
|
233
|
+
|
|
234
|
+
# If it's a mock container, we need to set these manually
|
|
235
|
+
if not HAS_TESTCONTAINERS:
|
|
236
|
+
instance.host = "localhost"
|
|
237
|
+
# Try to find port from container ports
|
|
238
|
+
ports = container.attrs.get("NetworkSettings", {}).get("Ports", {})
|
|
239
|
+
if "1972/tcp" in ports and ports["1972/tcp"]:
|
|
240
|
+
instance._mapped_port = int(ports["1972/tcp"][0]["HostPort"])
|
|
241
|
+
else:
|
|
242
|
+
# testcontainers will handle discovery via get_config()
|
|
243
|
+
instance.get_config()
|
|
244
|
+
|
|
245
|
+
except Exception as e:
|
|
246
|
+
logger.warning(f"Could not fully inspect container '{container_name}': {e}")
|
|
247
|
+
# Fallback to defaults
|
|
248
|
+
instance.host = instance.host or "localhost"
|
|
249
|
+
instance._mapped_port = instance._mapped_port or 1972
|
|
250
|
+
|
|
251
|
+
return instance
|
|
252
|
+
|
|
208
253
|
def with_name(self, name: str) -> "IRISContainer":
|
|
209
254
|
"""Set the container name."""
|
|
210
255
|
self._container_name = name
|
|
@@ -305,7 +350,7 @@ class IRISContainer(IRISBase):
|
|
|
305
350
|
container_name = self.get_container_name()
|
|
306
351
|
ns = namespace or self._namespace
|
|
307
352
|
|
|
308
|
-
cmd = ["docker", "exec", "-i", container_name, "iris", "session", "IRIS", "-U", ns]
|
|
353
|
+
cmd = ["docker", "exec", "-u", "irisowner", "-i", container_name, "iris", "session", "IRIS", "-U", ns]
|
|
309
354
|
|
|
310
355
|
result = subprocess.run(
|
|
311
356
|
cmd, input=f"{script}\nHalt\n".encode("utf-8"), capture_output=True, timeout=30
|
{iris_devtester-1.10.2 → iris_devtester-1.10.4}/iris_devtester/containers/wait_strategies.py
RENAMED
|
@@ -120,7 +120,7 @@ class IRISReadyWaitStrategy:
|
|
|
120
120
|
" docker logs <container_name>\n"
|
|
121
121
|
"\n"
|
|
122
122
|
" 2. Verify IRIS is starting:\n"
|
|
123
|
-
" docker exec <container_name> iris list\n"
|
|
123
|
+
" docker exec -u irisowner <container_name> iris list\n"
|
|
124
124
|
"\n"
|
|
125
125
|
" 3. Increase timeout if needed:\n"
|
|
126
126
|
f" IRISReadyWaitStrategy(timeout={timeout * 2})\n"
|
|
@@ -170,7 +170,7 @@ class IRISReadyWaitStrategy:
|
|
|
170
170
|
"""
|
|
171
171
|
try:
|
|
172
172
|
result = subprocess.run(
|
|
173
|
-
["docker", "exec", container_name, "iris", "list"],
|
|
173
|
+
["docker", "exec", "-u", "irisowner", container_name, "iris", "list"],
|
|
174
174
|
capture_output=True,
|
|
175
175
|
text=True,
|
|
176
176
|
timeout=5,
|
|
@@ -132,7 +132,7 @@ class FixtureCreator:
|
|
|
132
132
|
Halt
|
|
133
133
|
"""
|
|
134
134
|
result = subprocess.run(
|
|
135
|
-
["docker", "exec", "-i", container_name, "iris", "session", "IRIS", "-U", namespace],
|
|
135
|
+
["docker", "exec", "-u", "irisowner", "-i", container_name, "iris", "session", "IRIS", "-U", namespace],
|
|
136
136
|
input=export_classes_script.encode("utf-8"),
|
|
137
137
|
capture_output=True,
|
|
138
138
|
timeout=120,
|
|
@@ -156,7 +156,7 @@ class FixtureCreator:
|
|
|
156
156
|
Halt
|
|
157
157
|
"""
|
|
158
158
|
result = subprocess.run(
|
|
159
|
-
["docker", "exec", "-i", container_name, "iris", "session", "IRIS", "-U", namespace],
|
|
159
|
+
["docker", "exec", "-u", "irisowner", "-i", container_name, "iris", "session", "IRIS", "-U", namespace],
|
|
160
160
|
input=export_globals_script.encode("utf-8"),
|
|
161
161
|
capture_output=True,
|
|
162
162
|
timeout=120,
|
|
@@ -146,7 +146,7 @@ class FixtureLoader:
|
|
|
146
146
|
Halt
|
|
147
147
|
"""
|
|
148
148
|
result = subprocess.run(
|
|
149
|
-
["docker", "exec", "-i", container_name, "iris", "session", "IRIS", "-U", "%SYS"],
|
|
149
|
+
["docker", "exec", "-u", "irisowner", "-i", container_name, "iris", "session", "IRIS", "-U", "%SYS"],
|
|
150
150
|
input=create_ns_script.encode("utf-8"),
|
|
151
151
|
capture_output=True,
|
|
152
152
|
timeout=60,
|
|
@@ -168,6 +168,8 @@ class FixtureLoader:
|
|
|
168
168
|
[
|
|
169
169
|
"docker",
|
|
170
170
|
"exec",
|
|
171
|
+
"-u",
|
|
172
|
+
"irisowner",
|
|
171
173
|
"-i",
|
|
172
174
|
container_name,
|
|
173
175
|
"iris",
|
|
@@ -200,6 +202,8 @@ class FixtureLoader:
|
|
|
200
202
|
[
|
|
201
203
|
"docker",
|
|
202
204
|
"exec",
|
|
205
|
+
"-u",
|
|
206
|
+
"irisowner",
|
|
203
207
|
"-i",
|
|
204
208
|
container_name,
|
|
205
209
|
"iris",
|
|
@@ -236,7 +240,7 @@ class FixtureLoader:
|
|
|
236
240
|
Write "SUCCESS" Halt
|
|
237
241
|
"""
|
|
238
242
|
subprocess.run(
|
|
239
|
-
["docker", "exec", "-i", container_name, "iris", "session", "IRIS", "-U", "%SYS"],
|
|
243
|
+
["docker", "exec", "-u", "irisowner", "-i", container_name, "iris", "session", "IRIS", "-U", "%SYS"],
|
|
240
244
|
input=ensure_user_script.encode("utf-8"),
|
|
241
245
|
capture_output=True,
|
|
242
246
|
timeout=30,
|
|
@@ -166,7 +166,7 @@ class LangChainIRISContainer(IRISContainer):
|
|
|
166
166
|
>>> with LangChainIRISContainer.community() as iris:
|
|
167
167
|
... conn_str = iris.get_connection_string()
|
|
168
168
|
... print(conn_str)
|
|
169
|
-
iris://
|
|
169
|
+
iris://_SYSTEM:SYS@localhost:52773/USER
|
|
170
170
|
"""
|
|
171
171
|
# Ensure connection is ready (auto-remediation)
|
|
172
172
|
_ = self.get_connection()
|
|
@@ -174,7 +174,7 @@ class LangChainIRISContainer(IRISContainer):
|
|
|
174
174
|
# Get connection details
|
|
175
175
|
host = self.get_container_host_ip()
|
|
176
176
|
port = self.get_exposed_port(1972) # SuperServer port
|
|
177
|
-
username = getattr(self, "username", "
|
|
177
|
+
username = getattr(self, "username", "_SYSTEM")
|
|
178
178
|
password = getattr(self, "password", "SYS")
|
|
179
179
|
namespace = getattr(self, "namespace", "USER")
|
|
180
180
|
|
|
@@ -135,19 +135,39 @@ def detect_dbapi_package() -> DBAPIPackageInfo:
|
|
|
135
135
|
"""
|
|
136
136
|
start_time = time.perf_counter()
|
|
137
137
|
|
|
138
|
-
# Try modern package first (
|
|
139
|
-
#
|
|
140
|
-
#
|
|
138
|
+
# Try modern stable package first (intersystems_iris)
|
|
139
|
+
# This is preferred over the 'iris' module because 'iris.connect'
|
|
140
|
+
# in intersystems-irispython 5.3.1+ uses the _elsdk_ driver path
|
|
141
|
+
# which has known SIGSEGV bugs with FETCH FIRST N ROWS ONLY syntax.
|
|
142
|
+
try:
|
|
143
|
+
import intersystems_iris
|
|
144
|
+
|
|
145
|
+
if hasattr(intersystems_iris, "connect"):
|
|
146
|
+
# Validate version from metadata
|
|
147
|
+
pkg_version = importlib.metadata.version("intersystems-irispython")
|
|
148
|
+
validate_package_version("intersystems-irispython", pkg_version, "5.1.2")
|
|
149
|
+
|
|
150
|
+
elapsed_ms = (time.perf_counter() - start_time) * 1000
|
|
151
|
+
logger.info(f"Detected IRIS DBAPI package: intersystems-irispython v{pkg_version} (via intersystems_iris)")
|
|
152
|
+
|
|
153
|
+
return DBAPIPackageInfo(
|
|
154
|
+
package_name="intersystems-irispython",
|
|
155
|
+
import_path="intersystems_iris",
|
|
156
|
+
version=pkg_version,
|
|
157
|
+
connect_function=intersystems_iris.connect,
|
|
158
|
+
detection_time_ms=elapsed_ms,
|
|
159
|
+
)
|
|
160
|
+
except (ImportError, importlib.metadata.PackageNotFoundError):
|
|
161
|
+
logger.debug("intersystems_iris not available or metadata not found, trying iris")
|
|
162
|
+
|
|
163
|
+
# Fallback to 'iris' module (also part of intersystems-irispython)
|
|
141
164
|
modern_available = False
|
|
142
165
|
try:
|
|
143
|
-
import os
|
|
144
|
-
import sys
|
|
145
|
-
|
|
146
166
|
import iris
|
|
147
167
|
|
|
148
168
|
modern_available = True
|
|
149
169
|
except ImportError as e:
|
|
150
|
-
logger.debug(f"Modern package not available, trying legacy: {e}")
|
|
170
|
+
logger.debug(f"Modern 'iris' package not available, trying legacy: {e}")
|
|
151
171
|
|
|
152
172
|
if modern_available:
|
|
153
173
|
import os
|
|
@@ -110,6 +110,8 @@ def enable_callin_service(
|
|
|
110
110
|
enable_cmd = [
|
|
111
111
|
"docker",
|
|
112
112
|
"exec",
|
|
113
|
+
"-u",
|
|
114
|
+
"irisowner",
|
|
113
115
|
"-i",
|
|
114
116
|
container_name,
|
|
115
117
|
"bash",
|
|
@@ -160,13 +162,13 @@ def enable_callin_service(
|
|
|
160
162
|
f" docker logs {container_name} | tail -20\n"
|
|
161
163
|
"\n"
|
|
162
164
|
" 2. Try manually enabling CallIn:\n"
|
|
163
|
-
f" docker exec -it {container_name} iris session IRIS -U %SYS\n"
|
|
165
|
+
f" docker exec -u irisowner -it {container_name} iris session IRIS -U %SYS\n"
|
|
164
166
|
' Do ##class(Security.Services).Get("%Service_CallIn",.prop)\n'
|
|
165
167
|
' Set prop("Enabled")=1\n'
|
|
166
168
|
' Do ##class(Security.Services).Modify("%Service_CallIn",.prop)\n'
|
|
167
169
|
"\n"
|
|
168
170
|
" 3. Check IRIS license (Community vs Enterprise):\n"
|
|
169
|
-
" docker exec {container_name} iris list\n"
|
|
171
|
+
" docker exec -u irisowner {container_name} iris list\n"
|
|
170
172
|
"\n"
|
|
171
173
|
"Documentation: See docs/learnings/callin-service-requirement.md\n",
|
|
172
174
|
)
|
|
@@ -357,6 +357,8 @@ Halt
|
|
|
357
357
|
cmd = [
|
|
358
358
|
"docker",
|
|
359
359
|
"exec",
|
|
360
|
+
"-u",
|
|
361
|
+
"irisowner",
|
|
360
362
|
"-i",
|
|
361
363
|
container_name,
|
|
362
364
|
"iris",
|
|
@@ -569,6 +571,8 @@ Halt
|
|
|
569
571
|
cmd = [
|
|
570
572
|
"docker",
|
|
571
573
|
"exec",
|
|
574
|
+
"-u",
|
|
575
|
+
"irisowner",
|
|
572
576
|
container_name,
|
|
573
577
|
"sh",
|
|
574
578
|
"-c",
|
|
@@ -625,7 +629,7 @@ Halt
|
|
|
625
629
|
f"Failed to unexpire passwords in {container_name}: {str(e)}\n"
|
|
626
630
|
"\n"
|
|
627
631
|
"Manual fix:\n"
|
|
628
|
-
f" docker exec {container_name} bash -c 'echo \"do ##class(Security.Users)"
|
|
632
|
+
f" docker exec -u irisowner {container_name} bash -c 'echo \"do ##class(Security.Users)"
|
|
629
633
|
f'.UnExpireUserPasswords(\\"*\\")" | iris session IRIS -U %SYS\'\n',
|
|
630
634
|
)
|
|
631
635
|
|
|
@@ -90,6 +90,8 @@ def test_connection(
|
|
|
90
90
|
test_cmd = [
|
|
91
91
|
"docker",
|
|
92
92
|
"exec",
|
|
93
|
+
"-u",
|
|
94
|
+
"irisowner",
|
|
93
95
|
"-i",
|
|
94
96
|
container_name,
|
|
95
97
|
"bash",
|
|
@@ -126,10 +128,10 @@ def test_connection(
|
|
|
126
128
|
"\n"
|
|
127
129
|
"How to fix it:\n"
|
|
128
130
|
" 1. List available namespaces:\n"
|
|
129
|
-
f' docker exec {container_name} iris session IRIS -U %SYS """Do ^%GSIZE"""\n'
|
|
131
|
+
f' docker exec -u irisowner {container_name} iris session IRIS -U %SYS """Do ^%GSIZE"""\n'
|
|
130
132
|
"\n"
|
|
131
133
|
" 2. Create the namespace if needed:\n"
|
|
132
|
-
f" docker exec {container_name} iris session IRIS -U %SYS\n"
|
|
134
|
+
f" docker exec -u irisowner {container_name} iris session IRIS -U %SYS\n"
|
|
133
135
|
f' Do ##class(Config.Namespaces).Create("{namespace}")\n'
|
|
134
136
|
"\n"
|
|
135
137
|
" 3. Or use an existing namespace like 'USER' or '%SYS'\n",
|
|
@@ -151,7 +153,7 @@ def test_connection(
|
|
|
151
153
|
" iris-devtester container enable-callin {container_name}\n"
|
|
152
154
|
"\n"
|
|
153
155
|
" 3. Test basic IRIS access:\n"
|
|
154
|
-
f" docker exec -it {container_name} iris session IRIS -U %SYS\n",
|
|
156
|
+
f" docker exec -u irisowner -it {container_name} iris session IRIS -U %SYS\n",
|
|
155
157
|
)
|
|
156
158
|
|
|
157
159
|
except subprocess.TimeoutExpired:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: iris-devtester
|
|
3
|
-
Version: 1.10.
|
|
3
|
+
Version: 1.10.4
|
|
4
4
|
Summary: Battle-tested InterSystems IRIS infrastructure utilities for Python development
|
|
5
5
|
Author-email: InterSystems Community <community@intersystems.com>
|
|
6
6
|
Maintainer-email: Thomas Dyar <thomas.dyar@intersystems.com>
|
|
@@ -183,7 +183,7 @@ with IRISContainer.community() \
|
|
|
183
183
|
```python
|
|
184
184
|
IRISContainer(
|
|
185
185
|
image="intersystemsdc/iris-community:latest", # Docker image
|
|
186
|
-
username="
|
|
186
|
+
username="_SYSTEM", # Default username
|
|
187
187
|
password="SYS", # Default password
|
|
188
188
|
namespace="USER", # Default namespace
|
|
189
189
|
name="my-container", # Container name (alternative to with_name)
|
|
@@ -76,6 +76,7 @@ examples/09_enterprise.py
|
|
|
76
76
|
examples/10_docker_compose_integration.py
|
|
77
77
|
examples/langchain_integration_example.py
|
|
78
78
|
iris_devtester/__init__.py
|
|
79
|
+
iris_devtester/__main__.py
|
|
79
80
|
iris_devtester.egg-info/PKG-INFO
|
|
80
81
|
iris_devtester.egg-info/SOURCES.txt
|
|
81
82
|
iris_devtester.egg-info/dependency_links.txt
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "iris-devtester"
|
|
7
|
-
version = "1.10.
|
|
7
|
+
version = "1.10.4"
|
|
8
8
|
description = "Battle-tested InterSystems IRIS infrastructure utilities for Python development"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.9"
|
|
@@ -88,6 +88,7 @@ docs = [
|
|
|
88
88
|
|
|
89
89
|
[project.scripts]
|
|
90
90
|
iris-devtester = "iris_devtester.cli:main"
|
|
91
|
+
idt = "iris_devtester.cli:main"
|
|
91
92
|
|
|
92
93
|
[project.urls]
|
|
93
94
|
Homepage = "https://github.com/intersystems-community/iris-devtester"
|
{iris_devtester-1.10.2 → iris_devtester-1.10.4}/tests/contract/test_reset_verification_contract.py
RENAMED
|
@@ -32,7 +32,7 @@ class TestResetVerificationContract:
|
|
|
32
32
|
new_pwd = "RealPassword123!"
|
|
33
33
|
result = reset_password(
|
|
34
34
|
container_name=container_name,
|
|
35
|
-
username="
|
|
35
|
+
username="_SYSTEM",
|
|
36
36
|
new_password=new_pwd,
|
|
37
37
|
hostname=config.host,
|
|
38
38
|
port=config.port,
|
|
@@ -47,7 +47,7 @@ class TestResetVerificationContract:
|
|
|
47
47
|
hostname=config.host,
|
|
48
48
|
port=config.port,
|
|
49
49
|
namespace=config.namespace,
|
|
50
|
-
username="
|
|
50
|
+
username="_SYSTEM",
|
|
51
51
|
password=new_pwd,
|
|
52
52
|
)
|
|
53
53
|
cursor = conn.cursor()
|
|
@@ -69,7 +69,7 @@ class TestResetVerificationContract:
|
|
|
69
69
|
# This will cause a REAL connection failure during verification
|
|
70
70
|
result = reset_password(
|
|
71
71
|
container_name=container_name,
|
|
72
|
-
username="
|
|
72
|
+
username="_SYSTEM",
|
|
73
73
|
new_password="ShouldNotWork",
|
|
74
74
|
hostname=config.host,
|
|
75
75
|
port=9999, # WRONG PORT
|