pyopenapi-gen 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.
Files changed (29) hide show
  1. pyopenapi_gen/core/loader/loader.py +4 -2
  2. pyopenapi_gen/core/loader/operations/parser.py +12 -6
  3. pyopenapi_gen/core/loader/operations/post_processor.py +4 -2
  4. pyopenapi_gen/core/loader/operations/request_body.py +10 -5
  5. pyopenapi_gen/core/loader/parameters/parser.py +43 -10
  6. pyopenapi_gen/core/loader/responses/parser.py +14 -7
  7. pyopenapi_gen/core/loader/schemas/extractor.py +25 -11
  8. pyopenapi_gen/core/parsing/context.py +4 -2
  9. pyopenapi_gen/core/parsing/keywords/all_of_parser.py +8 -4
  10. pyopenapi_gen/core/parsing/keywords/any_of_parser.py +10 -5
  11. pyopenapi_gen/core/parsing/keywords/array_items_parser.py +6 -3
  12. pyopenapi_gen/core/parsing/keywords/one_of_parser.py +10 -5
  13. pyopenapi_gen/core/parsing/schema_finalizer.py +6 -3
  14. pyopenapi_gen/core/parsing/schema_parser.py +6 -4
  15. pyopenapi_gen/emitters/endpoints_emitter.py +2 -1
  16. pyopenapi_gen/emitters/models_emitter.py +12 -14
  17. pyopenapi_gen/helpers/type_resolution/named_resolver.py +6 -7
  18. pyopenapi_gen/helpers/type_resolution/object_resolver.py +18 -14
  19. pyopenapi_gen/types/resolvers/schema_resolver.py +9 -2
  20. pyopenapi_gen/visit/endpoint/generators/response_handler_generator.py +1 -1
  21. pyopenapi_gen/visit/model/alias_generator.py +15 -8
  22. pyopenapi_gen/visit/model/dataclass_generator.py +25 -15
  23. pyopenapi_gen/visit/model/enum_generator.py +34 -22
  24. pyopenapi_gen/visit/model/model_visitor.py +7 -5
  25. {pyopenapi_gen-0.11.0.dist-info → pyopenapi_gen-0.12.0.dist-info}/METADATA +3 -3
  26. {pyopenapi_gen-0.11.0.dist-info → pyopenapi_gen-0.12.0.dist-info}/RECORD +29 -29
  27. {pyopenapi_gen-0.11.0.dist-info → pyopenapi_gen-0.12.0.dist-info}/WHEEL +0 -0
  28. {pyopenapi_gen-0.11.0.dist-info → pyopenapi_gen-0.12.0.dist-info}/entry_points.txt +0 -0
  29. {pyopenapi_gen-0.11.0.dist-info → pyopenapi_gen-0.12.0.dist-info}/licenses/LICENSE +0 -0
@@ -148,8 +148,10 @@ class SpecLoader:
148
148
  )
149
149
 
150
150
  # Post-condition check
151
- assert ir_spec.schemas == schemas_dict, "Schemas mismatch in IRSpec"
152
- assert ir_spec.operations == operations, "Operations mismatch in IRSpec"
151
+ if ir_spec.schemas != schemas_dict:
152
+ raise RuntimeError("Schemas mismatch in IRSpec")
153
+ if ir_spec.operations != operations:
154
+ raise RuntimeError("Operations mismatch in IRSpec")
153
155
 
154
156
  return ir_spec
155
157
 
@@ -39,11 +39,16 @@ def parse_operations(
39
39
  - All operations have correct path, method, parameters, responses, etc.
40
40
  - All referenced schemas are properly stored in context
41
41
  """
42
- assert isinstance(paths, Mapping), "paths must be a Mapping"
43
- assert isinstance(raw_parameters, Mapping), "raw_parameters must be a Mapping"
44
- assert isinstance(raw_responses, Mapping), "raw_responses must be a Mapping"
45
- assert isinstance(raw_request_bodies, Mapping), "raw_request_bodies must be a Mapping"
46
- assert isinstance(context, ParsingContext), "context must be a ParsingContext"
42
+ if not isinstance(paths, Mapping):
43
+ raise TypeError("paths must be a Mapping")
44
+ if not isinstance(raw_parameters, Mapping):
45
+ raise TypeError("raw_parameters must be a Mapping")
46
+ if not isinstance(raw_responses, Mapping):
47
+ raise TypeError("raw_responses must be a Mapping")
48
+ if not isinstance(raw_request_bodies, Mapping):
49
+ raise TypeError("raw_request_bodies must be a Mapping")
50
+ if not isinstance(context, ParsingContext):
51
+ raise TypeError("context must be a ParsingContext")
47
52
 
48
53
  ops: List[IROperation] = []
49
54
 
@@ -150,6 +155,7 @@ def parse_operations(
150
155
  ops.append(op)
151
156
 
152
157
  # Post-condition check
153
- assert all(isinstance(op, IROperation) for op in ops), "All items must be IROperation objects"
158
+ if not all(isinstance(op, IROperation) for op in ops):
159
+ raise TypeError("All items must be IROperation objects")
154
160
 
155
161
  return ops
@@ -24,8 +24,10 @@ def post_process_operation(op: IROperation, context: ParsingContext) -> None:
24
24
  Postconditions:
25
25
  - All request body and response schemas are properly named and registered
26
26
  """
27
- assert isinstance(op, IROperation), "op must be an IROperation"
28
- assert isinstance(context, ParsingContext), "context must be a ParsingContext"
27
+ if not isinstance(op, IROperation):
28
+ raise TypeError("op must be an IROperation")
29
+ if not isinstance(context, ParsingContext):
30
+ raise TypeError("context must be a ParsingContext")
29
31
 
30
32
  # Handle request body schemas
31
33
  if op.request_body:
@@ -33,10 +33,14 @@ def parse_request_body(
33
33
  - Returns a properly populated IRRequestBody or None if invalid
34
34
  - All content media types are properly mapped to schemas
35
35
  """
36
- assert isinstance(rb_node, Mapping), "rb_node must be a Mapping"
37
- assert isinstance(raw_request_bodies, Mapping), "raw_request_bodies must be a Mapping"
38
- assert isinstance(context, ParsingContext), "context must be a ParsingContext"
39
- assert operation_id, "operation_id must be provided"
36
+ if not isinstance(rb_node, Mapping):
37
+ raise TypeError("rb_node must be a Mapping")
38
+ if not isinstance(raw_request_bodies, Mapping):
39
+ raise TypeError("raw_request_bodies must be a Mapping")
40
+ if not isinstance(context, ParsingContext):
41
+ raise TypeError("context must be a ParsingContext")
42
+ if not operation_id:
43
+ raise ValueError("operation_id must be provided")
40
44
 
41
45
  # Handle $ref in request body
42
46
  if (
@@ -80,6 +84,7 @@ def parse_request_body(
80
84
  request_body = IRRequestBody(required=required_flag, content=content_map, description=desc)
81
85
 
82
86
  # Post-condition check
83
- assert request_body.content == content_map, "Request body content mismatch"
87
+ if request_body.content != content_map:
88
+ raise RuntimeError("Request body content mismatch")
84
89
 
85
90
  return request_body
@@ -27,8 +27,10 @@ def resolve_parameter_node_if_ref(param_node_data: Mapping[str, Any], context: P
27
27
  - Returns the resolved parameter node or the original if not a ref
28
28
  - If a reference, the parameter is looked up in components
29
29
  """
30
- assert isinstance(param_node_data, Mapping), "param_node_data must be a Mapping"
31
- assert isinstance(context, ParsingContext), "context must be a ParsingContext"
30
+ if not isinstance(param_node_data, Mapping):
31
+ raise TypeError("param_node_data must be a Mapping")
32
+ if not isinstance(context, ParsingContext):
33
+ raise TypeError("context must be a ParsingContext")
32
34
 
33
35
  if "$ref" in param_node_data and isinstance(param_node_data.get("$ref"), str):
34
36
  ref_path = param_node_data["$ref"]
@@ -62,9 +64,12 @@ def parse_parameter(
62
64
  - Returns a properly populated IRParameter
63
65
  - Complex parameter schemas are given appropriate names
64
66
  """
65
- assert isinstance(node, Mapping), "node must be a Mapping"
66
- assert "name" in node, "Parameter node must have a name"
67
- assert isinstance(context, ParsingContext), "context must be a ParsingContext"
67
+ if not isinstance(node, Mapping):
68
+ raise TypeError("node must be a Mapping")
69
+ if "name" not in node:
70
+ raise ValueError("Parameter node must have a name")
71
+ if not isinstance(context, ParsingContext):
72
+ raise TypeError("context must be a ParsingContext")
68
73
 
69
74
  sch = node.get("schema")
70
75
  param_name = node["name"]
@@ -114,12 +119,38 @@ def parse_parameter(
114
119
  and "enum" in sch["items"]
115
120
  and "$ref" not in sch["items"]
116
121
  ):
117
- # This is an array of string enums - for parameters, we can treat this as List[str]
118
- # rather than creating complex named schemas
122
+ # This is an array of string enums - create a proper enum schema for the items
123
+ # Give it a name based on the parameter and operation
124
+ enum_name = None
125
+ if operation_id_for_promo and param_name:
126
+ # Create a name for this inline enum when we have operation context
127
+ enum_name = f"{operation_id_for_promo}Param{NameSanitizer.sanitize_class_name(param_name)}Item"
128
+ elif param_name:
129
+ # For component parameters without operation context, use just the parameter name
130
+ enum_name = f"{NameSanitizer.sanitize_class_name(param_name)}Item"
131
+
132
+ if enum_name:
133
+ items_schema = IRSchema(
134
+ name=enum_name,
135
+ type="string",
136
+ enum=sch["items"]["enum"],
137
+ generation_name=enum_name, # Mark it as promoted
138
+ )
139
+ logger.debug(
140
+ f"Created enum schema '{enum_name}' for array parameter '{param_name}' with values {sch['items']['enum'][:3]}..."
141
+ )
142
+ else:
143
+ # Fallback if we don't have enough info to create a good name
144
+ items_schema = IRSchema(name=None, type="string", enum=sch["items"]["enum"])
145
+ logger.warning(
146
+ f"Could not create proper enum name for parameter array items with values {sch['items']['enum'][:3]}... "
147
+ f"This will generate a warning during type resolution."
148
+ )
149
+
119
150
  schema_ir = IRSchema(
120
151
  name=None,
121
152
  type="array",
122
- items=IRSchema(name=None, type="string", enum=sch["items"]["enum"]),
153
+ items=items_schema,
123
154
  description=sch.get("description"),
124
155
  )
125
156
  else:
@@ -138,7 +169,9 @@ def parse_parameter(
138
169
  )
139
170
 
140
171
  # Post-condition check
141
- assert param.name == node["name"], "Parameter name mismatch"
142
- assert param.schema is not None, "Parameter schema must be created"
172
+ if param.name != node["name"]:
173
+ raise RuntimeError("Parameter name mismatch")
174
+ if param.schema is None:
175
+ raise RuntimeError("Parameter schema must be created")
143
176
 
144
177
  return param
@@ -34,10 +34,14 @@ def parse_response(
34
34
  - All content media types are properly mapped to schemas
35
35
  - Stream flags are correctly set based on media types
36
36
  """
37
- assert isinstance(code, str), "code must be a string"
38
- assert isinstance(node, Mapping), "node must be a Mapping"
39
- assert isinstance(context, ParsingContext), "context must be a ParsingContext"
40
- assert operation_id_for_promo, "operation_id_for_promo must be provided"
37
+ if not isinstance(code, str):
38
+ raise TypeError("code must be a string")
39
+ if not isinstance(node, Mapping):
40
+ raise TypeError("node must be a Mapping")
41
+ if not isinstance(context, ParsingContext):
42
+ raise TypeError("context must be a ParsingContext")
43
+ if not operation_id_for_promo:
44
+ raise ValueError("operation_id_for_promo must be provided")
41
45
 
42
46
  content: Dict[str, IRSchema] = {}
43
47
  STREAM_FORMATS = {
@@ -97,8 +101,11 @@ def parse_response(
97
101
  )
98
102
 
99
103
  # Post-condition checks
100
- assert response.status_code == code, "Response status code mismatch"
101
- assert response.content == content, "Response content mismatch"
102
- assert response.stream == stream_flag, "Response stream flag mismatch"
104
+ if response.status_code != code:
105
+ raise RuntimeError("Response status code mismatch")
106
+ if response.content != content:
107
+ raise RuntimeError("Response content mismatch")
108
+ if response.stream != stream_flag:
109
+ raise RuntimeError("Response stream flag mismatch")
103
110
 
104
111
  return response
@@ -28,8 +28,10 @@ def build_schemas(raw_schemas: Dict[str, Mapping[str, Any]], raw_components: Map
28
28
  - A ParsingContext is returned with all schemas parsed
29
29
  - All schemas in raw_schemas are populated in context.parsed_schemas
30
30
  """
31
- assert isinstance(raw_schemas, dict), "raw_schemas must be a dict"
32
- assert isinstance(raw_components, Mapping), "raw_components must be a Mapping"
31
+ if not isinstance(raw_schemas, dict):
32
+ raise TypeError("raw_schemas must be a dict")
33
+ if not isinstance(raw_components, Mapping):
34
+ raise TypeError("raw_components must be a Mapping")
33
35
 
34
36
  context = ParsingContext(raw_spec_schemas=raw_schemas, raw_spec_components=raw_components)
35
37
 
@@ -39,7 +41,8 @@ def build_schemas(raw_schemas: Dict[str, Mapping[str, Any]], raw_components: Map
39
41
  _parse_schema(n, nd, context, allow_self_reference=True)
40
42
 
41
43
  # Post-condition check
42
- assert all(n in context.parsed_schemas for n in raw_schemas), "Not all schemas were parsed"
44
+ if not all(n in context.parsed_schemas for n in raw_schemas):
45
+ raise RuntimeError("Not all schemas were parsed")
43
46
 
44
47
  return context
45
48
 
@@ -55,8 +58,10 @@ def extract_inline_array_items(schemas: Dict[str, IRSchema]) -> Dict[str, IRSche
55
58
  - All array item schemas have proper names
56
59
  - No duplicate schema names are created
57
60
  """
58
- assert isinstance(schemas, dict), "schemas must be a dict"
59
- assert all(isinstance(s, IRSchema) for s in schemas.values()), "all values must be IRSchema objects"
61
+ if not isinstance(schemas, dict):
62
+ raise TypeError("schemas must be a dict")
63
+ if not all(isinstance(s, IRSchema) for s in schemas.values()):
64
+ raise TypeError("all values must be IRSchema objects")
60
65
 
61
66
  # Store original schema count for post-condition validation
62
67
  original_schema_count = len(schemas)
@@ -119,8 +124,10 @@ def extract_inline_array_items(schemas: Dict[str, IRSchema]) -> Dict[str, IRSche
119
124
  schemas.update(new_item_schemas)
120
125
 
121
126
  # Post-condition checks
122
- assert len(schemas) >= original_schema_count, "Schemas count should not decrease"
123
- assert original_schemas.issubset(set(schemas.keys())), "Original schemas should still be present"
127
+ if len(schemas) < original_schema_count:
128
+ raise RuntimeError("Schemas count should not decrease")
129
+ if not original_schemas.issubset(set(schemas.keys())):
130
+ raise RuntimeError("Original schemas should still be present")
124
131
 
125
132
  return schemas
126
133
 
@@ -140,8 +147,10 @@ def extract_inline_enums(schemas: Dict[str, IRSchema]) -> Dict[str, IRSchema]:
140
147
  - No duplicate schema names are created
141
148
  - Top-level enum schemas have generation_name set
142
149
  """
143
- assert isinstance(schemas, dict), "schemas must be a dict"
144
- assert all(isinstance(s, IRSchema) for s in schemas.values()), "all values must be IRSchema objects"
150
+ if not isinstance(schemas, dict):
151
+ raise TypeError("schemas must be a dict")
152
+ if not all(isinstance(s, IRSchema) for s in schemas.values()):
153
+ raise TypeError("all values must be IRSchema objects")
145
154
 
146
155
  # Store original schema count for post-condition validation
147
156
  original_schema_count = len(schemas)
@@ -160,6 +169,9 @@ def extract_inline_enums(schemas: Dict[str, IRSchema]) -> Dict[str, IRSchema]:
160
169
  # but we can set it here to avoid the warning)
161
170
  if not hasattr(schema, "generation_name") or not schema.generation_name:
162
171
  schema.generation_name = schema.name
172
+ logger.info(
173
+ f"Set generation_name for top-level enum schema: {schema_name} with values {schema.enum[:3]}..."
174
+ )
163
175
  # Mark this as a properly processed enum by ensuring generation_name is set
164
176
  # This serves as the marker that this enum was properly processed
165
177
  logger.debug(f"Marked top-level enum schema: {schema_name}")
@@ -195,7 +207,9 @@ def extract_inline_enums(schemas: Dict[str, IRSchema]) -> Dict[str, IRSchema]:
195
207
  schemas.update(new_enums)
196
208
 
197
209
  # Post-condition checks
198
- assert len(schemas) >= original_schema_count, "Schemas count should not decrease"
199
- assert original_schemas.issubset(set(schemas.keys())), "Original schemas should still be present"
210
+ if len(schemas) < original_schema_count:
211
+ raise RuntimeError("Schemas count should not decrease")
212
+ if not original_schemas.issubset(set(schemas.keys())):
213
+ raise RuntimeError("Original schemas should still be present")
200
214
 
201
215
  return schemas
@@ -169,7 +169,8 @@ class ParsingContext:
169
169
  Postconditions:
170
170
  - Returns True if the schema exists in parsed_schemas, False otherwise
171
171
  """
172
- assert isinstance(schema_name, str), "schema_name must be a string"
172
+ if not isinstance(schema_name, str):
173
+ raise TypeError("schema_name must be a string")
173
174
  return schema_name in self.parsed_schemas
174
175
 
175
176
  def get_parsed_schema(self, schema_name: str) -> Optional["IRSchema"]:
@@ -181,5 +182,6 @@ class ParsingContext:
181
182
  Postconditions:
182
183
  - Returns the IRSchema if it exists, None otherwise
183
184
  """
184
- assert isinstance(schema_name, str), "schema_name must be a string"
185
+ if not isinstance(schema_name, str):
186
+ raise TypeError("schema_name must be a string")
185
187
  return self.parsed_schemas.get(schema_name)
@@ -43,10 +43,14 @@ def _process_all_of(
43
43
  - parsed_all_of_components: List of IRSchema for each item in 'allOf' (empty if 'allOf' not present).
44
44
  """
45
45
  # Pre-conditions
46
- assert isinstance(node, Mapping) and node, "node must be a non-empty Mapping"
47
- assert isinstance(context, ParsingContext), "context must be a ParsingContext instance"
48
- assert callable(_parse_schema_func), "_parse_schema_func must be callable"
49
- assert isinstance(max_depth, int) and max_depth >= 0, "max_depth must be a non-negative integer"
46
+ if not (isinstance(node, Mapping) and node):
47
+ raise TypeError("node must be a non-empty Mapping")
48
+ if not isinstance(context, ParsingContext):
49
+ raise TypeError("context must be a ParsingContext instance")
50
+ if not callable(_parse_schema_func):
51
+ raise TypeError("_parse_schema_func must be callable")
52
+ if not (isinstance(max_depth, int) and max_depth >= 0):
53
+ raise ValueError("max_depth must be a non-negative integer")
50
54
 
51
55
  parsed_all_of_components: List[IRSchema] = []
52
56
  merged_required: Set[str] = set(node.get("required", []))
@@ -38,11 +38,16 @@ def _parse_any_of_schemas(
38
38
  - is_nullable: True if a null type was present.
39
39
  - effective_schema_type: Potential schema_type if list becomes empty/None (currently always None).
40
40
  """
41
- assert isinstance(any_of_nodes, list), "any_of_nodes must be a list"
42
- assert all(isinstance(n, Mapping) for n in any_of_nodes), "all items in any_of_nodes must be Mappings"
43
- assert isinstance(context, ParsingContext), "context must be a ParsingContext instance"
44
- assert max_depth >= 0, "max_depth must be non-negative"
45
- assert callable(parse_fn), "parse_fn must be a callable"
41
+ if not isinstance(any_of_nodes, list):
42
+ raise TypeError("any_of_nodes must be a list")
43
+ if not all(isinstance(n, Mapping) for n in any_of_nodes):
44
+ raise TypeError("all items in any_of_nodes must be Mappings")
45
+ if not isinstance(context, ParsingContext):
46
+ raise TypeError("context must be a ParsingContext instance")
47
+ if not max_depth >= 0:
48
+ raise ValueError("max_depth must be non-negative")
49
+ if not callable(parse_fn):
50
+ raise TypeError("parse_fn must be a callable")
46
51
 
47
52
  parsed_schemas_list: List[IRSchema] = [] # Renamed to avoid confusion with module name
48
53
  is_nullable_from_any_of = False
@@ -51,9 +51,12 @@ def _parse_array_items_schema(
51
51
  """
52
52
  # Pre-conditions
53
53
  # items_node_data is checked later, as it can be non-Mapping to return None
54
- assert isinstance(context, ParsingContext), "context must be a ParsingContext instance"
55
- assert callable(parse_fn), "parse_fn must be callable"
56
- assert isinstance(max_depth, int) and max_depth >= 0, "max_depth must be a non-negative integer"
54
+ if not isinstance(context, ParsingContext):
55
+ raise TypeError("context must be a ParsingContext instance")
56
+ if not callable(parse_fn):
57
+ raise TypeError("parse_fn must be callable")
58
+ if not (isinstance(max_depth, int) and max_depth >= 0):
59
+ raise ValueError("max_depth must be a non-negative integer")
57
60
 
58
61
  item_name_for_parse = f"{parent_schema_name}Item" if parent_schema_name else None
59
62
  if (
@@ -35,11 +35,16 @@ def _parse_one_of_schemas(
35
35
  - is_nullable: True if a null type was present.
36
36
  - effective_schema_type: Potential schema_type if list becomes empty/None (currently always None).
37
37
  """
38
- assert isinstance(one_of_nodes, list), "one_of_nodes must be a list"
39
- assert all(isinstance(n, Mapping) for n in one_of_nodes), "all items in one_of_nodes must be Mappings"
40
- assert isinstance(context, ParsingContext), "context must be a ParsingContext instance"
41
- assert max_depth >= 0, "max_depth must be non-negative"
42
- assert callable(parse_fn), "parse_fn must be a callable"
38
+ if not isinstance(one_of_nodes, list):
39
+ raise TypeError("one_of_nodes must be a list")
40
+ if not all(isinstance(n, Mapping) for n in one_of_nodes):
41
+ raise TypeError("all items in one_of_nodes must be Mappings")
42
+ if not isinstance(context, ParsingContext):
43
+ raise TypeError("context must be a ParsingContext instance")
44
+ if not max_depth >= 0:
45
+ raise ValueError("max_depth must be non-negative")
46
+ if not callable(parse_fn):
47
+ raise TypeError("parse_fn must be a callable")
43
48
 
44
49
  parsed_schemas_list: List[IRSchema] = []
45
50
  is_nullable_from_one_of = False
@@ -53,9 +53,12 @@ def _finalize_schema_object(
53
53
  - Returns a finalized IRSchema instance.
54
54
  - If schema has a name and isn't a placeholder, it's in context.parsed_schemas.
55
55
  """
56
- assert isinstance(node, Mapping), "node must be a Mapping"
57
- assert isinstance(context, ParsingContext), "context must be a ParsingContext instance"
58
- assert callable(parse_fn), "parse_fn must be callable"
56
+ if not isinstance(node, Mapping):
57
+ raise TypeError("node must be a Mapping")
58
+ if not isinstance(context, ParsingContext):
59
+ raise TypeError("context must be a ParsingContext instance")
60
+ if not callable(parse_fn):
61
+ raise TypeError("parse_fn must be callable")
59
62
  # Remove logger type check to support mock loggers in tests
60
63
 
61
64
  # If a placeholder for this schema name already exists due to a cycle detected deeper,
@@ -326,7 +326,8 @@ def _parse_schema(
326
326
  Parse a schema node and return an IRSchema object.
327
327
  """
328
328
  # Pre-conditions
329
- assert context is not None, "Context cannot be None for _parse_schema"
329
+ if context is None:
330
+ raise ValueError("Context cannot be None for _parse_schema")
330
331
 
331
332
  # Set allow_self_reference flag on unified context
332
333
  context.unified_cycle_context.allow_self_reference = allow_self_reference
@@ -377,9 +378,10 @@ def _parse_schema(
377
378
  if schema_node is None:
378
379
  return IRSchema(name=NameSanitizer.sanitize_class_name(schema_name) if schema_name else None)
379
380
 
380
- assert isinstance(
381
- schema_node, Mapping
382
- ), f"Schema node for '{schema_name or 'anonymous'}' must be a Mapping (e.g., dict), got {type(schema_node)}"
381
+ if not isinstance(schema_node, Mapping):
382
+ raise TypeError(
383
+ f"Schema node for '{schema_name or 'anonymous'}' must be a Mapping (e.g., dict), got {type(schema_node)}"
384
+ )
383
385
 
384
386
  # If the current schema_node itself is a $ref, resolve it.
385
387
  if "$ref" in schema_node:
@@ -197,7 +197,8 @@ class EndpointsEmitter:
197
197
  self._deduplicate_operation_ids(ops_for_tag)
198
198
 
199
199
  # EndpointVisitor must exist here due to check above
200
- assert self.visitor is not None, "EndpointVisitor not initialized"
200
+ if self.visitor is None:
201
+ raise RuntimeError("EndpointVisitor not initialized")
201
202
  methods = [self.visitor.visit(op, self.context) for op in ops_for_tag]
202
203
  class_content = self.visitor.emit_endpoint_client_class(canonical_tag_name, methods, self.context)
203
204
 
@@ -42,12 +42,10 @@ class ModelsEmitter:
42
42
  # )
43
43
 
44
44
  # Assert that de-collided names have been set by the emit() method's preprocessing.
45
- assert (
46
- schema_ir.generation_name is not None
47
- ), f"Schema '{schema_ir.name}' must have generation_name set before file generation."
48
- assert (
49
- schema_ir.final_module_stem is not None
50
- ), f"Schema '{schema_ir.name}' must have final_module_stem set before file generation."
45
+ if schema_ir.generation_name is None:
46
+ raise RuntimeError(f"Schema '{schema_ir.name}' must have generation_name set before file generation.")
47
+ if schema_ir.final_module_stem is None:
48
+ raise RuntimeError(f"Schema '{schema_ir.name}' must have final_module_stem set before file generation.")
51
49
 
52
50
  file_path = models_dir / f"{schema_ir.final_module_stem}.py"
53
51
 
@@ -138,12 +136,10 @@ class ModelsEmitter:
138
136
 
139
137
  for s_schema in sorted_schemas_for_init:
140
138
  # These should have been set in the emit() preprocessing step.
141
- assert (
142
- s_schema.generation_name is not None
143
- ), f"Schema '{s_schema.name}' missing generation_name in __init__ generation."
144
- assert (
145
- s_schema.final_module_stem is not None
146
- ), f"Schema '{s_schema.name}' missing final_module_stem in __init__ generation."
139
+ if s_schema.generation_name is None:
140
+ raise RuntimeError(f"Schema '{s_schema.name}' missing generation_name in __init__ generation.")
141
+ if s_schema.final_module_stem is None:
142
+ raise RuntimeError(f"Schema '{s_schema.name}' missing final_module_stem in __init__ generation.")
147
143
 
148
144
  if s_schema._from_unresolved_ref: # Check this flag if it's relevant
149
145
  # logger.debug(
@@ -184,8 +180,10 @@ class ModelsEmitter:
184
180
  - All models are properly formatted and type-annotated
185
181
  - Returns a list of file paths generated
186
182
  """
187
- assert isinstance(spec, IRSpec), "spec must be an IRSpec"
188
- assert output_root, "output_root must be a non-empty string"
183
+ if not isinstance(spec, IRSpec):
184
+ raise TypeError("spec must be an IRSpec")
185
+ if not output_root:
186
+ raise ValueError("output_root must be a non-empty string")
189
187
 
190
188
  output_dir = Path(output_root.rstrip("/"))
191
189
  models_dir = output_dir / "models"
@@ -75,15 +75,14 @@ class NamedTypeResolver:
75
75
  if schema.name and schema.name in self.all_schemas:
76
76
  # This schema is a REFERENCE to a globally defined schema (e.g., in components/schemas)
77
77
  ref_schema = self.all_schemas[schema.name] # Get the actual definition
78
- assert ref_schema.name is not None, f"Schema '{schema.name}' resolved to ref_schema with None name."
78
+ if ref_schema.name is None:
79
+ raise RuntimeError(f"Schema '{schema.name}' resolved to ref_schema with None name.")
79
80
 
80
81
  # NEW: Use generation_name and final_module_stem from the referenced schema
81
- assert (
82
- ref_schema.generation_name is not None
83
- ), f"Referenced schema '{ref_schema.name}' must have generation_name set."
84
- assert (
85
- ref_schema.final_module_stem is not None
86
- ), f"Referenced schema '{ref_schema.name}' must have final_module_stem set."
82
+ if ref_schema.generation_name is None:
83
+ raise RuntimeError(f"Referenced schema '{ref_schema.name}' must have generation_name set.")
84
+ if ref_schema.final_module_stem is None:
85
+ raise RuntimeError(f"Referenced schema '{ref_schema.name}' must have final_module_stem set.")
87
86
 
88
87
  class_name_for_ref = ref_schema.generation_name
89
88
  module_name_for_ref = ref_schema.final_module_stem
@@ -113,12 +113,14 @@ class ObjectTypeResolver:
113
113
  # If this named object is a component schema, ensure it's imported.
114
114
  if schema.name and schema.name in self.all_schemas:
115
115
  actual_schema_def = self.all_schemas[schema.name]
116
- assert (
117
- actual_schema_def.generation_name is not None
118
- ), f"Actual schema '{actual_schema_def.name}' for '{schema.name}' must have generation_name."
119
- assert (
120
- actual_schema_def.final_module_stem is not None
121
- ), f"Actual schema '{actual_schema_def.name}' for '{schema.name}' must have final_module_stem."
116
+ if actual_schema_def.generation_name is None:
117
+ raise RuntimeError(
118
+ f"Actual schema '{actual_schema_def.name}' for '{schema.name}' must have generation_name."
119
+ )
120
+ if actual_schema_def.final_module_stem is None:
121
+ raise RuntimeError(
122
+ f"Actual schema '{actual_schema_def.name}' for '{schema.name}' must have final_module_stem."
123
+ )
122
124
 
123
125
  class_name_to_use = actual_schema_def.generation_name
124
126
  module_stem_to_use = actual_schema_def.final_module_stem
@@ -162,14 +164,16 @@ class ObjectTypeResolver:
162
164
  schema.name and schema.name in self.all_schemas
163
165
  ): # Named object, no properties, AND it's a known component
164
166
  actual_schema_def = self.all_schemas[schema.name]
165
- assert actual_schema_def.generation_name is not None, (
166
- f"Actual schema (no props) '{actual_schema_def.name}' "
167
- f"for '{schema.name}' must have generation_name."
168
- )
169
- assert actual_schema_def.final_module_stem is not None, (
170
- f"Actual schema (no props) '{actual_schema_def.name}' "
171
- f"for '{schema.name}' must have final_module_stem."
172
- )
167
+ if actual_schema_def.generation_name is None:
168
+ raise RuntimeError(
169
+ f"Actual schema (no props) '{actual_schema_def.name}' "
170
+ f"for '{schema.name}' must have generation_name."
171
+ )
172
+ if actual_schema_def.final_module_stem is None:
173
+ raise RuntimeError(
174
+ f"Actual schema (no props) '{actual_schema_def.name}' "
175
+ f"for '{schema.name}' must have final_module_stem."
176
+ )
173
177
 
174
178
  class_name_to_use = actual_schema_def.generation_name
175
179
  module_stem_to_use = actual_schema_def.final_module_stem
@@ -181,8 +181,15 @@ class OpenAPISchemaResolver(SchemaTypeResolver):
181
181
  # Return the enum type name
182
182
  return ResolvedType(python_type=schema.generation_name, is_optional=not required)
183
183
  else:
184
- # This is an unprocessed inline enum - log warning but continue
185
- logger.warning(f"Found inline enum in string schema that wasn't promoted: {schema.name or 'unnamed'}")
184
+ # This is an unprocessed inline enum - log warning with details
185
+ enum_values = schema.enum[:5] if len(schema.enum) > 5 else schema.enum
186
+ more = f" (and {len(schema.enum) - 5} more)" if len(schema.enum) > 5 else ""
187
+ context_info = f"name='{schema.name}'" if schema.name else "unnamed"
188
+ logger.warning(
189
+ f"Found inline enum in string schema that wasn't promoted: "
190
+ f"{context_info}, type={schema.type}, enum_values={enum_values}{more}. "
191
+ f"This will be treated as plain 'str' instead of a proper Enum type."
192
+ )
186
193
  return ResolvedType(python_type="str", is_optional=not required)
187
194
 
188
195
  # Handle string formats
@@ -388,7 +388,7 @@ class EndpointResponseHandlerGenerator:
388
388
  # All code paths should be covered by the match statement above
389
389
  writer.write_line("# All paths above should return or raise - this should never execute")
390
390
  context.add_import("typing", "NoReturn")
391
- writer.write_line("assert False, 'Unexpected code path' # pragma: no cover")
391
+ writer.write_line("raise RuntimeError('Unexpected code path') # pragma: no cover")
392
392
  writer.write_line("") # Add a blank line for readability
393
393
 
394
394
  def _write_strategy_based_return(
@@ -24,7 +24,8 @@ class AliasGenerator:
24
24
  all_schemas: Optional[Dict[str, IRSchema]],
25
25
  ):
26
26
  # Pre-condition
27
- assert renderer is not None, "PythonConstructRenderer cannot be None"
27
+ if renderer is None:
28
+ raise ValueError("PythonConstructRenderer cannot be None")
28
29
  self.renderer = renderer
29
30
  self.all_schemas = all_schemas if all_schemas is not None else {}
30
31
  self.type_service = UnifiedTypeService(self.all_schemas)
@@ -58,10 +59,14 @@ class AliasGenerator:
58
59
  - ``TypeAlias`` is imported in the context if not already present.
59
60
  """
60
61
  # Pre-conditions
61
- assert schema is not None, "Schema cannot be None for alias generation."
62
- assert schema.name is not None, "Schema name must be present for alias generation."
63
- assert base_name, "Base name cannot be empty for alias generation."
64
- assert context is not None, "RenderContext cannot be None."
62
+ if schema is None:
63
+ raise ValueError("Schema cannot be None for alias generation.")
64
+ if schema.name is None:
65
+ raise ValueError("Schema name must be present for alias generation.")
66
+ if not base_name:
67
+ raise ValueError("Base name cannot be empty for alias generation.")
68
+ if context is None:
69
+ raise ValueError("RenderContext cannot be None.")
65
70
 
66
71
  alias_name = NameSanitizer.sanitize_class_name(base_name)
67
72
  target_type = self.type_service.resolve_schema_type(schema, context, required=True, resolve_underlying=True)
@@ -77,13 +82,15 @@ class AliasGenerator:
77
82
  )
78
83
 
79
84
  # Post-condition
80
- assert rendered_code.strip(), "Generated alias code cannot be empty."
85
+ if not rendered_code.strip():
86
+ raise RuntimeError("Generated alias code cannot be empty.")
81
87
  # PythonConstructRenderer is responsible for adding TypeAlias import
82
88
  # We can check if it was added to context if 'TypeAlias' is in the rendered code
83
89
  if "TypeAlias" in rendered_code:
84
- assert (
90
+ if not (
85
91
  "typing" in context.import_collector.imports
86
92
  and "TypeAlias" in context.import_collector.imports["typing"]
87
- ), "TypeAlias import was not added to context by renderer."
93
+ ):
94
+ raise RuntimeError("TypeAlias import was not added to context by renderer.")
88
95
 
89
96
  return rendered_code
@@ -31,7 +31,8 @@ class DataclassGenerator:
31
31
  Pre-conditions:
32
32
  - ``renderer`` is not None.
33
33
  """
34
- assert renderer is not None, "PythonConstructRenderer cannot be None."
34
+ if renderer is None:
35
+ raise ValueError("PythonConstructRenderer cannot be None.")
35
36
  self.renderer = renderer
36
37
  self.all_schemas = all_schemas if all_schemas is not None else {}
37
38
  self.type_service = UnifiedTypeService(self.all_schemas)
@@ -56,8 +57,10 @@ class DataclassGenerator:
56
57
  - Returns a valid Python default value string
57
58
  (e.g., "None", "field(default_factory=list)", "\"abc\"") or None.
58
59
  """
59
- assert ps is not None, "Property schema (ps) cannot be None."
60
- assert context is not None, "RenderContext cannot be None."
60
+ if ps is None:
61
+ raise ValueError("Property schema (ps) cannot be None.")
62
+ if context is None:
63
+ raise ValueError("RenderContext cannot be None.")
61
64
 
62
65
  if ps.type == "array":
63
66
  context.add_import("dataclasses", "field")
@@ -124,10 +127,14 @@ class DataclassGenerator:
124
127
  - Returns a non-empty string containing valid Python code for a dataclass.
125
128
  - ``@dataclass`` decorator is present, implying ``dataclasses.dataclass`` is imported.
126
129
  """
127
- assert schema is not None, "Schema cannot be None for dataclass generation."
128
- assert schema.name is not None, "Schema name must be present for dataclass generation."
129
- assert base_name, "Base name cannot be empty for dataclass generation."
130
- assert context is not None, "RenderContext cannot be None."
130
+ if schema is None:
131
+ raise ValueError("Schema cannot be None for dataclass generation.")
132
+ if schema.name is None:
133
+ raise ValueError("Schema name must be present for dataclass generation.")
134
+ if not base_name:
135
+ raise ValueError("Base name cannot be empty for dataclass generation.")
136
+ if context is None:
137
+ raise ValueError("RenderContext cannot be None.")
131
138
  # Additional check for schema type might be too strict here, as ModelVisitor decides eligibility.
132
139
 
133
140
  class_name = base_name
@@ -136,7 +143,8 @@ class DataclassGenerator:
136
143
 
137
144
  if schema.type == "array" and schema.items:
138
145
  field_name_for_array_content = "items"
139
- assert schema.items is not None, "Schema items must be present for array type dataclass field."
146
+ if schema.items is None:
147
+ raise ValueError("Schema items must be present for array type dataclass field.")
140
148
 
141
149
  list_item_py_type = self.type_service.resolve_schema_type(schema.items, context, required=True)
142
150
  list_item_py_type = TypeFinalizer(context)._clean_type(list_item_py_type)
@@ -213,16 +221,18 @@ class DataclassGenerator:
213
221
  field_mappings=field_mappings if field_mappings else None,
214
222
  )
215
223
 
216
- assert rendered_code.strip(), "Generated dataclass code cannot be empty."
224
+ if not rendered_code.strip():
225
+ raise RuntimeError("Generated dataclass code cannot be empty.")
217
226
  # PythonConstructRenderer adds the @dataclass decorator and import
218
- assert "@dataclass" in rendered_code, "Dataclass code missing @dataclass decorator."
219
- assert (
227
+ if "@dataclass" not in rendered_code:
228
+ raise RuntimeError("Dataclass code missing @dataclass decorator.")
229
+ if not (
220
230
  "dataclasses" in context.import_collector.imports
221
231
  and "dataclass" in context.import_collector.imports["dataclasses"]
222
- ), "dataclass import was not added to context by renderer."
232
+ ):
233
+ raise RuntimeError("dataclass import was not added to context by renderer.")
223
234
  if "default_factory" in rendered_code: # Check for field import if factory is used
224
- assert "field" in context.import_collector.imports.get(
225
- "dataclasses", set()
226
- ), "'field' import from dataclasses missing when default_factory is used."
235
+ if "field" not in context.import_collector.imports.get("dataclasses", set()):
236
+ raise RuntimeError("'field' import from dataclasses missing when default_factory is used.")
227
237
 
228
238
  return rendered_code
@@ -19,7 +19,8 @@ class EnumGenerator:
19
19
 
20
20
  def __init__(self, renderer: PythonConstructRenderer):
21
21
  # Pre-condition
22
- assert renderer is not None, "PythonConstructRenderer cannot be None"
22
+ if renderer is None:
23
+ raise ValueError("PythonConstructRenderer cannot be None")
23
24
  self.renderer = renderer
24
25
 
25
26
  def _generate_member_name_for_string_enum(self, value: str) -> str:
@@ -32,7 +33,8 @@ class EnumGenerator:
32
33
  Post-conditions:
33
34
  - Returns a non-empty string that is a valid Python identifier, typically uppercase.
34
35
  """
35
- assert isinstance(value, str), "Input value must be a string."
36
+ if not isinstance(value, str):
37
+ raise TypeError("Input value must be a string.")
36
38
  base_member_name = str(value).upper().replace("-", "_").replace(" ", "_")
37
39
  sanitized_member_name = re.sub(r"[^A-Z0-9_]", "", base_member_name)
38
40
 
@@ -58,10 +60,11 @@ class EnumGenerator:
58
60
  if not re.match(r"^[A-Z_]", sanitized_member_name.upper()):
59
61
  sanitized_member_name = f"MEMBER_{sanitized_member_name}"
60
62
 
61
- assert sanitized_member_name and re.match(r"^[A-Z_][A-Z0-9_]*$", sanitized_member_name.upper()), (
62
- f"Generated string enum member name '{sanitized_member_name}' "
63
- f"is not a valid Python identifier from value '{value}'."
64
- )
63
+ if not (sanitized_member_name and re.match(r"^[A-Z_][A-Z0-9_]*$", sanitized_member_name.upper())):
64
+ raise ValueError(
65
+ f"Generated string enum member name '{sanitized_member_name}' "
66
+ f"is not a valid Python identifier from value '{value}'."
67
+ )
65
68
  return sanitized_member_name
66
69
 
67
70
  def _generate_member_name_for_integer_enum(self, value: str | int, int_value_for_fallback: int) -> str:
@@ -75,8 +78,10 @@ class EnumGenerator:
75
78
  Post-conditions:
76
79
  - Returns a non-empty string that is a valid Python identifier, typically uppercase.
77
80
  """
78
- assert isinstance(value, (str, int)), "Input value for integer enum naming must be str or int."
79
- assert isinstance(int_value_for_fallback, int), "Fallback integer value must be an int."
81
+ if not isinstance(value, (str, int)):
82
+ raise TypeError("Input value for integer enum naming must be str or int.")
83
+ if not isinstance(int_value_for_fallback, int):
84
+ raise TypeError("Fallback integer value must be an int.")
80
85
 
81
86
  name_basis = str(value) # Use string representation as basis for name
82
87
  base_member_name = name_basis.upper().replace("-", "_").replace(" ", "_").replace(".", "_DOT_")
@@ -105,10 +110,11 @@ class EnumGenerator:
105
110
  if not sanitized_member_name: # Should be impossible
106
111
  sanitized_member_name = f"ENUM_MEMBER_UNKNOWN_{abs(int_value_for_fallback)}"
107
112
 
108
- assert sanitized_member_name and re.match(r"^[A-Z_][A-Z0-9_]*$", sanitized_member_name.upper()), (
109
- f"Generated integer enum member name '{sanitized_member_name}' "
110
- f"is not a valid Python identifier from value '{value}'."
111
- )
113
+ if not (sanitized_member_name and re.match(r"^[A-Z_][A-Z0-9_]*$", sanitized_member_name.upper())):
114
+ raise ValueError(
115
+ f"Generated integer enum member name '{sanitized_member_name}' "
116
+ f"is not a valid Python identifier from value '{value}'."
117
+ )
112
118
  return sanitized_member_name
113
119
 
114
120
  def generate(
@@ -138,12 +144,18 @@ class EnumGenerator:
138
144
  - Returns a non-empty string containing valid Python code for an enum.
139
145
  - ``Enum`` from the ``enum`` module is imported in the context.
140
146
  """
141
- assert schema is not None, "Schema cannot be None for enum generation."
142
- assert schema.name is not None, "Schema name must be present for enum generation."
143
- assert base_name, "Base name cannot be empty for enum generation."
144
- assert context is not None, "RenderContext cannot be None."
145
- assert schema.enum, "Schema must have enum values for enum generation."
146
- assert schema.type in ("string", "integer"), "Enum schema type must be 'string' or 'integer'."
147
+ if schema is None:
148
+ raise ValueError("Schema cannot be None for enum generation.")
149
+ if schema.name is None:
150
+ raise ValueError("Schema name must be present for enum generation.")
151
+ if not base_name:
152
+ raise ValueError("Base name cannot be empty for enum generation.")
153
+ if context is None:
154
+ raise ValueError("RenderContext cannot be None.")
155
+ if not schema.enum:
156
+ raise ValueError("Schema must have enum values for enum generation.")
157
+ if schema.type not in ("string", "integer"):
158
+ raise ValueError("Enum schema type must be 'string' or 'integer'.")
147
159
 
148
160
  enum_class_name = base_name # PythonConstructRenderer will sanitize this class name
149
161
  base_type = "str" if schema.type == "string" else "int"
@@ -192,9 +204,9 @@ class EnumGenerator:
192
204
  context=context,
193
205
  )
194
206
 
195
- assert rendered_code.strip(), "Generated enum code cannot be empty."
196
- assert (
197
- "enum" in context.import_collector.imports and "Enum" in context.import_collector.imports["enum"]
198
- ), "Enum import was not added to context by renderer."
207
+ if not rendered_code.strip():
208
+ raise RuntimeError("Generated enum code cannot be empty.")
209
+ if not ("enum" in context.import_collector.imports and "Enum" in context.import_collector.imports["enum"]):
210
+ raise RuntimeError("Enum import was not added to context by renderer.")
199
211
 
200
212
  return rendered_code
@@ -114,7 +114,7 @@ class ModelVisitor(Visitor[IRSchema, str]):
114
114
  logger.error(
115
115
  f"ModelVisitor: Schema has no usable name (name or generation_name) for model generation: {schema}"
116
116
  )
117
- assert False, "Schema must have a name or generation_name for model code generation at this point."
117
+ raise RuntimeError("Schema must have a name or generation_name for model code generation at this point.")
118
118
  # return "" # Should not reach here if assertions are active
119
119
 
120
120
  # --- Import Registration ---
@@ -144,13 +144,15 @@ class ModelVisitor(Visitor[IRSchema, str]):
144
144
  # "alias, enum, or dataclass. No standalone model generated by ModelVisitor."
145
145
  # )
146
146
  # Post-condition: returns empty string if no specific generator called
147
- assert not rendered_code, "Rendered code should be empty if no generator was matched."
147
+ if rendered_code:
148
+ raise RuntimeError("Rendered code should be empty if no generator was matched.")
148
149
  return ""
149
150
 
150
151
  # Post-condition: ensure some code was generated if a generator was called
151
- assert rendered_code.strip() or not (
152
- is_type_alias or is_enum or is_dataclass
153
- ), f"Code generation resulted in an empty string for schema '{schema.name}' which was matched as a model type."
152
+ if not rendered_code.strip() and (is_type_alias or is_enum or is_dataclass):
153
+ raise RuntimeError(
154
+ f"Code generation resulted in an empty string for schema '{schema.name}' which was matched as a model type."
155
+ )
154
156
 
155
157
  return self.formatter.format(rendered_code)
156
158
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyopenapi-gen
3
- Version: 0.11.0
3
+ Version: 0.12.0
4
4
  Summary: Modern, async-first Python client generator for OpenAPI specifications with advanced cycle detection and unified type resolution
5
5
  Project-URL: Homepage, https://github.com/your-org/pyopenapi-gen
6
6
  Project-URL: Documentation, https://github.com/your-org/pyopenapi-gen/blob/main/README.md
@@ -32,13 +32,13 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
32
32
  Classifier: Topic :: System :: Networking
33
33
  Classifier: Typing :: Typed
34
34
  Requires-Python: <4.0.0,>=3.12
35
- Requires-Dist: click<9.0.0,>=8.0.0
35
+ Requires-Dist: click>=8.0.0
36
36
  Requires-Dist: dataclass-wizard>=0.22.0
37
37
  Requires-Dist: httpx>=0.24.0
38
38
  Requires-Dist: openapi-core>=0.19
39
39
  Requires-Dist: openapi-spec-validator>=0.7
40
40
  Requires-Dist: pyyaml>=6.0
41
- Requires-Dist: typer<0.14.0,>=0.12.0
41
+ Requires-Dist: typer>=0.14.0
42
42
  Provides-Extra: dev
43
43
  Requires-Dist: bandit[toml]>=1.7.0; extra == 'dev'
44
44
  Requires-Dist: black>=23.0; extra == 'dev'
@@ -22,22 +22,22 @@ pyopenapi_gen/core/warning_collector.py,sha256=DYl9D7eZYs04mDU84KeonS-5-d0aM7hNq
22
22
  pyopenapi_gen/core/auth/base.py,sha256=E2KUerA_mYv9D7xulUm-lenIxqZHqanjA4oRKpof2ZE,792
23
23
  pyopenapi_gen/core/auth/plugins.py,sha256=bDWx4MTRFsCKp1i__BsQtZEvQPGU-NKI137-zoxmrgs,3465
24
24
  pyopenapi_gen/core/loader/__init__.py,sha256=bt-MQ35fbq-f1YnCcopPg53TuXCI9_7wcMzQZoWVpjU,391
25
- pyopenapi_gen/core/loader/loader.py,sha256=aehmWhOwWzv2af4Q0XxuOwP9AoAozG36o4-yMVMO0hE,6318
25
+ pyopenapi_gen/core/loader/loader.py,sha256=fjRw6ZrG6hRS2RBWJY5IOv9e1ULc6tnxVGagqXhMmpk,6374
26
26
  pyopenapi_gen/core/loader/operations/__init__.py,sha256=7se21D-BOy7Qw6C9auJ9v6D3NCuRiDpRlhqxGq11fJs,366
27
- pyopenapi_gen/core/loader/operations/parser.py,sha256=ai5iZZA2nicouC77iEvo8jKGXbHKbX_NcTy44lkwOVQ,6896
28
- pyopenapi_gen/core/loader/operations/post_processor.py,sha256=3FZ5o59J2bSpZP-tNIec0A2hw095cC27GKqkhGrgHZA,2437
29
- pyopenapi_gen/core/loader/operations/request_body.py,sha256=qz-wh014ejb1SGTuVRNODSXc95_iOLAjw05aDRhbXoo,3099
27
+ pyopenapi_gen/core/loader/operations/parser.py,sha256=QHg3o8TRaReYofEEcBwuDuNxGDxZjkWXRDqOxKFiRtk,7046
28
+ pyopenapi_gen/core/loader/operations/post_processor.py,sha256=Rzb3GSiLyJk-0hTBZ6s6iWAj4KqE4Rfo3w-q2wm_R7w,2487
29
+ pyopenapi_gen/core/loader/operations/request_body.py,sha256=r-jscZEfOmqFA-E4i1Uj3S66rNEf1gDTlBiGUiA0P9k,3224
30
30
  pyopenapi_gen/core/loader/parameters/__init__.py,sha256=p13oSibCRC5RCfsP6w7yD9MYs5TXcdI4WwPv7oGUYKk,284
31
- pyopenapi_gen/core/loader/parameters/parser.py,sha256=ohyi0Ay7vterM8ho_kscWzzNXuwKISDGjgpArByeFSw,6089
31
+ pyopenapi_gen/core/loader/parameters/parser.py,sha256=rOZWbykHQy7MH1gTHI61460mFG1nPKdU9A4hOsYAiIc,7505
32
32
  pyopenapi_gen/core/loader/responses/__init__.py,sha256=6APWoH3IdNkgVmI0KsgZoZ6knDaG-S-pnUCa6gkzT8E,216
33
- pyopenapi_gen/core/loader/responses/parser.py,sha256=T0QXH_3c-Y6_S6DvveKHPfV_tID7qhBoX0nFtdLCa0A,3896
33
+ pyopenapi_gen/core/loader/responses/parser.py,sha256=F9otAn6ncQiY3C25Fq4mEJ5UFNgN83eujcX20Vd_nPU,4069
34
34
  pyopenapi_gen/core/loader/schemas/__init__.py,sha256=rlhujYfw_IzWgzhVhYMJ3eIhE6C5Vi1Ylba-BHEVqOg,296
35
- pyopenapi_gen/core/loader/schemas/extractor.py,sha256=TlLflugYrkQg-Fe7p-C4ppT8rRC9OKvK4nubEUR58tY,9445
35
+ pyopenapi_gen/core/loader/schemas/extractor.py,sha256=n2jF_g8ZjA4GQiSKEWGAt35Hw7Ek93cnxFaS4Ld21Sc,9889
36
36
  pyopenapi_gen/core/parsing/__init__.py,sha256=RJsIR6cHaNoI4tBcpMlAa0JsY64vsHb9sPxPg6rd8FQ,486
37
- pyopenapi_gen/core/parsing/context.py,sha256=crn5oTkzEvnSzYdPuHBA_s72kmq0RKzXpyaqNh67k68,7947
37
+ pyopenapi_gen/core/parsing/context.py,sha256=8cM8mPItvDvJr8ZiukvdHBumlQl9hK1gUZL4BDpHaBk,8005
38
38
  pyopenapi_gen/core/parsing/cycle_helpers.py,sha256=nG5ysNavL_6lpnHWFUZR9qraBxqOzuNfI6NgSEa8a5M,5939
39
- pyopenapi_gen/core/parsing/schema_finalizer.py,sha256=fsyuOenLJA3TndzYVETqKkSlo2Qz3TsD1YDtlbyOATQ,6839
40
- pyopenapi_gen/core/parsing/schema_parser.py,sha256=qFdan2djgdRBtzVCLiDBooVqXgcuWy_JbzDGLTJpPeE,30502
39
+ pyopenapi_gen/core/parsing/schema_finalizer.py,sha256=qRTHUoVBQTgGmdfLuBuWxtWdj_SG71STGC3rn-tJvnA,6914
40
+ pyopenapi_gen/core/parsing/schema_parser.py,sha256=W0kCV0ucq6Wybr7x1wZl-nMSRXVWAqI4T57ASSabZsM,30557
41
41
  pyopenapi_gen/core/parsing/unified_cycle_detection.py,sha256=3nplaCVh2dFwBPbmDc2kiU0SzTPXXktdQ5Rc0Q9Uu9s,10873
42
42
  pyopenapi_gen/core/parsing/common/__init__.py,sha256=U3sHMO-l6S3Cm04CVOYmBCpqLEZvCylUI7yQfcTwxYU,27
43
43
  pyopenapi_gen/core/parsing/common/type_parser.py,sha256=cK7xtxhoD43K2WjLP9TGip3As3akYeYW7L2XztXCecg,2562
@@ -52,10 +52,10 @@ pyopenapi_gen/core/parsing/common/ref_resolution/helpers/missing_ref.py,sha256=B
52
52
  pyopenapi_gen/core/parsing/common/ref_resolution/helpers/new_schema.py,sha256=MTaxiyqoPEaNFqF7tQHii3IH41M05wPKt6lBQi1SCDU,1625
53
53
  pyopenapi_gen/core/parsing/common/ref_resolution/helpers/stripped_suffix.py,sha256=ukKU64ozHINPiVlHE9YBDz1Nq2i6Xh64jhoWSEqbK5c,1774
54
54
  pyopenapi_gen/core/parsing/keywords/__init__.py,sha256=enTLacWXGXLIOjSJ3j7KNUDzU27Kq3Ww79sFElz02cM,27
55
- pyopenapi_gen/core/parsing/keywords/all_of_parser.py,sha256=s0aav49R4LYAwfEimWa0ZuFwbNWkYpRAJmcmSVDsO-s,3594
56
- pyopenapi_gen/core/parsing/keywords/any_of_parser.py,sha256=r9_0opPM75p0rPgdcRTBmae7Td3jPkJouuL_ksuFWtM,2856
57
- pyopenapi_gen/core/parsing/keywords/array_items_parser.py,sha256=dIb3_VsEkqsR9W4rwXoTT9IW313TnH66sQzJL4K7EQQ,2645
58
- pyopenapi_gen/core/parsing/keywords/one_of_parser.py,sha256=82SUPd0hk0QF4-hMr0QJmRSFa9nnJL8ncYmvgkIKKXs,2601
55
+ pyopenapi_gen/core/parsing/keywords/all_of_parser.py,sha256=ZH8rkxdDjldd226UGw5tv853ONXKaoqvWj5FfbgSoRY,3699
56
+ pyopenapi_gen/core/parsing/keywords/any_of_parser.py,sha256=HQ4iBBPgox48KIPPhM6VVZTXHIUVqpMoHkCbqcebXOw,2982
57
+ pyopenapi_gen/core/parsing/keywords/array_items_parser.py,sha256=nk9AFbx5ANLdDeGsxSTeYHhd8MqqrQwDRMzJ8FJmJxY,2723
58
+ pyopenapi_gen/core/parsing/keywords/one_of_parser.py,sha256=TUiT1dH1r8GEPExzlR3zdgnYpGxilH8yvnSWOvQmKmY,2727
59
59
  pyopenapi_gen/core/parsing/keywords/properties_parser.py,sha256=bm248ApsNskFPQF4fXq7mT5oJf6FF9yAcdVLmK6el3E,4426
60
60
  pyopenapi_gen/core/parsing/transformers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
61
61
  pyopenapi_gen/core/parsing/transformers/inline_enum_extractor.py,sha256=hXuht-t0Syi5vPO8qn9GcjEpyDcZnfFVHVIlwfMa8L0,13461
@@ -70,9 +70,9 @@ pyopenapi_gen/emitters/CLAUDE.md,sha256=iZYEZq1a1h033rxuh97cMpsKUElv72ysvTm3-QQU
70
70
  pyopenapi_gen/emitters/client_emitter.py,sha256=kmMVnG-wAOJm7TUm0xOQ5YnSJfYxz1SwtpiyoUCbcCA,1939
71
71
  pyopenapi_gen/emitters/core_emitter.py,sha256=RcBsAYQ3ZKcWwtkzQmyHkL7VtDQjbIObFLXD9M_GdpI,8020
72
72
  pyopenapi_gen/emitters/docs_emitter.py,sha256=aouKqhRdtVvYfGVsye_uqM80nONRy0SqN06cr1l3OgA,1137
73
- pyopenapi_gen/emitters/endpoints_emitter.py,sha256=2VuJJF0hpzyN-TqY9XVLQtTJ-QgedZe5Vj8ITBGsJYE,9558
73
+ pyopenapi_gen/emitters/endpoints_emitter.py,sha256=tzSLUzlZle2Lih_aZc4cJ-Y1ItjN5H_rABEWcDwECXA,9586
74
74
  pyopenapi_gen/emitters/exceptions_emitter.py,sha256=qPTIPXDyqSUtpmBIp-V4ap1uMHUPmYziCSN62t7qcAE,1918
75
- pyopenapi_gen/emitters/models_emitter.py,sha256=I3IKwtKVocD3UVrI7cINXI8NjLwUZqHuGgvS3hjWUJ8,22192
75
+ pyopenapi_gen/emitters/models_emitter.py,sha256=Gd0z2Xoze1XkVnajkOptW90ti7197wQ15I7vIITnULM,22243
76
76
  pyopenapi_gen/generator/CLAUDE.md,sha256=BS9KkmLvk2WD-Io-_apoWjGNeMU4q4LKy4UOxYF9WxM,10870
77
77
  pyopenapi_gen/generator/client_generator.py,sha256=MULKJY9SdRuYjt_R4XCXh3vJSW-92rsxOu-MVpIklho,29333
78
78
  pyopenapi_gen/helpers/CLAUDE.md,sha256=GyIJ0grp4SkD3plAUzyycW4nTUZf9ewtvvsdAGkmIZw,10609
@@ -85,8 +85,8 @@ pyopenapi_gen/helpers/type_resolution/__init__.py,sha256=TbaQZp7jvBiYgmuzuG8Wp56
85
85
  pyopenapi_gen/helpers/type_resolution/array_resolver.py,sha256=dFppBtA6CxmiWAMR6rwGnQPv4AibL3nxtzw1LbeXVn4,2023
86
86
  pyopenapi_gen/helpers/type_resolution/composition_resolver.py,sha256=wq6CRGxGgOKK470ln5Tpk9SzHtMuwB22TXHsRLtUFyw,3015
87
87
  pyopenapi_gen/helpers/type_resolution/finalizer.py,sha256=_BcOBmOvadhBTUAvIc0Ak8FNxFw1uYL4rkKWtU68_m4,4332
88
- pyopenapi_gen/helpers/type_resolution/named_resolver.py,sha256=akHVthcD7cp9lHI-TCeABMacwQ2Z1gGp8zMGNsI_b5A,9403
89
- pyopenapi_gen/helpers/type_resolution/object_resolver.py,sha256=jayEjBr4evzIVMMAPc7g_gKb6BShFbAXG1oHMgskOcI,12373
88
+ pyopenapi_gen/helpers/type_resolution/named_resolver.py,sha256=hXu6Gao92EVV0jyHRqf9cIhoAFn3suuEw5ye9nRTFks,9423
89
+ pyopenapi_gen/helpers/type_resolution/object_resolver.py,sha256=Jm4m5QgzWU-4joPqfUSC0Y-za3Yx0ROdJjyv5J8VNk0,12557
90
90
  pyopenapi_gen/helpers/type_resolution/primitive_resolver.py,sha256=qTshZaye5ohibVfcJYCzh4v3CAshguMGWPt2FgvQeNM,1960
91
91
  pyopenapi_gen/helpers/type_resolution/resolver.py,sha256=qQY6wAitBluA-tofiyJ67Gxx8ol1W528zDWd9izYN5s,1982
92
92
  pyopenapi_gen/types/CLAUDE.md,sha256=xRYlHdLhw3QGIfIlWqPt9pewRs736H1YCzwmslKtzZc,4255
@@ -97,7 +97,7 @@ pyopenapi_gen/types/contracts/types.py,sha256=-Qvbx3N_14AaN-1BeyocrvsjiwXPn_eWQh
97
97
  pyopenapi_gen/types/resolvers/__init__.py,sha256=_5kA49RvyOTyXgt0GbbOfHJcdQw2zHxvU9af8GGyNWc,295
98
98
  pyopenapi_gen/types/resolvers/reference_resolver.py,sha256=qnaZeLmtyh4_NBMcKib58s6o5ycUJaattYt8F38_qIo,2053
99
99
  pyopenapi_gen/types/resolvers/response_resolver.py,sha256=Kb1a2803lyoukoZy06ztPBlUw-A1lHiZ6NlJmsixxA8,6500
100
- pyopenapi_gen/types/resolvers/schema_resolver.py,sha256=6cgJPgRsEyMNrEnaR_ONExvMNWjWWBuWa69D7gKTsSY,17528
100
+ pyopenapi_gen/types/resolvers/schema_resolver.py,sha256=PsSF-DE8-GDXmvbAJz-tHlTCR-1UATGhT4dHf6kUDQQ,17988
101
101
  pyopenapi_gen/types/services/__init__.py,sha256=inSUKmY_Vnuym6tC-AhvjCTj16GbkfxCGLESRr_uQPE,123
102
102
  pyopenapi_gen/types/services/type_service.py,sha256=-LQj7oSx1mxb10Zi6DpawS8uyoUrUbnYhmUA0GuKZTc,4402
103
103
  pyopenapi_gen/types/strategies/__init__.py,sha256=bju8_KEPNIow1-woMO-zJCgK_E0M6JnFq0NFsK1R4Ss,171
@@ -113,19 +113,19 @@ pyopenapi_gen/visit/endpoint/generators/__init__.py,sha256=-X-GYnJZ9twiEBr_U0obW
113
113
  pyopenapi_gen/visit/endpoint/generators/docstring_generator.py,sha256=U02qvuYtFElQNEtOHuTNXFl2NxUriIiuZMkmUsapOg4,5913
114
114
  pyopenapi_gen/visit/endpoint/generators/endpoint_method_generator.py,sha256=wUJ4_gaA1gRrFCHYFCObBIankxGQu0MNqiOSoZOZmoA,4352
115
115
  pyopenapi_gen/visit/endpoint/generators/request_generator.py,sha256=OnkrkRk39_BrK9ZDvyWqJYLz1mocD2zY7j70yIpS0J4,5374
116
- pyopenapi_gen/visit/endpoint/generators/response_handler_generator.py,sha256=VuyYpUUQ3hIOwM0X_hrMk9qmQTC0P6xRQdC2HTTIyQw,22828
116
+ pyopenapi_gen/visit/endpoint/generators/response_handler_generator.py,sha256=xbh4GQcA-fA98mOZxVSylLbZADse-7RLcLIbjnVAmlE,22834
117
117
  pyopenapi_gen/visit/endpoint/generators/signature_generator.py,sha256=CYtfsPMlTZN95g2WxrdnTloGx2RmqeNQRiyP9fOkUEQ,3892
118
118
  pyopenapi_gen/visit/endpoint/generators/url_args_generator.py,sha256=EsmNuVSkGfUqrmV7-1GiLPzdN86V5UqLfs1SVY0jsf0,9590
119
119
  pyopenapi_gen/visit/endpoint/processors/__init__.py,sha256=_6RqpOdDuDheArqDBi3ykhsaetACny88WUuuAJvr_ME,29
120
120
  pyopenapi_gen/visit/endpoint/processors/import_analyzer.py,sha256=tNmhgWwt-CjLE774TC8sPVH1-yaTKKm6JmfgBT2-iRk,3386
121
121
  pyopenapi_gen/visit/endpoint/processors/parameter_processor.py,sha256=BygP8yzSTrxfvNpEQIHERjd2NpEXDiwpCtmMseJKRq0,7700
122
122
  pyopenapi_gen/visit/model/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
123
- pyopenapi_gen/visit/model/alias_generator.py,sha256=3iPFDjCXU0Vm59Hfp64jTDfHoUL8ouXTTfoEwiOVm4Q,3558
124
- pyopenapi_gen/visit/model/dataclass_generator.py,sha256=WtcQNx6l2sxVyTlH1MdQ-UFYWVMsxQk5nyJr1Mk02iM,9999
125
- pyopenapi_gen/visit/model/enum_generator.py,sha256=QWsD-IAxGOxKQuC6LLNUvbT8Ot3NWrLFsaYT0DI16DU,9670
126
- pyopenapi_gen/visit/model/model_visitor.py,sha256=PZeQd7-dlxZf5gY10BW-DhswmAGF903NccV6L56mjoE,9439
127
- pyopenapi_gen-0.11.0.dist-info/METADATA,sha256=gv2QjmQpa6Oj87vq7sE14_6MqXO3YEmQsZS6-4NQsNQ,14040
128
- pyopenapi_gen-0.11.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
129
- pyopenapi_gen-0.11.0.dist-info/entry_points.txt,sha256=gxSlNiwom50T3OEZnlocA6qRjGdV0bn6hN_Xr-Ub5wA,56
130
- pyopenapi_gen-0.11.0.dist-info/licenses/LICENSE,sha256=UFAyTWKa4w10-QerlJaHJeep7G2gcwpf-JmvI2dS2Gc,1088
131
- pyopenapi_gen-0.11.0.dist-info/RECORD,,
123
+ pyopenapi_gen/visit/model/alias_generator.py,sha256=TGL3AMq_PkBWFWeeXbNnA8hgO9hvp0flwBA00Gr6S3o,3744
124
+ pyopenapi_gen/visit/model/dataclass_generator.py,sha256=nyTvBph6rtbJlCwTiDW_Y2UJmLLiA6D2QJUpA2xE0m8,10289
125
+ pyopenapi_gen/visit/model/enum_generator.py,sha256=AXqKUFuWUUjUF_6_HqBKY8vB5GYu35Pb2C2WPFrOw1k,10061
126
+ pyopenapi_gen/visit/model/model_visitor.py,sha256=4kAQSWsI4XumVYB3aAE7Ts_31hGfDlbytRalxyMFV3g,9510
127
+ pyopenapi_gen-0.12.0.dist-info/METADATA,sha256=do9Qt8fZ_bOvewCqxXYsCYbNE0qs7BtvC5Xe-AhBnBQ,14025
128
+ pyopenapi_gen-0.12.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
129
+ pyopenapi_gen-0.12.0.dist-info/entry_points.txt,sha256=gxSlNiwom50T3OEZnlocA6qRjGdV0bn6hN_Xr-Ub5wA,56
130
+ pyopenapi_gen-0.12.0.dist-info/licenses/LICENSE,sha256=UFAyTWKa4w10-QerlJaHJeep7G2gcwpf-JmvI2dS2Gc,1088
131
+ pyopenapi_gen-0.12.0.dist-info/RECORD,,