universal-function-zsd 1.0.0__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.
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2018 The Python Packaging Authority
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
File without changes
@@ -0,0 +1,14 @@
1
+ Metadata-Version: 2.1
2
+ Name: universal_function_zsd
3
+ Version: 1.0.0
4
+ Summary: 可用于大部分项目的通用型函数库
5
+ Author-email: Colin Zhang <zsd0830@163.com>
6
+ Classifier: Programming Language :: Python :: 3
7
+ Classifier: License :: OSI Approved :: MIT License
8
+ Classifier: Operating System :: OS Independent
9
+ Requires-Python: >=3.10
10
+ Description-Content-Type: text/markdown
11
+ License-File: LICENSE
12
+
13
+ 本函数包一般用于现有的项目,具备一定的通用性;
14
+ 目前由张绍东维护,有任何问题可咨询zsd0830@163.com。
@@ -0,0 +1,2 @@
1
+ 本函数包一般用于现有的项目,具备一定的通用性;
2
+ 目前由张绍东维护,有任何问题可咨询zsd0830@163.com。
@@ -0,0 +1,15 @@
1
+ [project]
2
+ name = "universal_function_zsd"
3
+ version = "1.0.0"
4
+ authors = [
5
+ { name = "Colin Zhang", email = "zsd0830@163.com" },
6
+ ]
7
+ dependencies = []
8
+ description = "可用于大部分项目的通用型函数库"
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ classifiers = [
12
+ "Programming Language :: Python :: 3",
13
+ "License :: OSI Approved :: MIT License",
14
+ "Operating System :: OS Independent",
15
+ ]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,461 @@
1
+ # -*- coding: utf-8 -*-
2
+ # @Time : 2024/11/13 10:00
3
+ # @Author : Zhang Shaodong
4
+ # @Email : zsd0830@163.com
5
+ # @File : universal_function.py
6
+ # @Info : 该脚本中包含通用的函数模块
7
+
8
+ import os
9
+ import time
10
+ import json
11
+ import pandas as pd
12
+ import random
13
+ import pymysql
14
+ import datetime
15
+ import bs4
16
+ import re
17
+ import sys
18
+
19
+
20
+ # 如果数据库改了,就要修改这里
21
+ ip_database = {"localhost": "wom_db_local", "BA_USING": "BA_USING", "BI_READ": "bi"} # 需修改本地数据库名
22
+ dic_connet = {"localhost": {'host': 'localhost', 'port': 3306, 'user': 'root', 'password': 'zwp650811', 'database': 'wom_db_local'},
23
+ "BA_USING": {'host': '10.26.241.164', 'port': 3306, 'user': 'BA_USING', 'password': 'BA_USING@2022', 'database': ip_database["BA_USING"]},
24
+ "BI_READ": {'host': '10.26.241.164', 'port': 3306, 'user': 'BI_READ', 'password': 'Bireader@1027', 'database': ip_database["BI_READ"]}}
25
+
26
+ # 通用功能
27
+ #########################################################################
28
+ # 功能:判断sth是否为NaN、None或者空字符串,NaN、None或者空字符串返回True,其他情况返回False
29
+ def is_nano(sth):
30
+ if not sth:
31
+ return True
32
+ if isinstance(sth, float):
33
+ if np.isnan(sth):
34
+ return True
35
+ return False
36
+
37
+
38
+ # 文件读取
39
+ #########################################################################
40
+
41
+ # 功能:读取json文件变成字典格式
42
+ # 输入:json_file - json文件的路径 - str
43
+ # 输出:data_dict - json文件转化成的字典 - dict
44
+ def read_json(json_file: str):
45
+ with open(json_file, 'r', encoding='utf-8') as load_f:
46
+ data_dict = json.load(load_f)
47
+ return data_dict
48
+
49
+
50
+ # 数据库相关
51
+ #########################################################################
52
+
53
+ # 功能:尝试多次连接数据库
54
+ def get_cursor_times(config, times):
55
+ cnt_conn = 0
56
+ while cnt_conn < times:
57
+ try:
58
+ conn = pymysql.connect(**config)
59
+ cursor = conn.cursor()
60
+ break
61
+ except:
62
+ print(f'数据库连接失败,现进行第{cnt_conn}次重新连接,总共{times}次重新连接的机会...')
63
+ sleep_some_seconds(20, 21, 1)
64
+ cnt_conn += 1
65
+ return cursor, conn
66
+
67
+
68
+ # 将dataframe写进数据库
69
+ def df2mysql(db_config, db, insert_df, insert_tbl, cover_flag):
70
+ if len(insert_df) != 0:
71
+ insert_cursor, insert_conn = get_cursor_times(db_config[db], 10000)
72
+ # 将dataframe中的Nan用None代替
73
+ insert_df = insert_df.where(insert_df.notnull(), None)
74
+ len_cols = insert_df.columns.size
75
+ insert_sql = f"{'replace' if cover_flag else 'insert ignore'} into {insert_tbl} values ({', '.join(['%s']*len_cols)})"
76
+ insert_data = (tuple(row) for _, row in insert_df.iterrows())
77
+ try:
78
+ insert_cursor.executemany(insert_sql, insert_data)
79
+ insert_conn.commit()
80
+ print(f"数据插入{insert_tbl}成功(๑•̀ㅂ•́)و✧")
81
+ except Exception as e:
82
+ print(e, f"数据插入{insert_tbl}失败:", insert_data)
83
+ finally:
84
+ insert_cursor.close()
85
+ insert_conn.close()
86
+ else:
87
+ print(f'无数据需要插入{insert_tbl}ε=(´ο`*)))')
88
+
89
+
90
+ # 功能:将dict格式的数据插入insert_db的insert_tbl中
91
+ # 输入样例
92
+ # insert_db = 'BA_USING'
93
+ # insert_tbl = 'autohome_policy_post'
94
+ # db_config = {"BA_USING": {'host': '10.26.241.164', 'port': 3306, 'user': 'BA_USING', 'password': 'BA_USING@2022',
95
+ # 'database': "BA_USING"}}
96
+ def dict2mysql(db_config, db, insert_dict, insert_tbl, cover_flag):
97
+ insert_cursor, insert_conn = gc.get_cursor_times(db_config[db], 10000)
98
+ keys = ", ".join(insert_dict.keys())
99
+ values = ", ".join(['%s'] * len(insert_dict.keys()))
100
+ if cover_flag:
101
+ insert_sql = '''
102
+ INSERT INTO {table}({keys}) VALUES ({values}) ON DUPLICATE KEY UPDATE
103
+ '''.format(table=insert_tbl, keys=keys, values=values)
104
+ update = ','.join([" {key} = values({key})".format(key=key) for key in insert_dict])
105
+ insert_sql += update
106
+ else:
107
+ insert_sql = """
108
+ INSERT ignore INTO {table}({keys}) VALUES ({values})
109
+ """.format(table=insert_tbl, keys=keys, values=values)
110
+ try:
111
+ insert_cursor.execute(insert_sql, tuple(insert_dict.values()))
112
+ insert_conn.commit()
113
+ print("数据库插入结果数据成功(๑•̀ㅂ•́)و✧")
114
+ except Exception as e:
115
+ print(e, "数据库插入数据失败:", insert_dict)
116
+ finally:
117
+ insert_cursor.close()
118
+ insert_conn.close()
119
+
120
+
121
+ # 功能:修正sql查询得到的数据,为其加入表头
122
+ def fix_sql_df(results, col_name_list):
123
+ col_name = []
124
+ for head in col_name_list:
125
+ col_name.append(head[0])
126
+ df = pd.DataFrame(list(results), columns=col_name)
127
+ return df
128
+
129
+
130
+ # 功能:查询某段sql,并返回一个df(带表头)
131
+ def read_sql2df(db, db_config, sql):
132
+ # 连接导入数据库
133
+ cursor, conn = get_cursor_times(db_config[db], 10000)
134
+ cursor.execute(sql)
135
+ results = cursor.fetchall() # 用于返回多条数据
136
+ col_name_list = cursor.description
137
+ cursor.close()
138
+ conn.close()
139
+ df = fix_sql_df(results, col_name_list)
140
+ return df
141
+
142
+
143
+ # 功能:执行一段sql,但不返回数据
144
+ def process_sql(db, db_config, sql):
145
+ cursor, conn = gc.get_cursor_times(db_config[db], 10000)
146
+ try:
147
+ cursor.execute(sql)
148
+ conn.commit()
149
+ except Exception as e:
150
+ conn.rollback()
151
+ print("执行失败:", e)
152
+ finally:
153
+ cursor.close()
154
+ conn.close()
155
+
156
+ # 时间处理的模块
157
+ #########################################################################
158
+
159
+ # 功能:获取当前时间,返回yyyymmddhhmmss格式的时间字符串
160
+ # 输入:-
161
+ # 输出:time_out - yyyymmddhhmmss格式的时间字符串 - str
162
+ def get_time_now():
163
+ time_out = time.strftime('%Y%m%d%H%M%S', time.localtime(time.time()))
164
+ return time_out
165
+
166
+
167
+ # 功能:获取当前时间,返回 %Y-%m-%d %H:%M:%S 格式的时间字符串
168
+ # 输入:-
169
+ # 输出:datetime_out - %Y-%m-%d %H:%M:%S格式的时间字符串 - str
170
+ def get_datetime_now():
171
+ datetime_out = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
172
+ return datetime_out
173
+
174
+
175
+ # 功能:比较两个"yyyy-mm-dd"格式时间字符串的大小
176
+ # 输入:time1 - 时间1 - str,如'2022-01-01'
177
+ # time2 - 时间2 - str,如'2022-01-01'
178
+ # identifier - 比较符,可选5种:大于(>)、大于等于(>=)、等于(=)、小于等于(<=)、小于(<) - str
179
+ # 输出:True/False - 比较结果 - bool
180
+ def compare_time_v1(time1: str, time2: str, identifier: str):
181
+ s_time = time.mktime(time.strptime(time1, '%Y-%m-%d'))
182
+ e_time = time.mktime(time.strptime(time2, '%Y-%m-%d'))
183
+ if identifier == '>':
184
+ if int(s_time) - int(e_time) > 0:
185
+ return True
186
+ else:
187
+ return False
188
+ if identifier == '<':
189
+ if int(s_time) - int(e_time) < 0:
190
+ return True
191
+ else:
192
+ return False
193
+ if identifier == '>=':
194
+ if int(s_time) - int(e_time) >= 0:
195
+ return True
196
+ else:
197
+ return False
198
+ if identifier == '<=':
199
+ if int(s_time) - int(e_time) <= 0:
200
+ return True
201
+ else:
202
+ return False
203
+ if identifier == '=':
204
+ if int(s_time) - int(e_time) == 0:
205
+ return True
206
+ else:
207
+ return False
208
+
209
+
210
+ # 功能:比较两个"yyyy-mm-dd hh:mm:ss"格式时间字符串的大小
211
+ # 输入:time1 - 时间1 - str,如'2022-01-01 00:00:00'
212
+ # time2 - 时间2 - str,如'2022-01-01 00:00:00'
213
+ # identifier - 比较符,可选5种:大于(>)、大于等于(>=)、等于(=)、小于等于(<=)、小于(<) - str
214
+ # 输出:True/False - 比较结果 - bool
215
+ def compare_time_v2(time1: str, time2: str, identifier: str):
216
+ s_time = time.mktime(time.strptime(time1, '%Y-%m-%d %H:%M:%S'))
217
+ e_time = time.mktime(time.strptime(time2, '%Y-%m-%d %H:%M:%S'))
218
+ if identifier == '>':
219
+ if int(s_time) - int(e_time) > 0:
220
+ return True
221
+ else:
222
+ return False
223
+ if identifier == '<':
224
+ if int(s_time) - int(e_time) < 0:
225
+ return True
226
+ else:
227
+ return False
228
+ if identifier == '>=':
229
+ if int(s_time) - int(e_time) >= 0:
230
+ return True
231
+ else:
232
+ return False
233
+ if identifier == '<=':
234
+ if int(s_time) - int(e_time) <= 0:
235
+ return True
236
+ else:
237
+ return False
238
+ if identifier == '=':
239
+ if int(s_time) - int(e_time) == 0:
240
+ return True
241
+ else:
242
+ return False
243
+
244
+
245
+ # 功能:将自epoch以来经过的秒数字符串转化为"yyyy-mm-dd hh:mm:ss"格式
246
+ # 输入:stamp_string - 自epoch以来经过的秒数字符串 - str,如'1545925769'
247
+ # 输出:date_time - "yyyy-mm-dd hh:mm:ss"格式的时间字符串 - str
248
+ def stamp2date(stamp_string: str):
249
+ time_array = time.localtime(int(stamp_string))
250
+ date_time = time.strftime("%Y-%m-%d %H:%M:%S", time_array)
251
+ return date_time
252
+
253
+
254
+ # 功能:随机sleep n - m 秒,k表示小数点后k位的时间
255
+ # 输入:m - 最短时间 - int
256
+ # n - 最长时间 - int
257
+ # k - 小数点后k位 - int
258
+ # 输出:True - 表示完成 - bool
259
+ def sleep_some_seconds(m: int, n: int, k: int):
260
+ time.sleep(round(random.uniform(m, n), k))
261
+ return True
262
+
263
+
264
+ # 功能:计算sec(秒数)与当前时间的时间间隔,并且输出指定格式的字符串形式
265
+ # 输入:sec - 最短时间 - int/str
266
+ # date_format - 指定的输出格式 - str
267
+ # 输出:time_gap - 指定格式的时间间隔 - str
268
+ def change2date(sec, date_format: str):
269
+ sec = int(sec)
270
+ time_gap = time.time() - sec
271
+ time_gap = time.strftime(date_format, time.localtime(time_gap))
272
+ return time_gap
273
+
274
+
275
+ # 功能:将n天前/n小时前/n周前转化为%Y-%m-%d %H:%M:%S的字符串格式
276
+ # 输入:before - 时间表达形式 - str
277
+ # 输出:datetime_str - 格式化的时间字符串 - str
278
+ def before2datetime(before: str):
279
+ before_str = re.findall(r"(\d{4}-\d{1,2}-\d{1,2}\s\d{1,2}:\d{1,2}:\d{1,2})", before)
280
+ if before_str != []:
281
+ datetime_str = before_str[0]
282
+ else:
283
+ if '前天' in before:
284
+ sec = 2 * 86400
285
+ datetime_str = change2date(sec, date_format='%Y-%m-%d %H:%M:%S')
286
+ elif '周前' in before:
287
+ a = re.findall('(.*?)天前', before)
288
+ sec = int(a[0]) * 7 * 86400
289
+ datetime_str = change2date(sec, date_format='%Y-%m-%d %H:%M:%S')
290
+ elif '天前' in before:
291
+ a = re.findall('(.*?)天前', before)
292
+ sec = int(a[0]) * 86400
293
+ datetime_str = change2date(sec, date_format='%Y-%m-%d %H:%M:%S')
294
+ elif '小时前' in before:
295
+ a = re.findall('(.*?)小时前', before)
296
+ sec = int(a[0]) * 3600
297
+ datetime_str = change2date(sec, date_format='%Y-%m-%d %H:%M:%S')
298
+ elif '分钟前' in before:
299
+ a = re.findall('(.*?)分钟前', before)
300
+ sec = int(a[0]) * 60
301
+ datetime_str = change2date(sec, date_format='%Y-%m-%d %H:%M:%S')
302
+ elif '秒钟前' in before:
303
+ a = re.findall('(.*?)秒钟前', before)
304
+ sec = int(a[0])
305
+ datetime_str = change2date(sec, date_format='%Y-%m-%d %H:%M:%S')
306
+ elif '刚刚' in before:
307
+ sec = 0
308
+ datetime_str = change2date(sec, date_format='%Y-%m-%d %H:%M:%S')
309
+ else:
310
+ print('意外的时间表达方式!!!!!!return当前时间')
311
+ sec = 0
312
+ datetime_str = change2date(sec, date_format='%Y-%m-%d %H:%M:%S')
313
+ return datetime_str
314
+
315
+
316
+ # 功能:将yyyymmdd-yyyymmdd格式的字符串拆分,并转化为前后两个时间的起始及结束datetime
317
+ # 输入:text - 两个时间的表达形式,yyyymmdd-yyyymmdd - str
318
+ # 输出:True/False - 若输入不符合格式要求,则直接返回False - bool
319
+ # start_dt - 起始的dateframe字符串
320
+ # end_dt - 结束的dateframe字符串
321
+ def split_yyyymmdd(text: str):
322
+ date_list = text.split('-')
323
+ start_text = date_list[0]
324
+ end_text = date_list[1]
325
+ if len(date_list) != 2 or len(start_text) != 8 or len(end_text) != 8 or int(start_text) > int(end_text):
326
+ return False, '', ''
327
+ else:
328
+ start_dt = start_text[:4] + '-' + start_text[4:6] + '-' + start_text[6:8] + ' 00:00:00'
329
+ end_dt = end_text[:4] + '-' + end_text[4:6] + '-' + end_text[6:8] + ' 23:59:59'
330
+ return True, start_dt, end_dt
331
+
332
+
333
+ # 功能:根据当前时间,反馈现在是周几
334
+ # 输入:-
335
+ # 输出:weekday - 周几 - str
336
+ def get_day_of_week():
337
+ day_of_week = datetime.datetime.now().weekday() + 1
338
+ if day_of_week == 1:
339
+ weekday = '周一'
340
+ elif day_of_week == 2:
341
+ weekday = '周二'
342
+ elif day_of_week == 3:
343
+ weekday = '周三'
344
+ elif day_of_week == 4:
345
+ weekday = '周四'
346
+ elif day_of_week == 5:
347
+ weekday = '周五'
348
+ elif day_of_week == 6:
349
+ weekday = '周六'
350
+ else:
351
+ weekday = '周日'
352
+ return weekday
353
+
354
+
355
+ # 功能:根据输入的date格式,得到n_day前的date格式日期
356
+ # 输入:date_start - 起始的日期 - datetime.date
357
+ # n_day - n天前 - int
358
+ # 输出:date_before - n_day天之前的date - datetime.date
359
+ def get_date_before(date_start, n_day):
360
+ days = datetime.timedelta(days=n_day)
361
+ date_before = date_start - days
362
+ return date_before
363
+
364
+
365
+ # excel处理模块
366
+ #########################################################################
367
+
368
+ # 功能:将一个df写入到excel的指定位置
369
+ def wirte_df2excel(goal_sheet, start_row, start_col, df_input, align_style, header_include=False):
370
+ col_idx = start_col
371
+ # 如果表头也要写入,就把表头放在第一行
372
+ if header_include:
373
+ df_input.T.reset_index().rename(columns={'index': '列名'}).T
374
+ for row in df_input.iteritems():
375
+ input_list = row[1].apply(str).to_list()
376
+ row_idx = start_row
377
+ for ele in input_list:
378
+ try:
379
+ goal_sheet.cell(row=row_idx, column=col_idx).value = ele
380
+ goal_sheet.cell(row=row_idx, column=col_idx).alignment = align_style
381
+ except:
382
+ print('无法写入:', ele)
383
+ row_idx += 1
384
+ col_idx += 1
385
+
386
+
387
+ # 功能:将一个series写入到excel的指定位置
388
+ def write_series2excel(goal_sheet, start_row, start_col, series_input, align_style, value_only=False, top_n=10000000):
389
+ cnt = 0
390
+ for idx, val in series_input.items():
391
+ if val is not None:
392
+ # 如果要把索引也记录上
393
+ if not value_only:
394
+ goal_sheet.cell(row=start_row, column=start_col).value = idx
395
+ goal_sheet.cell(row=start_row, column=start_col+1).value = val
396
+ goal_sheet.cell(row=start_row, column=start_col).alignment = align_style
397
+ goal_sheet.cell(row=start_row, column=start_col+1).alignment = align_style
398
+ else:
399
+ goal_sheet.cell(row=start_row, column=start_col).value = val
400
+ goal_sheet.cell(row=start_row, column=start_col).alignment = align_style
401
+ cnt += 1
402
+ if cnt >= top_n:
403
+ break
404
+ start_row += 1
405
+
406
+
407
+ # 功能:将一个数值写入到excel的指定位置
408
+ def write_val2excel(goal_sheet, row_pos, col_pos, val, align_style):
409
+ goal_sheet.cell(row=row_pos, column=col_pos).value = val
410
+ goal_sheet.cell(row=row_pos, column=col_pos).alignment = align_style
411
+
412
+
413
+
414
+ # 自动化处理模块
415
+ #########################################################################
416
+
417
+ # 功能:自动发送指定邮件给指定的人
418
+ # 输入:f_origin - 宏文件的地址 - str
419
+ # to_list - 发送的用户清单 - list
420
+ # cc_list - 抄送的用户清单 - list
421
+ # attached_list - 附件的地址list,支持最多两个附件 - list
422
+ # subject_text - 邮件标题 - str
423
+ # content_text - 正文内容 - str
424
+ # 输出:-
425
+ def send_mail(f_origin, to_list, cc_list, attached_list, subject_text, content_text):
426
+ if len(attached_list) > 2:
427
+ print('附件数过多,请缩减至2个及以下的附件。')
428
+ sys.quit()
429
+ to_string = '; '.join(to_list)
430
+ cc_string = '; '.join(cc_list)
431
+ # 更新xlsm的内容信息
432
+ print('开始对xlsm的内容信息进行更新...')
433
+ wb = load_workbook(f_origin, keep_vba=True)
434
+ ws_1 = wb.get_sheet_by_name('发送清单')
435
+ ws_1.cell(row=2, column=1).value = to_string
436
+ ws_1.cell(row=2, column=2).value = cc_string
437
+ n_idx = 3
438
+ for attached in attached_list:
439
+ ws_1.cell(row=2, column=n_idx).value = attached
440
+ n_idx += 1
441
+ ws_2 = wb.get_sheet_by_name('正文')
442
+ ws_2.cell(row=1, column=2).value = subject_text
443
+ ws_2.cell(row=2, column=2).value = content_text
444
+ f_goal = f_origin[:-5] + f'_tmp_{get_time_now()}.xlsm'
445
+ wb.save(f_goal)
446
+ time.sleep(3)
447
+ # 通过excel的宏进行发送
448
+ app = xw.App(visible=False, add_book=False)
449
+ app.screen_updating = False
450
+ # 宏文件
451
+ wb = app.books.open(f_goal)
452
+ # 执行宏文件
453
+ marco = wb.macro('Mygirl') # 这里需要特别注意,当你的宏名是唯一的时候,不需要写模块名,但如果模块名和宏名重复,需要补全
454
+ marco()
455
+ time.sleep(3) # 等待macro运行完毕,具体等待时长视宏运行的时间
456
+ # 保存关闭退出
457
+ wb.save()
458
+ wb.close()
459
+ app.quit()
460
+ print('邮件发送成功(๑•̀ㅂ•́)و✧')
461
+ os.remove(f_goal)
@@ -0,0 +1,14 @@
1
+ Metadata-Version: 2.1
2
+ Name: universal_function_zsd
3
+ Version: 1.0.0
4
+ Summary: 可用于大部分项目的通用型函数库
5
+ Author-email: Colin Zhang <zsd0830@163.com>
6
+ Classifier: Programming Language :: Python :: 3
7
+ Classifier: License :: OSI Approved :: MIT License
8
+ Classifier: Operating System :: OS Independent
9
+ Requires-Python: >=3.10
10
+ Description-Content-Type: text/markdown
11
+ License-File: LICENSE
12
+
13
+ 本函数包一般用于现有的项目,具备一定的通用性;
14
+ 目前由张绍东维护,有任何问题可咨询zsd0830@163.com。
@@ -0,0 +1,10 @@
1
+ LICENSE
2
+ MANIFEST.in
3
+ README.md
4
+ pyproject.toml
5
+ src/universal_function_zsd/__init__.py
6
+ src/universal_function_zsd/universal_function.py
7
+ src/universal_function_zsd.egg-info/PKG-INFO
8
+ src/universal_function_zsd.egg-info/SOURCES.txt
9
+ src/universal_function_zsd.egg-info/dependency_links.txt
10
+ src/universal_function_zsd.egg-info/top_level.txt