funcguard 0.2.51__tar.gz → 0.2.53__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.51 → funcguard-0.2.53}/PKG-INFO +6 -1
- {funcguard-0.2.51 → funcguard-0.2.53}/funcguard/ip_utils.py +2 -2
- {funcguard-0.2.51 → funcguard-0.2.53}/funcguard/pd_utils/convert_utils.py +14 -9
- {funcguard-0.2.51 → funcguard-0.2.53}/funcguard/pd_utils/fill_round.py +10 -0
- {funcguard-0.2.51 → funcguard-0.2.53}/funcguard/pd_utils/statistics/df_statistics.py +10 -2
- {funcguard-0.2.51 → funcguard-0.2.53}/funcguard/pd_utils/statistics/mask_utils.py +2 -2
- {funcguard-0.2.51 → funcguard-0.2.53}/funcguard/printer.py +3 -0
- {funcguard-0.2.51 → funcguard-0.2.53}/funcguard/tools.py +8 -3
- {funcguard-0.2.51 → funcguard-0.2.53}/funcguard.egg-info/PKG-INFO +6 -1
- {funcguard-0.2.51 → funcguard-0.2.53}/setup.py +6 -1
- {funcguard-0.2.51 → funcguard-0.2.53}/LICENSE +0 -0
- {funcguard-0.2.51 → funcguard-0.2.53}/README.md +0 -0
- {funcguard-0.2.51 → funcguard-0.2.53}/funcguard/__init__.py +0 -0
- {funcguard-0.2.51 → funcguard-0.2.53}/funcguard/calculate.py +0 -0
- {funcguard-0.2.51 → funcguard-0.2.53}/funcguard/core.py +0 -0
- {funcguard-0.2.51 → funcguard-0.2.53}/funcguard/data_models/__init__.py +0 -0
- {funcguard-0.2.51 → funcguard-0.2.53}/funcguard/data_models/request_models.py +0 -0
- {funcguard-0.2.51 → funcguard-0.2.53}/funcguard/log_utils.py +0 -0
- {funcguard-0.2.51 → funcguard-0.2.53}/funcguard/pd_utils/__init__.py +0 -0
- {funcguard-0.2.51 → funcguard-0.2.53}/funcguard/pd_utils/date_utils.py +0 -0
- {funcguard-0.2.51 → funcguard-0.2.53}/funcguard/pd_utils/filter.py +0 -0
- {funcguard-0.2.51 → funcguard-0.2.53}/funcguard/pd_utils/json_utils/__init__.py +0 -0
- {funcguard-0.2.51 → funcguard-0.2.53}/funcguard/pd_utils/json_utils/json_parser.py +0 -0
- {funcguard-0.2.51 → funcguard-0.2.53}/funcguard/pd_utils/statistics/__init__.py +0 -0
- {funcguard-0.2.51 → funcguard-0.2.53}/funcguard/pd_utils/statistics/agg_utils.py +0 -0
- {funcguard-0.2.51 → funcguard-0.2.53}/funcguard/pd_utils/statistics/count_utils.py +0 -0
- {funcguard-0.2.51 → funcguard-0.2.53}/funcguard/time_utils.py +0 -0
- {funcguard-0.2.51 → funcguard-0.2.53}/funcguard.egg-info/SOURCES.txt +0 -0
- {funcguard-0.2.51 → funcguard-0.2.53}/funcguard.egg-info/dependency_links.txt +0 -0
- {funcguard-0.2.51 → funcguard-0.2.53}/funcguard.egg-info/not-zip-safe +0 -0
- {funcguard-0.2.51 → funcguard-0.2.53}/funcguard.egg-info/requires.txt +0 -0
- {funcguard-0.2.51 → funcguard-0.2.53}/funcguard.egg-info/top_level.txt +0 -0
- {funcguard-0.2.51 → funcguard-0.2.53}/setup.cfg +0 -0
- {funcguard-0.2.51 → funcguard-0.2.53}/tests/__init__.py +0 -0
- {funcguard-0.2.51 → funcguard-0.2.53}/tests/test_pd_filter_empty.py +0 -0
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: funcguard
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.53
|
|
4
4
|
Summary: FuncGuard是一个Python库,提供函数执行超时控制、重试机制、HTTP请求封装和格式化打印工具。
|
|
5
5
|
Home-page: https://github.com/tinycen/funcguard
|
|
6
6
|
Author: tinycen
|
|
7
7
|
Author-email: sky_ruocen@qq.com
|
|
8
8
|
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
9
14
|
Classifier: License :: OSI Approved :: MIT License
|
|
10
15
|
Classifier: Operating System :: OS Independent
|
|
11
16
|
Requires-Python: >=3.10
|
|
@@ -51,7 +51,7 @@ def get_public_ip():
|
|
|
51
51
|
# 验证是否为有效的IP地址格式
|
|
52
52
|
if is_valid_ip(ip):
|
|
53
53
|
return ip
|
|
54
|
-
except:
|
|
54
|
+
except Exception:
|
|
55
55
|
continue
|
|
56
56
|
|
|
57
57
|
return None
|
|
@@ -80,7 +80,7 @@ def is_valid_ip(ip_string):
|
|
|
80
80
|
return False
|
|
81
81
|
|
|
82
82
|
return True
|
|
83
|
-
except:
|
|
83
|
+
except Exception:
|
|
84
84
|
return False
|
|
85
85
|
|
|
86
86
|
|
|
@@ -134,6 +134,14 @@ def convert_columns(df: pd.DataFrame, columns: Dict[str, str], decimal_places: O
|
|
|
134
134
|
return df
|
|
135
135
|
|
|
136
136
|
|
|
137
|
+
def _has_decimal(df: pd.DataFrame, column: str) -> bool:
|
|
138
|
+
"""检查列中是否存在 Decimal 类型值"""
|
|
139
|
+
for val in df[column]:
|
|
140
|
+
if pd.notna(val) and isinstance(val, Decimal):
|
|
141
|
+
return True
|
|
142
|
+
return False
|
|
143
|
+
|
|
144
|
+
|
|
137
145
|
def convert_decimal(
|
|
138
146
|
df: pd.DataFrame,
|
|
139
147
|
columns: Union[List[str], Dict[str, str], None] = None,
|
|
@@ -182,20 +190,17 @@ def convert_decimal(
|
|
|
182
190
|
# 检查列是否存在且为object类型 (只有object类型列才可能包含Decimal)
|
|
183
191
|
if column not in df.columns or df[column].dtype != object:
|
|
184
192
|
continue
|
|
185
|
-
#
|
|
186
|
-
|
|
187
|
-
if first_non_null is None:
|
|
188
|
-
continue
|
|
189
|
-
if isinstance( df.at[first_non_null, column], Decimal ): # pyright: ignore[reportArgumentType]
|
|
193
|
+
# 检查列中是否存在 Decimal 类型值
|
|
194
|
+
if _has_decimal(df, column):
|
|
190
195
|
# 根据指定的类型进行转换
|
|
191
|
-
|
|
192
|
-
if
|
|
196
|
+
col_target_type = column_types[column]
|
|
197
|
+
if col_target_type == "int":
|
|
193
198
|
df[column] = df[column].astype(int)
|
|
194
|
-
elif
|
|
199
|
+
elif col_target_type == "float":
|
|
195
200
|
df[column] = df[column].astype(float)
|
|
196
201
|
if decimal_places is not None:
|
|
197
202
|
df[column] = df[column].round(decimal_places)
|
|
198
|
-
elif
|
|
203
|
+
elif col_target_type == "auto":
|
|
199
204
|
df[column] = convert_numeric_series(df[column], decimal_places)
|
|
200
205
|
|
|
201
206
|
return df
|
|
@@ -24,6 +24,9 @@ def fill_na(
|
|
|
24
24
|
|
|
25
25
|
返回:
|
|
26
26
|
- pd.DataFrame:替换空值后的DataFrame。
|
|
27
|
+
|
|
28
|
+
注意:本函数直接修改传入的 DataFrame,不返回副本。如需保留原数据,
|
|
29
|
+
请在调用前使用 df.copy()。
|
|
27
30
|
"""
|
|
28
31
|
_is_numeric_fill = isinstance(fill_value, (int, float))
|
|
29
32
|
|
|
@@ -76,10 +79,17 @@ def round_columns(
|
|
|
76
79
|
|
|
77
80
|
返回:
|
|
78
81
|
- pd.DataFrame:四舍五入后的DataFrame。
|
|
82
|
+
|
|
83
|
+
注意:
|
|
84
|
+
- 当 decimal_places 为 0 时,结果列会自动转换为 Int64(可空整数)类型。
|
|
85
|
+
- decimal.Decimal 类型在 pandas 中以 object dtype 存储,不被视为数值类型,
|
|
86
|
+
调用本函数会抛出 TypeError。需先手动将其转换为 float 类型再调用本函数。
|
|
79
87
|
"""
|
|
80
88
|
for column in columns:
|
|
81
89
|
if column in df.columns:
|
|
82
90
|
if not is_numeric_dtype(df[column]):
|
|
83
91
|
raise TypeError(f"列 '{column}' 不是数值类型,无法执行四舍五入操作")
|
|
84
92
|
df[column] = df[column].round(decimal_places)
|
|
93
|
+
if decimal_places == 0:
|
|
94
|
+
df[column] = df[column].astype('Int64')
|
|
85
95
|
return df
|
|
@@ -39,9 +39,13 @@ class DataFrameStatistics:
|
|
|
39
39
|
# 重置 true_mask 和 false_mask
|
|
40
40
|
def _reset_base_masks(self):
|
|
41
41
|
"""重置基础掩码为全True和全False"""
|
|
42
|
-
self._true_mask = pd.Series([True] * self.
|
|
43
|
-
self._false_mask = pd.Series([False] * self.
|
|
42
|
+
self._true_mask = pd.Series([True] * len(self._df), index=self._df.index)
|
|
43
|
+
self._false_mask = pd.Series([False] * len(self._df), index=self._df.index)
|
|
44
44
|
|
|
45
|
+
def _ensure_masks_valid(self):
|
|
46
|
+
"""如果 DataFrame 发生变化,重新生成基础掩码"""
|
|
47
|
+
if self._true_mask is not None and len(self._true_mask) != len(self._df):
|
|
48
|
+
self._reset_base_masks()
|
|
45
49
|
|
|
46
50
|
def build_base_mask(self, conditions: List[Tuple], logic: str = "and",
|
|
47
51
|
true_mask: Optional[pd.Series] = None,
|
|
@@ -58,6 +62,7 @@ class DataFrameStatistics:
|
|
|
58
62
|
返回:
|
|
59
63
|
- pd.Series:布尔掩码,True表示符合条件的行
|
|
60
64
|
"""
|
|
65
|
+
self._ensure_masks_valid()
|
|
61
66
|
# 如果没有提供外部掩码,使用内部缓存的掩码
|
|
62
67
|
if true_mask is None:
|
|
63
68
|
true_mask = self._true_mask
|
|
@@ -96,6 +101,7 @@ class DataFrameStatistics:
|
|
|
96
101
|
返回:
|
|
97
102
|
- int:符合条件的数量
|
|
98
103
|
"""
|
|
104
|
+
self._ensure_masks_valid()
|
|
99
105
|
# 如果没有提供外部掩码,使用内部缓存的掩码
|
|
100
106
|
if true_mask is None:
|
|
101
107
|
true_mask = self._true_mask
|
|
@@ -147,6 +153,7 @@ class DataFrameStatistics:
|
|
|
147
153
|
>>> stats.value_counts("status", conditions=[("age", ">", 18)])
|
|
148
154
|
{'active': 120, 'inactive': 30}
|
|
149
155
|
"""
|
|
156
|
+
self._ensure_masks_valid()
|
|
150
157
|
# 如果没有提供外部掩码,使用内部缓存的掩码
|
|
151
158
|
if true_mask is None:
|
|
152
159
|
true_mask = self._true_mask
|
|
@@ -198,6 +205,7 @@ class DataFrameStatistics:
|
|
|
198
205
|
>>> stats.group_agg("category", "amount", "sum", sort="desc")
|
|
199
206
|
{'B': 2000, 'C': 1500, 'A': 1000}
|
|
200
207
|
"""
|
|
208
|
+
self._ensure_masks_valid()
|
|
201
209
|
# 如果没有提供外部掩码,使用内部缓存的掩码
|
|
202
210
|
if true_mask is None:
|
|
203
211
|
true_mask = self._true_mask
|
|
@@ -42,7 +42,7 @@ def md5_hash(*texts: str, encoding: str = "utf-8") -> str:
|
|
|
42
42
|
|
|
43
43
|
|
|
44
44
|
# 生成 base64 格式的 Basic Auth 字符串
|
|
45
|
-
def encode_basic_auth(username, password):
|
|
45
|
+
def encode_basic_auth(username: str, password: str) -> str:
|
|
46
46
|
# 将 Username 和 Password 拼接成字符串
|
|
47
47
|
auth_str = f"{username}:{password}"
|
|
48
48
|
|
|
@@ -189,7 +189,12 @@ def send_request(
|
|
|
189
189
|
|
|
190
190
|
# ---------- 结果处理 ----------
|
|
191
191
|
if return_type == "json":
|
|
192
|
-
|
|
192
|
+
try:
|
|
193
|
+
result = response.json()
|
|
194
|
+
except (json.JSONDecodeError, ValueError) as e:
|
|
195
|
+
raise ValueError(
|
|
196
|
+
f"响应内容不是有效的 JSON 格式 (status={response.status_code}): {e}"
|
|
197
|
+
) from e
|
|
193
198
|
if request_log.save_path:
|
|
194
199
|
res_log = {}
|
|
195
200
|
save_fields = [
|
|
@@ -247,7 +252,7 @@ def check_url_valid(
|
|
|
247
252
|
response = curl_cffi_request(
|
|
248
253
|
"HEAD", url, req_kwargs, curl_fallback_impersonate, auto_retry
|
|
249
254
|
)
|
|
250
|
-
if response.status_code == 200: # type: ignore
|
|
255
|
+
if response is not None and response.status_code == 200: # type: ignore
|
|
251
256
|
return True
|
|
252
257
|
except Exception:
|
|
253
258
|
pass
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: funcguard
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.53
|
|
4
4
|
Summary: FuncGuard是一个Python库,提供函数执行超时控制、重试机制、HTTP请求封装和格式化打印工具。
|
|
5
5
|
Home-page: https://github.com/tinycen/funcguard
|
|
6
6
|
Author: tinycen
|
|
7
7
|
Author-email: sky_ruocen@qq.com
|
|
8
8
|
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
9
14
|
Classifier: License :: OSI Approved :: MIT License
|
|
10
15
|
Classifier: Operating System :: OS Independent
|
|
11
16
|
Requires-Python: >=3.10
|
|
@@ -9,7 +9,7 @@ except FileNotFoundError:
|
|
|
9
9
|
|
|
10
10
|
setup(
|
|
11
11
|
name='funcguard',
|
|
12
|
-
version='0.2.
|
|
12
|
+
version='0.2.53',
|
|
13
13
|
packages=find_packages(),
|
|
14
14
|
install_requires=[
|
|
15
15
|
'requests',
|
|
@@ -24,6 +24,11 @@ setup(
|
|
|
24
24
|
url='https://github.com/tinycen/funcguard',
|
|
25
25
|
classifiers=[
|
|
26
26
|
'Programming Language :: Python :: 3',
|
|
27
|
+
'Programming Language :: Python :: 3.10',
|
|
28
|
+
'Programming Language :: Python :: 3.11',
|
|
29
|
+
'Programming Language :: Python :: 3.12',
|
|
30
|
+
'Programming Language :: Python :: 3.13',
|
|
31
|
+
'Programming Language :: Python :: 3.14',
|
|
27
32
|
'License :: OSI Approved :: MIT License',
|
|
28
33
|
'Operating System :: OS Independent',
|
|
29
34
|
],
|
|
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
|