pyopenapi-gen 2.7.2__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 (137) hide show
  1. pyopenapi_gen/__init__.py +224 -0
  2. pyopenapi_gen/__main__.py +6 -0
  3. pyopenapi_gen/cli.py +62 -0
  4. pyopenapi_gen/context/CLAUDE.md +284 -0
  5. pyopenapi_gen/context/file_manager.py +52 -0
  6. pyopenapi_gen/context/import_collector.py +382 -0
  7. pyopenapi_gen/context/render_context.py +726 -0
  8. pyopenapi_gen/core/CLAUDE.md +224 -0
  9. pyopenapi_gen/core/__init__.py +0 -0
  10. pyopenapi_gen/core/auth/base.py +22 -0
  11. pyopenapi_gen/core/auth/plugins.py +89 -0
  12. pyopenapi_gen/core/cattrs_converter.py +810 -0
  13. pyopenapi_gen/core/exceptions.py +20 -0
  14. pyopenapi_gen/core/http_status_codes.py +218 -0
  15. pyopenapi_gen/core/http_transport.py +222 -0
  16. pyopenapi_gen/core/loader/__init__.py +12 -0
  17. pyopenapi_gen/core/loader/loader.py +174 -0
  18. pyopenapi_gen/core/loader/operations/__init__.py +12 -0
  19. pyopenapi_gen/core/loader/operations/parser.py +161 -0
  20. pyopenapi_gen/core/loader/operations/post_processor.py +62 -0
  21. pyopenapi_gen/core/loader/operations/request_body.py +90 -0
  22. pyopenapi_gen/core/loader/parameters/__init__.py +10 -0
  23. pyopenapi_gen/core/loader/parameters/parser.py +186 -0
  24. pyopenapi_gen/core/loader/responses/__init__.py +10 -0
  25. pyopenapi_gen/core/loader/responses/parser.py +111 -0
  26. pyopenapi_gen/core/loader/schemas/__init__.py +11 -0
  27. pyopenapi_gen/core/loader/schemas/extractor.py +275 -0
  28. pyopenapi_gen/core/pagination.py +64 -0
  29. pyopenapi_gen/core/parsing/__init__.py +13 -0
  30. pyopenapi_gen/core/parsing/common/__init__.py +1 -0
  31. pyopenapi_gen/core/parsing/common/ref_resolution/__init__.py +9 -0
  32. pyopenapi_gen/core/parsing/common/ref_resolution/helpers/__init__.py +0 -0
  33. pyopenapi_gen/core/parsing/common/ref_resolution/helpers/cyclic_properties.py +66 -0
  34. pyopenapi_gen/core/parsing/common/ref_resolution/helpers/direct_cycle.py +33 -0
  35. pyopenapi_gen/core/parsing/common/ref_resolution/helpers/existing_schema.py +22 -0
  36. pyopenapi_gen/core/parsing/common/ref_resolution/helpers/list_response.py +54 -0
  37. pyopenapi_gen/core/parsing/common/ref_resolution/helpers/missing_ref.py +52 -0
  38. pyopenapi_gen/core/parsing/common/ref_resolution/helpers/new_schema.py +50 -0
  39. pyopenapi_gen/core/parsing/common/ref_resolution/helpers/stripped_suffix.py +51 -0
  40. pyopenapi_gen/core/parsing/common/ref_resolution/resolve_schema_ref.py +86 -0
  41. pyopenapi_gen/core/parsing/common/type_parser.py +73 -0
  42. pyopenapi_gen/core/parsing/context.py +187 -0
  43. pyopenapi_gen/core/parsing/cycle_helpers.py +126 -0
  44. pyopenapi_gen/core/parsing/keywords/__init__.py +1 -0
  45. pyopenapi_gen/core/parsing/keywords/all_of_parser.py +81 -0
  46. pyopenapi_gen/core/parsing/keywords/any_of_parser.py +84 -0
  47. pyopenapi_gen/core/parsing/keywords/array_items_parser.py +72 -0
  48. pyopenapi_gen/core/parsing/keywords/one_of_parser.py +77 -0
  49. pyopenapi_gen/core/parsing/keywords/properties_parser.py +98 -0
  50. pyopenapi_gen/core/parsing/schema_finalizer.py +169 -0
  51. pyopenapi_gen/core/parsing/schema_parser.py +804 -0
  52. pyopenapi_gen/core/parsing/transformers/__init__.py +0 -0
  53. pyopenapi_gen/core/parsing/transformers/inline_enum_extractor.py +285 -0
  54. pyopenapi_gen/core/parsing/transformers/inline_object_promoter.py +120 -0
  55. pyopenapi_gen/core/parsing/unified_cycle_detection.py +293 -0
  56. pyopenapi_gen/core/postprocess_manager.py +260 -0
  57. pyopenapi_gen/core/spec_fetcher.py +148 -0
  58. pyopenapi_gen/core/streaming_helpers.py +84 -0
  59. pyopenapi_gen/core/telemetry.py +69 -0
  60. pyopenapi_gen/core/utils.py +456 -0
  61. pyopenapi_gen/core/warning_collector.py +83 -0
  62. pyopenapi_gen/core/writers/code_writer.py +135 -0
  63. pyopenapi_gen/core/writers/documentation_writer.py +222 -0
  64. pyopenapi_gen/core/writers/line_writer.py +217 -0
  65. pyopenapi_gen/core/writers/python_construct_renderer.py +321 -0
  66. pyopenapi_gen/core_package_template/README.md +21 -0
  67. pyopenapi_gen/emit/models_emitter.py +143 -0
  68. pyopenapi_gen/emitters/CLAUDE.md +286 -0
  69. pyopenapi_gen/emitters/client_emitter.py +51 -0
  70. pyopenapi_gen/emitters/core_emitter.py +181 -0
  71. pyopenapi_gen/emitters/docs_emitter.py +44 -0
  72. pyopenapi_gen/emitters/endpoints_emitter.py +247 -0
  73. pyopenapi_gen/emitters/exceptions_emitter.py +187 -0
  74. pyopenapi_gen/emitters/mocks_emitter.py +185 -0
  75. pyopenapi_gen/emitters/models_emitter.py +426 -0
  76. pyopenapi_gen/generator/CLAUDE.md +352 -0
  77. pyopenapi_gen/generator/client_generator.py +567 -0
  78. pyopenapi_gen/generator/exceptions.py +7 -0
  79. pyopenapi_gen/helpers/CLAUDE.md +325 -0
  80. pyopenapi_gen/helpers/__init__.py +1 -0
  81. pyopenapi_gen/helpers/endpoint_utils.py +532 -0
  82. pyopenapi_gen/helpers/type_cleaner.py +334 -0
  83. pyopenapi_gen/helpers/type_helper.py +112 -0
  84. pyopenapi_gen/helpers/type_resolution/__init__.py +1 -0
  85. pyopenapi_gen/helpers/type_resolution/array_resolver.py +57 -0
  86. pyopenapi_gen/helpers/type_resolution/composition_resolver.py +79 -0
  87. pyopenapi_gen/helpers/type_resolution/finalizer.py +105 -0
  88. pyopenapi_gen/helpers/type_resolution/named_resolver.py +172 -0
  89. pyopenapi_gen/helpers/type_resolution/object_resolver.py +216 -0
  90. pyopenapi_gen/helpers/type_resolution/primitive_resolver.py +109 -0
  91. pyopenapi_gen/helpers/type_resolution/resolver.py +47 -0
  92. pyopenapi_gen/helpers/url_utils.py +14 -0
  93. pyopenapi_gen/http_types.py +20 -0
  94. pyopenapi_gen/ir.py +165 -0
  95. pyopenapi_gen/py.typed +1 -0
  96. pyopenapi_gen/types/CLAUDE.md +140 -0
  97. pyopenapi_gen/types/__init__.py +11 -0
  98. pyopenapi_gen/types/contracts/__init__.py +13 -0
  99. pyopenapi_gen/types/contracts/protocols.py +106 -0
  100. pyopenapi_gen/types/contracts/types.py +28 -0
  101. pyopenapi_gen/types/resolvers/__init__.py +7 -0
  102. pyopenapi_gen/types/resolvers/reference_resolver.py +71 -0
  103. pyopenapi_gen/types/resolvers/response_resolver.py +177 -0
  104. pyopenapi_gen/types/resolvers/schema_resolver.py +498 -0
  105. pyopenapi_gen/types/services/__init__.py +5 -0
  106. pyopenapi_gen/types/services/type_service.py +165 -0
  107. pyopenapi_gen/types/strategies/__init__.py +5 -0
  108. pyopenapi_gen/types/strategies/response_strategy.py +310 -0
  109. pyopenapi_gen/visit/CLAUDE.md +272 -0
  110. pyopenapi_gen/visit/client_visitor.py +477 -0
  111. pyopenapi_gen/visit/docs_visitor.py +38 -0
  112. pyopenapi_gen/visit/endpoint/__init__.py +1 -0
  113. pyopenapi_gen/visit/endpoint/endpoint_visitor.py +292 -0
  114. pyopenapi_gen/visit/endpoint/generators/__init__.py +1 -0
  115. pyopenapi_gen/visit/endpoint/generators/docstring_generator.py +123 -0
  116. pyopenapi_gen/visit/endpoint/generators/endpoint_method_generator.py +222 -0
  117. pyopenapi_gen/visit/endpoint/generators/mock_generator.py +140 -0
  118. pyopenapi_gen/visit/endpoint/generators/overload_generator.py +252 -0
  119. pyopenapi_gen/visit/endpoint/generators/request_generator.py +103 -0
  120. pyopenapi_gen/visit/endpoint/generators/response_handler_generator.py +705 -0
  121. pyopenapi_gen/visit/endpoint/generators/signature_generator.py +83 -0
  122. pyopenapi_gen/visit/endpoint/generators/url_args_generator.py +207 -0
  123. pyopenapi_gen/visit/endpoint/processors/__init__.py +1 -0
  124. pyopenapi_gen/visit/endpoint/processors/import_analyzer.py +78 -0
  125. pyopenapi_gen/visit/endpoint/processors/parameter_processor.py +171 -0
  126. pyopenapi_gen/visit/exception_visitor.py +90 -0
  127. pyopenapi_gen/visit/model/__init__.py +0 -0
  128. pyopenapi_gen/visit/model/alias_generator.py +93 -0
  129. pyopenapi_gen/visit/model/dataclass_generator.py +553 -0
  130. pyopenapi_gen/visit/model/enum_generator.py +212 -0
  131. pyopenapi_gen/visit/model/model_visitor.py +198 -0
  132. pyopenapi_gen/visit/visitor.py +97 -0
  133. pyopenapi_gen-2.7.2.dist-info/METADATA +1169 -0
  134. pyopenapi_gen-2.7.2.dist-info/RECORD +137 -0
  135. pyopenapi_gen-2.7.2.dist-info/WHEEL +4 -0
  136. pyopenapi_gen-2.7.2.dist-info/entry_points.txt +2 -0
  137. pyopenapi_gen-2.7.2.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,272 @@
1
+ # visit/ - Code Generation Visitor Pattern
2
+
3
+ ## Why This Folder?
4
+ Transform IR objects into Python code strings using visitor pattern. Each visitor specializes in generating one aspect of the client (models, endpoints, exceptions, etc.).
5
+
6
+ ## Key Dependencies
7
+ - **Input**: `IRSpec`, `IRSchema`, `IROperation` from `../ir.py`
8
+ - **Output**: Python code strings for emitters
9
+ - **Services**: `UnifiedTypeService` from `../types/services/`
10
+ - **Context**: `RenderContext` from `../context/render_context.py`
11
+
12
+ ## Essential Architecture
13
+
14
+ ### 1. Visitor Pattern Hierarchy
15
+ ```python
16
+ # visitor.py - Base visitor
17
+ class Visitor(Generic[tNode, tRet]):
18
+ def visit(self, node: tNode, context: RenderContext) -> tRet:
19
+ # Dispatch to specific visit methods
20
+
21
+ # Concrete visitors
22
+ class ModelVisitor(Visitor[IRSchema, str]):
23
+ def visit_schema(self, schema: IRSchema, context: RenderContext) -> str:
24
+ # Generate dataclass/enum code
25
+ ```
26
+
27
+ ### 2. Generators vs Visitors
28
+ - **Visitors**: High-level orchestration, traverse IR structure
29
+ - **Generators**: Low-level code generation, create specific code blocks
30
+
31
+ ```python
32
+ # endpoint/endpoint_visitor.py
33
+ class EndpointVisitor:
34
+ def __init__(self):
35
+ self.signature_generator = SignatureGenerator()
36
+ self.request_generator = RequestGenerator()
37
+ self.response_generator = ResponseHandlerGenerator()
38
+ ```
39
+
40
+ ## Critical Components
41
+
42
+ ### model/model_visitor.py
43
+ **Purpose**: Generate dataclass and enum code from schemas
44
+ ```python
45
+ def visit_schema(self, schema: IRSchema, context: RenderContext) -> str:
46
+ if schema.enum:
47
+ return self.enum_generator.generate_enum(schema, context)
48
+ elif schema.type == "object":
49
+ return self.dataclass_generator.generate_dataclass(schema, context)
50
+ else:
51
+ return self.alias_generator.generate_alias(schema, context)
52
+ ```
53
+
54
+ ### endpoint/endpoint_visitor.py
55
+ **Purpose**: Generate async method code from operations
56
+ ```python
57
+ def visit_operation(self, operation: IROperation, context: RenderContext) -> str:
58
+ # 1. Generate method signature
59
+ signature = self.signature_generator.generate(operation, context)
60
+
61
+ # 2. Generate request construction
62
+ request_code = self.request_generator.generate(operation, context)
63
+
64
+ # 3. Generate response handling
65
+ response_code = self.response_generator.generate(operation, context)
66
+
67
+ # 4. Combine into complete method
68
+ return self.combine_method_parts(signature, request_code, response_code)
69
+ ```
70
+
71
+ ### client_visitor.py
72
+ **Purpose**: Generate main client class with tag-grouped methods
73
+ ```python
74
+ def visit_spec(self, spec: IRSpec, context: RenderContext) -> str:
75
+ # 1. Group operations by tag
76
+ operations_by_tag = self.group_operations_by_tag(spec.operations)
77
+
78
+ # 2. Generate client class
79
+ # 3. Generate tag-based property methods
80
+ # 4. Generate context manager methods
81
+ ```
82
+
83
+ ## Code Generation Patterns
84
+
85
+ ### 1. Template-Based Generation
86
+ ```python
87
+ # Use string templates for consistent formatting
88
+ METHOD_TEMPLATE = '''
89
+ async def {method_name}(self, {parameters}) -> {return_type}:
90
+ """
91
+ {docstring}
92
+ """
93
+ {body}
94
+ '''
95
+
96
+ # Fill template with generated content
97
+ method_code = METHOD_TEMPLATE.format(
98
+ method_name=operation.operation_id,
99
+ parameters=self.signature_generator.generate_parameters(operation),
100
+ return_type=self.get_return_type(operation),
101
+ docstring=self.docstring_generator.generate(operation),
102
+ body=self.generate_method_body(operation)
103
+ )
104
+ ```
105
+
106
+ ### 2. Type Resolution Integration
107
+ ```python
108
+ # endpoint/generators/signature_generator.py
109
+ def generate_parameters(self, operation: IROperation, context: RenderContext) -> str:
110
+ params = []
111
+ for param in operation.parameters:
112
+ # Use unified type service for parameter types
113
+ param_type = self.type_service.resolve_schema_type(
114
+ param.schema, context, required=param.required
115
+ )
116
+ params.append(f"{param.name}: {param_type}")
117
+ return ", ".join(params)
118
+ ```
119
+
120
+ ### 3. Import Management
121
+ ```python
122
+ # Always register imports when using complex types
123
+ def generate_dataclass(self, schema: IRSchema, context: RenderContext) -> str:
124
+ imports = []
125
+
126
+ for prop_name, prop_schema in schema.properties.items():
127
+ prop_type = self.type_service.resolve_schema_type(prop_schema, context)
128
+
129
+ # Type service handles import registration
130
+ # context.add_import() called internally
131
+
132
+ return dataclass_code
133
+ ```
134
+
135
+ ## Specialized Generators
136
+
137
+ ### endpoint/generators/
138
+ **Purpose**: Generate specific parts of endpoint methods
139
+
140
+ #### docstring_generator.py
141
+ ```python
142
+ def generate_docstring(self, operation: IROperation, context: RenderContext) -> str:
143
+ # Generate Google-style docstrings
144
+ # Include parameter descriptions
145
+ # Include return type information
146
+ # Include raises information
147
+ ```
148
+
149
+ #### request_generator.py
150
+ ```python
151
+ def generate_request_construction(self, operation: IROperation, context: RenderContext) -> str:
152
+ # Generate httpx.Request construction
153
+ # Handle query parameters, headers, body
154
+ # Apply authentication
155
+ ```
156
+
157
+ #### response_handler_generator.py
158
+ ```python
159
+ def generate_response_handling(self, operation: IROperation, context: RenderContext) -> str:
160
+ # Generate match/case for status codes
161
+ # Handle response deserialization
162
+ # Generate exception raising
163
+ ```
164
+
165
+ ## Dependencies on Other Systems
166
+
167
+ ### From types/
168
+ - `UnifiedTypeService` for all type resolution
169
+ - Response unwrapping detection
170
+ - Forward reference handling
171
+
172
+ ### From context/
173
+ - `RenderContext` for import management
174
+ - Template rendering utilities
175
+ - Path resolution
176
+
177
+ ### To emitters/
178
+ - Visitors produce code strings
179
+ - Emitters organize code into files
180
+
181
+ ## Testing Requirements
182
+
183
+ ### Visitor Tests
184
+ ```python
185
+ def test_model_visitor__dataclass_schema__generates_correct_code():
186
+ # Arrange
187
+ schema = IRSchema(type="object", properties={"name": {"type": "string"}})
188
+ context = RenderContext()
189
+ visitor = ModelVisitor()
190
+
191
+ # Act
192
+ code = visitor.visit_schema(schema, context)
193
+
194
+ # Assert
195
+ assert "@dataclass" in code
196
+ assert "name: str" in code
197
+ ```
198
+
199
+ ### Generator Tests
200
+ ```python
201
+ def test_signature_generator__operation_with_params__generates_correct_signature():
202
+ # Test specific code generation components
203
+ operation = IROperation(parameters=[...])
204
+ generator = SignatureGenerator()
205
+
206
+ signature = generator.generate(operation, context)
207
+
208
+ # Verify parameter types, defaults, etc.
209
+ ```
210
+
211
+ ## Extension Points
212
+
213
+ ### Adding New Visitors
214
+ ```python
215
+ # Create new visitor for new code aspects
216
+ class CustomVisitor(Visitor[IRCustomNode, str]):
217
+ def visit_custom_node(self, node: IRCustomNode, context: RenderContext) -> str:
218
+ # Custom code generation logic
219
+ pass
220
+ ```
221
+
222
+ ### Adding New Generators
223
+ ```python
224
+ # endpoint/generators/custom_generator.py
225
+ class CustomGenerator:
226
+ def __init__(self, type_service: UnifiedTypeService):
227
+ self.type_service = type_service
228
+
229
+ def generate(self, operation: IROperation, context: RenderContext) -> str:
230
+ # Custom code generation logic
231
+ pass
232
+ ```
233
+
234
+ ## Critical Implementation Details
235
+
236
+ ### Error Handling in Visitors
237
+ ```python
238
+ def visit_schema(self, schema: IRSchema, context: RenderContext) -> str:
239
+ try:
240
+ return self.generate_code(schema, context)
241
+ except Exception as e:
242
+ # Add context to errors
243
+ raise CodeGenerationError(f"Failed to generate code for schema {schema.name}: {e}")
244
+ ```
245
+
246
+ ### Context Management
247
+ ```python
248
+ # Always use context for imports and state
249
+ def generate_method(self, operation: IROperation, context: RenderContext) -> str:
250
+ # Register imports
251
+ context.add_import("from typing import Optional")
252
+
253
+ # Use context for type resolution
254
+ return_type = self.type_service.resolve_operation_response_type(operation, context)
255
+
256
+ # Return code string
257
+ return method_code
258
+ ```
259
+
260
+ ### Code Formatting
261
+ ```python
262
+ # Use consistent indentation and formatting
263
+ def format_method_body(self, lines: List[str]) -> str:
264
+ # Ensure proper indentation
265
+ formatted_lines = []
266
+ for line in lines:
267
+ if line.strip():
268
+ formatted_lines.append(f" {line}") # 4-space indent
269
+ else:
270
+ formatted_lines.append("")
271
+ return "\n".join(formatted_lines)
272
+ ```