Skip to content

Commit 9e8ff99

Browse files
authored
Merge pull request #7 from h0rn3t/uuid-fix-2
add UUID support in dialect; enhance tests for Mapped[uuid.UUID] beha…
2 parents 9dfde90 + 0bbaba3 commit 9e8ff99

4 files changed

Lines changed: 58 additions & 3 deletions

File tree

psqlpy_sqlalchemy/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22

33
PsqlpyDialect = PSQLPyAsyncDialect
44

5-
__version__ = "0.1.1b1"
5+
__version__ = "0.1.1b2"
66
__all__ = ["PsqlpyDialect", "PSQLPyAsyncDialect"]

psqlpy_sqlalchemy/dialect.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,7 @@ class PSQLPyAsyncDialect(PGDialect):
331331
sqltypes.SmallInteger: _PGSmallInteger,
332332
sqltypes.BigInteger: _PGBigInteger,
333333
sqltypes.Boolean: _PGBoolean,
334+
sqltypes.Uuid: _PGUUID, # Uuid type (lowercase) inferred from Mapped[uuid.UUID]
334335
UUID: _PGUUID, # UUID support with proper parameter binding
335336
# Note: NullType mapping removed - standard PostgreSQL dialect doesn't map it
336337
# and mapping it with render_bind_cast=True causes DDL compilation errors

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "psqlpy-sqlalchemy"
7-
version = "0.1.1b1"
7+
version = "0.1.1b2"
88
description = "SQLAlchemy dialect for psqlpy PostgreSQL driver"
99
readme = "README.md"
1010
license = {text = "MIT"}

tests/test_uuid_support.py

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from sqlalchemy.dialects.postgresql import UUID
1111
from sqlalchemy.exc import StatementError
1212
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
13-
from sqlalchemy.orm import DeclarativeBase, sessionmaker
13+
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, sessionmaker
1414

1515

1616
# Skip tests if database is not available (check for CI environment or explicit flag)
@@ -357,6 +357,60 @@ async def test_uuid_select_full_row(self, session):
357357
assert isinstance(row.uid, uuid.UUID)
358358
assert row.uid == test_uuid
359359

360+
async def test_uuid_mapped_annotation_without_explicit_as_uuid(
361+
self, engine
362+
):
363+
"""Test that Mapped[uuid.UUID] without explicit UUID(as_uuid=True) returns uuid.UUID objects.
364+
365+
This test verifies the exact pattern:
366+
id: Mapped[uuid.UUID] = mapped_column(primary_key=True)
367+
368+
When using SQLAlchemy 2.0+ Mapped annotations with Python's uuid.UUID type,
369+
the dialect should automatically return uuid.UUID objects, not strings.
370+
"""
371+
from sqlalchemy import select
372+
373+
# Create a model using the Mapped[uuid.UUID] annotation pattern
374+
class SimplifiedUUIDModel(Base):
375+
__tablename__ = "test_simplified_uuid"
376+
377+
id: Mapped[uuid.UUID] = mapped_column(primary_key=True)
378+
name: Mapped[str] = mapped_column(String(100))
379+
380+
# Create table
381+
async with engine.begin() as conn:
382+
await conn.run_sync(
383+
SimplifiedUUIDModel.__table__.create, checkfirst=True
384+
)
385+
386+
try:
387+
# Create session
388+
async_session = sessionmaker(engine, class_=AsyncSession)
389+
async with async_session() as session:
390+
# Insert test data
391+
test_uuid = uuid.uuid4()
392+
obj = SimplifiedUUIDModel(id=test_uuid, name="test")
393+
session.add(obj)
394+
await session.commit()
395+
396+
# Select using the exact pattern from the issue
397+
stmt = select(SimplifiedUUIDModel.id)
398+
result = (await session.scalars(stmt)).all()
399+
400+
# Critical assertion: should be uuid.UUID, not str
401+
assert len(result) == 1
402+
assert isinstance(result[0], uuid.UUID), (
403+
f"Expected uuid.UUID but got {type(result[0]).__name__}. "
404+
f"This means the Mapped[UUID] pattern is returning strings instead of UUID objects."
405+
)
406+
assert result[0] == test_uuid
407+
finally:
408+
# Clean up
409+
async with engine.begin() as conn:
410+
await conn.run_sync(
411+
SimplifiedUUIDModel.__table__.drop, checkfirst=True
412+
)
413+
360414

361415
class TestUUIDTypeCompatibility:
362416
"""Test UUID type compatibility with existing functionality."""

0 commit comments

Comments
 (0)