cloudoll 3.0.4__tar.gz → 3.0.6__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-3.0.4 → cloudoll-3.0.6}/PKG-INFO +1 -1
- cloudoll-3.0.6/cloudoll/__init__.py +1 -0
- {cloudoll-3.0.4 → cloudoll-3.0.6}/cloudoll/orm/__init__.py +10 -9
- {cloudoll-3.0.4 → cloudoll-3.0.6}/cloudoll/orm/base.py +13 -4
- {cloudoll-3.0.4 → cloudoll-3.0.6}/cloudoll/orm/field.py +23 -6
- {cloudoll-3.0.4 → cloudoll-3.0.6}/cloudoll/orm/model.py +2 -2
- {cloudoll-3.0.4 → cloudoll-3.0.6}/cloudoll/orm/mysql.py +2 -4
- {cloudoll-3.0.4 → cloudoll-3.0.6}/cloudoll/orm/postgres.py +5 -6
- cloudoll-3.0.6/cloudoll/orm/test_sql.py +89 -0
- {cloudoll-3.0.4 → cloudoll-3.0.6}/cloudoll/utils/snowflake.py +18 -19
- {cloudoll-3.0.4 → cloudoll-3.0.6}/cloudoll/web/core.py +9 -5
- {cloudoll-3.0.4 → cloudoll-3.0.6}/cloudoll.egg-info/PKG-INFO +1 -1
- {cloudoll-3.0.4 → cloudoll-3.0.6}/cloudoll.egg-info/SOURCES.txt +1 -0
- {cloudoll-3.0.4 → cloudoll-3.0.6}/pyproject.toml +1 -1
- cloudoll-3.0.4/cloudoll/__init__.py +0 -1
- {cloudoll-3.0.4 → cloudoll-3.0.6}/LICENSE +0 -0
- {cloudoll-3.0.4 → cloudoll-3.0.6}/README.md +0 -0
- {cloudoll-3.0.4 → cloudoll-3.0.6}/cloudoll/__main__.py +0 -0
- {cloudoll-3.0.4 → cloudoll-3.0.6}/cloudoll/cli.py +0 -0
- {cloudoll-3.0.4 → cloudoll-3.0.6}/cloudoll/clitool/__init__.py +0 -0
- {cloudoll-3.0.4 → cloudoll-3.0.6}/cloudoll/clitool/cli_main.py +0 -0
- {cloudoll-3.0.4 → cloudoll-3.0.6}/cloudoll/clitool/m2d.py +0 -0
- {cloudoll-3.0.4 → cloudoll-3.0.6}/cloudoll/clitool/process.py +0 -0
- {cloudoll-3.0.4 → cloudoll-3.0.6}/cloudoll/clitool/spinner.py +0 -0
- {cloudoll-3.0.4 → cloudoll-3.0.6}/cloudoll/clitool/watch.py +0 -0
- {cloudoll-3.0.4 → cloudoll-3.0.6}/cloudoll/logging/__init__.py +0 -0
- {cloudoll-3.0.4 → cloudoll-3.0.6}/cloudoll/mail/__init__.py +0 -0
- {cloudoll-3.0.4 → cloudoll-3.0.6}/cloudoll/mail/smtp.py +0 -0
- {cloudoll-3.0.4 → cloudoll-3.0.6}/cloudoll/orm/err.py +0 -0
- {cloudoll-3.0.4 → cloudoll-3.0.6}/cloudoll/orm/parse.py +0 -0
- {cloudoll-3.0.4 → cloudoll-3.0.6}/cloudoll/template/__init__.py +0 -0
- {cloudoll-3.0.4 → cloudoll-3.0.6}/cloudoll/utils/__init__.py +0 -0
- {cloudoll-3.0.4 → cloudoll-3.0.6}/cloudoll/utils/common.py +0 -0
- {cloudoll-3.0.4 → cloudoll-3.0.6}/cloudoll/web/__init__.py +0 -0
- {cloudoll-3.0.4 → cloudoll-3.0.6}/cloudoll/web/exception.py +0 -0
- {cloudoll-3.0.4 → cloudoll-3.0.6}/cloudoll/web/html.py +0 -0
- {cloudoll-3.0.4 → cloudoll-3.0.6}/cloudoll/web/jwt.py +0 -0
- {cloudoll-3.0.4 → cloudoll-3.0.6}/cloudoll/web/requests.py +0 -0
- {cloudoll-3.0.4 → cloudoll-3.0.6}/cloudoll/web/settings.py +0 -0
- {cloudoll-3.0.4 → cloudoll-3.0.6}/cloudoll.egg-info/dependency_links.txt +0 -0
- {cloudoll-3.0.4 → cloudoll-3.0.6}/cloudoll.egg-info/entry_points.txt +0 -0
- {cloudoll-3.0.4 → cloudoll-3.0.6}/cloudoll.egg-info/requires.txt +0 -0
- {cloudoll-3.0.4 → cloudoll-3.0.6}/cloudoll.egg-info/top_level.txt +0 -0
- {cloudoll-3.0.4 → cloudoll-3.0.6}/setup.cfg +0 -0
- {cloudoll-3.0.4 → cloudoll-3.0.6}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cloudoll
|
|
3
|
-
Version: 3.0.
|
|
3
|
+
Version: 3.0.6
|
|
4
4
|
Summary: Assist in quickly creating distributable microservices based on aiohttp, with a focus on simplicity and ease of use.
|
|
5
5
|
Home-page: https://github.com/smallerqiu/cloudoll-py
|
|
6
6
|
Author: Qiu
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "3.0.6"
|
|
@@ -9,6 +9,7 @@ from aiomysql import Pool as MYPool
|
|
|
9
9
|
|
|
10
10
|
import aiopg as pg
|
|
11
11
|
from aiopg.pool import Pool as PGPool
|
|
12
|
+
from typing import Optional
|
|
12
13
|
|
|
13
14
|
__all__ = ["create_engine"]
|
|
14
15
|
|
|
@@ -46,7 +47,7 @@ async def create_engine(**kw):
|
|
|
46
47
|
|
|
47
48
|
class Postgres(MeteBase):
|
|
48
49
|
def __init__(self, pool=None):
|
|
49
|
-
self.pool: PGPool = pool
|
|
50
|
+
# self.pool: Optional[PGPool] = pool
|
|
50
51
|
self.driver = "postgres"
|
|
51
52
|
|
|
52
53
|
def __call__(self, *args: Any, **kwds: Any) -> Any:
|
|
@@ -61,7 +62,7 @@ class Postgres(MeteBase):
|
|
|
61
62
|
|
|
62
63
|
async with self.pool.acquire() as conn:
|
|
63
64
|
if conn.echo:
|
|
64
|
-
info("sql", sql, params)
|
|
65
|
+
info("sql: %s ,%s", sql, params)
|
|
65
66
|
|
|
66
67
|
async with conn.cursor() as cursor:
|
|
67
68
|
# current_cursor = getattr(cursor, 'lastrowid', None)
|
|
@@ -75,18 +76,18 @@ class Postgres(MeteBase):
|
|
|
75
76
|
await cursor.execute(sql, params)
|
|
76
77
|
|
|
77
78
|
result = None
|
|
78
|
-
|
|
79
|
-
if query_type == QueryTypes.ALL:
|
|
79
|
+
|
|
80
|
+
if query_type == QueryTypes.ALL and cursor.description is not None:
|
|
80
81
|
columns = [desc[0] for desc in cursor.description]
|
|
81
82
|
rows = await cursor.fetchall()
|
|
82
83
|
result = [dict(zip(columns, row)) for row in rows]
|
|
83
84
|
return result
|
|
84
|
-
elif query_type == QueryTypes.ONE:
|
|
85
|
+
elif query_type == QueryTypes.ONE and cursor.description is not None:
|
|
85
86
|
columns = [desc[0] for desc in cursor.description]
|
|
86
87
|
row = await cursor.fetchone()
|
|
87
88
|
result = dict(zip(columns, row)) if row else {}
|
|
88
89
|
return result
|
|
89
|
-
elif query_type == QueryTypes.MANY:
|
|
90
|
+
elif query_type == QueryTypes.MANY and cursor.description is not None:
|
|
90
91
|
columns = [desc[0] for desc in cursor.description]
|
|
91
92
|
rows = await cursor.fetchmany(size)
|
|
92
93
|
result = [dict(zip(columns, row)) for row in rows]
|
|
@@ -160,14 +161,14 @@ class AttrDictCursor(aiomysql.DictCursor):
|
|
|
160
161
|
|
|
161
162
|
class Mysql(MeteBase):
|
|
162
163
|
def __init__(self, pool=None):
|
|
163
|
-
self.pool: MYPool = pool
|
|
164
|
+
# self.pool: Optional[MYPool] = pool
|
|
164
165
|
self.driver = "mysql"
|
|
165
166
|
|
|
166
167
|
def __call__(self, *args: Any, **kwds: Any) -> Any:
|
|
167
168
|
self.__init__(*args, **kwds)
|
|
168
169
|
return self
|
|
169
170
|
|
|
170
|
-
async def query(self, sql, params=None, query_type: QueryTypes =
|
|
171
|
+
async def query(self, sql, params=None, query_type: QueryTypes = QueryTypes.ONE, size: int = 10):
|
|
171
172
|
sql = sql.replace("?", "%s")
|
|
172
173
|
if not self.pool:
|
|
173
174
|
raise ValueError("must be create_engine first.")
|
|
@@ -175,7 +176,7 @@ class Mysql(MeteBase):
|
|
|
175
176
|
return None
|
|
176
177
|
async with self.pool.acquire() as conn:
|
|
177
178
|
if conn.echo:
|
|
178
|
-
info("sql", sql, params)
|
|
179
|
+
info("sql: %s , %s", sql, params)
|
|
179
180
|
|
|
180
181
|
async with conn.cursor() as cursor:
|
|
181
182
|
# current_cursor = getattr(cursor, 'lastrowid', None)
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
from abc import abstractmethod
|
|
1
2
|
from enum import Enum
|
|
2
|
-
from typing import Tuple
|
|
3
|
+
from typing import Any, Dict, List, Optional, Tuple, Union
|
|
4
|
+
from aiomysql.pool import Pool as MyPool
|
|
5
|
+
from aiopg import Pool as PGPool
|
|
3
6
|
|
|
4
7
|
|
|
5
8
|
class QueryTypes(Enum):
|
|
@@ -16,6 +19,10 @@ class QueryTypes(Enum):
|
|
|
16
19
|
|
|
17
20
|
|
|
18
21
|
class MeteBase:
|
|
22
|
+
def __init__(self):
|
|
23
|
+
self.pool: Optional[MyPool | PGPool] = None
|
|
24
|
+
# self.cursor: Optional[Cursor] = None
|
|
25
|
+
# self.conn: Optional[Connection] = None
|
|
19
26
|
|
|
20
27
|
async def __aexit__(self):
|
|
21
28
|
await self.close()
|
|
@@ -46,9 +53,10 @@ class MeteBase:
|
|
|
46
53
|
# if cursor:
|
|
47
54
|
# await cursor.close()
|
|
48
55
|
# self.pool.release(conn)
|
|
56
|
+
@abstractmethod
|
|
49
57
|
async def query(
|
|
50
|
-
self, sql, params=None, query_type: QueryTypes =
|
|
51
|
-
): ...
|
|
58
|
+
self, sql, params=None, query_type: QueryTypes = QueryTypes.ONE, size: int = 10
|
|
59
|
+
) -> Union[None, int, Tuple[Any, Any], Dict, List[Dict]]: ...
|
|
52
60
|
|
|
53
61
|
async def all(self, sql, params):
|
|
54
62
|
return await self.query(sql, params, QueryTypes.ALL)
|
|
@@ -61,6 +69,7 @@ class MeteBase:
|
|
|
61
69
|
|
|
62
70
|
async def count(self, sql, params):
|
|
63
71
|
return await self.query(sql, params, QueryTypes.COUNT)
|
|
72
|
+
|
|
64
73
|
async def group_count(self, sql, params):
|
|
65
74
|
return await self.query(sql, params, QueryTypes.GROUP_COUNT)
|
|
66
75
|
|
|
@@ -73,7 +82,7 @@ class MeteBase:
|
|
|
73
82
|
async def delete(self, sql, params):
|
|
74
83
|
return await self.query(sql, params, QueryTypes.DELETE)
|
|
75
84
|
|
|
76
|
-
async def create(self, sql, params)
|
|
85
|
+
async def create(self, sql, params):
|
|
77
86
|
return await self.query(sql, params, QueryTypes.CREATE)
|
|
78
87
|
|
|
79
88
|
async def create_batch(self, sql, params):
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
|
|
3
|
+
|
|
1
4
|
class objdict(dict):
|
|
2
5
|
def __getattr__(self, attr):
|
|
3
6
|
try:
|
|
@@ -141,7 +144,7 @@ class FieldBase(object):
|
|
|
141
144
|
|
|
142
145
|
def max_when(self, *arg):
|
|
143
146
|
"""
|
|
144
|
-
input: max_when(A.field > 10 ,A.field) \n
|
|
147
|
+
input: max_when(A.field > 10 ,A.field) \n
|
|
145
148
|
output: max(case when A.field > 10 then A.field end)
|
|
146
149
|
"""
|
|
147
150
|
return Function(self, OP.MAX_WHEN, arg)
|
|
@@ -151,7 +154,7 @@ class FieldBase(object):
|
|
|
151
154
|
|
|
152
155
|
def min_when(self, *arg):
|
|
153
156
|
"""
|
|
154
|
-
input: min_when(A.field > 10 ,A.field) \n
|
|
157
|
+
input: min_when(A.field > 10 ,A.field) \n
|
|
155
158
|
output: min(case when A.field > 10 then A.field end)
|
|
156
159
|
"""
|
|
157
160
|
return Function(self, OP.MIN_WHEN, arg)
|
|
@@ -288,14 +291,14 @@ class ExpList(FieldBase):
|
|
|
288
291
|
def deconstruct(args):
|
|
289
292
|
f = args[0] if len(args) > 0 else None
|
|
290
293
|
v1 = args[1] if len(args) > 1 else 1
|
|
291
|
-
v2 = args[2] if len(args) > 2 and args[2] is not None else
|
|
294
|
+
v2 = args[2] if len(args) > 2 and args[2] is not None else "NULL"
|
|
292
295
|
c = None
|
|
293
296
|
v = None
|
|
294
297
|
if isinstance(f, FieldBase):
|
|
295
298
|
c = f"{f.lhs.full_name} {f.op} ?"
|
|
296
299
|
v = f.rhs
|
|
297
300
|
if isinstance(v1, FieldBase):
|
|
298
|
-
v1 = v1.
|
|
301
|
+
v1 = v1.full_name
|
|
299
302
|
return c, v, v1, v2
|
|
300
303
|
|
|
301
304
|
|
|
@@ -355,32 +358,46 @@ class Function(FieldBase):
|
|
|
355
358
|
return f"json_contains({col_name},json_object({key},?))", [_v]
|
|
356
359
|
elif op == OP.JSON_CONTAINS_ARRAY:
|
|
357
360
|
if is_field:
|
|
358
|
-
return
|
|
361
|
+
return (
|
|
362
|
+
f"json_contains({col_name},json_array({self.rpt.full_name}))",
|
|
363
|
+
None,
|
|
364
|
+
)
|
|
359
365
|
return f"json_contains({col_name},json_array(?))", [self.rpt]
|
|
360
366
|
elif op == OP.COUNT:
|
|
361
367
|
return f"COUNT({col_name})", None
|
|
362
368
|
elif op == OP.COUNT_WHEN:
|
|
363
369
|
c, v, v1, v2 = deconstruct(self.rpt)
|
|
370
|
+
if v2 == "NULL":
|
|
371
|
+
return f"COUNT(CASE WHEN {c} THEN {v1} END)", [v]
|
|
364
372
|
return f"COUNT(CASE WHEN {c} THEN {v1} ELSE {v2} END)", [v]
|
|
365
373
|
elif op == OP.SUM:
|
|
366
374
|
return f"SUM({col_name})", None
|
|
367
375
|
elif op == OP.SUM_WHEN:
|
|
368
376
|
c, v, v1, v2 = deconstruct(self.rpt)
|
|
377
|
+
if v2 == "NULL":
|
|
378
|
+
return f"SUM(CASE WHEN {c} THEN {v1} END)", [v]
|
|
369
379
|
return f"SUM(CASE WHEN {c} THEN {v1} ELSE {v2} END)", [v]
|
|
370
380
|
elif op == OP.AVG:
|
|
371
381
|
return f"AVG({col_name})", None
|
|
372
382
|
elif op == OP.AVG_WHEN:
|
|
373
383
|
c, v, v1, v2 = deconstruct(self.rpt)
|
|
384
|
+
print("avg", v2)
|
|
385
|
+
if v2 == "NULL":
|
|
386
|
+
return f"AVG(CASE WHEN {c} THEN {v1} END)", [v]
|
|
374
387
|
return f"AVG(CASE WHEN {c} THEN {v1} ELSE {v2} END)", [v]
|
|
375
388
|
elif op == OP.MAX:
|
|
376
389
|
return f"MAX({col_name})", None
|
|
377
390
|
elif op == OP.MAX_WHEN:
|
|
378
391
|
c, v, v1, v2 = deconstruct(self.rpt)
|
|
392
|
+
if v2 == "NULL":
|
|
393
|
+
return f"MAX(CASE WHEN {c} THEN {v1} END)", [v]
|
|
379
394
|
return f"MAX(CASE WHEN {c} THEN {v1} ELSE {v2} END)", [v]
|
|
380
395
|
elif op == OP.MIN:
|
|
381
396
|
return f"MIN({col_name})", None
|
|
382
397
|
elif op == OP.MIN_WHEN:
|
|
383
398
|
c, v, v1, v2 = deconstruct(self.rpt)
|
|
399
|
+
if v2 == "NULL":
|
|
400
|
+
return f"MIN(CASE WHEN {c} THEN {v1} END)", [v]
|
|
384
401
|
return f"MIN(CASE WHEN {c} THEN {v1} ELSE {v2} END)", [v]
|
|
385
402
|
elif op == OP.GROUP_CONCAT:
|
|
386
403
|
arg = self.rpt
|
|
@@ -488,7 +505,7 @@ class Field(FieldBase):
|
|
|
488
505
|
**kwargs,
|
|
489
506
|
):
|
|
490
507
|
super().__init__()
|
|
491
|
-
self.full_name = None
|
|
508
|
+
self.full_name: Optional[str] = None
|
|
492
509
|
self._value = None
|
|
493
510
|
self.name = name
|
|
494
511
|
self.column_type = column_type
|
|
@@ -150,7 +150,7 @@ class Model(metaclass=ModelMetaclass):
|
|
|
150
150
|
@classmethod
|
|
151
151
|
def use(cls, pool=None):
|
|
152
152
|
cls.__pool__ = pool
|
|
153
|
-
cls.__ispg =
|
|
153
|
+
cls.__ispg = pool.driver == "postgres" if pool else False
|
|
154
154
|
return cls()
|
|
155
155
|
|
|
156
156
|
def select(cls, *args):
|
|
@@ -339,7 +339,7 @@ class Model(metaclass=ModelMetaclass):
|
|
|
339
339
|
return self
|
|
340
340
|
|
|
341
341
|
def test(self):
|
|
342
|
-
return self._sql()
|
|
342
|
+
return self._sql(), self.__params__
|
|
343
343
|
|
|
344
344
|
async def one(self):
|
|
345
345
|
self.limit(1)
|
|
@@ -24,9 +24,7 @@ result = await pool.query("sql")
|
|
|
24
24
|
"""
|
|
25
25
|
__author__ = "Qiu / smallerqiu@gmail.com"
|
|
26
26
|
|
|
27
|
-
from typing import Any
|
|
28
27
|
from aiomysql import create_pool, DictCursor
|
|
29
|
-
from aiomysql.pool import Pool
|
|
30
28
|
|
|
31
29
|
# from aiomysql.cursors import Cursor
|
|
32
30
|
# from aiomysql.connection import Connection
|
|
@@ -51,8 +49,8 @@ class AttrDictCursor(DictCursor):
|
|
|
51
49
|
|
|
52
50
|
|
|
53
51
|
class Mysql(MeteBase):
|
|
54
|
-
def __init__(self):
|
|
55
|
-
self.pool: Pool = None
|
|
52
|
+
# def __init__(self):
|
|
53
|
+
# self.pool: Optional[Pool] = None
|
|
56
54
|
# self.cursor: Cursor = None
|
|
57
55
|
# self.conn: Connection = None
|
|
58
56
|
# self.__MODELS__ = []
|
|
@@ -25,17 +25,16 @@ result = await pool.query("sql")
|
|
|
25
25
|
"""
|
|
26
26
|
__author__ = "Qiu / smallerqiu@gmail.com"
|
|
27
27
|
|
|
28
|
-
from aiopg import create_pool
|
|
28
|
+
from aiopg import create_pool
|
|
29
29
|
from cloudoll.logging import error
|
|
30
30
|
from cloudoll.orm.base import MeteBase
|
|
31
|
-
from typing import Any, Optional
|
|
32
31
|
|
|
33
32
|
|
|
34
33
|
class Postgres(MeteBase):
|
|
35
|
-
def __init__(self):
|
|
36
|
-
|
|
37
|
-
self.cursor: Optional[Cursor] = None
|
|
38
|
-
self.conn: Optional[Connection] = None
|
|
34
|
+
# def __init__(self):
|
|
35
|
+
# self.pool: Optional[Pool] = None
|
|
36
|
+
# self.cursor: Optional[Cursor] = None
|
|
37
|
+
# self.conn: Optional[Connection] = None
|
|
39
38
|
# self.__MODELS__ = []
|
|
40
39
|
|
|
41
40
|
# def __call__(cls, *args: Any, **kwds: Any) -> Any:
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
from model import models, Model
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class A(Model):
|
|
5
|
+
|
|
6
|
+
__table__ = "a"
|
|
7
|
+
|
|
8
|
+
id = models.BigIntegerField(
|
|
9
|
+
primary_key=True, max_length=64, not_null=True, comment="ID"
|
|
10
|
+
)
|
|
11
|
+
source = models.IntegerField(max_length=16, not_null=True, comment="状态")
|
|
12
|
+
param = models.TextField(not_null=True)
|
|
13
|
+
gmt_create = models.TimestampField(
|
|
14
|
+
max_length=3, default="CURRENT_TIMESTAMP(3)", not_null=True, comment="创建时间"
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class B(Model):
|
|
19
|
+
|
|
20
|
+
__table__ = "b"
|
|
21
|
+
|
|
22
|
+
id = models.BigIntegerField(primary_key=True, max_length=64, not_null=True)
|
|
23
|
+
task_id = models.BigIntegerField(max_length=64, default="0", not_null=True)
|
|
24
|
+
employee_id = models.BigIntegerField(max_length=64, default="0", not_null=True)
|
|
25
|
+
agency_id = models.BigIntegerField(max_length=64, default="0", not_null=True)
|
|
26
|
+
proxy_str = models.VarCharField(max_length=512, default="", not_null=True)
|
|
27
|
+
proxy_scheme = models.VarCharField(max_length=16, default="", not_null=True)
|
|
28
|
+
proxy_ip = models.VarCharField(max_length=64, default="", not_null=True)
|
|
29
|
+
proxy_region = models.VarCharField(max_length=32, default="", not_null=True)
|
|
30
|
+
proxy_order_no = models.VarCharField(max_length=64, default="", not_null=True)
|
|
31
|
+
proxy_merchant = models.VarCharField(max_length=32, default="", not_null=True)
|
|
32
|
+
proxy_subnet = models.VarCharField(max_length=128, default="", not_null=True)
|
|
33
|
+
channel_type = models.IntegerField(max_length=16, default="0", not_null=True)
|
|
34
|
+
channel = models.VarCharField(max_length=512, default="", not_null=True)
|
|
35
|
+
type = models.IntegerField(max_length=16, default="0", not_null=True)
|
|
36
|
+
url = models.VarCharField(max_length=512, default="", not_null=True)
|
|
37
|
+
gmt_create = models.TimestampField(
|
|
38
|
+
max_length=3, default="CURRENT_TIMESTAMP(3)", not_null=True
|
|
39
|
+
)
|
|
40
|
+
timeout = models.IntegerField(max_length=32, default="0", not_null=True)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class C(Model):
|
|
44
|
+
|
|
45
|
+
__table__ = "i_network_speed_result"
|
|
46
|
+
|
|
47
|
+
id = models.BigIntegerField(primary_key=True, max_length=64, not_null=True)
|
|
48
|
+
pack_id = models.BigIntegerField(max_length=64, default="0", not_null=True)
|
|
49
|
+
delay = models.IntegerField(max_length=32, default="-1", not_null=True)
|
|
50
|
+
finish_load = models.IntegerField(max_length=32, default="-1", not_null=True)
|
|
51
|
+
ip = models.VarCharField(max_length=64, default="", not_null=True)
|
|
52
|
+
region = models.VarCharField(max_length=32, default="", not_null=True)
|
|
53
|
+
gmt_create = models.TimestampField(
|
|
54
|
+
max_length=3, default="CURRENT_TIMESTAMP(3)", not_null=True
|
|
55
|
+
)
|
|
56
|
+
speed = models.NumericField(
|
|
57
|
+
max_length=12, scale_length=2, default="0", not_null=True
|
|
58
|
+
)
|
|
59
|
+
packet_loss_rate = models.NumericField(
|
|
60
|
+
max_length=12, scale_length=2, default="0", not_null=True
|
|
61
|
+
)
|
|
62
|
+
is_failed = models.BooleanField(default="true", not_null=True)
|
|
63
|
+
is_timeout = models.BooleanField(default="true", not_null=True)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
if __name__ == "__main__":
|
|
67
|
+
sql, arg = (
|
|
68
|
+
B.use()
|
|
69
|
+
.select(
|
|
70
|
+
B.proxy_order_no.As("host_no"),
|
|
71
|
+
B.proxy_order_no.count().As("total_count"),
|
|
72
|
+
C.region.As("region"),
|
|
73
|
+
C.is_failed.avg_when(C.is_failed == False, C.finish_load).As("avg_val"),
|
|
74
|
+
C.is_failed.min_when(C.is_failed == False, C.finish_load).As("min_val"),
|
|
75
|
+
C.is_failed.max_when(C.is_failed == False, C.finish_load).As("max_val"),
|
|
76
|
+
C.is_failed.sum_when(C.is_failed == False, 1, 0).As("success_count"),
|
|
77
|
+
C.is_failed.sum_when(C.is_failed == True, 1, 0).As("failure_count"),
|
|
78
|
+
)
|
|
79
|
+
.join(C, C.pack_id == B.id)
|
|
80
|
+
.where(
|
|
81
|
+
B.channel_type == 1,
|
|
82
|
+
B.type == int(1),
|
|
83
|
+
B.proxy_order_no.In(tuple(["aa"])),
|
|
84
|
+
)
|
|
85
|
+
.group_by(B.proxy_order_no, C.region)
|
|
86
|
+
.test()
|
|
87
|
+
)
|
|
88
|
+
# sql = B()._exchange_sql(sql)
|
|
89
|
+
print(sql, arg)
|
|
@@ -1,34 +1,30 @@
|
|
|
1
|
-
|
|
2
1
|
import time
|
|
3
2
|
import threading
|
|
4
3
|
|
|
5
4
|
|
|
6
5
|
"""
|
|
7
|
-
雪花算法(全局唯一id)
|
|
8
|
-
|
|
9
|
-
# 最早是Twitter公司在其内部用于分布式环境下生成唯一ID
|
|
10
|
-
|
|
11
6
|
# Twitter's Snowflake algorithm implementation which is used to generate distributed IDs.
|
|
12
|
-
|
|
13
7
|
# https://github.com/twitter-archive/snowflake/blob/snowflake-2010/src/main/scala/com/twitter/service/snowflake/IdWorker.scala
|
|
14
8
|
"""
|
|
15
9
|
|
|
16
10
|
|
|
17
11
|
class IdWorker:
|
|
18
12
|
def __init__(self, worker_id, datacenter_id, sequence=0):
|
|
19
|
-
|
|
13
|
+
# 位移值
|
|
20
14
|
self.worker_id_bits = 5
|
|
21
15
|
self.datacenter_id_bits = 5
|
|
22
16
|
self.sequence_bits = 12
|
|
23
|
-
|
|
17
|
+
|
|
24
18
|
self.max_worker_id = -1 ^ (-1 << self.worker_id_bits)
|
|
25
19
|
self.max_datacenter_id = -1 ^ (-1 << self.datacenter_id_bits)
|
|
26
20
|
|
|
27
21
|
# 参数校验
|
|
28
22
|
if worker_id > self.max_worker_id or worker_id < 0:
|
|
29
|
-
raise ValueError(f
|
|
23
|
+
raise ValueError(f"worker_id must be between 0 and {self.max_worker_id}")
|
|
30
24
|
if datacenter_id > self.max_datacenter_id or datacenter_id < 0:
|
|
31
|
-
raise ValueError(
|
|
25
|
+
raise ValueError(
|
|
26
|
+
f"datacenter_id must be between 0 and {self.max_datacenter_id}"
|
|
27
|
+
)
|
|
32
28
|
|
|
33
29
|
self.worker_id = worker_id
|
|
34
30
|
self.datacenter_id = datacenter_id
|
|
@@ -38,12 +34,11 @@ class IdWorker:
|
|
|
38
34
|
# Twitter Epoch (2010-11-04 01:42:54 UTC)
|
|
39
35
|
self.twepoch = 1288834974657
|
|
40
36
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
37
|
self.worker_id_shift = self.sequence_bits
|
|
45
38
|
self.datacenter_id_shift = self.sequence_bits + self.worker_id_bits
|
|
46
|
-
self.timestamp_left_shift =
|
|
39
|
+
self.timestamp_left_shift = (
|
|
40
|
+
self.sequence_bits + self.worker_id_bits + self.datacenter_id_bits
|
|
41
|
+
)
|
|
47
42
|
self.sequence_mask = -1 ^ (-1 << self.sequence_bits)
|
|
48
43
|
|
|
49
44
|
self.last_timestamp = -1
|
|
@@ -62,7 +57,9 @@ class IdWorker:
|
|
|
62
57
|
timestamp = self._time_gen()
|
|
63
58
|
|
|
64
59
|
if timestamp < self.last_timestamp:
|
|
65
|
-
raise Exception(
|
|
60
|
+
raise Exception(
|
|
61
|
+
f"Clock moved backwards. Refusing to generate id for {self.last_timestamp - timestamp} milliseconds"
|
|
62
|
+
)
|
|
66
63
|
|
|
67
64
|
if self.last_timestamp == timestamp:
|
|
68
65
|
self.sequence = (self.sequence + 1) & self.sequence_mask
|
|
@@ -73,10 +70,12 @@ class IdWorker:
|
|
|
73
70
|
|
|
74
71
|
self.last_timestamp = timestamp
|
|
75
72
|
|
|
76
|
-
id = (
|
|
77
|
-
(self.
|
|
78
|
-
(self.
|
|
79
|
-
self.
|
|
73
|
+
id = (
|
|
74
|
+
((timestamp - self.twepoch) << self.timestamp_left_shift)
|
|
75
|
+
| (self.datacenter_id << self.datacenter_id_shift)
|
|
76
|
+
| (self.worker_id << self.worker_id_shift)
|
|
77
|
+
| self.sequence
|
|
78
|
+
)
|
|
80
79
|
|
|
81
80
|
return id
|
|
82
81
|
|
|
@@ -6,7 +6,6 @@ __author__ = "Qiu / smallerqiu@gmail.com"
|
|
|
6
6
|
import argparse
|
|
7
7
|
import asyncio
|
|
8
8
|
import hashlib
|
|
9
|
-
import os
|
|
10
9
|
import base64
|
|
11
10
|
import importlib.util
|
|
12
11
|
import inspect
|
|
@@ -17,7 +16,7 @@ import time
|
|
|
17
16
|
from urllib import parse
|
|
18
17
|
from aiohttp import web, hdrs
|
|
19
18
|
from aiohttp.web import Response
|
|
20
|
-
from aiohttp.web_ws import WebSocketResponse,
|
|
19
|
+
from aiohttp.web_ws import WebSocketResponse,WSMsgType
|
|
21
20
|
from aiohttp.web_response import StreamResponse
|
|
22
21
|
from aiohttp.web_request import Request
|
|
23
22
|
from aiohttp.typedefs import LooseHeaders
|
|
@@ -157,7 +156,7 @@ class Application(object):
|
|
|
157
156
|
def __init__(self):
|
|
158
157
|
self._loop = None
|
|
159
158
|
self.env = None
|
|
160
|
-
self.app: web.Application = None
|
|
159
|
+
self.app: Optional[web.Application] = None
|
|
161
160
|
self._route_table = web.RouteTableDef()
|
|
162
161
|
self._middleware = []
|
|
163
162
|
self.config = {}
|
|
@@ -282,8 +281,13 @@ class Application(object):
|
|
|
282
281
|
async def _init_database(self, apps):
|
|
283
282
|
conf_db = self.config.get("database")
|
|
284
283
|
if conf_db:
|
|
285
|
-
for db_key in conf_db:
|
|
286
|
-
|
|
284
|
+
# for db_key in conf_db:
|
|
285
|
+
# apps.db[db_key] = await create_engine(**conf_db[db_key])
|
|
286
|
+
|
|
287
|
+
tasks = [create_engine(**conf_db[db_key]) for db_key in conf_db]
|
|
288
|
+
engines = await asyncio.gather(*tasks)
|
|
289
|
+
for db_key, engine in zip(conf_db.keys(), engines):
|
|
290
|
+
apps.db[db_key] = engine
|
|
287
291
|
|
|
288
292
|
async def _init_session(self, apps):
|
|
289
293
|
config = self.config or {}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cloudoll
|
|
3
|
-
Version: 3.0.
|
|
3
|
+
Version: 3.0.6
|
|
4
4
|
Summary: Assist in quickly creating distributable microservices based on aiohttp, with a focus on simplicity and ease of use.
|
|
5
5
|
Home-page: https://github.com/smallerqiu/cloudoll-py
|
|
6
6
|
Author: Qiu
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "cloudoll"
|
|
7
|
-
version = "3.0.
|
|
7
|
+
version = "3.0.6"
|
|
8
8
|
description = "Assist in quickly creating distributable microservices based on aiohttp, with a focus on simplicity and ease of use."
|
|
9
9
|
authors = [
|
|
10
10
|
{name = "Qiu", email = "smallerqiu@gmail.com"},
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "3.0.4"
|
|
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
|
|
File without changes
|