datacom-device-api 0.1.8__tar.gz → 0.1.10__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 (25) hide show
  1. {datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/PKG-INFO +1 -1
  2. {datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/pyproject.toml +1 -1
  3. {datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/src/datacom_device_api/process/terminal_process.py +62 -11
  4. {datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/src/datacom_device_api.egg-info/PKG-INFO +1 -1
  5. {datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/README.md +0 -0
  6. {datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/setup.cfg +0 -0
  7. {datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/src/datacom_device_api/__init__.py +0 -0
  8. {datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/src/datacom_device_api/data/__init__.py +0 -0
  9. {datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/src/datacom_device_api/data/table.py +0 -0
  10. {datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/src/datacom_device_api/event/event.py +0 -0
  11. {datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/src/datacom_device_api/ext/ext_meta.py +0 -0
  12. {datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/src/datacom_device_api/ext/ext_meta_display.py +0 -0
  13. {datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/src/datacom_device_api/operation/__init__.py +0 -0
  14. {datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/src/datacom_device_api/operation/table_operation.py +0 -0
  15. {datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/src/datacom_device_api/operation/table_read_from_xlsx.py +0 -0
  16. {datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/src/datacom_device_api/operation/table_save_to_db.py +0 -0
  17. {datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/src/datacom_device_api/process/__init__.py +0 -0
  18. {datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/src/datacom_device_api/utils/__init__.py +0 -0
  19. {datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/src/datacom_device_api/utils/directory_util.py +0 -0
  20. {datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/src/datacom_device_api/utils/logger.py +0 -0
  21. {datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/src/datacom_device_api.egg-info/SOURCES.txt +0 -0
  22. {datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/src/datacom_device_api.egg-info/dependency_links.txt +0 -0
  23. {datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/src/datacom_device_api.egg-info/requires.txt +0 -0
  24. {datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/src/datacom_device_api.egg-info/top_level.txt +0 -0
  25. {datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/test/test_table_matching.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: datacom-device-api
3
- Version: 0.1.8
3
+ Version: 0.1.10
4
4
  Summary: Add your description here
5
5
  Requires-Python: >=3.14
6
6
  Description-Content-Type: text/markdown
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "datacom-device-api"
3
- version = "0.1.8"
3
+ version = "0.1.10"
4
4
  description = "Add your description here"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.14"
@@ -15,6 +15,7 @@ from typing import Any, Callable, Optional, ParamSpec, Protocol, TypeVar, runtim
15
15
  from uuid import UUID
16
16
  import uuid
17
17
 
18
+ from rich.console import Console
18
19
  from rich.progress import Progress, TaskID
19
20
 
20
21
 
@@ -60,15 +61,17 @@ class TerminalProcess:
60
61
  process.submit(task2)
61
62
  """
62
63
 
63
- def __init__(self, max_workers: Optional[int] = None):
64
+ def __init__(self, max_workers: Optional[int] = None, console: Optional[Console] = None):
64
65
  """初始化终端进程执行器。
65
66
 
66
67
  Args:
67
68
  max_workers: 进程池最大并发数,默认为 CPU 核心数
69
+ console: 共享的 Rich Console 实例,用于日志输出与进度条保持同一终端
68
70
  """
69
71
  self.__pool = ProcessPoolExecutor(max_workers=max_workers or os.cpu_count())
70
72
  self.__manager = Manager()
71
73
  self.__progress_queue: queue.Queue[ProgressMessage] = self.__manager.Queue()
74
+ self.__log_queue: queue.Queue[str] = self.__manager.Queue()
72
75
 
73
76
  self.__task_future_count = 0
74
77
  self.__tasks: dict[UUID, Future[Any]] = {}
@@ -76,7 +79,10 @@ class TerminalProcess:
76
79
 
77
80
  self.__progress_thread_stop_event = threading.Event()
78
81
  self.__progress_tasks: dict[UUID, TaskID] = {}
79
- self.__progress = Progress()
82
+ self.__console = console if console is not None else Console()
83
+ # 让 Progress 固定在终端底部,使用同一个 Console 输出日志时,
84
+ # 日志会显示在进度条之上,进度条始终保持在终端底部
85
+ self.__progress = Progress(console=self.__console)
80
86
  self.__progress_thread: Optional[threading.Thread] = None
81
87
  self.__progress_main_task: TaskID = self.__progress.add_task(
82
88
  'main', total=self.__task_future_count
@@ -113,10 +119,24 @@ class TerminalProcess:
113
119
  if message.type == 'done':
114
120
  self.__progress.update(self.__progress_main_task, advance=1)
115
121
 
122
+ def print(self, *args, **kwargs) -> None:
123
+ """在进度条之上输出日志信息。
124
+
125
+ 使用与 Progress 共享的 Console 输出,日志会显示在终端上方,
126
+ 进度条始终保持在终端底部。
127
+ """
128
+ self.__console.print(*args, **kwargs)
129
+
130
+ @property
131
+ def console(self) -> Console:
132
+ """返回与 Progress 共享的 Console 实例。"""
133
+ return self.__console
134
+
116
135
  @staticmethod
117
136
  def _warrper_fn(
118
137
  fn: EXECUTE_FUNC_TYPE,
119
138
  progress_queue: queue.Queue[ProgressMessage],
139
+ log_queue: queue.Queue[str],
120
140
  task_id: UUID,
121
141
  *args,
122
142
  **kwargs,
@@ -125,7 +145,19 @@ class TerminalProcess:
125
145
 
126
146
  封装进度上报、完成标记和异常处理,通过队列将进度消息
127
147
  发送回主进程。任务正常结束或异常均会发送对应类型的消息。
148
+ 同时配置根 logger 使用 QueueHandler 将子进程日志转发到主进程。
128
149
  """
150
+ import logging
151
+ import logging.handlers
152
+
153
+ root_logger = logging.getLogger()
154
+ queue_handler = logging.handlers.QueueHandler(log_queue)
155
+ queue_handler.setLevel(logging.INFO)
156
+ formatter = logging.Formatter('[%(asctime)s-%(levelname)s](%(name)s): %(message)s')
157
+ queue_handler.setFormatter(formatter)
158
+ root_logger.addHandler(queue_handler)
159
+ root_logger.setLevel(logging.INFO)
160
+
129
161
  done_send = False
130
162
 
131
163
  def report(progress: float, total: float, message: str, msg_type: str = 'progress'):
@@ -165,21 +197,33 @@ class TerminalProcess:
165
197
  def run_display_progress(self) -> None:
166
198
  """进度消费线程主循环。
167
199
 
168
- 持续从队列中取出进度消息,依次更新内置进度条并触发监听器。
200
+ 持续从队列中取出进度消息和日志消息,进度消息依次更新内置进度条并触发监听器,
201
+ 日志消息通过共享 Console 输出到终端(显示在进度条上方)。
169
202
  使用带超时的轮询避免阻塞,确保停止事件触发后能及时退出。
170
203
  """
171
- while not self.__progress_thread_stop_event.is_set() or not self.__progress_queue.empty():
204
+ while not self.__progress_thread_stop_event.is_set() or not self.__progress_queue.empty() or not self.__log_queue.empty():
172
205
  try:
173
206
  message = self.__progress_queue.get(timeout=0.1)
174
207
  self.update_progress(message)
175
208
  self.trigger_progress(message.task_id, message)
176
209
  except queue.Empty:
177
- if (
178
- self.__progress_thread_stop_event.is_set()
179
- and all(futrue.done() for futrue in self.__tasks.values())
180
- ):
210
+ pass
211
+
212
+ while not self.__log_queue.empty():
213
+ try:
214
+ log_msg = self.__log_queue.get_nowait()
215
+ self.__console.print(log_msg)
216
+ except queue.Empty:
181
217
  break
182
218
 
219
+ if (
220
+ self.__progress_thread_stop_event.is_set()
221
+ and all(futrue.done() for futrue in self.__tasks.values())
222
+ and self.__progress_queue.empty()
223
+ and self.__log_queue.empty()
224
+ ):
225
+ break
226
+
183
227
  def submit(
184
228
  self,
185
229
  fn: EXECUTE_FUNC_TYPE,
@@ -199,7 +243,7 @@ class TerminalProcess:
199
243
  任务的 Future 对象,可用于获取结果或异常
200
244
  """
201
245
  task_id = uuid.uuid4()
202
- task_fn = partial(TerminalProcess._warrper_fn, fn, self.__progress_queue, task_id)
246
+ task_fn = partial(TerminalProcess._warrper_fn, fn, self.__progress_queue, self.__log_queue, task_id)
203
247
  future = self.__pool.submit(task_fn, *args, **kwargs)
204
248
  self.__tasks[task_id] = future
205
249
  self.__task_update_lisening_fn_dict[task_id] = []
@@ -222,8 +266,8 @@ class TerminalProcess:
222
266
  def shutdown(self) -> None:
223
267
  """停止任务执行并释放资源。
224
268
 
225
- 按顺序执行:等待所有任务完成 → 消费完剩余进度消息
226
- 关闭进程池 → 停止进度条。确保不会因消息未消费完而丢失进度。
269
+ 按顺序执行:等待所有任务完成 → 设置停止事件 消费线程退出并消费剩余消息 →
270
+ 关闭进程池 → 停止进度条。确保不会因消息未消费完而丢失进度或日志。
227
271
  """
228
272
  for future in self.__tasks.values():
229
273
  try:
@@ -236,6 +280,13 @@ class TerminalProcess:
236
280
  self.__progress_thread.join()
237
281
  self.__progress_thread = None
238
282
 
283
+ while not self.__log_queue.empty():
284
+ try:
285
+ log_msg = self.__log_queue.get_nowait()
286
+ self.__console.print(log_msg)
287
+ except queue.Empty:
288
+ break
289
+
239
290
  self.__pool.shutdown(wait=True)
240
291
  self.__progress.stop()
241
292
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: datacom-device-api
3
- Version: 0.1.8
3
+ Version: 0.1.10
4
4
  Summary: Add your description here
5
5
  Requires-Python: >=3.14
6
6
  Description-Content-Type: text/markdown