From 7d54846edacd09bb6d1f2161218048e531820728 Mon Sep 17 00:00:00 2001 From: aromeroromero Date: Tue, 17 Feb 2026 14:45:46 +0100 Subject: [PATCH] chore: update psycopg from v2 to v3 --- .gitignore | 4 +- VERSION | 2 +- docs/multi-database.md | 12 +++--- example/alembic/alembic.ini | 4 +- example/multi-database-config.yaml | 10 ++--- example/simple-config.yaml | 6 +-- pyproject.toml | 4 +- requirements.txt | 4 +- scripts/validate_config.py | 4 +- src/chartreuse/config_loader.py | 6 +-- src/chartreuse/tests/e2e_tests/conftest.py | 2 +- .../tests/unit_tests/test_alembic.py | 30 ++++++------- .../tests/unit_tests/test_chartreuse.py | 32 +++++++------- .../test_chartreuse_upgrade_extended.py | 16 +++---- .../tests/unit_tests/test_config_loader.py | 42 +++++++++---------- 15 files changed, 91 insertions(+), 87 deletions(-) diff --git a/.gitignore b/.gitignore index b40fe5f..e366723 100644 --- a/.gitignore +++ b/.gitignore @@ -71,4 +71,6 @@ venv-python3.10 # Helm Chart *.lock -example/helm-chart/my-example-chart/charts/ \ No newline at end of file +example/helm-chart/my-example-chart/charts/ + +.envrc \ No newline at end of file diff --git a/VERSION b/VERSION index 6abaeb2..f07dc2c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -6.2.0 +6.2.1-dev0 diff --git a/docs/multi-database.md b/docs/multi-database.md index d715d1f..eab5003 100644 --- a/docs/multi-database.md +++ b/docs/multi-database.md @@ -18,7 +18,7 @@ databases: main: alembic_directory_path: /app/alembic/main alembic_config_file_path: alembic.ini - dialect: postgresql + dialect: postgresql+psycopg user: app_user password: app_password host: postgres-main @@ -31,7 +31,7 @@ databases: analytics: alembic_directory_path: /app/alembic/analytics alembic_config_file_path: alembic.ini - dialect: postgresql + dialect: postgresql+psycopg user: analytics_user password: analytics_password host: postgres-analytics @@ -49,7 +49,7 @@ databases: - `alembic_config_file_path`: Alembic configuration file name **Database connection components (all required):** -- `dialect`: Database dialect (e.g., postgresql, mysql, sqlite) +- `dialect`: Database dialect (e.g., postgresql+psycopg, mysql, sqlite) - `user`: Database username - `password`: Database password - `host`: Database host @@ -129,7 +129,7 @@ data: main: alembic_directory_path: /app/alembic/main alembic_config_file_path: alembic.ini - dialect: postgresql + dialect: postgresql+psycopg user: {{ .Values.database.main.user }} password: {{ .Values.database.main.password }} host: {{ .Values.database.main.host }} @@ -140,7 +140,7 @@ data: analytics: alembic_directory_path: /app/alembic/analytics alembic_config_file_path: alembic.ini - dialect: postgresql + dialect: postgresql+psycopg user: {{ .Values.database.analytics.user }} password: {{ .Values.database.analytics.password }} host: {{ .Values.database.analytics.host }} @@ -163,4 +163,4 @@ volumes: - name: config configMap: name: chartreuse-config -``` \ No newline at end of file +``` diff --git a/example/alembic/alembic.ini b/example/alembic/alembic.ini index b1d468a..c7c849d 100644 --- a/example/alembic/alembic.ini +++ b/example/alembic/alembic.ini @@ -1,6 +1,6 @@ [postgresql] script_location = postgresl -sqlalchemy.url = postgresql://wiremind_owner@localhost:5432/wiremind +sqlalchemy.url = postgresql+psycopg://wiremind_owner@localhost:5432/wiremind prepend_sys_path = .. file_template = %%(year)d%%(month).2d%%(day).2d-%%(slug)s @@ -44,4 +44,4 @@ formatter = generic [formatter_generic] format = %(levelname)-5.5s [%(name)s] %(message)s -datefmt = %H:%M:%S \ No newline at end of file +datefmt = %H:%M:%S diff --git a/example/multi-database-config.yaml b/example/multi-database-config.yaml index 73bd247..2b62766 100644 --- a/example/multi-database-config.yaml +++ b/example/multi-database-config.yaml @@ -9,7 +9,7 @@ databases: alembic_directory_path: /app/alembic/main alembic_config_file_path: alembic.ini # Database connection components (URL will be built automatically) - dialect: postgresql + dialect: postgresql+psycopg user: app_user password: app_password host: postgres-main @@ -22,7 +22,7 @@ databases: analytics: alembic_directory_path: /app/alembic/analytics alembic_config_file_path: alembic.ini - dialect: postgresql + dialect: postgresql+psycopg user: analytics_user password: analytics_password host: postgres-analytics @@ -35,7 +35,7 @@ databases: audit: alembic_directory_path: /app/alembic/audit alembic_config_file_path: alembic.ini - dialect: postgresql + dialect: postgresql+psycopg user: audit_user password: audit_password host: postgres-audit @@ -48,11 +48,11 @@ databases: reports: alembic_directory_path: /app/alembic/reports alembic_config_file_path: alembic.ini - dialect: postgresql + dialect: postgresql+psycopg user: "${REPORTS_DB_USER}" password: "${REPORTS_DB_PASSWORD}" host: postgres-reports port: 5432 database: reports allow_migration_for_empty_database: false - additional_parameters: "" \ No newline at end of file + additional_parameters: "" diff --git a/example/simple-config.yaml b/example/simple-config.yaml index 9d59389..bc8a341 100644 --- a/example/simple-config.yaml +++ b/example/simple-config.yaml @@ -4,7 +4,7 @@ databases: main: alembic_directory_path: /app/alembic/main alembic_config_file_path: alembic.ini - dialect: postgresql + dialect: postgresql+psycopg user: myuser password: mypassword host: localhost @@ -16,10 +16,10 @@ databases: cache: alembic_directory_path: /app/alembic/cache alembic_config_file_path: alembic.ini - dialect: postgresql + dialect: postgresql+psycopg user: cache_user password: cache_pass host: redis-db port: 5432 database: cache_db - allow_migration_for_empty_database: false \ No newline at end of file + allow_migration_for_empty_database: false diff --git a/pyproject.toml b/pyproject.toml index 862155f..9ebd7c9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,7 +11,7 @@ requires-python = ">=3.11.0" dependencies = [ "alembic", - "psycopg2", + "psycopg[binary]", "pydantic>=2.0.0", "PyYAML", "wiremind-kubernetes~=7.0", @@ -76,4 +76,4 @@ known-first-party = ["chartreuse"] log_level = "INFO" # Deterministic ordering for tests; useful for pytest-xdist. env = ["PYTHONHASHSEED=0"] -filterwarnings = ["ignore::pytest.PytestUnknownMarkWarning"] \ No newline at end of file +filterwarnings = ["ignore::pytest.PytestUnknownMarkWarning"] diff --git a/requirements.txt b/requirements.txt index 84c02ef..d25dff0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -28,8 +28,10 @@ markupsafe==3.0.3 # via mako oauthlib==3.3.1 # via requests-oauthlib -psycopg2==2.9.10 +psycopg==3.3.2 # via chartreuse (pyproject.toml) +psycopg-binary==3.3.2 + # via psycopg pyasn1==0.6.1 # via # pyasn1-modules diff --git a/scripts/validate_config.py b/scripts/validate_config.py index 828084d..3fc353a 100644 --- a/scripts/validate_config.py +++ b/scripts/validate_config.py @@ -86,9 +86,9 @@ def validate_config(config_path: str) -> bool: print(f" 📍 Built URL: {url}") # Basic URL format validation - if not url.startswith(("postgresql://", "mysql://", "sqlite://")): + if not url.startswith(("postgresql+psycopg://", "mysql://", "sqlite://")): print( - f"⚠️ Database {db_name}: URL format may be invalid (expected postgresql://, mysql://, or sqlite://)" + f"⚠️ Database {db_name}: URL format may be invalid (expected postgresql+psycopg://, mysql://, or sqlite://)" ) except ValueError as e: diff --git a/src/chartreuse/config_loader.py b/src/chartreuse/config_loader.py index 85fc50d..9e3e911 100644 --- a/src/chartreuse/config_loader.py +++ b/src/chartreuse/config_loader.py @@ -39,7 +39,7 @@ def url(self) -> str: @classmethod def validate_dialect(cls, v: str) -> str: """Validate database dialect.""" - supported_dialects = ["postgresql", "mysql", "sqlite", "oracle", "mssql", "clickhouse"] + supported_dialects = ["postgresql+psycopg", "mysql", "sqlite", "oracle", "mssql", "clickhouse"] if v.lower() not in supported_dialects: logger.warning("Dialect '%s' might not be supported. Supported dialects: %s", v, supported_dialects) return v @@ -86,7 +86,7 @@ def load_multi_database_config(config_path: str) -> dict[str, DatabaseConfig]: ```yaml databases: main: # Database name/identifier - dialect: postgresql + dialect: postgresql+psycopg user: app_user password: app_password host: postgres-main @@ -99,7 +99,7 @@ def load_multi_database_config(config_path: str) -> dict[str, DatabaseConfig]: # For single database setups, just include one database: # analytics: - # dialect: postgresql + # dialect: postgresql+psycopg # user: analytics_user # password: analytics_password # host: postgres-analytics diff --git a/src/chartreuse/tests/e2e_tests/conftest.py b/src/chartreuse/tests/e2e_tests/conftest.py index bed5fe4..2a563c0 100644 --- a/src/chartreuse/tests/e2e_tests/conftest.py +++ b/src/chartreuse/tests/e2e_tests/conftest.py @@ -23,7 +23,7 @@ ALEMBIC_PATH = os.path.join(EXAMPLE_PATH, "alembic") # Calculated from deployed test helm chart + kubectl exec -POSTGRESQL_URL = "postgresql://foo:foo@localhost/foo?sslmode=prefer" +POSTGRESQL_URL = "postgresql+psycopg://foo:foo@localhost/foo?sslmode=prefer" def _cluster_init(include_chartreuse: bool, pre_upgrade: bool = False) -> Generator: diff --git a/src/chartreuse/tests/unit_tests/test_alembic.py b/src/chartreuse/tests/unit_tests/test_alembic.py index f478a44..d487a1c 100644 --- a/src/chartreuse/tests/unit_tests/test_alembic.py +++ b/src/chartreuse/tests/unit_tests/test_alembic.py @@ -45,7 +45,7 @@ def test_detect_needed_migration(mocker: MockerFixture) -> None: Test that chartreuse detects that a migration is needed. """ sample_alembic_output = """ -2018-11-29 17:58:32 - wiremind_python.settings - DEBUG - Database: postgresql://***/public +2018-11-29 17:58:32 - wiremind_python.settings - DEBUG - Database: postgresql+psycopg://***/public 2018-11-29 17:58:32 - wiremind_python.settings - DEBUG - redis instance at localhost is activated 2018-11-29 17:58:32 - alembic.runtime.migration - INFO - Context impl PostgresqlImpl. 2018-11-29 17:58:32 - alembic.runtime.migration - INFO - Will assume transactional DDL. @@ -72,7 +72,7 @@ def test_detect_not_needed_migration(mocker: MockerFixture) -> None: Test that chartreuse detects that a migration is not needed. """ sample_alembic_output = """ -2018-11-29 17:58:32 - wiremind_python.settings - DEBUG - Database: postgresql://***/public +2018-11-29 17:58:32 - wiremind_python.settings - DEBUG - Database: postgresql+psycopg://***/public 2018-11-29 17:58:32 - wiremind_python.settings - DEBUG - redis instance at localhost is activated 2018-11-29 17:58:32 - alembic.runtime.migration - INFO - Context impl PostgresqlImpl. 2018-11-29 17:58:32 - alembic.runtime.migration - INFO - Will assume transactional DDL. @@ -205,7 +205,7 @@ def test_multi_database_configuration_postgresql_section(mocker: MockerFixture) # Sample alembic.ini content with multiple sections sample_alembic_ini = """[postgresql] script_location = postgresl -sqlalchemy.url = postgresql://wiremind_owner@localhost:5432/wiremind +sqlalchemy.url = postgresql+psycopg://wiremind_owner@localhost:5432/wiremind prepend_sys_path = .. file_template = %%(year)d%%(month).2d%%(day).2d-%%(slug)s @@ -229,7 +229,7 @@ def test_multi_database_configuration_postgresql_section(mocker: MockerFixture) chartreuse.utils.AlembicMigrationHelper( alembic_directory_path=temp_dir, alembic_config_file_path="alembic.ini", - database_url="postgresql://new_user:new_pass@new_host:5432/new_db", + database_url="postgresql+psycopg://new_user:new_pass@new_host:5432/new_db", alembic_section_name="postgresql", configure=True, skip_db_checks=True, @@ -240,7 +240,7 @@ def test_multi_database_configuration_postgresql_section(mocker: MockerFixture) content = f.read() # Verify PostgreSQL URL was updated - assert "postgresql://new_user:new_pass@new_host:5432/new_db" in content + assert "postgresql+psycopg://new_user:new_pass@new_host:5432/new_db" in content # Verify ClickHouse URL was NOT changed assert "clickhouse://default@localhost:8123/wiremind" in content # Verify sections are still intact @@ -256,7 +256,7 @@ def test_multi_database_configuration_clickhouse_section(mocker: MockerFixture) # Sample alembic.ini content with multiple sections sample_alembic_ini = """[postgresql] script_location = postgresl -sqlalchemy.url = postgresql://wiremind_owner@localhost:5432/wiremind +sqlalchemy.url = postgresql+psycopg://wiremind_owner@localhost:5432/wiremind prepend_sys_path = .. file_template = %%(year)d%%(month).2d%%(day).2d-%%(slug)s @@ -293,7 +293,7 @@ def test_multi_database_configuration_clickhouse_section(mocker: MockerFixture) # Verify ClickHouse URL was updated assert "clickhouse://new_user:new_pass@new_host:8123/new_db" in content # Verify PostgreSQL URL was NOT changed - assert "postgresql://wiremind_owner@localhost:5432/wiremind" in content + assert "postgresql+psycopg://wiremind_owner@localhost:5432/wiremind" in content # Verify sections are still intact assert "[postgresql]" in content assert "[clickhouse]" in content @@ -307,7 +307,7 @@ def test_multi_database_configuration_both_sections(mocker: MockerFixture) -> No # Sample alembic.ini content with multiple sections sample_alembic_ini = """[postgresql] script_location = postgresl -sqlalchemy.url = postgresql://wiremind_owner@localhost:5432/wiremind +sqlalchemy.url = postgresql+psycopg://wiremind_owner@localhost:5432/wiremind prepend_sys_path = .. file_template = %%(year)d%%(month).2d%%(day).2d-%%(slug)s @@ -331,7 +331,7 @@ def test_multi_database_configuration_both_sections(mocker: MockerFixture) -> No chartreuse.utils.AlembicMigrationHelper( alembic_directory_path=temp_dir, alembic_config_file_path="alembic.ini", - database_url="postgresql://pg_user:pg_pass@pg_host:5432/pg_db", + database_url="postgresql+psycopg://pg_user:pg_pass@pg_host:5432/pg_db", alembic_section_name="postgresql", configure=True, skip_db_checks=True, @@ -352,10 +352,10 @@ def test_multi_database_configuration_both_sections(mocker: MockerFixture) -> No final_content = f.read() # Verify both URLs are now updated correctly - assert "postgresql://pg_user:pg_pass@pg_host:5432/pg_db" in final_content + assert "postgresql+psycopg://pg_user:pg_pass@pg_host:5432/pg_db" in final_content assert "clickhouse://ch_user:ch_pass@ch_host:8123/ch_db" in final_content # Verify original URLs are gone - assert "postgresql://wiremind_owner@localhost:5432/wiremind" not in final_content + assert "postgresql+psycopg://wiremind_owner@localhost:5432/wiremind" not in final_content assert "clickhouse://default@localhost:8123/wiremind" not in final_content # Verify sections are still intact assert "[postgresql]" in final_content @@ -370,7 +370,7 @@ def test_single_database_configuration_with_alembic_section(mocker: MockerFixtur # Sample simple alembic.ini content (single database) sample_alembic_ini = """[alembic] script_location = alembic -sqlalchemy.url = postgresql://old@localhost:5432/old +sqlalchemy.url = postgresql+psycopg://old@localhost:5432/old prepend_sys_path = .. file_template = %%(year)d%%(month).2d%%(day).2d-%%(slug)s """ @@ -385,7 +385,7 @@ def test_single_database_configuration_with_alembic_section(mocker: MockerFixtur chartreuse.utils.AlembicMigrationHelper( alembic_directory_path=temp_dir, alembic_config_file_path="alembic.ini", - database_url="postgresql://new_user:new_pass@new_host:5432/new_db", + database_url="postgresql+psycopg://new_user:new_pass@new_host:5432/new_db", alembic_section_name="alembic", configure=True, skip_db_checks=True, @@ -396,8 +396,8 @@ def test_single_database_configuration_with_alembic_section(mocker: MockerFixtur content = f.read() # Verify URL was updated - assert "postgresql://new_user:new_pass@new_host:5432/new_db" in content + assert "postgresql+psycopg://new_user:new_pass@new_host:5432/new_db" in content # Verify original URL is gone - assert "postgresql://old@localhost:5432/old" not in content + assert "postgresql+psycopg://old@localhost:5432/old" not in content # Verify section is still intact assert "[alembic]" in content diff --git a/src/chartreuse/tests/unit_tests/test_chartreuse.py b/src/chartreuse/tests/unit_tests/test_chartreuse.py index d30e074..3945842 100644 --- a/src/chartreuse/tests/unit_tests/test_chartreuse.py +++ b/src/chartreuse/tests/unit_tests/test_chartreuse.py @@ -45,7 +45,7 @@ def test_chartreuse_init_with_kubernetes_helper(self, mocker: MockerFixture) -> # Use the new dictionary format with DatabaseConfig objects databases_config = { "test-db": DatabaseConfig( - dialect="postgresql", + dialect="postgresql+psycopg", user="user", password="pass", host="localhost", @@ -68,7 +68,7 @@ def test_chartreuse_init_with_kubernetes_helper(self, mocker: MockerFixture) -> mock_alembic_helper.assert_called_once_with( alembic_directory_path="/app/alembic", alembic_config_file_path="alembic.ini", - database_url="postgresql://user:pass@localhost:5432/db", + database_url="postgresql+psycopg://user:pass@localhost:5432/db", allow_migration_for_empty_database=True, additional_parameters="--verbose -n test-db", alembic_section_name="test-db", @@ -97,7 +97,7 @@ def test_chartreuse_init_without_kubernetes_helper(self, mocker: MockerFixture) # Use the new dictionary format with DatabaseConfig objects databases_config = { "test-db": DatabaseConfig( - dialect="postgresql", + dialect="postgresql+psycopg", user="user", password="pass", host="localhost", @@ -134,7 +134,7 @@ def test_check_migration_needed(self, mocker: MockerFixture) -> None: # Use the new dictionary format with DatabaseConfig objects databases_config = { "test-db": DatabaseConfig( - dialect="postgresql", + dialect="postgresql+psycopg", user="user", password="pass", host="localhost", @@ -174,7 +174,7 @@ def test_upgrade_when_migration_needed(self, mocker: MockerFixture) -> None: # Use the new dictionary format with DatabaseConfig objects databases_config = { "test-db": DatabaseConfig( - dialect="postgresql", + dialect="postgresql+psycopg", user="user", password="pass", host="localhost", @@ -211,7 +211,7 @@ def test_upgrade_when_migration_not_needed(self, mocker: MockerFixture) -> None: # Use the new dictionary format with DatabaseConfig objects databases_config = { "test-db": DatabaseConfig( - dialect="postgresql", + dialect="postgresql+psycopg", user="user", password="pass", host="localhost", @@ -262,7 +262,7 @@ def test_multi_chartreuse_init_with_kubernetes_helper(self, mocker: MockerFixtur databases_config = { "main": DatabaseConfig( - dialect="postgresql", + dialect="postgresql+psycopg", user="user", password="pass", host="localhost", @@ -274,7 +274,7 @@ def test_multi_chartreuse_init_with_kubernetes_helper(self, mocker: MockerFixtur additional_parameters="--verbose", ), "secondary": DatabaseConfig( - dialect="postgresql", + dialect="postgresql+psycopg", user="user", password="pass", host="localhost", @@ -324,7 +324,7 @@ def test_multi_chartreuse_init_without_kubernetes_helper(self, mocker: MockerFix databases_config = { "test": DatabaseConfig( - dialect="postgresql", + dialect="postgresql+psycopg", user="user", password="pass", host="localhost", @@ -363,7 +363,7 @@ def test_check_migration_needed_with_mixed_needs(self, mocker: MockerFixture) -> databases_config = { "main": DatabaseConfig( - dialect="postgresql", + dialect="postgresql+psycopg", user="user", password="pass", host="localhost", @@ -373,7 +373,7 @@ def test_check_migration_needed_with_mixed_needs(self, mocker: MockerFixture) -> alembic_config_file_path="alembic.ini", ), "secondary": DatabaseConfig( - dialect="postgresql", + dialect="postgresql+psycopg", user="user", password="pass", host="localhost", @@ -407,7 +407,7 @@ def test_check_migration_needed_none_need_migration(self, mocker: MockerFixture) databases_config = { "test": DatabaseConfig( - dialect="postgresql", + dialect="postgresql+psycopg", user="user", password="pass", host="localhost", @@ -445,7 +445,7 @@ def test_upgrade_only_needed_databases(self, mocker: MockerFixture) -> None: databases_config = { "main": DatabaseConfig( - dialect="postgresql", + dialect="postgresql+psycopg", user="user", password="pass", host="localhost", @@ -455,7 +455,7 @@ def test_upgrade_only_needed_databases(self, mocker: MockerFixture) -> None: alembic_config_file_path="alembic.ini", ), "secondary": DatabaseConfig( - dialect="postgresql", + dialect="postgresql+psycopg", user="user", password="pass", host="localhost", @@ -490,7 +490,7 @@ def test_multi_chartreuse_default_values(self, mocker: MockerFixture) -> None: databases_config = { "test": DatabaseConfig( - dialect="postgresql", + dialect="postgresql+psycopg", user="user", password="pass", host="localhost", @@ -512,7 +512,7 @@ def test_multi_chartreuse_default_values(self, mocker: MockerFixture) -> None: mock_alembic_helper.assert_called_once_with( alembic_directory_path="/app/alembic", alembic_config_file_path="alembic.ini", - database_url="postgresql://user:pass@localhost:5432/db", + database_url="postgresql+psycopg://user:pass@localhost:5432/db", allow_migration_for_empty_database=True, # Default value from DatabaseConfig additional_parameters="-n test", # Section name parameter added (no leading space when original is empty) alembic_section_name="test", # New parameter for multi-database support diff --git a/src/chartreuse/tests/unit_tests/test_chartreuse_upgrade_extended.py b/src/chartreuse/tests/unit_tests/test_chartreuse_upgrade_extended.py index 2c82f5e..c671d20 100644 --- a/src/chartreuse/tests/unit_tests/test_chartreuse_upgrade_extended.py +++ b/src/chartreuse/tests/unit_tests/test_chartreuse_upgrade_extended.py @@ -87,7 +87,7 @@ def test_main_multi_database_success(self, mocker: MockerFixture) -> None: mock_config = [ { "name": "main", - "url": "postgresql://user:pass@localhost:5432/maindb", + "url": "postgresql+psycopg://user:pass@localhost:5432/maindb", "alembic_directory_path": "/app/alembic/main", "alembic_config_file_path": "alembic.ini", } @@ -140,7 +140,7 @@ def test_main_multi_database_no_migration_needed(self, mocker: MockerFixture) -> mock_config = [ { "name": "main", - "url": "postgresql://user:pass@localhost:5432/maindb", + "url": "postgresql+psycopg://user:pass@localhost:5432/maindb", "alembic_directory_path": "/app/alembic/main", "alembic_config_file_path": "alembic.ini", } @@ -208,7 +208,7 @@ def test_main_multi_database_stop_pods_disabled(self, mocker: MockerFixture) -> mock_config = [ { "name": "main", - "url": "postgresql://user:pass@localhost:5432/maindb", + "url": "postgresql+psycopg://user:pass@localhost:5432/maindb", "alembic_directory_path": "/app/alembic/main", "alembic_config_file_path": "alembic.ini", } @@ -256,7 +256,7 @@ def test_main_multi_database_upgrade_before_deployment(self, mocker: MockerFixtu mock_config = [ { "name": "main", - "url": "postgresql://user:pass@localhost:5432/maindb", + "url": "postgresql+psycopg://user:pass@localhost:5432/maindb", "alembic_directory_path": "/app/alembic/main", "alembic_config_file_path": "alembic.ini", } @@ -304,7 +304,7 @@ def test_main_multi_database_start_pods_failure(self, mocker: MockerFixture) -> mock_config = [ { "name": "main", - "url": "postgresql://user:pass@localhost:5432/maindb", + "url": "postgresql+psycopg://user:pass@localhost:5432/maindb", "alembic_directory_path": "/app/alembic/main", "alembic_config_file_path": "alembic.ini", } @@ -361,7 +361,7 @@ def test_main_single_database_success(self, mocker: MockerFixture) -> None: mock_config = [ { "name": "main", - "url": "postgresql://user:pass@localhost:5432/db", + "url": "postgresql+psycopg://user:pass@localhost:5432/db", "alembic_directory_path": "/app/alembic", "alembic_config_file_path": "alembic.ini", "alembic_allow_migration_for_empty_database": True, @@ -421,7 +421,7 @@ def test_main_single_database_default_values(self, mocker: MockerFixture) -> Non mock_config = [ { "name": "main", - "url": "postgresql://user:pass@localhost:5432/db", + "url": "postgresql+psycopg://user:pass@localhost:5432/db", "alembic_directory_path": "/app/alembic", "alembic_config_file_path": "alembic.ini", "alembic_allow_migration_for_empty_database": False, @@ -494,7 +494,7 @@ def test_boolean_parsing_variations(self, mocker: MockerFixture, bool_str: str, mock_config = [ { "name": "main", - "url": "postgresql://user:pass@localhost:5432/db", + "url": "postgresql+psycopg://user:pass@localhost:5432/db", "alembic_directory_path": "/app/alembic", "alembic_config_file_path": "alembic.ini", } diff --git a/src/chartreuse/tests/unit_tests/test_config_loader.py b/src/chartreuse/tests/unit_tests/test_config_loader.py index 17472c3..bbb23da 100644 --- a/src/chartreuse/tests/unit_tests/test_config_loader.py +++ b/src/chartreuse/tests/unit_tests/test_config_loader.py @@ -19,7 +19,7 @@ class TestDatabaseConfig: def test_valid_database_config(self): """Test creating a valid database configuration.""" config_data = { - "dialect": "postgresql", + "dialect": "postgresql+psycopg", "user": "testuser", "password": "testpass", "host": "localhost", @@ -30,7 +30,7 @@ def test_valid_database_config(self): config = DatabaseConfig(**config_data) - assert config.dialect == "postgresql" + assert config.dialect == "postgresql+psycopg" assert config.user == "testuser" assert config.password == "testpass" assert config.host == "localhost" @@ -44,7 +44,7 @@ def test_valid_database_config(self): def test_database_config_url_computation(self): """Test that the URL is computed correctly from components.""" config = DatabaseConfig( - dialect="postgresql", + dialect="postgresql+psycopg", user="myuser", password="mypass", host="example.com", @@ -53,7 +53,7 @@ def test_database_config_url_computation(self): alembic_directory_path="/app/alembic", ) - expected_url = "postgresql://myuser:mypass@example.com:5432/mydb" + expected_url = "postgresql+psycopg://myuser:mypass@example.com:5432/mydb" assert config.url == expected_url def test_database_config_with_optional_fields(self): @@ -80,7 +80,7 @@ def test_database_config_with_optional_fields(self): def test_database_config_missing_required_fields(self): """Test that missing required fields raise validation errors.""" incomplete_config = { - "dialect": "postgresql", + "dialect": "postgresql+psycopg", "user": "testuser", # Missing password, host, port, database, alembic_directory_path } @@ -99,7 +99,7 @@ def test_database_config_invalid_port(self): # Test port too small with pytest.raises(ValidationError) as excinfo: DatabaseConfig( - dialect="postgresql", + dialect="postgresql+psycopg", user="testuser", password="testpass", host="localhost", @@ -112,7 +112,7 @@ def test_database_config_invalid_port(self): # Test port too large with pytest.raises(ValidationError) as excinfo: DatabaseConfig( - dialect="postgresql", + dialect="postgresql+psycopg", user="testuser", password="testpass", host="localhost", @@ -126,7 +126,7 @@ def test_database_config_dialect_validation(self): """Test dialect validation with supported and unsupported dialects.""" # Test supported dialect config = DatabaseConfig( - dialect="postgresql", + dialect="postgresql+psycopg", user="testuser", password="testpass", host="localhost", @@ -134,7 +134,7 @@ def test_database_config_dialect_validation(self): database="testdb", alembic_directory_path="/app/alembic", ) - assert config.dialect == "postgresql" + assert config.dialect == "postgresql+psycopg" # Test unsupported dialect (should still work but log warning) config = DatabaseConfig( @@ -151,7 +151,7 @@ def test_database_config_dialect_validation(self): def test_additional_parameters_empty_string_handling(self): """Test that additional_parameters defaults to empty string when not provided.""" config = DatabaseConfig( - dialect="postgresql", + dialect="postgresql+psycopg", user="testuser", password="testpass", host="localhost", @@ -168,7 +168,7 @@ class TestMultiDatabaseConfig: def test_valid_multi_database_config(self): """Test creating a valid multi-database configuration.""" db_config = DatabaseConfig( - dialect="postgresql", + dialect="postgresql+psycopg", user="testuser", password="testpass", host="localhost", @@ -185,7 +185,7 @@ def test_valid_multi_database_config(self): def test_multi_database_config_multiple_databases(self): """Test multi-database configuration with multiple databases.""" db1 = DatabaseConfig( - dialect="postgresql", + dialect="postgresql+psycopg", user="user1", password="pass1", host="host1", @@ -236,7 +236,7 @@ def test_load_valid_config_file(self): config_content = { "databases": { "main": { - "dialect": "postgresql", + "dialect": "postgresql+psycopg", "user": "testuser", "password": "testpass", "host": "localhost", @@ -270,7 +270,7 @@ def test_load_valid_config_file(self): # Check main database main_db = databases["main"] - assert main_db.dialect == "postgresql" + assert main_db.dialect == "postgresql+psycopg" assert main_db.user == "testuser" assert main_db.password == "testpass" assert main_db.host == "localhost" @@ -278,7 +278,7 @@ def test_load_valid_config_file(self): assert main_db.database == "testdb" assert main_db.alembic_directory_path == "/app/alembic" assert main_db.allow_migration_for_empty_database is True # default - assert main_db.url == "postgresql://testuser:testpass@localhost:5432/testdb" + assert main_db.url == "postgresql+psycopg://testuser:testpass@localhost:5432/testdb" # Check analytics database analytics_db = databases["analytics"] @@ -295,7 +295,7 @@ def test_load_single_database_config(self): config_content = { "databases": { "main": { - "dialect": "postgresql", + "dialect": "postgresql+psycopg", "user": "testuser", "password": "testpass", "host": "localhost", @@ -316,7 +316,7 @@ def test_load_single_database_config(self): assert len(databases) == 1 assert "main" in databases main_db = databases["main"] - assert main_db.dialect == "postgresql" + assert main_db.dialect == "postgresql+psycopg" finally: Path(config_path).unlink() @@ -330,7 +330,7 @@ def test_load_nonexistent_file(self): def test_load_invalid_yaml(self): """Test loading a file with invalid YAML.""" - invalid_yaml = "databases:\n main:\n dialect: postgresql\n invalid: yaml: content:" + invalid_yaml = "databases:\n main:\n dialect: postgresql+psycopg\n invalid: yaml: content:" with tempfile.NamedTemporaryFile(mode="w", suffix=".yaml", delete=False) as f: f.write(invalid_yaml) @@ -350,7 +350,7 @@ def test_load_config_missing_required_fields(self): config_content = { "databases": { "main": { - "dialect": "postgresql", + "dialect": "postgresql+psycopg", "user": "testuser", # Missing required fields: password, host, port, database, alembic_directory_path } @@ -409,7 +409,7 @@ def test_load_config_with_all_optional_fields(self): config_content = { "databases": { "main": { - "dialect": "postgresql", + "dialect": "postgresql+psycopg", "user": "testuser", "password": "testpass", "host": "localhost", @@ -445,7 +445,7 @@ def test_load_config_logs_info(self, mock_logger): config_content = { "databases": { "main": { - "dialect": "postgresql", + "dialect": "postgresql+psycopg", "user": "testuser", "password": "testpass", "host": "localhost",