pytest-dsl 0.11.0__py3-none-any.whl → 0.12.0__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.
- pytest_dsl/cli.py +89 -83
- pytest_dsl/core/http_client.py +93 -80
- pytest_dsl/keywords/http_keywords.py +90 -34
- pytest_dsl/keywords/system_keywords.py +420 -1
- pytest_dsl/remote/keyword_client.py +30 -17
- pytest_dsl/remote/keyword_server.py +18 -1
- pytest_dsl/remote/variable_bridge.py +41 -8
- {pytest_dsl-0.11.0.dist-info → pytest_dsl-0.12.0.dist-info}/METADATA +3 -3
- {pytest_dsl-0.11.0.dist-info → pytest_dsl-0.12.0.dist-info}/RECORD +13 -13
- {pytest_dsl-0.11.0.dist-info → pytest_dsl-0.12.0.dist-info}/WHEEL +0 -0
- {pytest_dsl-0.11.0.dist-info → pytest_dsl-0.12.0.dist-info}/entry_points.txt +0 -0
- {pytest_dsl-0.11.0.dist-info → pytest_dsl-0.12.0.dist-info}/licenses/LICENSE +0 -0
- {pytest_dsl-0.11.0.dist-info → pytest_dsl-0.12.0.dist-info}/top_level.txt +0 -0
pytest_dsl/cli.py
CHANGED
@@ -69,7 +69,7 @@ def parse_args():
|
|
69
69
|
)
|
70
70
|
list_parser.add_argument(
|
71
71
|
'--output', '-o', type=str, default=None,
|
72
|
-
help='
|
72
|
+
help='输出文件路径(json格式默认为keywords.json,html格式默认为keywords.html)'
|
73
73
|
)
|
74
74
|
list_parser.add_argument(
|
75
75
|
'--filter', type=str, default=None,
|
@@ -77,7 +77,10 @@ def parse_args():
|
|
77
77
|
)
|
78
78
|
list_parser.add_argument(
|
79
79
|
'--category',
|
80
|
-
choices=[
|
80
|
+
choices=[
|
81
|
+
'builtin', 'plugin', 'custom',
|
82
|
+
'project_custom', 'remote', 'all'
|
83
|
+
],
|
81
84
|
default='all',
|
82
85
|
help='关键字类别:builtin(内置)、plugin(插件)、custom(自定义)、'
|
83
86
|
'project_custom(项目自定义)、remote(远程)、all(全部,默认)'
|
@@ -105,7 +108,8 @@ def parse_args():
|
|
105
108
|
parser.add_argument(
|
106
109
|
'--category',
|
107
110
|
choices=[
|
108
|
-
'builtin', 'plugin', 'custom',
|
111
|
+
'builtin', 'plugin', 'custom',
|
112
|
+
'project_custom', 'remote', 'all'
|
109
113
|
],
|
110
114
|
default='all'
|
111
115
|
)
|
@@ -136,7 +140,7 @@ def parse_args():
|
|
136
140
|
|
137
141
|
def load_all_keywords(include_remote=False):
|
138
142
|
"""加载所有可用的关键字
|
139
|
-
|
143
|
+
|
140
144
|
Args:
|
141
145
|
include_remote: 是否包含远程关键字,默认为False
|
142
146
|
"""
|
@@ -152,28 +156,28 @@ def load_all_keywords(include_remote=False):
|
|
152
156
|
|
153
157
|
# 扫描本地关键字
|
154
158
|
scan_local_keywords()
|
155
|
-
|
159
|
+
|
156
160
|
# 扫描项目中的自定义关键字(.resource文件中定义的)
|
157
161
|
project_custom_keywords = scan_project_custom_keywords()
|
158
162
|
if project_custom_keywords:
|
159
163
|
print(f"发现 {len(project_custom_keywords)} 个项目自定义关键字")
|
160
|
-
|
164
|
+
|
161
165
|
# 加载.resource文件中的关键字到关键字管理器
|
162
166
|
from pytest_dsl.core.custom_keyword_manager import (
|
163
167
|
custom_keyword_manager
|
164
168
|
)
|
165
169
|
from pathlib import Path
|
166
|
-
|
170
|
+
|
167
171
|
project_root = Path(os.getcwd())
|
168
172
|
resource_files = list(project_root.glob('**/*.resource'))
|
169
|
-
|
173
|
+
|
170
174
|
for resource_file in resource_files:
|
171
175
|
try:
|
172
176
|
custom_keyword_manager.load_resource_file(str(resource_file))
|
173
177
|
print(f"已加载资源文件: {resource_file}")
|
174
178
|
except Exception as e:
|
175
179
|
print(f"加载资源文件失败 {resource_file}: {e}")
|
176
|
-
|
180
|
+
|
177
181
|
# 根据参数决定是否加载远程关键字
|
178
182
|
if include_remote:
|
179
183
|
print("正在扫描远程关键字...")
|
@@ -181,11 +185,11 @@ def load_all_keywords(include_remote=False):
|
|
181
185
|
# 目前远程关键字是通过DSL文件中的@remote导入指令动态加载的
|
182
186
|
else:
|
183
187
|
print("跳过远程关键字扫描")
|
184
|
-
|
188
|
+
|
185
189
|
return project_custom_keywords
|
186
190
|
|
187
191
|
|
188
|
-
def categorize_keyword(keyword_name, keyword_info,
|
192
|
+
def categorize_keyword(keyword_name, keyword_info,
|
189
193
|
project_custom_keywords=None):
|
190
194
|
"""判断关键字的类别"""
|
191
195
|
# 优先使用存储的来源信息
|
@@ -199,11 +203,11 @@ def categorize_keyword(keyword_name, keyword_info,
|
|
199
203
|
return 'custom'
|
200
204
|
elif source_type == 'project_custom':
|
201
205
|
return 'project_custom'
|
202
|
-
|
206
|
+
|
203
207
|
# 向后兼容:使用原有的判断逻辑
|
204
208
|
if keyword_info.get('remote', False):
|
205
209
|
return 'remote'
|
206
|
-
|
210
|
+
|
207
211
|
# 检查是否是项目自定义关键字(DSL文件中定义的)
|
208
212
|
if project_custom_keywords and keyword_name in project_custom_keywords:
|
209
213
|
return 'project_custom'
|
@@ -222,7 +226,7 @@ def get_keyword_source_info(keyword_info):
|
|
222
226
|
"""获取关键字的详细来源信息"""
|
223
227
|
source_type = keyword_info.get('source_type', 'unknown')
|
224
228
|
source_name = keyword_info.get('source_name', '未知')
|
225
|
-
|
229
|
+
|
226
230
|
return {
|
227
231
|
'type': source_type,
|
228
232
|
'name': source_name,
|
@@ -234,7 +238,7 @@ def get_keyword_source_info(keyword_info):
|
|
234
238
|
|
235
239
|
def group_keywords_by_source(keywords_dict, project_custom_keywords=None):
|
236
240
|
"""按来源分组关键字
|
237
|
-
|
241
|
+
|
238
242
|
Returns:
|
239
243
|
dict: 格式为 {source_group: {source_name: [keywords]}}
|
240
244
|
"""
|
@@ -245,33 +249,33 @@ def group_keywords_by_source(keywords_dict, project_custom_keywords=None):
|
|
245
249
|
'project_custom': {},
|
246
250
|
'remote': {}
|
247
251
|
}
|
248
|
-
|
252
|
+
|
249
253
|
for keyword_name, keyword_info in keywords_dict.items():
|
250
254
|
category = categorize_keyword(
|
251
255
|
keyword_name, keyword_info, project_custom_keywords
|
252
256
|
)
|
253
257
|
source_info = get_keyword_source_info(keyword_info)
|
254
|
-
|
258
|
+
|
255
259
|
# 特殊处理项目自定义关键字
|
256
260
|
if category == 'project_custom' and project_custom_keywords:
|
257
261
|
custom_info = project_custom_keywords[keyword_name]
|
258
262
|
source_name = custom_info['file']
|
259
263
|
else:
|
260
264
|
source_name = source_info['name']
|
261
|
-
|
265
|
+
|
262
266
|
if source_name not in groups[category]:
|
263
267
|
groups[category][source_name] = []
|
264
|
-
|
268
|
+
|
265
269
|
groups[category][source_name].append({
|
266
270
|
'name': keyword_name,
|
267
271
|
'info': keyword_info,
|
268
272
|
'source_info': source_info
|
269
273
|
})
|
270
|
-
|
274
|
+
|
271
275
|
return groups
|
272
276
|
|
273
277
|
|
274
|
-
def format_keyword_info_text(keyword_name, keyword_info, show_category=True,
|
278
|
+
def format_keyword_info_text(keyword_name, keyword_info, show_category=True,
|
275
279
|
project_custom_keywords=None):
|
276
280
|
"""格式化关键字信息为文本格式"""
|
277
281
|
lines = []
|
@@ -281,9 +285,9 @@ def format_keyword_info_text(keyword_name, keyword_info, show_category=True,
|
|
281
285
|
keyword_name, keyword_info, project_custom_keywords
|
282
286
|
)
|
283
287
|
category_names = {
|
284
|
-
'builtin': '内置',
|
285
|
-
'custom': '自定义',
|
286
|
-
'project_custom': '项目自定义',
|
288
|
+
'builtin': '内置',
|
289
|
+
'custom': '自定义',
|
290
|
+
'project_custom': '项目自定义',
|
287
291
|
'remote': '远程'
|
288
292
|
}
|
289
293
|
|
@@ -304,7 +308,7 @@ def format_keyword_info_text(keyword_name, keyword_info, show_category=True,
|
|
304
308
|
if category == 'project_custom' and project_custom_keywords:
|
305
309
|
custom_info = project_custom_keywords[keyword_name]
|
306
310
|
lines.append(f" 文件位置: {custom_info['file']}")
|
307
|
-
|
311
|
+
|
308
312
|
# 对于项目自定义关键字,使用从AST中提取的参数信息
|
309
313
|
custom_parameters = custom_info.get('parameters', [])
|
310
314
|
if custom_parameters:
|
@@ -321,13 +325,13 @@ def format_keyword_info_text(keyword_name, keyword_info, show_category=True,
|
|
321
325
|
param_parts.append(f"{param_name} ({param_mapping})")
|
322
326
|
else:
|
323
327
|
param_parts.append(param_name)
|
324
|
-
|
328
|
+
|
325
329
|
param_parts.append(f": {param_desc}")
|
326
|
-
|
330
|
+
|
327
331
|
# 添加默认值信息
|
328
332
|
if param_default is not None:
|
329
333
|
param_parts.append(f" (默认值: {param_default})")
|
330
|
-
|
334
|
+
|
331
335
|
lines.append(f" {''.join(param_parts)}")
|
332
336
|
else:
|
333
337
|
lines.append(" 参数: 无")
|
@@ -348,13 +352,13 @@ def format_keyword_info_text(keyword_name, keyword_info, show_category=True,
|
|
348
352
|
param_info.append(f"{param_name} ({param_mapping})")
|
349
353
|
else:
|
350
354
|
param_info.append(param_name)
|
351
|
-
|
355
|
+
|
352
356
|
param_info.append(f": {param_desc}")
|
353
|
-
|
357
|
+
|
354
358
|
# 添加默认值信息
|
355
359
|
if param_default is not None:
|
356
360
|
param_info.append(f" (默认值: {param_default})")
|
357
|
-
|
361
|
+
|
358
362
|
lines.append(f" {''.join(param_info)}")
|
359
363
|
else:
|
360
364
|
lines.append(" 参数: 无")
|
@@ -393,7 +397,7 @@ def format_keyword_info_json(keyword_name, keyword_info,
|
|
393
397
|
if category == 'project_custom' and project_custom_keywords:
|
394
398
|
custom_info = project_custom_keywords[keyword_name]
|
395
399
|
keyword_data['file_location'] = custom_info['file']
|
396
|
-
|
400
|
+
|
397
401
|
# 对于项目自定义关键字,使用从AST中提取的参数信息
|
398
402
|
for param_info in custom_info.get('parameters', []):
|
399
403
|
keyword_data['parameters'].append(param_info)
|
@@ -406,12 +410,12 @@ def format_keyword_info_json(keyword_name, keyword_info,
|
|
406
410
|
'mapping': getattr(param, 'mapping', ''),
|
407
411
|
'description': getattr(param, 'description', '')
|
408
412
|
}
|
409
|
-
|
413
|
+
|
410
414
|
# 添加默认值信息
|
411
415
|
param_default = getattr(param, 'default', None)
|
412
416
|
if param_default is not None:
|
413
417
|
param_data['default'] = param_default
|
414
|
-
|
418
|
+
|
415
419
|
keyword_data['parameters'].append(param_data)
|
416
420
|
|
417
421
|
# 函数文档
|
@@ -426,11 +430,11 @@ def generate_html_report(keywords_data, output_file):
|
|
426
430
|
"""生成HTML格式的关键字报告"""
|
427
431
|
from jinja2 import Environment, FileSystemLoader, select_autoescape
|
428
432
|
import os
|
429
|
-
|
433
|
+
|
430
434
|
# 准备数据
|
431
435
|
summary = keywords_data['summary']
|
432
436
|
keywords = keywords_data['keywords']
|
433
|
-
|
437
|
+
|
434
438
|
# 按类别分组
|
435
439
|
categories = {}
|
436
440
|
for keyword in keywords:
|
@@ -438,14 +442,14 @@ def generate_html_report(keywords_data, output_file):
|
|
438
442
|
if category not in categories:
|
439
443
|
categories[category] = []
|
440
444
|
categories[category].append(keyword)
|
441
|
-
|
445
|
+
|
442
446
|
# 按来源分组(用于更详细的分组视图)
|
443
447
|
source_groups = {}
|
444
448
|
for keyword in keywords:
|
445
449
|
source_info = keyword.get('source_info', {})
|
446
450
|
category = keyword['category']
|
447
451
|
source_name = source_info.get('name', '未知来源')
|
448
|
-
|
452
|
+
|
449
453
|
# 构建分组键
|
450
454
|
if category == 'plugin':
|
451
455
|
group_key = f"插件 - {source_name}"
|
@@ -457,11 +461,11 @@ def generate_html_report(keywords_data, output_file):
|
|
457
461
|
group_key = f"远程 - {source_name}"
|
458
462
|
else:
|
459
463
|
group_key = f"自定义 - {source_name}"
|
460
|
-
|
464
|
+
|
461
465
|
if group_key not in source_groups:
|
462
466
|
source_groups[group_key] = []
|
463
467
|
source_groups[group_key].append(keyword)
|
464
|
-
|
468
|
+
|
465
469
|
# 按位置分组(用于全部关键字视图,保持向后兼容)
|
466
470
|
location_groups = {}
|
467
471
|
for keyword in keywords:
|
@@ -470,11 +474,11 @@ def generate_html_report(keywords_data, output_file):
|
|
470
474
|
if not location:
|
471
475
|
source_info = keyword.get('source_info', {})
|
472
476
|
location = source_info.get('name', '内置/插件')
|
473
|
-
|
477
|
+
|
474
478
|
if location not in location_groups:
|
475
479
|
location_groups[location] = []
|
476
480
|
location_groups[location].append(keyword)
|
477
|
-
|
481
|
+
|
478
482
|
# 类别名称映射
|
479
483
|
category_names = {
|
480
484
|
'builtin': '内置',
|
@@ -483,18 +487,18 @@ def generate_html_report(keywords_data, output_file):
|
|
483
487
|
'project_custom': '项目自定义',
|
484
488
|
'remote': '远程'
|
485
489
|
}
|
486
|
-
|
490
|
+
|
487
491
|
# 设置Jinja2环境
|
488
492
|
template_dir = os.path.join(os.path.dirname(__file__), 'templates')
|
489
|
-
|
493
|
+
|
490
494
|
env = Environment(
|
491
495
|
loader=FileSystemLoader(template_dir),
|
492
496
|
autoescape=select_autoescape(['html', 'xml'])
|
493
497
|
)
|
494
|
-
|
498
|
+
|
495
499
|
# 加载模板
|
496
500
|
template = env.get_template('keywords_report.html')
|
497
|
-
|
501
|
+
|
498
502
|
# 渲染模板
|
499
503
|
html_content = template.render(
|
500
504
|
summary=summary,
|
@@ -504,16 +508,16 @@ def generate_html_report(keywords_data, output_file):
|
|
504
508
|
location_groups=location_groups,
|
505
509
|
category_names=category_names
|
506
510
|
)
|
507
|
-
|
511
|
+
|
508
512
|
# 写入文件
|
509
513
|
with open(output_file, 'w', encoding='utf-8') as f:
|
510
514
|
f.write(html_content)
|
511
|
-
|
515
|
+
|
512
516
|
print(f"HTML报告已生成: {output_file}")
|
513
517
|
|
514
518
|
|
515
519
|
def list_keywords(output_format='json', name_filter=None,
|
516
|
-
category_filter='all', output_file=None,
|
520
|
+
category_filter='all', output_file=None,
|
517
521
|
include_remote=False):
|
518
522
|
"""罗列所有关键字信息"""
|
519
523
|
import json
|
@@ -561,18 +565,18 @@ def list_keywords(output_format='json', name_filter=None,
|
|
561
565
|
total_count = len(filtered_keywords)
|
562
566
|
category_counts = {}
|
563
567
|
source_counts = {}
|
564
|
-
|
568
|
+
|
565
569
|
for name, info in filtered_keywords.items():
|
566
570
|
cat = categorize_keyword(name, info, project_custom_keywords)
|
567
571
|
category_counts[cat] = category_counts.get(cat, 0) + 1
|
568
|
-
|
572
|
+
|
569
573
|
# 统计各来源的关键字数量
|
570
574
|
source_info = get_keyword_source_info(info)
|
571
575
|
source_name = source_info['name']
|
572
576
|
if cat == 'project_custom' and project_custom_keywords:
|
573
577
|
custom_info = project_custom_keywords[name]
|
574
578
|
source_name = custom_info['file']
|
575
|
-
|
579
|
+
|
576
580
|
source_key = f"{cat}:{source_name}"
|
577
581
|
source_counts[source_key] = source_counts.get(source_key, 0) + 1
|
578
582
|
|
@@ -590,13 +594,13 @@ def list_keywords(output_format='json', name_filter=None,
|
|
590
594
|
grouped = group_keywords_by_source(
|
591
595
|
filtered_keywords, project_custom_keywords
|
592
596
|
)
|
593
|
-
|
597
|
+
|
594
598
|
for category in [
|
595
599
|
'builtin', 'plugin', 'custom', 'project_custom', 'remote'
|
596
600
|
]:
|
597
601
|
if category not in grouped or not grouped[category]:
|
598
602
|
continue
|
599
|
-
|
603
|
+
|
600
604
|
cat_names = {
|
601
605
|
'builtin': '内置关键字',
|
602
606
|
'plugin': '插件关键字',
|
@@ -605,11 +609,11 @@ def list_keywords(output_format='json', name_filter=None,
|
|
605
609
|
'remote': '远程关键字'
|
606
610
|
}
|
607
611
|
print(f"\n=== {cat_names[category]} ===")
|
608
|
-
|
612
|
+
|
609
613
|
for source_name, keyword_list in grouped[category].items():
|
610
614
|
if len(grouped[category]) > 1: # 如果有多个来源,显示来源名
|
611
615
|
print(f"\n--- {source_name} ---")
|
612
|
-
|
616
|
+
|
613
617
|
for keyword_data in keyword_list:
|
614
618
|
name = keyword_data['name']
|
615
619
|
info = keyword_data['info']
|
@@ -637,11 +641,11 @@ def list_keywords(output_format='json', name_filter=None,
|
|
637
641
|
keywords_data['keywords'].append(keyword_data)
|
638
642
|
|
639
643
|
json_output = json.dumps(keywords_data, ensure_ascii=False, indent=2)
|
640
|
-
|
644
|
+
|
641
645
|
# 确定输出文件名
|
642
646
|
if output_file is None:
|
643
647
|
output_file = 'keywords.json'
|
644
|
-
|
648
|
+
|
645
649
|
# 写入到文件
|
646
650
|
try:
|
647
651
|
with open(output_file, 'w', encoding='utf-8') as f:
|
@@ -679,7 +683,7 @@ def list_keywords(output_format='json', name_filter=None,
|
|
679
683
|
# 确定输出文件名
|
680
684
|
if output_file is None:
|
681
685
|
output_file = 'keywords.html'
|
682
|
-
|
686
|
+
|
683
687
|
# 生成HTML报告
|
684
688
|
try:
|
685
689
|
generate_html_report(keywords_data, output_file)
|
@@ -850,7 +854,9 @@ def main_list_keywords():
|
|
850
854
|
)
|
851
855
|
parser.add_argument(
|
852
856
|
'--category',
|
853
|
-
choices=[
|
857
|
+
choices=[
|
858
|
+
'builtin', 'plugin', 'custom', 'project_custom', 'remote', 'all'
|
859
|
+
],
|
854
860
|
default='all',
|
855
861
|
help='关键字类别:builtin(内置)、plugin(插件)、custom(自定义)、'
|
856
862
|
'project_custom(项目自定义)、remote(远程)、all(全部,默认)'
|
@@ -873,103 +879,103 @@ def main_list_keywords():
|
|
873
879
|
|
874
880
|
def scan_project_custom_keywords(project_root=None):
|
875
881
|
"""扫描项目中.resource文件中的自定义关键字
|
876
|
-
|
882
|
+
|
877
883
|
Args:
|
878
884
|
project_root: 项目根目录,默认为当前工作目录
|
879
|
-
|
885
|
+
|
880
886
|
Returns:
|
881
887
|
dict: 自定义关键字信息,格式为
|
882
888
|
{keyword_name: {'file': file_path, 'node': ast_node}}
|
883
889
|
"""
|
884
890
|
if project_root is None:
|
885
891
|
project_root = os.getcwd()
|
886
|
-
|
892
|
+
|
887
893
|
project_root = Path(project_root)
|
888
894
|
custom_keywords = {}
|
889
|
-
|
895
|
+
|
890
896
|
# 查找所有.resource文件
|
891
897
|
resource_files = list(project_root.glob('**/*.resource'))
|
892
|
-
|
898
|
+
|
893
899
|
if not resource_files:
|
894
900
|
return custom_keywords
|
895
|
-
|
901
|
+
|
896
902
|
lexer = get_lexer()
|
897
903
|
parser = get_parser()
|
898
|
-
|
904
|
+
|
899
905
|
for file_path in resource_files:
|
900
906
|
try:
|
901
907
|
# 读取并解析文件
|
902
908
|
content = read_file(str(file_path))
|
903
909
|
ast = parser.parse(content, lexer=lexer)
|
904
|
-
|
910
|
+
|
905
911
|
# 查找自定义关键字定义
|
906
912
|
keywords_in_file = extract_custom_keywords_from_ast(
|
907
913
|
ast, str(file_path)
|
908
914
|
)
|
909
915
|
custom_keywords.update(keywords_in_file)
|
910
|
-
|
916
|
+
|
911
917
|
except Exception as e:
|
912
918
|
print(f"解析资源文件 {file_path} 时出错: {e}")
|
913
|
-
|
919
|
+
|
914
920
|
return custom_keywords
|
915
921
|
|
916
922
|
|
917
923
|
def extract_custom_keywords_from_ast(ast, file_path):
|
918
924
|
"""从AST中提取自定义关键字定义
|
919
|
-
|
925
|
+
|
920
926
|
Args:
|
921
927
|
ast: 抽象语法树
|
922
928
|
file_path: 文件路径
|
923
|
-
|
929
|
+
|
924
930
|
Returns:
|
925
931
|
dict: 自定义关键字信息
|
926
932
|
"""
|
927
933
|
custom_keywords = {}
|
928
|
-
|
934
|
+
|
929
935
|
if ast.type != 'Start' or len(ast.children) < 2:
|
930
936
|
return custom_keywords
|
931
|
-
|
937
|
+
|
932
938
|
# 遍历语句节点
|
933
939
|
statements_node = ast.children[1]
|
934
940
|
if statements_node.type != 'Statements':
|
935
941
|
return custom_keywords
|
936
|
-
|
942
|
+
|
937
943
|
for node in statements_node.children:
|
938
944
|
# 支持两种格式:CustomKeyword(旧格式)和Function(新格式)
|
939
945
|
if node.type in ['CustomKeyword', 'Function']:
|
940
946
|
keyword_name = node.value
|
941
|
-
|
947
|
+
|
942
948
|
# 提取参数信息
|
943
949
|
params_node = node.children[0] if node.children else None
|
944
950
|
parameters = []
|
945
|
-
|
951
|
+
|
946
952
|
if params_node:
|
947
953
|
for param in params_node:
|
948
954
|
param_name = param.value
|
949
955
|
param_default = None
|
950
|
-
|
956
|
+
|
951
957
|
# 检查是否有默认值
|
952
958
|
if param.children and param.children[0]:
|
953
959
|
param_default = param.children[0].value
|
954
|
-
|
960
|
+
|
955
961
|
param_info = {
|
956
962
|
'name': param_name,
|
957
963
|
'mapping': param_name,
|
958
964
|
'description': f'自定义关键字参数 {param_name}'
|
959
965
|
}
|
960
|
-
|
966
|
+
|
961
967
|
if param_default is not None:
|
962
968
|
param_info['default'] = param_default
|
963
|
-
|
969
|
+
|
964
970
|
parameters.append(param_info)
|
965
|
-
|
971
|
+
|
966
972
|
custom_keywords[keyword_name] = {
|
967
973
|
'file': file_path,
|
968
974
|
'node': node,
|
969
975
|
'type': 'project_custom',
|
970
976
|
'parameters': parameters
|
971
977
|
}
|
972
|
-
|
978
|
+
|
973
979
|
return custom_keywords
|
974
980
|
|
975
981
|
|