smartpush 1.3.1__py3-none-any.whl → 1.3.4__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.
@@ -1,74 +1,415 @@
1
+ import datetime
2
+ import json
3
+ import requests
1
4
  from jira import JIRA
2
- import re
5
+ from datetime import datetime
6
+ from smartpush.utils.StringUtils import StringUtils
3
7
 
4
- def get_jira_info(jira_user, jira_api_key):
8
+ test_user = {
9
+ "邵宇飞": "dw_shaoyufei",
10
+ "卢泽彬-Lulu-QA": "dw_luzebin",
11
+ "xiangchen zhong": "dw_zhongxiangchen",
12
+ "周彦龙": "dw_zhouyanlong",
13
+ "梁铭津-bryant": "dw_liangmingjin",
14
+ "高忠明 - gaozhongming": "dw_gaozhongming",
15
+ "jiayong zhang": "dw_zhangjiayong",
16
+ "毕杰芳-Dawn Bi": "dw_bijiefang",
17
+ "李志": "dw_lizhi7",
18
+ "张玉吉-小橙C": "dw_zhangyuji",
19
+ "周艳辉-zhouyanhui-QA": "dw_zhouyanhui",
20
+ "zhaoyi wang": "dw_wangzhaoyi",
21
+ "测试-陈美伶-Zoe": "dw_chenmeiling",
22
+ "黄伟灵": "dw_huangweiling"
23
+ }
24
+
25
+
26
+ def get_last_friday_and_this_thursday():
5
27
  """
6
- 获取jira对象
7
- @return:
28
+ 获取上个周五和本周四的日期
29
+ :return:
8
30
  """
9
- # api_key = "ATATT3xFfGF0JPzR4t2coi53yM2eKZfUy5eXJSbZHqWmbX9PzStyaNCM2lEjn_uP5TkOl_p4pqZCICH5ZqdWkdmfSxJmTsn6AOcU7I3vVWnDl0i1PRktMdSSqWs1yg1JVSVtlGCrMKfZaztsJOjAQsp3Jd6hHdKpB4A4nVBBkmB7sDOpsNbTNeY=910B5249"
31
+ today = datetime.date.today()
32
+ # 计算今天是星期几,0 表示周一,6 表示周日
33
+ weekday = today.weekday()
34
+ # 计算距离上周五的天数
35
+ days_to_last_friday = (weekday + 3) % 7
36
+ if days_to_last_friday == 0:
37
+ days_to_last_friday = 7
38
+ # 得到上周五的日期
39
+ last_friday = today - datetime.timedelta(days=days_to_last_friday)
40
+ # 得到本周四的日期
41
+ this_thursday = last_friday + datetime.timedelta(days=6)
42
+ return last_friday, this_thursday
10
43
 
11
- # Jira 服务器的 URL
12
- jira_url = "https://shopline.atlassian.net/"
13
- # # Jira API 密钥
14
- # jira_api_key = api_key
15
- # # Jira 用户名
16
- # jira_user = "lu.lu@shopline.com"
17
44
 
18
- # 连接到 Jira 服务器
19
- jira = JIRA(server=jira_url, basic_auth=(jira_user, jira_api_key))
20
- return jira
45
+ def get_update_issues_jql():
46
+ """
47
+ 根据上周五到本周四的日期范围生成 JQL 查询语句
48
+ """
21
49
 
50
+ # 获取上周五和本周四的日期
51
+ start_date, end_date = get_last_friday_and_this_thursday()
22
52
 
23
- def get_jira_prodcut(jira, project_key):
24
- project = jira.project(str(project_key))
25
- print(f"Project: {project.key} - {project.name}")
26
- return project
53
+ # 定义 JQL 模板
54
+ jql_template = f'''
55
+ project = "SSP"
56
+ AND issuetype IN (产品需求, 技术需求)
57
+ AND (("计划上线时间[date]" >= "{{start_date}}"
58
+ AND "计划上线时间[date]" <= "{{end_date}}" and "调整后上线时间[Date]" is EMPTY)
59
+ OR ("实际上线时间[date]" >= "{{start_date}}"
60
+ AND "实际上线时间[date]" <= "{{end_date}}") OR ("调整后上线时间[Date]" >= "{{start_date}}"
61
+ AND "调整后上线时间[Date]" <= "{{end_date}}"))
62
+ ORDER BY cf[12536] ASC, key ASC, cf[12466] ASC, status DESC, created DESC
63
+ '''
64
+ # 填充模板中的日期
65
+ jql_update = jql_template.format(
66
+ start_date=start_date,
67
+ end_date=end_date,
68
+ )
69
+ print(jql_update)
70
+ return jql_update
27
71
 
28
72
 
29
- def get_custom_fields(jira_obj, project_key='10559'):
30
- """
31
- 查询指定项目jira中的自定义字段,smartpush项目是 10559
32
- @param project_id: 项目id
33
- @param jira_obj: 对象
34
- @return:
35
- """
36
- all_fields = jira_obj.fields()
37
- # print("all_fields:",all_fields)
38
- custom_fields = {}
39
- for field in all_fields:
40
- try:
41
- if field.get('custom'):
42
- if field['scope']['project']['id'] == str(project_key):
73
+ class JiraInfo:
74
+ def __init__(self, _jira_user, _api_key):
75
+ self.project_name = None
76
+ self.jira_url = "https://shopline.atlassian.net/"
77
+ # self.project_key = _project_key
78
+ self.issue = None
79
+ self.jira_user = _jira_user
80
+ self.jira_api_key = _api_key
81
+ self.jira = JIRA(server=self.jira_url, basic_auth=(self.jira_user, self.jira_api_key))
82
+ # self.get_jira_prodcut()
83
+ self.custom_fields = self.get_custom_fields()
84
+
85
+ # def get_jira_prodcut(self):
86
+ # """"""
87
+ # project = self.jira.project(str(self.project_key))
88
+ # self.project_name = project.name
89
+ # print(f"Project: {project.key} - {project.name}")
90
+ # return project
91
+
92
+ def get_custom_fields(self) -> dict:
93
+ """
94
+ 查询指定项目jira中的自定义字段,smartpush项目是 10559 商品是 10092
95
+ @param project_id: 项目id
96
+ @param jira_obj: 对象
97
+ @return: 返回的是自定义的值对应的id
98
+ :param project_key:
99
+ """
100
+ all_fields = self.jira.fields()
101
+ custom_fields = {}
102
+ for field in all_fields:
103
+ try:
104
+ if field.get('custom'):
43
105
  custom_fields[field['id']] = field['name']
44
- except:
45
- continue
46
- print("custom_fields:", custom_fields)
47
- return custom_fields
48
-
49
-
50
- def get_custom_fields_map(jira, project_key=10559):
51
- # 获取项目的问题
52
- issues = jira.search_issues(f"project={project_key}")
53
- issue = jira.issue(issues[0])
54
- custom_fields = get_custom_fields(jira, project_key)
55
- print(custom_fields)
56
- fields_map = {}
57
- for field_name, field_value in issue.fields.__dict__.items():
106
+ except:
107
+ continue
108
+ # print(custom_fields)
109
+ return custom_fields
110
+
111
+ def get_jira_issues_by_jql(self, filter_id=None, jql=None):
112
+ """
113
+ 根据过滤id查询,或者jql查询
114
+ :param filter_id:
115
+ :param jql:
116
+ :return:
117
+ """
118
+ if filter_id:
119
+ filter_obj = self.jira.filter(filter_id)
120
+ jql = filter_obj.jql
121
+ elif jql is None:
122
+ default_jql_str = f'project = SSP'
58
123
  try:
59
- if field_name.startswith("customfield_"):
60
- fields_map[custom_fields[field_name]] = field_value
61
- print(f"Custom Field ID: {field_name}, NAME:{custom_fields[field_name]}, Value: {field_value}")
124
+ all_issues = {}
125
+ start_at = 0
126
+ max_results = 100 # 每次查询的最大结果数
127
+ while True:
128
+ # 构建 JQL 查询语句,根据项目 key 进行查询
129
+ jql_str = jql if jql else default_jql_str
130
+ print(f"执行查询的jql语句为:{jql_str}")
131
+ # 执行 JQL 查询获取 issues
132
+ issues = self.jira.search_issues(jql_str=jql_str, startAt=start_at, maxResults=max_results)
133
+ if not issues:
134
+ break
135
+ for issue in issues:
136
+ self.issue = issue
137
+ datas = self.custom_value_type()
138
+ all_issues[self.issue.key] = datas
139
+ if len(issues) < max_results:
140
+ break
141
+ start_at += max_results
142
+ return all_issues
143
+ except Exception as e:
144
+ raise
145
+ # return {'error': str(e)}
146
+
147
+ def custom_value_type(self):
148
+ """
149
+ 用于获取自定义字段的key和value值的处理
150
+ :return:
151
+ """
152
+ custom_value_info = {}
153
+ for custom_field_id, custom_field_value in self.issue.raw['fields'].items():
154
+ custom_field_id = self.custom_fields.get(custom_field_id, custom_field_id)
155
+ if custom_field_id in ["comment", "attachment"]:
156
+ custom_field_value = "省略内容..有需要再打开,在这方法过滤:custom_value_type"
157
+ custom_field_value = self.transform_data(custom_field_value) # 转换数据
158
+ custom_value_info['url'] = self.jira_url + 'browse/' + self.issue.key
159
+ custom_value_info[custom_field_id] = custom_field_value
160
+ return custom_value_info
161
+
162
+ def transform_data(self, data):
163
+ """
164
+ 转换数据,否则数据冗余的有点多
165
+ :param data:
166
+ :return:
167
+ """
168
+ if not isinstance(data, list) and not isinstance(data, dict):
169
+ return data
170
+ if isinstance(data, list):
171
+ result = []
172
+ for item in data:
173
+ if isinstance(item, dict):
174
+ for priority_key in ['value', 'name', 'displayName']:
175
+ if priority_key in item:
176
+ result.append(item[priority_key])
177
+ break
178
+ else:
179
+ result.append(item)
180
+ else:
181
+ result.append(item)
182
+ return result
183
+ elif isinstance(data, dict):
184
+ for priority_key in ['value', 'name', 'displayName']:
185
+ if priority_key in data:
186
+ return data[priority_key]
187
+ return data
188
+ return data
189
+
190
+ def update_filter_jql(self, filter_id=None, new_jql=None, double_check=False):
191
+
192
+ try:
193
+ if new_jql is None:
194
+ new_jql = get_update_issues_jql()
195
+ # 获取过滤器对象
196
+ filter_obj = self.jira.filter(filter_id)
197
+ # 更新过滤器的 JQL
198
+ if str(filter_id) == '19030' or double_check:
199
+ filter_obj.update(jql=new_jql)
200
+ print(f"过滤器 {filter_id} 的 JQL 已更新为: {new_jql}")
62
201
  else:
63
- fields_map[field_name] = field_value
64
- print(f"ID: {field_name},Value: {field_value}")
65
- except:
66
- # raise
67
- continue
68
- print('fields_map:',fields_map)
69
- if __name__ == '__main__':
70
- api_key = "ATATT3xFfGF0JPzR4t2coi53yM2eKZfUy5eXJSbZHqWmbX9PzStyaNCM2lEjn_uP5TkOl_p4pqZCICH5ZqdWkdmfSxJmTsn6AOcU7I3vVWnDl0i1PRktMdSSqWs1yg1JVSVtlGCrMKfZaztsJOjAQsp3Jd6hHdKpB4A4nVBBkmB7sDOpsNbTNeY=910B5249"
71
- # Jira 用户名
72
- jira_user = "lu.lu@shopline.com"
73
- jira = get_jira_info(jira_user, api_key)
74
- get_custom_fields_map(jira)
202
+ print(f"{new_jql} 更新失败!")
203
+ except Exception as e:
204
+ print(f"更新过滤器 JQL 时出错: {e}")
205
+
206
+ def product_and_ui_acceptance_notice(self, webhook, datas):
207
+ """
208
+ 每周一早上11点通知产品/UI验收
209
+ 1、有前端工作量时才需要通知ui
210
+ 2、列出对应的ui,没有显示未填写
211
+ :return:
212
+ """
213
+ fixVersions = ""
214
+ content = ""
215
+ for key, value in datas.items():
216
+ if value.get("issuetype") == "产品需求":
217
+ summary = value.get("summary")
218
+ url = value.get("url")
219
+ tester_user_id = self.get_tester_wecom_userid(value.get("测试人员"), test_user)
220
+ product_manager = value.get("产品经理")
221
+ ued = value.get("设计师")
222
+ fixVersions = value.get("fixVersions")
223
+ content += f"> [{key + '-' + summary}]({url})\n PM:{product_manager}\n" \
224
+ f"UED:{ued}\n测试:{tester_user_id} \n\n "
225
+ content = f"### <font color=\"warning\"> 提醒本周{fixVersions}上线产品需求验收</font> \n" + content
226
+ self.send_wecom_robot_message(webhook, content)
227
+
228
+ def registration_coverage_notice(self, webhook, datas):
229
+ """
230
+ 测试环境通知登记覆盖率--每周三早上
231
+ 1、有后端开发工作量时才提示
232
+ 2、并且把填写的链接附上
233
+ :return:
234
+ """
235
+ content = ""
236
+ for key, value in datas.items():
237
+ if value.get("后端工作量") > 0:
238
+ summary = value.get("summary")
239
+ url = value.get("url")
240
+ tester_user_id = self.get_tester_wecom_userid(value.get("测试人员"), test_user)
241
+ test_end_time = value.get("测试完成时间(测试环境)")
242
+ content += f"> [{key + '-' + summary}]({url}) \n测试:{tester_user_id} \n测试完成时间:{test_end_time}\n\n "
243
+ content = f"### <font color=\"warning\"> 本周涉及后端需求如下,请分析并登记覆盖率报告,周会前填写</font> \n" + content
244
+ self.send_wecom_robot_message(webhook, content)
245
+
246
+ def registration_coverage_notice_every_day(self, webhook, datas):
247
+ """
248
+ 1、有后端开发工作量时才提示
249
+ 2、并且把填写的链接附上
250
+ :return:
251
+ """
252
+ content = ""
253
+ today = datetime.today().strftime('%Y-%m-%d')
254
+ for key, value in datas.items():
255
+ adjusted_test_completion_time = value.get("调整后测试完成时间(测试环境)")
256
+ test_end_time = value.get("测试完成时间(测试环境)") if adjusted_test_completion_time is None else adjusted_test_completion_time
257
+ test_end_text = '测试完成时间(测试环境)' if adjusted_test_completion_time is None else '调整后测试完成时间(测试环境)'
258
+ test_end_time_new = datetime.strptime(test_end_time, "%Y-%m-%d").strftime('%Y-%m-%d') if test_end_time is not None else None
259
+ summary = value.get("summary")
260
+ url = value.get("url")
261
+ backend_workload = value.get("后端工作量")
262
+ if test_end_time is not None and backend_workload is not None and backend_workload > 0 and test_end_time_new == today:
263
+ tester_user_id = self.get_tester_wecom_userid(value.get("测试人员"), test_user)
264
+ content += f"> [{key + '-' + summary}]({url}) \n后端工作量:{backend_workload}\n测试人员:{tester_user_id} \n{test_end_text}:{test_end_time}\n\n "
265
+ if StringUtils.is_empty(content):
266
+ print(f"*** {today} 无涉及覆盖率登记需求,不发送通知 ***")
267
+ return
268
+ content = f"### <font color=\"warning\"> 涉及后端需求,测试完成后,请分析并登记覆盖率报告</font> \n" + content
269
+ self.send_wecom_robot_message(webhook, content)
270
+
271
+ def bug_not_closed_notice(self, webhook, datas):
272
+ """
273
+ 预发环境或者测试环境通知bug还未关闭的需求,每周二,周三执行
274
+ 1、'待修复', '修复中', '待验证'
275
+ :return:
276
+ """
277
+ content = ""
278
+ for key, value in datas.items():
279
+ issuelinks = value['issuelinks']
280
+ not_fixed_dict = self.is_bug_not_fixed(issuelinks)
281
+ if not_fixed_dict:
282
+ summary = value.get("summary")
283
+ url = value.get("url")
284
+ tester_user_id = self.get_tester_wecom_userid(value.get("测试人员"), test_user)
285
+ content += f"> [{key + '-' + summary}]({url}) \n暂未修复bug数量:{len(not_fixed_dict)}\n测试:{tester_user_id} \n\n "
286
+ if StringUtils.is_empty(content):
287
+ print("无待修复bug..不发送通知")
288
+ return
289
+ content = f"### <font color=\"warning\"> 提醒本周上线需求暂未修复缺陷,请尽快确认</font> \n" + content
290
+ self.send_wecom_robot_message(webhook, content)
291
+ # print(content)
292
+
293
+ def modify_the_online_status_of_jira_notice(self, webhook, datas):
294
+ """
295
+ 每周四上线完通知修改jira上线日期、上线状态、自动化工作量填写 -- 每周四下午4点
296
+ 1、显示jira状态
297
+ 2、jira链接
298
+ 3、测试人员
299
+ :return:
300
+ """
301
+ content = ""
302
+ fixVersions = ""
303
+ for key, value in datas.items():
304
+ summary = value.get("summary")
305
+ url = value.get("url")
306
+ tester_user_id = self.get_tester_wecom_userid(value.get("测试人员"), test_user)
307
+ status = value.get("status")
308
+ actually_online_time = value.get("实际上线时间")
309
+ automated_testing_workload = value.get("自动化测试工作量")
310
+ automation_saves_labor_time = value.get("自动化节省工时")
311
+ fixVersions = value.get("fixVersions")
312
+ content += f"> [{key + '-' + summary}]({url}) \n状态:{status}\n实际上线时间:{actually_online_time}\n自动化测试工作量:{automated_testing_workload}\n自动节省工时:{automation_saves_labor_time}\n" \
313
+ f"测试:{tester_user_id} \n\n "
314
+ content = f"### <font color=\"warning\"> 版本{fixVersions}需求已上线,请更新jira数据,进行版本收尾</font> \n" + content
315
+ self.send_wecom_robot_message(webhook, content)
316
+
317
+ def get_tester_wecom_userid(self, tester, user_data):
318
+ """
319
+ 获取名字用于群里@使用
320
+ :param user_data: 用户id映射关系
321
+ :param tester: 传名字
322
+ :param data:数据结构
323
+ :return:
324
+ """
325
+ mobile_string = ""
326
+ if tester is None:
327
+ return None
328
+ for name in tester:
329
+ user_id = user_data.get(name, None)
330
+ mobile_string += f"<@{user_id}>"
331
+ return mobile_string
332
+
333
+ def is_bug_not_fixed(self, issuelinks) -> dict:
334
+ """
335
+ 查询未修复的bug
336
+ :param issuelinks:
337
+ :return:
338
+ """
339
+ not_fixed_bug_dict = {}
340
+ not_fixed_status_list = ['待修复', '修复中', '待验证']
341
+ for issue in issuelinks:
342
+ if issue.get('type').get('id') == '10003': # bug类型
343
+ status_name = issue['inwardIssue']['fields']['status']['name']
344
+ bug_key = issue['inwardIssue']['key']
345
+ bug_name = issue['inwardIssue']['fields']['summary']
346
+ if status_name in not_fixed_status_list:
347
+ not_fixed_bug_dict[bug_key] = bug_name
348
+ return not_fixed_bug_dict
349
+
350
+ def send_wecom_robot_message(self, webhook_url, content, msg_type='markdown'):
351
+ headers = {
352
+ 'Content-Type': 'application/json'
353
+ }
354
+ if msg_type == 'text':
355
+ data = {
356
+ "msgtype": "text",
357
+ "text": {
358
+ "content": content
359
+ }
360
+ }
361
+ elif msg_type == 'markdown':
362
+ data = {
363
+ "msgtype": "markdown",
364
+ "markdown": {
365
+ "content": content
366
+ }
367
+ }
368
+ elif msg_type == 'link':
369
+ if not isinstance(content, dict) or 'title' not in content or 'text' not in content or 'url' not in content:
370
+ raise ValueError("link类型消息content必须是包含title、text、url的字典")
371
+ data = {
372
+ "msgtype": "link",
373
+ "link": content
374
+ }
375
+ elif msg_type == 'file':
376
+ if not isinstance(content, dict) or 'media_id' not in content:
377
+ raise ValueError("file类型消息content必须是包含media_id的字典")
378
+ data = {
379
+ "msgtype": "file",
380
+ "file": content
381
+ }
382
+ elif msg_type == 'image':
383
+ if not isinstance(content, dict) or 'media_id' not in content:
384
+ raise ValueError("image类型消息content必须是包含media_id的字典")
385
+ data = {
386
+ "msgtype": "image",
387
+ "image": content
388
+ }
389
+ elif msg_type == 'news':
390
+ if not isinstance(content, list):
391
+ raise ValueError("news类型消息content必须是列表")
392
+ for item in content:
393
+ if not isinstance(item,
394
+ dict) or 'title' not in item or 'description' not in item or 'url' not in item or 'picurl' not in item:
395
+ raise ValueError("news类型消息content列表中的每个元素必须是包含title、description、url、picurl的字典")
396
+ data = {
397
+ "msgtype": "news",
398
+ "news": {
399
+ "articles": content
400
+ }
401
+ }
402
+ else:
403
+ raise ValueError("不支持的消息类型,请选择text、markdown、link、file、image、news")
404
+
405
+ try:
406
+ response = requests.post(webhook_url, headers=headers, data=json.dumps(data))
407
+ response.raise_for_status()
408
+ print("发送企微消息成功!")
409
+ return response.json()
410
+ except requests.RequestException as e:
411
+ print(f"请求出错: {e}")
412
+ return None
413
+ except ValueError as e:
414
+ print(f"解析响应出错: {e}")
415
+ return None
smartpush/test.py CHANGED
@@ -1,41 +0,0 @@
1
- # -*- codeing = utf-8 -*-
2
- # @Time :2025/2/20 00:27
3
- # @Author :luzebin
4
- import pandas as pd
5
-
6
- from smartpush.export.basic.ExcelExportChecker import check_excel_all, read_excel_and_write_to_list, \
7
- read_excel_from_oss, read_excel_csv_data, check_excel
8
- from smartpush.export.basic.ReadExcel import read_excel_from_oss
9
- from smartpush.export.basic.ReadExcel import read_excel_and_write_to_dict
10
- from smartpush.export.basic.GetOssUrl import get_oss_address_with_retry, export_requestParam, import_requestParam
11
-
12
- if __name__ == '__main__':
13
- oss1 = "https://cdn.smartpushedm.com/material_ec2/2025-02-25/58c4a3a885884741b22380c360ac2894/【自动化导出】营销活动URL点击与热图.xlsx"
14
- oss2 = "https://cdn.smartpushedm.com/material_ec2/2025-02-27/a5e18e3b3a83432daca871953cb8471b/【自动化导出】营销活动URL点击与热图.xlsx"
15
- # # print(check_excel_all(oss1, oss1))
16
- oss3 = "https://cdn.smartpushedm.com/material_ec2/2025-02-25/58c4a3a885884741b22380c360ac2894/【自动化导出】营销活动URL点击与热图.xlsx"
17
- oss4 = "https://cdn.smartpushedm.com/material_ec2/2025-02-26/58cee630b4c84eec9572b867af4ce692/%E3%80%90%E8%87%AA%E5%8A%A8%E5%8C%96%E5%AF%BC%E5%87%BA%E3%80%91%E8%90%A5%E9%94%80%E6%B4%BB%E5%8A%A8URL%E7%82%B9%E5%87%BB%E4%B8%8E%E7%83%AD%E5%9B%BE.xlsx"
18
- expected_oss = "https://cdn.smartpushedm.com/material_ec2/2025-02-26/757df7e77ce544e193257c0da35a4983/%E3%80%90%E8%87%AA%E5%8A%A8%E5%8C%96%E5%AF%BC%E5%87%BA%E3%80%91%E8%90%A5%E9%94%80%E6%B4%BB%E5%8A%A8%E6%95%B0%E6%8D%AE%E6%A6%82%E8%A7%88.xlsx"
19
- actual_oss = "https://cdn.smartpushedm.com/material_ec2/2025-02-26/757df7e77ce544e193257c0da35a4983/%E3%80%90%E8%87%AA%E5%8A%A8%E5%8C%96%E5%AF%BC%E5%87%BA%E3%80%91%E8%90%A5%E9%94%80%E6%B4%BB%E5%8A%A8%E6%95%B0%E6%8D%AE%E6%A6%82%E8%A7%88.xlsx"
20
-
21
- e_person_oss1 = "https://cdn.smartpushedm.com/material_ec2/2025-02-27/b48f34b3e88045d189631ec1f0f23d51/%E5%AF%BC%E5%87%BA%E5%85%A8%E9%83%A8%E5%AE%A2%E6%88%B7.csv"
22
- a_person_oss2 = "https://cdn.smartpushedm.com/material_ec2/2025-02-27/c50519d803c04e3b9b52d9f625fed413/%E5%AF%BC%E5%87%BA%E5%85%A8%E9%83%A8%E5%AE%A2%E6%88%B7.csv"
23
- host = "https://test.smartpushedm.com/api-em-ec2"
24
- reqHeaders = {
25
- 'cookie': 'osudb_appid=SMARTPUSH;osudb_oar=#01#SID0000123BL6ciRHRKpvOm/vWT9OS9brpfhSErcOdgeXJc0RJFopg83z0N3RzDE4w2DE5cQj6ALkLP8vG6Rhs0sR7NfToZvCLWXdQtYk6DJoKe4tqdo4kNcIc9F5obzLuyRmwGy9CZKcg/bMlmNyDZwBI1SIO;osudb_subappid=1;osudb_uid=4213785247;ecom_http_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3NDM4NDI1NTIsImp0aSI6IjEwNGQwOTVjLTA3MDItNDI5MC1iZjQzLWQ4YTVhNjdmNDM2NSIsInVzZXJJbmZvIjp7ImlkIjowLCJ1c2VySWQiOiI0MjEzNzg1MjQ3IiwidXNlcm5hbWUiOiIiLCJlbWFpbCI6ImZlbGl4LnNoYW9Ac2hvcGxpbmVhcHAuY29tIiwidXNlclJvbGUiOiJvd25lciIsInBsYXRmb3JtVHlwZSI6Nywic3ViUGxhdGZvcm0iOjEsInBob25lIjoiIiwibGFuZ3VhZ2UiOiJ6aC1oYW5zLWNuIiwiYXV0aFR5cGUiOiIiLCJhdHRyaWJ1dGVzIjp7ImNvdW50cnlDb2RlIjoiQ04iLCJjdXJyZW5jeSI6IkpQWSIsImN1cnJlbmN5U3ltYm9sIjoiSlDCpSIsImRvbWFpbiI6InNtYXJ0cHVzaDQubXlzaG9wbGluZXN0Zy5jb20iLCJsYW5ndWFnZSI6ImVuIiwibWVyY2hhbnRFbWFpbCI6ImZlbGl4LnNoYW9Ac2hvcGxpbmUuY29tIiwibWVyY2hhbnROYW1lIjoiU21hcnRQdXNoNF9lYzJf6Ieq5Yqo5YyW5bqX6ZO6IiwicGhvbmUiOiIiLCJzY29wZUNoYW5nZWQiOmZhbHNlLCJzdGFmZkxhbmd1YWdlIjoiemgtaGFucy1jbiIsInN0YXR1cyI6MCwidGltZXpvbmUiOiJBc2lhL01hY2FvIn0sInN0b3JlSWQiOiIxNjQ0Mzk1OTIwNDQ0IiwiaGFuZGxlIjoic21hcnRwdXNoNCIsImVudiI6IkNOIiwic3RlIjoiIiwidmVyaWZ5IjoiIn0sImxvZ2luVGltZSI6MTc0MTI1MDU1MjI4Miwic2NvcGUiOlsiZW1haWwtbWFya2V0IiwiY29va2llIiwic2wtZWNvbS1lbWFpbC1tYXJrZXQtbmV3LXRlc3QiLCJlbWFpbC1tYXJrZXQtbmV3LWRldi1mcyIsImFwaS11Yy1lYzIiLCJhcGktc3UtZWMyIiwiYXBpLWVtLWVjMiIsImZsb3ctcGx1Z2luIl0sImNsaWVudF9pZCI6ImVtYWlsLW1hcmtldCJ9.SjeTCLaZqbEFEFNeKe_EjrwmR0LdEYO9697ymVNzf5Q;',
26
- 'Content-Type': 'application/json'}
27
- # actual_oss = get_oss_address_with_retry(11911, host, reqHeaders, import_requestParam, is_import=True)
28
- # actual_oss = get_oss_address_with_retry(11896, host, reqHeaders, export_requestParam)
29
- # # res=read_excel_and_write_to_dict(read_excel_from_oss(actual_oss))
30
- # # print(res)
31
- # # print(read_excel_and_write_to_dict(read_excel_from_oss(oss1), type=".xlsx"))
32
- # print(check_excel(check_type="all", actual_oss=actual_oss, expected_oss=expected_oss))
33
- # print(check_excel_all(actual_oss=oss1, expected_oss=oss2,skiprows =1))
34
- # print(check_excel_all(actual_oss=oss1, expected_oss=oss2, ignore_sort=0))
35
- print(check_excel_all(actual_oss=a_person_oss2, expected_oss=e_person_oss1, check_type="including"))
36
- # print(check_excel_all(actual_oss=e_person_oss1, expected_oss=a_person_oss2, check_type="person"))
37
- # read_excel_csv_data(type=)
38
-
39
- # flow_ex="https://cdn.smartpushedm.com/material_ec2/2025-02-20/ad9e1534b8134dd098e96813f17d4b4d/%E6%B5%8B%E8%AF%95flow%E6%95%B0%E6%8D%AE%E6%8A%A5%E5%91%8A%E5%AF%BC%E5%87%BA%E5%8B%BF%E5%8A%A8%E6%95%B0%E6%8D%AE%E6%A6%82%E8%A7%88.xlsx"
40
- # flow_ac="https://cdn.smartpushedm.com/material_ec2/2025-03-04/0c8f919f28d4455f9908f905aada7efb/测试flow数据报告导出勿动数据概览.xlsx"
41
- # print(check_excel_all(actual_oss=flow_ac, expected_oss=flow_ex, check_type="including",export_type="flow",skiprows=1))
@@ -123,4 +123,10 @@ class StringUtils:
123
123
  :param suffix: 后缀字符串
124
124
  :return: 如果以指定后缀结尾返回 True,否则返回 False
125
125
  """
126
- return s.endswith(suffix) if isinstance(s, str) and isinstance(suffix, str) else False
126
+ return s.endswith(suffix) if isinstance(s, str) and isinstance(suffix, str) else False
127
+
128
+ @staticmethod
129
+ def truncate_string(input_string):
130
+ if len(input_string) > 30:
131
+ return input_string[:15]
132
+ return input_string
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: smartpush
3
- Version: 1.3.1
3
+ Version: 1.3.4
4
4
  Summary: 用于smartpush自动化测试工具包
5
5
  Author: 卢泽彬、邵宇飞、周彦龙
6
6
 
@@ -1,15 +1,15 @@
1
1
  smartpush/__init__.py,sha256=XJrl1vhGATHSeSVqKmPXxYqxyseriUpvY5tLIXir3EE,24
2
- smartpush/get_jira_info.py,sha256=dmCwkKa94xwyE2hegE1KBI3cV_LbrJ67P9osORUGPt4,2633
3
- smartpush/test.py,sha256=eXstqNlINEG3bmuFpt1QI0FRyid34awyQy-oGxWFoDc,5119
2
+ smartpush/get_jira_info.py,sha256=VWFQAK78sW_U2iAbRkhS9wLpj3uaFmUiM37rlq80Q5s,17741
3
+ smartpush/test.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  smartpush/export/__init__.py,sha256=D9GbWcmwnetEndFDty5XbVienFK1WjqV2yYcQp3CM84,99
5
5
  smartpush/export/basic/ExcelExportChecker.py,sha256=R_1gFy69vE2V5pY20zFsnhqWgJ42Vtf35zBtOPfhUpU,17590
6
6
  smartpush/export/basic/GetOssUrl.py,sha256=LeF1y1_uJaYXth1KvO6mEDS29ezb9tliBv5SrbqYkXc,6136
7
7
  smartpush/export/basic/ReadExcel.py,sha256=ZnG2mtYqLY-xuYx9SyulbdYUP_0E5jIeKDewfakAsTw,7342
8
8
  smartpush/export/basic/__init__.py,sha256=6tcrS-2NSlsJo-UwEsnGUmwCf7jgOsh_UEbM0FD-gYE,70
9
9
  smartpush/utils/DataTypeUtils.py,sha256=BC7ioztO3vAfKd1EOoNvXdVuXYY8qjNskV1DP7LhW-M,1082
10
- smartpush/utils/StringUtils.py,sha256=NXomJ4qmyBRAFnGj5hrFRWwQnRQMTcPzy20fk1dunSw,3980
10
+ smartpush/utils/StringUtils.py,sha256=n8mo9k0JQN63MReImgv-66JxmmymOGknR8pH2fkQrAo,4139
11
11
  smartpush/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
- smartpush-1.3.1.dist-info/METADATA,sha256=SOfiSC5L9lH65h35mm4ne9HurMW6pwu2vtEn38MHg4k,145
13
- smartpush-1.3.1.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
14
- smartpush-1.3.1.dist-info/top_level.txt,sha256=5_CXqu08EfbPaKLjuSAOAqCmGU6shiatwDU_ViBGCmg,10
15
- smartpush-1.3.1.dist-info/RECORD,,
12
+ smartpush-1.3.4.dist-info/METADATA,sha256=5JMdO_0w-Gih2eLZ4LxdPqrROG1yIGTEcqHyK3SnrWs,145
13
+ smartpush-1.3.4.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
14
+ smartpush-1.3.4.dist-info/top_level.txt,sha256=5_CXqu08EfbPaKLjuSAOAqCmGU6shiatwDU_ViBGCmg,10
15
+ smartpush-1.3.4.dist-info/RECORD,,