openapi-python-client 0.20.0__tar.gz → 0.21.1__tar.gz
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.
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/PKG-INFO +2 -2
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/__init__.py +27 -49
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/cli.py +42 -51
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/config.py +10 -1
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/parser/bodies.py +26 -6
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/parser/openapi.py +8 -2
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/templates/property_templates/list_property.py.jinja +1 -1
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/pyproject.toml +4 -6
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/.gitignore +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/LICENSE +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/README.md +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/__main__.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/parser/__init__.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/parser/errors.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/parser/properties/__init__.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/parser/properties/any.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/parser/properties/boolean.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/parser/properties/const.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/parser/properties/date.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/parser/properties/datetime.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/parser/properties/enum_property.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/parser/properties/file.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/parser/properties/float.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/parser/properties/int.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/parser/properties/list_property.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/parser/properties/model_property.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/parser/properties/none.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/parser/properties/property.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/parser/properties/protocol.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/parser/properties/schemas.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/parser/properties/string.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/parser/properties/union.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/parser/responses.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/py.typed +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/schema/3.0.3.md +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/schema/3.1.0.md +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/schema/__init__.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/schema/data_type.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/schema/openapi_schema_pydantic/LICENSE +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/schema/openapi_schema_pydantic/README.md +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/schema/openapi_schema_pydantic/__init__.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/schema/openapi_schema_pydantic/callback.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/schema/openapi_schema_pydantic/components.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/schema/openapi_schema_pydantic/contact.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/schema/openapi_schema_pydantic/discriminator.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/schema/openapi_schema_pydantic/encoding.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/schema/openapi_schema_pydantic/example.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/schema/openapi_schema_pydantic/external_documentation.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/schema/openapi_schema_pydantic/header.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/schema/openapi_schema_pydantic/info.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/schema/openapi_schema_pydantic/license.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/schema/openapi_schema_pydantic/link.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/schema/openapi_schema_pydantic/media_type.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/schema/openapi_schema_pydantic/oauth_flow.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/schema/openapi_schema_pydantic/oauth_flows.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/schema/openapi_schema_pydantic/open_api.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/schema/openapi_schema_pydantic/operation.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/schema/openapi_schema_pydantic/parameter.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/schema/openapi_schema_pydantic/path_item.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/schema/openapi_schema_pydantic/paths.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/schema/openapi_schema_pydantic/reference.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/schema/openapi_schema_pydantic/request_body.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/schema/openapi_schema_pydantic/response.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/schema/openapi_schema_pydantic/responses.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/schema/openapi_schema_pydantic/schema.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/schema/openapi_schema_pydantic/security_requirement.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/schema/openapi_schema_pydantic/security_scheme.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/schema/openapi_schema_pydantic/server.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/schema/openapi_schema_pydantic/server_variable.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/schema/openapi_schema_pydantic/tag.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/schema/openapi_schema_pydantic/xml.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/schema/parameter_location.py +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/templates/.gitignore.jinja +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/templates/README.md.jinja +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/templates/api_init.py.jinja +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/templates/client.py.jinja +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/templates/endpoint_init.py.jinja +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/templates/endpoint_macros.py.jinja +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/templates/endpoint_module.py.jinja +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/templates/errors.py.jinja +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/templates/helpers.jinja +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/templates/int_enum.py.jinja +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/templates/model.py.jinja +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/templates/models_init.py.jinja +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/templates/package_init.py.jinja +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/templates/property_templates/any_property.py.jinja +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/templates/property_templates/boolean_property.py.jinja +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/templates/property_templates/const_property.py.jinja +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/templates/property_templates/date_property.py.jinja +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/templates/property_templates/datetime_property.py.jinja +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/templates/property_templates/enum_property.py.jinja +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/templates/property_templates/file_property.py.jinja +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/templates/property_templates/float_property.py.jinja +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/templates/property_templates/helpers.jinja +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/templates/property_templates/int_property.py.jinja +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/templates/property_templates/model_property.py.jinja +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/templates/property_templates/property_macros.py.jinja +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/templates/property_templates/union_property.py.jinja +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/templates/pyproject.toml.jinja +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/templates/pyproject_ruff.toml.jinja +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/templates/setup.py.jinja +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/templates/str_enum.py.jinja +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/templates/types.py.jinja +0 -0
- {openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: openapi-python-client
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.21.1
|
|
4
4
|
Summary: Generate modern Python clients from OpenAPI
|
|
5
5
|
Project-URL: repository, https://github.com/openapi-generators/openapi-python-client
|
|
6
6
|
Author-email: Dylan Anthony <contact@dylananthony.com>
|
|
@@ -18,7 +18,7 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
18
18
|
Classifier: Programming Language :: Python :: 3.12
|
|
19
19
|
Classifier: Topic :: Software Development :: Code Generators
|
|
20
20
|
Classifier: Typing :: Typed
|
|
21
|
-
Requires-Python: <4.0,>=3.8
|
|
21
|
+
Requires-Python: <4.0,>=3.8.1
|
|
22
22
|
Requires-Dist: attrs>=21.3.0
|
|
23
23
|
Requires-Dist: colorama>=0.4.3; sys_platform == 'win32'
|
|
24
24
|
Requires-Dist: httpx<0.28.0,>=0.20.0
|
{openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/__init__.py
RENAMED
|
@@ -65,12 +65,22 @@ class Project:
|
|
|
65
65
|
)
|
|
66
66
|
|
|
67
67
|
self.project_name: str = config.project_name_override or f"{utils.kebab_case(openapi.title).lower()}-client"
|
|
68
|
-
self.project_dir: Path = Path.cwd()
|
|
69
|
-
if config.meta_type != MetaType.NONE:
|
|
70
|
-
self.project_dir /= self.project_name
|
|
71
|
-
|
|
72
68
|
self.package_name: str = config.package_name_override or self.project_name.replace("-", "_")
|
|
73
|
-
self.
|
|
69
|
+
self.project_dir: Path # Where the generated code will be placed
|
|
70
|
+
self.package_dir: Path # Where the generated Python module will be placed (same as project_dir if no meta)
|
|
71
|
+
|
|
72
|
+
if config.output_path is not None:
|
|
73
|
+
self.project_dir = config.output_path
|
|
74
|
+
elif config.meta_type == MetaType.NONE:
|
|
75
|
+
self.project_dir = Path.cwd() / self.package_name
|
|
76
|
+
else:
|
|
77
|
+
self.project_dir = Path.cwd() / self.project_name
|
|
78
|
+
|
|
79
|
+
if config.meta_type == MetaType.NONE:
|
|
80
|
+
self.package_dir = self.project_dir
|
|
81
|
+
else:
|
|
82
|
+
self.package_dir = self.project_dir / self.package_name
|
|
83
|
+
|
|
74
84
|
self.package_description: str = utils.remove_string_escapes(
|
|
75
85
|
f"A client library for accessing {self.openapi.title}"
|
|
76
86
|
)
|
|
@@ -95,29 +105,16 @@ class Project:
|
|
|
95
105
|
def build(self) -> Sequence[GeneratorError]:
|
|
96
106
|
"""Create the project from templates"""
|
|
97
107
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
print(f"Generating {self.project_name}")
|
|
102
|
-
try:
|
|
103
|
-
self.project_dir.mkdir()
|
|
104
|
-
except FileExistsError:
|
|
105
|
-
return [GeneratorError(detail="Directory already exists. Delete it or use the update command.")]
|
|
106
|
-
self._create_package()
|
|
107
|
-
self._build_metadata()
|
|
108
|
-
self._build_models()
|
|
109
|
-
self._build_api()
|
|
110
|
-
self._run_post_hooks()
|
|
111
|
-
return self._get_errors()
|
|
112
|
-
|
|
113
|
-
def update(self) -> Sequence[GeneratorError]:
|
|
114
|
-
"""Update an existing project"""
|
|
108
|
+
print(f"Generating {self.project_dir}")
|
|
109
|
+
if self.config.overwrite:
|
|
110
|
+
shutil.rmtree(self.project_dir, ignore_errors=True)
|
|
115
111
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
112
|
+
try:
|
|
113
|
+
self.project_dir.mkdir()
|
|
114
|
+
except FileExistsError:
|
|
115
|
+
return [GeneratorError(detail="Directory already exists. Delete it or use the --overwrite option.")]
|
|
120
116
|
self._create_package()
|
|
117
|
+
self._build_metadata()
|
|
121
118
|
self._build_models()
|
|
122
119
|
self._build_api()
|
|
123
120
|
self._run_post_hooks()
|
|
@@ -138,7 +135,7 @@ class Project:
|
|
|
138
135
|
)
|
|
139
136
|
return
|
|
140
137
|
try:
|
|
141
|
-
cwd = self.
|
|
138
|
+
cwd = self.project_dir
|
|
142
139
|
subprocess.run(cmd, cwd=cwd, shell=True, capture_output=True, check=True)
|
|
143
140
|
except CalledProcessError as err:
|
|
144
141
|
self.errors.append(
|
|
@@ -158,7 +155,8 @@ class Project:
|
|
|
158
155
|
return errors
|
|
159
156
|
|
|
160
157
|
def _create_package(self) -> None:
|
|
161
|
-
self.package_dir.
|
|
158
|
+
if self.package_dir != self.project_dir:
|
|
159
|
+
self.package_dir.mkdir()
|
|
162
160
|
# Package __init__.py
|
|
163
161
|
package_init = self.package_dir / "__init__.py"
|
|
164
162
|
|
|
@@ -303,7 +301,7 @@ def _get_project_for_url_or_path(
|
|
|
303
301
|
)
|
|
304
302
|
|
|
305
303
|
|
|
306
|
-
def
|
|
304
|
+
def generate(
|
|
307
305
|
*,
|
|
308
306
|
config: Config,
|
|
309
307
|
custom_template_path: Optional[Path] = None,
|
|
@@ -323,26 +321,6 @@ def create_new_client(
|
|
|
323
321
|
return project.build()
|
|
324
322
|
|
|
325
323
|
|
|
326
|
-
def update_existing_client(
|
|
327
|
-
*,
|
|
328
|
-
config: Config,
|
|
329
|
-
custom_template_path: Optional[Path] = None,
|
|
330
|
-
) -> Sequence[GeneratorError]:
|
|
331
|
-
"""
|
|
332
|
-
Update an existing client library
|
|
333
|
-
|
|
334
|
-
Returns:
|
|
335
|
-
A list containing any errors encountered when generating.
|
|
336
|
-
"""
|
|
337
|
-
project = _get_project_for_url_or_path(
|
|
338
|
-
custom_template_path=custom_template_path,
|
|
339
|
-
config=config,
|
|
340
|
-
)
|
|
341
|
-
if isinstance(project, GeneratorError):
|
|
342
|
-
return [project]
|
|
343
|
-
return project.update()
|
|
344
|
-
|
|
345
|
-
|
|
346
324
|
def _load_yaml_or_json(data: bytes, content_type: Optional[str]) -> Union[Dict[str, Any], GeneratorError]:
|
|
347
325
|
if content_type == "application/json":
|
|
348
326
|
try:
|
|
@@ -21,7 +21,14 @@ def _version_callback(value: bool) -> None:
|
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
def _process_config(
|
|
24
|
-
*,
|
|
24
|
+
*,
|
|
25
|
+
url: Optional[str],
|
|
26
|
+
path: Optional[Path],
|
|
27
|
+
config_path: Optional[Path],
|
|
28
|
+
meta_type: MetaType,
|
|
29
|
+
file_encoding: str,
|
|
30
|
+
overwrite: bool,
|
|
31
|
+
output_path: Optional[Path],
|
|
25
32
|
) -> Config:
|
|
26
33
|
source: Union[Path, str]
|
|
27
34
|
if url and not path:
|
|
@@ -49,7 +56,7 @@ def _process_config(
|
|
|
49
56
|
except Exception as err:
|
|
50
57
|
raise typer.BadParameter("Unable to parse config") from err
|
|
51
58
|
|
|
52
|
-
return Config.from_sources(config_file, meta_type, source, file_encoding)
|
|
59
|
+
return Config.from_sources(config_file, meta_type, source, file_encoding, overwrite, output_path=output_path)
|
|
53
60
|
|
|
54
61
|
|
|
55
62
|
# noinspection PyUnusedLocal
|
|
@@ -117,62 +124,46 @@ def handle_errors(errors: Sequence[GeneratorError], fail_on_warning: bool = Fals
|
|
|
117
124
|
raise typer.Exit(code=1)
|
|
118
125
|
|
|
119
126
|
|
|
120
|
-
custom_template_path_options = {
|
|
121
|
-
"help": "A path to a directory containing custom template(s)",
|
|
122
|
-
"file_okay": False,
|
|
123
|
-
"dir_okay": True,
|
|
124
|
-
"readable": True,
|
|
125
|
-
"resolve_path": True,
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
_meta_option = typer.Option(
|
|
129
|
-
MetaType.POETRY,
|
|
130
|
-
help="The type of metadata you want to generate.",
|
|
131
|
-
)
|
|
132
|
-
|
|
133
|
-
CONFIG_OPTION = typer.Option(None, "--config", help="Path to the config file to use")
|
|
134
|
-
|
|
135
|
-
|
|
136
127
|
@app.command()
|
|
137
128
|
def generate(
|
|
138
|
-
url: Optional[str] = typer.Option(None, help="A URL to read the
|
|
139
|
-
path: Optional[Path] = typer.Option(None, help="A path to the
|
|
140
|
-
custom_template_path: Optional[Path] = typer.Option(
|
|
141
|
-
|
|
129
|
+
url: Optional[str] = typer.Option(None, help="A URL to read the OpenAPI document from"),
|
|
130
|
+
path: Optional[Path] = typer.Option(None, help="A path to the OpenAPI document"),
|
|
131
|
+
custom_template_path: Optional[Path] = typer.Option(
|
|
132
|
+
None,
|
|
133
|
+
help="A path to a directory containing custom template(s)",
|
|
134
|
+
file_okay=False,
|
|
135
|
+
dir_okay=True,
|
|
136
|
+
readable=True,
|
|
137
|
+
resolve_path=True,
|
|
138
|
+
), # type: ignore
|
|
139
|
+
meta: MetaType = typer.Option(
|
|
140
|
+
MetaType.POETRY,
|
|
141
|
+
help="The type of metadata you want to generate.",
|
|
142
|
+
),
|
|
142
143
|
file_encoding: str = typer.Option("utf-8", help="Encoding used when writing generated"),
|
|
143
|
-
config_path: Optional[Path] =
|
|
144
|
+
config_path: Optional[Path] = typer.Option(None, "--config", help="Path to the config file to use"),
|
|
144
145
|
fail_on_warning: bool = False,
|
|
146
|
+
overwrite: bool = typer.Option(False, help="Overwrite the existing client if it exists"),
|
|
147
|
+
output_path: Optional[Path] = typer.Option(
|
|
148
|
+
None,
|
|
149
|
+
help="Path to write the generated code to. "
|
|
150
|
+
"Defaults to the OpenAPI document title converted to kebab or snake case (depending on meta type). "
|
|
151
|
+
"Can also be overridden with `project_name_override` or `package_name_override` in config.",
|
|
152
|
+
),
|
|
145
153
|
) -> None:
|
|
146
154
|
"""Generate a new OpenAPI Client library"""
|
|
147
|
-
from . import
|
|
148
|
-
|
|
149
|
-
config = _process_config(
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
155
|
+
from . import generate
|
|
156
|
+
|
|
157
|
+
config = _process_config(
|
|
158
|
+
url=url,
|
|
159
|
+
path=path,
|
|
160
|
+
config_path=config_path,
|
|
161
|
+
meta_type=meta,
|
|
162
|
+
file_encoding=file_encoding,
|
|
163
|
+
overwrite=overwrite,
|
|
164
|
+
output_path=output_path,
|
|
153
165
|
)
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
@app.command()
|
|
158
|
-
def update(
|
|
159
|
-
url: Optional[str] = typer.Option(None, help="A URL to read the JSON from"),
|
|
160
|
-
path: Optional[Path] = typer.Option(None, help="A path to the JSON file"),
|
|
161
|
-
custom_template_path: Optional[Path] = typer.Option(None, **custom_template_path_options), # type: ignore
|
|
162
|
-
meta: MetaType = _meta_option,
|
|
163
|
-
file_encoding: str = typer.Option("utf-8", help="Encoding used when writing generated"),
|
|
164
|
-
config_path: Optional[Path] = CONFIG_OPTION,
|
|
165
|
-
fail_on_warning: bool = False,
|
|
166
|
-
) -> None:
|
|
167
|
-
"""Update an existing OpenAPI Client library
|
|
168
|
-
|
|
169
|
-
The update command performs the same operations as generate except it does not overwrite specific metadata for the
|
|
170
|
-
generated client such as the README.md, .gitignore, and pyproject.toml.
|
|
171
|
-
"""
|
|
172
|
-
from . import update_existing_client
|
|
173
|
-
|
|
174
|
-
config = _process_config(config_path=config_path, meta_type=meta, url=url, path=path, file_encoding=file_encoding)
|
|
175
|
-
errors = update_existing_client(
|
|
166
|
+
errors = generate(
|
|
176
167
|
custom_template_path=custom_template_path,
|
|
177
168
|
config=config,
|
|
178
169
|
)
|
{openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/config.py
RENAMED
|
@@ -73,10 +73,17 @@ class Config:
|
|
|
73
73
|
document_source: Union[Path, str]
|
|
74
74
|
file_encoding: str
|
|
75
75
|
content_type_overrides: Dict[str, str]
|
|
76
|
+
overwrite: bool
|
|
77
|
+
output_path: Optional[Path]
|
|
76
78
|
|
|
77
79
|
@staticmethod
|
|
78
80
|
def from_sources(
|
|
79
|
-
config_file: ConfigFile,
|
|
81
|
+
config_file: ConfigFile,
|
|
82
|
+
meta_type: MetaType,
|
|
83
|
+
document_source: Union[Path, str],
|
|
84
|
+
file_encoding: str,
|
|
85
|
+
overwrite: bool,
|
|
86
|
+
output_path: Optional[Path],
|
|
80
87
|
) -> "Config":
|
|
81
88
|
if config_file.post_hooks is not None:
|
|
82
89
|
post_hooks = config_file.post_hooks
|
|
@@ -104,5 +111,7 @@ class Config:
|
|
|
104
111
|
http_timeout=config_file.http_timeout,
|
|
105
112
|
document_source=document_source,
|
|
106
113
|
file_encoding=file_encoding,
|
|
114
|
+
overwrite=overwrite,
|
|
115
|
+
output_path=output_path,
|
|
107
116
|
)
|
|
108
117
|
return config
|
{openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/parser/bodies.py
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import sys
|
|
2
|
-
from typing import List, Tuple, Union
|
|
2
|
+
from typing import Dict, List, Tuple, Union
|
|
3
3
|
|
|
4
4
|
import attr
|
|
5
5
|
|
|
@@ -44,15 +44,19 @@ def body_from_data(
|
|
|
44
44
|
*,
|
|
45
45
|
data: oai.Operation,
|
|
46
46
|
schemas: Schemas,
|
|
47
|
+
request_bodies: Dict[str, Union[oai.RequestBody, oai.Reference]],
|
|
47
48
|
config: Config,
|
|
48
49
|
endpoint_name: str,
|
|
49
50
|
) -> Tuple[List[Union[Body, ParseError]], Schemas]:
|
|
50
51
|
"""Adds form or JSON body to Endpoint if included in data"""
|
|
51
|
-
|
|
52
|
+
body = _resolve_reference(data.request_body, request_bodies)
|
|
53
|
+
if isinstance(body, ParseError):
|
|
54
|
+
return [body], schemas
|
|
55
|
+
if body is None:
|
|
52
56
|
return [], schemas
|
|
53
57
|
|
|
54
58
|
bodies: List[Union[Body, ParseError]] = []
|
|
55
|
-
body_content =
|
|
59
|
+
body_content = body.content
|
|
56
60
|
prefix_type_names = len(body_content) > 1
|
|
57
61
|
|
|
58
62
|
for content_type, media_type in body_content.items():
|
|
@@ -61,7 +65,7 @@ def body_from_data(
|
|
|
61
65
|
bodies.append(
|
|
62
66
|
ParseError(
|
|
63
67
|
detail="Invalid content type",
|
|
64
|
-
data=
|
|
68
|
+
data=body,
|
|
65
69
|
level=ErrorLevel.WARNING,
|
|
66
70
|
)
|
|
67
71
|
)
|
|
@@ -71,7 +75,7 @@ def body_from_data(
|
|
|
71
75
|
bodies.append(
|
|
72
76
|
ParseError(
|
|
73
77
|
detail="Missing schema",
|
|
74
|
-
data=
|
|
78
|
+
data=body,
|
|
75
79
|
level=ErrorLevel.WARNING,
|
|
76
80
|
)
|
|
77
81
|
)
|
|
@@ -88,7 +92,7 @@ def body_from_data(
|
|
|
88
92
|
bodies.append(
|
|
89
93
|
ParseError(
|
|
90
94
|
detail=f"Unsupported content type {simplified_content_type}",
|
|
91
|
-
data=
|
|
95
|
+
data=body,
|
|
92
96
|
level=ErrorLevel.WARNING,
|
|
93
97
|
)
|
|
94
98
|
)
|
|
@@ -123,3 +127,19 @@ def body_from_data(
|
|
|
123
127
|
)
|
|
124
128
|
|
|
125
129
|
return bodies, schemas
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def _resolve_reference(
|
|
133
|
+
body: Union[oai.RequestBody, oai.Reference, None], request_bodies: Dict[str, Union[oai.RequestBody, oai.Reference]]
|
|
134
|
+
) -> Union[oai.RequestBody, ParseError, None]:
|
|
135
|
+
if body is None:
|
|
136
|
+
return None
|
|
137
|
+
references_seen = []
|
|
138
|
+
while isinstance(body, oai.Reference) and body.ref not in references_seen:
|
|
139
|
+
references_seen.append(body.ref)
|
|
140
|
+
body = request_bodies.get(body.ref.split("/")[-1])
|
|
141
|
+
if isinstance(body, oai.Reference):
|
|
142
|
+
return ParseError(detail="Circular $ref in request body", data=body)
|
|
143
|
+
if body is None and references_seen:
|
|
144
|
+
return ParseError(detail=f"Could not resolve $ref {references_seen[-1]} in request body")
|
|
145
|
+
return body
|
|
@@ -48,6 +48,7 @@ class EndpointCollection:
|
|
|
48
48
|
data: Dict[str, oai.PathItem],
|
|
49
49
|
schemas: Schemas,
|
|
50
50
|
parameters: Parameters,
|
|
51
|
+
request_bodies: Dict[str, Union[oai.RequestBody, oai.Reference]],
|
|
51
52
|
config: Config,
|
|
52
53
|
) -> Tuple[Dict[utils.PythonIdentifier, "EndpointCollection"], Schemas, Parameters]:
|
|
53
54
|
"""Parse the openapi paths data to get EndpointCollections by tag"""
|
|
@@ -69,6 +70,7 @@ class EndpointCollection:
|
|
|
69
70
|
tag=tag,
|
|
70
71
|
schemas=schemas,
|
|
71
72
|
parameters=parameters,
|
|
73
|
+
request_bodies=request_bodies,
|
|
72
74
|
config=config,
|
|
73
75
|
)
|
|
74
76
|
# Add `PathItem` parameters
|
|
@@ -392,6 +394,7 @@ class Endpoint:
|
|
|
392
394
|
tag: str,
|
|
393
395
|
schemas: Schemas,
|
|
394
396
|
parameters: Parameters,
|
|
397
|
+
request_bodies: Dict[str, Union[oai.RequestBody, oai.Reference]],
|
|
395
398
|
config: Config,
|
|
396
399
|
) -> Tuple[Union["Endpoint", ParseError], Schemas, Parameters]:
|
|
397
400
|
"""Construct an endpoint from the OpenAPI data"""
|
|
@@ -423,7 +426,9 @@ class Endpoint:
|
|
|
423
426
|
result, schemas = Endpoint._add_responses(endpoint=result, data=data.responses, schemas=schemas, config=config)
|
|
424
427
|
if isinstance(result, ParseError):
|
|
425
428
|
return result, schemas, parameters
|
|
426
|
-
bodies, schemas = body_from_data(
|
|
429
|
+
bodies, schemas = body_from_data(
|
|
430
|
+
data=data, schemas=schemas, config=config, endpoint_name=result.name, request_bodies=request_bodies
|
|
431
|
+
)
|
|
427
432
|
body_errors = []
|
|
428
433
|
for body in bodies:
|
|
429
434
|
if isinstance(body, ParseError):
|
|
@@ -507,8 +512,9 @@ class GeneratorData:
|
|
|
507
512
|
parameters=parameters,
|
|
508
513
|
config=config,
|
|
509
514
|
)
|
|
515
|
+
request_bodies = (openapi.components and openapi.components.requestBodies) or {}
|
|
510
516
|
endpoint_collections_by_tag, schemas, parameters = EndpointCollection.from_data(
|
|
511
|
-
data=openapi.paths, schemas=schemas, parameters=parameters, config=config
|
|
517
|
+
data=openapi.paths, schemas=schemas, parameters=parameters, request_bodies=request_bodies, config=config
|
|
512
518
|
)
|
|
513
519
|
|
|
514
520
|
enums = (prop for prop in schemas.classes_by_name.values() if isinstance(prop, EnumProperty))
|
|
@@ -60,7 +60,7 @@ if not isinstance({{ source }}, Unset):
|
|
|
60
60
|
{% else %}
|
|
61
61
|
{{ destination }}: {{ type_string }} = UNSET
|
|
62
62
|
if not isinstance({{ source }}, Unset):
|
|
63
|
-
{{ _transform(property, source, destination, True, "to_dict") | indent(4)}}
|
|
63
|
+
{{ _transform(property, source, destination, True, "to_dict") | indent(4)}}
|
|
64
64
|
{% endif %}
|
|
65
65
|
{% endmacro %}
|
|
66
66
|
|
|
@@ -3,7 +3,7 @@ authors = [
|
|
|
3
3
|
{ name = "Dylan Anthony", email = "contact@dylananthony.com" },
|
|
4
4
|
]
|
|
5
5
|
license = { text = "MIT" }
|
|
6
|
-
requires-python = ">=3.8,<4.0"
|
|
6
|
+
requires-python = ">=3.8.1,<4.0"
|
|
7
7
|
dependencies = [
|
|
8
8
|
"jinja2>=3.0.0,<4.0.0",
|
|
9
9
|
"typer>0.6,<0.13",
|
|
@@ -18,7 +18,7 @@ dependencies = [
|
|
|
18
18
|
"typing-extensions>=4.8.0,<5.0.0",
|
|
19
19
|
]
|
|
20
20
|
name = "openapi-python-client"
|
|
21
|
-
version = "0.
|
|
21
|
+
version = "0.21.1"
|
|
22
22
|
description = "Generate modern Python clients from OpenAPI"
|
|
23
23
|
keywords = [
|
|
24
24
|
"OpenAPI",
|
|
@@ -84,20 +84,19 @@ ignore_missing_imports = true
|
|
|
84
84
|
[tool.pytest.ini_options]
|
|
85
85
|
junit_family = "xunit2"
|
|
86
86
|
|
|
87
|
-
|
|
88
87
|
[tool.pdm.dev-dependencies]
|
|
89
88
|
dev = [
|
|
90
89
|
"pytest",
|
|
91
90
|
"pytest-mock",
|
|
92
91
|
"mypy",
|
|
93
92
|
"taskipy",
|
|
94
|
-
"safety",
|
|
95
93
|
"pytest-cov",
|
|
96
94
|
"python-multipart",
|
|
97
95
|
"types-PyYAML<7.0.0,>=6.0.3",
|
|
98
96
|
"types-certifi<2021.10.9,>=2020.0.0",
|
|
99
97
|
"types-python-dateutil<3.0.0,>=2.0.0",
|
|
100
98
|
"ruamel-yaml-string>=0.1.1",
|
|
99
|
+
"syrupy>=4",
|
|
101
100
|
]
|
|
102
101
|
|
|
103
102
|
[tool.pdm.build]
|
|
@@ -110,9 +109,8 @@ includes = [
|
|
|
110
109
|
[tool.pdm.scripts]
|
|
111
110
|
lint = "ruff check --fix ."
|
|
112
111
|
format = "ruff format ."
|
|
113
|
-
safety_check = { shell = "pdm export -o requirements.txt && safety check -r requirements.txt --bare && rm requirements.txt" }
|
|
114
112
|
mypy = "mypy openapi_python_client"
|
|
115
|
-
check = { composite = ["lint", "format", "
|
|
113
|
+
check = { composite = ["lint", "format", "mypy", "test"] }
|
|
116
114
|
regen = {composite = ["regen_e2e", "regen_integration"]}
|
|
117
115
|
e2e = "pytest openapi_python_client end_to_end_tests/test_end_to_end.py"
|
|
118
116
|
re = {composite = ["regen_e2e", "e2e"]}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/__main__.py
RENAMED
|
File without changes
|
|
File without changes
|
{openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/parser/errors.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/py.typed
RENAMED
|
File without changes
|
{openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/schema/3.0.3.md
RENAMED
|
File without changes
|
{openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/schema/3.1.0.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openapi_python_client-0.20.0 → openapi_python_client-0.21.1}/openapi_python_client/utils.py
RENAMED
|
File without changes
|