staran 1.0.1__py3-none-any.whl → 1.0.3__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 +57 -5
- staran/date/__init__.py +37 -0
- staran/date/core.py +549 -0
- staran/date/examples/__init__.py +11 -0
- staran/date/examples/basic_usage.py +177 -0
- staran/date/tests/__init__.py +11 -0
- staran/date/tests/run_tests.py +109 -0
- staran/{tools/tests/test_date.py → date/tests/test_core.py} +289 -335
- staran/date/utils/__init__.py +11 -0
- staran/date/utils/helpers.py +203 -0
- staran-1.0.3.dist-info/METADATA +198 -0
- staran-1.0.3.dist-info/RECORD +15 -0
- staran/tools/__init__.py +0 -43
- staran/tools/date.py +0 -405
- staran/tools/tests/__init__.py +0 -119
- staran/tools/tests/run_tests.py +0 -241
- staran/tools/tests/test_api_compatibility.py +0 -319
- staran/tools/tests/test_logging.py +0 -402
- staran-1.0.1.dist-info/METADATA +0 -37
- staran-1.0.1.dist-info/RECORD +0 -13
- {staran-1.0.1.dist-info → staran-1.0.3.dist-info}/WHEEL +0 -0
- {staran-1.0.1.dist-info → staran-1.0.3.dist-info}/licenses/LICENSE +0 -0
- {staran-1.0.1.dist-info → staran-1.0.3.dist-info}/top_level.txt +0 -0
@@ -1,402 +0,0 @@
|
|
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)
|
staran-1.0.1.dist-info/METADATA
DELETED
@@ -1,37 +0,0 @@
|
|
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
|
staran-1.0.1.dist-info/RECORD
DELETED
@@ -1,13 +0,0 @@
|
|
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,,
|
File without changes
|
File without changes
|
File without changes
|