sdpy-kit 0.4.0__tar.gz → 0.4.1__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 (48) hide show
  1. {sdpy_kit-0.4.0 → sdpy_kit-0.4.1}/PKG-INFO +1 -1
  2. {sdpy_kit-0.4.0 → sdpy_kit-0.4.1}/kit/__init__.py +1 -1
  3. {sdpy_kit-0.4.0 → sdpy_kit-0.4.1}/kit/config/log_config.py +42 -5
  4. {sdpy_kit-0.4.0 → sdpy_kit-0.4.1}/.gitignore +0 -0
  5. {sdpy_kit-0.4.0 → sdpy_kit-0.4.1}/README.md +0 -0
  6. {sdpy_kit-0.4.0 → sdpy_kit-0.4.1}/kit/ai/__init__.py +0 -0
  7. {sdpy_kit-0.4.0 → sdpy_kit-0.4.1}/kit/ai/base_service.py +0 -0
  8. {sdpy_kit-0.4.0 → sdpy_kit-0.4.1}/kit/ai/chat_service.py +0 -0
  9. {sdpy_kit-0.4.0 → sdpy_kit-0.4.1}/kit/ai/embedding_service.py +0 -0
  10. {sdpy_kit-0.4.0 → sdpy_kit-0.4.1}/kit/ai/exceptions.py +0 -0
  11. {sdpy_kit-0.4.0 → sdpy_kit-0.4.1}/kit/ai/failover.py +0 -0
  12. {sdpy_kit-0.4.0 → sdpy_kit-0.4.1}/kit/ai/image_service.py +0 -0
  13. {sdpy_kit-0.4.0 → sdpy_kit-0.4.1}/kit/ai/model_builder.py +0 -0
  14. {sdpy_kit-0.4.0 → sdpy_kit-0.4.1}/kit/ai/model_client.py +0 -0
  15. {sdpy_kit-0.4.0 → sdpy_kit-0.4.1}/kit/ai/pool.py +0 -0
  16. {sdpy_kit-0.4.0 → sdpy_kit-0.4.1}/kit/ai/profiles.py +0 -0
  17. {sdpy_kit-0.4.0 → sdpy_kit-0.4.1}/kit/ai/rerank_service.py +0 -0
  18. {sdpy_kit-0.4.0 → sdpy_kit-0.4.1}/kit/ai/runner.py +0 -0
  19. {sdpy_kit-0.4.0 → sdpy_kit-0.4.1}/kit/ai/types.py +0 -0
  20. {sdpy_kit-0.4.0 → sdpy_kit-0.4.1}/kit/anydoc_kit.py +0 -0
  21. {sdpy_kit-0.4.0 → sdpy_kit-0.4.1}/kit/common_kit.py +0 -0
  22. {sdpy_kit-0.4.0 → sdpy_kit-0.4.1}/kit/config/__init__.py +0 -0
  23. {sdpy_kit-0.4.0 → sdpy_kit-0.4.1}/kit/config/kit_config.py +0 -0
  24. {sdpy_kit-0.4.0 → sdpy_kit-0.4.1}/kit/crawl/__init__.py +0 -0
  25. {sdpy_kit-0.4.0 → sdpy_kit-0.4.1}/kit/crawl/article_models.py +0 -0
  26. {sdpy_kit-0.4.0 → sdpy_kit-0.4.1}/kit/crawl/web_article_kit.py +0 -0
  27. {sdpy_kit-0.4.0 → sdpy_kit-0.4.1}/kit/crawl/wx_article_kit.py +0 -0
  28. {sdpy_kit-0.4.0 → sdpy_kit-0.4.1}/kit/db/__init__.py +0 -0
  29. {sdpy_kit-0.4.0 → sdpy_kit-0.4.1}/kit/db/base_db_kit.py +0 -0
  30. {sdpy_kit-0.4.0 → sdpy_kit-0.4.1}/kit/db/crud.py +0 -0
  31. {sdpy_kit-0.4.0 → sdpy_kit-0.4.1}/kit/db/engine.py +0 -0
  32. {sdpy_kit-0.4.0 → sdpy_kit-0.4.1}/kit/db/exceptions.py +0 -0
  33. {sdpy_kit-0.4.0 → sdpy_kit-0.4.1}/kit/db/models/__init__.py +0 -0
  34. {sdpy_kit-0.4.0 → sdpy_kit-0.4.1}/kit/db/models/base.py +0 -0
  35. {sdpy_kit-0.4.0 → sdpy_kit-0.4.1}/kit/db/mysql_kit.py +0 -0
  36. {sdpy_kit-0.4.0 → sdpy_kit-0.4.1}/kit/db/pg_kit.py +0 -0
  37. {sdpy_kit-0.4.0 → sdpy_kit-0.4.1}/kit/db/query.py +0 -0
  38. {sdpy_kit-0.4.0 → sdpy_kit-0.4.1}/kit/db/session.py +0 -0
  39. {sdpy_kit-0.4.0 → sdpy_kit-0.4.1}/kit/db/sqlite_kit.py +0 -0
  40. {sdpy_kit-0.4.0 → sdpy_kit-0.4.1}/kit/db/transaction.py +0 -0
  41. {sdpy_kit-0.4.0 → sdpy_kit-0.4.1}/kit/docx_kit.py +0 -0
  42. {sdpy_kit-0.4.0 → sdpy_kit-0.4.1}/kit/file_kit.py +0 -0
  43. {sdpy_kit-0.4.0 → sdpy_kit-0.4.1}/kit/laya_kit.py +0 -0
  44. {sdpy_kit-0.4.0 → sdpy_kit-0.4.1}/kit/marker_kit.py +0 -0
  45. {sdpy_kit-0.4.0 → sdpy_kit-0.4.1}/kit/md2doc_kit.py +0 -0
  46. {sdpy_kit-0.4.0 → sdpy_kit-0.4.1}/kit/mineru_kit.py +0 -0
  47. {sdpy_kit-0.4.0 → sdpy_kit-0.4.1}/kit/redis_kit.py +0 -0
  48. {sdpy_kit-0.4.0 → sdpy_kit-0.4.1}/pyproject.toml +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: sdpy-kit
3
- Version: 0.4.0
3
+ Version: 0.4.1
4
4
  Summary: SDPY Kit——统一数据库访问层(PG/MySQL/SQLite)与 AI/Redis/文件/文档/向量工具集
5
5
  Author-email: Clark <changhongyuan@126.com>
6
6
  License-Expression: MIT
@@ -23,7 +23,7 @@ Author: Clark Chang
23
23
  数据库访问通过 kit.db 子包提供(基于 SQLModel)。
24
24
  """
25
25
 
26
- __version__ = "0.4.0"
26
+ __version__ = "0.4.1"
27
27
 
28
28
  from kit.db import (
29
29
  MYSQL,
@@ -24,6 +24,7 @@ Author: Clark Chang
24
24
  import logging
25
25
  import os
26
26
  import sys
27
+ import threading
27
28
  from logging.handlers import RotatingFileHandler
28
29
 
29
30
  from kit.config.kit_config import get_settings
@@ -49,6 +50,43 @@ def ensure_log_dir(log_dir: str) -> None:
49
50
  os.makedirs(log_dir, exist_ok=True)
50
51
 
51
52
 
53
+ # 同一日志文件路径共享单例文件 handler:
54
+ # 进程内该文件仅一个句柄,避免 Windows 下多句柄占用导致轮转必失败(WinError 32)。
55
+ # 参数策略 first-wins:maxBytes / backupCount / formatter 以首个创建者为准。
56
+ _file_handlers: dict[str, RotatingFileHandler] = {}
57
+ _file_handlers_lock = threading.Lock()
58
+
59
+
60
+ def _file_handler_cache_key(log_file_path: str) -> str:
61
+ """计算共享 handler 缓存 key(归一 Windows 大小写、分隔符与相对路径)"""
62
+ return os.path.normcase(os.path.abspath(log_file_path))
63
+
64
+
65
+ def _get_shared_file_handler(
66
+ log_file_path: str, max_bytes: int, backup_count: int, formatter: logging.Formatter
67
+ ) -> RotatingFileHandler:
68
+ """获取指定日志文件路径的共享文件 handler(不存在则创建)"""
69
+ key = _file_handler_cache_key(log_file_path)
70
+ with _file_handlers_lock:
71
+ handler = _file_handlers.get(key)
72
+ if handler is None:
73
+ handler = RotatingFileHandler(
74
+ log_file_path,
75
+ maxBytes=max_bytes,
76
+ backupCount=backup_count,
77
+ encoding="utf-8",
78
+ )
79
+ handler.setFormatter(formatter)
80
+ _file_handlers[key] = handler
81
+ return handler
82
+
83
+
84
+ def _reset_file_handlers() -> None:
85
+ """复位共享 handler 缓存(仅供测试隔离使用,不进 __all__)"""
86
+ with _file_handlers_lock:
87
+ _file_handlers.clear()
88
+
89
+
52
90
  def setup_logger(
53
91
  name: str | None = None,
54
92
  log_level: str | None = None,
@@ -77,13 +115,12 @@ def setup_logger(
77
115
  if settings.LOG_TO_FILE:
78
116
  ensure_log_dir(settings.LOG_DIR)
79
117
  log_file_path = log_file or os.path.join(settings.LOG_DIR, settings.LOG_FILE)
80
- file_handler = RotatingFileHandler(
118
+ file_handler = _get_shared_file_handler(
81
119
  log_file_path,
82
- maxBytes=max_bytes,
83
- backupCount=backup_count,
84
- encoding="utf-8",
120
+ max_bytes=max_bytes,
121
+ backup_count=backup_count,
122
+ formatter=formatter,
85
123
  )
86
- file_handler.setFormatter(formatter)
87
124
  logger.addHandler(file_handler)
88
125
 
89
126
  return logger
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes