-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathdbapi.py
More file actions
175 lines (142 loc) · 5.4 KB
/
Copy pathdbapi.py
File metadata and controls
175 lines (142 loc) · 5.4 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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
import typing as t
from sqlalchemy.util.concurrency import await_only
from .connection import AsyncAdapt_psqlpy_connection
class PSQLPyAdaptDBAPI:
def __init__(self, psqlpy: t.Any) -> None:
self.psqlpy = psqlpy
self.paramstyle = "numeric_dollar"
# DBAPI 2.0 module attributes
self.apilevel = "2.0"
self.threadsafety = 2 # Threads may share the module and connections
# Single reusable exception class for all error types
_error_class = psqlpy.Error
self.Warning = _error_class
self.Error = _error_class
self.InterfaceError = _error_class
self.DatabaseError = _error_class
self.DataError = _error_class
self.OperationalError = _error_class
self.IntegrityError = _error_class
self.InternalError = _error_class
self.ProgrammingError = _error_class
self.NotSupportedError = _error_class
for k, v in self.psqlpy.__dict__.items():
if k != "connect":
self.__dict__[k] = v
def connect(
self, *arg: t.Any, **kw: t.Any
) -> AsyncAdapt_psqlpy_connection:
creator_fn = kw.pop("async_creator_fn", self.psqlpy.connect)
# Handle server_settings parameter that SQLAlchemy might pass
server_settings = kw.pop("server_settings", None)
if server_settings and "application_name" in server_settings:
kw["application_name"] = server_settings["application_name"]
# Add other server_settings mappings as needed
# Filter out any other unsupported parameters that SQLAlchemy might pass
supported_params = frozenset(
{
"dsn",
"username",
"password",
"host",
"hosts",
"port",
"ports",
"db_name",
"target_session_attrs",
"options",
"application_name",
"connect_timeout_sec",
"connect_timeout_nanosec",
"tcp_user_timeout_sec",
"tcp_user_timeout_nanosec",
"keepalives",
"keepalives_idle_sec",
"keepalives_idle_nanosec",
"keepalives_interval_sec",
"keepalives_interval_nanosec",
"keepalives_retries",
"load_balance_hosts",
"max_db_pool_size",
"conn_recycling_method",
"ssl_mode",
"ca_file",
}
)
filtered_kw = {k: v for k, v in kw.items() if k in supported_params}
return AsyncAdapt_psqlpy_connection(
self, await_only(creator_fn(*arg, **filtered_kw))
)
class PsqlpyDBAPI:
"""DBAPI-compatible module interface for psqlpy"""
apilevel = "2.0"
threadsafety = 2 # Threads may share the module and connections
paramstyle = (
"numeric_dollar" # PostgreSQL uses $1, $2, etc. style parameters
)
def __init__(self) -> None:
# Initialize with psqlpy module
import psqlpy
self._adapt_dbapi = PSQLPyAdaptDBAPI(psqlpy)
# Single reusable exception class for all error types
_error_class = psqlpy.Error
self.Warning = _error_class
self.Error = _error_class
self.InterfaceError = _error_class
self.DatabaseError = _error_class
self.DataError = _error_class
self.OperationalError = _error_class
self.IntegrityError = _error_class
self.InternalError = _error_class
self.ProgrammingError = _error_class
self.NotSupportedError = _error_class
# Type constructors
def Date(self, year: int, month: int, day: int) -> t.Any:
"""Construct a date value"""
import datetime
return datetime.date(year, month, day)
def Time(self, hour: int, minute: int, second: int) -> t.Any:
"""Construct a time value"""
import datetime
return datetime.time(hour, minute, second)
def Timestamp(
self,
year: int,
month: int,
day: int,
hour: int,
minute: int,
second: int,
) -> t.Any:
"""Construct a timestamp value"""
import datetime
return datetime.datetime(year, month, day, hour, minute, second)
def DateFromTicks(self, ticks: float) -> t.Any:
"""Construct a date from ticks"""
import datetime
return datetime.date.fromtimestamp(ticks)
def TimeFromTicks(self, ticks: float) -> t.Any:
"""Construct a time from ticks"""
import datetime
dt = datetime.datetime.fromtimestamp(ticks)
return dt.time()
def TimestampFromTicks(self, ticks: float) -> t.Any:
"""Construct a timestamp from ticks"""
import datetime
return datetime.datetime.fromtimestamp(ticks)
def Binary(self, string: str | bytes) -> bytes:
"""Construct a binary value"""
if isinstance(string, str):
return string.encode("utf-8")
return bytes(string)
# Type objects for type comparison
STRING = str
BINARY = bytes
NUMBER = (int, float)
DATETIME = object # datetime objects
ROWID = int
def connect(
self, *args: t.Any, **kwargs: t.Any
) -> AsyncAdapt_psqlpy_connection:
"""Create a connection - delegates to the adapted DBAPI"""
return self._adapt_dbapi.connect(*args, **kwargs)