cloudoll 2.2.37__tar.gz → 2.2.38__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 (46) hide show
  1. {cloudoll-2.2.37 → cloudoll-2.2.38}/PKG-INFO +1 -1
  2. cloudoll-2.2.38/cloudoll/__init__.py +1 -0
  3. cloudoll-2.2.38/cloudoll/cli.py +76 -0
  4. {cloudoll-2.2.37 → cloudoll-2.2.38}/cloudoll/orm/__init__.py +1 -1
  5. cloudoll-2.2.38/cloudoll/utils/cli_mian.py +74 -0
  6. {cloudoll-2.2.37 → cloudoll-2.2.38}/cloudoll/utils/common.py +12 -0
  7. {cloudoll-2.2.37 → cloudoll-2.2.38}/cloudoll/utils/watch.py +33 -12
  8. {cloudoll-2.2.37 → cloudoll-2.2.38}/cloudoll/web/__init__.py +5 -1
  9. {cloudoll-2.2.37 → cloudoll-2.2.38}/cloudoll.egg-info/PKG-INFO +1 -1
  10. {cloudoll-2.2.37 → cloudoll-2.2.38}/cloudoll.egg-info/SOURCES.txt +1 -0
  11. cloudoll-2.2.37/cloudoll/__init__.py +0 -1
  12. cloudoll-2.2.37/cloudoll/cli.py +0 -137
  13. {cloudoll-2.2.37 → cloudoll-2.2.38}/LICENSE +0 -0
  14. {cloudoll-2.2.37 → cloudoll-2.2.38}/README.md +0 -0
  15. {cloudoll-2.2.37 → cloudoll-2.2.38}/cloudoll/__main__.py +0 -0
  16. {cloudoll-2.2.37 → cloudoll-2.2.38}/cloudoll/error/__init__.py +0 -0
  17. {cloudoll-2.2.37 → cloudoll-2.2.38}/cloudoll/error/errors.py +0 -0
  18. {cloudoll-2.2.37 → cloudoll-2.2.38}/cloudoll/logging/__init__.py +0 -0
  19. {cloudoll-2.2.37 → cloudoll-2.2.38}/cloudoll/mail/__init__.py +0 -0
  20. {cloudoll-2.2.37 → cloudoll-2.2.38}/cloudoll/mail/smtp.py +0 -0
  21. {cloudoll-2.2.37 → cloudoll-2.2.38}/cloudoll/orm/base.py +0 -0
  22. {cloudoll-2.2.37 → cloudoll-2.2.38}/cloudoll/orm/err.py +0 -0
  23. {cloudoll-2.2.37 → cloudoll-2.2.38}/cloudoll/orm/field.py +0 -0
  24. {cloudoll-2.2.37 → cloudoll-2.2.38}/cloudoll/orm/model.py +0 -0
  25. {cloudoll-2.2.37 → cloudoll-2.2.38}/cloudoll/orm/mysql.py +0 -0
  26. {cloudoll-2.2.37 → cloudoll-2.2.38}/cloudoll/orm/parse.py +0 -0
  27. {cloudoll-2.2.37 → cloudoll-2.2.38}/cloudoll/orm/postgres.py +0 -0
  28. {cloudoll-2.2.37 → cloudoll-2.2.38}/cloudoll/robot/__init__.py +0 -0
  29. {cloudoll-2.2.37 → cloudoll-2.2.38}/cloudoll/robot/dingtalk.py +0 -0
  30. {cloudoll-2.2.37 → cloudoll-2.2.38}/cloudoll/robot/feishu.py +0 -0
  31. {cloudoll-2.2.37 → cloudoll-2.2.38}/cloudoll/robot/slack.py +0 -0
  32. {cloudoll-2.2.37 → cloudoll-2.2.38}/cloudoll/utils/__init__.py +0 -0
  33. {cloudoll-2.2.37 → cloudoll-2.2.38}/cloudoll/utils/m2d.py +0 -0
  34. {cloudoll-2.2.37 → cloudoll-2.2.38}/cloudoll/utils/patch_loop.py +0 -0
  35. {cloudoll-2.2.37 → cloudoll-2.2.38}/cloudoll/utils/snowflake.py +0 -0
  36. {cloudoll-2.2.37 → cloudoll-2.2.38}/cloudoll/web/exception.py +0 -0
  37. {cloudoll-2.2.37 → cloudoll-2.2.38}/cloudoll/web/html.py +0 -0
  38. {cloudoll-2.2.37 → cloudoll-2.2.38}/cloudoll/web/http.py +0 -0
  39. {cloudoll-2.2.37 → cloudoll-2.2.38}/cloudoll/web/jwt.py +0 -0
  40. {cloudoll-2.2.37 → cloudoll-2.2.38}/cloudoll/web/settings.py +0 -0
  41. {cloudoll-2.2.37 → cloudoll-2.2.38}/cloudoll.egg-info/dependency_links.txt +0 -0
  42. {cloudoll-2.2.37 → cloudoll-2.2.38}/cloudoll.egg-info/entry_points.txt +0 -0
  43. {cloudoll-2.2.37 → cloudoll-2.2.38}/cloudoll.egg-info/requires.txt +0 -0
  44. {cloudoll-2.2.37 → cloudoll-2.2.38}/cloudoll.egg-info/top_level.txt +0 -0
  45. {cloudoll-2.2.37 → cloudoll-2.2.38}/setup.cfg +0 -0
  46. {cloudoll-2.2.37 → cloudoll-2.2.38}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cloudoll
3
- Version: 2.2.37
3
+ Version: 2.2.38
4
4
  Summary: 辅助快速创建可分布的微服务。
5
5
  Home-page: https://gitee.com/chuchur/cloudoll-py
6
6
  Author: chuchur
@@ -0,0 +1 @@
1
+ __version__ = "2.2.38"
@@ -0,0 +1,76 @@
1
+ import click
2
+ import asyncio
3
+ import os
4
+ import sys
5
+ from .logging import print_error
6
+ from . import __version__
7
+ from typing import Any
8
+ from .utils.cli_mian import run_app, run_gen
9
+ sys.path.append(os.path.abspath("."))
10
+
11
+
12
+ @click.group()
13
+ @click.version_option(__version__, "-V", "--version", prog_name="cloudoll")
14
+ def cli() -> None:
15
+ pass
16
+
17
+
18
+ life_cycle = ["on_startup", "on_shutdown", "on_cleanup", "cleanup_ctx"]
19
+
20
+
21
+ @cli.command()
22
+ @click.option("-p", "--path", help="Model's relative path,save models or create tables", default="models.py",)
23
+ @click.option("-c", "--create", help="For create model or table, model / table", default="model")
24
+ @click.option("-t", "--table", help="Table's name or Model's name, split by `,` or 'ALL'", required=True,)
25
+ @click.option("-env", "--environment", help="Environment, local / test / prod", default="local")
26
+ @click.option("-db", "--database", help="Database name, pick the database in conf.{env}.yaml", default="mysql",)
27
+ def gen(**config: Any) -> None:
28
+ """Help to create models or tables."""
29
+
30
+ # click.echo(create)
31
+ async def start():
32
+ try:
33
+ sa = await run_gen(**config)
34
+ except Exception as e:
35
+ # traceback.print_exc()
36
+ print_error('Error: %s', e)
37
+ click.echo("input `cloudoll --help` for more helps.")
38
+ finally:
39
+ await sa.close()
40
+
41
+ asyncio.run(start())
42
+
43
+
44
+ @cli.command()
45
+ @click.option("-env", "--environment", help="Environment, local / test / prod", default="local")
46
+ @click.option("-p", "--port", help="Server's port", default=None)
47
+ @click.option("-h", "--host", help="Server's host", default=None)
48
+ @click.option("-m", "--mode", help="development or production mode", default='development')
49
+ @click.option("-path", "--path", help="Unix file system path to serve on. Specifying a path will cause hostname and port arguments to be ignored.",)
50
+ @click.option("-e", "--entry", help="Entry point model name. delfault name app", default="app")
51
+ def start(**config: Any) -> None:
52
+ """Start a services."""
53
+ try:
54
+ active_config = {k: v for k, v in config.items() if v is not None}
55
+ run_app(**active_config)
56
+ except Exception as e:
57
+ print_error('Error: %s', e)
58
+ # traceback.format_exc()
59
+ sys.exit(2)
60
+
61
+
62
+ _project_existing = click.Path(dir_okay=True)
63
+
64
+
65
+ @cli.command()
66
+ @click.argument("project-name", type=_project_existing, required=True)
67
+ def create(project_name) -> None:
68
+ full_path = os.path.join(os.path.abspath("."), project_name)
69
+ # log = logging.getLogger('cloudoll.create')
70
+ if os.path.exists(full_path):
71
+ print_error(f"Project name `{project_name}` already exist.")
72
+ # return None
73
+
74
+
75
+ if __name__ == "__main__":
76
+ cli()
@@ -44,7 +44,7 @@ async def create_engine(**kw):
44
44
  url = f"{driver}://{configs['username']}:{configs['password']}@{configs['host']}:{configs['port']}/{configs['db']}"
45
45
  return await aioredis.from_url(url, **query)
46
46
  else:
47
- print_error("Not suport this database type.")
47
+ raise "Not suport this database type."
48
48
 
49
49
 
50
50
  class Postgres(MeteBase):
@@ -0,0 +1,74 @@
1
+
2
+
3
+ from typing import Any
4
+ from ..web.settings import get_config
5
+ from ..logging import print_info
6
+ from .common import Object, chainMap
7
+ from ..utils.watch import AppTask
8
+ from aiohttp import web
9
+ from ..web import app
10
+ from pathlib import Path
11
+ from ..utils.m2d import create_models, create_tables
12
+ from ..orm import create_engine
13
+ import os
14
+
15
+
16
+ def run_app(**config_kwargs: Any):
17
+ config = Object(config_kwargs)
18
+ print_info("Current mode: ", config.mode)
19
+ app_config = get_config(config.environment)
20
+ # print(environment, host, port, mode, path, entry)
21
+ # return
22
+ if config.mode == 'production':
23
+ App = app.create(env=config.environment, config=app_config, entry_model=config.entry)
24
+ App.run()
25
+ else:
26
+ aux_app = web.Application(
27
+ logger=None,
28
+ )
29
+ defaults = {"host": "0.0.0.0", "port": 9001, "path": None}
30
+ conf_server = app_config.get("server", {})
31
+ env_server = {"host": config.host, "port": config.port, "path": config.path}
32
+ server = chainMap(defaults, conf_server, env_server)
33
+ app_config["server"] = server
34
+ aux_port = int(server.port) + 1
35
+ task = AppTask(Path(".").resolve(), app_config, entry=config.entry, env=config.environment)
36
+ aux_app.cleanup_ctx.append(task.cleanup_ctx)
37
+ web.run_app(
38
+ aux_app,
39
+ access_log=None,
40
+ host=config.host,
41
+ port=aux_port,
42
+ print=None,
43
+ shutdown_timeout=0.1,
44
+ )
45
+
46
+
47
+ async def run_gen(**config_kwargs: Any):
48
+ config = Object(config_kwargs)
49
+ configs = get_config(config.environment)
50
+ db_configs = configs.get("database")
51
+ if db_configs is None:
52
+ raise KeyError(
53
+ f"Can't find the database config in conf.{config.environment}.yaml"
54
+ )
55
+ db_config = db_configs.get(config.database)
56
+ if db_config is None:
57
+ raise KeyError(
58
+ f"Can't find the database config key ->{config.database} in conf.{config.environment}.yaml"
59
+ )
60
+ sa = await create_engine(**db_config)
61
+ if sa.pool is None:
62
+ return
63
+ model_path = os.path.join(os.path.abspath("."), config.path)
64
+ tables = None
65
+ if config.table != "ALL":
66
+ tables = config.table.split(",")
67
+
68
+ if config.create == "model":
69
+ await create_models(sa, config.path, tables=tables)
70
+ print_info(f"Model save at:{model_path}")
71
+ elif config.create == "table":
72
+ if model_path is None:
73
+ raise ValueError("Need package name or model name.")
74
+ await create_tables(sa, model_path, tables=tables)
@@ -6,7 +6,19 @@ class Object(dict):
6
6
 
7
7
  def __getattr__(self, key):
8
8
  return self.get(key, None)
9
+
10
+ def __delattr__(self, key):
11
+ try:
12
+ del self[key]
13
+ except KeyError:
14
+ raise AttributeError(f"'DotDict' object has no attribute '{key}'")
15
+
16
+ def __getstate__(self):
17
+ '''to fix pickle.dumps '''
18
+ return dict(self)
9
19
 
20
+ def __setstate__(self, state):
21
+ self.update(state)
10
22
 
11
23
  def chainMap(*dicts):
12
24
  merged_dict = Object()
@@ -1,4 +1,4 @@
1
- from typing import AsyncIterator, Iterable, Optional, Tuple, Union
1
+ from typing import AsyncIterator, Optional, Union
2
2
  from pathlib import Path
3
3
  from ..web import Application, app, check_port_open
4
4
  import asyncio
@@ -10,9 +10,10 @@ from multiprocessing import Process
10
10
  from watchfiles import awatch, DefaultFilter
11
11
  from ..logging import print_info, print_warn
12
12
  import contextlib
13
- from typing import Any, Iterator, Optional, NoReturn
14
- from typing import TYPE_CHECKING, Optional, Sequence, Union
13
+ from typing import Iterator, Optional
14
+ from typing import Optional, Union
15
15
  from aiohttp import web
16
+ import traceback
16
17
 
17
18
 
18
19
  class CloudollFilter(DefaultFilter):
@@ -95,6 +96,8 @@ def mian_app(tty_path, config, entry, env):
95
96
  loop.run_forever()
96
97
  except KeyboardInterrupt:
97
98
  pass
99
+ except Exception as e:
100
+ traceback.print_exc()
98
101
  finally:
99
102
  with suppress(asyncio.TimeoutError, KeyboardInterrupt):
100
103
  loop.run_until_complete(runner.cleanup())
@@ -123,9 +126,8 @@ class AppTask(WatchTask):
123
126
 
124
127
  async def _run(self) -> None:
125
128
  assert self._app is not None
129
+ self._start_dev_server()
126
130
  try:
127
- self._start_dev_server()
128
-
129
131
  async for changes in self._awatch:
130
132
  self._reloads += 1
131
133
  if any(f.endswith(".py") for _, f in changes):
@@ -134,15 +136,14 @@ class AppTask(WatchTask):
134
136
  self._start_dev_server()
135
137
  await asyncio.sleep(1)
136
138
  except Exception as exc:
137
- # exception(exc)
139
+ traceback.print_exc()
140
+
138
141
  raise Exception("error running dev server")
139
142
 
140
143
  def _start_dev_server(self) -> None:
141
144
  act = "Start" if self._reloads == 0 else "Restart"
142
145
  print_info(f"{act}ing dev server")
143
- print_info(
144
- f"Server Running on http://{self._config['server']['host']}:{self._config['server']['port']}"
145
- )
146
+
146
147
 
147
148
  try:
148
149
  tty_path = os.ttyname(sys.stdin.fileno())
@@ -153,10 +154,30 @@ class AppTask(WatchTask):
153
154
  # on windows, without a windows machine I've no idea what else to do here
154
155
  tty_path = None
155
156
 
156
- self._process = Process(
157
- target=mian_app, args=(tty_path, self._config, self._entry, self._env)
157
+ # for key, value in self._config.items():
158
+ # try:
159
+ # pickle.dumps(value)
160
+ # except Exception as e:
161
+ # print(f"Serialization error on key '{key}': {e} {value}")
162
+
163
+ # import pickle
164
+ # try:
165
+ # pickle.dumps(b) # 检查是否可序列化
166
+ # except Exception as e:
167
+ # print("Serialization error:", e)
168
+ try:
169
+ self._process = Process(
170
+ target=mian_app, args=(tty_path, self._config, self._entry, self._env)
171
+ )
172
+ self._process.start()
173
+ except Exception as e:
174
+ print(f"Error starting server: {e}")
175
+
176
+ print_info(
177
+ f"Server Running on http://{self._config['server']['host']}:{self._config['server']['port']}"
158
178
  )
159
- self._process.start()
179
+ print_info("(Press CTRL+C to quit)")
180
+
160
181
 
161
182
  async def _stop_dev_server(self) -> None:
162
183
  if self._process.is_alive():
@@ -142,6 +142,7 @@ async def check_port_open(port: int, delay: float = 1) -> None:
142
142
 
143
143
 
144
144
  def auto_reg_module(module_dir: str):
145
+
145
146
  module_path = os.path.join(os.path.abspath("."), module_dir)
146
147
  if not os.path.exists(module_path):
147
148
  print_info(f"{module_dir} not detected")
@@ -218,6 +219,7 @@ class Application(object):
218
219
 
219
220
  # middlewares
220
221
  auto_reg_module("middlewares")
222
+ print_info("auto register middlewares")
221
223
 
222
224
  conf_server = config.get("server")
223
225
  client_max_size = 1024**2 * 2
@@ -242,6 +244,8 @@ class Application(object):
242
244
  # self._init_session()
243
245
  # router:
244
246
  auto_reg_module("controllers")
247
+ print_info("auto register controllers")
248
+
245
249
  self.app.add_routes(self._route_table)
246
250
 
247
251
  # load life
@@ -584,7 +588,7 @@ def render_json(data, **kw) -> Response:
584
588
  res.update(data)
585
589
  elif isinstance(data, tuple):
586
590
  data = dict(data)
587
- res.update(data)
591
+ res.update(data)
588
592
  else:
589
593
  res["data"] = data
590
594
  status = kw.get("status", 200)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cloudoll
3
- Version: 2.2.37
3
+ Version: 2.2.38
4
4
  Summary: 辅助快速创建可分布的微服务。
5
5
  Home-page: https://gitee.com/chuchur/cloudoll-py
6
6
  Author: chuchur
@@ -28,6 +28,7 @@ cloudoll/robot/dingtalk.py
28
28
  cloudoll/robot/feishu.py
29
29
  cloudoll/robot/slack.py
30
30
  cloudoll/utils/__init__.py
31
+ cloudoll/utils/cli_mian.py
31
32
  cloudoll/utils/common.py
32
33
  cloudoll/utils/m2d.py
33
34
  cloudoll/utils/patch_loop.py
@@ -1 +0,0 @@
1
- __version__ = "2.2.37"
@@ -1,137 +0,0 @@
1
- import click
2
- from .web.settings import get_config
3
- from .web import app
4
- from .orm import create_engine
5
- from .utils.m2d import create_models, create_tables
6
- import asyncio
7
- import os
8
- import sys
9
- from .logging import print_error, print_info
10
- from pathlib import Path
11
- from . import __version__
12
- import traceback
13
- from .utils.watch import AppTask
14
- from aiohttp import web
15
- from .utils.common import chainMap
16
-
17
- sys.path.append(os.path.abspath("."))
18
-
19
-
20
- @click.group()
21
- @click.version_option(__version__, "-V", "--version", prog_name="cloudoll")
22
- def cli() -> None:
23
- pass
24
-
25
-
26
- life_cycle = ["on_startup", "on_shutdown", "on_cleanup", "cleanup_ctx"]
27
-
28
-
29
- @cli.command()
30
- @click.option("-p", "--path", help="Model's relative path,save models or create tables", default="models.py",)
31
- @click.option("-c", "--create", help="For create model or table, model / table", default="model")
32
- @click.option("-t", "--table", help="Table's name or Model's name, split by `,` or 'ALL'", required=True,)
33
- @click.option("-env", "--environment", help="Environment, local / test / prod", default="local")
34
- @click.option("-db", "--database", help="Database name, pick the database in conf.{env}.yaml", default="mysql",)
35
- def gen(path, create, table, environment, database) -> None:
36
- """Help to create models or tables."""
37
-
38
- # click.echo(create)
39
- async def start():
40
- try:
41
- config = get_config(environment)
42
- url_config = config.get("database")
43
- if url_config is None:
44
- raise ValueError(
45
- f"Can't find the database config in conf.{environment}.yaml"
46
- )
47
- db_config = url_config.get(database)
48
- if db_config is None:
49
- raise ValueError(
50
- f"Can't find the database config key ->{database} in conf.{environment}.yaml"
51
- )
52
- sa = await create_engine(**db_config)
53
- if sa.pool is None:
54
- return
55
- model_path = os.path.join(os.path.abspath("."), path)
56
- tables = None
57
- if table != "ALL":
58
- tables = table.split(",")
59
-
60
- if create == "model":
61
- await create_models(sa, path, tables=tables)
62
- print_info(f"Model save at:{model_path}")
63
- elif create == "table":
64
- if model_path is None:
65
- raise ValueError("Need package name or model name.")
66
- await create_tables(sa, model_path, tables=tables)
67
-
68
- except Exception as e:
69
- print_error(traceback.print_exc())
70
- click.echo("input `cloudoll --help` for more helps.")
71
- finally:
72
- await sa.close()
73
-
74
- asyncio.run(start())
75
-
76
-
77
- @cli.command()
78
- @click.option("-env", "--environment", help="Environment, local / test / prod", default="local")
79
- @click.option("-p", "--port", help="Server's port", default=None)
80
- @click.option("-h", "--host", help="Server's host", default=None)
81
- @click.option("-m", "--mode", help="development or production mode", default='development')
82
- @click.option("-path", "--path", help="Unix file system path to serve on. Specifying a path will cause hostname and port arguments to be ignored.",)
83
- @click.option("-e", "--entry", help="Entry point model name. delfault name app", default="app")
84
- def start(environment, host, port, mode, path, entry) -> None:
85
- """Start a services."""
86
- try:
87
- print_info("Current mode: ", mode)
88
- config = get_config(environment)
89
- # print(environment, host, port, mode, path, entry)
90
- # return
91
- if mode == 'production':
92
- App = app.create(env=environment, config=config, entry_model=entry)
93
- App.run()
94
- return
95
- aux_app = web.Application(
96
- logger=None,
97
- )
98
- defaults = {"host": "0.0.0.0", "port": 9001, "path": None}
99
- conf_server = config.get("server", {})
100
- env_server = {"host": host, "port": port, "path": path}
101
- server = chainMap(defaults, conf_server, env_server)
102
- config["server"] = server
103
-
104
- aux_port = int(server.port) + 1
105
- task = AppTask(Path(".").resolve(), config, entry=entry, env=environment)
106
- aux_app.cleanup_ctx.append(task.cleanup_ctx)
107
- web.run_app(
108
- aux_app,
109
- access_log=None,
110
- host=host,
111
- port=aux_port,
112
- print=None,
113
- shutdown_timeout=0.1,
114
- )
115
- except KeyboardInterrupt:
116
- sys.exit(0)
117
- except Exception as e:
118
- print_error(e)
119
- print_error(traceback.format_exc())
120
- sys.exit(0)
121
-
122
-
123
- _project_existing = click.Path(dir_okay=True)
124
-
125
-
126
- @cli.command()
127
- @click.argument("project-name", type=_project_existing, required=True)
128
- def create(project_name) -> None:
129
- full_path = os.path.join(os.path.abspath("."), project_name)
130
- # log = logging.getLogger('cloudoll.create')
131
- if os.path.exists(full_path):
132
- print_error(f"Project name `{project_name}` already exist.")
133
- # return None
134
-
135
-
136
- if __name__ == "__main__":
137
- cli()
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes