funcguard 0.2.49__tar.gz → 0.2.51__tar.gz
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.
- {funcguard-0.2.49 → funcguard-0.2.51}/PKG-INFO +39 -6
- {funcguard-0.2.49 → funcguard-0.2.51}/README.md +38 -5
- {funcguard-0.2.49 → funcguard-0.2.51}/funcguard/core.py +55 -26
- {funcguard-0.2.49 → funcguard-0.2.51}/funcguard.egg-info/PKG-INFO +39 -6
- {funcguard-0.2.49 → funcguard-0.2.51}/setup.py +1 -1
- {funcguard-0.2.49 → funcguard-0.2.51}/LICENSE +0 -0
- {funcguard-0.2.49 → funcguard-0.2.51}/funcguard/__init__.py +0 -0
- {funcguard-0.2.49 → funcguard-0.2.51}/funcguard/calculate.py +0 -0
- {funcguard-0.2.49 → funcguard-0.2.51}/funcguard/data_models/__init__.py +0 -0
- {funcguard-0.2.49 → funcguard-0.2.51}/funcguard/data_models/request_models.py +0 -0
- {funcguard-0.2.49 → funcguard-0.2.51}/funcguard/ip_utils.py +0 -0
- {funcguard-0.2.49 → funcguard-0.2.51}/funcguard/log_utils.py +0 -0
- {funcguard-0.2.49 → funcguard-0.2.51}/funcguard/pd_utils/__init__.py +0 -0
- {funcguard-0.2.49 → funcguard-0.2.51}/funcguard/pd_utils/convert_utils.py +0 -0
- {funcguard-0.2.49 → funcguard-0.2.51}/funcguard/pd_utils/date_utils.py +0 -0
- {funcguard-0.2.49 → funcguard-0.2.51}/funcguard/pd_utils/fill_round.py +0 -0
- {funcguard-0.2.49 → funcguard-0.2.51}/funcguard/pd_utils/filter.py +0 -0
- {funcguard-0.2.49 → funcguard-0.2.51}/funcguard/pd_utils/json_utils/__init__.py +0 -0
- {funcguard-0.2.49 → funcguard-0.2.51}/funcguard/pd_utils/json_utils/json_parser.py +0 -0
- {funcguard-0.2.49 → funcguard-0.2.51}/funcguard/pd_utils/statistics/__init__.py +0 -0
- {funcguard-0.2.49 → funcguard-0.2.51}/funcguard/pd_utils/statistics/agg_utils.py +0 -0
- {funcguard-0.2.49 → funcguard-0.2.51}/funcguard/pd_utils/statistics/count_utils.py +0 -0
- {funcguard-0.2.49 → funcguard-0.2.51}/funcguard/pd_utils/statistics/df_statistics.py +0 -0
- {funcguard-0.2.49 → funcguard-0.2.51}/funcguard/pd_utils/statistics/mask_utils.py +0 -0
- {funcguard-0.2.49 → funcguard-0.2.51}/funcguard/printer.py +0 -0
- {funcguard-0.2.49 → funcguard-0.2.51}/funcguard/time_utils.py +0 -0
- {funcguard-0.2.49 → funcguard-0.2.51}/funcguard/tools.py +0 -0
- {funcguard-0.2.49 → funcguard-0.2.51}/funcguard.egg-info/SOURCES.txt +0 -0
- {funcguard-0.2.49 → funcguard-0.2.51}/funcguard.egg-info/dependency_links.txt +0 -0
- {funcguard-0.2.49 → funcguard-0.2.51}/funcguard.egg-info/not-zip-safe +0 -0
- {funcguard-0.2.49 → funcguard-0.2.51}/funcguard.egg-info/requires.txt +0 -0
- {funcguard-0.2.49 → funcguard-0.2.51}/funcguard.egg-info/top_level.txt +0 -0
- {funcguard-0.2.49 → funcguard-0.2.51}/setup.cfg +0 -0
- {funcguard-0.2.49 → funcguard-0.2.51}/tests/__init__.py +0 -0
- {funcguard-0.2.49 → funcguard-0.2.51}/tests/test_pd_filter_empty.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: funcguard
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.51
|
|
4
4
|
Summary: FuncGuard是一个Python库,提供函数执行超时控制、重试机制、HTTP请求封装和格式化打印工具。
|
|
5
5
|
Home-page: https://github.com/tinycen/funcguard
|
|
6
6
|
Author: tinycen
|
|
@@ -97,17 +97,20 @@ except Exception as e:
|
|
|
97
97
|
|
|
98
98
|
### 交互式选择菜单
|
|
99
99
|
|
|
100
|
-
使用 `ask_select` 函数创建一个带数字编号的交互式选择菜单(编号从0
|
|
100
|
+
使用 `ask_select` 函数创建一个带数字编号的交互式选择菜单(编号从0开始),支持超时自动选择和倒计时动态显示。`options` 参数支持**字典**或**列表**两种模式:
|
|
101
|
+
|
|
102
|
+
#### 字典模式
|
|
103
|
+
字典模式下,键为选项标识(任意类型),值为显示文本,返回用户选择的键:
|
|
101
104
|
|
|
102
105
|
```python
|
|
103
106
|
from funcguard import ask_select
|
|
104
107
|
|
|
105
|
-
# 基础用法 -
|
|
108
|
+
# 基础用法 - 选择属性填写模式(默认超时10秒)
|
|
106
109
|
result = ask_select(
|
|
107
110
|
options={True: "需要填写属性", False: "不需要填写属性", "all": "不限制"},
|
|
108
111
|
default_key="all",
|
|
109
112
|
prompt="请选择属性填写模式",
|
|
110
|
-
timeout=
|
|
113
|
+
timeout=10
|
|
111
114
|
)
|
|
112
115
|
print(f"用户选择: {result}") # 返回 True, False 或 "all"
|
|
113
116
|
|
|
@@ -116,7 +119,7 @@ env = ask_select(
|
|
|
116
119
|
options={"dev": "开发环境", "test": "测试环境", "prod": "生产环境"},
|
|
117
120
|
default_key="dev",
|
|
118
121
|
prompt="请选择部署环境",
|
|
119
|
-
timeout=
|
|
122
|
+
timeout=10
|
|
120
123
|
)
|
|
121
124
|
print(f"当前环境: {env}")
|
|
122
125
|
|
|
@@ -125,11 +128,41 @@ count = ask_select(
|
|
|
125
128
|
options={10: "10条", 50: "50条", 100: "100条"},
|
|
126
129
|
default_key=50,
|
|
127
130
|
prompt="查询数量",
|
|
128
|
-
timeout=
|
|
131
|
+
timeout=10
|
|
129
132
|
)
|
|
130
133
|
print(f"查询 {count} 条数据")
|
|
131
134
|
```
|
|
132
135
|
|
|
136
|
+
#### 列表模式
|
|
137
|
+
列表模式下,元素即为选项值,返回用户选中的元素:
|
|
138
|
+
|
|
139
|
+
```python
|
|
140
|
+
from funcguard import ask_select
|
|
141
|
+
|
|
142
|
+
# 使用列表 - 返回选中的元素值
|
|
143
|
+
env = ask_select(
|
|
144
|
+
options=["开发环境", "测试环境", "生产环境"],
|
|
145
|
+
default_key="开发环境",
|
|
146
|
+
prompt="请选择部署环境",
|
|
147
|
+
timeout=10
|
|
148
|
+
)
|
|
149
|
+
print(f"当前环境: {env}") # 直接返回 "开发环境"、"测试环境" 或 "生产环境"
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
#### 无超时模式
|
|
153
|
+
设置 `timeout=None` 可以禁用超时,一直等待用户输入:
|
|
154
|
+
|
|
155
|
+
```python
|
|
156
|
+
# 无超时模式 - 一直等待用户输入
|
|
157
|
+
result = ask_select(
|
|
158
|
+
options={"save": "保存", "discard": "放弃", "cancel": "取消"},
|
|
159
|
+
default_key="cancel",
|
|
160
|
+
prompt="文件已修改,请选择操作",
|
|
161
|
+
timeout=None
|
|
162
|
+
)
|
|
163
|
+
print(f"用户选择: {result}")
|
|
164
|
+
```
|
|
165
|
+
|
|
133
166
|
### HTTP请求
|
|
134
167
|
|
|
135
168
|
FuncGuard 提供了强大的 HTTP 请求功能,支持自动重试、请求日志记录、以及 curl_cffi 兜底(用于绕过反爬虫检测)。详细文档请参考 [network.md](docs/network.md)。
|
|
@@ -70,17 +70,20 @@ except Exception as e:
|
|
|
70
70
|
|
|
71
71
|
### 交互式选择菜单
|
|
72
72
|
|
|
73
|
-
使用 `ask_select` 函数创建一个带数字编号的交互式选择菜单(编号从0
|
|
73
|
+
使用 `ask_select` 函数创建一个带数字编号的交互式选择菜单(编号从0开始),支持超时自动选择和倒计时动态显示。`options` 参数支持**字典**或**列表**两种模式:
|
|
74
|
+
|
|
75
|
+
#### 字典模式
|
|
76
|
+
字典模式下,键为选项标识(任意类型),值为显示文本,返回用户选择的键:
|
|
74
77
|
|
|
75
78
|
```python
|
|
76
79
|
from funcguard import ask_select
|
|
77
80
|
|
|
78
|
-
# 基础用法 -
|
|
81
|
+
# 基础用法 - 选择属性填写模式(默认超时10秒)
|
|
79
82
|
result = ask_select(
|
|
80
83
|
options={True: "需要填写属性", False: "不需要填写属性", "all": "不限制"},
|
|
81
84
|
default_key="all",
|
|
82
85
|
prompt="请选择属性填写模式",
|
|
83
|
-
timeout=
|
|
86
|
+
timeout=10
|
|
84
87
|
)
|
|
85
88
|
print(f"用户选择: {result}") # 返回 True, False 或 "all"
|
|
86
89
|
|
|
@@ -89,7 +92,7 @@ env = ask_select(
|
|
|
89
92
|
options={"dev": "开发环境", "test": "测试环境", "prod": "生产环境"},
|
|
90
93
|
default_key="dev",
|
|
91
94
|
prompt="请选择部署环境",
|
|
92
|
-
timeout=
|
|
95
|
+
timeout=10
|
|
93
96
|
)
|
|
94
97
|
print(f"当前环境: {env}")
|
|
95
98
|
|
|
@@ -98,11 +101,41 @@ count = ask_select(
|
|
|
98
101
|
options={10: "10条", 50: "50条", 100: "100条"},
|
|
99
102
|
default_key=50,
|
|
100
103
|
prompt="查询数量",
|
|
101
|
-
timeout=
|
|
104
|
+
timeout=10
|
|
102
105
|
)
|
|
103
106
|
print(f"查询 {count} 条数据")
|
|
104
107
|
```
|
|
105
108
|
|
|
109
|
+
#### 列表模式
|
|
110
|
+
列表模式下,元素即为选项值,返回用户选中的元素:
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
from funcguard import ask_select
|
|
114
|
+
|
|
115
|
+
# 使用列表 - 返回选中的元素值
|
|
116
|
+
env = ask_select(
|
|
117
|
+
options=["开发环境", "测试环境", "生产环境"],
|
|
118
|
+
default_key="开发环境",
|
|
119
|
+
prompt="请选择部署环境",
|
|
120
|
+
timeout=10
|
|
121
|
+
)
|
|
122
|
+
print(f"当前环境: {env}") # 直接返回 "开发环境"、"测试环境" 或 "生产环境"
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
#### 无超时模式
|
|
126
|
+
设置 `timeout=None` 可以禁用超时,一直等待用户输入:
|
|
127
|
+
|
|
128
|
+
```python
|
|
129
|
+
# 无超时模式 - 一直等待用户输入
|
|
130
|
+
result = ask_select(
|
|
131
|
+
options={"save": "保存", "discard": "放弃", "cancel": "取消"},
|
|
132
|
+
default_key="cancel",
|
|
133
|
+
prompt="文件已修改,请选择操作",
|
|
134
|
+
timeout=None
|
|
135
|
+
)
|
|
136
|
+
print(f"用户选择: {result}")
|
|
137
|
+
```
|
|
138
|
+
|
|
106
139
|
### HTTP请求
|
|
107
140
|
|
|
108
141
|
FuncGuard 提供了强大的 HTTP 请求功能,支持自动重试、请求日志记录、以及 curl_cffi 兜底(用于绕过反爬虫检测)。详细文档请参考 [network.md](docs/network.md)。
|
|
@@ -92,46 +92,70 @@ def retry_function( func , max_retries = 5 , execute_timeout = 90 , task_name =
|
|
|
92
92
|
|
|
93
93
|
# 交互式选择菜单
|
|
94
94
|
def ask_select(
|
|
95
|
-
options: dict,
|
|
95
|
+
options: dict | list,
|
|
96
96
|
default_key = None,
|
|
97
97
|
prompt: str = "请选择",
|
|
98
|
-
timeout: int =
|
|
98
|
+
timeout: int | None = 10,
|
|
99
99
|
):
|
|
100
100
|
"""
|
|
101
101
|
显示一个数字选择菜单,接受用户输入,超时自动返回默认值。
|
|
102
102
|
|
|
103
103
|
参数:
|
|
104
|
-
options:
|
|
105
|
-
|
|
106
|
-
|
|
104
|
+
options: 字典或列表。
|
|
105
|
+
字典模式: 键为选项标识,值为显示文本,返回选中的键
|
|
106
|
+
列表模式: 元素为显示文本,返回选中的元素值
|
|
107
|
+
例如: {True: "需要填写属性", False: "不需要填写属性"} 或 ["选项A", "选项B", "选项C"]
|
|
108
|
+
default_key: 超时或输入无效时的默认返回值
|
|
109
|
+
字典模式下为某个键,若为None则使用最后一个选项的键
|
|
110
|
+
列表模式下为某个元素值,若为None则使用最后一个元素
|
|
107
111
|
prompt: 提示语前缀
|
|
108
|
-
timeout: 超时时间(秒),默认
|
|
112
|
+
timeout: 超时时间(秒),默认10秒;若为None则不设置超时,一直等待用户输入
|
|
109
113
|
|
|
110
114
|
返回:
|
|
111
|
-
|
|
115
|
+
字典模式: 返回选项键(options中的某个键),或default_key
|
|
116
|
+
列表模式: 返回选中的列表元素值,或default_key
|
|
112
117
|
|
|
113
118
|
示例:
|
|
119
|
+
>>> # 字典模式
|
|
114
120
|
>>> result = ask_select(
|
|
115
121
|
... {True: "需要填写属性", False: "不需要填写属性", "all": "不限制"},
|
|
116
122
|
... default_key="all",
|
|
117
123
|
... prompt="请选择属性填写模式",
|
|
118
|
-
... timeout=
|
|
124
|
+
... timeout=10,
|
|
125
|
+
... )
|
|
126
|
+
>>> # 列表模式
|
|
127
|
+
>>> value = ask_select(
|
|
128
|
+
... ["选项A", "选项B", "选项C"],
|
|
129
|
+
... default_key="选项A",
|
|
130
|
+
... prompt="请选择一个选项",
|
|
131
|
+
... timeout=10,
|
|
119
132
|
... )
|
|
120
133
|
"""
|
|
121
134
|
# 确保选项非空
|
|
122
135
|
if not options:
|
|
123
|
-
raise ValueError("options
|
|
124
|
-
|
|
125
|
-
#
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
136
|
+
raise ValueError("options不能为空")
|
|
137
|
+
|
|
138
|
+
# 判断是字典,还是列表
|
|
139
|
+
is_list_mode = isinstance(options, list)
|
|
140
|
+
|
|
141
|
+
# 设置默认值并构建选项列表
|
|
142
|
+
if is_list_mode:
|
|
143
|
+
# 列表模式: 将列表转为 {值: 显示文本} 的字典格式
|
|
144
|
+
if default_key is None:
|
|
145
|
+
default_key = options[-1]
|
|
146
|
+
items = [(value, value) for value in options]
|
|
147
|
+
else:
|
|
148
|
+
# 字典模式: 保持原有逻辑
|
|
149
|
+
if default_key is None:
|
|
150
|
+
default_key = list(options.keys())[-1]
|
|
151
|
+
items = list(options.items())
|
|
131
152
|
|
|
132
153
|
# 显示选项
|
|
133
154
|
option_lines = ", ".join([f"{i}-{label}" for i, (_, label) in enumerate(items)])
|
|
134
|
-
|
|
155
|
+
if is_list_mode:
|
|
156
|
+
default_label = default_key
|
|
157
|
+
else:
|
|
158
|
+
default_label = options.get(default_key, default_key)
|
|
135
159
|
|
|
136
160
|
# 使用线程实现跨平台超时输入
|
|
137
161
|
from threading import Thread
|
|
@@ -149,12 +173,17 @@ def ask_select(
|
|
|
149
173
|
thread = Thread(target=input_thread, daemon=True)
|
|
150
174
|
thread.start()
|
|
151
175
|
|
|
152
|
-
#
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
176
|
+
# 倒计时显示(仅当设置了timeout时)
|
|
177
|
+
if timeout is not None:
|
|
178
|
+
remaining = timeout
|
|
179
|
+
while remaining > 0 and thread.is_alive():
|
|
180
|
+
print(f"\r{prompt} ({option_lines}),{remaining} 秒后自动选择[{default_label}]: ", end="", flush=True)
|
|
181
|
+
time.sleep(1)
|
|
182
|
+
remaining -= 1
|
|
183
|
+
else:
|
|
184
|
+
# 无超时,直接显示提示并等待用户输入
|
|
185
|
+
print(f"{prompt} ({option_lines}): ", end="", flush=True)
|
|
186
|
+
thread.join()
|
|
158
187
|
|
|
159
188
|
# 等待线程结束(如果用户已输入)或超时
|
|
160
189
|
thread.join(0)
|
|
@@ -164,18 +193,18 @@ def ask_select(
|
|
|
164
193
|
except Empty:
|
|
165
194
|
user_input = None
|
|
166
195
|
|
|
167
|
-
if user_input is None:
|
|
196
|
+
if user_input is None and timeout is not None:
|
|
168
197
|
print(f"\n超时,自动选择[{default_label}]")
|
|
169
198
|
return default_key
|
|
170
199
|
|
|
171
200
|
# 验证输入
|
|
172
201
|
try:
|
|
173
|
-
choice = int(user_input)
|
|
202
|
+
choice = int(user_input) # pyright: ignore[reportArgumentType]
|
|
174
203
|
if 0 <= choice < len(items):
|
|
175
204
|
selected_key, selected_label = items[choice]
|
|
176
205
|
print(f"\n已选择 {choice}:{selected_label}")
|
|
177
206
|
return selected_key
|
|
178
|
-
except ValueError:
|
|
207
|
+
except (ValueError, TypeError):
|
|
179
208
|
pass
|
|
180
209
|
|
|
181
210
|
# 输入无效,返回默认值
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: funcguard
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.51
|
|
4
4
|
Summary: FuncGuard是一个Python库,提供函数执行超时控制、重试机制、HTTP请求封装和格式化打印工具。
|
|
5
5
|
Home-page: https://github.com/tinycen/funcguard
|
|
6
6
|
Author: tinycen
|
|
@@ -97,17 +97,20 @@ except Exception as e:
|
|
|
97
97
|
|
|
98
98
|
### 交互式选择菜单
|
|
99
99
|
|
|
100
|
-
使用 `ask_select` 函数创建一个带数字编号的交互式选择菜单(编号从0
|
|
100
|
+
使用 `ask_select` 函数创建一个带数字编号的交互式选择菜单(编号从0开始),支持超时自动选择和倒计时动态显示。`options` 参数支持**字典**或**列表**两种模式:
|
|
101
|
+
|
|
102
|
+
#### 字典模式
|
|
103
|
+
字典模式下,键为选项标识(任意类型),值为显示文本,返回用户选择的键:
|
|
101
104
|
|
|
102
105
|
```python
|
|
103
106
|
from funcguard import ask_select
|
|
104
107
|
|
|
105
|
-
# 基础用法 -
|
|
108
|
+
# 基础用法 - 选择属性填写模式(默认超时10秒)
|
|
106
109
|
result = ask_select(
|
|
107
110
|
options={True: "需要填写属性", False: "不需要填写属性", "all": "不限制"},
|
|
108
111
|
default_key="all",
|
|
109
112
|
prompt="请选择属性填写模式",
|
|
110
|
-
timeout=
|
|
113
|
+
timeout=10
|
|
111
114
|
)
|
|
112
115
|
print(f"用户选择: {result}") # 返回 True, False 或 "all"
|
|
113
116
|
|
|
@@ -116,7 +119,7 @@ env = ask_select(
|
|
|
116
119
|
options={"dev": "开发环境", "test": "测试环境", "prod": "生产环境"},
|
|
117
120
|
default_key="dev",
|
|
118
121
|
prompt="请选择部署环境",
|
|
119
|
-
timeout=
|
|
122
|
+
timeout=10
|
|
120
123
|
)
|
|
121
124
|
print(f"当前环境: {env}")
|
|
122
125
|
|
|
@@ -125,11 +128,41 @@ count = ask_select(
|
|
|
125
128
|
options={10: "10条", 50: "50条", 100: "100条"},
|
|
126
129
|
default_key=50,
|
|
127
130
|
prompt="查询数量",
|
|
128
|
-
timeout=
|
|
131
|
+
timeout=10
|
|
129
132
|
)
|
|
130
133
|
print(f"查询 {count} 条数据")
|
|
131
134
|
```
|
|
132
135
|
|
|
136
|
+
#### 列表模式
|
|
137
|
+
列表模式下,元素即为选项值,返回用户选中的元素:
|
|
138
|
+
|
|
139
|
+
```python
|
|
140
|
+
from funcguard import ask_select
|
|
141
|
+
|
|
142
|
+
# 使用列表 - 返回选中的元素值
|
|
143
|
+
env = ask_select(
|
|
144
|
+
options=["开发环境", "测试环境", "生产环境"],
|
|
145
|
+
default_key="开发环境",
|
|
146
|
+
prompt="请选择部署环境",
|
|
147
|
+
timeout=10
|
|
148
|
+
)
|
|
149
|
+
print(f"当前环境: {env}") # 直接返回 "开发环境"、"测试环境" 或 "生产环境"
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
#### 无超时模式
|
|
153
|
+
设置 `timeout=None` 可以禁用超时,一直等待用户输入:
|
|
154
|
+
|
|
155
|
+
```python
|
|
156
|
+
# 无超时模式 - 一直等待用户输入
|
|
157
|
+
result = ask_select(
|
|
158
|
+
options={"save": "保存", "discard": "放弃", "cancel": "取消"},
|
|
159
|
+
default_key="cancel",
|
|
160
|
+
prompt="文件已修改,请选择操作",
|
|
161
|
+
timeout=None
|
|
162
|
+
)
|
|
163
|
+
print(f"用户选择: {result}")
|
|
164
|
+
```
|
|
165
|
+
|
|
133
166
|
### HTTP请求
|
|
134
167
|
|
|
135
168
|
FuncGuard 提供了强大的 HTTP 请求功能,支持自动重试、请求日志记录、以及 curl_cffi 兜底(用于绕过反爬虫检测)。详细文档请参考 [network.md](docs/network.md)。
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|