reydb 1.3.61__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- reydb-1.3.61/.gitignore +10 -0
- reydb-1.3.61/.python-version +1 -0
- reydb-1.3.61/LICENSE +7 -0
- reydb-1.3.61/PKG-INFO +34 -0
- reydb-1.3.61/README.md +9 -0
- reydb-1.3.61/pyproject.toml +27 -0
- reydb-1.3.61/src/reydb/__init__.py +26 -0
- reydb-1.3.61/src/reydb/rall.py +22 -0
- reydb-1.3.61/src/reydb/rbase.py +314 -0
- reydb-1.3.61/src/reydb/rbuild.py +1359 -0
- reydb-1.3.61/src/reydb/rconfig.py +740 -0
- reydb-1.3.61/src/reydb/rconn.py +256 -0
- reydb-1.3.61/src/reydb/rdb.py +253 -0
- reydb-1.3.61/src/reydb/rengine.py +597 -0
- reydb-1.3.61/src/reydb/rerror.py +516 -0
- reydb-1.3.61/src/reydb/rexec.py +1683 -0
- reydb-1.3.61/src/reydb/rinfo.py +472 -0
- reydb-1.3.61/src/reydb/rorm.py +2177 -0
- reydb-1.3.61/uv.lock +1811 -0
reydb-1.3.61/.gitignore
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.13
|
reydb-1.3.61/LICENSE
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Copyright 2025 ReyXBo
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
4
|
+
|
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
reydb-1.3.61/PKG-INFO
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: reydb
|
|
3
|
+
Version: 1.3.61
|
|
4
|
+
Summary: Database method set.
|
|
5
|
+
Project-URL: Homepage, https://www.reyxbo.com
|
|
6
|
+
Project-URL: Repository, https://github.com/reyxbo/reydb-py.git
|
|
7
|
+
Author-email: Rey <reyxbo@163.com>
|
|
8
|
+
License: Copyright 2025 ReyXBo
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
15
|
+
License-File: LICENSE
|
|
16
|
+
Keywords: PostgreSQL,async,asynchronous,database,db,orm,postgres,rey,reyxbo
|
|
17
|
+
Requires-Python: >=3.12
|
|
18
|
+
Requires-Dist: asyncpg
|
|
19
|
+
Requires-Dist: psycopg[binary]
|
|
20
|
+
Requires-Dist: pydantic[email]
|
|
21
|
+
Requires-Dist: reykit
|
|
22
|
+
Requires-Dist: sqlalchemy==2.0.42
|
|
23
|
+
Requires-Dist: sqlmodel
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
|
|
26
|
+
# reydb
|
|
27
|
+
|
|
28
|
+
> Backend database method set.
|
|
29
|
+
|
|
30
|
+
## Install
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
pip install reydb
|
|
34
|
+
```
|
reydb-1.3.61/README.md
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "reydb"
|
|
3
|
+
version = "1.3.61"
|
|
4
|
+
description = "Database method set."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.12"
|
|
7
|
+
license = {file = "LICENSE"}
|
|
8
|
+
keywords = ["rey", "reyxbo", "PostgreSQL", "postgres", "db", "database", "orm", "async", "asynchronous"]
|
|
9
|
+
authors = [
|
|
10
|
+
{name = "Rey", email = "reyxbo@163.com"}
|
|
11
|
+
]
|
|
12
|
+
dependencies = [
|
|
13
|
+
"asyncpg",
|
|
14
|
+
"psycopg[binary]",
|
|
15
|
+
"pydantic[email]",
|
|
16
|
+
"reykit",
|
|
17
|
+
"sqlalchemy==2.0.42",
|
|
18
|
+
"sqlmodel"
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
[project.urls]
|
|
22
|
+
Homepage = "https://www.reyxbo.com"
|
|
23
|
+
Repository = "https://github.com/reyxbo/reydb-py.git"
|
|
24
|
+
|
|
25
|
+
[build-system]
|
|
26
|
+
requires = ["hatchling"]
|
|
27
|
+
build-backend = "hatchling.build"
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# !/usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
@Time : 2024-01-07
|
|
6
|
+
@Author : Rey
|
|
7
|
+
@Contact : reyxbo@163.com
|
|
8
|
+
@Explain : Backend database method set.
|
|
9
|
+
|
|
10
|
+
Modules
|
|
11
|
+
-------
|
|
12
|
+
rall : All import methods.
|
|
13
|
+
rbase : Base methods.
|
|
14
|
+
rbuild : Database build methods.
|
|
15
|
+
rconfig : Database config methods.
|
|
16
|
+
rconn : Database connection methods.
|
|
17
|
+
rdb : Database methods.
|
|
18
|
+
rengine : Database engine methods.
|
|
19
|
+
rerror : Database error methods.
|
|
20
|
+
rexec : Database execute methods.
|
|
21
|
+
rorm : Database ORM methods.
|
|
22
|
+
rinfo : Database information methods.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
from .rdb import Database, DatabaseAsync
|
|
26
|
+
from .rengine import DatabaseEngine, DatabaseEngineAsync
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# !/usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
@Time : 2024-01-07
|
|
6
|
+
@Author : Rey
|
|
7
|
+
@Contact : reyxbo@163.com
|
|
8
|
+
@Explain : All import methods.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
# ruff: noqa: F403
|
|
12
|
+
|
|
13
|
+
from .rbase import *
|
|
14
|
+
from .rbuild import *
|
|
15
|
+
from .rconfig import *
|
|
16
|
+
from .rconn import *
|
|
17
|
+
from .rdb import *
|
|
18
|
+
from .rengine import *
|
|
19
|
+
from .rerror import *
|
|
20
|
+
from .rexec import *
|
|
21
|
+
from .rorm import *
|
|
22
|
+
from .rinfo import *
|
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
# !/usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
@Time : 2025-07-18
|
|
6
|
+
@Author : Rey
|
|
7
|
+
@Contact : reyxbo@163.com
|
|
8
|
+
@Explain : Base methods.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from typing import Any, TypedDict, Literal, TypeVar
|
|
12
|
+
from enum import EnumType
|
|
13
|
+
from sqlalchemy import Engine, Connection, Transaction, text as sqlalchemy_text, bindparam as sqlalchemy_bindparam
|
|
14
|
+
from sqlalchemy.orm import Session, SessionTransaction
|
|
15
|
+
from sqlalchemy.ext.asyncio import AsyncEngine, AsyncConnection, AsyncTransaction, AsyncSession, AsyncSessionTransaction
|
|
16
|
+
from sqlalchemy.engine.url import URL
|
|
17
|
+
from sqlalchemy.sql.elements import TextClause
|
|
18
|
+
from reykit.rbase import Base, throw
|
|
19
|
+
from reykit.rre import search
|
|
20
|
+
from reykit.rdata import to_json
|
|
21
|
+
from reykit.rre import findall
|
|
22
|
+
|
|
23
|
+
__all__ = (
|
|
24
|
+
'DatabaseBase',
|
|
25
|
+
'handle_sql_data',
|
|
26
|
+
'extract_url',
|
|
27
|
+
'extract_engine',
|
|
28
|
+
'get_syntax',
|
|
29
|
+
'is_multi_sql'
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
EngineT = TypeVar('EngineT', Engine, AsyncEngine)
|
|
33
|
+
ConnectionT = TypeVar('ConnectionT', Connection, AsyncConnection)
|
|
34
|
+
TransactionT = TypeVar('TransactionT', Transaction, AsyncTransaction)
|
|
35
|
+
SessionT = TypeVar('SessionT', Session, AsyncSession)
|
|
36
|
+
SessionTransactionT = TypeVar('SessionTransactionT', SessionTransaction, AsyncSessionTransaction)
|
|
37
|
+
|
|
38
|
+
URLParameters = TypedDict(
|
|
39
|
+
'URLParameters',
|
|
40
|
+
{
|
|
41
|
+
'drivername': str,
|
|
42
|
+
'backend': str,
|
|
43
|
+
'driver': str | None,
|
|
44
|
+
'username': str | None,
|
|
45
|
+
'password': str | None,
|
|
46
|
+
'host': str | None,
|
|
47
|
+
'port': str | None,
|
|
48
|
+
'database': str | None,
|
|
49
|
+
'query': dict[str, str] | None
|
|
50
|
+
}
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
class DatabaseBase(Base):
|
|
54
|
+
"""
|
|
55
|
+
Database base type.
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
def handle_sql_data(sql: str | TextClause, data: list[dict]) -> tuple[TextClause, list[dict]]:
|
|
59
|
+
"""
|
|
60
|
+
Handle sql and data.
|
|
61
|
+
|
|
62
|
+
Parameters
|
|
63
|
+
----------
|
|
64
|
+
sql : SQL in method `sqlalchemy.text` format, or TextClause object.
|
|
65
|
+
data : Data set for filling.
|
|
66
|
+
|
|
67
|
+
Returns
|
|
68
|
+
-------
|
|
69
|
+
TextClause instance and filled data.
|
|
70
|
+
"""
|
|
71
|
+
|
|
72
|
+
# Parameter.
|
|
73
|
+
if type(sql) is TextClause:
|
|
74
|
+
sql = sql.text
|
|
75
|
+
|
|
76
|
+
## Extract keys.
|
|
77
|
+
pattern = '(?<!\\\\):(\\w+)'
|
|
78
|
+
sql_keys = findall(pattern, sql)
|
|
79
|
+
|
|
80
|
+
## Extract keys of syntax "in".
|
|
81
|
+
pattern = '[iI][nN]\\s+(?<!\\\\):(\\w+)'
|
|
82
|
+
sql_keys_in = findall(pattern, sql)
|
|
83
|
+
|
|
84
|
+
# Handle SQL.
|
|
85
|
+
sql = sql.strip()
|
|
86
|
+
if sql[-1] != ';':
|
|
87
|
+
sql += ';'
|
|
88
|
+
sql = sqlalchemy_text(sql)
|
|
89
|
+
if len(data) != 0:
|
|
90
|
+
row = data[0]
|
|
91
|
+
for key, value in row.items():
|
|
92
|
+
if key in sql_keys_in:
|
|
93
|
+
param = sqlalchemy_bindparam(key, expanding=True)
|
|
94
|
+
sql = sql.bindparams(param)
|
|
95
|
+
|
|
96
|
+
# Handle data.
|
|
97
|
+
for row in data:
|
|
98
|
+
if row == {}:
|
|
99
|
+
continue
|
|
100
|
+
for key in sql_keys:
|
|
101
|
+
value = row.get(key)
|
|
102
|
+
|
|
103
|
+
# Empty string.
|
|
104
|
+
if value == '':
|
|
105
|
+
value = None
|
|
106
|
+
|
|
107
|
+
# JSON.
|
|
108
|
+
elif (
|
|
109
|
+
isinstance(value, list)
|
|
110
|
+
and key not in sql_keys_in
|
|
111
|
+
) or isinstance(value, dict):
|
|
112
|
+
value = to_json(value)
|
|
113
|
+
|
|
114
|
+
# Array.
|
|
115
|
+
elif isinstance(value, tuple):
|
|
116
|
+
value = list(value)
|
|
117
|
+
|
|
118
|
+
# Enum.
|
|
119
|
+
elif isinstance(type(value), EnumType):
|
|
120
|
+
value = value.value
|
|
121
|
+
|
|
122
|
+
row[key] = value
|
|
123
|
+
|
|
124
|
+
return sql, data
|
|
125
|
+
|
|
126
|
+
def extract_url(url: str | URL) -> URLParameters:
|
|
127
|
+
"""
|
|
128
|
+
Extract parameters from URL of string.
|
|
129
|
+
|
|
130
|
+
Parameters
|
|
131
|
+
----------
|
|
132
|
+
url : URL of string.
|
|
133
|
+
|
|
134
|
+
Returns
|
|
135
|
+
-------
|
|
136
|
+
URL parameters.
|
|
137
|
+
"""
|
|
138
|
+
|
|
139
|
+
# Extract.
|
|
140
|
+
match url:
|
|
141
|
+
|
|
142
|
+
## Type str.
|
|
143
|
+
case str():
|
|
144
|
+
pattern_remote = r'^([^+]+)\+?([^:]+)??://([^:]+):([^@]+)@([^:]+):(\d+)[/]?([^\?]+)?\??(\S+)?$'
|
|
145
|
+
pattern_local = r'^([^+]+)\+?([^:]+)??:////?([^\?]+)[\?]?(\S+)?$'
|
|
146
|
+
|
|
147
|
+
### Server.
|
|
148
|
+
if (result_remote := search(pattern_remote, url)) is not None:
|
|
149
|
+
(
|
|
150
|
+
backend,
|
|
151
|
+
driver,
|
|
152
|
+
username,
|
|
153
|
+
password,
|
|
154
|
+
host,
|
|
155
|
+
port,
|
|
156
|
+
database,
|
|
157
|
+
query_str
|
|
158
|
+
) = result_remote
|
|
159
|
+
port = int(port)
|
|
160
|
+
|
|
161
|
+
### SQLite.
|
|
162
|
+
elif (result_local := search(pattern_local, url)) is not None:
|
|
163
|
+
username = password = host = port = None
|
|
164
|
+
(
|
|
165
|
+
backend,
|
|
166
|
+
driver,
|
|
167
|
+
database,
|
|
168
|
+
query_str
|
|
169
|
+
) = result_local
|
|
170
|
+
|
|
171
|
+
### Throw exception.
|
|
172
|
+
else:
|
|
173
|
+
throw(ValueError, url)
|
|
174
|
+
|
|
175
|
+
if query_str is not None:
|
|
176
|
+
query = {
|
|
177
|
+
key: value
|
|
178
|
+
for query_item_str in query_str.split('&')
|
|
179
|
+
for key, value in (query_item_str.split('=', 1),)
|
|
180
|
+
}
|
|
181
|
+
else:
|
|
182
|
+
query = {}
|
|
183
|
+
|
|
184
|
+
## Type URL.
|
|
185
|
+
case URL():
|
|
186
|
+
drivername = url.drivername
|
|
187
|
+
username = url.username
|
|
188
|
+
password = url.password
|
|
189
|
+
host = url.host
|
|
190
|
+
port = url.port
|
|
191
|
+
database = url.database
|
|
192
|
+
query = dict(url.query)
|
|
193
|
+
|
|
194
|
+
## Drivername.
|
|
195
|
+
if driver is None:
|
|
196
|
+
drivername = backend
|
|
197
|
+
else:
|
|
198
|
+
drivername = f'{backend}+{driver}'
|
|
199
|
+
|
|
200
|
+
# Generate parameter.
|
|
201
|
+
params = {
|
|
202
|
+
'drivername': drivername,
|
|
203
|
+
'backend': backend,
|
|
204
|
+
'driver': driver,
|
|
205
|
+
'username': username,
|
|
206
|
+
'password': password,
|
|
207
|
+
'host': host,
|
|
208
|
+
'port': port,
|
|
209
|
+
'database': database,
|
|
210
|
+
'query': query
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
return params
|
|
214
|
+
|
|
215
|
+
def extract_engine(engine: Engine | Connection) -> dict[
|
|
216
|
+
Literal[
|
|
217
|
+
'drivername', 'username', 'password', 'host', 'port', 'database', 'query',
|
|
218
|
+
'pool_size', 'max_overflow', 'pool_timeout', 'pool_recycle'
|
|
219
|
+
],
|
|
220
|
+
Any
|
|
221
|
+
]:
|
|
222
|
+
"""
|
|
223
|
+
Extract parameters from `Engine` or `Connection` object.
|
|
224
|
+
|
|
225
|
+
Parameters
|
|
226
|
+
----------
|
|
227
|
+
engine : Engine or Connection object.
|
|
228
|
+
|
|
229
|
+
Returns
|
|
230
|
+
-------
|
|
231
|
+
Extracted parameters.
|
|
232
|
+
"""
|
|
233
|
+
|
|
234
|
+
## Extract Engine object from Connection boject.
|
|
235
|
+
if type(engine) is Connection:
|
|
236
|
+
engine = engine.engine
|
|
237
|
+
|
|
238
|
+
## Extract.
|
|
239
|
+
drivername: str = engine.url.drivername
|
|
240
|
+
username: str | None = engine.url.username
|
|
241
|
+
password: str | None = engine.url.password
|
|
242
|
+
host: str | None = engine.url.host
|
|
243
|
+
port: str | None = engine.url.port
|
|
244
|
+
database: str | None = engine.url.database
|
|
245
|
+
query: dict[str, str] = dict(engine.url.query)
|
|
246
|
+
pool_size: int = engine.pool._pool.maxsize
|
|
247
|
+
max_overflow: int = engine.pool._max_overflow
|
|
248
|
+
pool_timeout: float = engine.pool._timeout
|
|
249
|
+
pool_recycle: int = engine.pool._recycle
|
|
250
|
+
|
|
251
|
+
# Generate parameter.
|
|
252
|
+
params = {
|
|
253
|
+
'drivername': drivername,
|
|
254
|
+
'username': username,
|
|
255
|
+
'password': password,
|
|
256
|
+
'host': host,
|
|
257
|
+
'port': port,
|
|
258
|
+
'database': database,
|
|
259
|
+
'query': query,
|
|
260
|
+
'pool_size': pool_size,
|
|
261
|
+
'max_overflow': max_overflow,
|
|
262
|
+
'pool_timeout': pool_timeout,
|
|
263
|
+
'pool_recycle': pool_recycle
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
return params
|
|
267
|
+
|
|
268
|
+
def get_syntax(self, sql: str | TextClause) -> list[str]:
|
|
269
|
+
"""
|
|
270
|
+
Extract SQL syntax type for each segment form SQL.
|
|
271
|
+
|
|
272
|
+
Parameters
|
|
273
|
+
----------
|
|
274
|
+
sql : SQL text or TextClause object.
|
|
275
|
+
|
|
276
|
+
Returns
|
|
277
|
+
-------
|
|
278
|
+
SQL syntax type for each segment.
|
|
279
|
+
"""
|
|
280
|
+
|
|
281
|
+
# Parameter.
|
|
282
|
+
if type(sql) is TextClause:
|
|
283
|
+
sql = sql.text
|
|
284
|
+
|
|
285
|
+
# Extract.
|
|
286
|
+
syntax = [
|
|
287
|
+
search('[a-zA-Z]+', sql_part).upper()
|
|
288
|
+
for sql_part in sql.split(';')
|
|
289
|
+
if sql_part != ''
|
|
290
|
+
]
|
|
291
|
+
|
|
292
|
+
return syntax
|
|
293
|
+
|
|
294
|
+
def is_multi_sql(self, sql: str | TextClause) -> bool:
|
|
295
|
+
"""
|
|
296
|
+
Judge whether it is multi segment SQL.
|
|
297
|
+
|
|
298
|
+
Parameters
|
|
299
|
+
----------
|
|
300
|
+
sql : SQL text or TextClause object.
|
|
301
|
+
|
|
302
|
+
Returns
|
|
303
|
+
-------
|
|
304
|
+
Judgment result.
|
|
305
|
+
"""
|
|
306
|
+
|
|
307
|
+
# Parameter.
|
|
308
|
+
if type(sql) is TextClause:
|
|
309
|
+
sql = sql.text
|
|
310
|
+
|
|
311
|
+
# Judge.
|
|
312
|
+
if ';' in sql.rstrip()[:-1]:
|
|
313
|
+
return True
|
|
314
|
+
return False
|