cloudoll 2.2.38__tar.gz → 2.3.1__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.2.38 → cloudoll-2.3.1}/PKG-INFO +13 -2
- cloudoll-2.3.1/cloudoll/__init__.py +1 -0
- {cloudoll-2.2.38 → cloudoll-2.3.1}/cloudoll/cli.py +1 -1
- {cloudoll-2.2.38 → cloudoll-2.3.1}/cloudoll/logging/__init__.py +2 -2
- {cloudoll-2.2.38 → cloudoll-2.3.1}/cloudoll/orm/__init__.py +6 -78
- {cloudoll-2.2.38 → cloudoll-2.3.1}/cloudoll/orm/model.py +117 -116
- cloudoll-2.2.38/cloudoll/utils/cli_mian.py → cloudoll-2.3.1/cloudoll/utils/cli_main.py +2 -4
- cloudoll-2.3.1/cloudoll/utils/common.py +51 -0
- {cloudoll-2.2.38 → cloudoll-2.3.1}/cloudoll/utils/watch.py +14 -23
- cloudoll-2.3.1/cloudoll/web/__init__.py +53 -0
- cloudoll-2.2.38/cloudoll/web/__init__.py → cloudoll-2.3.1/cloudoll/web/core.py +134 -199
- cloudoll-2.3.1/cloudoll/web/http.py +79 -0
- {cloudoll-2.2.38 → cloudoll-2.3.1}/cloudoll/web/settings.py +4 -4
- {cloudoll-2.2.38 → cloudoll-2.3.1}/cloudoll.egg-info/PKG-INFO +13 -2
- {cloudoll-2.2.38 → cloudoll-2.3.1}/cloudoll.egg-info/SOURCES.txt +2 -1
- {cloudoll-2.2.38 → cloudoll-2.3.1}/setup.py +0 -3
- cloudoll-2.2.38/cloudoll/__init__.py +0 -1
- cloudoll-2.2.38/cloudoll/utils/common.py +0 -29
- cloudoll-2.2.38/cloudoll/web/http.py +0 -139
- {cloudoll-2.2.38 → cloudoll-2.3.1}/LICENSE +0 -0
- {cloudoll-2.2.38 → cloudoll-2.3.1}/README.md +0 -0
- {cloudoll-2.2.38 → cloudoll-2.3.1}/cloudoll/__main__.py +0 -0
- {cloudoll-2.2.38 → cloudoll-2.3.1}/cloudoll/error/__init__.py +0 -0
- {cloudoll-2.2.38 → cloudoll-2.3.1}/cloudoll/error/errors.py +0 -0
- {cloudoll-2.2.38 → cloudoll-2.3.1}/cloudoll/mail/__init__.py +0 -0
- {cloudoll-2.2.38 → cloudoll-2.3.1}/cloudoll/mail/smtp.py +0 -0
- {cloudoll-2.2.38 → cloudoll-2.3.1}/cloudoll/orm/base.py +0 -0
- {cloudoll-2.2.38 → cloudoll-2.3.1}/cloudoll/orm/err.py +0 -0
- {cloudoll-2.2.38 → cloudoll-2.3.1}/cloudoll/orm/field.py +0 -0
- {cloudoll-2.2.38 → cloudoll-2.3.1}/cloudoll/orm/mysql.py +0 -0
- {cloudoll-2.2.38 → cloudoll-2.3.1}/cloudoll/orm/parse.py +0 -0
- {cloudoll-2.2.38 → cloudoll-2.3.1}/cloudoll/orm/postgres.py +0 -0
- {cloudoll-2.2.38 → cloudoll-2.3.1}/cloudoll/robot/__init__.py +0 -0
- {cloudoll-2.2.38 → cloudoll-2.3.1}/cloudoll/robot/dingtalk.py +0 -0
- {cloudoll-2.2.38 → cloudoll-2.3.1}/cloudoll/robot/feishu.py +0 -0
- {cloudoll-2.2.38 → cloudoll-2.3.1}/cloudoll/robot/slack.py +0 -0
- {cloudoll-2.2.38 → cloudoll-2.3.1}/cloudoll/utils/__init__.py +0 -0
- {cloudoll-2.2.38 → cloudoll-2.3.1}/cloudoll/utils/m2d.py +0 -0
- {cloudoll-2.2.38 → cloudoll-2.3.1}/cloudoll/utils/patch_loop.py +0 -0
- {cloudoll-2.2.38 → cloudoll-2.3.1}/cloudoll/utils/snowflake.py +0 -0
- {cloudoll-2.2.38 → cloudoll-2.3.1}/cloudoll/web/exception.py +0 -0
- {cloudoll-2.2.38 → cloudoll-2.3.1}/cloudoll/web/html.py +0 -0
- {cloudoll-2.2.38 → cloudoll-2.3.1}/cloudoll/web/jwt.py +0 -0
- {cloudoll-2.2.38 → cloudoll-2.3.1}/cloudoll.egg-info/dependency_links.txt +0 -0
- {cloudoll-2.2.38 → cloudoll-2.3.1}/cloudoll.egg-info/entry_points.txt +0 -0
- {cloudoll-2.2.38 → cloudoll-2.3.1}/cloudoll.egg-info/requires.txt +0 -0
- {cloudoll-2.2.38 → cloudoll-2.3.1}/cloudoll.egg-info/top_level.txt +0 -0
- {cloudoll-2.2.38 → cloudoll-2.3.1}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: cloudoll
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.3.1
|
|
4
4
|
Summary: 辅助快速创建可分布的微服务。
|
|
5
5
|
Home-page: https://gitee.com/chuchur/cloudoll-py
|
|
6
6
|
Author: chuchur
|
|
@@ -29,6 +29,17 @@ Requires-Dist: aiohttp_session[secure]
|
|
|
29
29
|
Requires-Dist: PyYAML
|
|
30
30
|
Requires-Dist: click
|
|
31
31
|
Requires-Dist: envyaml
|
|
32
|
+
Dynamic: author
|
|
33
|
+
Dynamic: author-email
|
|
34
|
+
Dynamic: classifier
|
|
35
|
+
Dynamic: description
|
|
36
|
+
Dynamic: description-content-type
|
|
37
|
+
Dynamic: home-page
|
|
38
|
+
Dynamic: license
|
|
39
|
+
Dynamic: license-file
|
|
40
|
+
Dynamic: requires-dist
|
|
41
|
+
Dynamic: requires-python
|
|
42
|
+
Dynamic: summary
|
|
32
43
|
|
|
33
44
|
|
|
34
45
|
# cloudoll 云端玩具
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "2.3.1"
|
|
@@ -42,10 +42,10 @@ class ColorAnsi:
|
|
|
42
42
|
_FORMATS = {
|
|
43
43
|
# 终端输出格式
|
|
44
44
|
# "console_format": "%(log_color)s[%(levelname)s]-%(asctime)s-%(pathname)s-%(module)s-%(funcName)s-[line:%(lineno)d]: %(message)s",
|
|
45
|
-
"console_format": "%(log_color)s%(asctime)s %(levelname)s %(
|
|
45
|
+
"console_format": "%(log_color)s%(asctime)s %(levelname)s %(message)s",
|
|
46
46
|
# 日志输出格式
|
|
47
47
|
# "log_format": "[%(levelname)s]-%(asctime)s-%(pathname)s-%(module)s-%(funcName)s-[line:%(lineno)d]: %(message)s",
|
|
48
|
-
"log_format": "%(asctime)s %(levelname)s %(
|
|
48
|
+
"log_format": "%(asctime)s %(levelname)s %(message)s",
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
_LOG_SIZE = 1024 * 1024 * 1 # 1MB 日志最大1MB
|
|
@@ -10,9 +10,6 @@ from aiomysql import Pool as MYPool
|
|
|
10
10
|
import aiopg as pg
|
|
11
11
|
from aiopg.pool import Pool as PGPool
|
|
12
12
|
|
|
13
|
-
# import asyncpg as pg
|
|
14
|
-
# from asyncpg.pool import Pool as PGPool
|
|
15
|
-
|
|
16
13
|
__ALL__ = "create_engine"
|
|
17
14
|
|
|
18
15
|
|
|
@@ -55,65 +52,6 @@ class Postgres(MeteBase):
|
|
|
55
52
|
def __call__(self, *args: Any, **kwds: Any) -> Any:
|
|
56
53
|
self.__init__(*args, **kwds)
|
|
57
54
|
|
|
58
|
-
# async def query(self, sql, params=None, query_type: QueryTypes = 2, size: int = 10):
|
|
59
|
-
# sql = sql.replace("?", "%s").replace("`", "")
|
|
60
|
-
# print_info("sql", sql, params)
|
|
61
|
-
# if not self.pool:
|
|
62
|
-
# raise ValueError("must be create_engine first.")
|
|
63
|
-
# if self.pool._closing or self.pool._closed:
|
|
64
|
-
# return None
|
|
65
|
-
|
|
66
|
-
# # async with self.pool.acquire() as conn:
|
|
67
|
-
# async with self.pool.acquire() as conn:
|
|
68
|
-
# # current_cursor = getattr(cursor, 'lastrowid', None)
|
|
69
|
-
# if (
|
|
70
|
-
# query_type == QueryTypes.CREATEBATCH
|
|
71
|
-
# or query_type == QueryTypes.UPDATEBATCH
|
|
72
|
-
# ):
|
|
73
|
-
# result = await conn.executemany(sql, params) # aiopg don't support executemany
|
|
74
|
-
# else:
|
|
75
|
-
# result = await conn.execute(sql, params)
|
|
76
|
-
|
|
77
|
-
# # result = None
|
|
78
|
-
|
|
79
|
-
# return result
|
|
80
|
-
|
|
81
|
-
# if query_type == QueryTypes.ALL:
|
|
82
|
-
# columns = [desc[0] for desc in cursor.description]
|
|
83
|
-
# rows = await cursor.fetchall()
|
|
84
|
-
# result = [dict(zip(columns, row)) for row in rows]
|
|
85
|
-
# return result
|
|
86
|
-
# elif query_type == QueryTypes.ONE:
|
|
87
|
-
# columns = [desc[0] for desc in cursor.description]
|
|
88
|
-
# row = await cursor.fetchone()
|
|
89
|
-
# # print("rows_reuslt", rows)
|
|
90
|
-
# result = dict(zip(columns, row)) if row else {}
|
|
91
|
-
# return result
|
|
92
|
-
# elif query_type == QueryTypes.MANY:
|
|
93
|
-
# columns = [desc[0] for desc in cursor.description]
|
|
94
|
-
# rows = await cursor.fetchmany(size)
|
|
95
|
-
# result = [dict(zip(columns, row)) for row in rows]
|
|
96
|
-
# return result
|
|
97
|
-
# elif query_type == QueryTypes.COUNT:
|
|
98
|
-
# rs = await cursor.fetchone()
|
|
99
|
-
# return rs[0] if row else 0
|
|
100
|
-
# elif query_type == QueryTypes.CREATE:
|
|
101
|
-
# result = cursor.rowcount > 0
|
|
102
|
-
# id = cursor.lastrowid
|
|
103
|
-
# return result, id
|
|
104
|
-
# elif query_type == QueryTypes.CREATEBATCH:
|
|
105
|
-
# count = cursor.rowcount
|
|
106
|
-
# id = cursor.lastrowid
|
|
107
|
-
# return count, id
|
|
108
|
-
# elif query_type == QueryTypes.UPDATE:
|
|
109
|
-
# return cursor.rowcount > 0
|
|
110
|
-
# elif query_type == QueryTypes.UPDATEBATCH:
|
|
111
|
-
# return cursor.rowcount
|
|
112
|
-
# elif query_type == QueryTypes.DELETE:
|
|
113
|
-
# return cursor.rowcount > 0
|
|
114
|
-
|
|
115
|
-
# self.pool.release(cursor)
|
|
116
|
-
|
|
117
55
|
async def query(self, sql, params=None, query_type: QueryTypes = 2, size: int = 10):
|
|
118
56
|
sql = sql.replace("?", "%s").replace("`", '"')
|
|
119
57
|
if not self.pool:
|
|
@@ -132,7 +70,7 @@ class Postgres(MeteBase):
|
|
|
132
70
|
or query_type == QueryTypes.UPDATEBATCH
|
|
133
71
|
):
|
|
134
72
|
# aiopg don't support executemany
|
|
135
|
-
|
|
73
|
+
raise RuntimeError("postgres don't support executemany")
|
|
136
74
|
else:
|
|
137
75
|
await cursor.execute(sql, params)
|
|
138
76
|
|
|
@@ -155,8 +93,7 @@ class Postgres(MeteBase):
|
|
|
155
93
|
result = [dict(zip(columns, row)) for row in rows]
|
|
156
94
|
return result
|
|
157
95
|
elif query_type == QueryTypes.COUNT:
|
|
158
|
-
|
|
159
|
-
return rs[0] if row else 0
|
|
96
|
+
return cursor.rowcount
|
|
160
97
|
elif query_type == QueryTypes.CREATE:
|
|
161
98
|
result = cursor.rowcount > 0
|
|
162
99
|
id = cursor.lastrowid
|
|
@@ -182,13 +119,13 @@ class Postgres(MeteBase):
|
|
|
182
119
|
password = (str(kw.get("password", "")),)
|
|
183
120
|
db = (kw.get("db"),)
|
|
184
121
|
dsn = f"dbname={db[0]} user={user[0]} password={password[0]} host={host[0]} port={port[0]}" # aiopg
|
|
185
|
-
# dsn = f"postgres://{user[0]}:{password[0]}@{host[0]}:{port[0]}/{db[0]}" #asyncpg
|
|
122
|
+
# dsn = f"postgres://{user[0]}:{password[0]}@{host[0]}:{port[0]}/{db[0]}" # asyncpg
|
|
186
123
|
self.pool = await pg.create_pool(
|
|
187
124
|
dsn=dsn,
|
|
188
125
|
timeout=kw.get("timeout"),
|
|
189
126
|
echo=kw.get("echo", False), # aiopg
|
|
190
|
-
# max_size=kw.get("maxsize", 10), #asyncpg
|
|
191
|
-
# min_size=kw.get("minsize", 5), #asyncpg
|
|
127
|
+
# max_size=kw.get("maxsize", 10), # asyncpg
|
|
128
|
+
# min_size=kw.get("minsize", 5), # asyncpg
|
|
192
129
|
maxsize=kw.get("maxsize", 10), # aiopg
|
|
193
130
|
minsize=kw.get("minsize", 5), # aiopg
|
|
194
131
|
)
|
|
@@ -246,11 +183,7 @@ class Mysql(MeteBase):
|
|
|
246
183
|
else:
|
|
247
184
|
await cursor.execute(sql, params)
|
|
248
185
|
|
|
249
|
-
# if query_type.value > 4:
|
|
250
|
-
# if self.driver == "mysql":
|
|
251
186
|
await conn.commit()
|
|
252
|
-
# elif self.driver == "postgres":
|
|
253
|
-
# columns = [desc[0] for desc in cursor.description]
|
|
254
187
|
|
|
255
188
|
if query_type == QueryTypes.ALL:
|
|
256
189
|
return await cursor.fetchall()
|
|
@@ -259,11 +192,7 @@ class Mysql(MeteBase):
|
|
|
259
192
|
elif query_type == QueryTypes.MANY:
|
|
260
193
|
return await cursor.fetchmany(size)
|
|
261
194
|
elif query_type == QueryTypes.COUNT:
|
|
262
|
-
|
|
263
|
-
value = 0
|
|
264
|
-
for r in rs:
|
|
265
|
-
value = rs[r]
|
|
266
|
-
return value
|
|
195
|
+
return cursor.rowcount
|
|
267
196
|
elif query_type == QueryTypes.CREATE:
|
|
268
197
|
result = cursor.rowcount > 0
|
|
269
198
|
id = cursor.lastrowid
|
|
@@ -299,7 +228,6 @@ class Mysql(MeteBase):
|
|
|
299
228
|
)
|
|
300
229
|
print_info(f"Database connection successfuly for mysql/{kw.get('db')}.")
|
|
301
230
|
except Exception as e:
|
|
302
|
-
# print(e)
|
|
303
231
|
# print(traceback.format_exc())
|
|
304
232
|
print_error(
|
|
305
233
|
f"Database connection failed,the instance : mysql/{kw.get('db')}"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from .field import Field, Function, Expression
|
|
2
|
-
from ..logging import
|
|
2
|
+
from ..logging import warning
|
|
3
3
|
from functools import reduce
|
|
4
4
|
import operator
|
|
5
5
|
import copy
|
|
@@ -35,13 +35,13 @@ class ModelMetaclass(type):
|
|
|
35
35
|
# mappings[k] = v
|
|
36
36
|
if v.primary_key:
|
|
37
37
|
if primary_key:
|
|
38
|
-
|
|
38
|
+
warning(f"Duplicate primary key for {table_name}")
|
|
39
39
|
primary_key = k
|
|
40
40
|
# else:
|
|
41
41
|
fields.append(k)
|
|
42
42
|
|
|
43
43
|
if not primary_key:
|
|
44
|
-
|
|
44
|
+
warning(f"{table_name} Missing primary key")
|
|
45
45
|
|
|
46
46
|
# for k in mappings.keys():
|
|
47
47
|
# attrs.pop(k)
|
|
@@ -458,7 +458,8 @@ class Model(metaclass=ModelMetaclass):
|
|
|
458
458
|
cls = copy.deepcopy(self)
|
|
459
459
|
JOIN = cls._literal("LEFT JOIN", __join__)
|
|
460
460
|
WHERE = cls._literal("WHERE", __where__)
|
|
461
|
-
|
|
461
|
+
GROUPBY = self._literal("GROUP BY", self.__group_by__)
|
|
462
|
+
aft = " ".join([JOIN, WHERE, GROUPBY])
|
|
462
463
|
sql = f"SELECT COUNT(*) FROM {cls.__table__} {aft}"
|
|
463
464
|
args = cls.__params__
|
|
464
465
|
sql = self._exchange_sql(sql)
|
|
@@ -468,14 +469,14 @@ class Model(metaclass=ModelMetaclass):
|
|
|
468
469
|
class Models(object):
|
|
469
470
|
class CharField(Field):
|
|
470
471
|
def __init__(
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
472
|
+
self,
|
|
473
|
+
name=None,
|
|
474
|
+
primary_key=False,
|
|
475
|
+
default=None,
|
|
476
|
+
charset=None,
|
|
477
|
+
max_length=None,
|
|
478
|
+
not_null=False,
|
|
479
|
+
comment=None,
|
|
479
480
|
):
|
|
480
481
|
super().__init__(
|
|
481
482
|
name,
|
|
@@ -490,14 +491,14 @@ class Models(object):
|
|
|
490
491
|
|
|
491
492
|
class VarCharField(Field):
|
|
492
493
|
def __init__(
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
494
|
+
self,
|
|
495
|
+
name=None,
|
|
496
|
+
primary_key=False,
|
|
497
|
+
default=None,
|
|
498
|
+
charset=None,
|
|
499
|
+
max_length=None,
|
|
500
|
+
not_null=False,
|
|
501
|
+
comment=None,
|
|
501
502
|
):
|
|
502
503
|
super().__init__(
|
|
503
504
|
name,
|
|
@@ -512,7 +513,7 @@ class Models(object):
|
|
|
512
513
|
|
|
513
514
|
class BooleanField(Field):
|
|
514
515
|
def __init__(
|
|
515
|
-
|
|
516
|
+
self, name=None, default=False, not_null=False, comment=None, unsigned=False
|
|
516
517
|
):
|
|
517
518
|
super().__init__(
|
|
518
519
|
name,
|
|
@@ -525,15 +526,15 @@ class Models(object):
|
|
|
525
526
|
|
|
526
527
|
class IntegerField(Field):
|
|
527
528
|
def __init__(
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
529
|
+
self,
|
|
530
|
+
name=None,
|
|
531
|
+
primary_key=False,
|
|
532
|
+
default=None,
|
|
533
|
+
auto_increment=False,
|
|
534
|
+
not_null=False,
|
|
535
|
+
unsigned=False,
|
|
536
|
+
comment=None,
|
|
537
|
+
max_length=None,
|
|
537
538
|
):
|
|
538
539
|
super().__init__(
|
|
539
540
|
name,
|
|
@@ -549,15 +550,15 @@ class Models(object):
|
|
|
549
550
|
|
|
550
551
|
class BigIntegerField(Field):
|
|
551
552
|
def __init__(
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
553
|
+
self,
|
|
554
|
+
name=None,
|
|
555
|
+
primary_key=False,
|
|
556
|
+
default=None,
|
|
557
|
+
auto_increment=False,
|
|
558
|
+
not_null=False,
|
|
559
|
+
unsigned=False,
|
|
560
|
+
comment=None,
|
|
561
|
+
max_length=None,
|
|
561
562
|
):
|
|
562
563
|
super().__init__(
|
|
563
564
|
name,
|
|
@@ -573,13 +574,13 @@ class Models(object):
|
|
|
573
574
|
|
|
574
575
|
class DoubleField(Field):
|
|
575
576
|
def __init__(
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
577
|
+
self,
|
|
578
|
+
name=None,
|
|
579
|
+
default=None,
|
|
580
|
+
not_null=False,
|
|
581
|
+
max_length=None,
|
|
582
|
+
unsigned=False,
|
|
583
|
+
comment=None,
|
|
583
584
|
):
|
|
584
585
|
super().__init__(
|
|
585
586
|
name,
|
|
@@ -593,14 +594,14 @@ class Models(object):
|
|
|
593
594
|
|
|
594
595
|
class FloatField(Field):
|
|
595
596
|
def __init__(
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
597
|
+
self,
|
|
598
|
+
name=None,
|
|
599
|
+
default=None,
|
|
600
|
+
not_null=False,
|
|
601
|
+
max_length=None,
|
|
602
|
+
scale_length=None,
|
|
603
|
+
unsigned=False,
|
|
604
|
+
comment=None,
|
|
604
605
|
):
|
|
605
606
|
super().__init__(
|
|
606
607
|
name,
|
|
@@ -615,14 +616,14 @@ class Models(object):
|
|
|
615
616
|
|
|
616
617
|
class NumericField(Field):
|
|
617
618
|
def __init__(
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
619
|
+
self,
|
|
620
|
+
name=None,
|
|
621
|
+
default=0.0,
|
|
622
|
+
not_null=False,
|
|
623
|
+
max_length=None,
|
|
624
|
+
scale_length=None,
|
|
625
|
+
unsigned=False,
|
|
626
|
+
comment=None,
|
|
626
627
|
):
|
|
627
628
|
super().__init__(
|
|
628
629
|
name,
|
|
@@ -637,14 +638,14 @@ class Models(object):
|
|
|
637
638
|
|
|
638
639
|
class DecimalField(Field):
|
|
639
640
|
def __init__(
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
641
|
+
self,
|
|
642
|
+
name=None,
|
|
643
|
+
default=0.0,
|
|
644
|
+
not_null=False,
|
|
645
|
+
max_length=None,
|
|
646
|
+
scale_length=None,
|
|
647
|
+
unsigned=False,
|
|
648
|
+
comment=None,
|
|
648
649
|
):
|
|
649
650
|
super().__init__(
|
|
650
651
|
name,
|
|
@@ -659,13 +660,13 @@ class Models(object):
|
|
|
659
660
|
|
|
660
661
|
class TextField(Field):
|
|
661
662
|
def __init__(
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
663
|
+
self,
|
|
664
|
+
name=None,
|
|
665
|
+
default=None,
|
|
666
|
+
charset=None,
|
|
667
|
+
max_length=None,
|
|
668
|
+
not_null=False,
|
|
669
|
+
comment=None,
|
|
669
670
|
):
|
|
670
671
|
super().__init__(
|
|
671
672
|
name,
|
|
@@ -679,13 +680,13 @@ class Models(object):
|
|
|
679
680
|
|
|
680
681
|
class LongTextField(Field):
|
|
681
682
|
def __init__(
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
683
|
+
self,
|
|
684
|
+
name=None,
|
|
685
|
+
default=None,
|
|
686
|
+
charset=None,
|
|
687
|
+
max_length=None,
|
|
688
|
+
not_null=False,
|
|
689
|
+
comment=None,
|
|
689
690
|
):
|
|
690
691
|
super().__init__(
|
|
691
692
|
name,
|
|
@@ -699,13 +700,13 @@ class Models(object):
|
|
|
699
700
|
|
|
700
701
|
class MediumTextField(Field):
|
|
701
702
|
def __init__(
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
703
|
+
self,
|
|
704
|
+
name=None,
|
|
705
|
+
default=None,
|
|
706
|
+
charset=None,
|
|
707
|
+
max_length=None,
|
|
708
|
+
not_null=False,
|
|
709
|
+
comment=None,
|
|
709
710
|
):
|
|
710
711
|
super().__init__(
|
|
711
712
|
name,
|
|
@@ -719,14 +720,14 @@ class Models(object):
|
|
|
719
720
|
|
|
720
721
|
class DatetimeField(Field):
|
|
721
722
|
def __init__(
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
723
|
+
self,
|
|
724
|
+
name=None,
|
|
725
|
+
default=None,
|
|
726
|
+
max_length=None,
|
|
727
|
+
not_null=False,
|
|
728
|
+
created_generated=False,
|
|
729
|
+
update_generated=False,
|
|
730
|
+
comment=None,
|
|
730
731
|
):
|
|
731
732
|
super().__init__(
|
|
732
733
|
name,
|
|
@@ -741,14 +742,14 @@ class Models(object):
|
|
|
741
742
|
|
|
742
743
|
class DateField(Field):
|
|
743
744
|
def __init__(
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
745
|
+
self,
|
|
746
|
+
name=None,
|
|
747
|
+
default=None,
|
|
748
|
+
max_length=None,
|
|
749
|
+
not_null=False,
|
|
750
|
+
created_generated=False,
|
|
751
|
+
update_generated=False,
|
|
752
|
+
comment=None,
|
|
752
753
|
):
|
|
753
754
|
super().__init__(
|
|
754
755
|
name,
|
|
@@ -763,14 +764,14 @@ class Models(object):
|
|
|
763
764
|
|
|
764
765
|
class TimestampField(Field):
|
|
765
766
|
def __init__(
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
767
|
+
self,
|
|
768
|
+
name=None,
|
|
769
|
+
default=None,
|
|
770
|
+
max_length=None,
|
|
771
|
+
not_null=False,
|
|
772
|
+
created_generated=False,
|
|
773
|
+
update_generated=False,
|
|
774
|
+
comment=None,
|
|
774
775
|
):
|
|
775
776
|
super().__init__(
|
|
776
777
|
name,
|
|
@@ -786,7 +787,7 @@ class Models(object):
|
|
|
786
787
|
|
|
787
788
|
class JsonField(Field):
|
|
788
789
|
def __init__(
|
|
789
|
-
|
|
790
|
+
self, name=None, default=None, charset=None, not_null=False, comment=None
|
|
790
791
|
):
|
|
791
792
|
super().__init__(
|
|
792
793
|
name,
|
|
@@ -1,14 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
1
|
from typing import Any
|
|
4
2
|
from ..web.settings import get_config
|
|
5
3
|
from ..logging import print_info
|
|
6
4
|
from .common import Object, chainMap
|
|
7
|
-
from
|
|
5
|
+
from .watch import AppTask
|
|
8
6
|
from aiohttp import web
|
|
9
7
|
from ..web import app
|
|
10
8
|
from pathlib import Path
|
|
11
|
-
from
|
|
9
|
+
from .m2d import create_models, create_tables
|
|
12
10
|
from ..orm import create_engine
|
|
13
11
|
import os
|
|
14
12
|
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
class Object(dict):
|
|
3
|
+
# __setattr__ = dict.__setitem__
|
|
4
|
+
# __getattr__ = dict.__getitem__
|
|
5
|
+
def __setattr__(self, key, value):
|
|
6
|
+
self[key] = value
|
|
7
|
+
|
|
8
|
+
def __getattr__(self, key):
|
|
9
|
+
return self.get(key, None)
|
|
10
|
+
|
|
11
|
+
def __delattr__(self, key):
|
|
12
|
+
try:
|
|
13
|
+
del self[key]
|
|
14
|
+
except KeyError:
|
|
15
|
+
raise AttributeError(f"'DotDict' object has no attribute '{key}'")
|
|
16
|
+
|
|
17
|
+
def __getstate__(self):
|
|
18
|
+
'''to fix pickle.dumps '''
|
|
19
|
+
return dict(self)
|
|
20
|
+
|
|
21
|
+
def __setstate__(self, state):
|
|
22
|
+
self.update(state)
|
|
23
|
+
|
|
24
|
+
def chainMap(*dicts):
|
|
25
|
+
merged_dict = Object()
|
|
26
|
+
for d in dicts:
|
|
27
|
+
for key, value in d.items():
|
|
28
|
+
if key not in merged_dict or value is not None:
|
|
29
|
+
merged_dict[key] = value
|
|
30
|
+
return merged_dict
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
async def check_port_open(port: int, delay: float = 1) -> None:
|
|
34
|
+
loop = asyncio.get_running_loop()
|
|
35
|
+
# the "s = socket.socket; s.bind" approach sometimes says a port is in use when it's not
|
|
36
|
+
# this approach replicates aiohttp so should always give the same answer
|
|
37
|
+
for i in range(5, 0, -1):
|
|
38
|
+
try:
|
|
39
|
+
server = await loop.create_server(
|
|
40
|
+
asyncio.Protocol, host="0.0.0.0", port=port
|
|
41
|
+
)
|
|
42
|
+
except OSError as e:
|
|
43
|
+
if e.errno != EADDRINUSE:
|
|
44
|
+
raise
|
|
45
|
+
warning("port %d is already in use, waiting %d...", port, i)
|
|
46
|
+
await asyncio.sleep(delay)
|
|
47
|
+
else:
|
|
48
|
+
server.close()
|
|
49
|
+
await server.wait_closed()
|
|
50
|
+
return
|
|
51
|
+
raise Exception("The port {} is already is use".format(port))
|