staran 0.6.1__py3-none-any.whl → 1.0.1__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.
- staran/__init__.py +10 -0
- staran/tools/__init__.py +6 -6
- staran/tools/date.py +327 -222
- staran/tools/tests/__init__.py +119 -0
- staran/tools/tests/run_tests.py +241 -0
- staran/tools/tests/test_api_compatibility.py +319 -0
- staran/tools/tests/test_date.py +565 -0
- staran/tools/tests/test_logging.py +402 -0
- staran-1.0.1.dist-info/METADATA +37 -0
- staran-1.0.1.dist-info/RECORD +13 -0
- staran/banks/__init__.py +0 -30
- staran/banks/xinjiang_icbc/__init__.py +0 -90
- staran/engines/__init__.py +0 -65
- staran/engines/base.py +0 -255
- staran/engines/hive.py +0 -163
- staran/engines/spark.py +0 -252
- staran/engines/turing.py +0 -439
- staran/features/__init__.py +0 -59
- staran/features/engines.py +0 -284
- staran/features/generator.py +0 -603
- staran/features/manager.py +0 -155
- staran/features/schema.py +0 -193
- staran/models/__init__.py +0 -72
- staran/models/config.py +0 -271
- staran/models/daifa_models.py +0 -361
- staran/models/registry.py +0 -281
- staran/models/target.py +0 -321
- staran/schemas/__init__.py +0 -27
- staran/schemas/aum/__init__.py +0 -210
- staran/tools/document_generator.py +0 -350
- staran-0.6.1.dist-info/METADATA +0 -586
- staran-0.6.1.dist-info/RECORD +0 -28
- {staran-0.6.1.dist-info → staran-1.0.1.dist-info}/WHEEL +0 -0
- {staran-0.6.1.dist-info → staran-1.0.1.dist-info}/licenses/LICENSE +0 -0
- {staran-0.6.1.dist-info → staran-1.0.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,402 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
|
4
|
+
"""
|
5
|
+
日志系统测试
|
6
|
+
==========
|
7
|
+
|
8
|
+
测试Date类的日志功能,包括:
|
9
|
+
- 日志级别设置
|
10
|
+
- 日志消息记录
|
11
|
+
- 日志输出控制
|
12
|
+
- 性能日志
|
13
|
+
"""
|
14
|
+
|
15
|
+
import unittest
|
16
|
+
import sys
|
17
|
+
import os
|
18
|
+
import logging
|
19
|
+
import io
|
20
|
+
from contextlib import redirect_stderr
|
21
|
+
|
22
|
+
# 添加项目根目录到路径
|
23
|
+
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', '..'))
|
24
|
+
|
25
|
+
from staran.tools.date import Date
|
26
|
+
|
27
|
+
|
28
|
+
class TestLoggingSystem(unittest.TestCase):
|
29
|
+
"""测试日志系统基本功能"""
|
30
|
+
|
31
|
+
def setUp(self):
|
32
|
+
"""设置测试环境"""
|
33
|
+
# 重置日志级别
|
34
|
+
Date.set_log_level(logging.DEBUG)
|
35
|
+
|
36
|
+
# 创建字符串流来捕获日志输出
|
37
|
+
self.log_stream = io.StringIO()
|
38
|
+
|
39
|
+
# 获取Date的日志记录器
|
40
|
+
self.logger = logging.getLogger('staran.tools.date')
|
41
|
+
|
42
|
+
# 清除现有的处理器
|
43
|
+
for handler in self.logger.handlers[:]:
|
44
|
+
self.logger.removeHandler(handler)
|
45
|
+
|
46
|
+
# 添加流处理器
|
47
|
+
self.handler = logging.StreamHandler(self.log_stream)
|
48
|
+
self.handler.setLevel(logging.DEBUG)
|
49
|
+
formatter = logging.Formatter('%(levelname)s:%(name)s:%(message)s')
|
50
|
+
self.handler.setFormatter(formatter)
|
51
|
+
self.logger.addHandler(self.handler)
|
52
|
+
self.logger.setLevel(logging.DEBUG)
|
53
|
+
|
54
|
+
def tearDown(self):
|
55
|
+
"""清理测试环境"""
|
56
|
+
# 移除处理器
|
57
|
+
self.logger.removeHandler(self.handler)
|
58
|
+
self.handler.close()
|
59
|
+
|
60
|
+
# 重置日志级别为ERROR,避免干扰其他测试
|
61
|
+
Date.set_log_level(logging.ERROR)
|
62
|
+
|
63
|
+
def get_log_output(self):
|
64
|
+
"""获取日志输出"""
|
65
|
+
return self.log_stream.getvalue()
|
66
|
+
|
67
|
+
def test_log_level_setting(self):
|
68
|
+
"""测试日志级别设置"""
|
69
|
+
# 测试设置不同的日志级别
|
70
|
+
Date.set_log_level(logging.INFO)
|
71
|
+
Date.set_log_level(logging.WARNING)
|
72
|
+
Date.set_log_level(logging.ERROR)
|
73
|
+
Date.set_log_level(logging.DEBUG)
|
74
|
+
|
75
|
+
# 验证级别设置成功(通过创建对象来触发日志)
|
76
|
+
self.log_stream.truncate(0)
|
77
|
+
self.log_stream.seek(0)
|
78
|
+
|
79
|
+
Date('20250415')
|
80
|
+
log_output = self.get_log_output()
|
81
|
+
|
82
|
+
# 应该有DEBUG级别的日志
|
83
|
+
self.assertIn('DEBUG', log_output)
|
84
|
+
|
85
|
+
def test_object_creation_logging(self):
|
86
|
+
"""测试对象创建日志"""
|
87
|
+
self.log_stream.truncate(0)
|
88
|
+
self.log_stream.seek(0)
|
89
|
+
|
90
|
+
# 创建不同类型的Date对象
|
91
|
+
Date('20250415')
|
92
|
+
Date('202504')
|
93
|
+
Date('2025')
|
94
|
+
Date(2025, 4, 15)
|
95
|
+
|
96
|
+
log_output = self.get_log_output()
|
97
|
+
|
98
|
+
# 验证有创建日志
|
99
|
+
self.assertIn('创建Date对象', log_output)
|
100
|
+
self.assertIn('20250415', log_output)
|
101
|
+
|
102
|
+
def test_method_call_logging(self):
|
103
|
+
"""测试方法调用日志"""
|
104
|
+
self.log_stream.truncate(0)
|
105
|
+
self.log_stream.seek(0)
|
106
|
+
|
107
|
+
date = Date('20250415')
|
108
|
+
|
109
|
+
# 调用各种方法
|
110
|
+
date.format_iso()
|
111
|
+
date.add_days(10)
|
112
|
+
date.get_weekday()
|
113
|
+
date.is_weekend()
|
114
|
+
|
115
|
+
log_output = self.get_log_output()
|
116
|
+
|
117
|
+
# 验证有方法调用日志
|
118
|
+
self.assertIn('调用方法', log_output)
|
119
|
+
|
120
|
+
def test_error_logging(self):
|
121
|
+
"""测试错误日志"""
|
122
|
+
self.log_stream.truncate(0)
|
123
|
+
self.log_stream.seek(0)
|
124
|
+
|
125
|
+
# 触发错误
|
126
|
+
try:
|
127
|
+
Date('invalid_date')
|
128
|
+
except ValueError:
|
129
|
+
pass
|
130
|
+
|
131
|
+
log_output = self.get_log_output()
|
132
|
+
|
133
|
+
# 验证有错误日志
|
134
|
+
self.assertIn('ERROR', log_output)
|
135
|
+
|
136
|
+
def test_performance_logging(self):
|
137
|
+
"""测试性能日志"""
|
138
|
+
self.log_stream.truncate(0)
|
139
|
+
self.log_stream.seek(0)
|
140
|
+
|
141
|
+
date = Date('20250415')
|
142
|
+
|
143
|
+
# 执行一些计算密集的操作
|
144
|
+
for i in range(10):
|
145
|
+
date.add_days(i)
|
146
|
+
|
147
|
+
log_output = self.get_log_output()
|
148
|
+
|
149
|
+
# 性能日志可能不会每次都出现,但应该有调用日志
|
150
|
+
self.assertIn('调用方法', log_output)
|
151
|
+
|
152
|
+
|
153
|
+
class TestLoggingConfiguration(unittest.TestCase):
|
154
|
+
"""测试日志配置"""
|
155
|
+
|
156
|
+
def setUp(self):
|
157
|
+
"""设置测试环境"""
|
158
|
+
Date.set_log_level(logging.ERROR) # 默认高级别
|
159
|
+
|
160
|
+
def test_log_level_effects(self):
|
161
|
+
"""测试日志级别效果"""
|
162
|
+
# 创建测试流
|
163
|
+
log_stream = io.StringIO()
|
164
|
+
logger = logging.getLogger('staran.tools.date')
|
165
|
+
|
166
|
+
# 清除现有处理器
|
167
|
+
for handler in logger.handlers[:]:
|
168
|
+
logger.removeHandler(handler)
|
169
|
+
|
170
|
+
# 添加新处理器
|
171
|
+
handler = logging.StreamHandler(log_stream)
|
172
|
+
handler.setLevel(logging.DEBUG)
|
173
|
+
formatter = logging.Formatter('%(levelname)s:%(message)s')
|
174
|
+
handler.setFormatter(formatter)
|
175
|
+
logger.addHandler(handler)
|
176
|
+
|
177
|
+
try:
|
178
|
+
# 测试ERROR级别
|
179
|
+
Date.set_log_level(logging.ERROR)
|
180
|
+
logger.setLevel(logging.ERROR)
|
181
|
+
|
182
|
+
log_stream.truncate(0)
|
183
|
+
log_stream.seek(0)
|
184
|
+
|
185
|
+
Date('20250415')
|
186
|
+
error_output = log_stream.getvalue()
|
187
|
+
|
188
|
+
# 测试DEBUG级别
|
189
|
+
Date.set_log_level(logging.DEBUG)
|
190
|
+
logger.setLevel(logging.DEBUG)
|
191
|
+
|
192
|
+
log_stream.truncate(0)
|
193
|
+
log_stream.seek(0)
|
194
|
+
|
195
|
+
Date('20250415')
|
196
|
+
debug_output = log_stream.getvalue()
|
197
|
+
|
198
|
+
# DEBUG级别应该有更多输出
|
199
|
+
self.assertGreaterEqual(len(debug_output), len(error_output))
|
200
|
+
|
201
|
+
finally:
|
202
|
+
logger.removeHandler(handler)
|
203
|
+
handler.close()
|
204
|
+
|
205
|
+
def test_log_message_format(self):
|
206
|
+
"""测试日志消息格式"""
|
207
|
+
log_stream = io.StringIO()
|
208
|
+
logger = logging.getLogger('staran.tools.date')
|
209
|
+
|
210
|
+
# 清除现有处理器
|
211
|
+
for handler in logger.handlers[:]:
|
212
|
+
logger.removeHandler(handler)
|
213
|
+
|
214
|
+
handler = logging.StreamHandler(log_stream)
|
215
|
+
handler.setLevel(logging.DEBUG)
|
216
|
+
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
217
|
+
handler.setFormatter(formatter)
|
218
|
+
logger.addHandler(handler)
|
219
|
+
logger.setLevel(logging.DEBUG)
|
220
|
+
|
221
|
+
try:
|
222
|
+
Date.set_log_level(logging.DEBUG)
|
223
|
+
|
224
|
+
Date('20250415')
|
225
|
+
output = log_stream.getvalue()
|
226
|
+
|
227
|
+
# 验证日志格式包含时间戳、名称、级别、消息
|
228
|
+
if output: # 如果有输出
|
229
|
+
lines = output.strip().split('\n')
|
230
|
+
for line in lines:
|
231
|
+
parts = line.split(' - ')
|
232
|
+
if len(parts) >= 4:
|
233
|
+
self.assertIn('staran.tools.date', parts[1])
|
234
|
+
self.assertIn(parts[2], ['DEBUG', 'INFO', 'WARNING', 'ERROR'])
|
235
|
+
|
236
|
+
finally:
|
237
|
+
logger.removeHandler(handler)
|
238
|
+
handler.close()
|
239
|
+
|
240
|
+
|
241
|
+
class TestLoggingIntegration(unittest.TestCase):
|
242
|
+
"""测试日志集成"""
|
243
|
+
|
244
|
+
def setUp(self):
|
245
|
+
"""设置测试环境"""
|
246
|
+
Date.set_log_level(logging.WARNING)
|
247
|
+
|
248
|
+
def test_logging_with_various_operations(self):
|
249
|
+
"""测试各种操作的日志集成"""
|
250
|
+
log_stream = io.StringIO()
|
251
|
+
logger = logging.getLogger('staran.tools.date')
|
252
|
+
|
253
|
+
# 清除现有处理器
|
254
|
+
for handler in logger.handlers[:]:
|
255
|
+
logger.removeHandler(handler)
|
256
|
+
|
257
|
+
handler = logging.StreamHandler(log_stream)
|
258
|
+
handler.setLevel(logging.DEBUG)
|
259
|
+
formatter = logging.Formatter('%(levelname)s:%(funcName)s:%(message)s')
|
260
|
+
handler.setFormatter(formatter)
|
261
|
+
logger.addHandler(handler)
|
262
|
+
logger.setLevel(logging.DEBUG)
|
263
|
+
|
264
|
+
try:
|
265
|
+
Date.set_log_level(logging.DEBUG)
|
266
|
+
|
267
|
+
# 执行各种操作
|
268
|
+
date = Date('20250415')
|
269
|
+
date.format_iso()
|
270
|
+
date.add_days(10)
|
271
|
+
date.get_weekday()
|
272
|
+
result = date.is_weekend()
|
273
|
+
|
274
|
+
output = log_stream.getvalue()
|
275
|
+
|
276
|
+
# 验证不同操作都有日志记录
|
277
|
+
if output:
|
278
|
+
self.assertIsInstance(output, str)
|
279
|
+
# 基本验证日志不为空
|
280
|
+
self.assertGreater(len(output.strip()), 0)
|
281
|
+
|
282
|
+
finally:
|
283
|
+
logger.removeHandler(handler)
|
284
|
+
handler.close()
|
285
|
+
|
286
|
+
def test_logging_performance_impact(self):
|
287
|
+
"""测试日志对性能的影响"""
|
288
|
+
import time
|
289
|
+
|
290
|
+
# 测试无日志性能
|
291
|
+
Date.set_log_level(logging.CRITICAL)
|
292
|
+
|
293
|
+
start_time = time.time()
|
294
|
+
for i in range(100):
|
295
|
+
date = Date('20250415')
|
296
|
+
date.add_days(i % 10)
|
297
|
+
no_log_time = time.time() - start_time
|
298
|
+
|
299
|
+
# 测试有日志性能
|
300
|
+
Date.set_log_level(logging.DEBUG)
|
301
|
+
|
302
|
+
start_time = time.time()
|
303
|
+
for i in range(100):
|
304
|
+
date = Date('20250415')
|
305
|
+
date.add_days(i % 10)
|
306
|
+
with_log_time = time.time() - start_time
|
307
|
+
|
308
|
+
# 日志不应该显著影响性能(这里允许10倍的性能差异)
|
309
|
+
self.assertLess(with_log_time, no_log_time * 10)
|
310
|
+
|
311
|
+
# 重置日志级别
|
312
|
+
Date.set_log_level(logging.ERROR)
|
313
|
+
|
314
|
+
|
315
|
+
class TestLoggingEdgeCases(unittest.TestCase):
|
316
|
+
"""测试日志边缘情况"""
|
317
|
+
|
318
|
+
def setUp(self):
|
319
|
+
"""设置测试环境"""
|
320
|
+
Date.set_log_level(logging.ERROR)
|
321
|
+
|
322
|
+
def test_logging_with_invalid_operations(self):
|
323
|
+
"""测试无效操作的日志"""
|
324
|
+
log_stream = io.StringIO()
|
325
|
+
logger = logging.getLogger('staran.tools.date')
|
326
|
+
|
327
|
+
# 清除现有处理器
|
328
|
+
for handler in logger.handlers[:]:
|
329
|
+
logger.removeHandler(handler)
|
330
|
+
|
331
|
+
handler = logging.StreamHandler(log_stream)
|
332
|
+
handler.setLevel(logging.DEBUG)
|
333
|
+
formatter = logging.Formatter('%(levelname)s:%(message)s')
|
334
|
+
handler.setFormatter(formatter)
|
335
|
+
logger.addHandler(handler)
|
336
|
+
logger.setLevel(logging.DEBUG)
|
337
|
+
|
338
|
+
try:
|
339
|
+
Date.set_log_level(logging.DEBUG)
|
340
|
+
|
341
|
+
# 尝试无效操作
|
342
|
+
try:
|
343
|
+
Date('invalid')
|
344
|
+
except ValueError:
|
345
|
+
pass
|
346
|
+
|
347
|
+
try:
|
348
|
+
Date(2025, 13, 1) # 无效月份
|
349
|
+
except ValueError:
|
350
|
+
pass
|
351
|
+
|
352
|
+
output = log_stream.getvalue()
|
353
|
+
|
354
|
+
# 应该有错误日志
|
355
|
+
if output:
|
356
|
+
self.assertIn('ERROR', output)
|
357
|
+
|
358
|
+
finally:
|
359
|
+
logger.removeHandler(handler)
|
360
|
+
handler.close()
|
361
|
+
|
362
|
+
def test_concurrent_logging(self):
|
363
|
+
"""测试并发日志"""
|
364
|
+
import threading
|
365
|
+
import time
|
366
|
+
|
367
|
+
Date.set_log_level(logging.DEBUG)
|
368
|
+
|
369
|
+
results = []
|
370
|
+
|
371
|
+
def create_dates():
|
372
|
+
for i in range(10):
|
373
|
+
try:
|
374
|
+
date = Date(f'2025041{i % 10}')
|
375
|
+
results.append(str(date))
|
376
|
+
except:
|
377
|
+
pass
|
378
|
+
|
379
|
+
# 创建多个线程
|
380
|
+
threads = []
|
381
|
+
for i in range(5):
|
382
|
+
thread = threading.Thread(target=create_dates)
|
383
|
+
threads.append(thread)
|
384
|
+
|
385
|
+
# 启动所有线程
|
386
|
+
for thread in threads:
|
387
|
+
thread.start()
|
388
|
+
|
389
|
+
# 等待所有线程完成
|
390
|
+
for thread in threads:
|
391
|
+
thread.join()
|
392
|
+
|
393
|
+
# 验证结果
|
394
|
+
self.assertGreater(len(results), 0)
|
395
|
+
|
396
|
+
# 重置日志级别
|
397
|
+
Date.set_log_level(logging.ERROR)
|
398
|
+
|
399
|
+
|
400
|
+
if __name__ == '__main__':
|
401
|
+
# 运行所有日志测试
|
402
|
+
unittest.main(verbosity=2)
|
@@ -0,0 +1,37 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: staran
|
3
|
+
Version: 1.0.1
|
4
|
+
Summary: staran - 轻量级Python日期工具库
|
5
|
+
Home-page: https://github.com/starlxa/staran
|
6
|
+
Author: StarAn
|
7
|
+
Author-email: starlxa@icloud.com
|
8
|
+
License: MIT
|
9
|
+
Project-URL: Bug Reports, https://github.com/starlxa/staran/issues
|
10
|
+
Project-URL: Source, https://github.com/starlxa/staran
|
11
|
+
Keywords: date datetime utilities time-processing
|
12
|
+
Classifier: Development Status :: 5 - Production/Stable
|
13
|
+
Classifier: Intended Audience :: Developers
|
14
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
15
|
+
Classifier: Topic :: Utilities
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
17
|
+
Classifier: Programming Language :: Python :: 3.7
|
18
|
+
Classifier: Programming Language :: Python :: 3.8
|
19
|
+
Classifier: Programming Language :: Python :: 3.9
|
20
|
+
Classifier: Programming Language :: Python :: 3.10
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
23
|
+
Classifier: Operating System :: OS Independent
|
24
|
+
Requires-Python: >=3.7
|
25
|
+
Description-Content-Type: text/markdown
|
26
|
+
License-File: LICENSE
|
27
|
+
Dynamic: author
|
28
|
+
Dynamic: author-email
|
29
|
+
Dynamic: classifier
|
30
|
+
Dynamic: description-content-type
|
31
|
+
Dynamic: home-page
|
32
|
+
Dynamic: keywords
|
33
|
+
Dynamic: license
|
34
|
+
Dynamic: license-file
|
35
|
+
Dynamic: project-url
|
36
|
+
Dynamic: requires-python
|
37
|
+
Dynamic: summary
|
@@ -0,0 +1,13 @@
|
|
1
|
+
staran/__init__.py,sha256=KBMMJN15kcGQLCOVUqfGf7UnuJs3_HFOXZq7SLlSF_U,208
|
2
|
+
staran/tools/__init__.py,sha256=lSEZeU6pp9smeiuVS3eYci203IFYBode0vUU5GeYb8w,1061
|
3
|
+
staran/tools/date.py,sha256=zZz9W94jed_KYgRnnPTaG8zyDD99UJdqwa0A5C_EyOw,14208
|
4
|
+
staran/tools/tests/__init__.py,sha256=s8WYc5XhtK7saVOeYyY85lmeLNoB8qpfbxZYSVEMfxs,3068
|
5
|
+
staran/tools/tests/run_tests.py,sha256=i-IjimWMOLDD4XZY-Tr1GNXV6yX01-7TjKiYKjB186A,7904
|
6
|
+
staran/tools/tests/test_api_compatibility.py,sha256=wmmM6f7nrS9J-b70xIltmtaIbiLALYCmaCsV4_wTxbE,11942
|
7
|
+
staran/tools/tests/test_date.py,sha256=8vVe0QyRSfPqvGK0WBhmOAs03MGjDlnw-fxYV5Wjv6Q,18429
|
8
|
+
staran/tools/tests/test_logging.py,sha256=VdoD8PJoKob01yQ93asQHz9Zo69jNfyq6jKtNSEi8UM,12041
|
9
|
+
staran-1.0.1.dist-info/licenses/LICENSE,sha256=2EmsBIyDCono4iVXNpv5_px9qt2b7hfPq1WuyGVMNP4,1361
|
10
|
+
staran-1.0.1.dist-info/METADATA,sha256=gx3O-5bO2L3hdJ1JgVDJuOwIh2X9VC_xL58g_pIbmfc,1295
|
11
|
+
staran-1.0.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
12
|
+
staran-1.0.1.dist-info/top_level.txt,sha256=NOUZtXSh5oSIEjHrC0lQ9WmoKtD010Q00dghWyag-Zs,7
|
13
|
+
staran-1.0.1.dist-info/RECORD,,
|
staran/banks/__init__.py
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
staran.banks - 银行配置模块
|
3
|
-
|
4
|
-
该模块包含不同银行的特定配置,包括:
|
5
|
-
- 数据库连接配置
|
6
|
-
- 表结构定义
|
7
|
-
- 业务规则设置
|
8
|
-
- 模型配置
|
9
|
-
|
10
|
-
支持的银行:
|
11
|
-
- xinjiang_icbc: 新疆工行配置
|
12
|
-
|
13
|
-
版本: 0.6.0
|
14
|
-
"""
|
15
|
-
|
16
|
-
from .xinjiang_icbc import (
|
17
|
-
XinjiangICBCConfig,
|
18
|
-
get_xinjiang_icbc_tables,
|
19
|
-
get_xinjiang_icbc_models,
|
20
|
-
xinjiang_icbc_config
|
21
|
-
)
|
22
|
-
|
23
|
-
__all__ = [
|
24
|
-
'XinjiangICBCConfig',
|
25
|
-
'xinjiang_icbc_config',
|
26
|
-
'get_xinjiang_icbc_tables',
|
27
|
-
'get_xinjiang_icbc_models'
|
28
|
-
]
|
29
|
-
|
30
|
-
__version__ = "0.6.0"
|
@@ -1,90 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
新疆工行银行配置模块
|
3
|
-
|
4
|
-
专门针对新疆工行代发长尾客户的配置:
|
5
|
-
- 数据库表结构定义(代发长尾客户专用)
|
6
|
-
- 业务规则配置
|
7
|
-
- 模型配置(提升模型和防流失模型)
|
8
|
-
|
9
|
-
数据库: xinjiang_icbc_daifa_longtail
|
10
|
-
业务范围: 代发长尾客户
|
11
|
-
"""
|
12
|
-
|
13
|
-
from dataclasses import dataclass
|
14
|
-
from typing import Dict, List, Optional
|
15
|
-
from datetime import datetime
|
16
|
-
|
17
|
-
|
18
|
-
@dataclass
|
19
|
-
class XinjiangICBCConfig:
|
20
|
-
"""新疆工行配置类"""
|
21
|
-
|
22
|
-
# 数据库配置
|
23
|
-
database_name: str = "xinjiang_icbc_daifa_longtail"
|
24
|
-
schema_name: str = "daifa_longtail"
|
25
|
-
|
26
|
-
# 业务配置
|
27
|
-
business_domain: str = "代发长尾客户"
|
28
|
-
customer_segment: str = "代发长尾"
|
29
|
-
|
30
|
-
# 模型配置
|
31
|
-
available_models: List[str] = None
|
32
|
-
|
33
|
-
# 业务规则
|
34
|
-
longtail_asset_min: float = 10000 # 长尾客户最小资产
|
35
|
-
longtail_asset_max: float = 100000 # 长尾客户最大资产
|
36
|
-
upgrade_target: float = 3000 # 提升目标金额
|
37
|
-
churn_threshold: float = 1500 # 流失阈值金额
|
38
|
-
|
39
|
-
def __post_init__(self):
|
40
|
-
if self.available_models is None:
|
41
|
-
self.available_models = [
|
42
|
-
"daifa_longtail_upgrade_3k", # 代发长尾提升3k模型
|
43
|
-
"daifa_longtail_churn_1_5k" # 代发长尾防流失1.5k模型
|
44
|
-
]
|
45
|
-
|
46
|
-
|
47
|
-
def get_xinjiang_icbc_tables() -> Dict[str, str]:
|
48
|
-
"""获取新疆工行代发长尾客户表配置"""
|
49
|
-
return {
|
50
|
-
# 代发长尾客户行为表
|
51
|
-
"daifa_longtail_behavior": "xinjiang_icbc_daifa_hlwj_dfcw_f1_f4_wy",
|
52
|
-
|
53
|
-
# 代发长尾客户资产平均表
|
54
|
-
"daifa_longtail_asset_avg": "xinjiang_icbc_daifa_hlwj_zi_chan_avg_wy",
|
55
|
-
|
56
|
-
# 代发长尾客户资产配置表
|
57
|
-
"daifa_longtail_asset_config": "xinjiang_icbc_daifa_hlwj_zi_chan_config_wy",
|
58
|
-
|
59
|
-
# 代发长尾客户月度统计表
|
60
|
-
"daifa_longtail_monthly_stat": "xinjiang_icbc_daifa_hlwj_monthly_stat_wy"
|
61
|
-
}
|
62
|
-
|
63
|
-
|
64
|
-
def get_xinjiang_icbc_models() -> Dict[str, Dict]:
|
65
|
-
"""获取新疆工行代发长尾客户模型配置"""
|
66
|
-
return {
|
67
|
-
"daifa_longtail_upgrade_3k": {
|
68
|
-
"name": "代发长尾客户提升3k预测模型",
|
69
|
-
"description": "预测下个月代发长尾客户资产提升3000元的概率",
|
70
|
-
"target": "upgrade_3k_next_month",
|
71
|
-
"model_type": "binary_classification",
|
72
|
-
"business_objective": "识别有潜力提升资产的代发长尾客户",
|
73
|
-
"target_threshold": 3000,
|
74
|
-
"prediction_window": "1_month"
|
75
|
-
},
|
76
|
-
|
77
|
-
"daifa_longtail_churn_1_5k": {
|
78
|
-
"name": "代发长尾客户防流失1.5k预测模型",
|
79
|
-
"description": "预测下个月代发长尾客户流失1500元资产的风险",
|
80
|
-
"target": "churn_1_5k_next_month",
|
81
|
-
"model_type": "binary_classification",
|
82
|
-
"business_objective": "识别有流失风险的代发长尾客户",
|
83
|
-
"target_threshold": 1500,
|
84
|
-
"prediction_window": "1_month"
|
85
|
-
}
|
86
|
-
}
|
87
|
-
|
88
|
-
|
89
|
-
# 创建默认配置实例
|
90
|
-
xinjiang_icbc_config = XinjiangICBCConfig()
|
staran/engines/__init__.py
DELETED
@@ -1,65 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
# -*- coding: utf-8 -*-
|
3
|
-
|
4
|
-
"""
|
5
|
-
数据库引擎模块
|
6
|
-
提供统一的数据库引擎接口
|
7
|
-
"""
|
8
|
-
|
9
|
-
# 基础组件
|
10
|
-
from .base import BaseEngine, DatabaseType
|
11
|
-
|
12
|
-
# 具体引擎实现
|
13
|
-
from .spark import SparkEngine
|
14
|
-
from .hive import HiveEngine
|
15
|
-
|
16
|
-
# 图灵平台引擎 (可选导入)
|
17
|
-
try:
|
18
|
-
from .turing import TuringEngine, create_turing_engine
|
19
|
-
_TURING_AVAILABLE = True
|
20
|
-
except ImportError:
|
21
|
-
TuringEngine = None
|
22
|
-
create_turing_engine = None
|
23
|
-
_TURING_AVAILABLE = False
|
24
|
-
|
25
|
-
# 便捷创建函数
|
26
|
-
def create_engine(engine_type: str, database_name: str, **kwargs) -> BaseEngine:
|
27
|
-
"""
|
28
|
-
创建数据库引擎的便捷函数
|
29
|
-
|
30
|
-
Args:
|
31
|
-
engine_type: 引擎类型 ('spark', 'hive', 'turing')
|
32
|
-
database_name: 数据库名称
|
33
|
-
**kwargs: 其他参数
|
34
|
-
|
35
|
-
Returns:
|
36
|
-
数据库引擎实例
|
37
|
-
"""
|
38
|
-
engine_type = engine_type.lower()
|
39
|
-
|
40
|
-
if engine_type == 'spark':
|
41
|
-
return SparkEngine(database_name, **kwargs)
|
42
|
-
elif engine_type == 'hive':
|
43
|
-
return HiveEngine(database_name, **kwargs)
|
44
|
-
elif engine_type == 'turing':
|
45
|
-
if not _TURING_AVAILABLE:
|
46
|
-
raise ImportError("TuringEngine不可用,请确保turingPythonLib已安装")
|
47
|
-
return TuringEngine(database_name, **kwargs)
|
48
|
-
else:
|
49
|
-
raise ValueError(f"不支持的引擎类型: {engine_type}")
|
50
|
-
|
51
|
-
# 主要导出
|
52
|
-
__all__ = [
|
53
|
-
'BaseEngine',
|
54
|
-
'DatabaseType',
|
55
|
-
'SparkEngine',
|
56
|
-
'HiveEngine',
|
57
|
-
'create_engine'
|
58
|
-
]
|
59
|
-
|
60
|
-
# 如果图灵引擎可用,添加到导出
|
61
|
-
if _TURING_AVAILABLE:
|
62
|
-
__all__.extend([
|
63
|
-
'TuringEngine',
|
64
|
-
'create_turing_engine'
|
65
|
-
])
|