staran 0.4.2__py3-none-any.whl → 0.6.0__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,350 @@
1
+ """
2
+ Schema文档生成器
3
+
4
+ 支持根据表结构定义生成多种格式的技术文档:
5
+ - Markdown格式:适合开发团队和版本控制
6
+ - PDF格式:适合正式交付和业务方审阅
7
+ - HTML格式:适合在线查看和分享
8
+
9
+ 主要功能:
10
+ 1. 表结构自动解析
11
+ 2. 字段信息格式化
12
+ 3. 业务含义说明
13
+ 4. 技术规范文档
14
+ 5. 多格式导出支持
15
+ """
16
+
17
+ import os
18
+ from typing import Dict, List, Optional
19
+ from datetime import datetime
20
+
21
+
22
+ class SchemaDocumentGenerator:
23
+ """表结构文档生成器"""
24
+
25
+ def __init__(self):
26
+ self.template_configs = {
27
+ 'markdown': {
28
+ 'extension': '.md',
29
+ 'header_template': self._get_markdown_header_template(),
30
+ 'field_template': self._get_markdown_field_template(),
31
+ 'footer_template': self._get_markdown_footer_template()
32
+ },
33
+ 'pdf': {
34
+ 'extension': '.pdf',
35
+ 'requires_conversion': True,
36
+ 'base_format': 'markdown' # 先生成MD再转PDF
37
+ },
38
+ 'html': {
39
+ 'extension': '.html',
40
+ 'header_template': self._get_html_header_template(),
41
+ 'field_template': self._get_html_field_template(),
42
+ 'footer_template': self._get_html_footer_template()
43
+ }
44
+ }
45
+
46
+ def export_schema_doc(self, schema, business_domain: str, table_type: str,
47
+ output_dir: str = "./docs", format_type: str = "markdown") -> str:
48
+ """
49
+ 导出表结构文档
50
+
51
+ Args:
52
+ schema: TableSchema对象
53
+ business_domain: 业务域名称 (如: AUM, CRM, RISK)
54
+ table_type: 表类型 (如: behavior, asset_avg)
55
+ output_dir: 输出目录
56
+ format_type: 文档格式 ('markdown', 'pdf', 'html')
57
+
58
+ Returns:
59
+ 生成的文档文件路径
60
+ """
61
+ # 确保输出目录存在
62
+ os.makedirs(output_dir, exist_ok=True)
63
+
64
+ # 生成文件名
65
+ timestamp = datetime.now().strftime("%Y%m%d")
66
+ filename = f"{business_domain}_{table_type}_schema_{timestamp}"
67
+
68
+ if format_type.lower() == 'pdf':
69
+ # PDF格式先生成Markdown再转换
70
+ md_content = self._generate_markdown_content(schema, business_domain, table_type)
71
+ md_path = os.path.join(output_dir, f"{filename}.md")
72
+
73
+ with open(md_path, 'w', encoding='utf-8') as f:
74
+ f.write(md_content)
75
+
76
+ # 转换为PDF (这里可以集成pandoc或其他转换工具)
77
+ pdf_path = os.path.join(output_dir, f"{filename}.pdf")
78
+ self._convert_md_to_pdf(md_path, pdf_path)
79
+ return pdf_path
80
+
81
+ elif format_type.lower() == 'html':
82
+ # HTML格式
83
+ html_content = self._generate_html_content(schema, business_domain, table_type)
84
+ html_path = os.path.join(output_dir, f"{filename}.html")
85
+
86
+ with open(html_path, 'w', encoding='utf-8') as f:
87
+ f.write(html_content)
88
+ return html_path
89
+
90
+ else:
91
+ # 默认Markdown格式
92
+ md_content = self._generate_markdown_content(schema, business_domain, table_type)
93
+ md_path = os.path.join(output_dir, f"{filename}.md")
94
+
95
+ with open(md_path, 'w', encoding='utf-8') as f:
96
+ f.write(md_content)
97
+ return md_path
98
+
99
+ def _generate_markdown_content(self, schema, business_domain: str, table_type: str) -> str:
100
+ """生成Markdown格式内容"""
101
+ content = []
102
+
103
+ # 文档头部
104
+ content.append(f"# {business_domain} - {table_type.upper()}表结构文档")
105
+ content.append("")
106
+ content.append(f"## 基本信息")
107
+ content.append("")
108
+ content.append(f"- **表名**: `{schema.table_name}`")
109
+ content.append(f"- **业务域**: {business_domain}")
110
+ content.append(f"- **表类型**: {table_type}")
111
+ content.append(f"- **生成时间**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
112
+ content.append(f"- **月度唯一性**: {'是' if getattr(schema, 'is_monthly_unique', False) else '否'}")
113
+ content.append("")
114
+
115
+ # 表结构说明
116
+ content.append("## 表结构说明")
117
+ content.append("")
118
+ if hasattr(schema, 'description'):
119
+ content.append(f"{schema.description}")
120
+ content.append("")
121
+
122
+ # 主键信息
123
+ if hasattr(schema, 'primary_key') and schema.primary_key:
124
+ content.append("### 主键字段")
125
+ content.append("")
126
+ content.append(f"- `{schema.primary_key}` (主键)")
127
+ content.append("")
128
+
129
+ # 日期字段
130
+ if hasattr(schema, 'date_field') and schema.date_field:
131
+ content.append("### 日期字段")
132
+ content.append("")
133
+ content.append(f"- `{schema.date_field}` (日期字段)")
134
+ content.append("")
135
+
136
+ # 字段详情表格
137
+ content.append("## 字段详情")
138
+ content.append("")
139
+ content.append("| 字段名 | 数据类型 | 业务含义 | 可聚合 | 备注 |")
140
+ content.append("|--------|----------|----------|--------|------|")
141
+
142
+ if hasattr(schema, 'fields'):
143
+ for field_name, field in schema.fields.items():
144
+ # 简化数据类型显示
145
+ field_type_str = str(field.field_type) if hasattr(field, 'field_type') else 'string'
146
+ field_type = field_type_str.replace('FieldType.', '').lower()
147
+ comment = field.comment if hasattr(field, 'comment') else ''
148
+ aggregatable = '是' if getattr(field, 'aggregatable', False) else '否'
149
+ remarks = '' # 可以从其他地方获取备注
150
+
151
+ content.append(f"| `{field_name}` | {field_type} | {comment} | {aggregatable} | {remarks} |")
152
+
153
+ content.append("")
154
+
155
+ # 业务规则说明
156
+ content.append("## 业务规则")
157
+ content.append("")
158
+ content.append("### 数据更新规则")
159
+ if getattr(schema, 'is_monthly_unique', False):
160
+ content.append("- 每人每月一条记录")
161
+ content.append("- 月末批量更新")
162
+ else:
163
+ content.append("- 每人每日一条记录")
164
+ content.append("- 日终批量更新")
165
+ content.append("")
166
+
167
+ content.append("### 数据质量要求")
168
+ content.append("- 主键字段不允许为空")
169
+ content.append("- 日期字段格式统一为YYYYMMDD")
170
+ content.append("- 金额字段精度保持2位小数")
171
+ content.append("- 比例字段取值范围[0,1]")
172
+ content.append("")
173
+
174
+ # 使用说明
175
+ content.append("## 使用说明")
176
+ content.append("")
177
+ content.append("### 特征工程配置")
178
+ if table_type == 'behavior':
179
+ content.append("- 生成原始拷贝特征")
180
+ content.append("- 生成聚合特征")
181
+ content.append("- 不生成环比、同比特征")
182
+ else:
183
+ content.append("- 生成聚合特征")
184
+ content.append("- 生成5个月环比特征")
185
+ content.append("- 生成1年同比特征")
186
+ content.append("")
187
+
188
+ content.append("### 示例SQL查询")
189
+ content.append("```sql")
190
+ content.append(f"-- 查询最新数据")
191
+ content.append(f"SELECT * FROM {schema.table_name}")
192
+ content.append(f"WHERE data_dt = (SELECT MAX(data_dt) FROM {schema.table_name})")
193
+ content.append(f"LIMIT 10;")
194
+ content.append("```")
195
+ content.append("")
196
+
197
+ # 文档尾部
198
+ content.append("---")
199
+ content.append("*本文档由Staran Schema自动生成*")
200
+
201
+ return "\n".join(content)
202
+
203
+ def _generate_html_content(self, schema, business_domain: str, table_type: str) -> str:
204
+ """生成HTML格式内容"""
205
+ # 基础HTML模板,可以根据需要扩展
206
+ html_content = f"""
207
+ <!DOCTYPE html>
208
+ <html lang="zh-CN">
209
+ <head>
210
+ <meta charset="UTF-8">
211
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
212
+ <title>{business_domain} - {table_type.upper()}表结构文档</title>
213
+ <style>
214
+ body {{ font-family: 'Microsoft YaHei', Arial, sans-serif; margin: 40px; }}
215
+ h1, h2, h3 {{ color: #333; }}
216
+ table {{ border-collapse: collapse; width: 100%; margin: 20px 0; }}
217
+ th, td {{ border: 1px solid #ddd; padding: 12px; text-align: left; }}
218
+ th {{ background-color: #f2f2f2; font-weight: bold; }}
219
+ code {{ background-color: #f4f4f4; padding: 2px 4px; border-radius: 3px; }}
220
+ .info-table {{ background-color: #f9f9f9; }}
221
+ </style>
222
+ </head>
223
+ <body>
224
+ <h1>{business_domain} - {table_type.upper()}表结构文档</h1>
225
+
226
+ <h2>基本信息</h2>
227
+ <table class="info-table">
228
+ <tr><th>表名</th><td><code>{schema.table_name}</code></td></tr>
229
+ <tr><th>业务域</th><td>{business_domain}</td></tr>
230
+ <tr><th>表类型</th><td>{table_type}</td></tr>
231
+ <tr><th>生成时间</th><td>{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}</td></tr>
232
+ <tr><th>月度唯一性</th><td>{'是' if getattr(schema, 'is_monthly_unique', False) else '否'}</td></tr>
233
+ </table>
234
+
235
+ <h2>字段详情</h2>
236
+ <table>
237
+ <thead>
238
+ <tr>
239
+ <th>字段名</th>
240
+ <th>数据类型</th>
241
+ <th>业务含义</th>
242
+ <th>可聚合</th>
243
+ <th>备注</th>
244
+ </tr>
245
+ </thead>
246
+ <tbody>
247
+ """
248
+
249
+ # 添加字段行
250
+ if hasattr(schema, 'fields'):
251
+ for field_name, field in schema.fields.items():
252
+ # 简化数据类型显示
253
+ field_type_str = str(field.field_type) if hasattr(field, 'field_type') else 'string'
254
+ field_type = field_type_str.replace('FieldType.', '').lower()
255
+ comment = field.comment if hasattr(field, 'comment') else ''
256
+ aggregatable = '是' if getattr(field, 'aggregatable', False) else '否'
257
+ remarks = '' # 可以从其他地方获取备注
258
+
259
+ html_content += f"""
260
+ <tr>
261
+ <td><code>{field_name}</code></td>
262
+ <td>{field_type}</td>
263
+ <td>{comment}</td>
264
+ <td>{aggregatable}</td>
265
+ <td>{remarks}</td>
266
+ </tr>"""
267
+
268
+ html_content += """
269
+ </tbody>
270
+ </table>
271
+
272
+ <hr>
273
+ <p><em>本文档由Staran Schema自动生成</em></p>
274
+ </body>
275
+ </html>"""
276
+
277
+ return html_content
278
+
279
+ def _convert_md_to_pdf(self, md_path: str, pdf_path: str):
280
+ """将Markdown转换为PDF (需要安装pandoc或其他转换工具)"""
281
+ try:
282
+ import subprocess
283
+ # 尝试使用pandoc转换
284
+ subprocess.run([
285
+ 'pandoc', md_path, '-o', pdf_path,
286
+ '--pdf-engine=xelatex',
287
+ '--variable=CJKmainfont:Microsoft YaHei'
288
+ ], check=True)
289
+ except (subprocess.CalledProcessError, FileNotFoundError):
290
+ # 如果pandoc不可用,创建一个说明文件
291
+ with open(pdf_path.replace('.pdf', '_conversion_note.txt'), 'w', encoding='utf-8') as f:
292
+ f.write(f"PDF转换说明:\\n")
293
+ f.write(f"原始Markdown文件:{md_path}\\n")
294
+ f.write(f"如需PDF格式,请安装pandoc工具:\\n")
295
+ f.write(f"pip install pandoc\\n")
296
+ f.write(f"或访问:https://pandoc.org/installing.html\\n")
297
+
298
+ def _get_markdown_header_template(self) -> str:
299
+ return "# {title}\\n\\n## 基本信息\\n\\n"
300
+
301
+ def _get_markdown_field_template(self) -> str:
302
+ return "| {name} | {type} | {comment} | {aggregatable} |\\n"
303
+
304
+ def _get_markdown_footer_template(self) -> str:
305
+ return "\\n---\\n*文档生成时间: {timestamp}*\\n"
306
+
307
+ def _get_html_header_template(self) -> str:
308
+ return "<h1>{title}</h1>\\n<h2>基本信息</h2>\\n"
309
+
310
+ def _get_html_field_template(self) -> str:
311
+ return "<tr><td>{name}</td><td>{type}</td><td>{comment}</td><td>{aggregatable}</td></tr>\\n"
312
+
313
+ def _get_html_footer_template(self) -> str:
314
+ return "<hr><p><em>文档生成时间: {timestamp}</em></p>\\n"
315
+
316
+
317
+ def export_business_docs(business_domain: str, schemas_dict: Dict, output_dir: str = "./docs",
318
+ format_type: str = "markdown") -> Dict[str, str]:
319
+ """
320
+ 批量导出业务域表结构文档
321
+
322
+ Args:
323
+ business_domain: 业务域名称
324
+ schemas_dict: 表结构字典 {table_type: schema}
325
+ output_dir: 输出目录
326
+ format_type: 文档格式
327
+
328
+ Returns:
329
+ 生成的文档文件路径字典
330
+ """
331
+ generator = SchemaDocumentGenerator()
332
+ results = {}
333
+
334
+ for table_type, schema in schemas_dict.items():
335
+ file_path = generator.export_schema_doc(
336
+ schema=schema,
337
+ business_domain=business_domain,
338
+ table_type=table_type,
339
+ output_dir=output_dir,
340
+ format_type=format_type
341
+ )
342
+ results[table_type] = file_path
343
+
344
+ return results
345
+
346
+
347
+ __all__ = [
348
+ 'SchemaDocumentGenerator',
349
+ 'export_business_docs'
350
+ ]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: staran
3
- Version: 0.4.2
3
+ Version: 0.6.0
4
4
  Summary: staran - 高性能Python工具库
5
5
  Home-page: https://github.com/starlxa/staran
6
6
  Author: StarAn
@@ -24,7 +24,7 @@ Dynamic: requires-dist
24
24
  Dynamic: requires-python
25
25
  Dynamic: summary
26
26
 
27
- # Star## ✨ v0.4.2 新特性
27
+ # Star## ✨ v0.6.0 新特性
28
28
 
29
29
  - 📋 **独立Schema模块** - 专门的表结构定义和管理模块
30
30
  - 📄 **文档自动生成** - 支持Markdown/PDF/HTML格式的技术文档生成
@@ -42,7 +42,7 @@ Dynamic: summary
42
42
 
43
43
  Staran是一个强大的特征工程和数据处理工具包,提供从数据到模型的完整解决方案。特别针对工银图灵平台优化,让特征工程和模型训练变得前所未有的简单。
44
44
 
45
- ## ✨ v0.4.2 新特性
45
+ ## ✨ v0.6.0 新特性
46
46
 
47
47
  - �️ **模块化引擎架构** - 独立的引擎模块,支持Spark、Hive、图灵平台
48
48
  - 🔧 **统一接口设计** - 所有引擎提供一致的SQL生成、执行和下载接口
@@ -361,7 +361,7 @@ tomorrow = date.add_days(1) # 202504 (智能处理)
361
361
 
362
362
  ```
363
363
  staran/
364
- ├── __init__.py # 主包入口,v0.4.2功能导出
364
+ ├── __init__.py # 主包入口,v0.6.0功能导出
365
365
  ├── schemas/ # 🆕 表结构定义与文档生成模块
366
366
  │ ├── __init__.py # Schema模块入口
367
367
  │ ├── document_generator.py # 文档生成器 (MD/PDF/HTML)
@@ -385,7 +385,7 @@ staran/
385
385
  │ ├── __init__.py # 工具模块
386
386
  │ └── date.py # Date类实现
387
387
  ├── setup.py # 安装配置
388
- ├── README.md # 本文档 v0.4.2
388
+ ├── README.md # 本文档 v0.6.0
389
389
  └── quick-upload.sh # 快速部署脚本
390
390
  ```
391
391
 
@@ -561,4 +561,4 @@ MIT License
561
561
 
562
562
  ---
563
563
 
564
- **Staran v0.4.2** - 模块化引擎架构,让机器学习特征工程变得前所未有的简单 🌟
564
+ **Staran v0.6.0** - 模块化引擎架构,让机器学习特征工程变得前所未有的简单 🌟
@@ -1,4 +1,6 @@
1
- staran/__init__.py,sha256=cBUxN-qmS_Bf8r-8k94VdA-OLvjdRZyxTNfgd-X_AE8,7234
1
+ staran/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ staran/banks/__init__.py,sha256=m4IUdFLXvNtgpmxDhKptCtALyaGkF1-T9hbNqdXczLI,544
3
+ staran/banks/xinjiang_icbc/__init__.py,sha256=Ql3gQFh1h4EwUdU3fePW1chV5iAegxjLWiPxbYa_J80,3131
2
4
  staran/engines/__init__.py,sha256=aQCpDxY_JcKlApEsEp2wg_P3IwNDTCFb7OYcLHiPPmk,1627
3
5
  staran/engines/base.py,sha256=IIN-QxPsO-q3KmQ3Lz0cB9bs6Oac0Wy5MIF605HrHVw,7969
4
6
  staran/engines/hive.py,sha256=-KwZiAvK5cxwnoyYQlqGWrcZkeKhbd8QCX3chpbezd0,5894
@@ -12,13 +14,20 @@ staran/features/engines.py,sha256=kqdS2xjmCVi0Xz1Oc3WaTMIavgAriX8F7VvUgVcpfqo,10
12
14
  staran/features/generator.py,sha256=CI1F_PshOvokQJelsqSaVp-SNQpMc-WVmjMQKzgdeLw,23114
13
15
  staran/features/manager.py,sha256=2-3Hc3qthtyzwiuQy5QTz6RfhKK3szoylconzI3moc4,5201
14
16
  staran/features/schema.py,sha256=FwOfpTcxq4K8zkO3MFNqKPQBp_e8qY-N6gazqm9_lAQ,6067
15
- staran/schemas/__init__.py,sha256=2RkcWCaIkrOHd37zzRCla0-jNg4cPnc6BGmmW5Vha0Y,652
17
+ staran/models/__init__.py,sha256=VbfrRjmnp8KlFSEZOa-buECAaERptzAnvUUZK9dpgtY,2390
18
+ staran/models/bank_configs.py,sha256=wN3GA_8cb5wevDC-sWRcJ3lMuaHahZVjC85K_t2aQt0,8177
19
+ staran/models/config.py,sha256=fTbZtJq4-ZuCSSd1eW7TkIbEdDyZv2agHJCYnwOCJ_s,8886
20
+ staran/models/daifa_models.py,sha256=J7aqK41NDMDjacsjmxqwyuJfgf1kJx-Kaxj5CGQLISE,13166
21
+ staran/models/registry.py,sha256=Zeey4TtbHtJ40odyZQzOLijyZCmlMBRuniPk_znS2Q8,10223
22
+ staran/models/target.py,sha256=gKTTatxvOJjmE50qD6G6mhlYLuZL3Cvn3FLNbXl1eeU,10531
23
+ staran/schemas/__init__.py,sha256=ztrBlQ3irbgM7gHB_dhiLEX1ZpDX2AAWOeiPnZTe-sk,779
16
24
  staran/schemas/document_generator.py,sha256=Mr7TjmKwspqxXnp9DhzZxsRx0l2Bo7MOI8mOxRtgwxU,13600
17
- staran/schemas/aum/__init__.py,sha256=jVkmJdhHGHdGE4rJ605zsRU2zIQMEHWnlgW2ZQk8AdU,13082
25
+ staran/schemas/aum/__init__.py,sha256=z0cuC6A3z-1cPKMDYrn0wCumjKkpk_0kfqGfW1JNEbc,9815
18
26
  staran/tools/__init__.py,sha256=KtudrYnxKD9HZEL4H-mrWlKrmsI3rYjJrLeC9YDTpG4,1054
19
27
  staran/tools/date.py,sha256=-QyEMWVx6czMuOIwcV7kR3gBMRVOwb5qevo7GEFSJKE,10488
20
- staran-0.4.2.dist-info/licenses/LICENSE,sha256=2EmsBIyDCono4iVXNpv5_px9qt2b7hfPq1WuyGVMNP4,1361
21
- staran-0.4.2.dist-info/METADATA,sha256=u8_IU7kGJqbFbKZLXUIgACqklcrSp56UWcawoWAtGtY,18809
22
- staran-0.4.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
23
- staran-0.4.2.dist-info/top_level.txt,sha256=NOUZtXSh5oSIEjHrC0lQ9WmoKtD010Q00dghWyag-Zs,7
24
- staran-0.4.2.dist-info/RECORD,,
28
+ staran/tools/document_generator.py,sha256=Mr7TjmKwspqxXnp9DhzZxsRx0l2Bo7MOI8mOxRtgwxU,13600
29
+ staran-0.6.0.dist-info/licenses/LICENSE,sha256=2EmsBIyDCono4iVXNpv5_px9qt2b7hfPq1WuyGVMNP4,1361
30
+ staran-0.6.0.dist-info/METADATA,sha256=KTBVO9J_Z20Nya-Mj48lXDTUNjWRfbU9wwo81__y7fk,18809
31
+ staran-0.6.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
32
+ staran-0.6.0.dist-info/top_level.txt,sha256=NOUZtXSh5oSIEjHrC0lQ9WmoKtD010Q00dghWyag-Zs,7
33
+ staran-0.6.0.dist-info/RECORD,,
File without changes