vools 0.1.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.
- tests/__init__.py +45 -0
- tests/test_curried.py +150 -0
- tests/test_curry_overload.py +181 -0
- tests/test_data.py +60 -0
- tests/test_datetime.py +52 -0
- tests/test_decorators.py +362 -0
- tests/test_functional.py +230 -0
- tests/test_functional_simple.py +230 -0
- tests/test_main_import.py +70 -0
- tests/test_oop.py +51 -0
- tests/test_overcurry_vic.py +102 -0
- tests/test_placeholder.py +86 -0
- tests/test_shotcut.py +232 -0
- tests/test_stuff.py +53 -0
- tests/test_utils.py +99 -0
- tests/test_vools.py +150 -0
- vools/__init__.py +299 -0
- vools/__main__.py +110 -0
- vools/config.py +43 -0
- vools/config.template.py +36 -0
- vools/data/__init__.py +3 -0
- vools/data/seq.py +737 -0
- vools/datetime/__init__.py +32 -0
- vools/datetime/dates_format.py +921 -0
- vools/datetime/utils.py +1130 -0
- vools/decorators/__init__.py +119 -0
- vools/decorators/cache.py +424 -0
- vools/decorators/control.py +377 -0
- vools/decorators/curried.py +483 -0
- vools/decorators/curry_core.py +440 -0
- vools/decorators/curry_delay.py +338 -0
- vools/decorators/extend.py +159 -0
- vools/decorators/lazy.py +165 -0
- vools/decorators/overcurry.py +182 -0
- vools/decorators/overload.py +387 -0
- vools/decorators/overloads.py +347 -0
- vools/decorators/selector.py +255 -0
- vools/decorators/trd.py +75 -0
- vools/functional/__init__.py +284 -0
- vools/functional/arrow_func.py +597 -0
- vools/functional/box.py +1275 -0
- vools/functional/iif.py +340 -0
- vools/functional/placeholder.py +647 -0
- vools/oop/__init__.py +25 -0
- vools/oop/calltype.py +287 -0
- vools/oop/extend.py +911 -0
- vools/oop/mixer.py +247 -0
- vools/oop/selector.py +39 -0
- vools/shotcut.py +554 -0
- vools/utils/__init__.py +71 -0
- vools/utils/stuff.py +841 -0
- vools/vools.py +2496 -0
- vools-0.1.1.dist-info/METADATA +334 -0
- vools-0.1.1.dist-info/RECORD +59 -0
- vools-0.1.1.dist-info/WHEEL +5 -0
- vools-0.1.1.dist-info/entry_points.txt +2 -0
- vools-0.1.1.dist-info/licenses/LICENSE +31 -0
- vools-0.1.1.dist-info/licenses/NOTICE +32 -0
- vools-0.1.1.dist-info/top_level.txt +2 -0
tests/__init__.py
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"""
|
|
2
|
+
测试入口文件
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import sys
|
|
6
|
+
import os
|
|
7
|
+
|
|
8
|
+
# 添加父目录到路径
|
|
9
|
+
sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))
|
|
10
|
+
|
|
11
|
+
# 导入所有测试模块
|
|
12
|
+
from .test_decorators import *
|
|
13
|
+
from .test_functional import *
|
|
14
|
+
from .test_utils import *
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def run_all_tests():
|
|
18
|
+
"""运行所有测试"""
|
|
19
|
+
print("=" * 60)
|
|
20
|
+
print("运行 vools 测试套件")
|
|
21
|
+
print("=" * 60)
|
|
22
|
+
|
|
23
|
+
# 装饰器测试
|
|
24
|
+
test_memorize()
|
|
25
|
+
test_once()
|
|
26
|
+
test_lazy()
|
|
27
|
+
|
|
28
|
+
# 函数式编程测试
|
|
29
|
+
test_pipe()
|
|
30
|
+
test_ops()
|
|
31
|
+
test_seq()
|
|
32
|
+
test_p()
|
|
33
|
+
test_none()
|
|
34
|
+
|
|
35
|
+
# 通用工具测试
|
|
36
|
+
test_basic_functions()
|
|
37
|
+
test_stuff()
|
|
38
|
+
|
|
39
|
+
print("\n" + "=" * 60)
|
|
40
|
+
print("[SUCCESS] 所有测试通过!")
|
|
41
|
+
print("=" * 60)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
if __name__ == '__main__':
|
|
45
|
+
run_all_tests()
|
tests/test_curried.py
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
测试 curried 模块中的柯里化函数
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import sys
|
|
9
|
+
import os
|
|
10
|
+
|
|
11
|
+
# 添加父目录到路径
|
|
12
|
+
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
13
|
+
|
|
14
|
+
from vools.decorators import (
|
|
15
|
+
curried_map, curried_filter, curried_reduce, compose, pipe, curried_pipe,
|
|
16
|
+
add, mul, sub, div,
|
|
17
|
+
and_, or_, not_,
|
|
18
|
+
identity, const, flip, apply, curried_apply
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def test_higher_order_functions():
|
|
23
|
+
"""测试高阶函数"""
|
|
24
|
+
print("=== 测试高阶函数 ===")
|
|
25
|
+
|
|
26
|
+
# 测试 curried_map
|
|
27
|
+
double = lambda x: x * 2
|
|
28
|
+
assert curried_map(double, [1, 2, 3]) == [2, 4, 6]
|
|
29
|
+
assert curried_map(double)([1, 2, 3]) == [2, 4, 6]
|
|
30
|
+
print("[OK] curried_map 测试通过")
|
|
31
|
+
|
|
32
|
+
# 测试 curried_filter
|
|
33
|
+
is_even = lambda x: x % 2 == 0
|
|
34
|
+
assert curried_filter(is_even, [1, 2, 3, 4]) == [2, 4]
|
|
35
|
+
assert curried_filter(is_even)([1, 2, 3, 4]) == [2, 4]
|
|
36
|
+
print("[OK] curried_filter 测试通过")
|
|
37
|
+
|
|
38
|
+
# 测试 curried_reduce
|
|
39
|
+
add_func = lambda x, y: x + y
|
|
40
|
+
assert curried_reduce(add_func, [1, 2, 3]) == 6
|
|
41
|
+
assert curried_reduce(add_func)([1, 2, 3]) == 6
|
|
42
|
+
assert curried_reduce(add_func, [1, 2, 3], 10) == 16
|
|
43
|
+
print("[OK] curried_reduce 测试通过")
|
|
44
|
+
|
|
45
|
+
# 测试 compose
|
|
46
|
+
add_one = lambda x: x + 1
|
|
47
|
+
composed = compose(add_one, double)
|
|
48
|
+
assert composed(5) == 11
|
|
49
|
+
print("[OK] compose 测试通过")
|
|
50
|
+
|
|
51
|
+
# 测试 pipe
|
|
52
|
+
result = pipe(5, double, add_one)
|
|
53
|
+
assert result == 11
|
|
54
|
+
print("[OK] pipe 测试通过")
|
|
55
|
+
|
|
56
|
+
# 测试 curried_pipe
|
|
57
|
+
result = curried_pipe(5, double, add_one)
|
|
58
|
+
assert result == 11
|
|
59
|
+
assert curried_pipe(5)(double, add_one) == 11
|
|
60
|
+
print("[OK] curried_pipe 测试通过")
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def test_math_functions():
|
|
64
|
+
"""测试数学函数"""
|
|
65
|
+
print("\n=== 测试数学函数 ===")
|
|
66
|
+
|
|
67
|
+
# 测试 add
|
|
68
|
+
assert add(1, 2) == 3
|
|
69
|
+
assert add(1)(2) == 3
|
|
70
|
+
print("[OK] add 测试通过")
|
|
71
|
+
|
|
72
|
+
# 测试 mul
|
|
73
|
+
assert mul(2, 3) == 6
|
|
74
|
+
assert mul(2)(3) == 6
|
|
75
|
+
print("[OK] mul 测试通过")
|
|
76
|
+
|
|
77
|
+
# 测试 sub
|
|
78
|
+
assert sub(5, 2) == 3
|
|
79
|
+
assert sub(5)(2) == 3
|
|
80
|
+
print("[OK] sub 测试通过")
|
|
81
|
+
|
|
82
|
+
# 测试 div
|
|
83
|
+
assert div(6, 2) == 3.0
|
|
84
|
+
assert div(6)(2) == 3.0
|
|
85
|
+
print("[OK] div 测试通过")
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def test_logic_functions():
|
|
89
|
+
"""测试逻辑函数"""
|
|
90
|
+
print("\n=== 测试逻辑函数 ===")
|
|
91
|
+
|
|
92
|
+
# 测试 and_
|
|
93
|
+
assert and_(True, False) is False
|
|
94
|
+
assert and_(True)(True) is True
|
|
95
|
+
print("[OK] and_ 测试通过")
|
|
96
|
+
|
|
97
|
+
# 测试 or_
|
|
98
|
+
assert or_(True, False) is True
|
|
99
|
+
assert or_(False)(False) is False
|
|
100
|
+
print("[OK] or_ 测试通过")
|
|
101
|
+
|
|
102
|
+
# 测试 not_
|
|
103
|
+
assert not_(True) is False
|
|
104
|
+
assert not_(False) is True
|
|
105
|
+
print("[OK] not_ 测试通过")
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def test_util_functions():
|
|
109
|
+
"""测试工具函数"""
|
|
110
|
+
print("\n=== 测试工具函数 ===")
|
|
111
|
+
|
|
112
|
+
# 测试 identity
|
|
113
|
+
assert identity(5) == 5
|
|
114
|
+
assert identity("hello") == "hello"
|
|
115
|
+
print("[OK] identity 测试通过")
|
|
116
|
+
|
|
117
|
+
# 测试 const
|
|
118
|
+
always_five = const(5)
|
|
119
|
+
assert always_five(10) == 5
|
|
120
|
+
assert const("hello", "world") == "hello"
|
|
121
|
+
print("[OK] const 测试通过")
|
|
122
|
+
|
|
123
|
+
# 测试 flip
|
|
124
|
+
subtract = lambda a, b: a - b
|
|
125
|
+
flipped_subtract = flip(subtract)
|
|
126
|
+
assert flipped_subtract(2, 5) == 3 # 相当于 subtract(5, 2)
|
|
127
|
+
print("[OK] flip 测试通过")
|
|
128
|
+
|
|
129
|
+
# 测试 apply
|
|
130
|
+
add_func = lambda a, b: a + b
|
|
131
|
+
assert apply(add_func, 1, 2) == 3
|
|
132
|
+
print("[OK] apply 测试通过")
|
|
133
|
+
|
|
134
|
+
# 测试 curried_apply
|
|
135
|
+
assert curried_apply(add_func, 1, 2) == 3
|
|
136
|
+
assert curried_apply(add_func)(1, 2) == 3
|
|
137
|
+
print("[OK] curried_apply 测试通过")
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
if __name__ == "__main__":
|
|
141
|
+
try:
|
|
142
|
+
test_higher_order_functions()
|
|
143
|
+
test_math_functions()
|
|
144
|
+
test_logic_functions()
|
|
145
|
+
test_util_functions()
|
|
146
|
+
print("\n[SUCCESS] 所有测试通过!")
|
|
147
|
+
except Exception as e:
|
|
148
|
+
print(f"\n[ERROR] 测试失败: {e}")
|
|
149
|
+
import traceback
|
|
150
|
+
traceback.print_exc()
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
"""测试 curry 和 overload 装饰器"""
|
|
2
|
+
|
|
3
|
+
import sys
|
|
4
|
+
import os
|
|
5
|
+
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
6
|
+
|
|
7
|
+
from vools import curry, overload, overloads
|
|
8
|
+
from vools.decorators import strict,curry as curry_decorator
|
|
9
|
+
|
|
10
|
+
print("=" * 60)
|
|
11
|
+
print("测试 smart_partial 和 overload 装饰器")
|
|
12
|
+
print("=" * 60)
|
|
13
|
+
|
|
14
|
+
# 测试 smart_partial
|
|
15
|
+
print("\n=== 测试 smart_partial ===")
|
|
16
|
+
|
|
17
|
+
@curry_decorator
|
|
18
|
+
def add(a, b, c):
|
|
19
|
+
return a + b + c
|
|
20
|
+
|
|
21
|
+
result = add(1)(2)(3)
|
|
22
|
+
print(f"add(1)(2)(3) = {result}")
|
|
23
|
+
assert result == 6
|
|
24
|
+
|
|
25
|
+
result = add(1, 2)(3)
|
|
26
|
+
print(f"add(1, 2)(3) = {result}")
|
|
27
|
+
assert result == 6
|
|
28
|
+
|
|
29
|
+
print("[OK] smart_partial 测试通过")
|
|
30
|
+
|
|
31
|
+
# 测试 overload
|
|
32
|
+
print("\n=== 测试 overload ===")
|
|
33
|
+
|
|
34
|
+
@overload
|
|
35
|
+
def process():
|
|
36
|
+
return "无参数"
|
|
37
|
+
|
|
38
|
+
@process.register
|
|
39
|
+
def process(x):
|
|
40
|
+
return f"一个参数: {x}"
|
|
41
|
+
|
|
42
|
+
@process.register
|
|
43
|
+
def process(x, y):
|
|
44
|
+
return f"两个参数: {x}, {y}"
|
|
45
|
+
|
|
46
|
+
result1 = process()
|
|
47
|
+
result2 = process(10)
|
|
48
|
+
result3 = process(10, 20)
|
|
49
|
+
|
|
50
|
+
print(f"process() = {result1}")
|
|
51
|
+
print(f"process(10) = {result2}")
|
|
52
|
+
print(f"process(10, 20) = {result3}")
|
|
53
|
+
|
|
54
|
+
assert result1 == "无参数"
|
|
55
|
+
assert result2 == "一个参数: 10"
|
|
56
|
+
assert result3 == "两个参数: 10, 20"
|
|
57
|
+
|
|
58
|
+
print("[OK] overload 测试通过")
|
|
59
|
+
|
|
60
|
+
# 测试 strict
|
|
61
|
+
print("\n=== 测试 strict ===")
|
|
62
|
+
|
|
63
|
+
@strict
|
|
64
|
+
def multiply(a: int, b: int) -> int:
|
|
65
|
+
return a * b
|
|
66
|
+
|
|
67
|
+
result = multiply(3, 4)
|
|
68
|
+
print(f"multiply(3, 4) = {result}")
|
|
69
|
+
assert result == 12
|
|
70
|
+
|
|
71
|
+
try:
|
|
72
|
+
multiply(3, "4")
|
|
73
|
+
assert False, "应该抛出 TypeError"
|
|
74
|
+
except TypeError as e:
|
|
75
|
+
print(f"正确捕获类型错误: {e}")
|
|
76
|
+
|
|
77
|
+
print("[OK] strict 测试通过")
|
|
78
|
+
|
|
79
|
+
print("\n" + "=" * 60)
|
|
80
|
+
print("[SUCCESS] 所有测试通过!")
|
|
81
|
+
print("=" * 60)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def test_overloads():
|
|
87
|
+
"""测试 overloads 装饰器"""
|
|
88
|
+
@overload
|
|
89
|
+
def process():
|
|
90
|
+
return "无参数"
|
|
91
|
+
|
|
92
|
+
@process.register
|
|
93
|
+
def process(x):
|
|
94
|
+
return f"一个参数: {x}"
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
@process.register
|
|
98
|
+
def process(x, y):
|
|
99
|
+
return f"两个参数: {x}, {y}"
|
|
100
|
+
|
|
101
|
+
result1 = process()
|
|
102
|
+
result2 = process(10)
|
|
103
|
+
result3 = process(10, 20)
|
|
104
|
+
|
|
105
|
+
assert result1 == "无参数"
|
|
106
|
+
assert result2 == "一个参数: 10"
|
|
107
|
+
assert result3 == "两个参数: 10, 20"
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
class Test:
|
|
111
|
+
def __init__(self, a, b):
|
|
112
|
+
self.a = a
|
|
113
|
+
self.b = b
|
|
114
|
+
|
|
115
|
+
@overload
|
|
116
|
+
def process(self):
|
|
117
|
+
return f"一个参数: {self.a}, {self.b}"
|
|
118
|
+
|
|
119
|
+
@process.register
|
|
120
|
+
def process(self, x):
|
|
121
|
+
return f"两个参数: {self.a}, {self.b}, {x}"
|
|
122
|
+
|
|
123
|
+
@process.register
|
|
124
|
+
def process(self, x, y):
|
|
125
|
+
return f"三个参数: {self.a}, {self.b}, {x}, {y}"
|
|
126
|
+
|
|
127
|
+
test = Test(1, 2)
|
|
128
|
+
result1 = test.process()
|
|
129
|
+
result2 = test.process(3)
|
|
130
|
+
result3 = test.process(4, 5)
|
|
131
|
+
|
|
132
|
+
assert result1 == "一个参数: 1, 2"
|
|
133
|
+
assert result2 == "两个参数: 1, 2, 3"
|
|
134
|
+
assert result3 == "三个参数: 1, 2, 4, 5"
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
@overload
|
|
138
|
+
def process2(x:int, y:int):
|
|
139
|
+
return f"两个参数: {x}, {y},type:{type(x)},{type(y)}"
|
|
140
|
+
|
|
141
|
+
@process2.register
|
|
142
|
+
def process2(x:str, y:str):
|
|
143
|
+
return f"两个参数: {x}, {y},type:{type(x)},{type(y)}"
|
|
144
|
+
|
|
145
|
+
result1 = process2(10, 20)
|
|
146
|
+
result2 = process2("10", "20")
|
|
147
|
+
# print(result1)
|
|
148
|
+
# print(result2)
|
|
149
|
+
assert result1 == "两个参数: 10, 20,type:<class 'int'>,<class 'int'>"
|
|
150
|
+
assert result2 == "两个参数: 10, 20,type:<class 'str'>,<class 'str'>"
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
test_overloads()
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def test_curry_decorator():
|
|
161
|
+
"""测试 curry_decorator 装饰器"""
|
|
162
|
+
@curry_decorator
|
|
163
|
+
def process(a, b, c):
|
|
164
|
+
return a + b + c
|
|
165
|
+
|
|
166
|
+
result = process(1)(2)(3)
|
|
167
|
+
print(f"process(1)(2)(3) = {result}")
|
|
168
|
+
assert result == 6
|
|
169
|
+
|
|
170
|
+
process.delaied = True
|
|
171
|
+
|
|
172
|
+
rs = process(1)(2)(3)
|
|
173
|
+
print(f"process(1)(2)(3) = {rs}")
|
|
174
|
+
assert rs() == 6
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
print("[OK] curry_decorator 测试通过")
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
test_curry_decorator()
|
tests/test_data.py
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"""
|
|
2
|
+
数据处理工具测试
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import sys
|
|
6
|
+
import os
|
|
7
|
+
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
8
|
+
|
|
9
|
+
import unittest
|
|
10
|
+
from vools import data
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class TestDataModule(unittest.TestCase):
|
|
14
|
+
"""数据处理模块测试"""
|
|
15
|
+
|
|
16
|
+
def test_data_available(self):
|
|
17
|
+
"""测试数据模块是否可用"""
|
|
18
|
+
from vools import DATA_AVAILABLE
|
|
19
|
+
self.assertTrue(DATA_AVAILABLE)
|
|
20
|
+
|
|
21
|
+
def test_tabulate_import(self):
|
|
22
|
+
"""测试 tabulate 导入"""
|
|
23
|
+
try:
|
|
24
|
+
from vools.data.tabulate import tabulate
|
|
25
|
+
self.assertIsNotNone(tabulate)
|
|
26
|
+
except ImportError:
|
|
27
|
+
self.skipTest("tabulate not available")
|
|
28
|
+
|
|
29
|
+
def test_tabulate_basic(self):
|
|
30
|
+
"""测试 tabulate 基本功能"""
|
|
31
|
+
try:
|
|
32
|
+
from vools.data.tabulate import tabulate
|
|
33
|
+
table = [["Alice", 24], ["Bob", 19]]
|
|
34
|
+
headers = ["Name", "Age"]
|
|
35
|
+
result = tabulate(table, headers=headers)
|
|
36
|
+
self.assertIn("Alice", result)
|
|
37
|
+
self.assertIn("Bob", result)
|
|
38
|
+
except ImportError:
|
|
39
|
+
self.skipTest("tabulate not available")
|
|
40
|
+
|
|
41
|
+
def test_transform_import(self):
|
|
42
|
+
"""测试 transform 导入"""
|
|
43
|
+
try:
|
|
44
|
+
from vools.data.transform import to_spark_df
|
|
45
|
+
self.assertIsNotNone(to_spark_df)
|
|
46
|
+
except ImportError:
|
|
47
|
+
self.skipTest("transform not available (requires pandas/pyspark)")
|
|
48
|
+
|
|
49
|
+
def test_excel_import(self):
|
|
50
|
+
"""测试 excel 导入"""
|
|
51
|
+
try:
|
|
52
|
+
from vools.data.excel import write_excel, delete_obsolete_files
|
|
53
|
+
self.assertIsNotNone(write_excel)
|
|
54
|
+
self.assertIsNotNone(delete_obsolete_files)
|
|
55
|
+
except ImportError:
|
|
56
|
+
self.skipTest("excel not available (requires pandas/openpyxl)")
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
if __name__ == '__main__':
|
|
60
|
+
unittest.main()
|
tests/test_datetime.py
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"""
|
|
2
|
+
日期时间工具测试
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import sys
|
|
6
|
+
import os
|
|
7
|
+
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
8
|
+
|
|
9
|
+
import unittest
|
|
10
|
+
from vools import datetime
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class TestDatetimeModule(unittest.TestCase):
|
|
14
|
+
"""日期时间模块测试"""
|
|
15
|
+
|
|
16
|
+
def test_datetime_available(self):
|
|
17
|
+
"""测试日期时间模块是否可用"""
|
|
18
|
+
from vools import DATETIME_AVAILABLE
|
|
19
|
+
self.assertTrue(DATETIME_AVAILABLE)
|
|
20
|
+
|
|
21
|
+
def test_range_import(self):
|
|
22
|
+
"""测试 range 导入"""
|
|
23
|
+
try:
|
|
24
|
+
from vools.datetime.range import get_date_range, parse_date_string
|
|
25
|
+
self.assertIsNotNone(get_date_range)
|
|
26
|
+
self.assertIsNotNone(parse_date_string)
|
|
27
|
+
except ImportError as e:
|
|
28
|
+
self.skipTest(f"range not available: {e}")
|
|
29
|
+
|
|
30
|
+
def test_utils_import(self):
|
|
31
|
+
"""测试 utils 导入"""
|
|
32
|
+
try:
|
|
33
|
+
from vools.datetime.utils import get_recently_months, get_recently_weeks, get_recently_days
|
|
34
|
+
self.assertIsNotNone(get_recently_months)
|
|
35
|
+
self.assertIsNotNone(get_recently_weeks)
|
|
36
|
+
self.assertIsNotNone(get_recently_days)
|
|
37
|
+
except ImportError as e:
|
|
38
|
+
self.skipTest(f"utils not available: {e}")
|
|
39
|
+
|
|
40
|
+
def test_get_recently_months(self):
|
|
41
|
+
"""测试 get_recently_months 功能"""
|
|
42
|
+
try:
|
|
43
|
+
from vools.datetime.utils import get_recently_months
|
|
44
|
+
result = get_recently_months("2024-01-15", 3)
|
|
45
|
+
self.assertIsInstance(result, list)
|
|
46
|
+
self.assertGreater(len(result), 0)
|
|
47
|
+
except ImportError as e:
|
|
48
|
+
self.skipTest(f"get_recently_months not available: {e}")
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
if __name__ == '__main__':
|
|
52
|
+
unittest.main()
|