cloudoll 2.0.24__tar.gz → 2.1.0__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.
- {cloudoll-2.0.24 → cloudoll-2.1.0}/PKG-INFO +1 -1
- cloudoll-2.1.0/cloudoll/__init__.py +1 -0
- cloudoll-2.1.0/cloudoll/orm/base.py +130 -0
- {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll/orm/field.py +127 -53
- {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll/orm/model.py +64 -56
- {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll/orm/mysql.py +9 -7
- {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll/web/__init__.py +1 -1
- {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll/web/settings.py +2 -1
- {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll.egg-info/PKG-INFO +1 -1
- cloudoll-2.0.24/cloudoll/__init__.py +0 -1
- cloudoll-2.0.24/cloudoll/orm/base.py +0 -87
- {cloudoll-2.0.24 → cloudoll-2.1.0}/LICENSE +0 -0
- {cloudoll-2.0.24 → cloudoll-2.1.0}/README.md +0 -0
- {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll/__main__.py +0 -0
- {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll/cli.py +0 -0
- {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll/error/__init__.py +0 -0
- {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll/error/errors.py +0 -0
- {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll/logging/__init__.py +0 -0
- {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll/mail/__init__.py +0 -0
- {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll/mail/smtp.py +0 -0
- {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll/orm/__init__.py +0 -0
- {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll/orm/postgres.py +0 -0
- {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll/robot/__init__.py +0 -0
- {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll/robot/dingtalk.py +0 -0
- {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll/robot/feishu.py +0 -0
- {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll/robot/slack.py +0 -0
- {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll/utils/__init__.py +0 -0
- {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll/utils/common.py +0 -0
- {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll/utils/m2d.py +0 -0
- {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll/utils/watch.py +0 -0
- {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll/web/html.py +0 -0
- {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll/web/http.py +0 -0
- {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll/web/jwt.py +0 -0
- {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll.egg-info/SOURCES.txt +0 -0
- {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll.egg-info/dependency_links.txt +0 -0
- {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll.egg-info/entry_points.txt +0 -0
- {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll.egg-info/requires.txt +0 -0
- {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll.egg-info/top_level.txt +0 -0
- {cloudoll-2.0.24 → cloudoll-2.1.0}/setup.cfg +0 -0
- {cloudoll-2.0.24 → cloudoll-2.1.0}/setup.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "2.1.0"
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
from .model import Model
|
|
2
|
+
from enum import Enum
|
|
3
|
+
import re
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class QueryTypes(Enum):
|
|
7
|
+
ALL = 1
|
|
8
|
+
ONE = 2
|
|
9
|
+
MANY = 3
|
|
10
|
+
COUNT = 4
|
|
11
|
+
CREATE = 5
|
|
12
|
+
UPDATE = 6
|
|
13
|
+
DELETE = 7
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class MeteBase:
|
|
17
|
+
def use(self, model: Model):
|
|
18
|
+
model.__pool__ = self.pool
|
|
19
|
+
return model
|
|
20
|
+
|
|
21
|
+
async def __aexit__(self):
|
|
22
|
+
await self.close()
|
|
23
|
+
|
|
24
|
+
async def close(self):
|
|
25
|
+
if self.pool:
|
|
26
|
+
self.pool.close()
|
|
27
|
+
await self.pool.wait_closed()
|
|
28
|
+
|
|
29
|
+
# async def begin_transaction(self):
|
|
30
|
+
# conn = await self._set_conn()
|
|
31
|
+
# await conn.begin()
|
|
32
|
+
# return conn
|
|
33
|
+
|
|
34
|
+
# async def begin_transaction_scope(self, fun):
|
|
35
|
+
# conn = await self._set_conn()
|
|
36
|
+
# await conn.begin()
|
|
37
|
+
# cursor = None
|
|
38
|
+
# if isfunction(fun):
|
|
39
|
+
# try:
|
|
40
|
+
# cursor = await conn.cursor()
|
|
41
|
+
# await fun(cursor)
|
|
42
|
+
# await conn.commit()
|
|
43
|
+
# except Exception as e:
|
|
44
|
+
# error(e)
|
|
45
|
+
# await conn.rollback()
|
|
46
|
+
# finally:
|
|
47
|
+
# if cursor:
|
|
48
|
+
# await cursor.close()
|
|
49
|
+
# self.pool.release(conn)
|
|
50
|
+
|
|
51
|
+
# async def release(self):
|
|
52
|
+
# cursor = self.cursor
|
|
53
|
+
# if cursor:
|
|
54
|
+
# await cursor.close()
|
|
55
|
+
# # self.conn.close()
|
|
56
|
+
# if self.pool:
|
|
57
|
+
# self.pool.release(self.conn)
|
|
58
|
+
|
|
59
|
+
async def query(self, sql, params=None, query_type: QueryTypes = 2, size: int = 10):
|
|
60
|
+
sql = sql.replace("?", "%s")
|
|
61
|
+
# if params:
|
|
62
|
+
# params = [
|
|
63
|
+
# (
|
|
64
|
+
# re.sub(r"(%{2,})", "%", x.replace("'", "\\'"))
|
|
65
|
+
# if isinstance(x, str)
|
|
66
|
+
# else x
|
|
67
|
+
# )
|
|
68
|
+
# for x in params
|
|
69
|
+
# ]
|
|
70
|
+
print("sql", sql, params)
|
|
71
|
+
if not self.pool:
|
|
72
|
+
raise ValueError("must be create_engine first.")
|
|
73
|
+
async with self.pool.acquire() as conn:
|
|
74
|
+
async with conn.cursor() as cursor:
|
|
75
|
+
# current_cursor = getattr(cur, 'lastrowid', None)
|
|
76
|
+
# conn = await self.pool.acquire()
|
|
77
|
+
# cursor = await conn.cursor()
|
|
78
|
+
# try:
|
|
79
|
+
await cursor.execute(sql, params)
|
|
80
|
+
|
|
81
|
+
# if query_type.value > 4:
|
|
82
|
+
await conn.commit()
|
|
83
|
+
|
|
84
|
+
if query_type == QueryTypes.ALL:
|
|
85
|
+
return await cursor.fetchall()
|
|
86
|
+
elif query_type == QueryTypes.ONE:
|
|
87
|
+
return await cursor.fetchone()
|
|
88
|
+
elif query_type == QueryTypes.MANY:
|
|
89
|
+
return await cursor.fetchmany(size)
|
|
90
|
+
elif query_type == QueryTypes.COUNT:
|
|
91
|
+
rs = await cursor.fetchone()
|
|
92
|
+
value = 0
|
|
93
|
+
for r in rs:
|
|
94
|
+
value = rs[r]
|
|
95
|
+
return value
|
|
96
|
+
elif query_type == QueryTypes.CREATE:
|
|
97
|
+
result = cursor.rowcount > 0
|
|
98
|
+
id = cursor.lastrowid
|
|
99
|
+
return result, id
|
|
100
|
+
elif query_type == QueryTypes.UPDATE:
|
|
101
|
+
return cursor.rowcount > 0
|
|
102
|
+
elif query_type == QueryTypes.DELETE:
|
|
103
|
+
return cursor.rowcount > 0
|
|
104
|
+
# except Exception as e:
|
|
105
|
+
# error(e)
|
|
106
|
+
# pass
|
|
107
|
+
# self.cursor = cursor
|
|
108
|
+
# self.conn = conn
|
|
109
|
+
# return self
|
|
110
|
+
|
|
111
|
+
async def all(self, sql, params):
|
|
112
|
+
return await self.query(sql, params, QueryTypes.ALL)
|
|
113
|
+
|
|
114
|
+
async def one(self, sql, params):
|
|
115
|
+
return await self.query(sql, params, QueryTypes.ONE)
|
|
116
|
+
|
|
117
|
+
async def many(self, sql, params, size: int):
|
|
118
|
+
return await self.query(sql, params, QueryTypes.MANY, size)
|
|
119
|
+
|
|
120
|
+
async def count(self, sql, params):
|
|
121
|
+
return await self.query(sql, params, QueryTypes.COUNT)
|
|
122
|
+
|
|
123
|
+
async def update(self, sql, params):
|
|
124
|
+
return await self.query(sql, params, QueryTypes.UPDATE)
|
|
125
|
+
|
|
126
|
+
async def delete(self, sql, params):
|
|
127
|
+
return await self.query(sql, params, QueryTypes.DELETE)
|
|
128
|
+
|
|
129
|
+
async def create(self, sql, params):
|
|
130
|
+
return await self.query(sql, params, QueryTypes.CREATE)
|
|
@@ -7,45 +7,49 @@ class objdict(dict):
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
OP = objdict(
|
|
10
|
-
AND=
|
|
11
|
-
OR=
|
|
12
|
-
ADD=
|
|
13
|
-
SUB=
|
|
14
|
-
MUL=
|
|
15
|
-
DIV=
|
|
16
|
-
BIN_AND=
|
|
17
|
-
BIN_OR=
|
|
18
|
-
XOR=
|
|
19
|
-
MOD=
|
|
20
|
-
EQ=
|
|
21
|
-
LT=
|
|
22
|
-
LTE=
|
|
23
|
-
GT=
|
|
24
|
-
GTE=
|
|
25
|
-
NE=
|
|
26
|
-
IN=
|
|
27
|
-
NOT_IN=
|
|
28
|
-
IS=
|
|
29
|
-
DESC=
|
|
30
|
-
ASC=
|
|
31
|
-
AVG=
|
|
32
|
-
AS=
|
|
33
|
-
SUM=
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
10
|
+
AND="AND",
|
|
11
|
+
OR="OR",
|
|
12
|
+
ADD="+",
|
|
13
|
+
SUB="-",
|
|
14
|
+
MUL="*",
|
|
15
|
+
DIV="/",
|
|
16
|
+
BIN_AND="&",
|
|
17
|
+
BIN_OR="|",
|
|
18
|
+
XOR="#",
|
|
19
|
+
MOD="%",
|
|
20
|
+
EQ="=",
|
|
21
|
+
LT="<",
|
|
22
|
+
LTE="<=",
|
|
23
|
+
GT=">",
|
|
24
|
+
GTE=">=",
|
|
25
|
+
NE="!=",
|
|
26
|
+
IN="IN",
|
|
27
|
+
NOT_IN="NOT IN",
|
|
28
|
+
IS="IS",
|
|
29
|
+
DESC="DESC",
|
|
30
|
+
ASC="ASC",
|
|
31
|
+
AVG="AVG",
|
|
32
|
+
AS="AS",
|
|
33
|
+
SUM="SUM",
|
|
34
|
+
DATE_FORMAT="DATE_FORMAT",
|
|
35
|
+
JSON_CONTAINS_OBJECT="JSON_CONTAINS_OBJECT",
|
|
36
|
+
JSON_CONTAINS_ARRAY="JSON_CONTAINS_ARRAY",
|
|
37
|
+
COUNT="COUNT",
|
|
38
|
+
IS_NOT="IS NOT",
|
|
39
|
+
IS_NOT_NULL="IS NOT NULL",
|
|
40
|
+
IS_NULL="IS NULL",
|
|
41
|
+
LIKE="LIKE",
|
|
42
|
+
NOT_LIKE="NOT LIKE",
|
|
43
|
+
ILIKE="ILIKE",
|
|
44
|
+
BETWEEN="BETWEEN",
|
|
45
|
+
CONTAINS="CONTAINS",
|
|
46
|
+
NOT_BETWEEN="NOT BETWEEN",
|
|
47
|
+
REGEXP="REGEXP",
|
|
48
|
+
IREGEXP="IREGEXP",
|
|
49
|
+
DISTINCT="DISTINCT",
|
|
50
|
+
CONCAT="||",
|
|
51
|
+
BITWISE_NEGATION="~",
|
|
52
|
+
)
|
|
49
53
|
|
|
50
54
|
|
|
51
55
|
class FieldBase:
|
|
@@ -54,6 +58,7 @@ class FieldBase:
|
|
|
54
58
|
if inverse:
|
|
55
59
|
return Expression(rhs, op, self)
|
|
56
60
|
return Expression(self, op, rhs)
|
|
61
|
+
|
|
57
62
|
return inner
|
|
58
63
|
|
|
59
64
|
def __eq__(self, rhs):
|
|
@@ -73,7 +78,7 @@ class FieldBase:
|
|
|
73
78
|
__add__ = _op(OP.ADD) # +
|
|
74
79
|
__radd__ = _op(OP.ADD, True) # +=
|
|
75
80
|
__sub__ = _op(OP.SUB) # -
|
|
76
|
-
|
|
81
|
+
__rsub__ = _op(OP.SUB, True) # -=
|
|
77
82
|
__mul__ = _op(OP.MUL) # *
|
|
78
83
|
__rmul__ = _op(OP.MUL, True) # *=
|
|
79
84
|
__div__ = _op(OP.DIV) # /
|
|
@@ -103,6 +108,15 @@ class FieldBase:
|
|
|
103
108
|
def avg(self):
|
|
104
109
|
return Function(self, OP.AVG)
|
|
105
110
|
|
|
111
|
+
def date_format(self, args):
|
|
112
|
+
return Function(self, OP.DATE_FORMAT, args)
|
|
113
|
+
|
|
114
|
+
def json_contains_object(self, key, value):
|
|
115
|
+
return Function(self, OP.JSON_CONTAINS_OBJECT, (key, value))
|
|
116
|
+
|
|
117
|
+
def json_contains_array(self, args):
|
|
118
|
+
return Function(self, OP.JSON_CONTAINS_ARRAY, args)
|
|
119
|
+
|
|
106
120
|
def contains(self, args):
|
|
107
121
|
return Function(self, OP.CONTAINS, args)
|
|
108
122
|
# return AO(f"contains({self.full_name},?)", args)
|
|
@@ -137,16 +151,16 @@ class ExpList(FieldBase):
|
|
|
137
151
|
q = []
|
|
138
152
|
if isinstance(lpt, Exception):
|
|
139
153
|
_q, _p = lpt.sql()
|
|
140
|
-
q = q+_q
|
|
141
|
-
p = p+_p
|
|
154
|
+
q = q + _q
|
|
155
|
+
p = p + _p
|
|
142
156
|
else:
|
|
143
157
|
q.append("?")
|
|
144
158
|
p.append(lpt)
|
|
145
159
|
q.append(f" {self.op} ")
|
|
146
160
|
if isinstance(rpt, Exception):
|
|
147
161
|
_q, _p = lpt.sql()
|
|
148
|
-
q = q+_q
|
|
149
|
-
p = p+_p
|
|
162
|
+
q = q + _q
|
|
163
|
+
p = p + _p
|
|
150
164
|
else:
|
|
151
165
|
q.append("?")
|
|
152
166
|
p.append(lpt)
|
|
@@ -162,8 +176,25 @@ class Function(FieldBase):
|
|
|
162
176
|
self.rpt = rpt
|
|
163
177
|
|
|
164
178
|
def sql(self):
|
|
179
|
+
op = self.op
|
|
180
|
+
col_name = self.col.full_name
|
|
181
|
+
is_field = isinstance(self.rpt, Field)
|
|
165
182
|
# todo:
|
|
166
|
-
|
|
183
|
+
if op == OP.DATE_FORMAT:
|
|
184
|
+
return f"{op}({col_name},?)", [self.rpt]
|
|
185
|
+
elif op == OP.JSON_CONTAINS_OBJECT:
|
|
186
|
+
_k, _v = self.rpt
|
|
187
|
+
key = _k.full_name if isinstance(_k, Field) else f"'{_k}'"
|
|
188
|
+
return f"json_contains({col_name},json_object({key},?))", [_v]
|
|
189
|
+
elif op == OP.JSON_CONTAINS_ARRAY:
|
|
190
|
+
if is_field:
|
|
191
|
+
return (
|
|
192
|
+
f"json_contains({col_name},json_array({self.rpt.full_name}))",
|
|
193
|
+
None,
|
|
194
|
+
)
|
|
195
|
+
return f"json_contains({col_name},json_array(?))", [self.rpt]
|
|
196
|
+
elif op == OP.COUNT:
|
|
197
|
+
return f"COUNT({col_name})", None
|
|
167
198
|
|
|
168
199
|
|
|
169
200
|
class Expression(FieldBase):
|
|
@@ -171,32 +202,75 @@ class Expression(FieldBase):
|
|
|
171
202
|
self.lhs = lhs
|
|
172
203
|
self.op = op
|
|
173
204
|
self.rhs = rhs
|
|
205
|
+
# self.__value = ""
|
|
206
|
+
# if op in "+-*/|&~" and lhs._value:
|
|
207
|
+
# cal = f"{lhs._value}{op}"
|
|
208
|
+
# if isinstance(rhs, FieldBase):
|
|
209
|
+
# self.__value = str(eval(f"{cal}{rhs._value}"))
|
|
210
|
+
# else:
|
|
211
|
+
# self.__value = str(eval(f"{cal}{rhs}"))
|
|
174
212
|
|
|
175
213
|
def sql(self):
|
|
176
214
|
l = self.lhs
|
|
177
215
|
r = self.rhs
|
|
216
|
+
is_fun = isinstance(l, Function)
|
|
178
217
|
p = []
|
|
179
|
-
q = [
|
|
218
|
+
q = []
|
|
219
|
+
if not is_fun:
|
|
220
|
+
q.append("(")
|
|
180
221
|
if isinstance(l, Field):
|
|
181
222
|
q.append(l.full_name)
|
|
182
223
|
elif isinstance(l, Expression):
|
|
183
224
|
_q, _p = l.sql()
|
|
184
225
|
q.append(_q)
|
|
185
|
-
p = p+_p
|
|
226
|
+
p = p + _p
|
|
227
|
+
elif is_fun:
|
|
228
|
+
_q, _p = l.sql()
|
|
229
|
+
q.append(_q)
|
|
230
|
+
if _p:
|
|
231
|
+
p = p + _p
|
|
232
|
+
# return l.sql()
|
|
233
|
+
|
|
186
234
|
q.append(f" {self.op} ")
|
|
187
235
|
|
|
188
236
|
if isinstance(r, Field):
|
|
189
|
-
|
|
237
|
+
if r._value is not None:
|
|
238
|
+
# _value = r._value if r._value is not None else r.full_name
|
|
239
|
+
q.append("?")
|
|
240
|
+
p.append(r._value)
|
|
241
|
+
else:
|
|
242
|
+
q.append(r.full_name)
|
|
243
|
+
# q.append(str(r._value) if r._value is not None else r.full_name)
|
|
190
244
|
elif isinstance(r, FieldBase):
|
|
191
245
|
_q, _p = r.sql()
|
|
192
246
|
q.append(_q)
|
|
193
|
-
p = p+_p
|
|
194
|
-
|
|
195
|
-
|
|
247
|
+
p = p + _p
|
|
248
|
+
elif self.op == OP.AS:
|
|
249
|
+
# is_fun or (isinstance(r, str) and (self.op == OP.AND or self.op == OP.OR)):
|
|
250
|
+
q.append(r)
|
|
251
|
+
elif r is not None:
|
|
252
|
+
q.append("?")
|
|
196
253
|
p.append(r)
|
|
197
|
-
|
|
254
|
+
if not is_fun:
|
|
255
|
+
q.append(")")
|
|
256
|
+
# q.append(")")
|
|
257
|
+
q = [str(num) for num in q]
|
|
258
|
+
# print("".join(q))
|
|
198
259
|
return "".join(q), p
|
|
199
|
-
|
|
260
|
+
|
|
261
|
+
# def __str__(self):
|
|
262
|
+
# return self.__value
|
|
263
|
+
# cal = f"{self.lhs._value}{self.op}"
|
|
264
|
+
# if isinstance(self.rhs, FieldBase):
|
|
265
|
+
# return str(eval(f"{cal}{self.rhs._value}"))
|
|
266
|
+
# return str(eval(f"{cal}{self.rhs}"))
|
|
267
|
+
|
|
268
|
+
def __repr__(self):
|
|
269
|
+
# return self.__value
|
|
270
|
+
cal = f"{self.lhs.get_value()}{self.op}"
|
|
271
|
+
if isinstance(self.rhs, FieldBase):
|
|
272
|
+
return str(eval(f"{cal}{self.rhs.get_value()}"))
|
|
273
|
+
return str(eval(f"{cal}{self.rhs}"))
|
|
200
274
|
|
|
201
275
|
|
|
202
276
|
class Field(FieldBase):
|
|
@@ -62,6 +62,8 @@ class Model(dict, metaclass=ModelMetaclass):
|
|
|
62
62
|
for k, v in kw.items():
|
|
63
63
|
f = getattr(self, k, None)
|
|
64
64
|
if isinstance(f, Field):
|
|
65
|
+
if v is None:
|
|
66
|
+
v = f.default
|
|
65
67
|
self.set_value(k, v)
|
|
66
68
|
|
|
67
69
|
super(Model, self).__init__(self, **kw)
|
|
@@ -90,6 +92,7 @@ class Model(dict, metaclass=ModelMetaclass):
|
|
|
90
92
|
# self[key] = value
|
|
91
93
|
self.set_value(key, value)
|
|
92
94
|
|
|
95
|
+
# @classmethod
|
|
93
96
|
def get_value(self, key):
|
|
94
97
|
return getattr(self, key, None).get_value()
|
|
95
98
|
|
|
@@ -116,7 +119,7 @@ class Model(dict, metaclass=ModelMetaclass):
|
|
|
116
119
|
@classmethod
|
|
117
120
|
def use(self, pool=None):
|
|
118
121
|
# model = self()
|
|
119
|
-
self.
|
|
122
|
+
self.db = pool
|
|
120
123
|
# self['__pool__'] = pool
|
|
121
124
|
return self
|
|
122
125
|
|
|
@@ -127,14 +130,24 @@ class Model(dict, metaclass=ModelMetaclass):
|
|
|
127
130
|
if isinstance(col, Field):
|
|
128
131
|
cols.append(col.full_name)
|
|
129
132
|
elif isinstance(col, Function):
|
|
130
|
-
|
|
133
|
+
q, p = col.sql()
|
|
134
|
+
cols.append(q)
|
|
135
|
+
elif isinstance(col, Expression):
|
|
136
|
+
q, p = col.sql()
|
|
137
|
+
cols.append(q)
|
|
138
|
+
self._merge_params(self, p)
|
|
131
139
|
self.__cols__ = ",".join(cols) if len(cols) else "*"
|
|
132
140
|
return self
|
|
133
141
|
|
|
134
142
|
@classmethod
|
|
135
143
|
def join(self, table, *exp):
|
|
136
|
-
|
|
137
|
-
|
|
144
|
+
ex = reduce(operator.and_, exp)
|
|
145
|
+
if isinstance(ex, Expression) or isinstance(ex, Function):
|
|
146
|
+
exp, q = ex.sql()
|
|
147
|
+
self._merge_params(self, q)
|
|
148
|
+
else:
|
|
149
|
+
exp = ex
|
|
150
|
+
join = f"{table.__table__} ON " + exp
|
|
138
151
|
if self.__join__ is None:
|
|
139
152
|
self.__join__ = join
|
|
140
153
|
else:
|
|
@@ -159,7 +172,10 @@ class Model(dict, metaclass=ModelMetaclass):
|
|
|
159
172
|
def order_by(self, *args):
|
|
160
173
|
by = []
|
|
161
174
|
for f in args:
|
|
162
|
-
|
|
175
|
+
if isinstance(f, str):
|
|
176
|
+
by.append(f)
|
|
177
|
+
else:
|
|
178
|
+
by.append(f"{f.lhs.full_name} {f.op}")
|
|
163
179
|
if self.__order_by__ is not None:
|
|
164
180
|
by = self.__order_by__ + by
|
|
165
181
|
self.__order_by__ = by
|
|
@@ -181,7 +197,7 @@ class Model(dict, metaclass=ModelMetaclass):
|
|
|
181
197
|
md = None
|
|
182
198
|
if args is None or not args:
|
|
183
199
|
for f in self.__fields__:
|
|
184
|
-
data[f] = self.get_value(f)
|
|
200
|
+
data[f] = self.get_value(self, f)
|
|
185
201
|
else:
|
|
186
202
|
for item in args:
|
|
187
203
|
md = item
|
|
@@ -195,24 +211,29 @@ class Model(dict, metaclass=ModelMetaclass):
|
|
|
195
211
|
params.append(v)
|
|
196
212
|
return ",".join(keys), params, md
|
|
197
213
|
|
|
214
|
+
def _merge_params(self, p):
|
|
215
|
+
if p is not None:
|
|
216
|
+
if self.__params__ is not None:
|
|
217
|
+
p = self.__params__ + p
|
|
218
|
+
self.__params__ = p
|
|
219
|
+
|
|
198
220
|
@classmethod
|
|
199
221
|
def _literal(self, op, exp):
|
|
200
222
|
if exp is not None:
|
|
201
223
|
if isinstance(exp, list):
|
|
202
224
|
return f'{op} {",".join(exp)}'
|
|
203
|
-
elif isinstance(exp, Expression):
|
|
225
|
+
elif isinstance(exp, Expression) or isinstance(exp, Function):
|
|
204
226
|
q, p = exp.sql()
|
|
205
|
-
|
|
206
|
-
p = self.__params__ + p
|
|
207
|
-
self.__params__ = p
|
|
227
|
+
self._merge_params(self, p)
|
|
208
228
|
return f"{op} {q}"
|
|
209
229
|
else:
|
|
210
|
-
return exp
|
|
230
|
+
# return exp
|
|
231
|
+
return f"{op} {exp}"
|
|
211
232
|
return ""
|
|
212
233
|
|
|
213
234
|
@classmethod
|
|
214
235
|
def sql(self):
|
|
215
|
-
JOIN = self._literal("JOIN", self.__join__)
|
|
236
|
+
JOIN = self._literal("LEFT JOIN", self.__join__)
|
|
216
237
|
WHERE = self._literal("WHERE", self.__where__)
|
|
217
238
|
GROUPBY = self._literal("GROUP BY", self.__group_by__)
|
|
218
239
|
HAVING = self._literal("HAVING", self.__having__)
|
|
@@ -224,43 +245,36 @@ class Model(dict, metaclass=ModelMetaclass):
|
|
|
224
245
|
# return self._build_sql(self)
|
|
225
246
|
|
|
226
247
|
@classmethod
|
|
227
|
-
def
|
|
228
|
-
|
|
248
|
+
def limit(self, limit: int):
|
|
249
|
+
self.__limit__ = f"{limit}"
|
|
250
|
+
return self
|
|
229
251
|
|
|
230
252
|
@classmethod
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
return
|
|
253
|
+
def offset(self, offset: int):
|
|
254
|
+
self.__offset__ = f"{offset}"
|
|
255
|
+
return self
|
|
256
|
+
|
|
257
|
+
@classmethod
|
|
258
|
+
def test(self):
|
|
259
|
+
return self.sql()
|
|
238
260
|
|
|
239
261
|
@classmethod
|
|
240
262
|
async def one(self):
|
|
241
|
-
sql = self.sql()
|
|
242
263
|
self.limit(1)
|
|
264
|
+
sql = self.sql()
|
|
243
265
|
args = self.__params__
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
def limit(self, limit: int):
|
|
250
|
-
self.__limit__ = f"LIMIT {limit}"
|
|
251
|
-
return self
|
|
252
|
-
|
|
253
|
-
@classmethod
|
|
254
|
-
def offset(self, offset: int):
|
|
255
|
-
self.__offset__ = f"OFFSET {offset}"
|
|
256
|
-
return self
|
|
266
|
+
self._clear()
|
|
267
|
+
rs = await self.db.one(sql, args)
|
|
268
|
+
if rs:
|
|
269
|
+
return self(**rs)
|
|
270
|
+
return None
|
|
257
271
|
|
|
258
272
|
@classmethod
|
|
259
273
|
async def all(self):
|
|
260
274
|
sql = self.sql()
|
|
261
275
|
args = self.__params__
|
|
262
|
-
|
|
263
|
-
return await
|
|
276
|
+
self._clear()
|
|
277
|
+
return await self.db.all(sql, args)
|
|
264
278
|
|
|
265
279
|
@classmethod
|
|
266
280
|
async def update(self, *args) -> bool:
|
|
@@ -274,7 +288,7 @@ class Model(dict, metaclass=ModelMetaclass):
|
|
|
274
288
|
|
|
275
289
|
sql = f"update `{table}` set {keys}"
|
|
276
290
|
|
|
277
|
-
pk, pkv = self.get_primary()
|
|
291
|
+
pk, pkv = self.get_primary(self)
|
|
278
292
|
if where is not None:
|
|
279
293
|
sql += f' where {" and ".join(f for f in where)}'
|
|
280
294
|
params += self.__params__
|
|
@@ -284,10 +298,8 @@ class Model(dict, metaclass=ModelMetaclass):
|
|
|
284
298
|
else:
|
|
285
299
|
raise "Need where or primary key"
|
|
286
300
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
await rs.release()
|
|
290
|
-
return result
|
|
301
|
+
self._clear()
|
|
302
|
+
return await self.db.update(sql, params)
|
|
291
303
|
|
|
292
304
|
@classmethod
|
|
293
305
|
async def delete(self) -> bool:
|
|
@@ -299,7 +311,7 @@ class Model(dict, metaclass=ModelMetaclass):
|
|
|
299
311
|
args = self.__params__
|
|
300
312
|
sql = f"delete from `{table}`"
|
|
301
313
|
|
|
302
|
-
pk, pkv = self.get_primary()
|
|
314
|
+
pk, pkv = self.get_primary(self)
|
|
303
315
|
if where is not None:
|
|
304
316
|
sql += f' where {" and ".join(f for f in where)}'
|
|
305
317
|
elif pkv is not None:
|
|
@@ -307,29 +319,23 @@ class Model(dict, metaclass=ModelMetaclass):
|
|
|
307
319
|
args = [pkv]
|
|
308
320
|
else:
|
|
309
321
|
raise "need where or primary"
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
result = rs.cursor.rowcount > 0
|
|
313
|
-
await rs.release()
|
|
314
|
-
return result
|
|
322
|
+
self._clear()
|
|
323
|
+
return await self.db.delete(sql, args)
|
|
315
324
|
|
|
316
325
|
@classmethod
|
|
317
326
|
async def insert(self, *args):
|
|
318
327
|
table = self.__table__
|
|
319
328
|
keys, params, md = self._get_key_args(args)
|
|
320
329
|
sql = f"insert into `{table}` set {keys}"
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
id = rs.cursor.lastrowid
|
|
324
|
-
await rs.release()
|
|
325
|
-
return result, id
|
|
330
|
+
self._clear()
|
|
331
|
+
return await self.db.create(sql, params)
|
|
326
332
|
|
|
327
333
|
@classmethod
|
|
328
334
|
async def count(self):
|
|
329
335
|
sql = self.sql()
|
|
330
336
|
args = self.__params__
|
|
331
|
-
|
|
332
|
-
return await
|
|
337
|
+
self._clear()
|
|
338
|
+
return await self.db.count(sql, args)
|
|
333
339
|
|
|
334
340
|
|
|
335
341
|
class Models(object):
|
|
@@ -378,7 +384,9 @@ class Models(object):
|
|
|
378
384
|
)
|
|
379
385
|
|
|
380
386
|
class BooleanField(Field):
|
|
381
|
-
def __init__(
|
|
387
|
+
def __init__(
|
|
388
|
+
self, name=None, default=False, not_null=False, comment=None, unsigned=False
|
|
389
|
+
):
|
|
382
390
|
super().__init__(
|
|
383
391
|
name,
|
|
384
392
|
"boolean",
|
|
@@ -26,9 +26,11 @@ __author__ = "chuchur/chuchur.com"
|
|
|
26
26
|
|
|
27
27
|
from aiomysql import create_pool, DictCursor
|
|
28
28
|
from aiomysql.pool import Pool
|
|
29
|
-
|
|
30
|
-
from aiomysql.
|
|
31
|
-
from
|
|
29
|
+
|
|
30
|
+
# from aiomysql.cursors import Cursor
|
|
31
|
+
# from aiomysql.connection import Connection
|
|
32
|
+
from cloudoll.logging import error, warning
|
|
33
|
+
|
|
32
34
|
# from inspect import isclass, isfunction
|
|
33
35
|
from .base import MeteBase
|
|
34
36
|
|
|
@@ -50,9 +52,9 @@ class AttrDictCursor(DictCursor):
|
|
|
50
52
|
class Mysql(MeteBase):
|
|
51
53
|
def __init__(self):
|
|
52
54
|
self.pool: Pool = None
|
|
53
|
-
self.cursor: Cursor = None
|
|
54
|
-
self.conn: Connection = None
|
|
55
|
-
self.__MODELS__ = []
|
|
55
|
+
# self.cursor: Cursor = None
|
|
56
|
+
# self.conn: Connection = None
|
|
57
|
+
# self.__MODELS__ = []
|
|
56
58
|
|
|
57
59
|
async def create_engine(self, loop=None, **kw):
|
|
58
60
|
try:
|
|
@@ -64,7 +66,7 @@ class Mysql(MeteBase):
|
|
|
64
66
|
db=kw.get("db"),
|
|
65
67
|
echo=kw.get("echo", False),
|
|
66
68
|
charset=kw.get("charset", "utf8"),
|
|
67
|
-
autocommit=kw.get("autocommit", False),
|
|
69
|
+
autocommit=False, # kw.get("autocommit", False),
|
|
68
70
|
maxsize=kw.get("maxsize", 10),
|
|
69
71
|
minsize=kw.get("pool_size", 5),
|
|
70
72
|
cursorclass=AttrDictCursor,
|
|
@@ -156,7 +156,6 @@ def _int(num):
|
|
|
156
156
|
class Application(object):
|
|
157
157
|
def __init__(self):
|
|
158
158
|
self._loop = None
|
|
159
|
-
self.mysql = None
|
|
160
159
|
self.env = None
|
|
161
160
|
self.app = None
|
|
162
161
|
self._route_table = web.RouteTableDef()
|
|
@@ -237,6 +236,7 @@ class Application(object):
|
|
|
237
236
|
for db in apps.db:
|
|
238
237
|
await apps.db[db].close()
|
|
239
238
|
|
|
239
|
+
# close for session
|
|
240
240
|
if "redis" in apps:
|
|
241
241
|
await apps.redis.close()
|
|
242
242
|
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import yaml
|
|
2
2
|
import os
|
|
3
|
-
from ..logging import error
|
|
3
|
+
from ..logging import error,info
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
def get_config(env):
|
|
7
7
|
if env is None:
|
|
8
8
|
return {}
|
|
9
9
|
conf_path = os.path.join(os.path.abspath("."), "config", f"conf.{env}.yaml")
|
|
10
|
+
info(f'loading config {conf_path}')
|
|
10
11
|
if not os.path.exists(conf_path):
|
|
11
12
|
error(f"Configuration file does not exist: {conf_path}")
|
|
12
13
|
return {}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "2.0.24"
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
from .model import Model
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
class MeteBase():
|
|
5
|
-
def use(self, model: Model):
|
|
6
|
-
model.__pool__ = self.pool
|
|
7
|
-
return model
|
|
8
|
-
|
|
9
|
-
async def __aexit__(self):
|
|
10
|
-
await self.close()
|
|
11
|
-
|
|
12
|
-
async def close(self):
|
|
13
|
-
if self.pool:
|
|
14
|
-
self.pool.close()
|
|
15
|
-
await self.pool.wait_closed()
|
|
16
|
-
|
|
17
|
-
# async def begin_transaction(self):
|
|
18
|
-
# conn = await self._set_conn()
|
|
19
|
-
# await conn.begin()
|
|
20
|
-
# return conn
|
|
21
|
-
|
|
22
|
-
# async def begin_transaction_scope(self, fun):
|
|
23
|
-
# conn = await self._set_conn()
|
|
24
|
-
# await conn.begin()
|
|
25
|
-
# cursor = None
|
|
26
|
-
# if isfunction(fun):
|
|
27
|
-
# try:
|
|
28
|
-
# cursor = await conn.cursor()
|
|
29
|
-
# await fun(cursor)
|
|
30
|
-
# await conn.commit()
|
|
31
|
-
# except Exception as e:
|
|
32
|
-
# error(e)
|
|
33
|
-
# await conn.rollback()
|
|
34
|
-
# finally:
|
|
35
|
-
# if cursor:
|
|
36
|
-
# await cursor.close()
|
|
37
|
-
# self.pool.release(conn)
|
|
38
|
-
|
|
39
|
-
async def release(self):
|
|
40
|
-
cursor = self.cursor
|
|
41
|
-
if cursor:
|
|
42
|
-
await cursor.close()
|
|
43
|
-
if self.pool:
|
|
44
|
-
self.pool.release(self.conn)
|
|
45
|
-
|
|
46
|
-
async def query(self, sql, params=None):
|
|
47
|
-
sql = sql.replace("?", "%s")
|
|
48
|
-
# print('sql', sql, params)
|
|
49
|
-
if not self.pool:
|
|
50
|
-
raise ValueError("must be create_engine first.")
|
|
51
|
-
conn = await self.pool.acquire()
|
|
52
|
-
cursor = await conn.cursor()
|
|
53
|
-
await cursor.execute(sql, params)
|
|
54
|
-
self.cursor = cursor
|
|
55
|
-
self.conn = conn
|
|
56
|
-
return self
|
|
57
|
-
|
|
58
|
-
async def all(self):
|
|
59
|
-
cursor = self.cursor
|
|
60
|
-
result = None
|
|
61
|
-
if cursor:
|
|
62
|
-
result = await cursor.fetchall()
|
|
63
|
-
await self.release()
|
|
64
|
-
return result
|
|
65
|
-
|
|
66
|
-
async def one(self):
|
|
67
|
-
cursor = self.cursor
|
|
68
|
-
result = None
|
|
69
|
-
if cursor:
|
|
70
|
-
result = await cursor.fetchone()
|
|
71
|
-
await self.release()
|
|
72
|
-
return result
|
|
73
|
-
|
|
74
|
-
async def many(self, size: int):
|
|
75
|
-
cursor = self.cursor
|
|
76
|
-
result = None
|
|
77
|
-
if cursor:
|
|
78
|
-
result = await cursor.fetchmany(size)
|
|
79
|
-
await self.release()
|
|
80
|
-
return result
|
|
81
|
-
|
|
82
|
-
async def count(self):
|
|
83
|
-
result = await self.one()
|
|
84
|
-
value = 0
|
|
85
|
-
for r in result:
|
|
86
|
-
value = result[r]
|
|
87
|
-
return value
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|