-
Notifications
You must be signed in to change notification settings - Fork 191
Expand file tree
/
Copy pathguid_type.py
More file actions
72 lines (57 loc) · 2.19 KB
/
guid_type.py
File metadata and controls
72 lines (57 loc) · 2.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# TODO: Add tests for postgres
import uuid
from typing import TYPE_CHECKING, no_type_check
import sqlalchemy as sa
from sqlalchemy.dialects.postgresql.base import UUID
from sqlalchemy.sql.sqltypes import CHAR
from sqlalchemy.sql.type_api import TypeDecorator
# Use the following as the value of server_default for primary keys of type GUID
GUID_SERVER_DEFAULT_POSTGRESQL = sa.DefaultClause(sa.text("gen_random_uuid()"))
GUID_DEFAULT_SQLITE = uuid.uuid4
if TYPE_CHECKING:
UUIDTypeDecorator = TypeDecorator[uuid.UUID]
else:
UUIDTypeDecorator = TypeDecorator
class GUID(UUIDTypeDecorator):
"""
Platform-independent GUID type.
Uses PostgreSQL's UUID type, otherwise uses CHAR(32), storing as stringified hex values.
Taken from SQLAlchemy docs: https://docs.sqlalchemy.org/en/13/core/custom_types.html#backend-agnostic-guid-type
"""
impl = CHAR
cache_ok = True
@no_type_check
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
@no_type_check
def load_dialect_impl(self, dialect):
if dialect.name == "postgresql": # pragma: no cover
return dialect.type_descriptor(UUID())
else:
return dialect.type_descriptor(CHAR(32))
@no_type_check
def process_bind_param(self, value, dialect):
if value is None:
return value
elif dialect.name == "postgresql": # pragma: no cover
return str(value)
else:
if not isinstance(value, uuid.UUID):
return "%.32x" % uuid.UUID(value).int
else:
# hexstring
return "%.32x" % value.int
@no_type_check
def process_result_value(self, value, dialect):
if value is None:
return value
else:
if not isinstance(value, uuid.UUID): # pragma: no branch
value = uuid.UUID(value)
return value
def setup_guids_postgresql(engine: sa.engine.Engine) -> None: # pragma: no cover
"""
Set up UUID generation using the pgcrypto extension for postgres
This query only needs to be executed once when the database is created
"""
engine.execute('create EXTENSION if not EXISTS "pgcrypto"')