Skip to content

Commit e35b31a

Browse files
committed
Merge branch 'main' of github.com:openapi-generators/openapi-python-client into issue1123-merge-model
2 parents 5cd16ac + 40d63f9 commit e35b31a

File tree

129 files changed

+3933
-455
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

129 files changed

+3933
-455
lines changed

.changeset/fix-model-override.md

+46-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,50 @@ default: patch
44

55
# Fix overriding of object property class
66

7-
Fixed issue #1123, in which a property could end up with the wrong type when combining two object schemas with `allOf`, if the type of the property was itself an object but had a different schema in each. Previously, if the property's type was A in the first schema and B in the second, the resulting schema would use type A for the property.
7+
Fixed issue #1123, in which a property could end up with the wrong type when combining two object schemas with `allOf`, if the type of the property was itself an object but had a different schema in each. Example:
88

9-
The new behavior is, that the generator will test whether one of the types A/B is derived from the other. "Derived" here means that the result of `allOf[A, B]` would be exactly identical to B. If so, it will use the class name of B. If not, it will attempt to merge A and B with the usual `allOf` logic to create a new inline schema.
9+
```yaml
10+
ModelA:
11+
properties:
12+
status:
13+
type: string
14+
result:
15+
- $ref: "#/components/schemas/BaseResult"
16+
17+
ModelB:
18+
allOf:
19+
- $ref: "#/components/schemas/ModelA"
20+
- properties:
21+
result:
22+
- $ref: "#/components/schemas/ExtendedResult"
23+
24+
ModelC:
25+
allOf:
26+
- $ref: "#/components/schemas/ModelA"
27+
- properties:
28+
result:
29+
- $ref: "#/components/schemas/UnrelatedResult"
30+
31+
BaseResult:
32+
properties:
33+
prop1:
34+
type: string
35+
36+
ExtendedResult:
37+
allOf:
38+
- $ref: "#/components/schemas/BaseResult"
39+
- properties:
40+
prop2:
41+
type: string
42+
43+
UnrelatedResult:
44+
properties:
45+
prop3:
46+
type: string
47+
```
48+
49+
Previously, in the generated classes for both `ModelB` and `ModelC`, the type of `result` was being incorrectly set to `BaseResult`.
50+
51+
The new behavior is, when computing `allOf: [A, B]` where `A` and `B` are both objects, any property `P` whose name exists in both schemas will have a schema equivalent to `allOf: [A.P, B.P]`. This is consistent with the basic definition of `allOf`.
52+
53+
When translating this into Python code, the generator will use a type that correctly describes the combined schema for the property. If the combined schema is exactly equal in shape to either `A.P` or `B.P` (implying that one was already derived from the other using `allOf`) then it will reuse the corresponding Python class. Otherwise it will create a new class, just as it would for an inline schema that used `allOf`. Therefore in the example above, the type of `ModelB.result` is `ExtendedResult`, but the type of `ModelC.result` is a new class called `ModelCResult` that includes all the properties from `BaseResult` and `UnrelatedResult`.

.github/workflows/checks.yml

+8-8
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ jobs:
1111
test:
1212
strategy:
1313
matrix:
14-
python: [ "3.8", "3.9", "3.10", "3.11", "3.12" ]
14+
python: [ "3.8", "3.9", "3.10", "3.11", "3.12", "3.13" ]
1515
os: [ ubuntu-latest, macos-latest, windows-latest ]
1616
runs-on: ${{ matrix.os }}
1717
steps:
18-
- uses: actions/checkout@v4.1.7
18+
- uses: actions/checkout@v4.2.2
1919
- name: Set up Python
20-
uses: actions/setup-python@v5.2.0
20+
uses: actions/setup-python@v5.3.0
2121
with:
2222
python-version: ${{ matrix.python }}
2323

@@ -64,7 +64,7 @@ jobs:
6464
if: matrix.os == 'ubuntu-latest'
6565

6666
- name: Store coverage report
67-
uses: actions/[email protected].0
67+
uses: actions/[email protected].3
6868
if: matrix.os == 'ubuntu-latest'
6969
with:
7070
name: coverage-${{ matrix.python }}
@@ -77,7 +77,7 @@ jobs:
7777
needs: test
7878
runs-on: ubuntu-latest
7979
steps:
80-
- uses: actions/checkout@v4.1.7
80+
- uses: actions/checkout@v4.2.2
8181
- uses: actions/setup-python@v5
8282
with:
8383
python-version: "3.12"
@@ -107,7 +107,7 @@ jobs:
107107
.venv/bin/python -m coverage report --fail-under=100
108108
109109
- name: Upload HTML report if check failed.
110-
uses: actions/[email protected].0
110+
uses: actions/[email protected].3
111111
with:
112112
name: html-report
113113
path: htmlcov
@@ -127,9 +127,9 @@ jobs:
127127
ports:
128128
- "3000:3000"
129129
steps:
130-
- uses: actions/checkout@v4.1.7
130+
- uses: actions/checkout@v4.2.2
131131
- name: Set up Python
132-
uses: actions/setup-python@v5.2.0
132+
uses: actions/setup-python@v5.3.0
133133
with:
134134
python-version: "3.8"
135135
- name: Get Python Version

.github/workflows/release.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ jobs:
1212
permissions:
1313
id-token: write
1414
steps:
15-
- uses: actions/checkout@v4.1.7
15+
- uses: actions/checkout@v4.2.2
1616
- name: Install Hatchling
1717
run: pip install --upgrade hatchling
1818
- name: Build
1919
run: hatchling build
2020
- name: Push to PyPI
21-
uses: pypa/[email protected].1
21+
uses: pypa/[email protected].3
2222
with:
2323
attestations: true

CHANGELOG.md

+33
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,39 @@ Programmatic usage of this project (e.g., importing it as a Python module) and t
1313

1414
The 0.x prefix used in versions for this project is to indicate that breaking changes are expected frequently (several times a year). Breaking changes will increment the minor number, all other changes will increment the patch number. You can track the progress toward 1.0 [here](https://github.com/openapi-generators/openapi-python-client/projects/2).
1515

16+
## 0.21.6 (2024-10-20)
17+
18+
### Features
19+
20+
- update Ruff to >=0.2,<0.8 (#1137)
21+
- Add UUID string format. Thanks @estyrke! (#1140)
22+
- Support OpenAPI 3.1 prefixItems property for arrays. Thanks @estyrke! (#1141)
23+
24+
#### Add `literal_enums` config setting
25+
26+
Instead of the default `Enum` classes for enums, you can now generate `Literal` sets wherever `enum` appears in the OpenAPI spec by setting `literal_enums: true` in your config file.
27+
28+
```yaml
29+
literal_enums: true
30+
```
31+
32+
Thanks to @emosenkis for PR #1114 closes #587, #725, #1076, and probably many more.
33+
Thanks also to @eli-bl, @expobrain, @theorm, @chrisguillory, and anyone else who helped getting to this design!
34+
35+
### Fixes
36+
37+
- Typo in docstring (#1128)
38+
39+
#### Use literal value instead of `HTTPStatus` enum when checking response statuses
40+
41+
Python 3.13 renamed some of the `HTTPStatus` enum members, which means clients generated with Python 3.13 may not work
42+
with older versions of Python. This change stops using the `HTTPStatus` enum directly when checking response statuses.
43+
44+
Statuses will still be checked for validity at generation time, and transformed into `HTTPStatus` _after_ being checked
45+
at runtime.
46+
47+
This may cause some linters to complain.
48+
1649
## 0.21.5 (2024-09-07)
1750

1851
### Features

README.md

+11
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,17 @@ class_overrides:
9797
9898
The easiest way to find what needs to be overridden is probably to generate your client and go look at everything in the `models` folder.
9999

100+
### literal_enums
101+
102+
By default, `openapi-python-client` generates classes inheriting for `Enum` for enums. It can instead use `Literal`
103+
values for enums by setting this to `true`:
104+
105+
```yaml
106+
literal_enums: true
107+
```
108+
109+
This is especially useful if enum values, when transformed to their Python names, end up conflicting due to case sensitivity or special symbols.
110+
100111
### project_name_override and package_name_override
101112

102113
Used to change the name of generated client library project/package. If the project name is changed but an override for the package name

end_to_end_tests/3.1_specific.openapi.yaml

+31
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,34 @@ paths:
4747
"application/json":
4848
schema:
4949
const: "Why have a fixed response? I dunno"
50+
"/prefixItems":
51+
post:
52+
tags: [ "prefixItems" ]
53+
requestBody:
54+
required: true
55+
content:
56+
"application/json":
57+
schema:
58+
type: object
59+
properties:
60+
prefixItemsAndItems:
61+
type: array
62+
prefixItems:
63+
- type: string
64+
const: "prefix"
65+
- type: string
66+
items:
67+
type: number
68+
prefixItemsOnly:
69+
type: array
70+
prefixItems:
71+
- type: string
72+
- type: number
73+
maxItems: 2
74+
responses:
75+
"200":
76+
description: "Successful Response"
77+
content:
78+
"application/json":
79+
schema:
80+
type: string

end_to_end_tests/__snapshots__/test_end_to_end.ambr

+20-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,25 @@
99
Circular $ref in request body
1010

1111

12+
If you believe this was a mistake or this tool is missing a feature you need, please open an issue at https://github.com/openapi-generators/openapi-python-client/issues/new/choose
13+
14+
'''
15+
# ---
16+
# name: test_documents_with_errors[invalid-uuid-defaults]
17+
'''
18+
Generating /test-documents-with-errors
19+
Warning(s) encountered while generating. Client was generated, but some pieces may be missing
20+
21+
WARNING parsing PUT / within default. Endpoint will not be generated.
22+
23+
cannot parse parameter of endpoint put_: Invalid UUID value: 3
24+
25+
26+
WARNING parsing POST / within default. Endpoint will not be generated.
27+
28+
cannot parse parameter of endpoint post_: Invalid UUID value: notauuid
29+
30+
1231
If you believe this was a mistake or this tool is missing a feature you need, please open an issue at https://github.com/openapi-generators/openapi-python-client/issues/new/choose
1332

1433
'''
@@ -36,7 +55,7 @@
3655

3756
Path parameter must be required
3857

39-
Parameter(name='optional', param_in=<ParameterLocation.PATH: 'path'>, description=None, required=False, deprecated=False, allowEmptyValue=False, style=None, explode=False, allowReserved=False, param_schema=Schema(title=None, multipleOf=None, maximum=None, exclusiveMaximum=None, minimum=None, exclusiveMinimum=None, maxLength=None, minLength=None, pattern=None, maxItems=None, minItems=None, uniqueItems=None, maxProperties=None, minProperties=None, required=None, enum=None, const=None, type=<DataType.STRING: 'string'>, allOf=[], oneOf=[], anyOf=[], schema_not=None, items=None, properties=None, additionalProperties=None, description=None, schema_format=None, default=None, nullable=False, discriminator=None, readOnly=None, writeOnly=None, xml=None, externalDocs=None, example=None, deprecated=None), example=None, examples=None, content=None)
58+
Parameter(name='optional', param_in=<ParameterLocation.PATH: 'path'>, description=None, required=False, deprecated=False, allowEmptyValue=False, style=None, explode=False, allowReserved=False, param_schema=Schema(title=None, multipleOf=None, maximum=None, exclusiveMaximum=None, minimum=None, exclusiveMinimum=None, maxLength=None, minLength=None, pattern=None, maxItems=None, minItems=None, uniqueItems=None, maxProperties=None, minProperties=None, required=None, enum=None, const=None, type=<DataType.STRING: 'string'>, allOf=[], oneOf=[], anyOf=[], schema_not=None, items=None, prefixItems=[], properties=None, additionalProperties=None, description=None, schema_format=None, default=None, nullable=False, discriminator=None, readOnly=None, writeOnly=None, xml=None, externalDocs=None, example=None, deprecated=None), example=None, examples=None, content=None)
4059

4160
If you believe this was a mistake or this tool is missing a feature you need, please open an issue at https://github.com/openapi-generators/openapi-python-client/issues/new/choose
4261

end_to_end_tests/baseline_openapi_3.0.json

+60
Original file line numberDiff line numberDiff line change
@@ -1666,6 +1666,47 @@
16661666
}
16671667
}
16681668
}
1669+
},
1670+
"/models/oneof-with-required-const": {
1671+
"get": {
1672+
"responses": {
1673+
"200": {
1674+
"description": "OK",
1675+
"content": {
1676+
"application/json": {
1677+
"schema": {
1678+
"oneOf": [
1679+
{
1680+
"type": "object",
1681+
"properties": {
1682+
"type": {
1683+
"const": "alpha"
1684+
},
1685+
"color": {
1686+
"type": "string"
1687+
}
1688+
},
1689+
"required": ["type"]
1690+
},
1691+
{
1692+
"type": "object",
1693+
"properties": {
1694+
"type": {
1695+
"const": "beta"
1696+
},
1697+
"texture": {
1698+
"type": "string"
1699+
}
1700+
},
1701+
"required": ["type"]
1702+
}
1703+
]
1704+
}
1705+
}
1706+
}
1707+
}
1708+
}
1709+
}
16691710
}
16701711
},
16711712
"components": {
@@ -1714,6 +1755,8 @@
17141755
"aCamelDateTime",
17151756
"a_date",
17161757
"a_nullable_date",
1758+
"a_uuid",
1759+
"a_nullable_uuid",
17171760
"required_nullable",
17181761
"required_not_nullable",
17191762
"model",
@@ -1784,6 +1827,23 @@
17841827
"type": "string",
17851828
"format": "date"
17861829
},
1830+
"a_uuid": {
1831+
"title": "A Uuid",
1832+
"type": "string",
1833+
"format": "uuid"
1834+
},
1835+
"a_nullable_uuid": {
1836+
"title": "A Nullable Uuid",
1837+
"type": "string",
1838+
"format": "uuid",
1839+
"nullable": true,
1840+
"default": "07EF8B4D-AA09-4FFA-898D-C710796AFF41"
1841+
},
1842+
"a_not_required_uuid": {
1843+
"title": "A Not Required Uuid",
1844+
"type": "string",
1845+
"format": "uuid"
1846+
},
17871847
"1_leading_digit": {
17881848
"title": "Leading Digit",
17891849
"type": "string"

0 commit comments

Comments
 (0)