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.
Files changed (40) hide show
  1. {cloudoll-2.0.24 → cloudoll-2.1.0}/PKG-INFO +1 -1
  2. cloudoll-2.1.0/cloudoll/__init__.py +1 -0
  3. cloudoll-2.1.0/cloudoll/orm/base.py +130 -0
  4. {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll/orm/field.py +127 -53
  5. {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll/orm/model.py +64 -56
  6. {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll/orm/mysql.py +9 -7
  7. {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll/web/__init__.py +1 -1
  8. {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll/web/settings.py +2 -1
  9. {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll.egg-info/PKG-INFO +1 -1
  10. cloudoll-2.0.24/cloudoll/__init__.py +0 -1
  11. cloudoll-2.0.24/cloudoll/orm/base.py +0 -87
  12. {cloudoll-2.0.24 → cloudoll-2.1.0}/LICENSE +0 -0
  13. {cloudoll-2.0.24 → cloudoll-2.1.0}/README.md +0 -0
  14. {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll/__main__.py +0 -0
  15. {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll/cli.py +0 -0
  16. {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll/error/__init__.py +0 -0
  17. {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll/error/errors.py +0 -0
  18. {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll/logging/__init__.py +0 -0
  19. {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll/mail/__init__.py +0 -0
  20. {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll/mail/smtp.py +0 -0
  21. {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll/orm/__init__.py +0 -0
  22. {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll/orm/postgres.py +0 -0
  23. {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll/robot/__init__.py +0 -0
  24. {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll/robot/dingtalk.py +0 -0
  25. {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll/robot/feishu.py +0 -0
  26. {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll/robot/slack.py +0 -0
  27. {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll/utils/__init__.py +0 -0
  28. {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll/utils/common.py +0 -0
  29. {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll/utils/m2d.py +0 -0
  30. {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll/utils/watch.py +0 -0
  31. {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll/web/html.py +0 -0
  32. {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll/web/http.py +0 -0
  33. {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll/web/jwt.py +0 -0
  34. {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll.egg-info/SOURCES.txt +0 -0
  35. {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll.egg-info/dependency_links.txt +0 -0
  36. {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll.egg-info/entry_points.txt +0 -0
  37. {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll.egg-info/requires.txt +0 -0
  38. {cloudoll-2.0.24 → cloudoll-2.1.0}/cloudoll.egg-info/top_level.txt +0 -0
  39. {cloudoll-2.0.24 → cloudoll-2.1.0}/setup.cfg +0 -0
  40. {cloudoll-2.0.24 → cloudoll-2.1.0}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cloudoll
3
- Version: 2.0.24
3
+ Version: 2.1.0
4
4
  Summary: 辅助快速创建可分布的微服务。
5
5
  Home-page: https://gitee.com/chuchur/cloudoll-py
6
6
  Author: chuchur
@@ -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='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
- COUNT='COUNT',
35
- IS_NOT='IS NOT',
36
- IS_NOT_NULL='IS NOT NULL',
37
- IS_NULL='IS NULL',
38
- LIKE='LIKE',
39
- NOT_LIKE='NOT LIKE',
40
- ILIKE='ILIKE',
41
- BETWEEN='BETWEEN',
42
- CONTAINS='CONTAINS',
43
- NOT_BETWEEN='NOT BETWEEN',
44
- REGEXP='REGEXP',
45
- IREGEXP='IREGEXP',
46
- DISTINCT='DISTINCT',
47
- CONCAT='||',
48
- BITWISE_NEGATION='~')
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
- __sub__ = _op(OP.SUB, True) # -=
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
- return f"{self.op}({self.col.full_name} {','+str(self.rpt) if self.rpt else ''})"
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
- q.append(r.full_name)
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
- else:
195
- q.append('?')
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
- q.append(')')
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
- # return f"({l.full_name if isinstance(l,Field) else l.sql()} {self.op} {r.full_name if isinstance(r,Field) else (r.sql() if isinstance(r,FieldBase) else str(r))})"
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.__pool__ = pool
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
- cols.append(col.sql())
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
- exp = reduce(operator.and_, exp).sql()
137
- join = f"JOIN {table.__table__} ON {exp}"
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
- by.append(f"{f.lhs.full_name} {f.op}")
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
- if self.__params__ is not None:
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 test(self):
228
- return self.sql()
248
+ def limit(self, limit: int):
249
+ self.__limit__ = f"{limit}"
250
+ return self
229
251
 
230
252
  @classmethod
231
- async def __query(self, sql, args):
232
- # print(sql, args)
233
- try:
234
- rs = await self.__pool__.query(sql, args)
235
- finally:
236
- self._clear()
237
- return rs
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
- rs = await self.__query(sql, args)
245
- item = await rs.one()
246
- return self(**item)
247
-
248
- @classmethod
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
- rs = await self.__query(sql, args)
263
- return await rs.all()
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
- rs = await self.__query(sql, params)
288
- result = rs.cursor.rowcount > 0
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
- # return await sa.query(sql, args)
311
- rs = await self.__query(sql, args)
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
- rs = await self.__query(sql, params)
322
- result = rs.cursor.rowcount > 0
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
- rs = await self.__query(sql, args)
332
- return await rs.count()
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__(self, name=None, default=False, not_null=False, comment=None, unsigned=False):
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
- from aiomysql.cursors import Cursor
30
- from aiomysql.connection import Connection
31
- from cloudoll.logging import error, warning
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,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cloudoll
3
- Version: 2.0.24
3
+ Version: 2.1.0
4
4
  Summary: 辅助快速创建可分布的微服务。
5
5
  Home-page: https://gitee.com/chuchur/cloudoll-py
6
6
  Author: chuchur
@@ -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