cloudoll 2.4.0__py3-none-any.whl

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.
@@ -0,0 +1,252 @@
1
+ from redis import asyncio as aioredis
2
+ from .parse import parse_coon
3
+ from .base import MeteBase, QueryTypes
4
+ from typing import Any
5
+ from ..logging import print_info, print_error
6
+ import traceback
7
+ import aiomysql
8
+ from aiomysql import Pool as MYPool
9
+
10
+ import aiopg as pg
11
+ from aiopg.pool import Pool as PGPool
12
+
13
+ __ALL__ = "create_engine"
14
+
15
+
16
+ async def create_engine(**kw):
17
+ url = kw.get("url")
18
+ driver = None
19
+ configs = {}
20
+ query = {}
21
+
22
+ if url is not None:
23
+ configs, query = parse_coon(url)
24
+ driver = configs["type"]
25
+ else:
26
+ driver = kw.get("type")
27
+ configs = kw
28
+
29
+ # print_info("DB Config:", configs, query)
30
+
31
+ if driver == "mysql":
32
+ return await Mysql().create_engine(**configs, **query)
33
+ elif driver == "postgres" or driver == "postgressql":
34
+ return await Postgres().create_engine(**configs, **query)
35
+ elif driver == "redis" or driver == "rediss":
36
+ """
37
+ redis://[[username]:[password]]@localhost:6379/0
38
+ rediss://[[username]:[password]]@localhost:6379/0
39
+ """
40
+ if url is None:
41
+ url = f"{driver}://{configs['username']}:{configs['password']}@{configs['host']}:{configs['port']}/{configs['db']}"
42
+ return await aioredis.from_url(url, **query)
43
+ else:
44
+ raise "Not suport this database type."
45
+
46
+
47
+ class Postgres(MeteBase):
48
+ def __init__(self, pool=None):
49
+ self.pool: PGPool = pool
50
+ self.driver = "postgres"
51
+
52
+ def __call__(self, *args: Any, **kwds: Any) -> Any:
53
+ self.__init__(*args, **kwds)
54
+
55
+ async def query(self, sql, params=None, query_type: QueryTypes = 2, size: int = 10):
56
+ sql = sql.replace("?", "%s").replace("`", '"')
57
+ if not self.pool:
58
+ raise ValueError("must be create_engine first.")
59
+ if self.pool._closing or self.pool._closed:
60
+ return None
61
+
62
+ async with self.pool.acquire() as conn:
63
+ if conn.echo:
64
+ print_info("sql", sql, params)
65
+
66
+ async with conn.cursor() as cursor:
67
+ # current_cursor = getattr(cursor, 'lastrowid', None)
68
+ if (
69
+ query_type == QueryTypes.CREATEBATCH
70
+ or query_type == QueryTypes.UPDATEBATCH
71
+ ):
72
+ # aiopg don't support executemany
73
+ raise RuntimeError("postgres don't support executemany")
74
+ else:
75
+ await cursor.execute(sql, params)
76
+
77
+ result = None
78
+
79
+ if query_type == QueryTypes.ALL:
80
+ columns = [desc[0] for desc in cursor.description]
81
+ rows = await cursor.fetchall()
82
+ result = [dict(zip(columns, row)) for row in rows]
83
+ return result
84
+ elif query_type == QueryTypes.ONE:
85
+ columns = [desc[0] for desc in cursor.description]
86
+ row = await cursor.fetchone()
87
+ result = dict(zip(columns, row)) if row else {}
88
+ return result
89
+ elif query_type == QueryTypes.MANY:
90
+ columns = [desc[0] for desc in cursor.description]
91
+ rows = await cursor.fetchmany(size)
92
+ result = [dict(zip(columns, row)) for row in rows]
93
+ return result
94
+ elif query_type == QueryTypes.COUNT:
95
+ result = await cursor.fetchone()
96
+ count = 0
97
+ if rows is None:
98
+ return count
99
+ for row in rows:
100
+ count = rows[row]
101
+ return count
102
+ elif query_type == QueryTypes.GROUP_COUNT:
103
+ result = await cursor.fetchall()
104
+ return 0 if not result else len(result)
105
+ elif query_type == QueryTypes.CREATE:
106
+ result = cursor.rowcount > 0
107
+ id = cursor.lastrowid
108
+ return result, id
109
+ elif query_type == QueryTypes.CREATEBATCH:
110
+ count = cursor.rowcount
111
+ id = cursor.lastrowid
112
+ return count, id
113
+ elif query_type == QueryTypes.UPDATE:
114
+ return cursor.rowcount > 0
115
+ elif query_type == QueryTypes.UPDATEBATCH:
116
+ return cursor.rowcount
117
+ elif query_type == QueryTypes.DELETE:
118
+ return cursor.rowcount > 0
119
+
120
+ self.pool.release(cursor)
121
+
122
+ async def create_engine(self, **kw):
123
+ try:
124
+ host = (kw.get("host", "localhost"),)
125
+ port = (kw.get("port", 5432),)
126
+ user = (kw.get("username"),)
127
+ password = (str(kw.get("password", "")),)
128
+ db = (kw.get("db"),)
129
+ dsn = f"dbname={db[0]} user={user[0]} password={password[0]} host={host[0]} port={port[0]}" # aiopg
130
+ # dsn = f"postgres://{user[0]}:{password[0]}@{host[0]}:{port[0]}/{db[0]}" # asyncpg
131
+ self.pool = await pg.create_pool(
132
+ dsn=dsn,
133
+ timeout=kw.get("timeout"),
134
+ echo=kw.get("echo", False), # aiopg
135
+ # max_size=kw.get("maxsize", 10), # asyncpg
136
+ # min_size=kw.get("minsize", 5), # asyncpg
137
+ maxsize=kw.get("maxsize", 10), # aiopg
138
+ minsize=kw.get("minsize", 5), # aiopg
139
+ )
140
+ print_info(f"Database connection successfuly for postgres/{kw.get('db')}")
141
+ except Exception as e:
142
+ print_error(e)
143
+ # print(traceback.format_exc())
144
+ print_error(
145
+ f"Database connection failed,the instance : postgres/{kw.get('db')}"
146
+ )
147
+
148
+ return self
149
+
150
+
151
+ class AttrDict(dict):
152
+ """Dict that can get attribute by dot, and doesn't raise KeyError"""
153
+
154
+ def __getattr__(self, name):
155
+ try:
156
+ return self[name]
157
+ except KeyError:
158
+ return None
159
+
160
+
161
+ class AttrDictCursor(aiomysql.DictCursor):
162
+ dict_type = AttrDict
163
+
164
+
165
+ class Mysql(MeteBase):
166
+ def __init__(self, pool=None):
167
+ self.pool: MYPool = pool
168
+ self.driver = "mysql"
169
+
170
+ def __call__(self, *args: Any, **kwds: Any) -> Any:
171
+ self.__init__(*args, **kwds)
172
+ return self
173
+
174
+ async def query(self, sql, params=None, query_type: QueryTypes = 2, size: int = 10):
175
+ sql = sql.replace("?", "%s")
176
+ if not self.pool:
177
+ raise ValueError("must be create_engine first.")
178
+ if self.pool._closing or self.pool._closed:
179
+ return None
180
+ async with self.pool.acquire() as conn:
181
+ if conn.echo:
182
+ print_info("sql", sql, params)
183
+
184
+ async with conn.cursor() as cursor:
185
+ # current_cursor = getattr(cursor, 'lastrowid', None)
186
+ if (
187
+ query_type == QueryTypes.CREATEBATCH
188
+ or query_type == QueryTypes.UPDATEBATCH
189
+ ):
190
+ await cursor.executemany(sql, params)
191
+ else:
192
+ await cursor.execute(sql, params)
193
+
194
+ await conn.commit()
195
+
196
+ if query_type == QueryTypes.ALL:
197
+ return await cursor.fetchall()
198
+ elif query_type == QueryTypes.ONE:
199
+ return await cursor.fetchone()
200
+ elif query_type == QueryTypes.MANY:
201
+ return await cursor.fetchmany(size)
202
+ elif query_type == QueryTypes.COUNT:
203
+ rows = await cursor.fetchone()
204
+ count = 0
205
+ if rows is None:
206
+ return count
207
+ for row in rows:
208
+ count = rows[row]
209
+ return count
210
+ elif query_type == QueryTypes.GROUP_COUNT:
211
+ result = await cursor.fetchall()
212
+ return 0 if not result else len(result)
213
+ elif query_type == QueryTypes.CREATE:
214
+ result = cursor.rowcount > 0
215
+ id = cursor.lastrowid
216
+ return result, id
217
+ elif query_type == QueryTypes.CREATEBATCH:
218
+ count = cursor.rowcount
219
+ id = cursor.lastrowid
220
+ return count, id
221
+ elif query_type == QueryTypes.UPDATE:
222
+ return cursor.rowcount > 0
223
+ elif query_type == QueryTypes.UPDATEBATCH:
224
+ return cursor.rowcount
225
+ elif query_type == QueryTypes.DELETE:
226
+ return cursor.rowcount > 0
227
+
228
+ self.pool.release(conn)
229
+
230
+ async def create_engine(self, loop=None, **kw):
231
+ try:
232
+ self.pool = await aiomysql.create_pool(
233
+ host=kw.get("host", "localhost"),
234
+ port=kw.get("port", 3306),
235
+ user=kw.get("username"),
236
+ password=str(kw.get("password", "")),
237
+ db=kw.get("db"),
238
+ echo=kw.get("echo", False),
239
+ charset=kw.get("charset", "utf8"),
240
+ autocommit=False, # kw.get("autocommit", False),
241
+ maxsize=kw.get("maxsize", 10),
242
+ minsize=kw.get("minsize", 5),
243
+ cursorclass=AttrDictCursor,
244
+ loop=loop,
245
+ )
246
+ print_info(f"Database connection successfuly for mysql/{kw.get('db')}.")
247
+ except Exception as e:
248
+ # print(traceback.format_exc())
249
+ print_error(
250
+ f"Database connection failed,the instance : mysql/{kw.get('db')}"
251
+ )
252
+ return self
cloudoll/orm/base.py ADDED
@@ -0,0 +1,80 @@
1
+ from enum import Enum
2
+ from typing import Tuple
3
+
4
+
5
+ class QueryTypes(Enum):
6
+ ALL = 1
7
+ ONE = 2
8
+ MANY = 3
9
+ COUNT = 4
10
+ CREATE = 5
11
+ UPDATE = 6
12
+ DELETE = 7
13
+ CREATEBATCH = 8
14
+ UPDATEBATCH = 9
15
+ GROUP_COUNT = 10
16
+
17
+
18
+ class MeteBase:
19
+
20
+ async def __aexit__(self):
21
+ await self.close()
22
+
23
+ async def close(self):
24
+ if self.pool:
25
+ self.pool.close()
26
+ await self.pool.wait_closed()
27
+
28
+ # async def begin_transaction(self):
29
+ # conn = await self._set_conn()
30
+ # await conn.begin()
31
+ # return conn
32
+
33
+ # async def begin_transaction_scope(self, fun):
34
+ # conn = await self._set_conn()
35
+ # await conn.begin()
36
+ # cursor = None
37
+ # if isfunction(fun):
38
+ # try:
39
+ # cursor = await conn.cursor()
40
+ # await fun(cursor)
41
+ # await conn.commit()
42
+ # except Exception as e:
43
+ # print_error(e)
44
+ # await conn.rollback()
45
+ # finally:
46
+ # if cursor:
47
+ # await cursor.close()
48
+ # self.pool.release(conn)
49
+ async def query(
50
+ self, sql, params=None, query_type: QueryTypes = 2, size: int = 10
51
+ ): ...
52
+
53
+ async def all(self, sql, params):
54
+ return await self.query(sql, params, QueryTypes.ALL)
55
+
56
+ async def one(self, sql, params):
57
+ return await self.query(sql, params, QueryTypes.ONE)
58
+
59
+ async def many(self, sql, params, size: int):
60
+ return await self.query(sql, params, QueryTypes.MANY, size)
61
+
62
+ async def count(self, sql, params):
63
+ return await self.query(sql, params, QueryTypes.COUNT)
64
+ async def group_count(self, sql, params):
65
+ return await self.query(sql, params, QueryTypes.GROUP_COUNT)
66
+
67
+ async def update(self, sql, params):
68
+ return await self.query(sql, params, QueryTypes.UPDATE)
69
+
70
+ async def update_batch(self, sql, params):
71
+ return await self.query(sql, params, QueryTypes.UPDATEBATCH)
72
+
73
+ async def delete(self, sql, params):
74
+ return await self.query(sql, params, QueryTypes.DELETE)
75
+
76
+ async def create(self, sql, params) -> Tuple[bool, int]:
77
+ return await self.query(sql, params, QueryTypes.CREATE)
78
+
79
+ async def create_batch(self, sql, params):
80
+ return await self.query(sql, params, QueryTypes.CREATEBATCH)
cloudoll/orm/err.py ADDED
@@ -0,0 +1,2 @@
1
+ from pymysql.err import OperationalError
2
+ from psycopg2.errors import DatabaseError