zoo-framework 0.5.4b0__py3-none-any.whl
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.
- zoo_framework/__init__.py +72 -0
- zoo_framework/__main__.py +99 -0
- zoo_framework/conf/__init__.py +3 -0
- zoo_framework/conf/log_config.py +55 -0
- zoo_framework/constant/__init__.py +4 -0
- zoo_framework/constant/waiter_constant.py +5 -0
- zoo_framework/constant/worker_constant.py +14 -0
- zoo_framework/core/__init__.py +6 -0
- zoo_framework/core/aop/__init__.py +21 -0
- zoo_framework/core/aop/cage.py +14 -0
- zoo_framework/core/aop/configure.py +22 -0
- zoo_framework/core/aop/event.py +44 -0
- zoo_framework/core/aop/logger.py +61 -0
- zoo_framework/core/aop/params.py +23 -0
- zoo_framework/core/aop/stopwatch.py +16 -0
- zoo_framework/core/aop/validation.py +54 -0
- zoo_framework/core/aop/worker.py +38 -0
- zoo_framework/core/master.py +363 -0
- zoo_framework/core/meta_singleton.py +8 -0
- zoo_framework/core/params_factory.py +58 -0
- zoo_framework/core/params_path.py +10 -0
- zoo_framework/core/persistence_scheduler.py +449 -0
- zoo_framework/core/waiter/__init__.py +7 -0
- zoo_framework/core/waiter/base_waiter.py +166 -0
- zoo_framework/core/waiter/safe_waiter.py +45 -0
- zoo_framework/core/waiter/simple_waiter.py +12 -0
- zoo_framework/core/waiter/stable_waiter.py +6 -0
- zoo_framework/core/waiter/waiter_factory.py +16 -0
- zoo_framework/core/worker_registry.py +271 -0
- zoo_framework/core/zoo_thread.py +36 -0
- zoo_framework/event/__init__.py +5 -0
- zoo_framework/event/event_channel.py +70 -0
- zoo_framework/event/event_channel_manager.py +112 -0
- zoo_framework/event/event_channel_register.py +49 -0
- zoo_framework/event/event_provider.py +28 -0
- zoo_framework/event/event_register.py +87 -0
- zoo_framework/fifo/__init__.py +6 -0
- zoo_framework/fifo/base_fifo.py +32 -0
- zoo_framework/fifo/delay_fifo.py +36 -0
- zoo_framework/fifo/event_fifo.py +43 -0
- zoo_framework/fifo/node/__init__.py +4 -0
- zoo_framework/fifo/node/delay_fifo_node.py +16 -0
- zoo_framework/fifo/node/event_fifo_node.py +264 -0
- zoo_framework/fifo/single_fifo.py +32 -0
- zoo_framework/lock/__init__.py +3 -0
- zoo_framework/lock/base_lock.py +5 -0
- zoo_framework/lock/count_lock.py +30 -0
- zoo_framework/lock/time_lock.py +55 -0
- zoo_framework/params/__init__.py +6 -0
- zoo_framework/params/event_params.py +8 -0
- zoo_framework/params/log_params.py +10 -0
- zoo_framework/params/state_machine_params.py +7 -0
- zoo_framework/params/worker_params.py +12 -0
- zoo_framework/plugin/__init__.py +417 -0
- zoo_framework/reactor/__init__.py +5 -0
- zoo_framework/reactor/event_priorities.py +23 -0
- zoo_framework/reactor/event_reactor.py +126 -0
- zoo_framework/reactor/event_reactor_manager.py +187 -0
- zoo_framework/reactor/event_reactor_req.py +179 -0
- zoo_framework/reactor/event_retry_strategy.py +15 -0
- zoo_framework/reactor/waiter_result_reactor.py +10 -0
- zoo_framework/statemachine/__init__.py +3 -0
- zoo_framework/statemachine/base_state_machine.py +11 -0
- zoo_framework/statemachine/state_effect.py +50 -0
- zoo_framework/statemachine/state_effect_scheduler.py +59 -0
- zoo_framework/statemachine/state_index_factory.py +244 -0
- zoo_framework/statemachine/state_machine_manager.py +116 -0
- zoo_framework/statemachine/state_node.py +147 -0
- zoo_framework/statemachine/state_node_index.py +6 -0
- zoo_framework/statemachine/state_node_index_factory.py +9 -0
- zoo_framework/statemachine/state_node_type.py +29 -0
- zoo_framework/statemachine/state_scope.py +271 -0
- zoo_framework/templates/__init__.py +40 -0
- zoo_framework/templates/main.pyt +10 -0
- zoo_framework/templates/thread.pyt +21 -0
- zoo_framework/utils/__init__.py +7 -0
- zoo_framework/utils/cmd_utils.py +20 -0
- zoo_framework/utils/datetime_utils.py +65 -0
- zoo_framework/utils/file_utils.py +66 -0
- zoo_framework/utils/log_utils.py +35 -0
- zoo_framework/utils/structured_log.py +235 -0
- zoo_framework/utils/thread_safe_dict.py +64 -0
- zoo_framework/utils/ws_utils.py +33 -0
- zoo_framework/workers/__init__.py +41 -0
- zoo_framework/workers/async_worker.py +299 -0
- zoo_framework/workers/base_worker.py +68 -0
- zoo_framework/workers/event_worker.py +57 -0
- zoo_framework/workers/state_machine_work.py +249 -0
- zoo_framework/workers/worker_props.py +5 -0
- zoo_framework/workers/worker_register.py +26 -0
- zoo_framework/workers/worker_result.py +5 -0
- zoo_framework-0.5.4b0.dist-info/METADATA +339 -0
- zoo_framework-0.5.4b0.dist-info/RECORD +96 -0
- zoo_framework-0.5.4b0.dist-info/WHEEL +4 -0
- zoo_framework-0.5.4b0.dist-info/entry_points.txt +3 -0
- zoo_framework-0.5.4b0.dist-info/licenses/LICENSE +201 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"""Zoo Framework - A simple and quick multi-threaded Python framework with zoo metaphor.
|
|
2
|
+
|
|
3
|
+
🎪 动物园框架 - 基于动物园隐喻的 Python 多线程框架
|
|
4
|
+
|
|
5
|
+
核心概念:
|
|
6
|
+
- 🦁 Worker: 动物,执行任务的基本单元
|
|
7
|
+
- 🏠 Cage: 笼子,提供线程安全和生命周期管理
|
|
8
|
+
- 👨🌾 Master: 园长,管理整个动物园
|
|
9
|
+
- 🍎 Event: 食物,Worker 间通信的载体
|
|
10
|
+
- 🥘 FIFO: 饲养员队列,管理事件的有序处理
|
|
11
|
+
|
|
12
|
+
示例:
|
|
13
|
+
>>> from zoo_framework.core import Master
|
|
14
|
+
>>> from zoo_framework.workers import BaseWorker
|
|
15
|
+
>>>
|
|
16
|
+
>>> class MyWorker(BaseWorker):
|
|
17
|
+
... def _execute(self):
|
|
18
|
+
... print("Hello from MyWorker!")
|
|
19
|
+
>>>
|
|
20
|
+
>>> master = Master()
|
|
21
|
+
>>> master.run()
|
|
22
|
+
|
|
23
|
+
版本: 0.1.0
|
|
24
|
+
作者: XiangMeng
|
|
25
|
+
许可证: Apache-2.0
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
__version__ = "0.1.1-beta"
|
|
29
|
+
__author__ = "XiangMeng"
|
|
30
|
+
__email__ = "mengxiang931015@live.com"
|
|
31
|
+
__license__ = "Apache-2.0"
|
|
32
|
+
|
|
33
|
+
from dotenv import find_dotenv, load_dotenv
|
|
34
|
+
|
|
35
|
+
# Replace wildcard imports with explicit package submodule imports to reduce linter noise
|
|
36
|
+
# and avoid importing many symbols at package import time.
|
|
37
|
+
from . import (
|
|
38
|
+
conf,
|
|
39
|
+
core,
|
|
40
|
+
fifo,
|
|
41
|
+
params,
|
|
42
|
+
reactor,
|
|
43
|
+
statemachine,
|
|
44
|
+
utils,
|
|
45
|
+
workers,
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
__all__ = [
|
|
49
|
+
"__version__",
|
|
50
|
+
"conf",
|
|
51
|
+
"core",
|
|
52
|
+
"fifo",
|
|
53
|
+
"params",
|
|
54
|
+
"reactor",
|
|
55
|
+
"statemachine",
|
|
56
|
+
"utils",
|
|
57
|
+
"workers",
|
|
58
|
+
]
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def load_env() -> None:
|
|
62
|
+
"""显式加载工程根目录下的 .env 文件(不在包导入时自动运行)。
|
|
63
|
+
|
|
64
|
+
调用示例:
|
|
65
|
+
from zoo_framework import load_env
|
|
66
|
+
load_env()
|
|
67
|
+
"""
|
|
68
|
+
load_dotenv(find_dotenv())
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
# NOTE: 原先代码在模块导入时会立即运行 `load_dotenv(find_dotenv())`,
|
|
72
|
+
# 为了降低导入时的副作用(并减少 linter 噪声),已改为显式函数调用。
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
import click
|
|
6
|
+
from jinja2 import Template
|
|
7
|
+
|
|
8
|
+
from zoo_framework.templates import main_template, worker_mod_insert_template, worker_template
|
|
9
|
+
|
|
10
|
+
DEFAULT_CONF = {
|
|
11
|
+
"_exports": [],
|
|
12
|
+
"log": {"path": "./logs", "level": "debug"},
|
|
13
|
+
"worker": {"runPolicy": "simple", "pool": {"size": 5, "enabled": False}},
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def create_func(object_name):
|
|
18
|
+
if os.path.exists(object_name):
|
|
19
|
+
return
|
|
20
|
+
|
|
21
|
+
os.mkdir(object_name)
|
|
22
|
+
src_dir = object_name + "/src"
|
|
23
|
+
conf_dir = src_dir + "/conf"
|
|
24
|
+
params_dir = src_dir + "/params"
|
|
25
|
+
main_file = src_dir + "/main.py"
|
|
26
|
+
events_dir = src_dir + "/events"
|
|
27
|
+
workers_dir = src_dir + "/workers"
|
|
28
|
+
config_file = object_name + "/config.json"
|
|
29
|
+
|
|
30
|
+
threads_init_file = workers_dir + "/__init__.py"
|
|
31
|
+
config_init_file = conf_dir + "/__init__.py"
|
|
32
|
+
events_init_file = events_dir + "/__init__.py"
|
|
33
|
+
params_init_file = params_dir + "/__init__.py"
|
|
34
|
+
|
|
35
|
+
os.mkdir(src_dir)
|
|
36
|
+
os.mkdir(conf_dir)
|
|
37
|
+
os.mkdir(workers_dir)
|
|
38
|
+
os.mkdir(params_dir)
|
|
39
|
+
os.mkdir(events_dir)
|
|
40
|
+
# os.mkdir(events_dir)
|
|
41
|
+
with open(config_file, "w") as fp:
|
|
42
|
+
json.dump(DEFAULT_CONF, fp)
|
|
43
|
+
|
|
44
|
+
with open(main_file, "w") as fp:
|
|
45
|
+
fp.write(main_template)
|
|
46
|
+
|
|
47
|
+
with open(threads_init_file, "w") as fp:
|
|
48
|
+
fp.write("")
|
|
49
|
+
|
|
50
|
+
with open(config_init_file, "w") as fp:
|
|
51
|
+
fp.write("")
|
|
52
|
+
|
|
53
|
+
with open(events_init_file, "w") as fp:
|
|
54
|
+
fp.write("")
|
|
55
|
+
|
|
56
|
+
with open(params_init_file, "w") as fp:
|
|
57
|
+
fp.write("")
|
|
58
|
+
|
|
59
|
+
# create main.py
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def worker_func(worker_name):
|
|
63
|
+
# 创建文件夹
|
|
64
|
+
src_dir = "./workers"
|
|
65
|
+
if sys.argv[0].endswith("/src"):
|
|
66
|
+
src_dir = "./src/workers"
|
|
67
|
+
file_path = src_dir + "/" + worker_name + "_worker.py"
|
|
68
|
+
workers_init_file = src_dir + "/__init__.py"
|
|
69
|
+
template = Template(worker_mod_insert_template)
|
|
70
|
+
content = template.render(worker_name=worker_name)
|
|
71
|
+
|
|
72
|
+
if not os.path.exists(src_dir):
|
|
73
|
+
os.mkdir(src_dir)
|
|
74
|
+
with open(workers_init_file, "w") as fp:
|
|
75
|
+
fp.write(content)
|
|
76
|
+
elif os.path.exists(workers_init_file):
|
|
77
|
+
with open(workers_init_file, "a") as fp:
|
|
78
|
+
fp.write(content)
|
|
79
|
+
|
|
80
|
+
template = Template(worker_template)
|
|
81
|
+
content = template.render(worker_name=worker_name) # 渲染
|
|
82
|
+
with open(file_path, "w") as fp:
|
|
83
|
+
fp.write(content)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
@click.command()
|
|
87
|
+
@click.option("--create", help="Input target object name and create it")
|
|
88
|
+
@click.option("--worker", help="Input new worker name and create it")
|
|
89
|
+
@click.option("--config", help="Input new config file name and create it")
|
|
90
|
+
def zfc(create, worker, config):
|
|
91
|
+
if create is not None:
|
|
92
|
+
create_func(create)
|
|
93
|
+
|
|
94
|
+
if worker is not None:
|
|
95
|
+
worker_func(worker.lower())
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
if __name__ == "__main__":
|
|
99
|
+
zfc()
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import os
|
|
3
|
+
|
|
4
|
+
from zoo_framework.core.aop import configure
|
|
5
|
+
from zoo_framework.params import LogParams
|
|
6
|
+
from zoo_framework.utils import DateTimeUtils, FileUtils
|
|
7
|
+
|
|
8
|
+
level_relations = {
|
|
9
|
+
"debug": logging.DEBUG,
|
|
10
|
+
"info": logging.INFO,
|
|
11
|
+
"warning": logging.WARNING,
|
|
12
|
+
"error": logging.ERROR,
|
|
13
|
+
"crit": logging.CRITICAL,
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
log_colors_config = {
|
|
17
|
+
# 终端输出日志颜色配置
|
|
18
|
+
"debug": "white",
|
|
19
|
+
"info": "cyan",
|
|
20
|
+
"warning": "yellow",
|
|
21
|
+
"error": "red",
|
|
22
|
+
"crit": "bold_red",
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@configure(topic="log_config")
|
|
27
|
+
def log_config(level: str = "info"):
|
|
28
|
+
logger = logging.getLogger()
|
|
29
|
+
log_config_instance(logger, level)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def log_config_instance(logger, level: str = "info"):
|
|
33
|
+
if level_relations.get(LogParams.LOG_LEVEL) is None:
|
|
34
|
+
raise Exception(
|
|
35
|
+
"Config params \"log.level\" only support to 'debug','info','warning','error','crit'"
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
logger.setLevel(level_relations[LogParams.LOG_LEVEL])
|
|
39
|
+
|
|
40
|
+
formatter = logging.Formatter(LogParams.LOG_BASIC_FORMAT, LogParams.LOG_DATE_FORMAT)
|
|
41
|
+
|
|
42
|
+
choler = logging.StreamHandler() # 输出到控制台的handler
|
|
43
|
+
choler.setFormatter(formatter)
|
|
44
|
+
choler.setLevel(logging.INFO) # 也可以不设置,不设置就默认用logger的level
|
|
45
|
+
|
|
46
|
+
log_dir_path = os.path.join(LogParams.LOG_BASE_PATH, DateTimeUtils.get_format_now("%Y-%m-%d"))
|
|
47
|
+
|
|
48
|
+
FileUtils.dir_exists_and_create(log_dir_path)
|
|
49
|
+
|
|
50
|
+
log_path = "{}/{}.log".format(log_dir_path, DateTimeUtils.get_format_now("%Y-%m-%d"))
|
|
51
|
+
filer = logging.FileHandler(log_path) # 输出到文件的handler
|
|
52
|
+
filer.setFormatter(formatter)
|
|
53
|
+
logger.addHandler(choler)
|
|
54
|
+
logger.addHandler(filer)
|
|
55
|
+
return logger
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
class WorkerConstant:
|
|
2
|
+
# worker 运行模式
|
|
3
|
+
RUN_MODE_THREAD = "thread"
|
|
4
|
+
RUN_MODE_PROCESS = "process"
|
|
5
|
+
RUN_MODE_COROUTINE = "coroutine"
|
|
6
|
+
# worker 运行模式(缩写)
|
|
7
|
+
RUN_MODE_THREAD_ABBREVIATE = "T"
|
|
8
|
+
RUN_MODE_PROCESS_ABBREVIATE = "P"
|
|
9
|
+
RUN_MODE_COROUTINE_ABBREVIATE = "C"
|
|
10
|
+
|
|
11
|
+
# 运行策略
|
|
12
|
+
RUN_POLICY_SAFE = "safe"
|
|
13
|
+
RUN_POLICY_SIMPLE = "simple"
|
|
14
|
+
RUN_POLICY_STABLE = "stable"
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
from zoo_framework.core.aop import cage, event, worker, worker_register
|
|
2
|
+
from zoo_framework.core.master import Master
|
|
3
|
+
from zoo_framework.core.params_factory import ParamsFactory
|
|
4
|
+
from zoo_framework.core.params_path import ParamsPath
|
|
5
|
+
|
|
6
|
+
__all__ = ["Master", "ParamsFactory", "ParamsPath", "cage", "event", "worker", "worker_register"]
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from .cage import cage
|
|
2
|
+
from .configure import config_funcs, configure
|
|
3
|
+
from .event import event
|
|
4
|
+
from .logger import logger
|
|
5
|
+
from .params import params
|
|
6
|
+
from .stopwatch import stopwatch
|
|
7
|
+
from .validation import validation
|
|
8
|
+
from .worker import worker, worker_register
|
|
9
|
+
|
|
10
|
+
__all__ = [
|
|
11
|
+
"cage",
|
|
12
|
+
"config_funcs",
|
|
13
|
+
"configure",
|
|
14
|
+
"event",
|
|
15
|
+
"logger",
|
|
16
|
+
"params",
|
|
17
|
+
"stopwatch",
|
|
18
|
+
"validation",
|
|
19
|
+
"worker",
|
|
20
|
+
"worker_register",
|
|
21
|
+
]
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from zoo_framework.utils.thread_safe_dict import ThreadSafeDict
|
|
2
|
+
|
|
3
|
+
# 单例对象注册器
|
|
4
|
+
cage_register_map = ThreadSafeDict()
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def cage(cls):
|
|
8
|
+
def _cage():
|
|
9
|
+
"""用于单例模式的装饰器."""
|
|
10
|
+
if cage_register_map.get(cls.__name__) is None:
|
|
11
|
+
cage_register_map[cls.__name__] = cls()
|
|
12
|
+
return cage_register_map[cls.__name__]
|
|
13
|
+
|
|
14
|
+
return _cage
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from zoo_framework.utils.thread_safe_dict import ThreadSafeDict
|
|
2
|
+
|
|
3
|
+
# 创建一个线程安全的字典,用于存储配置函数
|
|
4
|
+
config_funcs = ThreadSafeDict()
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def configure(topic: str):
|
|
8
|
+
"""装饰器工厂函数,用于将函数注册到指定的主题下。
|
|
9
|
+
|
|
10
|
+
参数:
|
|
11
|
+
topic (str): 主题名称,用于标识配置函数的分类或用途。
|
|
12
|
+
|
|
13
|
+
返回:
|
|
14
|
+
function: 返回一个装饰器函数,该装饰器将传入的函数注册到 config_funcs 字典中。
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
def inner(func):
|
|
18
|
+
# 将传入的函数以主题为键存储到线程安全字典中
|
|
19
|
+
config_funcs[topic] = func
|
|
20
|
+
return func
|
|
21
|
+
|
|
22
|
+
return inner
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import time
|
|
2
|
+
|
|
3
|
+
from zoo_framework.event.event_channel_manager import EventChannelManager
|
|
4
|
+
from zoo_framework.reactor import EventReactor
|
|
5
|
+
from zoo_framework.reactor.event_retry_strategy import EventRetryStrategy
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
# 自定义事件装饰器,用于注册事件
|
|
9
|
+
# 参数说明:
|
|
10
|
+
# topic: 事件的主题,用于标识事件类型
|
|
11
|
+
# channel: 事件通道名称,默认为"default"
|
|
12
|
+
# timeout: 事件超时时间,默认为当前时间加1000秒
|
|
13
|
+
# retry_time: 重试次数,默认为1次
|
|
14
|
+
# retry_strategy: 重试策略,默认为RetryOnce(仅重试一次)
|
|
15
|
+
# done_callback: 事件完成后的回调函数,默认为None
|
|
16
|
+
# error_callback: 事件出错时的回调函数,默认为None
|
|
17
|
+
# success_callback: 事件成功时的回调函数,默认为None
|
|
18
|
+
# 返回值:返回一个装饰器函数,用于包装目标函数
|
|
19
|
+
def event(
|
|
20
|
+
topic: str,
|
|
21
|
+
channel: str = "default",
|
|
22
|
+
timeout: int = time.time() + 1000,
|
|
23
|
+
retry_time: int = 1,
|
|
24
|
+
retry_strategy=EventRetryStrategy.RetryOnce,
|
|
25
|
+
done_callback=None,
|
|
26
|
+
error_callback=None,
|
|
27
|
+
success_callback=None,
|
|
28
|
+
):
|
|
29
|
+
# 内部装饰器函数,接收被装饰的目标函数
|
|
30
|
+
def _event(func: callable):
|
|
31
|
+
# 创建一个事件反应器实例,并设置相关属性
|
|
32
|
+
reactor = EventReactor(func.__name__)
|
|
33
|
+
reactor.set_event_callback(func) # 设置事件回调函数为目标函数
|
|
34
|
+
reactor.set_event_timeout(timeout) # 设置事件超时时间
|
|
35
|
+
reactor.set_retry_strategy(retry_strategy, retry_time) # 设置重试策略和重试次数
|
|
36
|
+
reactor.set_error_callback(error_callback) # 设置错误回调函数
|
|
37
|
+
reactor.set_success_callback(success_callback) # 设置成功回调函数
|
|
38
|
+
reactor.set_done_callback(done_callback) # 设置完成回调函数
|
|
39
|
+
|
|
40
|
+
# 检查并刷新事件通道,将当前反应器与指定主题和通道关联
|
|
41
|
+
EventChannelManager().refresh_channel(channel, topic, reactor)
|
|
42
|
+
return func # 返回原始函数,保持装饰器透明性
|
|
43
|
+
|
|
44
|
+
return _event # 返回内部装饰器函数
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
from zoo_framework.utils import LogUtils
|
|
4
|
+
|
|
5
|
+
log_utils = LogUtils()
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def logger(cls):
|
|
9
|
+
"""为类添加日志记录功能的装饰器。
|
|
10
|
+
|
|
11
|
+
该装饰器会为传入的类创建一个日志记录器,并将其赋值给类的 `_logger` 属性。
|
|
12
|
+
|
|
13
|
+
参数:
|
|
14
|
+
cls (class): 需要添加日志功能的类。
|
|
15
|
+
|
|
16
|
+
返回:
|
|
17
|
+
class: 添加了日志功能的类。
|
|
18
|
+
"""
|
|
19
|
+
from zoo_framework.conf.log_config import log_config_instance
|
|
20
|
+
|
|
21
|
+
# 创建类的日志记录器
|
|
22
|
+
_logger = logging.getLogger(cls.__name__)
|
|
23
|
+
|
|
24
|
+
_logger = log_config_instance(_logger)
|
|
25
|
+
|
|
26
|
+
# 将日志记录器赋值给类的 _logger 属性
|
|
27
|
+
cls._logger = _logger
|
|
28
|
+
|
|
29
|
+
# 定义装饰器函数,用于添加日志记录功能
|
|
30
|
+
def decorator(func):
|
|
31
|
+
"""为函数添加日志记录功能的装饰器。
|
|
32
|
+
|
|
33
|
+
在函数调用前后分别记录调试日志,包括函数名和返回值。
|
|
34
|
+
|
|
35
|
+
参数:
|
|
36
|
+
func (function): 需要添加日志功能的函数。
|
|
37
|
+
|
|
38
|
+
返回:
|
|
39
|
+
function: 添加了日志功能的函数。
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
def wrapper(*args, **kwargs):
|
|
43
|
+
# 记录方法调用前的日志
|
|
44
|
+
cls._logger.debug(f"Calling {func.__name__}")
|
|
45
|
+
|
|
46
|
+
# 执行原始方法
|
|
47
|
+
result = func(*args, **kwargs)
|
|
48
|
+
|
|
49
|
+
# 记录方法调用后的日志
|
|
50
|
+
cls._logger.debug(f"{func.__name__} returned: {result}")
|
|
51
|
+
|
|
52
|
+
return result
|
|
53
|
+
|
|
54
|
+
return wrapper
|
|
55
|
+
|
|
56
|
+
# 遍历类中的方法,并应用装饰器
|
|
57
|
+
for name, method in cls.__dict__.items():
|
|
58
|
+
if callable(method):
|
|
59
|
+
setattr(cls, name, decorator(method))
|
|
60
|
+
|
|
61
|
+
return cls
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from ..params_factory import ParamsFactory
|
|
2
|
+
from ..params_path import ParamsPath
|
|
3
|
+
|
|
4
|
+
config_params = {}
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def params(cls):
|
|
8
|
+
def inner():
|
|
9
|
+
if config_params.get(cls.__name__) is not None:
|
|
10
|
+
return config_params[cls.__name__]
|
|
11
|
+
params_list = dir(cls)
|
|
12
|
+
for param in params_list:
|
|
13
|
+
params_path = getattr(cls, param)
|
|
14
|
+
if not isinstance(params_path, ParamsPath):
|
|
15
|
+
continue
|
|
16
|
+
param_value = params_path.get_value()
|
|
17
|
+
default_value = params_path.get_default()
|
|
18
|
+
value = ParamsFactory().get_params(param_value, default_value=default_value)
|
|
19
|
+
setattr(cls, param, value)
|
|
20
|
+
config_params[cls.__name__] = cls
|
|
21
|
+
return cls
|
|
22
|
+
|
|
23
|
+
return inner()
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
def stopwatch(func):
|
|
2
|
+
"""Decorator for measuring time of function execution.
|
|
3
|
+
:param func: function to be measured
|
|
4
|
+
:return: function result.
|
|
5
|
+
"""
|
|
6
|
+
from functools import wraps
|
|
7
|
+
from time import time
|
|
8
|
+
|
|
9
|
+
@wraps(func)
|
|
10
|
+
def wrapper(*args, **kwargs):
|
|
11
|
+
start = time()
|
|
12
|
+
result = func(*args, **kwargs)
|
|
13
|
+
print(f"Function {func.__name__} took {time() - start} seconds")
|
|
14
|
+
return result
|
|
15
|
+
|
|
16
|
+
return wrapper
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# 全局字典,用于存储参数验证规则
|
|
2
|
+
params_validate_map = {}
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def validation(params_key="") -> object:
|
|
6
|
+
"""返回一个装饰器函数,用于将参数插入到指定键的验证列表中。
|
|
7
|
+
|
|
8
|
+
参数:
|
|
9
|
+
params_key (str): 用于标识参数验证规则的键,默认为空字符串。
|
|
10
|
+
|
|
11
|
+
返回:
|
|
12
|
+
function: 内部函数,接受一个参数并将其插入到对应键的验证列表中。
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
def inner(params):
|
|
16
|
+
# 如果指定键在验证映射中不存在,则初始化为空列表
|
|
17
|
+
if params_validate_map.get(params_key) is None:
|
|
18
|
+
params_validate_map[params_key] = []
|
|
19
|
+
|
|
20
|
+
# 将参数插入到对应键的验证列表中
|
|
21
|
+
params_validate_map[params_key].append(params)
|
|
22
|
+
return params
|
|
23
|
+
|
|
24
|
+
return inner
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def validation_params(params_key, value):
|
|
28
|
+
"""验证给定值是否存在于指定键的验证列表中。
|
|
29
|
+
|
|
30
|
+
参数:
|
|
31
|
+
params_key (str): 用于查找验证列表的键。
|
|
32
|
+
value (any): 需要验证的值。
|
|
33
|
+
|
|
34
|
+
返回:
|
|
35
|
+
bool or None:
|
|
36
|
+
- 如果值存在于验证列表中,返回True;
|
|
37
|
+
- 如果验证列表不存在或类型不正确,返回False;
|
|
38
|
+
- 如果值不在验证列表中,返回None。
|
|
39
|
+
"""
|
|
40
|
+
# 获取指定键对应的验证列表
|
|
41
|
+
valid_values = params_validate_map.get(params_key)
|
|
42
|
+
|
|
43
|
+
# 如果验证列表不存在,直接返回False
|
|
44
|
+
if valid_values is None:
|
|
45
|
+
return False
|
|
46
|
+
|
|
47
|
+
# 如果验证列表不是列表类型,返回False
|
|
48
|
+
if not isinstance(valid_values, list):
|
|
49
|
+
return False
|
|
50
|
+
|
|
51
|
+
# 检查值是否在验证列表中
|
|
52
|
+
if value in valid_values:
|
|
53
|
+
return True
|
|
54
|
+
return None
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# TODO: 使用 register 的方式来注册 worker
|
|
2
|
+
from zoo_framework.workers import WorkerRegister
|
|
3
|
+
|
|
4
|
+
worker_register: WorkerRegister = WorkerRegister()
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def worker(count: int = 1):
|
|
8
|
+
"""装饰器函数,用于注册指定数量的 worker 实例。
|
|
9
|
+
|
|
10
|
+
参数:
|
|
11
|
+
count (int): 需要注册的 worker 实例数量,默认为 1。
|
|
12
|
+
|
|
13
|
+
返回:
|
|
14
|
+
function: 返回一个内部装饰器函数,用于处理被装饰的类。
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
def inner(cls):
|
|
18
|
+
"""内部装饰器函数,负责实际的 worker 注册逻辑。
|
|
19
|
+
|
|
20
|
+
参数:
|
|
21
|
+
cls (class): 被装饰的类,表示 worker 的类型。
|
|
22
|
+
|
|
23
|
+
返回:
|
|
24
|
+
class: 返回原始类,保持装饰器的透明性。
|
|
25
|
+
"""
|
|
26
|
+
# 如果只需要注册一个实例,则直接注册该类的实例
|
|
27
|
+
if count == 1:
|
|
28
|
+
worker_register.register(cls.__name__, cls())
|
|
29
|
+
return cls
|
|
30
|
+
|
|
31
|
+
# 如果需要注册多个实例,则为每个实例分配编号并分别注册
|
|
32
|
+
for i in range(1, count + 1):
|
|
33
|
+
instance = cls()
|
|
34
|
+
instance.num = i
|
|
35
|
+
worker_register.register(f"{cls.__name__}_{i}", instance)
|
|
36
|
+
return cls
|
|
37
|
+
|
|
38
|
+
return inner
|