nlttask 1.0.2__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.
funtask/__init__.py ADDED
@@ -0,0 +1 @@
1
+ from .models import Task
funtask/__main__.py ADDED
@@ -0,0 +1,4 @@
1
+ from .web.app import start_web_server
2
+
3
+ if __name__ == "__main__":
4
+ start_web_server()
@@ -0,0 +1 @@
1
+ from .base import Task
funtask/models/base.py ADDED
@@ -0,0 +1,6 @@
1
+ class Task:
2
+ def __init__(self, *args, **kwargs):
3
+ pass
4
+
5
+ def run(self, *args, **kwargs):
6
+ pass
@@ -0,0 +1,27 @@
1
+ from datetime import datetime
2
+ from sqlalchemy import create_engine, Column, Integer, String, DateTime, Text
3
+ from sqlalchemy.ext.declarative import declarative_base
4
+ from sqlalchemy.orm import sessionmaker
5
+
6
+ Base = declarative_base()
7
+
8
+
9
+ class TaskModel(Base):
10
+ __tablename__ = "tasks"
11
+
12
+ id = Column(Integer, primary_key=True)
13
+ task_dir = Column(String(255), nullable=False)
14
+ status = Column(
15
+ String(50), default="pending"
16
+ ) # pending, running, completed, failed
17
+ created_at = Column(DateTime, default=datetime.now)
18
+ updated_at = Column(DateTime, default=datetime.now, onupdate=datetime.now)
19
+ description = Column(Text, nullable=True)
20
+ task_type = Column(String(50)) # slurm, cpp, etc.
21
+ output = Column(Text, nullable=True)
22
+
23
+
24
+ # 创建数据库连接
25
+ engine = create_engine("sqlite:///tasks.db", echo=True)
26
+ Base.metadata.create_all(engine)
27
+ Session = sessionmaker(bind=engine)
File without changes
@@ -0,0 +1,50 @@
1
+ from datetime import datetime
2
+ from typing import List, Optional
3
+ from ..models.task_model import TaskModel, Session
4
+
5
+
6
+ class TaskManager:
7
+ def __init__(self):
8
+ self.session = Session()
9
+
10
+ def create_task(
11
+ self, task_dir: str, task_type: str, description: Optional[str] = None
12
+ ) -> TaskModel:
13
+ task = TaskModel(
14
+ task_dir=task_dir,
15
+ task_type=task_type,
16
+ description=description,
17
+ status="pending",
18
+ )
19
+ self.session.add(task)
20
+ self.session.commit()
21
+ return task
22
+
23
+ def get_task(self, task_id: int) -> Optional[TaskModel]:
24
+ return self.session.query(TaskModel).filter(TaskModel.id == task_id).first()
25
+
26
+ def get_all_tasks(self) -> List[TaskModel]:
27
+ return self.session.query(TaskModel).order_by(TaskModel.created_at.desc()).all()
28
+
29
+ def update_task_status(
30
+ self, task_id: int, status: str, output: Optional[str] = None
31
+ ) -> Optional[TaskModel]:
32
+ task = self.get_task(task_id)
33
+ if task:
34
+ task.status = status
35
+ task.updated_at = datetime.now()
36
+ if output:
37
+ task.output = output
38
+ self.session.commit()
39
+ return task
40
+
41
+ def delete_task(self, task_id: int) -> bool:
42
+ task = self.get_task(task_id)
43
+ if task:
44
+ self.session.delete(task)
45
+ self.session.commit()
46
+ return True
47
+ return False
48
+
49
+ def __del__(self):
50
+ self.session.close()
funtask/task/submit.py ADDED
@@ -0,0 +1,84 @@
1
+ """
2
+ #!/bin/bash
3
+ task_root='/work/home/liuc12/workbench'
4
+ timestamp=$(date +"%Y%m%d%H%M%S")
5
+ task_dir="$task_root/task_$timestamp"
6
+
7
+ mkdir "$task_dir"
8
+ cp -r *.cpp *.h *.sh *.slurm *.f90 *.dat $task_dir 2>/dev/null
9
+ cd "$task_dir"
10
+ pwd
11
+ #ls -al
12
+ sbatch config.slurm
13
+ """
14
+
15
+ import os
16
+ from datetime import datetime
17
+
18
+ from funbuild.shell import run_shell
19
+ from nltlog import getLogger
20
+
21
+ from .manager import TaskManager
22
+
23
+ logger = getLogger("funbuild")
24
+
25
+
26
+ def submit_task():
27
+ task_dir = os.path.join(
28
+ os.environ["HOME"], "/workbench", datetime.now().strftime("%Y%m%d%H%M%S")
29
+ )
30
+ logger.info(f"任务主目录:{task_dir}")
31
+ os.makedirs(task_dir, exist_ok=True)
32
+
33
+ # 创建任务管理器实例
34
+ task_manager = TaskManager()
35
+ task_type = None
36
+ description = None
37
+
38
+ logger.info(f"step1: 复制文件到任务主目录:{task_dir}")
39
+ run_shell(f"cp -r *.cpp *.h *.sh *.slurm *.f90 *.dat {task_dir} 2>/dev/null")
40
+
41
+ try:
42
+ if os.path.exists("config.slurm"):
43
+ task_type = "slurm"
44
+ description = "SLURM cluster task"
45
+ logger.info("step2: 检测到config.slurm文件,提交任务")
46
+ # 创建任务记录
47
+ task = task_manager.create_task(task_dir, task_type, description)
48
+
49
+ try:
50
+ output = run_shell(f"cd {task_dir} && sbatch config.slurm")
51
+ task_manager.update_task_status(task.id, "running", output)
52
+ except Exception as e:
53
+ task_manager.update_task_status(task.id, "failed", str(e))
54
+ raise e
55
+
56
+ elif os.path.exists("main.cpp"):
57
+ task_type = "cpp"
58
+ description = "Local C++ compilation and execution"
59
+ # 创建任务记录
60
+ task = task_manager.create_task(task_dir, task_type, description)
61
+
62
+ try:
63
+ logger.info("step2: 检测到main.cpp文件,编译")
64
+ compile_output = run_shell(f"cd {task_dir} && g++ main.cpp -o task.app")
65
+ logger.info("step3: 编译完成,开始执行")
66
+ execution_output = run_shell(f"cd {task_dir} && ./task.app")
67
+ task_manager.update_task_status(
68
+ task.id,
69
+ "completed",
70
+ f"Compilation: {compile_output}\nExecution: {execution_output}",
71
+ )
72
+ except Exception as e:
73
+ task_manager.update_task_status(task.id, "failed", str(e))
74
+ raise e
75
+
76
+ logger.info("任务提交完成")
77
+ return task_dir
78
+ except Exception as e:
79
+ logger.error(f"任务执行失败: {str(e)}")
80
+ raise e
81
+
82
+
83
+ if __name__ == "__main__":
84
+ submit_task()
funtask/web/app.py ADDED
@@ -0,0 +1,90 @@
1
+ from nicegui import ui
2
+ from ..task.manager import TaskManager
3
+ from ..task.submit import submit_task
4
+
5
+ task_manager = TaskManager()
6
+
7
+
8
+ def create_task_list():
9
+ with ui.card().classes("w-full"):
10
+ ui.label("任务列表").classes("text-h6")
11
+
12
+ # 创建任务表格
13
+ columns = [
14
+ {"name": "id", "label": "ID", "field": "id"},
15
+ {"name": "task_dir", "label": "任务目录", "field": "task_dir"},
16
+ {"name": "status", "label": "状态", "field": "status"},
17
+ {"name": "task_type", "label": "任务类型", "field": "task_type"},
18
+ {"name": "created_at", "label": "创建时间", "field": "created_at"},
19
+ {"name": "description", "label": "描述", "field": "description"},
20
+ ]
21
+
22
+ tasks = task_manager.get_all_tasks()
23
+ rows = [
24
+ {
25
+ "id": task.id,
26
+ "task_dir": task.task_dir,
27
+ "status": task.status,
28
+ "task_type": task.task_type,
29
+ "created_at": task.created_at.strftime("%Y-%m-%d %H:%M:%S"),
30
+ "description": task.description,
31
+ }
32
+ for task in tasks
33
+ ]
34
+
35
+ table = ui.table(columns=columns, rows=rows, row_key="id").classes("w-full")
36
+
37
+ async def refresh_table():
38
+ tasks = task_manager.get_all_tasks()
39
+ rows = [
40
+ {
41
+ "id": task.id,
42
+ "task_dir": task.task_dir,
43
+ "status": task.status,
44
+ "task_type": task.task_type,
45
+ "created_at": task.created_at.strftime("%Y-%m-%d %H:%M:%S"),
46
+ "description": task.description,
47
+ }
48
+ for task in tasks
49
+ ]
50
+ table.rows = rows
51
+
52
+ async def delete_task(task_id: int):
53
+ if task_manager.delete_task(task_id):
54
+ ui.notify(f"任务 {task_id} 已删除")
55
+ await refresh_table()
56
+ else:
57
+ ui.notify(f"删除任务 {task_id} 失败", type="negative")
58
+
59
+ async def view_task_output(task_id: int):
60
+ task = task_manager.get_task(task_id)
61
+ if task and task.output:
62
+ with ui.dialog() as dialog, ui.card():
63
+ ui.label(f"任务 {task_id} 输出").classes("text-h6")
64
+ ui.textarea(value=task.output, readonly=True).classes("w-full")
65
+ ui.button("关闭", on_click=dialog.close)
66
+ dialog.open()
67
+ else:
68
+ ui.notify("没有可用的输出", type="warning")
69
+
70
+ # 添加操作按钮
71
+ with ui.row():
72
+ ui.button("刷新", on_click=refresh_table).classes("mr-2")
73
+ for row in rows:
74
+ with ui.row():
75
+ ui.button(
76
+ "查看输出", on_click=lambda r=row: view_task_output(r["id"])
77
+ ).classes("mr-2")
78
+ ui.button(
79
+ "删除", on_click=lambda r=row: delete_task(r["id"]), color="red"
80
+ )
81
+
82
+
83
+ @ui.page("/")
84
+ def main_page():
85
+ ui.label("任务管理系统").classes("text-h4 q-mb-md")
86
+ create_task_list()
87
+
88
+
89
+ def start_web_server(host="0.0.0.0", port=8080):
90
+ ui.run(host=host, port=port, title="任务管理系统")
@@ -0,0 +1,15 @@
1
+ Metadata-Version: 2.4
2
+ Name: nlttask
3
+ Version: 1.0.2
4
+ Summary: nlttask
5
+ Author-email: 牛哥 <niuliangtao@qq.com>, farfarfun <farfarfun@qq.com>
6
+ Maintainer-email: 牛哥 <niuliangtao@qq.com>, farfarfun <farfarfun@qq.com>
7
+ Project-URL: Organization, https://github.com/farfarfun
8
+ Project-URL: Repository, https://github.com/farfarfun/funtask
9
+ Project-URL: Releases, https://github.com/farfarfun/funtask/releases
10
+ Requires-Python: >=3.8
11
+ Description-Content-Type: text/markdown
12
+ Requires-Dist: nltlog>=1.1.3
13
+ Requires-Dist: sqlalchemy>=2.0.50
14
+
15
+ # notetask
@@ -0,0 +1,13 @@
1
+ funtask/__init__.py,sha256=1An9ji9Yqij_SZdHEcVm8V_HRgpd_D9QbAro9bGklVw,25
2
+ funtask/__main__.py,sha256=vPcdHTqX2krxMpQfa58Vei7_lzQcGbOZiSxr5Iv7_hY,89
3
+ funtask/models/__init__.py,sha256=WanozeTJqTPVIpaXQzB5lvDI9XJLPoioyEKWB9RYwUQ,23
4
+ funtask/models/base.py,sha256=1mPWWKfwU4upK1xUshwcSCFHecTWpbZ86-FJvOYDzd4,116
5
+ funtask/models/task_model.py,sha256=Q4W30WfQo0eKorR88SFHskwkRgXBiGluqUcGlRXf7r4,911
6
+ funtask/task/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
+ funtask/task/manager.py,sha256=KzO9vUiPBsMTTzfO_WrdWxU56pC3AffjhDi5t8JomYU,1498
8
+ funtask/task/submit.py,sha256=rILZLceHf0t8THZbL0eXzfUxvgPexDy3u4OA4y9R6e4,2681
9
+ funtask/web/app.py,sha256=onrKVp290rVNqs3_0vjGfb7tfn6NoUSX3IuTYYo7_nk,3323
10
+ nlttask-1.0.2.dist-info/METADATA,sha256=_jt-VcvjA1zRt2RLZj8XgHUCvyDxz8VbAvEGZ5PPl5I,541
11
+ nlttask-1.0.2.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
12
+ nlttask-1.0.2.dist-info/top_level.txt,sha256=svcT_-fhz7u77X8wJYILLorz0fp2LjdYljx7QGa6ieg,8
13
+ nlttask-1.0.2.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ funtask