universal-mcp 0.1.21rc2__py3-none-any.whl → 0.1.22rc4__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.
@@ -87,34 +87,34 @@ def _openapi_type_to_python_type(schema: dict, required: bool = True) -> str:
87
87
  """
88
88
  openapi_type = schema.get("type")
89
89
 
90
-
91
- if "$ref" in schema and not openapi_type:
92
- py_type = "dict[str, Any]"
90
+ if "$ref" in schema and not openapi_type:
91
+ py_type = "dict[str, Any]"
93
92
  elif openapi_type == "array":
94
93
  items_schema = schema.get("items", {})
95
- item_type = _openapi_type_to_python_type(items_schema, required=True)
94
+ item_type = _openapi_type_to_python_type(items_schema, required=True)
96
95
  py_type = f"List[{item_type}]"
97
96
  elif openapi_type == "object":
98
-
99
97
  if schema.get("format") in ["binary", "byte"]:
100
- py_type = "bytes"
98
+ py_type = "bytes"
101
99
  else:
102
-
103
100
  if "additionalProperties" in schema and isinstance(schema["additionalProperties"], dict):
104
101
  additional_props_schema = schema["additionalProperties"]
105
-
102
+
106
103
  value_type = _openapi_type_to_python_type(additional_props_schema, required=True)
107
104
  py_type = f"dict[str, {value_type}]"
108
- elif not schema.get("properties") and not schema.get("allOf") and not schema.get("oneOf") and not schema.get("anyOf"):
109
-
110
- py_type = "dict[str, Any]"
105
+ elif (
106
+ not schema.get("properties")
107
+ and not schema.get("allOf")
108
+ and not schema.get("oneOf")
109
+ and not schema.get("anyOf")
110
+ ):
111
+ py_type = "dict[str, Any]"
111
112
  else:
112
-
113
113
  py_type = "dict[str, Any]"
114
114
  elif openapi_type == "integer":
115
115
  py_type = "int"
116
116
  elif openapi_type == "number":
117
- py_type = "float"
117
+ py_type = "float"
118
118
  elif openapi_type == "boolean":
119
119
  py_type = "bool"
120
120
  elif openapi_type == "string":
@@ -124,9 +124,8 @@ def _openapi_type_to_python_type(schema: dict, required: bool = True) -> str:
124
124
  py_type = "str"
125
125
  else:
126
126
  py_type = "str"
127
- else:
128
-
129
- py_type = "Any"
127
+ else:
128
+ py_type = "Any"
130
129
 
131
130
  if not required:
132
131
  if py_type.startswith("Optional[") and py_type.endswith("]"):
@@ -150,7 +149,9 @@ def _sanitize_identifier(name: str | None) -> str:
150
149
  return ""
151
150
 
152
151
  # Initial replacements for common non-alphanumeric characters
153
- sanitized = name.replace("-", "_").replace(".", "_").replace("[", "_").replace("]", "").replace("$", "_")
152
+ sanitized = (
153
+ name.replace("-", "_").replace(".", "_").replace("[", "_").replace("]", "").replace("$", "_").replace("/", "_")
154
+ )
154
155
 
155
156
  # Remove leading underscores, but preserve a single underscore if the name (after initial replace)
156
157
  # consisted only of underscores.
@@ -256,7 +257,7 @@ def _determine_function_name(operation: dict[str, Any], path: str, method: str)
256
257
  if "operationId" in operation:
257
258
  raw_name = operation["operationId"]
258
259
  cleaned_name = raw_name.replace(".", "_").replace("-", "_")
259
- cleaned_name_no_numbers = re.sub(r'\d+', '', cleaned_name)
260
+ cleaned_name_no_numbers = re.sub(r"\d+", "", cleaned_name)
260
261
  func_name = convert_to_snake_case(cleaned_name_no_numbers)
261
262
  else:
262
263
  # Generate name from path and method
@@ -291,7 +292,7 @@ def _generate_path_params(path: str) -> list[Parameters]:
291
292
  where="path",
292
293
  required=True,
293
294
  example=None,
294
- schema={"type": "string"}
295
+ schema={"type": "string"},
295
296
  )
296
297
  )
297
298
  except Exception as e:
@@ -340,7 +341,7 @@ def _generate_query_params(operation: dict[str, Any]) -> list[Parameters]:
340
341
  where=where,
341
342
  required=required,
342
343
  example=str(example_value) if example_value is not None else None,
343
- schema=param_schema if param_schema else {"type": type_value}
344
+ schema=param_schema if param_schema else {"type": type_value},
344
345
  )
345
346
  query_params.append(parameter)
346
347
  return query_params
@@ -372,12 +373,12 @@ def _generate_body_params(schema_to_process: dict[str, Any] | None, overall_body
372
373
  name=_sanitize_identifier(param_name),
373
374
  identifier=param_name,
374
375
  description=param_description,
375
- type=effective_param_type,
376
+ type=effective_param_type,
376
377
  where="body",
377
378
  required=param_required,
378
379
  example=str(param_example) if param_example is not None else None,
379
380
  is_file=current_is_file,
380
- schema=param_schema_details
381
+ schema=param_schema_details,
381
382
  )
382
383
  )
383
384
  # print(f"[DEBUG] Final body_params list generated: {body_params}") # DEBUG
@@ -403,10 +404,10 @@ def _generate_method_code(path, method, operation):
403
404
 
404
405
  # --- Determine Function Name and Basic Operation Details ---
405
406
  func_name = _determine_function_name(operation, path, method)
406
- method_lower = method.lower() # Define method_lower earlier
407
- operation.get("summary", "") # Ensure summary is accessed if needed elsewhere
408
- operation.get("tags", []) # Ensure tags are accessed if needed elsewhere
409
-
407
+ method_lower = method.lower() # Define method_lower earlier
408
+ operation.get("summary", "") # Ensure summary is accessed if needed elsewhere
409
+ operation.get("tags", []) # Ensure tags are accessed if needed elsewhere
410
+
410
411
  # --- Generate Path and Query Parameters (pre-aliasing) ---
411
412
  path_params = _generate_path_params(path)
412
413
  query_params = _generate_query_params(operation)
@@ -415,7 +416,7 @@ def _generate_method_code(path, method, operation):
415
416
  # This section selects the primary content type and its schema to be used for the request body.
416
417
  has_body = "requestBody" in operation
417
418
  body_schema_to_use = None
418
- selected_content_type = None # This will hold the chosen content type string
419
+ selected_content_type = None # This will hold the chosen content type string
419
420
 
420
421
  if has_body:
421
422
  request_body_spec = operation["requestBody"]
@@ -428,7 +429,7 @@ def _generate_method_code(path, method, operation):
428
429
  "application/octet-stream",
429
430
  "text/plain",
430
431
  ]
431
-
432
+
432
433
  found_preferred = False
433
434
  for ct in preferred_content_types:
434
435
  if ct in request_body_content_map:
@@ -436,25 +437,25 @@ def _generate_method_code(path, method, operation):
436
437
  body_schema_to_use = request_body_content_map[ct].get("schema")
437
438
  found_preferred = True
438
439
  break
439
-
440
- if not found_preferred: # Check for image/* if no direct match yet
440
+
441
+ if not found_preferred: # Check for image/* if no direct match yet
441
442
  for ct_key in request_body_content_map:
442
443
  if ct_key.startswith("image/"):
443
444
  selected_content_type = ct_key
444
445
  body_schema_to_use = request_body_content_map[ct_key].get("schema")
445
446
  found_preferred = True
446
447
  break
447
-
448
- if not found_preferred and request_body_content_map: # Fallback to first listed
448
+
449
+ if not found_preferred and request_body_content_map: # Fallback to first listed
449
450
  first_ct_key = next(iter(request_body_content_map))
450
451
  selected_content_type = first_ct_key
451
452
  body_schema_to_use = request_body_content_map[first_ct_key].get("schema")
452
453
 
453
454
  # --- Generate Body Parameters (based on selected schema, pre-aliasing) ---
454
- if body_schema_to_use: # If a schema was actually found for the selected content type
455
+ if body_schema_to_use: # If a schema was actually found for the selected content type
455
456
  body_params = _generate_body_params(
456
- body_schema_to_use, # Pass the specific schema
457
- operation.get("requestBody", {}).get("required", False) # Pass the overall body requirement
457
+ body_schema_to_use, # Pass the specific schema
458
+ operation.get("requestBody", {}).get("required", False), # Pass the overall body requirement
458
459
  )
459
460
  else:
460
461
  body_params = []
@@ -526,29 +527,36 @@ def _generate_method_code(path, method, operation):
526
527
  current_body_param_names.add(b_param.name)
527
528
  # --- End Alias duplicate parameter names ---
528
529
 
529
-
530
530
  # --- Determine Return Type and Body Characteristics ---
531
531
  return_type = _determine_return_type(operation)
532
532
 
533
- body_required = has_body and operation["requestBody"].get("required", False) # Remains useful
534
-
533
+ body_required = has_body and operation["requestBody"].get("required", False) # Remains useful
534
+
535
535
  is_array_body = False
536
- has_empty_body = False
536
+ has_empty_body = False
537
537
 
538
- if has_body and body_schema_to_use: # Use the determined body_schema_to_use
538
+ if has_body and body_schema_to_use: # Use the determined body_schema_to_use
539
539
  if body_schema_to_use.get("type") == "array":
540
540
  is_array_body = True
541
-
541
+
542
542
  # Check for cases that might lead to an "empty" body parameter (for JSON) in the signature,
543
543
  # or indicate a raw body type where _generate_body_params wouldn't create named params.
544
- if not body_params and not is_array_body and selected_content_type == "application/json" and \
545
- (body_schema_to_use == {} or \
546
- (body_schema_to_use.get("type") == "object" and \
547
- not body_schema_to_use.get("properties") and \
548
- not body_schema_to_use.get("allOf") and \
549
- not body_schema_to_use.get("oneOf") and \
550
- not body_schema_to_use.get("anyOf"))):
551
- has_empty_body = True # Indicates a generic 'request_body: dict = None' might be needed for empty JSON
544
+ if (
545
+ not body_params
546
+ and not is_array_body
547
+ and selected_content_type == "application/json"
548
+ and (
549
+ body_schema_to_use == {}
550
+ or (
551
+ body_schema_to_use.get("type") == "object"
552
+ and not body_schema_to_use.get("properties")
553
+ and not body_schema_to_use.get("allOf")
554
+ and not body_schema_to_use.get("oneOf")
555
+ and not body_schema_to_use.get("anyOf")
556
+ )
557
+ )
558
+ ):
559
+ has_empty_body = True # Indicates a generic 'request_body: dict = None' might be needed for empty JSON
552
560
 
553
561
  # --- Build Function Arguments for Signature ---
554
562
  # This section constructs the list of arguments (required and optional)
@@ -588,8 +596,8 @@ def _generate_method_code(path, method, operation):
588
596
  # Process Body Parameters / Request Body
589
597
  # This list tracks the *final* names of parameters in the signature that come from the request body,
590
598
  final_request_body_arg_names_for_signature = []
591
- final_empty_body_param_name = None # For the specific case of has_empty_body (empty JSON object)
592
- raw_body_param_name = None # For raw content like octet-stream, text/plain, image/*
599
+ final_empty_body_param_name = None # For the specific case of has_empty_body (empty JSON object)
600
+ raw_body_param_name = None # For raw content like octet-stream, text/plain, image/*
593
601
 
594
602
  if has_body:
595
603
  current_arg_names_set = set(required_args) | {arg.split("=")[0] for arg in optional_args}
@@ -624,11 +632,17 @@ def _generate_method_code(path, method, operation):
624
632
  final_request_body_arg_names_for_signature.append(final_array_param_name)
625
633
 
626
634
  # New: Handle raw body parameter (if body_params is empty but body is expected and not array/empty JSON)
627
- elif not body_params and not is_array_body and selected_content_type and selected_content_type not in ["application/json", "application/x-www-form-urlencoded", "multipart/form-data"]:
635
+ elif (
636
+ not body_params
637
+ and not is_array_body
638
+ and selected_content_type
639
+ and selected_content_type
640
+ not in ["application/json", "application/x-www-form-urlencoded", "multipart/form-data"]
641
+ ):
628
642
  # This branch is for raw content types like application/octet-stream, text/plain, image/*
629
643
  # where _generate_body_params returned an empty list because the schema isn't an object with properties.
630
644
  raw_body_param_name_base = "body_content"
631
-
645
+
632
646
  temp_raw_body_name = raw_body_param_name_base
633
647
  counter = 1
634
648
  is_first_suffix_attempt = True
@@ -643,15 +657,15 @@ def _generate_method_code(path, method, operation):
643
657
 
644
658
  # For signature with types
645
659
  # Determine type based on selected_content_type for raw body
646
- raw_body_schema_for_type = {"type": "string", "format": "binary"} # Default to bytes
660
+ raw_body_schema_for_type = {"type": "string", "format": "binary"} # Default to bytes
647
661
  if selected_content_type and "text" in selected_content_type:
648
662
  raw_body_schema_for_type = {"type": "string"}
649
663
  elif selected_content_type and selected_content_type.startswith("image/"):
650
- raw_body_schema_for_type = {"type": "string", "format": "binary"} # image is bytes
651
-
664
+ raw_body_schema_for_type = {"type": "string", "format": "binary"} # image is bytes
665
+
652
666
  raw_body_py_type = _openapi_type_to_python_type(raw_body_schema_for_type, required=body_required)
653
667
 
654
- if body_required: # If the raw body itself is required
668
+ if body_required: # If the raw body itself is required
655
669
  required_args.append(raw_body_param_name)
656
670
  signature_required_args_typed.append(f"{raw_body_param_name}: {raw_body_py_type}")
657
671
  else:
@@ -659,13 +673,13 @@ def _generate_method_code(path, method, operation):
659
673
  signature_optional_args_typed.append(f"{raw_body_param_name}: {raw_body_py_type} = None")
660
674
  final_request_body_arg_names_for_signature.append(raw_body_param_name)
661
675
 
662
- elif body_params: # Object body with discernible properties
676
+ elif body_params: # Object body with discernible properties
663
677
  for param in body_params: # Iterate ALIASED body_params
664
- arg_name_for_sig = param.name #final aliased name (e.g., "id_body")
678
+ arg_name_for_sig = param.name # final aliased name (e.g., "id_body")
665
679
 
666
- # Defensive check against already added args
680
+ # Defensive check against already added args
667
681
  current_arg_names_set_loop = set(required_args) | {arg.split("=")[0] for arg in optional_args}
668
-
682
+
669
683
  # For signature with types
670
684
  param_py_type = _openapi_type_to_python_type(param.schema, required=param.required)
671
685
 
@@ -679,11 +693,16 @@ def _generate_method_code(path, method, operation):
679
693
  signature_optional_args_typed.append(f"{arg_name_for_sig}: {param_py_type} = None")
680
694
  final_request_body_arg_names_for_signature.append(arg_name_for_sig)
681
695
 
696
+ if (
697
+ has_empty_body
698
+ and selected_content_type == "application/json"
699
+ and not body_params
700
+ and not is_array_body
701
+ and not raw_body_param_name
702
+ ):
703
+ empty_body_param_name_base = "request_body" # For empty JSON object
704
+ current_arg_names_set = set(required_args) | {arg.split("=")[0] for arg in optional_args}
682
705
 
683
- if has_empty_body and selected_content_type == "application/json" and not body_params and not is_array_body and not raw_body_param_name:
684
- empty_body_param_name_base = "request_body" # For empty JSON object
685
- current_arg_names_set = set(required_args) | {arg.split('=')[0] for arg in optional_args}
686
-
687
706
  final_empty_body_param_name = empty_body_param_name_base
688
707
  counter = 1
689
708
  is_first_suffix_attempt = True
@@ -710,19 +729,19 @@ def _generate_method_code(path, method, operation):
710
729
 
711
730
  # Combine required and optional arguments FOR DOCSTRING (as before, without types)
712
731
  args = required_args + optional_args
713
- print(f"[DEBUG] Final combined args for DOCSTRING: {args}") # DEBUG
732
+ print(f"[DEBUG] Final combined args for DOCSTRING: {args}") # DEBUG
714
733
 
715
734
  # Combine required and optional arguments FOR SIGNATURE (with types)
716
735
  signature_args_combined_typed = signature_required_args_typed + signature_optional_args_typed
717
- print(f"[DEBUG] Final combined args for SIGNATURE: {signature_args_combined_typed}") # DEBUG
736
+ print(f"[DEBUG] Final combined args for SIGNATURE: {signature_args_combined_typed}") # DEBUG
718
737
 
719
- # ----- Build Docstring -----
738
+ # ----- Build Docstring -----
720
739
  # This section constructs the entire docstring for the generated method,
721
740
  # including summary, argument descriptions, return type, and tags.
722
741
  docstring_parts = []
723
742
  # NEW: Add OpenAPI path as the first line of the docstring
724
- openapi_path_comment_for_docstring = f"# openapi_path: {path}"
725
- docstring_parts.append(openapi_path_comment_for_docstring)
743
+ # openapi_path_comment_for_docstring = f"# openapi_path: {path}"
744
+ # docstring_parts.append(openapi_path_comment_for_docstring)
726
745
 
727
746
  return_type = _determine_return_type(operation)
728
747
 
@@ -737,7 +756,7 @@ def _generate_method_code(path, method, operation):
737
756
  # Args
738
757
  args_doc_lines = []
739
758
  param_details = {}
740
-
759
+
741
760
  # Create a combined list of all parameter objects (path, query, body) to fetch details for docstring
742
761
  all_parameter_objects_for_docstring = path_params + query_params + body_params
743
762
 
@@ -748,18 +767,18 @@ def _generate_method_code(path, method, operation):
748
767
  param_details[param_obj.name] = param_obj
749
768
 
750
769
  # Fetch request body example
751
- example_data = None # Initialize example_data here for wider scope
770
+ example_data = None # Initialize example_data here for wider scope
752
771
 
753
772
  if has_body:
754
773
  try:
755
774
  json_content = operation["requestBody"]["content"]["application/json"]
756
- #From direct content definition
775
+ # From direct content definition
757
776
  if "example" in json_content:
758
777
  example_data = json_content["example"]
759
778
  elif "examples" in json_content and json_content["examples"]:
760
779
  first_example_key = list(json_content["examples"].keys())[0]
761
780
  example_data = json_content["examples"][first_example_key].get("value")
762
- #If not found directly, try from resolved body schema (for nested/referenced examples)
781
+ # If not found directly, try from resolved body schema (for nested/referenced examples)
763
782
  if example_data is None and body_schema_to_use and "example" in body_schema_to_use:
764
783
  example_data = body_schema_to_use["example"]
765
784
  except KeyError:
@@ -777,18 +796,24 @@ def _generate_method_code(path, method, operation):
777
796
  # Adjust type_hint for file parameters for the docstring
778
797
  if detail.is_file:
779
798
  type_hint = "file (e.g., open('path/to/file', 'rb'))"
780
-
799
+
781
800
  arg_line = f" {arg_name} ({type_hint}): {desc}"
782
- if detail.example and not detail.is_file: # Don't show schema example for file inputs
801
+ if detail.example and not detail.is_file: # Don't show schema example for file inputs
783
802
  example_str = repr(detail.example)
784
803
  arg_line += f" Example: {example_str}."
785
804
  # Fallback for body parameters if no direct example was found
786
- elif not example_str and detail.where == "body" and example_data and isinstance(example_data, dict) and detail.identifier in example_data:
805
+ elif (
806
+ not example_str
807
+ and detail.where == "body"
808
+ and example_data
809
+ and isinstance(example_data, dict)
810
+ and detail.identifier in example_data
811
+ ):
787
812
  current_body_param_example = example_data[detail.identifier]
788
- if current_body_param_example is not None: # Ensure the extracted part is not None
813
+ if current_body_param_example is not None: # Ensure the extracted part is not None
789
814
  try:
790
815
  arg_line += f" Example: {repr(current_body_param_example)}."
791
- except Exception: # Fallback if repr fails
816
+ except Exception: # Fallback if repr fails
792
817
  arg_line += " Example: [Could not represent example]."
793
818
 
794
819
  args_doc_lines.append(arg_line)
@@ -797,19 +822,17 @@ def _generate_method_code(path, method, operation):
797
822
  args_doc_lines.append(
798
823
  f" {arg_name} (dict | None): Optional dictionary for an empty JSON request body (e.g., {{}})."
799
824
  )
800
- elif arg_name == raw_body_param_name:
825
+ elif arg_name == raw_body_param_name:
801
826
  raw_body_type_hint = "bytes"
802
827
  raw_body_desc = "Raw binary content for the request body."
803
828
  if selected_content_type and "text" in selected_content_type:
804
829
  raw_body_type_hint = "str"
805
830
  raw_body_desc = "Raw text content for the request body."
806
831
  elif selected_content_type and selected_content_type.startswith("image/"):
807
- raw_body_type_hint = "bytes (image data)"
808
- raw_body_desc = f"Raw image content ({selected_content_type}) for the request body."
809
- args_doc_lines.append(
810
- f" {arg_name} ({raw_body_type_hint} | None): {raw_body_desc}"
811
- )
812
-
832
+ raw_body_type_hint = "bytes (image data)"
833
+ raw_body_desc = f"Raw image content ({selected_content_type}) for the request body."
834
+ args_doc_lines.append(f" {arg_name} ({raw_body_type_hint} | None): {raw_body_desc}")
835
+
813
836
  if args_doc_lines:
814
837
  docstring_parts.append("\n".join(args_doc_lines))
815
838
 
@@ -825,7 +848,7 @@ def _generate_method_code(path, method, operation):
825
848
  raises_section_lines = [
826
849
  "Raises:",
827
850
  " HTTPError: Raised when the API request fails (e.g., non-2XX status code).",
828
- " JSONDecodeError: Raised if the response body cannot be parsed as JSON."
851
+ " JSONDecodeError: Raised if the response body cannot be parsed as JSON.",
829
852
  ]
830
853
  docstring_parts.append("\n".join(raises_section_lines))
831
854
 
@@ -853,7 +876,7 @@ def _generate_method_code(path, method, operation):
853
876
  else:
854
877
  signature = f" def {func_name}(self) -> {return_type}:"
855
878
 
856
- # --- Build Method Body ---
879
+ # --- Build Method Body ---
857
880
  # This section constructs the executable lines of code within the generated method.
858
881
  body_lines = []
859
882
 
@@ -861,10 +884,9 @@ def _generate_method_code(path, method, operation):
861
884
  for param in path_params:
862
885
  body_lines.append(f" if {param.name} is None:")
863
886
  body_lines.append(
864
- f' raise ValueError("Missing required parameter \'{param.identifier}\'.")' # Use original name in error, ensure quotes are balanced
887
+ f" raise ValueError(\"Missing required parameter '{param.identifier}'.\")" # Use original name in error, ensure quotes are balanced
865
888
  )
866
889
 
867
-
868
890
  if method_lower not in ["get", "delete"]:
869
891
  body_lines.append(" request_body_data = None")
870
892
 
@@ -874,7 +896,6 @@ def _generate_method_code(path, method, operation):
874
896
  if method_lower in ["post", "put"] and selected_content_type == "multipart/form-data":
875
897
  body_lines.append(" files_data = None")
876
898
 
877
-
878
899
  # --- Build Request Payload (request_body_data and files_data) ---
879
900
  # This section prepares the data to be sent in the request body,
880
901
  # differentiating between files and other data for multipart forms,
@@ -883,27 +904,30 @@ def _generate_method_code(path, method, operation):
883
904
  # This block will now overwrite the initial None values if a body is present.
884
905
  if is_array_body:
885
906
  # For array request bodies, use the array parameter directly
886
- array_arg_name = final_request_body_arg_names_for_signature[0] if final_request_body_arg_names_for_signature else "items_body" # Fallback
907
+ array_arg_name = (
908
+ final_request_body_arg_names_for_signature[0]
909
+ if final_request_body_arg_names_for_signature
910
+ else "items_body"
911
+ ) # Fallback
887
912
  body_lines.append(f" # Using array parameter '{array_arg_name}' directly as request body")
888
- body_lines.append(f" request_body_data = {array_arg_name}") # Use a neutral temp name
913
+ body_lines.append(f" request_body_data = {array_arg_name}") # Use a neutral temp name
889
914
  # files_data remains None
890
915
 
891
916
  elif selected_content_type == "multipart/form-data":
892
- body_lines.append(" request_body_data = {}") # For non-file form fields
893
- body_lines.append(" files_data = {}") # For file fields
894
- for b_param in body_params: # Iterate through ALIASED body_params
917
+ body_lines.append(" request_body_data = {}") # For non-file form fields
918
+ body_lines.append(" files_data = {}") # For file fields
919
+ for b_param in body_params: # Iterate through ALIASED body_params
895
920
  if b_param.is_file:
896
- body_lines.append(f" if {b_param.name} is not None:") # Check if file param is provided
921
+ body_lines.append(f" if {b_param.name} is not None:") # Check if file param is provided
897
922
  body_lines.append(f" files_data['{b_param.identifier}'] = {b_param.name}")
898
923
  else:
899
- body_lines.append(f" if {b_param.name} is not None:") # Check if form field is provided
924
+ body_lines.append(f" if {b_param.name} is not None:") # Check if form field is provided
900
925
  body_lines.append(f" request_body_data['{b_param.identifier}'] = {b_param.name}")
901
926
  body_lines.append(" files_data = {k: v for k, v in files_data.items() if v is not None}")
902
927
  # Ensure files_data is None if it's empty after filtering, as httpx expects None, not {}
903
928
  body_lines.append(" if not files_data: files_data = None")
904
929
 
905
-
906
- elif body_params: # Object request bodies (JSON, x-www-form-urlencoded) with specific parameters
930
+ elif body_params: # Object request bodies (JSON, x-www-form-urlencoded) with specific parameters
907
931
  body_lines.append(" request_body_data = {")
908
932
  for b_param in body_params:
909
933
  body_lines.append(f" '{b_param.identifier}': {b_param.name},")
@@ -911,13 +935,14 @@ def _generate_method_code(path, method, operation):
911
935
  body_lines.append(
912
936
  " request_body_data = {k: v for k, v in request_body_data.items() if v is not None}"
913
937
  )
914
-
915
- elif raw_body_param_name: # Raw content type (octet-stream, text, image)
938
+
939
+ elif raw_body_param_name: # Raw content type (octet-stream, text, image)
916
940
  body_lines.append(f" request_body_data = {raw_body_param_name}")
917
941
 
918
- elif has_empty_body and selected_content_type == "application/json": # Empty JSON object {}
919
- body_lines.append(f" request_body_data = {final_empty_body_param_name} if {final_empty_body_param_name} is not None else {{}}")
920
-
942
+ elif has_empty_body and selected_content_type == "application/json": # Empty JSON object {}
943
+ body_lines.append(
944
+ f" request_body_data = {final_empty_body_param_name} if {final_empty_body_param_name} is not None else {{}}"
945
+ )
921
946
 
922
947
  # --- Format URL and Query Parameters for Request ---
923
948
  url = _generate_url(path, path_params)
@@ -937,21 +962,20 @@ def _generate_method_code(path, method, operation):
937
962
 
938
963
  # --- Determine Final Content-Type for API Call (Obsolete Block, selected_content_type is used) ---
939
964
  # The following block for request_body_content_type is largely superseded by selected_content_type,
940
-
965
+
941
966
  # Use the selected_content_type determined by the new logic as the primary source of truth.
942
967
  final_content_type_for_api_call = selected_content_type if selected_content_type else "application/json"
943
968
 
944
969
  # --- Make HTTP Request ---
945
- # This section generates the actual HTTP call
970
+ # This section generates the actual HTTP call
946
971
  # using the prepared URL, query parameters, request body data, files, and content type.
947
972
 
948
-
949
973
  if method_lower == "get":
950
974
  body_lines.append(" response = self._get(url, params=query_params)")
951
975
  elif method_lower == "post":
952
976
  if selected_content_type == "multipart/form-data":
953
977
  body_lines.append(
954
- f" response = self._post(url, data=request_body_data, files=files_data, params=query_params, content_type='{final_content_type_for_api_call}')"
978
+ f" response = self._post(url, data=request_body_data, files=files_data, params=query_params, content_type='{final_content_type_for_api_call}')"
955
979
  )
956
980
  else:
957
981
  body_lines.append(
@@ -960,23 +984,18 @@ def _generate_method_code(path, method, operation):
960
984
  elif method_lower == "put":
961
985
  if selected_content_type == "multipart/form-data":
962
986
  body_lines.append(
963
- f" response = self._put(url, data=request_body_data, files=files_data, params=query_params, content_type='{final_content_type_for_api_call}')"
987
+ f" response = self._put(url, data=request_body_data, files=files_data, params=query_params, content_type='{final_content_type_for_api_call}')"
964
988
  )
965
989
  else:
966
990
  body_lines.append(
967
991
  f" response = self._put(url, data=request_body_data, params=query_params, content_type='{final_content_type_for_api_call}')"
968
992
  )
969
993
  elif method_lower == "patch":
970
-
971
- body_lines.append(
972
- " response = self._patch(url, data=request_body_data, params=query_params)"
973
- )
994
+ body_lines.append(" response = self._patch(url, data=request_body_data, params=query_params)")
974
995
  elif method_lower == "delete":
975
996
  body_lines.append(" response = self._delete(url, params=query_params)")
976
997
  else:
977
- body_lines.append(
978
- f" response = self._{method_lower}(url, data=request_body_data, params=query_params)"
979
- )
998
+ body_lines.append(f" response = self._{method_lower}(url, data=request_body_data, params=query_params)")
980
999
 
981
1000
  # --- Handle Response ---
982
1001
  body_lines.append(" response.raise_for_status()")
@@ -1145,4 +1164,4 @@ if __name__ == "__main__":
1145
1164
 
1146
1165
  schema = load_schema("openapi.yaml")
1147
1166
  code = generate_api_client(schema)
1148
- print(code)
1167
+ print(code)