Double casting UUID field with parameter as_uuid=True
Kostiantyn-Salnykov opened this issue · 5 comments
Hello, I've got an error when trying to use something like that:
id = Column(
UUID(as_uuid=True), # I need to use id as UUID object
default=uuid.uuid4,
primary_key=True,
)
UUID: from sqlalchemy.dialects.postgresql import UUID
I've also tested this logic at dockerized PostgreSQL v10.14 with psycopg2 - all works as expected.
So somewhere it tries to make code like uuid.UUID(<uuid.UUID object>)
File "<input>", line 1, in <module>
File "/usr/local/lib/python3.9/uuid.py", line 174, in __init__
hex = hex.replace('urn:', '').replace('uuid:', '')
AttributeError: 'UUID' object has no attribute 'replace'```
Thanks for the report, can you give a complete reproduction of the issue including the full code that triggers the issue?
I can't share all code, but I can point main steps that I did to get the error:
- Create Engine
engine = create_engine(
url=f"postgresql+auroradataapi://:@/{DB_NAME}", # noqa
echo=True,
connect_args={
"aurora_cluster_arn": CLUSTER_ARN,
"secret_arn": SECRET_ARN,
},
)
- Initiate session maker:
session_factory = sessionmaker(bind=engine, future=True)
- Create session:
session = session_factory()
- Create declarative_mixin:
@declarative_mixin
class TableNameMixin:
pattern = re.compile(r"(?<!^)(?=[A-Z])")
@declared_attr
def __tablename__(cls):
return cls.pattern.sub("_", cls.__name__).lower()
@declarative_mixin
class UUIDMixin:
id = Column(
UUID(as_uuid=True), # This option as_uuid=False by default
default=uuid.uuid4,
server_default=text("gen_random_uuid()"),
primary_key=True,
)
- Initiate declarative_base:
Base = declarative_base(cls=TableNameMixin)
- Create model like that:
class TestModel(Base, UUIDMixin):
name = Column(VARCHAR(length=128), nullable=False)
- Create
__repr__
for TestModel:
def __repr__(self):
return f"{self.__class__.__name__}(id='{self.id}', name='{self.name}')"
- Create TestModel object and commit it:
obj_id = uuid.uuid4() # need to create id at code side
obj = TestModel(id=obj_id, name="TEST)
session.add(obj)
session.commit()
print(obj) # this will produce an error
P.S. Also if I try to get the object from DB with as_uuid=True
I also get this issue
as I understand it try to convert UUID object to UUID object again
I suppose it also can be related to aurora-data-api
,
https://github.com/cloud-utils/aurora-data-api/pull/32/files
Hi @Kostiantyn-Salnykov I am having the same problem. I downgraded aurora-data-api to a version released before the PR you linked, v0.2.5, and things started working again.
Thanks for bringing this up. I wasn't able to figure out how to configure the SQLAlchemy driver API to handle UUID objects correctly when the underlying DB-API driver has already converted them to native types, so I reverted the PR in question and made a new release that should fix the problem, and added a regression test. Pleas let me know if this does not fix the problem for you.