|
| 1 | +import uuid |
1 | 2 | from datetime import date, datetime, time, timedelta, timezone |
2 | | -from typing import Any |
| 3 | +from typing import Annotated, Any |
| 4 | +from unittest.mock import MagicMock, PropertyMock |
3 | 5 |
|
4 | 6 | import pytest |
5 | | -from sqlalchemy import Column, Date, DateTime, ForeignKey, Integer, String, Time |
| 7 | +from sqlalchemy import Column, Date, DateTime, ForeignKey, Integer, String, Time, Uuid |
6 | 8 | from sqlalchemy.orm import declarative_base |
7 | 9 |
|
8 | 10 | from sqladmin.helpers import ( |
| 11 | + get_column_python_type, |
9 | 12 | get_object_identifier, |
10 | 13 | is_falsy_value, |
11 | 14 | object_identifier_values, |
@@ -147,3 +150,45 @@ def test_case(ident): |
147 | 150 |
|
148 | 151 | test_case("Missing;1") |
149 | 152 | test_case("Johnson;7;A;Extra") |
| 153 | + |
| 154 | + |
| 155 | +class UUIDPKModel(Base): |
| 156 | + __tablename__ = "uuid_pk_model" |
| 157 | + id = Column(Uuid, primary_key=True) |
| 158 | + |
| 159 | + |
| 160 | +def test_get_column_python_type_with_uuid_pk(): |
| 161 | + """Regression #981: must not raise TypeError when python_type |
| 162 | + returns a type annotation instead of a plain class.""" |
| 163 | + pk = UUIDPKModel.__table__.c["id"] |
| 164 | + result = get_column_python_type(pk) |
| 165 | + assert callable(result) |
| 166 | + |
| 167 | + |
| 168 | +def test_get_column_python_type_annotated_type_no_typeerror(): |
| 169 | + """When python_type returns Annotated[uuid.UUID, ...], issubclass |
| 170 | + must not be called on it — no TypeError should be raised.""" |
| 171 | + mock_col = MagicMock() |
| 172 | + mock_col.type.python_type = Annotated[uuid.UUID, "meta"] |
| 173 | + # Before the fix: TypeError: issubclass() arg 1 must be a class |
| 174 | + result = get_column_python_type(mock_col) |
| 175 | + assert callable(result) |
| 176 | + |
| 177 | + |
| 178 | +def test_get_column_python_type_annotated_returns_origin(): |
| 179 | + """When python_type is Annotated[uuid.UUID, ...], the returned |
| 180 | + type should resolve to the origin class (uuid.UUID).""" |
| 181 | + mock_col = MagicMock() |
| 182 | + mock_col.type.python_type = Annotated[uuid.UUID, "meta"] |
| 183 | + result = get_column_python_type(mock_col) |
| 184 | + assert result is uuid.UUID |
| 185 | + |
| 186 | + |
| 187 | +def test_get_column_python_type_not_implemented_no_impl(): |
| 188 | + """Falls back to str when python_type raises NotImplementedError |
| 189 | + and there is no impl.""" |
| 190 | + mock_col = MagicMock(spec=["type"]) |
| 191 | + t = MagicMock(spec=["python_type"]) |
| 192 | + type(t).python_type = PropertyMock(side_effect=NotImplementedError) |
| 193 | + mock_col.type = t |
| 194 | + assert get_column_python_type(mock_col) is str |
0 commit comments