AttributeError: 'UUID' object has no attribute 'replace' when using backend-agnostic GUID type AttributeError: 'UUID' object has no attribute 'replace' when using backend-agnostic GUID type python python

AttributeError: 'UUID' object has no attribute 'replace' when using backend-agnostic GUID type


This should fix it:

id = Column(GUID(as_uuid=True), ...)

from https://bitbucket.org/zzzeek/sqlalchemy/issues/3323/in-099-uuid-columns-are-broken-with:

"If you want to pass a UUID() object, the as_uuid flag must be set to True."


The pg8000 PostgreSQL database adapter is returning a uuid.UUID() object (see their type mapping documentation, and SQLAlchemy has passed that to the TypeDecorator.process_result_value() method.

The implementation given in the documentation expected a string, however, so this fails:

>>> import uuid>>> value = uuid.uuid4()>>> uuid.UUID(value)Traceback (most recent call last):  File "<stdin>", line 1, in <module>  File "/Users/mjpieters/Development/Library/buildout.python/parts/opt/lib/python2.7/uuid.py", line 133, in __init__    hex = hex.replace('urn:', '').replace('uuid:', '')AttributeError: 'UUID' object has no attribute 'replace'

The quick work-around is to force the value to be a string anyway:

def process_result_value(self, value, dialect):    if value is None:        return value    else:        return uuid.UUID(str(value))

or you can test for the type first:

def process_result_value(self, value, dialect):    if value is None:        return value    else:        if not isinstance(value, uuid.UUID):            value = uuid.UUID(value)        return value

I've submited pull request #403 to fix this in the documentation (since merged).


This can be fairly frustrating when using UUIDs across a system. Under certain conditions, it might be difficult to control whether a UUID comes in as a string, or as a raw UUID. To work around this, a solution like this might work. I've attached the examples of the doc to make sure everything else still holds true.

# TODO: Set this up such that the normal uuid interface is available as a pass throughimport uuidclass UUID(uuid.UUID):    def __init__(self, hex=None, bytes=None, bytes_le=None, fields=None,                       int=None, version=None):        if hex and (issubclass(type(hex), uuid.UUID) or isinstance(hex, uuid.UUID)):            hex = str(hex)        super(UUID, self).__init__(hex=hex, bytes=bytes, bytes_le=bytes_le, fields=fields, int=int, version=version)print(UUID(uuid4())) # Now this works!print(UUID('{12345678-1234-5678-1234-567812345678}'))print(UUID('12345678123456781234567812345678'))print(UUID('urn:uuid:12345678-1234-5678-1234-567812345678'))print(UUID(bytes=b'\x12\x34\x56\x78' * 4)) # Python 3 requires this to be prefixed with b''. Docs appear to be mainly for Python 2print(UUID(bytes_le=b'\x78\x56\x34\x12\x34\x12\x78\x56' +              b'\x12\x34\x56\x78\x12\x34\x56\x78'))print(UUID(fields=(0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x567812345678)))print(UUID(int=0x12345678123456781234567812345678))

Please use this your own discretion, this is just an example.