pro-craft 0.1.56__py3-none-any.whl → 0.2.58__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.

Potentially problematic release.


This version of pro-craft might be problematic. Click here for more details.

@@ -0,0 +1,113 @@
1
+ from .codermanager import CoderTemplateManager
2
+ from typing import List, Dict, Any,Optional
3
+ import re
4
+
5
+ coder = CoderTemplateManager()
6
+
7
+ # --- 工具函数实现 ---
8
+
9
+ def search_template_by_text(query: str, top_k: int = 5) -> List[Dict[str, Any]]:
10
+ """
11
+ 根据自然语言查询在模板库中进行语义搜索(使用 Qdrant 向量检索),返回最相关的 `top_k` 个模板的摘要信息。
12
+ """
13
+ print(f"input & {type(query)} & query: {query} top:k {top_k} ")
14
+ search_result = coder.search(
15
+ text=query,
16
+ limit=top_k,
17
+ # query_filter=None # 可以在这里添加额外的过滤条件,例如根据语言、框架过滤
18
+ )
19
+
20
+ templates_summary = []
21
+ for hit in search_result:
22
+ # 在实际 Qdrant 中,hit.id 是模板的ID,hit.payload 包含其他元数据
23
+ # 假设你的 Qdrant payload 中存储了 template_name 和 description
24
+ templates_summary.append({
25
+ 'template_id': hit.payload.get("template_id"),
26
+ 'description': hit.payload.get('description', 'No description provided.'),
27
+ 'match_score': hit.score
28
+ })
29
+ print(f"output & {type(templates_summary)} & {templates_summary} ")
30
+ return templates_summary
31
+
32
+ def get_template_details(template_id: str) -> Optional[Dict[str, Any]]: # template_id 根据你的模型是 Integer
33
+ """
34
+ 根据 `template_id` 从数据库中获取模板的完整详细信息,包括模板代码、推断出的命名约定和使用建议。
35
+ """
36
+ print(f"input & {type(template_id)} & query: {template_id} ")
37
+ template = coder.get_template_obj(template_id = template_id)
38
+ if template:
39
+ return {
40
+ 'template_id': template.template_id,
41
+ 'description': template.description,
42
+ 'template_code': template.template_code,
43
+ 'version': template.version,
44
+ }
45
+ print(f"output & {type(template)} & {template} ")
46
+ return None
47
+
48
+
49
+ def ask_user_for_clarification(question: str) -> str:
50
+ """
51
+ 当你对用户需求有疑问,或需要用户做选择(例如在多个匹配模板中选择一个)时,使用此工具向用户提问。
52
+ """
53
+ print(f"input & {type(question)} & query: {question} ")
54
+ print("\n--- Agent 需要你的帮助 ---")
55
+ print(f"Agent: {question}")
56
+ user_input = input("你的回答: ")
57
+ print("-------------------------\n")
58
+ print(f"output & {type(user_input)} & query: {user_input} ")
59
+ return user_input
60
+
61
+
62
+ def generate_request_file(template_code: str, user_request_details: Dict[str, Any], naming_conventions: Optional[Dict[str, Any]] = None) -> str:
63
+ """
64
+ 根据选定的模板代码、解析后的用户需求(结构化形式)和模板的命名约定,生成符合 `REQUEST_START/END` 格式的指令文件。
65
+ `user_request_details` 应该是一个字典,键是 BLOCK/PLACEHOLDER 的名称,值是包含 '指令' 和 '约束/示例' 的字典。
66
+ """
67
+ print(f"input & {type(template_code)} & template_code: {template_code} user_request_details: {user_request_details} naming_conventions: {naming_conventions}")
68
+
69
+ request_parts = []
70
+
71
+ request_parts.append("--- REQUEST_START ---")
72
+ request_parts.append("template.py # 目标文件通常是这个,可以根据实际情况调整") # 假设一个通用文件名
73
+
74
+ # 添加整体目标描述
75
+ overall_goal = user_request_details.get("overall_goal", "完善代码模板以满足以下需求。")
76
+ request_parts.append(f"\n**目标:** {overall_goal}\n")
77
+
78
+ # 添加命名约定 (如果提供了)
79
+ if naming_conventions:
80
+ request_parts.append("**命名约定:**")
81
+ for key, value in naming_conventions.items():
82
+ request_parts.append(f"* **{key}:** {value}")
83
+ request_parts.append("") # 空行
84
+
85
+ request_parts.append("**具体修改点:**\n")
86
+
87
+ # 遍历模板代码,找到所有的 BLOCK 和 PLACEHOLDER
88
+ # 然后根据 user_request_details 填充指令
89
+ # 这是一个简化版本,实际可能需要更复杂的解析器来处理嵌套块或动态生成的块
90
+ # 对于 MVP,我们可以假设 user_request_details 中包含了所有需要填充的块/占位符
91
+ block_pattern = r"(BLOCK_START|PLACEHOLDER):\s*(\w+)"
92
+ for match in re.finditer(block_pattern, template_code):
93
+ block_type = match.group(1)
94
+ block_name = match.group(2)
95
+
96
+ if block_name in user_request_details:
97
+ details = user_request_details[block_name]
98
+ instruction = details.get("指令", "")
99
+ constraint_example = details.get("约束/示例", "")
100
+
101
+ request_parts.append(f"* **{block_type}: {block_name}**")
102
+ request_parts.append(f" * **指令:** {instruction}")
103
+ if constraint_example:
104
+ # 确保多行约束/示例能正确缩进
105
+ formatted_ce = "\n".join([f" * **约束/示例:** {line}" if i == 0 else f" * {line}" for i, line in enumerate(str(constraint_example).splitlines())])
106
+ request_parts.append(formatted_ce)
107
+ request_parts.append("") # 空行
108
+
109
+ request_parts.append("--- REQUEST_END ---")
110
+ print(f"output & {type(request_parts)} & request_parts: {request_parts} ")
111
+
112
+ return "\n".join(request_parts)
113
+
@@ -0,0 +1,81 @@
1
+ # --- 假设的依赖项 ---
2
+ # Qdrant 客户端
3
+ from qdrant_client import QdrantClient, models # 你需要根据实际情况导入 Qdrant 客户端
4
+ qdrant_client = QdrantClient(host="localhost", port=6333) # 示例Qdrant客户端初始化
5
+
6
+
7
+ from typing import Any, List
8
+ from llama_index.core.bridge.pydantic import PrivateAttr
9
+ from llama_index.core.embeddings import BaseEmbedding
10
+ from volcenginesdkarkruntime import Ark
11
+
12
+
13
+ class VolcanoEmbedding(BaseEmbedding):
14
+ _model = PrivateAttr()
15
+ _ark_client = PrivateAttr()
16
+ _encoding_format = PrivateAttr()
17
+
18
+ def __init__(
19
+ self,
20
+ model_name: str = "doubao-embedding-text-240715",
21
+ api_key: str = "",
22
+ **kwargs: Any,
23
+ ) -> None:
24
+ super().__init__(**kwargs)
25
+ self._ark_client = Ark(api_key=api_key)
26
+ self._model = model_name
27
+ self._encoding_format = "float"
28
+
29
+ @classmethod
30
+ def class_name(cls) -> str:
31
+ return "ark"
32
+
33
+ def _get_query_embedding(self, query: str) -> List[float]:
34
+ """
35
+ 获取查询字符串的 embedding。
36
+ 通常查询和文档使用相同的 embedding 模型。
37
+ """
38
+
39
+ resp = self._ark_client.embeddings.create(
40
+ model=self._model,
41
+ input=[query],
42
+ encoding_format=self._encoding_format,
43
+ )
44
+ return resp.data[0].embedding
45
+
46
+ def _get_text_embedding(self, text: str) -> List[float]:
47
+ """
48
+ 获取单个文档字符串的 embedding。
49
+ """
50
+ resp = self._ark_client.embeddings.create(
51
+ model=self._model,
52
+ input=[text],
53
+ encoding_format=self._encoding_format,
54
+ )
55
+ return resp.data[0].embedding
56
+
57
+ def _get_text_embeddings(self, texts: List[str]) -> List[List[float]]:
58
+ """
59
+ 批量获取文档字符串的 embedding。
60
+ 如果你的火山模型支持批量推理,强烈建议实现此方法以提高效率。
61
+ 否则,它可以简单地循环调用 _get_text_embedding。
62
+ """
63
+ resp = self._ark_client.embeddings.create(
64
+ model=self._model,
65
+ input=texts,
66
+ encoding_format=self._encoding_format,
67
+ )
68
+ return [i.embedding for i in resp.data]
69
+
70
+ async def _aget_query_embedding(self, query: str) -> List[float]:
71
+ return self._get_query_embedding(query)
72
+
73
+ async def _aget_text_embedding(self, text: str) -> List[float]:
74
+ return self._get_text_embedding(text)
75
+
76
+ if __name__ == "__main__":
77
+
78
+ embedding_model = VolcanoEmbedding(
79
+ model_name = "doubao-embedding-text-240715",
80
+ api_key = "39ad310a-c6f7-4d66-962e-1fbfa7e6edf1"
81
+ )
@@ -0,0 +1,61 @@
1
+ llm2 = """
2
+ 你是一个专业的Python代码修改和生成AI。你的任务是根据用户提供的代码模板文件和详细的修改指令文件,精确地对模板进行补充、完善和修改。
3
+
4
+ **你的目标是:**
5
+ 1. **严格遵循指令文件中的所有要求,尤其是针对特定 `BLOCK` 和 `PLACEHOLDER` 的指令和约束/示例。**
6
+ 2. **尽可能应用指令文件中提供的命名约定。**
7
+ 3. **仅修改指令明确要求修改的部分,模板中未被指令覆盖的固定部分必须保持不变。**
8
+ 4. **最终输出完整且可运行的Python代码。**
9
+
10
+ **输入格式:**
11
+ 用户将以以下两个部分向你提供信息:
12
+
13
+ --- TEMPLATE_CODE_START ---
14
+ [原始的代码模板内容,其中包含 BLOCK_START/END 和 PLACEHOLDER/END_PLACEHOLDER 标记]
15
+ --- TEMPLATE_CODE_END ---
16
+
17
+ --- REQUEST_FILE_START ---
18
+ [一个结构化的指令文件,格式为 REQUEST_START/END,包含目标、命名约定和具体修改点]
19
+ --- REQUEST_FILE_END ---
20
+
21
+ **你的工作流程和生成原则:**
22
+
23
+ 1. **解析指令文件:**
24
+ * 首先解析 `REQUEST_FILE_START` 中的所有内容,理解其 `目标`、`命名约定` 和 `具体修改点`。
25
+ * 将 `具体修改点` 中的每个 `BLOCK` 和 `PLACEHOLDER` 指令及其 `约束/示例` 映射到模板代码中的对应位置。
26
+ 2. **处理模板代码:**
27
+ * 逐行读取 `TEMPLATE_CODE_START` 中的模板代码。
28
+ * 当遇到 `BLOCK_START` 或 `PLACEHOLDER` 标记时:
29
+ * 查找指令文件中对应 `块名称` 的修改指令。
30
+ * **如果存在指令:**
31
+ * 删除 `BLOCK_START` 和 `BLOCK_END` (或 `PLACEHOLDER` 和 `END_PLACEHOLDER`) 及其内部的原始内容(包括 `AI:` 注释)。
32
+ * 用指令中提供的代码**替换**该区域。
33
+ * 在替换的代码块的开始和结束位置,添加特殊的标记 `// AI_MODIFIED_START` 和 `// AI_MODIFIED_END` (如果只是新增内容,可以使用 `// AI_ADDED_START` 和 `// AI_ADDED_END`)。
34
+ * 如果指令是要求删除某些内容,请用 `// AI_DELETED_LINE: [原始行内容]` 标记被删除的行。
35
+ * **如果不存在指令:**
36
+ * 保留该 `BLOCK` 或 `PLACEHOLDER` 及其内部的原始内容(包括 `AI:` 注释和标记本身),不做任何改动。这允许模板中的可选部分在没有明确指令时保持原样。
37
+ * 当遇到非标记的普通代码行时,保持其不变。
38
+ 3. **应用命名约定:**
39
+ * 在生成或修改代码时,优先应用 `REQUEST_FILE_START` 中提供的 `命名约定`。
40
+ * **重要:** 命名约定只应影响由你**生成或修改**的代码部分(即 `AI_ADDED` 或 `AI_MODIFIED` 区域)。你不能随意修改模板中未被明确指令触及的固定代码部分的命名。
41
+ 4. **生成中间输出:**
42
+ * 首先生成包含所有 `// AI_ADDED/MODIFIED/DELETED` 标记的完整代码。这有助于后续的自动化工具进行变更追踪和人工核查。
43
+ 5. **生成最终输出:**
44
+ * 在生成中间输出后,进一步处理该代码,**移除所有 `// AI_ADDED/MODIFIED/DELETED` 类型的标记**。
45
+ * 移除所有模板中遗留的 `BLOCK_START/END` 和 `PLACEHOLDER/END_PLACEHOLDER` 标记。
46
+ * 保留所有的 Docstrings 和常规的代码注释。
47
+
48
+ **你的输出必须是最终的、清理后的完整 Python 代码文件内容。**
49
+
50
+ """
51
+
52
+ from modusched.core import BianXieAdapter
53
+ bx = BianXieAdapter()
54
+ from pro_craft.utils import extract_
55
+ def write_code(request):
56
+ result = bx.product(llm2 + request)
57
+ print(result)
58
+ python_code = extract_(result,r"python")
59
+ with open("output.py","w",encoding="utf-8") as f:
60
+ f.write(python_code)
61
+ return "success" + " output.py generated."
pro_craft/database.py CHANGED
@@ -1,5 +1,5 @@
1
1
 
2
- from sqlalchemy import Column, Integer, String, Text, DateTime, text, UniqueConstraint, Boolean, func, Float
2
+ from sqlalchemy import Column, Integer, String, Text, DateTime, text, UniqueConstraint, Boolean, func, Float, Double
3
3
  from sqlalchemy.orm import declarative_base
4
4
 
5
5
  from datetime import datetime, timedelta
@@ -179,13 +179,10 @@ class Prompt(PromptBase):
179
179
  class UseCase(PromptBase):
180
180
  __tablename__ = 'ai_usecase' # 数据库中的表名,你可以改成你希望的名字
181
181
 
182
- # __table_args__ = (
183
- # UniqueConstraint('prompt_id', 'use_case', name='_prompt_id_version_uc'),
184
- # # 'name' 参数是可选的,用于给数据库中的约束指定一个名称,方便管理和调试
185
- # )
186
-
187
- # id (int, primary_key=True, autoincrement=True)
188
- # 你的属性表中 id 为 int, true (not null), true (primary key), 0 (length), ASC (key order), true (auto increment)
182
+ __table_args__ = (
183
+ UniqueConstraint('time',name='time_double_uc'),
184
+ # 'name' 参数是可选的,用于给数据库中的约束指定一个名称,方便管理和调试
185
+ )
189
186
  id = Column(
190
187
  Integer,
191
188
  primary_key=True,
@@ -196,19 +193,16 @@ class UseCase(PromptBase):
196
193
 
197
194
  # prompt_id (varchar 255, not null, unique)
198
195
  # 你的属性表中 prompt_id 为 varchar, 255 (length), true (not null)
199
- prompt_id = Column(
196
+
197
+ level = Column(
200
198
  String(255), # VARCHAR 类型,长度 255
201
199
  nullable=False, # 不能为空 # 必须是唯一的,这会创建唯一索引
202
- comment="Unique identifier for the prompt"
200
+ comment="level"
203
201
  )
204
-
205
-
206
- # prompt (text, not null)
207
- # 你的属性表中 prompt 为 text, true (not null)
208
- use_case = Column(
209
- Text, # TEXT 类型,适用于长文本
210
- nullable=False, # 不能为空
211
- comment="用例"
202
+ time = Column(
203
+ Double,
204
+ nullable=False, # 不能为空
205
+ comment="时间戳"
212
206
  )
213
207
 
214
208
  timestamp = Column(
@@ -219,101 +213,47 @@ class UseCase(PromptBase):
219
213
  comment="时间戳"
220
214
  )
221
215
 
222
- output = Column(
223
- Text, # TEXT 类型,适用于长文本
216
+ filepath = Column(
217
+ String(255), # TEXT 类型,适用于长文本
224
218
  nullable=False, # 不能为空
225
- comment="AI输出"
219
+ comment="文件路径"
226
220
  )
227
221
 
228
- # use_case (text, nullable)
229
- # 你的属性表中 use_case 为 text, false (not null, 即 nullable=True), NULL (default value), '用例' (comment)
230
- solution = Column(
231
- Text,
232
- nullable=True, # 可以为空 (因为你的表格中 Not Null 为 false)
233
- comment="理想结果" # 列注释
234
- )
235
222
 
236
- faired_time = Column(
237
- Integer,
223
+ function = Column(
224
+ String(255), # TEXT 类型,适用于长文本
238
225
  nullable=False, # 不能为空
239
- comment="失败次数"
226
+ comment="函数"
240
227
  )
241
228
 
242
- is_deleted = Column(Boolean, default=False, server_default=text('0'))
243
-
244
- # 定义 __repr__ 方法以便打印对象时有清晰的表示
245
- def __repr__(self):
246
- return (f"<Prompt(id={self.id}, prompt_id='{self.prompt_id}', "
247
- f"use_case='{self.use_case[:50]}...', solution='{self.solution}')>"
248
- f"is_deleted='{self.is_deleted}...'>")
249
-
250
-
251
- class EvalsInfo(PromptBase):
252
- __tablename__ = 'ai_evals' # 数据库中的表名,你可以改成你希望的名字
253
-
254
- # __table_args__ = (
255
- # UniqueConstraint('prompt_id', 'use_case', name='_prompt_id_version_uc'),
256
- # # 'name' 参数是可选的,用于给数据库中的约束指定一个名称,方便管理和调试
257
- # )
258
-
259
- # id (int, primary_key=True, autoincrement=True)
260
- # 你的属性表中 id 为 int, true (not null), true (primary key), 0 (length), ASC (key order), true (auto increment)
261
- id = Column(
262
- Integer,
263
- primary_key=True,
264
- autoincrement=True, # 自动递增
229
+ lines = Column(
230
+ String(255), # TEXT 类型,适用于长文本
265
231
  nullable=False, # 不能为空
266
- comment="Primary key ID"
267
- )
268
-
269
- # prompt_id (varchar 255, not null, unique)
270
- # 你的属性表中 prompt_id 为 varchar, 255 (length), true (not null)
271
- prompt_id = Column(
272
- String(255), # VARCHAR 类型,长度 255
273
- nullable=False, # 不能为空 # 必须是唯一的,这会创建唯一索引
274
- comment="Unique identifier for the prompt"
275
- )
276
- status = Column(
277
- String(255), # VARCHAR 类型,长度 255
278
- nullable=False, # 不能为空 # 必须是唯一的,这会创建唯一索引
279
- comment="通过/未通过"
232
+ comment="函数"
280
233
  )
281
-
282
- score = Column(
283
- Float,
234
+ target = Column(
235
+ Text, # TEXT 类型,适用于长文本
284
236
  nullable=False, # 不能为空
285
- comment="失败次数"
237
+ comment="标签"
286
238
  )
287
239
 
288
- total = Column(
289
- Integer,
240
+ type_ = Column(
241
+ String(255), # TEXT 类型,适用于长文本
290
242
  nullable=False, # 不能为空
291
- comment="失败次数"
243
+ comment="函数"
292
244
  )
293
245
 
294
- # prompt (text, not null)
295
- # 你的属性表中 prompt 为 text, true (not null)
296
- bad_case = Column(
246
+ content = Column(
297
247
  Text, # TEXT 类型,适用于长文本
298
248
  nullable=False, # 不能为空
299
- comment="用例"
300
- )
301
-
302
- timestamp = Column(
303
- DateTime,
304
- nullable=False, # 不能为空
305
- server_default=text('CURRENT_TIMESTAMP'),
306
- onupdate=text('CURRENT_TIMESTAMP'),
307
- comment="时间戳"
249
+ comment="The actual prompt text content"
308
250
  )
309
251
 
310
-
311
252
  is_deleted = Column(Boolean, default=False, server_default=text('0'))
312
253
 
313
254
  # 定义 __repr__ 方法以便打印对象时有清晰的表示
314
255
  def __repr__(self):
315
256
  return (f"<Prompt(id={self.id}, prompt_id='{self.prompt_id}', "
316
- f"status='{self.status}...', score='{self.score}')>"
317
- f"total='{self.total}...', score='{self.score}')>"
257
+ f"use_case='{self.use_case[:50]}...', solution='{self.solution}')>"
318
258
  f"is_deleted='{self.is_deleted}...'>")
319
259
 
pro_craft/log.py CHANGED
@@ -1,7 +1,7 @@
1
1
  import logging
2
2
  import os
3
3
  from logging.handlers import RotatingFileHandler, TimedRotatingFileHandler
4
-
4
+ import inspect
5
5
  class Log:
6
6
  _instance = None
7
7
  def __new__(cls, *args, **kwargs):
@@ -12,18 +12,18 @@ class Log:
12
12
  def __init__(self, console_level = logging.INFO, log_file_name="app.log"):
13
13
  self.Console_LOG_LEVEL = console_level
14
14
  self.log_file_name = log_file_name
15
- os.makedirs("logs", exist_ok=True)
16
15
  self.LOG_FILE_PATH = os.path.join("logs", log_file_name)
16
+ os.makedirs(os.path.dirname(self.LOG_FILE_PATH), exist_ok=True)
17
17
  self.logger = self.get_logger()
18
- self.super_log_level = self.logger.critical
19
18
 
20
19
  def get_logger(self):
21
20
  logger = logging.getLogger()
22
- # logger.setLevel(self.LOG_LEVEL)
21
+ logger.setLevel(logging.DEBUG)
23
22
  if not logger.handlers:
24
23
  # --- 4. 配置 Formatter (格式化器) ---
24
+ # 以后有一个标准化的日志要使用logger 而非标的则使用super-log
25
25
  formatter = logging.Formatter(
26
- "%(asctime)s - %(levelname)s - %(name)s - %(funcName)s - %(module)s:%(lineno)d - %(message)s"
26
+ "%(asctime)s $ %(created)f $ %(levelname)s $ %(funcName)s $ :%(lineno)d $ %(pathname)s $ %(message)s||"
27
27
  )
28
28
  # --- 5. 配置 Handler (处理器) ---
29
29
 
@@ -33,50 +33,80 @@ class Log:
33
33
  console_handler.setFormatter(formatter)
34
34
  logger.addHandler(console_handler)
35
35
 
36
-
37
- # 文件
38
-
39
- # 5.2 信息数据
40
-
41
- # RotatingFileHandler: 按文件大小轮转
42
- # maxBytes: 单个日志文件的最大字节数 (例如 10MB)
43
- # backupCount: 保留的旧日志文件数量
44
- file_handler = RotatingFileHandler(
36
+ # 文件系统
37
+ ## 主日志本
38
+ file_handler = RotatingFileHandler( # RotatingFileHandler: 按文件大小轮转
45
39
  self.LOG_FILE_PATH,
46
- maxBytes=10 * 1024 * 1024, # 10 MB
47
- backupCount=5,
40
+ maxBytes=10 * 1024 * 1024, # 10 MB # maxBytes: 单个日志文件的最大字节数 (例如 10MB)
41
+ backupCount=10, # backupCount: 保留的旧日志文件数量
48
42
  encoding="utf-8",
49
43
  )
50
- file_handler.setLevel(logging.INFO) # 文件中显示所有指定级别的日志
44
+ file_handler.setLevel(logging.DEBUG) # 文件中显示所有指定级别的日志
51
45
  file_handler.setFormatter(formatter)
52
46
  logger.addHandler(file_handler)
53
47
 
54
- # 5.3 错误警告日志
48
+ ## 运行日志本
49
+ file_handler_info = RotatingFileHandler(
50
+ self.LOG_FILE_PATH.replace('.log','_info.log'),
51
+ maxBytes=10 * 1024 * 1024, # 10 MB
52
+ backupCount=5,
53
+ encoding="utf-8",
54
+ )
55
+ file_handler_info.setLevel(logging.INFO) # 文件中显示所有指定级别的日志
56
+ file_handler_info.setFormatter(formatter)
57
+ logger.addHandler(file_handler_info)
55
58
 
56
- file_handler_debug = RotatingFileHandler(
59
+ ## 错误日志本
60
+ file_handler_warning = RotatingFileHandler(
57
61
  self.LOG_FILE_PATH.replace('.log','_err.log'),
58
62
  maxBytes=10 * 1024 * 1024, # 10 MB
59
63
  backupCount=5,
60
64
  encoding="utf-8",
61
65
  )
62
- file_handler_debug.setLevel(logging.WARNING) # 文件中显示所有指定级别的日志
63
- file_handler_debug.setFormatter(formatter)
66
+ file_handler_warning.setLevel(logging.WARNING) # 文件中显示所有指定级别的日志
67
+ file_handler_warning.setFormatter(formatter)
68
+ logger.addHandler(file_handler_warning)
64
69
 
65
- file_handler_cri = RotatingFileHandler(
66
- self.LOG_FILE_PATH.replace('.log','_slog.log'),
70
+ ## 指定日志本
71
+ file_handler_super = RotatingFileHandler(
72
+ self.LOG_FILE_PATH.replace('.log','_s.log'),
67
73
  maxBytes=5 * 1024 * 1024, # 10 MB
68
74
  backupCount=5,
69
75
  encoding="utf-8",
70
76
  )
71
- file_handler_cri.setLevel(logging.CRITICAL) # 文件中显示所有指定级别的日志
72
- file_handler_cri.setFormatter(formatter)
73
- logger.addHandler(file_handler_cri)
74
- return logger
75
-
76
- def set_super_log(self,logger_info):
77
- self.super_log_level = logger_info
77
+ file_handler_super.setLevel(logging.CRITICAL) # 文件中显示所有指定级别的日志
78
+ file_handler_super.setFormatter(formatter)
79
+ logger.addHandler(file_handler_super)
80
+
81
+ # class ConfigFilter(logging.Filter):
82
+ # # 初始化的方案
83
+ # def __init__(self, config_value, name=''):
84
+ # super().__init__(name)
85
+ # self.config_value = config_value
78
86
 
79
- def super_log(self,s, target: str = "target",logger = None):
80
- logger = logger or self.super_log_level
81
- logger("\n" + "=="*25 + target +"=="*25 + f"\n type: {str(type(s))}" + f"\ncontent: {s}")
87
+ # def filter(self, record):
88
+ # record.config_info = self.config_value # 添加到LogRecord
89
+ # return True
82
90
 
91
+
92
+ # class CustomFilter(logging.Filter):
93
+ # def filter(self, record):
94
+ # # 添加自定义的用户ID
95
+ # print(record,'recordrecordrecordrecordrecord')
96
+ # record.user_id = os.getenv("CURRENT_USER_ID", "anonymous")
97
+ # # 添加会话ID
98
+ # # record.session_id = "SESSION_XYZ123" # 实际应用中可能从request或全局变量获取
99
+ # frame = inspect.currentframe()
100
+ # info = inspect.getframeinfo(frame)
101
+ # # logger.error(f"Function name: {info.function} : {e}")
102
+ # record.session_id = f"Function name: {info.function}"
103
+
104
+ # return True # 必须返回True才能继续处理该日志记录
105
+
106
+ # # 将自定义过滤器添加到处理器或记录器
107
+ # logger.addFilter(CustomFilter())
108
+ # handler.addFilter(CustomFilter()) # 也可以加到handler上
109
+
110
+ logger.info("这是一个包含自定义信息的日志")
111
+ return logger
112
+