universal-mcp 0.1.15rc7__py3-none-any.whl → 0.1.17__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.
- universal_mcp/applications/__init__.py +25 -27
- universal_mcp/applications/application.py +19 -55
- universal_mcp/cli.py +10 -29
- universal_mcp/config.py +16 -48
- universal_mcp/integrations/__init__.py +1 -3
- universal_mcp/logger.py +31 -29
- universal_mcp/servers/server.py +6 -18
- universal_mcp/tools/func_metadata.py +5 -19
- universal_mcp/tools/manager.py +5 -15
- universal_mcp/tools/tools.py +4 -11
- universal_mcp/utils/agentr.py +2 -6
- universal_mcp/utils/common.py +1 -1
- universal_mcp/utils/docstring_parser.py +4 -13
- universal_mcp/utils/installation.py +67 -184
- universal_mcp/utils/openapi/api_generator.py +1 -3
- universal_mcp/utils/openapi/docgen.py +17 -54
- universal_mcp/utils/openapi/openapi.py +62 -110
- universal_mcp/utils/openapi/preprocessor.py +60 -190
- universal_mcp/utils/openapi/readme.py +3 -9
- universal_mcp-0.1.17.dist-info/METADATA +282 -0
- universal_mcp-0.1.17.dist-info/RECORD +44 -0
- universal_mcp-0.1.15rc7.dist-info/METADATA +0 -247
- universal_mcp-0.1.15rc7.dist-info/RECORD +0 -44
- {universal_mcp-0.1.15rc7.dist-info → universal_mcp-0.1.17.dist-info}/WHEEL +0 -0
- {universal_mcp-0.1.15rc7.dist-info → universal_mcp-0.1.17.dist-info}/entry_points.txt +0 -0
- {universal_mcp-0.1.15rc7.dist-info → universal_mcp-0.1.17.dist-info}/licenses/LICENSE +0 -0
@@ -91,24 +91,24 @@ def _sanitize_identifier(name: str | None) -> str:
|
|
91
91
|
"""
|
92
92
|
if name is None:
|
93
93
|
return ""
|
94
|
-
|
94
|
+
|
95
95
|
# Initial replacements for common non-alphanumeric characters
|
96
96
|
sanitized = name.replace("-", "_").replace(".", "_").replace("[", "_").replace("]", "").replace("$", "_")
|
97
97
|
|
98
98
|
# Remove leading underscores, but preserve a single underscore if the name (after initial replace)
|
99
99
|
# consisted only of underscores.
|
100
|
-
if sanitized.startswith(
|
101
|
-
stripped_name = sanitized.lstrip(
|
100
|
+
if sanitized.startswith("_"):
|
101
|
+
stripped_name = sanitized.lstrip("_")
|
102
102
|
sanitized = stripped_name if stripped_name else "_"
|
103
|
-
|
103
|
+
|
104
104
|
# Append underscore if the sanitized name is a Python keyword
|
105
105
|
if iskeyword(sanitized):
|
106
106
|
sanitized += "_"
|
107
|
-
|
107
|
+
|
108
108
|
# Special handling for "self" to avoid conflict with instance method's self argument
|
109
109
|
if sanitized == "self":
|
110
110
|
sanitized = "self_arg"
|
111
|
-
|
111
|
+
|
112
112
|
return sanitized
|
113
113
|
|
114
114
|
|
@@ -202,18 +202,10 @@ def _determine_function_name(operation: dict[str, Any], path: str, method: str)
|
|
202
202
|
func_name = "_".join(name_parts).replace("-", "_").lower()
|
203
203
|
|
204
204
|
# Only fix isolated 'a' and 'an' as articles, not when they're part of words
|
205
|
-
func_name = re.sub(
|
206
|
-
|
207
|
-
) # Fix for patterns like
|
208
|
-
func_name = re.sub(
|
209
|
-
r"_a$", r"_a", func_name
|
210
|
-
) # Don't change if 'a' is at the end of the name
|
211
|
-
func_name = re.sub(
|
212
|
-
r"_an([^_a-z])", r"_an_\1", func_name
|
213
|
-
) # Fix for patterns like create_anitem -> create_an_item
|
214
|
-
func_name = re.sub(
|
215
|
-
r"_an$", r"_an", func_name
|
216
|
-
) # Don't change if 'an' is at the end of the name
|
205
|
+
func_name = re.sub(r"_a([^_a-z])", r"_a_\1", func_name) # Fix for patterns like retrieve_ablock -> retrieve_a_block
|
206
|
+
func_name = re.sub(r"_a$", r"_a", func_name) # Don't change if 'a' is at the end of the name
|
207
|
+
func_name = re.sub(r"_an([^_a-z])", r"_an_\1", func_name) # Fix for patterns like create_anitem -> create_an_item
|
208
|
+
func_name = re.sub(r"_an$", r"_an", func_name) # Don't change if 'an' is at the end of the name
|
217
209
|
return func_name
|
218
210
|
|
219
211
|
|
@@ -242,9 +234,7 @@ def _generate_path_params(path: str) -> list[Parameters]:
|
|
242
234
|
def _generate_url(path: str, path_params: list[Parameters]):
|
243
235
|
formatted_path = path
|
244
236
|
for param in path_params:
|
245
|
-
formatted_path = formatted_path.replace(
|
246
|
-
f"{{{param.identifier}}}", f"{{{param.name}}}"
|
247
|
-
)
|
237
|
+
formatted_path = formatted_path.replace(f"{{{param.identifier}}}", f"{{{param.name}}}")
|
248
238
|
return formatted_path
|
249
239
|
|
250
240
|
|
@@ -338,7 +328,7 @@ def _generate_method_code(path, method, operation):
|
|
338
328
|
Returns:
|
339
329
|
tuple: (method_code, func_name) - The Python code for the method and its name.
|
340
330
|
"""
|
341
|
-
print(f"--- Generating code for: {method.upper()} {path} ---")
|
331
|
+
print(f"--- Generating code for: {method.upper()} {path} ---") # Log endpoint being processed
|
342
332
|
|
343
333
|
func_name = _determine_function_name(operation, path, method)
|
344
334
|
operation.get("summary", "")
|
@@ -354,13 +344,12 @@ def _generate_method_code(path, method, operation):
|
|
354
344
|
|
355
345
|
# Define the string that "self" sanitizes to. This name will be treated as reserved
|
356
346
|
# for query/body params to force suffixing.
|
357
|
-
self_sanitized_marker = _sanitize_identifier("self")
|
347
|
+
self_sanitized_marker = _sanitize_identifier("self") # This will be "self_arg"
|
358
348
|
|
359
349
|
# Base names that will force query/body parameters to be suffixed.
|
360
350
|
# This includes actual path parameter names and the sanitized form of "self".
|
361
351
|
path_param_base_conflict_names = path_param_names | {self_sanitized_marker}
|
362
352
|
|
363
|
-
|
364
353
|
# Alias query parameters
|
365
354
|
current_query_param_names = set()
|
366
355
|
for q_param in query_params:
|
@@ -374,18 +363,19 @@ def _generate_method_code(path, method, operation):
|
|
374
363
|
# This step is more about ensuring the final suffixed name is unique if multiple query params mapped to same path param name
|
375
364
|
counter = 1
|
376
365
|
final_q_name = temp_q_name
|
377
|
-
while
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
366
|
+
while (
|
367
|
+
final_q_name in path_param_base_conflict_names or final_q_name in current_query_param_names
|
368
|
+
): # Check against path/\"self_arg\" and already processed query params
|
369
|
+
if temp_q_name == original_q_name: # first conflict was with path_param_base_conflict_names
|
370
|
+
final_q_name = f"{original_q_name}_query" # try simple suffix first
|
371
|
+
if final_q_name in path_param_base_conflict_names or final_q_name in current_query_param_names:
|
372
|
+
final_q_name = f"{original_q_name}_query_{counter}" # then add counter
|
373
|
+
else: # conflict was with another query param after initial suffixing
|
374
|
+
final_q_name = f"{temp_q_name}_{counter}"
|
384
375
|
counter += 1
|
385
376
|
q_param.name = final_q_name
|
386
377
|
current_query_param_names.add(q_param.name)
|
387
378
|
|
388
|
-
|
389
379
|
# Alias body parameters
|
390
380
|
# Names to check against: path param names (including "self_arg" marker) and (now aliased) query param names
|
391
381
|
existing_param_names_for_body = path_param_base_conflict_names.union(current_query_param_names)
|
@@ -402,11 +392,11 @@ def _generate_method_code(path, method, operation):
|
|
402
392
|
counter = 1
|
403
393
|
final_b_name = temp_b_name
|
404
394
|
while final_b_name in existing_param_names_for_body or final_b_name in current_body_param_names:
|
405
|
-
if temp_b_name == original_b_name:
|
395
|
+
if temp_b_name == original_b_name: # first conflict was with existing_param_names_for_body
|
406
396
|
final_b_name = f"{original_b_name}_body"
|
407
397
|
if final_b_name in existing_param_names_for_body or final_b_name in current_body_param_names:
|
408
398
|
final_b_name = f"{original_b_name}_body_{counter}"
|
409
|
-
else:
|
399
|
+
else: # conflict was with another body param after initial suffixing
|
410
400
|
final_b_name = f"{temp_b_name}_{counter}"
|
411
401
|
|
412
402
|
counter += 1
|
@@ -414,7 +404,6 @@ def _generate_method_code(path, method, operation):
|
|
414
404
|
current_body_param_names.add(b_param.name)
|
415
405
|
# --- End Alias duplicate parameter names ---
|
416
406
|
|
417
|
-
|
418
407
|
return_type = _determine_return_type(operation)
|
419
408
|
|
420
409
|
has_body = "requestBody" in operation
|
@@ -432,12 +421,10 @@ def _generate_method_code(path, method, operation):
|
|
432
421
|
if schema.get("type") == "array":
|
433
422
|
is_array_body = True
|
434
423
|
else:
|
435
|
-
request_body_properties, required_fields = (
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
not request_body_properties or len(request_body_properties) == 0
|
440
|
-
) and schema.get("additionalProperties") is True:
|
424
|
+
request_body_properties, required_fields = _extract_properties_from_schema(schema)
|
425
|
+
if (not request_body_properties or len(request_body_properties) == 0) and schema.get(
|
426
|
+
"additionalProperties"
|
427
|
+
) is True:
|
441
428
|
has_empty_body = True
|
442
429
|
elif not request_body_content or all(
|
443
430
|
not c for _, c in request_body_content.items()
|
@@ -453,13 +440,13 @@ def _generate_method_code(path, method, operation):
|
|
453
440
|
for param in path_params:
|
454
441
|
# Path param names are sanitized but not suffixed by aliasing.
|
455
442
|
# They are the baseline.
|
456
|
-
if param.name not in required_args:
|
443
|
+
if param.name not in required_args: # param.name is the sanitized name
|
457
444
|
required_args.append(param.name)
|
458
445
|
|
459
446
|
# 2. Process Query Parameters
|
460
|
-
for param in query_params:
|
447
|
+
for param in query_params: # param.name is the potentially aliased name (e.g., id_query)
|
461
448
|
arg_name_for_sig = param.name
|
462
|
-
current_arg_names_set = set(required_args) | {arg.split(
|
449
|
+
current_arg_names_set = set(required_args) | {arg.split("=")[0] for arg in optional_args}
|
463
450
|
if arg_name_for_sig not in current_arg_names_set:
|
464
451
|
if param.required:
|
465
452
|
required_args.append(arg_name_for_sig)
|
@@ -470,10 +457,10 @@ def _generate_method_code(path, method, operation):
|
|
470
457
|
# This list tracks the *final* names of parameters in the signature that come from the request body,
|
471
458
|
# used later for docstring example placement.
|
472
459
|
final_request_body_arg_names_for_signature = []
|
473
|
-
final_empty_body_param_name = None
|
460
|
+
final_empty_body_param_name = None # For the specific case of has_empty_body
|
474
461
|
|
475
462
|
if has_body:
|
476
|
-
current_arg_names_set = set(required_args) | {arg.split(
|
463
|
+
current_arg_names_set = set(required_args) | {arg.split("=")[0] for arg in optional_args}
|
477
464
|
if is_array_body:
|
478
465
|
array_param_name_base = "items" # Default base name
|
479
466
|
if func_name.endswith("_list_input"):
|
@@ -491,7 +478,7 @@ def _generate_method_code(path, method, operation):
|
|
491
478
|
else:
|
492
479
|
final_array_param_name = f"{array_param_name_base}_body_{counter}"
|
493
480
|
counter += 1
|
494
|
-
|
481
|
+
|
495
482
|
if body_required:
|
496
483
|
required_args.append(final_array_param_name)
|
497
484
|
else:
|
@@ -500,10 +487,10 @@ def _generate_method_code(path, method, operation):
|
|
500
487
|
|
501
488
|
elif request_body_properties: # Object body
|
502
489
|
for param in body_params: # Iterate ALIASED body_params
|
503
|
-
arg_name_for_sig = param.name
|
504
|
-
|
490
|
+
arg_name_for_sig = param.name # This is the final, aliased name (e.g., "id_body")
|
491
|
+
|
505
492
|
# Defensive check against already added args (should be covered by aliasing logic)
|
506
|
-
current_arg_names_set_loop = set(required_args) | {arg.split(
|
493
|
+
current_arg_names_set_loop = set(required_args) | {arg.split("=")[0] for arg in optional_args}
|
507
494
|
if arg_name_for_sig not in current_arg_names_set_loop:
|
508
495
|
if param.required:
|
509
496
|
required_args.append(arg_name_for_sig)
|
@@ -516,8 +503,8 @@ def _generate_method_code(path, method, operation):
|
|
516
503
|
# This is handled *after* specific body params, as it's a fallback.
|
517
504
|
if has_empty_body:
|
518
505
|
empty_body_param_name_base = "request_body"
|
519
|
-
current_arg_names_set = set(required_args) | {arg.split(
|
520
|
-
|
506
|
+
current_arg_names_set = set(required_args) | {arg.split("=")[0] for arg in optional_args}
|
507
|
+
|
521
508
|
final_empty_body_param_name = empty_body_param_name_base
|
522
509
|
counter = 1
|
523
510
|
is_first_suffix_attempt = True
|
@@ -531,11 +518,11 @@ def _generate_method_code(path, method, operation):
|
|
531
518
|
|
532
519
|
# Check if it was somehow added by other logic (e.g. if 'request_body' was an explicit param name)
|
533
520
|
# This check is mostly defensive.
|
534
|
-
if final_empty_body_param_name not in (set(required_args) | {arg.split(
|
521
|
+
if final_empty_body_param_name not in (set(required_args) | {arg.split("=")[0] for arg in optional_args}):
|
535
522
|
optional_args.append(f"{final_empty_body_param_name}=None")
|
536
523
|
# Track for docstring, even if it's just 'request_body' or 'request_body_body'
|
537
524
|
if final_empty_body_param_name not in final_request_body_arg_names_for_signature:
|
538
|
-
|
525
|
+
final_request_body_arg_names_for_signature.append(final_empty_body_param_name)
|
539
526
|
|
540
527
|
# Combine required and optional arguments
|
541
528
|
args = required_args + optional_args
|
@@ -547,9 +534,7 @@ def _generate_method_code(path, method, operation):
|
|
547
534
|
# Summary
|
548
535
|
summary = operation.get("summary", "").strip()
|
549
536
|
if not summary:
|
550
|
-
summary = operation.get(
|
551
|
-
"description", f"Execute {method.upper()} {path}"
|
552
|
-
).strip()
|
537
|
+
summary = operation.get("description", f"Execute {method.upper()} {path}").strip()
|
553
538
|
summary = summary.split("\n")[0]
|
554
539
|
if summary:
|
555
540
|
docstring_parts.append(summary)
|
@@ -579,9 +564,7 @@ def _generate_method_code(path, method, operation):
|
|
579
564
|
if example_data is not None:
|
580
565
|
try:
|
581
566
|
example_json = json.dumps(example_data, indent=2)
|
582
|
-
indented_example = textwrap.indent(
|
583
|
-
example_json, " " * 8
|
584
|
-
) # 8 spaces
|
567
|
+
indented_example = textwrap.indent(example_json, " " * 8) # 8 spaces
|
585
568
|
request_body_example_str = f"\n Example:\n ```json\n{indented_example}\n ```"
|
586
569
|
except TypeError:
|
587
570
|
request_body_example_str = f"\n Example: {example_data}"
|
@@ -591,7 +574,7 @@ def _generate_method_code(path, method, operation):
|
|
591
574
|
# Identify the last argument related to the request body
|
592
575
|
last_body_arg_name = None
|
593
576
|
# request_body_params contains the names as they appear in the signature
|
594
|
-
if final_request_body_arg_names_for_signature:
|
577
|
+
if final_request_body_arg_names_for_signature: # Use the new list with final aliased names
|
595
578
|
# Find which of these appears last in the combined args list
|
596
579
|
body_args_in_signature = [
|
597
580
|
a.split("=")[0] for a in args if a.split("=")[0] in final_request_body_arg_names_for_signature
|
@@ -617,28 +600,21 @@ def _generate_method_code(path, method, operation):
|
|
617
600
|
if arg_name == last_body_arg_name and request_body_example_str:
|
618
601
|
# Remove the simple Example: if it exists before adding the detailed one
|
619
602
|
if example_str and (
|
620
|
-
f" Example: {example_str}." in arg_line
|
621
|
-
or f" Example: {example_str} ." in arg_line
|
603
|
+
f" Example: {example_str}." in arg_line or f" Example: {example_str} ." in arg_line
|
622
604
|
):
|
623
605
|
arg_line = arg_line.replace(
|
624
606
|
f" Example: {example_str}.", ""
|
625
607
|
) # Remove with or without trailing period
|
626
|
-
arg_line +=
|
627
|
-
request_body_example_str # Append the formatted JSON example
|
628
|
-
)
|
608
|
+
arg_line += request_body_example_str # Append the formatted JSON example
|
629
609
|
|
630
610
|
args_doc_lines.append(arg_line)
|
631
|
-
elif arg_name == final_empty_body_param_name and has_empty_body:
|
611
|
+
elif arg_name == final_empty_body_param_name and has_empty_body: # Use potentially suffixed name
|
632
612
|
args_doc_lines.append(
|
633
613
|
f" {arg_name} (dict | None): Optional dictionary for arbitrary request body data."
|
634
614
|
)
|
635
615
|
# Also append example here if this is the designated body arg
|
636
|
-
if
|
637
|
-
|
638
|
-
):
|
639
|
-
args_doc_lines[-1] += (
|
640
|
-
request_body_example_str
|
641
|
-
)
|
616
|
+
if arg_name == last_body_arg_name and request_body_example_str:
|
617
|
+
args_doc_lines[-1] += request_body_example_str
|
642
618
|
|
643
619
|
if args_doc_lines:
|
644
620
|
docstring_parts.append("\n".join(args_doc_lines))
|
@@ -650,9 +626,7 @@ def _generate_method_code(path, method, operation):
|
|
650
626
|
if code.startswith("2"):
|
651
627
|
success_desc = resp_info.get("description", "").strip()
|
652
628
|
break
|
653
|
-
docstring_parts.append(
|
654
|
-
f"Returns:\n {return_type}: {success_desc or 'API response data.'}"
|
655
|
-
) # Use return_type
|
629
|
+
docstring_parts.append(f"Returns:\n {return_type}: {success_desc or 'API response data.'}") # Use return_type
|
656
630
|
|
657
631
|
# Tags Section
|
658
632
|
operation_tags = operation.get("tags", [])
|
@@ -668,9 +642,7 @@ def _generate_method_code(path, method, operation):
|
|
668
642
|
indented_docstring_content = textwrap.indent(docstring_content, doc_indent)
|
669
643
|
|
670
644
|
# Wrap in triple quotes
|
671
|
-
formatted_docstring =
|
672
|
-
f'\n{doc_indent}"""\n{indented_docstring_content}\n{doc_indent}"""'
|
673
|
-
)
|
645
|
+
formatted_docstring = f'\n{doc_indent}"""\n{indented_docstring_content}\n{doc_indent}"""'
|
674
646
|
# ----- End Build Docstring -----
|
675
647
|
|
676
648
|
if args:
|
@@ -685,7 +657,7 @@ def _generate_method_code(path, method, operation):
|
|
685
657
|
for param in path_params:
|
686
658
|
body_lines.append(f" if {param.name} is None:")
|
687
659
|
body_lines.append(
|
688
|
-
f
|
660
|
+
f" raise ValueError(\"Missing required parameter '{param.identifier}'\")" # Use original name in error
|
689
661
|
)
|
690
662
|
|
691
663
|
# Build request body (handle array and object types differently)
|
@@ -697,14 +669,12 @@ def _generate_method_code(path, method, operation):
|
|
697
669
|
elif request_body_properties:
|
698
670
|
# For object request bodies, build the request body from individual parameters
|
699
671
|
body_lines.append(" request_body = {")
|
700
|
-
for b_param in body_params:
|
672
|
+
for b_param in body_params: # Iterate through original body_params list
|
701
673
|
# Use b_param.identifier for the key in the request_body dictionary
|
702
674
|
# and b_param.name for the variable name from the function signature
|
703
675
|
body_lines.append(f" '{b_param.identifier}': {b_param.name},")
|
704
676
|
body_lines.append(" }")
|
705
|
-
body_lines.append(
|
706
|
-
" request_body = {k: v for k, v in request_body.items() if v is not None}"
|
707
|
-
)
|
677
|
+
body_lines.append(" request_body = {k: v for k, v in request_body.items() if v is not None}")
|
708
678
|
|
709
679
|
# Format URL directly with path parameters
|
710
680
|
url = _generate_url(path, path_params)
|
@@ -714,7 +684,7 @@ def _generate_method_code(path, method, operation):
|
|
714
684
|
# Build query parameters dictionary for the request
|
715
685
|
if query_params:
|
716
686
|
query_params_items = []
|
717
|
-
for param in query_params:
|
687
|
+
for param in query_params: # Iterate through original query_params list
|
718
688
|
# Use the original param.identifier for the key, and the (potentially aliased) param.name for the value variable
|
719
689
|
query_params_items.append(f"('{param.identifier}', {param.name})")
|
720
690
|
body_lines.append(
|
@@ -737,23 +707,15 @@ def _generate_method_code(path, method, operation):
|
|
737
707
|
if method_lower == "get":
|
738
708
|
body_lines.append(" response = self._get(url, params=query_params)")
|
739
709
|
elif method_lower == "post":
|
740
|
-
body_lines.append(
|
741
|
-
f" response = self._post(url, data={request_body_arg}, params=query_params)"
|
742
|
-
)
|
710
|
+
body_lines.append(f" response = self._post(url, data={request_body_arg}, params=query_params)")
|
743
711
|
elif method_lower == "put":
|
744
|
-
body_lines.append(
|
745
|
-
f" response = self._put(url, data={request_body_arg}, params=query_params)"
|
746
|
-
)
|
712
|
+
body_lines.append(f" response = self._put(url, data={request_body_arg}, params=query_params)")
|
747
713
|
elif method_lower == "patch":
|
748
|
-
body_lines.append(
|
749
|
-
f" response = self._patch(url, data={request_body_arg}, params=query_params)"
|
750
|
-
)
|
714
|
+
body_lines.append(f" response = self._patch(url, data={request_body_arg}, params=query_params)")
|
751
715
|
elif method_lower == "delete":
|
752
716
|
body_lines.append(" response = self._delete(url, params=query_params)")
|
753
717
|
else:
|
754
|
-
body_lines.append(
|
755
|
-
f" response = self._{method_lower}(url, data={request_body_arg}, params=query_params)"
|
756
|
-
)
|
718
|
+
body_lines.append(f" response = self._{method_lower}(url, data={request_body_arg}, params=query_params)")
|
757
719
|
|
758
720
|
# Handle response
|
759
721
|
body_lines.append(" response.raise_for_status()")
|
@@ -795,11 +757,7 @@ def generate_api_client(schema, class_name: str | None = None):
|
|
795
757
|
if api_title:
|
796
758
|
# Convert API title to a clean class name
|
797
759
|
if class_name:
|
798
|
-
clean_name = (
|
799
|
-
class_name.capitalize()[:-3]
|
800
|
-
if class_name.endswith("App")
|
801
|
-
else class_name.capitalize()
|
802
|
-
)
|
760
|
+
clean_name = class_name.capitalize()[:-3] if class_name.endswith("App") else class_name.capitalize()
|
803
761
|
else:
|
804
762
|
base_name = "".join(word.capitalize() for word in api_title.split())
|
805
763
|
clean_name = "".join(c for c in base_name if c.isalnum())
|
@@ -858,11 +816,7 @@ def generate_api_client(schema, class_name: str | None = None):
|
|
858
816
|
f"class {class_name}(APIApplication):\n"
|
859
817
|
f" def __init__(self, integration: Integration = None, **kwargs) -> None:\n"
|
860
818
|
f" super().__init__(name='{class_name.lower()}', integration=integration, **kwargs)\n"
|
861
|
-
f' self.base_url = "{base_url}"\n\n'
|
862
|
-
+ "\n\n".join(methods)
|
863
|
-
+ "\n\n"
|
864
|
-
+ list_tools_method
|
865
|
-
+ "\n"
|
819
|
+
f' self.base_url = "{base_url}"\n\n' + "\n\n".join(methods) + "\n\n" + list_tools_method + "\n"
|
866
820
|
)
|
867
821
|
return class_code
|
868
822
|
|
@@ -886,9 +840,7 @@ if __name__ == "__main__":
|
|
886
840
|
"responses": {
|
887
841
|
"200": {
|
888
842
|
"description": "A list of users",
|
889
|
-
"content": {
|
890
|
-
"application/json": {"schema": {"type": "array"}}
|
891
|
-
},
|
843
|
+
"content": {"application/json": {"schema": {"type": "array"}}},
|
892
844
|
}
|
893
845
|
},
|
894
846
|
},
|