openapi-python-client 0.5.3__tar.gz → 0.5.4__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.
Files changed (71) hide show
  1. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/CHANGELOG.md +8 -0
  2. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/PKG-INFO +1 -1
  3. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/parser/openapi.py +1 -0
  4. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/parser/properties.py +35 -19
  5. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/parser/responses.py +42 -0
  6. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/schema/schema.py +3 -3
  7. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/pyproject.toml +1 -1
  8. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/setup.py +1 -1
  9. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/LICENSE +0 -0
  10. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/README.md +0 -0
  11. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/__init__.py +0 -0
  12. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/__main__.py +0 -0
  13. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/cli.py +0 -0
  14. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/config.py +0 -0
  15. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/parser/__init__.py +0 -0
  16. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/parser/errors.py +0 -0
  17. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/parser/reference.py +0 -0
  18. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/py.typed +0 -0
  19. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/schema/LICENSE +0 -0
  20. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/schema/README.md +0 -0
  21. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/schema/__init__.py +0 -0
  22. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/schema/components.py +0 -0
  23. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/schema/contact.py +0 -0
  24. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/schema/discriminator.py +0 -0
  25. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/schema/encoding.py +0 -0
  26. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/schema/example.py +0 -0
  27. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/schema/external_documentation.py +0 -0
  28. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/schema/header.py +0 -0
  29. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/schema/info.py +0 -0
  30. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/schema/license.py +0 -0
  31. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/schema/link.py +0 -0
  32. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/schema/media_type.py +0 -0
  33. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/schema/oauth_flow.py +0 -0
  34. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/schema/oauth_flows.py +0 -0
  35. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/schema/open_api.py +0 -0
  36. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/schema/operation.py +0 -0
  37. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/schema/parameter.py +0 -0
  38. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/schema/path_item.py +0 -0
  39. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/schema/paths.py +0 -0
  40. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/schema/reference.py +0 -0
  41. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/schema/request_body.py +0 -0
  42. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/schema/response.py +0 -0
  43. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/schema/responses.py +0 -0
  44. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/schema/security_requirement.py +0 -0
  45. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/schema/security_scheme.py +0 -0
  46. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/schema/server.py +0 -0
  47. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/schema/server_variable.py +0 -0
  48. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/schema/tag.py +0 -0
  49. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/schema/xml.py +0 -0
  50. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/templates/.gitignore +0 -0
  51. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/templates/README.md +0 -0
  52. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/templates/async_endpoint_module.pyi +0 -0
  53. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/templates/client.pyi +0 -0
  54. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/templates/endpoint_macros.pyi +0 -0
  55. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/templates/endpoint_module.pyi +0 -0
  56. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/templates/enum.pyi +0 -0
  57. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/templates/errors.pyi +0 -0
  58. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/templates/model.pyi +0 -0
  59. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/templates/models_init.pyi +0 -0
  60. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/templates/package_init.pyi +0 -0
  61. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/templates/property_templates/date_property.pyi +0 -0
  62. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/templates/property_templates/datetime_property.pyi +0 -0
  63. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/templates/property_templates/dict_property.pyi +0 -0
  64. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/templates/property_templates/enum_property.pyi +0 -0
  65. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/templates/property_templates/file_property.pyi +0 -0
  66. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/templates/property_templates/list_property.pyi +0 -0
  67. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/templates/property_templates/ref_property.pyi +0 -0
  68. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/templates/property_templates/union_property.pyi +0 -0
  69. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/templates/pyproject.toml +0 -0
  70. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/templates/types.py +0 -0
  71. {openapi-python-client-0.5.3 → openapi-python-client-0.5.4}/openapi_python_client/utils.py +0 -0
@@ -5,6 +5,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5
5
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
7
 
8
+ ## 0.5.4 - 2020-08-29
9
+ ### Additions
10
+ - Support for octet-stream content type (#116)
11
+ - Support for [nullable](https://swagger.io/docs/specification/data-models/data-types/#null) (#99)
12
+ - Union properties can be defined using oneOf (#98)
13
+ - Support for lists of strings, integers, floats and booleans as responses (#165). Thanks @Maistho!
14
+
15
+
8
16
  ## 0.5.3 - 2020-08-13
9
17
  ### Security
10
18
  - All values that become file/directory names are sanitized to address path traversal vulnerabilities (CVE-2020-15141)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: openapi-python-client
3
- Version: 0.5.3
3
+ Version: 0.5.4
4
4
  Summary: Generate modern Python clients from OpenAPI
5
5
  Home-page: https://github.com/triaxtec/openapi-python-client
6
6
  License: MIT
@@ -273,6 +273,7 @@ class Schemas:
273
273
  required=True,
274
274
  default=data.default,
275
275
  values=EnumProperty.values_from_list(data.enum),
276
+ nullable=data.nullable,
276
277
  )
277
278
  continue
278
279
  s = Model.from_data(data=data, name=name)
@@ -2,6 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  from dataclasses import InitVar, dataclass, field
4
4
  from datetime import date, datetime
5
+ from itertools import chain
5
6
  from typing import Any, ClassVar, Dict, Generic, List, Optional, Set, TypeVar, Union
6
7
 
7
8
  from .. import schema as oai
@@ -27,6 +28,7 @@ class Property:
27
28
 
28
29
  name: str
29
30
  required: bool
31
+ nullable: bool
30
32
  default: Optional[Any]
31
33
 
32
34
  template: ClassVar[Optional[str]] = None
@@ -44,8 +46,13 @@ class Property:
44
46
  raise ValidationError
45
47
 
46
48
  def get_type_string(self, no_optional: bool = False) -> str:
47
- """ Get a string representation of type that should be used when declaring this property """
48
- if self.required or no_optional:
49
+ """
50
+ Get a string representation of type that should be used when declaring this property
51
+
52
+ Args:
53
+ no_optional: Do not include Optional even if the value is optional (needed for isinstance checks)
54
+ """
55
+ if no_optional or (self.required and not self.nullable):
49
56
  return self._type_string
50
57
  return f"Optional[{self._type_string}]"
51
58
 
@@ -212,7 +219,7 @@ class ListProperty(Property, Generic[InnerProp]):
212
219
 
213
220
  def get_type_string(self, no_optional: bool = False) -> str:
214
221
  """ Get a string representation of type that should be used when declaring this property """
215
- if self.required or no_optional:
222
+ if no_optional or (self.required and not self.nullable):
216
223
  return f"List[{self.inner_property.get_type_string()}]"
217
224
  return f"Optional[List[{self.inner_property.get_type_string()}]]"
218
225
 
@@ -253,7 +260,7 @@ class UnionProperty(Property):
253
260
  """ Get a string representation of type that should be used when declaring this property """
254
261
  inner_types = [p.get_type_string() for p in self.inner_properties]
255
262
  inner_prop_string = ", ".join(inner_types)
256
- if self.required or no_optional:
263
+ if no_optional or (self.required and not self.nullable):
257
264
  return f"Union[{inner_prop_string}]"
258
265
  return f"Optional[Union[{inner_prop_string}]]"
259
266
 
@@ -320,7 +327,7 @@ class EnumProperty(Property):
320
327
  def get_type_string(self, no_optional: bool = False) -> str:
321
328
  """ Get a string representation of type that should be used when declaring this property """
322
329
 
323
- if self.required or no_optional:
330
+ if no_optional or (self.required and not self.nullable):
324
331
  return self.reference.class_name
325
332
  return f"Optional[{self.reference.class_name}]"
326
333
 
@@ -375,7 +382,7 @@ class RefProperty(Property):
375
382
 
376
383
  def get_type_string(self, no_optional: bool = False) -> str:
377
384
  """ Get a string representation of type that should be used when declaring this property """
378
- if self.required or no_optional:
385
+ if no_optional or (self.required and not self.nullable):
379
386
  return self.reference.class_name
380
387
  return f"Optional[{self.reference.class_name}]"
381
388
 
@@ -437,13 +444,15 @@ def _string_based_property(
437
444
  """ Construct a Property from the type "string" """
438
445
  string_format = data.schema_format
439
446
  if string_format == "date-time":
440
- return DateTimeProperty(name=name, required=required, default=data.default)
447
+ return DateTimeProperty(name=name, required=required, default=data.default, nullable=data.nullable,)
441
448
  elif string_format == "date":
442
- return DateProperty(name=name, required=required, default=data.default)
449
+ return DateProperty(name=name, required=required, default=data.default, nullable=data.nullable,)
443
450
  elif string_format == "binary":
444
- return FileProperty(name=name, required=required, default=data.default)
451
+ return FileProperty(name=name, required=required, default=data.default, nullable=data.nullable,)
445
452
  else:
446
- return StringProperty(name=name, default=data.default, required=required, pattern=data.pattern)
453
+ return StringProperty(
454
+ name=name, default=data.default, required=required, pattern=data.pattern, nullable=data.nullable,
455
+ )
447
456
 
448
457
 
449
458
  def _property_from_data(
@@ -452,7 +461,9 @@ def _property_from_data(
452
461
  """ Generate a Property from the OpenAPI dictionary representation of it """
453
462
  name = utils.remove_string_escapes(name)
454
463
  if isinstance(data, oai.Reference):
455
- return RefProperty(name=name, required=required, reference=Reference.from_ref(data.ref), default=None)
464
+ return RefProperty(
465
+ name=name, required=required, reference=Reference.from_ref(data.ref), default=None, nullable=False,
466
+ )
456
467
  if data.enum:
457
468
  return EnumProperty(
458
469
  name=name,
@@ -460,34 +471,39 @@ def _property_from_data(
460
471
  values=EnumProperty.values_from_list(data.enum),
461
472
  title=data.title or name,
462
473
  default=data.default,
474
+ nullable=data.nullable,
463
475
  )
464
- if data.anyOf:
476
+ if data.anyOf or data.oneOf:
465
477
  sub_properties: List[Property] = []
466
- for sub_prop_data in data.anyOf:
478
+ for sub_prop_data in chain(data.anyOf, data.oneOf):
467
479
  sub_prop = property_from_data(name=name, required=required, data=sub_prop_data)
468
480
  if isinstance(sub_prop, PropertyError):
469
481
  return PropertyError(detail=f"Invalid property in union {name}", data=sub_prop_data)
470
482
  sub_properties.append(sub_prop)
471
- return UnionProperty(name=name, required=required, default=data.default, inner_properties=sub_properties)
483
+ return UnionProperty(
484
+ name=name, required=required, default=data.default, inner_properties=sub_properties, nullable=data.nullable,
485
+ )
472
486
  if not data.type:
473
487
  return PropertyError(data=data, detail="Schemas must either have one of enum, anyOf, or type defined.")
474
488
  if data.type == "string":
475
489
  return _string_based_property(name=name, required=required, data=data)
476
490
  elif data.type == "number":
477
- return FloatProperty(name=name, default=data.default, required=required)
491
+ return FloatProperty(name=name, default=data.default, required=required, nullable=data.nullable,)
478
492
  elif data.type == "integer":
479
- return IntProperty(name=name, default=data.default, required=required)
493
+ return IntProperty(name=name, default=data.default, required=required, nullable=data.nullable,)
480
494
  elif data.type == "boolean":
481
- return BooleanProperty(name=name, required=required, default=data.default)
495
+ return BooleanProperty(name=name, required=required, default=data.default, nullable=data.nullable,)
482
496
  elif data.type == "array":
483
497
  if data.items is None:
484
498
  return PropertyError(data=data, detail="type array must have items defined")
485
499
  inner_prop = property_from_data(name=f"{name}_item", required=True, data=data.items)
486
500
  if isinstance(inner_prop, PropertyError):
487
501
  return PropertyError(data=inner_prop.data, detail=f"invalid data in items of array {name}")
488
- return ListProperty(name=name, required=required, default=data.default, inner_property=inner_prop,)
502
+ return ListProperty(
503
+ name=name, required=required, default=data.default, inner_property=inner_prop, nullable=data.nullable,
504
+ )
489
505
  elif data.type == "object":
490
- return DictProperty(name=name, required=required, default=data.default)
506
+ return DictProperty(name=name, required=required, default=data.default, nullable=data.nullable,)
491
507
  return PropertyError(data=data, detail=f"unknown type {data.type}")
492
508
 
493
509
 
@@ -51,6 +51,25 @@ class RefResponse(Response):
51
51
  return f"{self.reference.class_name}.from_dict(cast(Dict[str, Any], response.json()))"
52
52
 
53
53
 
54
+ @dataclass
55
+ class ListBasicResponse(Response):
56
+ """ Response is a list of some basic type """
57
+
58
+ openapi_type: InitVar[str]
59
+ python_type: str = field(init=False)
60
+
61
+ def __post_init__(self, openapi_type: str) -> None:
62
+ self.python_type = openapi_types_to_python_type_strings[openapi_type]
63
+
64
+ def return_string(self) -> str:
65
+ """ How this Response should be represented as a return type """
66
+ return f"List[{self.python_type}]"
67
+
68
+ def constructor(self) -> str:
69
+ """ How the return value of this response should be constructed """
70
+ return f"[{self.python_type}(item) for item in cast(List[{self.python_type}], response.json())]"
71
+
72
+
54
73
  @dataclass
55
74
  class BasicResponse(Response):
56
75
  """ Response is a basic type """
@@ -70,6 +89,21 @@ class BasicResponse(Response):
70
89
  return f"{self.python_type}(response.text)"
71
90
 
72
91
 
92
+ @dataclass
93
+ class BytesResponse(Response):
94
+ """ Response is a basic type """
95
+
96
+ python_type: str = "bytes"
97
+
98
+ def return_string(self) -> str:
99
+ """ How this Response should be represented as a return type """
100
+ return self.python_type
101
+
102
+ def constructor(self) -> str:
103
+ """ How the return value of this response should be constructed """
104
+ return f"{self.python_type}(response.content)"
105
+
106
+
73
107
  openapi_types_to_python_type_strings = {
74
108
  "string": "str",
75
109
  "number": "float",
@@ -88,6 +122,8 @@ def response_from_data(*, status_code: int, data: Union[oai.Response, oai.Refere
88
122
  schema_data = None
89
123
  if "application/json" in content:
90
124
  schema_data = data.content["application/json"].media_type_schema
125
+ elif "application/octet-stream" in content:
126
+ return BytesResponse(status_code=status_code)
91
127
  elif "text/html" in content:
92
128
  schema_data = data.content["text/html"].media_type_schema
93
129
 
@@ -101,6 +137,12 @@ def response_from_data(*, status_code: int, data: Union[oai.Response, oai.Refere
101
137
  return Response(status_code=status_code)
102
138
  if response_type == "array" and isinstance(schema_data.items, oai.Reference):
103
139
  return ListRefResponse(status_code=status_code, reference=Reference.from_ref(schema_data.items.ref),)
140
+ if (
141
+ response_type == "array"
142
+ and isinstance(schema_data.items, oai.Schema)
143
+ and schema_data.items.type in openapi_types_to_python_type_strings
144
+ ):
145
+ return ListBasicResponse(status_code=status_code, openapi_type=schema_data.items.type)
104
146
  if response_type in openapi_types_to_python_type_strings:
105
147
  return BasicResponse(status_code=status_code, openapi_type=response_type)
106
148
  return ParseError(data=data, detail=f"Unrecognized type {schema_data.type}")
@@ -241,7 +241,7 @@ class Schema(BaseModel):
241
241
  value.
242
242
  """
243
243
 
244
- oneOf: Optional[List[Union[Reference, "Schema"]]] = None
244
+ oneOf: List[Union[Reference, "Schema"]] = []
245
245
  """
246
246
  **From OpenAPI spec:
247
247
  Inline or referenced schema MUST be of a [Schema Object](#schemaObject) and not a standard JSON Schema.**
@@ -258,7 +258,7 @@ class Schema(BaseModel):
258
258
  keyword's value.
259
259
  """
260
260
 
261
- anyOf: Optional[List[Union[Reference, "Schema"]]] = None
261
+ anyOf: List[Union[Reference, "Schema"]] = []
262
262
  """
263
263
  **From OpenAPI spec:
264
264
  Inline or referenced schema MUST be of a [Schema Object](#schemaObject) and not a standard JSON Schema.**
@@ -406,7 +406,7 @@ class Schema(BaseModel):
406
406
  Other than the JSON Schema subset fields, the following fields MAY be used for further schema documentation:
407
407
  """
408
408
 
409
- nullable: Optional[bool] = None
409
+ nullable: bool = False
410
410
  """
411
411
  A `true` value adds `"null"` to the allowed type specified by the `type` keyword,
412
412
  only if `type` is explicitly defined within the same Schema Object.
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "openapi-python-client"
3
- version = "0.5.3"
3
+ version = "0.5.4"
4
4
  description = "Generate modern Python clients from OpenAPI"
5
5
  repository = "https://github.com/triaxtec/openapi-python-client"
6
6
  license = "MIT"
@@ -30,7 +30,7 @@ entry_points = \
30
30
 
31
31
  setup_kwargs = {
32
32
  'name': 'openapi-python-client',
33
- 'version': '0.5.3',
33
+ 'version': '0.5.4',
34
34
  'description': 'Generate modern Python clients from OpenAPI',
35
35
  'long_description': '[![triaxtec](https://circleci.com/gh/triaxtec/openapi-python-client.svg?style=svg)](https://circleci.com/gh/triaxtec/openapi-python-client)\n[![codecov](https://codecov.io/gh/triaxtec/openapi-python-client/branch/master/graph/badge.svg)](https://codecov.io/gh/triaxtec/openapi-python-client)\n[![PyPI version shields.io](https://img.shields.io/pypi/v/openapi-python-client.svg)](https://pypi.python.org/pypi/openapi-python-client/)\n[![MIT license](https://img.shields.io/badge/License-MIT-blue.svg)](https://lbesson.mit-license.org/)\n[![Generic badge](https://img.shields.io/badge/type_checked-mypy-informational.svg)](https://mypy.readthedocs.io/en/stable/introduction.html)\n[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/ambv/black)\n\n\n# openapi-python-client\nGenerate modern Python clients from OpenAPI\n\n**This project is still in development and does not support all OpenAPI features**\n\n## Why This?\nThe Python clients generated by openapi-generator support Python 2 and therefore come with a lot of baggage. This tool \naims to generate clients which:\n1. Use all the latest and greatest Python features like type annotations and dataclasses\n1. Don\'t carry around a bunch of compatibility code for older version of Python (e.g. the `six` package)\n1. Have better documentation and more obvious usage instructions\n\nAdditionally, because this generator is written in Python, it should be more accessible to contribution by the people \nusing it (Python developers).\n\n## Installation\nI recommend you install with [pipx](https://pipxproject.github.io/pipx/) so you don\'t conflict with any other packages \nyou might have: `pipx install openapi-python-client`.\n\nBetter yet, use `pipx run openapi-python-client <normal params / options>` to always use the latest version of the generator.\n\nYou can install with normal pip if you want to though: `pip install openapi-python-client`\n\nThen, if you want tab completion: `openapi-python-client --install-completion`\n\n## Usage\n### Create a new client\n`openapi-python-client generate --url https://my.api.com/openapi.json`\n\nThis will generate a new client library named based on the title in your OpenAPI spec. For example, if the title \nof your API is "My API", the expected output will be "my-api-client". If a folder already exists by that name, you\'ll \nget an error.\n\n### Update an existing client\n`openapi-python-client update --url https://my.api.com/openapi.json`\n\n> For more usage details run `openapi-python-client --help` or read [usage](usage.md)\n\n## What You Get\n1. A `pyproject.toml` file with some basic metadata intended to be used with [Poetry].\n1. A `README.md` you\'ll most definitely need to update with your project\'s details\n1. A Python module named just like the auto-generated project name (e.g. "my_api_client") which contains:\n 1. A `client` module which will have both a `Client` class and an `AuthenticatedClient` class. You\'ll need these \n for calling the functions in the `api` module.\n 1. An `api` module which will contain one module for each tag in your OpenAPI spec, as well as a `default` module \n for endpoints without a tag. Each of these modules in turn contains one function for calling each endpoint.\n 1. A `models` module which has all the classes defined by the various schemas in your OpenAPI spec\n \nFor a full example you can look at the `test_end_to_end` directory which has a declared [FastAPI](https://fastapi.tiangolo.com/) \nserver and the resulting openapi.json file in the "fastapi" directory. "golden-master" is the generated client from that \nOpenAPI document.\n \n## OpenAPI features supported\n1. All HTTP Methods\n1. JSON and form bodies, path and query parameters\n1. File uploads with multipart/form-data bodies\n1. float, string, int, date, datetime, string enums, and custom schemas or lists containing any of those\n1. html/text or application/json responses containing any of the previous types\n1. Bearer token security\n\n## Configuration\nYou can pass a YAML (or JSON) file to openapi-python-client with the `--config` option in order to change some behavior.\nThe following parameters are supported:\n\n### class_overrides\nUsed to change the name of generated model classes. This param should be a mapping of existing class name \n(usually a key in the "schemas" section of your OpenAPI document) to class_name and module_name. As an example, if the \nname of the a model in OpenAPI (and therefore the generated class name) was something like "_PrivateInternalLongName" \nand you want the generated client\'s model to be called "ShortName" in a module called "short_name" you could do this:\n\nExample:\n```yaml\nclass_overrides:\n _PrivateInternalLongName:\n class_name: ShortName\n module_name: short_name\n```\n\nThe easiest way to find what needs to be overridden is probably to generate your client and go look at everything in the\n models folder.\n \n ### project_name_override and package_name_override\nUsed to change the name of generated client library project/package. If the project name is changed but an override for the package name\nisn\'t provided, the package name will be converted from the project name using the standard convention (replacing `-`\'s with `_`\'s).\n\nExample:\n```yaml\nproject_name_override: my-special-project-name\npackage_name_override: my_extra_special_package_name\n```\n\n\n[CHANGELOG.md]: CHANGELOG.md\n[Poetry]: https://python-poetry.org/\n',
36
36
  'author': 'Dylan Anthony',