fasttask-manager 0.2.1__py2.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.
@@ -0,0 +1 @@
1
+ from .manager import Manager
@@ -0,0 +1,40 @@
1
+ import os
2
+ import shutil
3
+
4
+
5
+ def get_int_input_or_default(name, default):
6
+ input_str = input(f"{name} (default:{default}):")
7
+ return int(input_str) if input_str else default
8
+
9
+
10
+ def read_file(file):
11
+ with open(file, encoding="utf-8") as f:
12
+ return f.read()
13
+
14
+
15
+ def write_file(content, file):
16
+ with open(file, "w", encoding="utf-8") as f:
17
+ f.write(content)
18
+
19
+
20
+ def replace_file_content(file, replace_dict):
21
+ content = read_file(file)
22
+ for k, v in replace_dict.items():
23
+ content = content.replace("{" + k + "}", str(v))
24
+ write_file(content, file)
25
+
26
+
27
+ def create_project():
28
+ project_name = input("project name:")
29
+ port = get_int_input_or_default("port", 80)
30
+ fasttask_path = os.path.abspath(os.path.dirname(__file__))
31
+
32
+ shutil.copytree(os.path.join(fasttask_path, "project"), f"{project_name}")
33
+
34
+ replace_dict = {"project_name": project_name, "port": port}
35
+
36
+ replace_file_content(f"{project_name}/docker-compose.yml", replace_dict)
37
+
38
+
39
+ if __name__ == "__main__":
40
+ create_project()
@@ -0,0 +1,88 @@
1
+ import time
2
+ import requests
3
+ from retry import retry
4
+ from logging import Logger, StreamHandler
5
+ from requests.auth import HTTPBasicAuth
6
+
7
+
8
+ class Manager:
9
+ def __init__(self, host: str, task_name: str, protocol: str = "http", port: int = 80, check_gap: int = 15,
10
+ tries: int = 5, delay: int = 3, logger: Logger = None, log_prefix: str = "",
11
+ auth_user: str = "", auth_passwd: str = "", url_base_path: str = "", req_timeout=30) -> None:
12
+
13
+ self.task_name = task_name
14
+ self.protocol = protocol
15
+ self.host = host
16
+ self.port = port
17
+ self.url = f"{self.protocol}://{self.host}:{self.port}{url_base_path}"
18
+ self.tries = tries
19
+ self.delay = delay
20
+ self.check_gap = check_gap
21
+ self.logger = logger
22
+ self.log_prefix = f"{log_prefix}{self.task_name}:"
23
+ self.auth = HTTPBasicAuth(auth_user, auth_passwd)
24
+ self.req_timeout = req_timeout
25
+ if self.logger:
26
+ return
27
+
28
+ self.logger = Logger(task_name)
29
+ self.logger.addHandler(StreamHandler())
30
+
31
+ def _req(self, path, data: dict = None, method="p", file: str = None, raw_resp: bool = False):
32
+ @retry(tries=self.tries, delay=self.delay)
33
+ def req():
34
+ params = {
35
+ "url": f"{self.url}{path}",
36
+ "auth": self.auth,
37
+ "files": None if not file else {
38
+ 'file': open(file, 'rb')
39
+ },
40
+ "timeout": self.req_timeout,
41
+ }
42
+ if method == "p":
43
+ r = requests.post(json=data, **params)
44
+ elif method == "g":
45
+ r = requests.get(params=data, **params)
46
+
47
+ r.raise_for_status()
48
+ return r if raw_resp else r.json()
49
+ return req()
50
+
51
+ def run(self, params: dict) -> dict:
52
+ return self._req(path=f"/run/{self.task_name}", data=params)
53
+
54
+ def create_task(self, params: dict) -> dict:
55
+ self.logger.info(f"{self.log_prefix}: task creating...")
56
+ return self._req(path=f"/create/{self.task_name}", data=params)
57
+
58
+ def check(self, result_id: str) -> dict:
59
+ resp = self._req(path=f"/check/{self.task_name}", data={"result_id": result_id}, method="g")
60
+ self.logger.info(f"{self.log_prefix}: check task: {resp['state']}")
61
+ return resp
62
+
63
+ def upload(self, file_path) -> str:
64
+ return self._req("/upload", method="p", file=file_path)["file_name"]
65
+
66
+ def download(self, file_name, local_path):
67
+ r = self._req("/download", data={"file_name": file_name}, method="g", raw_resp=True)
68
+ with open(local_path, "wb") as f:
69
+ for chunk in r.iter_content(chunk_size=512):
70
+ f.write(chunk)
71
+
72
+ def create_and_wait_result(self, params: dict) -> dict:
73
+ start = time.time()
74
+ resp = self.create_task(params)
75
+
76
+ self.logger.info(f"{self.log_prefix} cost: {time.time() - start} create_task resp: {resp}")
77
+
78
+ while True:
79
+ resp = self.check(result_id=resp["id"])
80
+ if resp["state"] == "FAILURE":
81
+ self.logger.info(f"{self.log_prefix} cost: {time.time()-start}")
82
+ raise Exception(f"task :{resp['result']}")
83
+
84
+ elif resp["state"] == "SUCCESS":
85
+ self.logger.info(f"{self.log_prefix} cost: {time.time()-start}")
86
+ return resp["result"]
87
+
88
+ time.sleep(self.check_gap)
@@ -0,0 +1,12 @@
1
+ FROM irid/fasttask
2
+
3
+ # set up your docker env here if necessary
4
+ # ---
5
+
6
+ # ---
7
+ WORKDIR /fasttask
8
+ COPY req.txt req.txt
9
+ RUN pip install -r req.txt
10
+ COPY setting.py setting.py
11
+ RUN rm -rf tasks
12
+ COPY tasks tasks
@@ -0,0 +1,32 @@
1
+ version: "3.9"
2
+
3
+ services:
4
+ {project_name}:
5
+ image: {project_name}
6
+ restart: always
7
+ command: sh run.sh
8
+
9
+ container_name: {project_name}
10
+
11
+ ports:
12
+ # 在single_node 与 distributed_master 需要映射api端口
13
+ - "{port}:80"
14
+ # 在distributed_master需要映射任务队列端口
15
+ # - "9000:6379"
16
+
17
+ volumes:
18
+ - ./files:/fasttask/files
19
+
20
+ environment:
21
+ # single_node: 单一节点提供接口+执行任务
22
+ - node_type=single_node
23
+
24
+ # # distributed_master: 分布式部署部署的主节点 提供api与任务队列后端
25
+ # - node_type=distributed_master
26
+ # - task_queue_passwd=passwd
27
+
28
+ # # distributed_worker: 分布式部署部署的从节点 负责cerery任务执行环境,需要配置distributed_master的主机地址, 任务队列端口与密码
29
+ # - node_type=distributed_worker
30
+ # - master_host=0.0.0.0
31
+ # - task_queue_port=9000
32
+ # - task_queue_passwd=passwd
File without changes
@@ -0,0 +1,21 @@
1
+ # fasttask setting
2
+ project_title = "⚡{project_name}⚡"
3
+ project_summary = "{project_name} Project"
4
+ project_description = "this is a fasttask project!"
5
+ project_version = "ver: 🐕"
6
+
7
+ api_docs = True
8
+ api_redoc = True
9
+
10
+ file_download = True
11
+ file_upload = True
12
+ user_to_passwd = {
13
+ "john wick": "john_passwd"
14
+ }
15
+
16
+
17
+ # celery setting use namespeace "celery"
18
+ # ref: https://docs.celeryq.dev/en/stable/userguide/configuration.html
19
+ # celery_result_expires = 3600
20
+ # celery_worker_pool = "prefork"
21
+ # celery_worker_concurrency = 4
@@ -0,0 +1,25 @@
1
+ from celery_app import app
2
+ from pydantic import BaseModel
3
+
4
+ from tasks.packages.tools import sleep_random
5
+ from typing import Union
6
+ from math import pi
7
+
8
+
9
+ class Params(BaseModel):
10
+ r: Union[float, int]
11
+
12
+
13
+ class Result(BaseModel):
14
+ area: Union[float, int]
15
+
16
+
17
+ @app.task
18
+ def get_circle_area(r):
19
+ if r <= 0:
20
+ raise ValueError("r must > 0")
21
+ print("running...")
22
+ sleep_random()
23
+ result = Result(area=pi * r**2)
24
+
25
+ return result.model_dump()
@@ -0,0 +1,28 @@
1
+ from typing import Union
2
+ from pydantic import BaseModel
3
+
4
+ from packages.tools import xx, sleep_random
5
+
6
+
7
+ class Params(BaseModel):
8
+ a: Union[float, int]
9
+ b: Union[float, int]
10
+
11
+
12
+ class Result(BaseModel):
13
+ hypotenuse: Union[float, int]
14
+
15
+
16
+ def get_hypotenuse(a, b):
17
+ if a <= 0 or b <= 0:
18
+ raise ValueError("side length must > 0")
19
+ print("running...")
20
+ sleep_random()
21
+ result = Result(hypotenuse=(xx(a) + xx(b))**0.5)
22
+ return result.model_dump()
23
+
24
+
25
+ if __name__ == '__main__':
26
+ with open("files/a.txt", "w") as f:
27
+ f.write("a")
28
+ print(get_hypotenuse(3, 4))
File without changes
@@ -0,0 +1,10 @@
1
+ import time
2
+ from random import random
3
+
4
+
5
+ def xx(x):
6
+ return x**2
7
+
8
+
9
+ def sleep_random():
10
+ time.sleep(random() * 10)
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) [year] [fullname]
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,53 @@
1
+ Metadata-Version: 2.1
2
+ Name: fasttask_manager
3
+ Version: 0.2.1
4
+ Summary: fasttask's manager
5
+ Home-page: https://github.com/iridesc/fasttask_manager
6
+ Author: Irid
7
+ Author-email: irid.zzy@gmail.com
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Operating System :: OS Independent
11
+ Description-Content-Type: text/markdown
12
+ License-File: LICENSE
13
+ Requires-Dist: retry
14
+ Requires-Dist: requests
15
+
16
+ manager for [fasttask](https://github.com/iridesc/fasttask)
17
+
18
+ ### create project
19
+
20
+ ```bash
21
+ python -m fasttask_manager.create_project
22
+ ```
23
+
24
+
25
+ ### create a Manager
26
+
27
+ ```python
28
+ m = Manager("127.0.0.1", task_name="get_hypotenuse", port=8080)
29
+ ```
30
+
31
+
32
+ ### run a task
33
+
34
+ ```python
35
+ result = m.run(params)
36
+ ```
37
+
38
+
39
+ ### create a task and check result later
40
+
41
+ ```python
42
+ result_id = m.create_task(params)
43
+ # do something...
44
+ # do something...
45
+ # do something...
46
+ result = m.check(result_id)
47
+ ```
48
+
49
+ ### create a task and wait for result
50
+
51
+ ```python
52
+ result = m.create_and_wait_result(params)
53
+ ```
@@ -0,0 +1,16 @@
1
+ fasttask_manager/__init__.py,sha256=iNQjDvmAgl5g0EihQQFT-VmOEFJAvZ5xHLTB2-eUjjI,29
2
+ fasttask_manager/create_project.py,sha256=vg3xxwxBcc4PagqHkVj_-Himei2hgCJL0OQAqtsQNaU,1068
3
+ fasttask_manager/manager.py,sha256=Z-FI5DYhViSOS5f7FWZY-nuddqHxYOEbWRm1QgxZNqw,3499
4
+ fasttask_manager/project/Dockerfile,sha256=ilF9ey6nhDTfVEbe0eh8bnRZYWKZTwh8CGlR19h9CQI,213
5
+ fasttask_manager/project/docker-compose.yml,sha256=LjOQ8TgEiCoUaIeYhIxpC_GByesZO0grnzXruUH4sSs,992
6
+ fasttask_manager/project/req.txt,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
+ fasttask_manager/project/setting.py,sha256=dqrslQfMZjxy0BZRh38VWPztKC998LdQq6RXdbcQjN4,520
8
+ fasttask_manager/project/tasks/get_circle_area.py,sha256=8f6YovtLcCTWamdVp5GY8ixt7li3pW_6-qYFLeVjZHA,483
9
+ fasttask_manager/project/tasks/get_hypotenuse.py,sha256=O6Ex07yLEuJzsLywuVBTz9LADIdeF4hpPBwFrZStcM8,618
10
+ fasttask_manager/project/tasks/packages/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
+ fasttask_manager/project/tasks/packages/tools.py,sha256=U7udJMeDtPIFdEUe4giiLh1-hOTEQnzg7lhUEOOgwKI,129
12
+ fasttask_manager-0.2.1.dist-info/LICENSE,sha256=Qv2ilebwoUtMJnRsZwRy729xS5JZQzLauJ0tQzkAkTA,1088
13
+ fasttask_manager-0.2.1.dist-info/METADATA,sha256=_yHUcbAYxNOeNBO74MpDSBgofXT32eqVpiutcDkS6S8,1012
14
+ fasttask_manager-0.2.1.dist-info/WHEEL,sha256=OpXWERl2xLPRHTvd2ZXo_iluPEQd8uSbYkJ53NAER_Y,109
15
+ fasttask_manager-0.2.1.dist-info/top_level.txt,sha256=pTXhlmzuBDPvkJ-u2YjLVC6Zyws1EglgsA26PryFZqs,17
16
+ fasttask_manager-0.2.1.dist-info/RECORD,,
@@ -0,0 +1,6 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (75.3.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py2-none-any
5
+ Tag: py3-none-any
6
+
@@ -0,0 +1 @@
1
+ fasttask_manager