Skip to content

Commit a0c24be

Browse files
Dhanush010karenc-bq
authored andcommitted
Fix Python 3.12+ test failures: Use real dialect instances for isinstance checks
- Replace MagicMock with real AuroraPgDialect instances in test fixtures - Fix test_connection_provider to use real class implementing CanReleaseResources - Fix test_limitless_plugin to use real AuroraPgDialect for dialect checks - Fix test_multi_az_rds_host_list_provider and test_rds_host_list_provider to use real AuroraPgDialect - Python 3.12+ has stricter isinstance() checks with Protocols/ABCs - Maintains backward compatibility with Python 3.8-3.11
1 parent c300893 commit a0c24be

File tree

7 files changed

+69
-12
lines changed

7 files changed

+69
-12
lines changed

.github/workflows/integration_tests.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ jobs:
1717
strategy:
1818
fail-fast: false
1919
matrix:
20-
python-version: [ "3.11" ]
20+
python-version: [ "3.11", "3.12", "3.13" ]
2121
environment: [ "mysql", "pg" ]
2222

2323
steps:
@@ -71,7 +71,7 @@ jobs:
7171
strategy:
7272
fail-fast: false
7373
matrix:
74-
python-version: [ "3.11" ]
74+
python-version: [ "3.11", "3.12", "3.13" ]
7575
environment: ["mysql", "pg"]
7676

7777
steps:

tests/unit/test_connection_provider.py

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,31 @@ def default_provider_mock(mocker):
3333

3434
@pytest.fixture
3535
def set_provider_mock(mocker):
36-
return mocker.MagicMock()
36+
# In Python 3.12+, isinstance checks with Protocols are stricter
37+
# Create a real instance that implements the protocol, then wrap release_resources
38+
# with a mock to allow method call tracking
39+
class MockConnectionProviderWithRelease:
40+
"""Mock connection provider that implements CanReleaseResources protocol."""
41+
def accepts_host_info(self, host_info, props):
42+
return True
43+
44+
def accepts_strategy(self, role, strategy):
45+
return True
46+
47+
def get_host_info_by_strategy(self, hosts, role, strategy, props):
48+
return hosts[0] if hosts else None
49+
50+
def connect(self, target_func, driver_dialect, database_dialect, host_info, props):
51+
return None
52+
53+
def release_resources(self):
54+
pass
55+
56+
# Create a real instance
57+
provider = MockConnectionProviderWithRelease()
58+
# Replace release_resources with a MagicMock so we can assert it was called
59+
provider.release_resources = mocker.MagicMock()
60+
return provider
3761

3862

3963
@pytest.fixture
@@ -177,4 +201,4 @@ def test_release_resources(connection_mock, default_provider_mock, set_provider_
177201
ConnectionProviderManager.set_connection_provider(set_provider_mock)
178202
ConnectionProviderManager.release_resources()
179203

180-
connection_provider_manager._conn_provider.release_resources.assert_called_once()
204+
set_provider_mock.release_resources.assert_called_once()

tests/unit/test_limitless_plugin.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414
import psycopg
1515
import pytest
1616

17-
from aws_advanced_python_wrapper.database_dialect import (DatabaseDialect,
17+
from aws_advanced_python_wrapper.database_dialect import (AuroraPgDialect,
18+
DatabaseDialect,
1819
MysqlDatabaseDialect)
1920
from aws_advanced_python_wrapper.errors import (AwsWrapperError,
2021
UnsupportedOperationError)
@@ -36,6 +37,8 @@ def mock_plugin_service(mocker, mock_driver_dialect, mock_conn, host_info):
3637
service_mock = mocker.MagicMock()
3738
service_mock.current_connection = mock_conn
3839
service_mock.current_host_info = host_info
40+
# Use a real AuroraPgDialect to pass isinstance checks in Python 3.12+
41+
service_mock.database_dialect = AuroraPgDialect()
3942

4043
type(service_mock).driver_dialect = mocker.PropertyMock(return_value=mock_driver_dialect)
4144
return service_mock
@@ -125,7 +128,8 @@ def test_connect_supported_dialect_after_refresh(
125128
mocker, plugin, host_info, props, mock_conn, mock_plugin_service, mock_limitless_router_service, mock_driver_dialect
126129
):
127130
unsupported_dialect: DatabaseDialect = MysqlDatabaseDialect()
128-
type(mock_plugin_service).database_dialect = PropertyMock(side_effect=[unsupported_dialect, mock_driver_dialect])
131+
supported_dialect: DatabaseDialect = AuroraPgDialect()
132+
type(mock_plugin_service).database_dialect = PropertyMock(side_effect=[unsupported_dialect, supported_dialect])
129133

130134
def replace_context_connection(invocation):
131135
context = invocation._connection_plugin._context

tests/unit/test_multi_az_rds_host_list_provider.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import psycopg
1818
import pytest
1919

20+
from aws_advanced_python_wrapper.database_dialect import AuroraPgDialect
2021
from aws_advanced_python_wrapper.errors import (AwsWrapperError,
2122
QueryTimeoutError)
2223
from aws_advanced_python_wrapper.host_list_provider import (
@@ -59,7 +60,10 @@ def mock_cursor(mocker):
5960

6061
@pytest.fixture
6162
def mock_provider_service(mocker):
62-
return mocker.MagicMock()
63+
service_mock = mocker.MagicMock()
64+
# Use a real AuroraPgDialect to pass isinstance checks in Python 3.12+
65+
service_mock.database_dialect = AuroraPgDialect()
66+
return service_mock
6367

6468

6569
@pytest.fixture

tests/unit/test_mysql_driver_dialect.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,24 @@
1414

1515
import psycopg
1616
import pytest
17-
from mysql.connector import CMySQLConnection
18-
from mysql.connector.cursor_cext import CMySQLCursor
1917

2018
from aws_advanced_python_wrapper.errors import AwsWrapperError
2119
from aws_advanced_python_wrapper.hostinfo import HostInfo
2220
from aws_advanced_python_wrapper.mysql_driver_dialect import MySQLDriverDialect
2321
from aws_advanced_python_wrapper.utils.properties import (Properties,
2422
WrapperProperties)
2523

24+
try:
25+
from mysql.connector import CMySQLConnection
26+
from mysql.connector.cursor_cext import CMySQLCursor
27+
except ImportError:
28+
# CMySQLConnection not available (e.g., Python 3.13 with mysql-connector-python 9.0.0)
29+
# Skip all tests in this module if C extension is not available
30+
pytest.skip(
31+
"CMySQLConnection not available (C extension not supported on this Python version)",
32+
allow_module_level=True
33+
)
34+
2635

2736
@pytest.fixture
2837
def dialect():

tests/unit/test_pg_driver_dialect.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414

1515
import psycopg
1616
import pytest
17-
from mysql.connector import CMySQLConnection
1817
from sqlalchemy import PoolProxiedConnection
1918

2019
from aws_advanced_python_wrapper.errors import AwsWrapperError
@@ -23,6 +22,14 @@
2322
from aws_advanced_python_wrapper.utils.properties import (Properties,
2423
WrapperProperties)
2524

25+
try:
26+
from mysql.connector import CMySQLConnection
27+
HAS_C_MYSQL_CONNECTION = True
28+
except ImportError:
29+
# CMySQLConnection not available (e.g., Python 3.13 with mysql-connector-python 9.0.0)
30+
HAS_C_MYSQL_CONNECTION = False
31+
CMySQLConnection = None
32+
2633

2734
@pytest.fixture
2835
def mock_conn(mocker):
@@ -40,7 +47,12 @@ def mock_pool_conn(mocker, mock_conn):
4047

4148
@pytest.fixture
4249
def mock_invalid_conn(mocker):
43-
return mocker.MagicMock(spec=CMySQLConnection)
50+
if HAS_C_MYSQL_CONNECTION:
51+
return mocker.MagicMock(spec=CMySQLConnection)
52+
else:
53+
# Use a different invalid connection type when CMySQLConnection is not available
54+
# This simulates an invalid connection type for error testing
55+
return mocker.MagicMock(spec=object)
4456

4557

4658
@pytest.fixture

tests/unit/test_rds_host_list_provider.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import psycopg
1919
import pytest
2020

21+
from aws_advanced_python_wrapper.database_dialect import AuroraPgDialect
2122
from aws_advanced_python_wrapper.errors import (AwsWrapperError,
2223
QueryTimeoutError)
2324
from aws_advanced_python_wrapper.host_list_provider import RdsHostListProvider
@@ -58,7 +59,10 @@ def mock_cursor(mocker):
5859

5960
@pytest.fixture
6061
def mock_provider_service(mocker):
61-
return mocker.MagicMock()
62+
service_mock = mocker.MagicMock()
63+
# Use a real AuroraPgDialect to pass isinstance checks in Python 3.12+
64+
service_mock.database_dialect = AuroraPgDialect()
65+
return service_mock
6266

6367

6468
@pytest.fixture

0 commit comments

Comments
 (0)