Skip to content

Commit 146db3a

Browse files
committed
[python] fix #23032 add sync httpx support
1 parent 2f35b81 commit 146db3a

402 files changed

Lines changed: 46504 additions & 12 deletions

File tree

Some content is hidden

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

.github/workflows/samples-python-petstore.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ jobs:
3535
sample:
3636
- samples/openapi3/client/petstore/python-aiohttp
3737
- samples/openapi3/client/petstore/python-httpx
38+
- samples/openapi3/client/petstore/python-httpx-sync
3839
- samples/openapi3/client/petstore/python
3940
- samples/openapi3/client/petstore/python-lazyImports
4041
services:

bin/configs/python-httpx-sync.yaml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
generatorName: python
2+
outputDir: samples/openapi3/client/petstore/python-httpx-sync
3+
inputSpec: modules/openapi-generator/src/test/resources/3_0/python/petstore-with-fake-endpoints-models-for-testing.yaml
4+
templateDir: modules/openapi-generator/src/main/resources/python
5+
library: httpx-sync
6+
additionalProperties:
7+
packageName: petstore_api
8+
mapNumberTo: float
9+
poetry1: false
10+
nameMappings:
11+
_type: underscore_type
12+
type_: type_with_underscore
13+
modelNameMappings:
14+
# The OpenAPI spec ApiResponse conflicts with the internal ApiResponse
15+
ApiResponse: ModelApiResponse

docs/generators/python.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
2525
|generateSourceCodeOnly|Specifies that only a library source code is to be generated.| |false|
2626
|hideGenerationTimestamp|Hides the generation timestamp when files are generated.| |true|
2727
|lazyImports|Enable lazy imports.| |false|
28-
|library|library template (sub-template) to use: asyncio, tornado (deprecated), urllib3, httpx| |urllib3|
28+
|library|library template (sub-template) to use: asyncio, tornado (deprecated), urllib3, httpx, httpx-sync| |urllib3|
2929
|mapNumberTo|Map number to Union[StrictFloat, StrictInt], StrictStr or float.| |Union[StrictFloat, StrictInt]|
3030
|packageName|python package name (convention: snake_case).| |openapi_client|
3131
|packageUrl|python package URL.| |null|

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonClientCodegen.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,8 @@ public PythonClientCodegen() {
158158
supportedLibraries.put("asyncio", "asyncio-based client");
159159
supportedLibraries.put("tornado", "tornado-based client (deprecated)");
160160
supportedLibraries.put("httpx", "httpx-based client");
161-
CliOption libraryOption = new CliOption(CodegenConstants.LIBRARY, "library template (sub-template) to use: asyncio, tornado (deprecated), urllib3, httpx");
161+
supportedLibraries.put("httpx-sync", "httpx-based sync client");
162+
CliOption libraryOption = new CliOption(CodegenConstants.LIBRARY, "library template (sub-template) to use: asyncio, tornado (deprecated), urllib3, httpx, httpx-sync");
162163
libraryOption.setDefault(DEFAULT_LIBRARY);
163164
cliOptions.add(libraryOption);
164165
setLibrary(DEFAULT_LIBRARY);
@@ -340,6 +341,9 @@ public void processOpts() {
340341
supportingFiles.add(new SupportingFile("httpx/rest.mustache", packagePath(), "rest.py"));
341342
additionalProperties.put("async", "true");
342343
additionalProperties.put("httpx", "true");
344+
} else if ("httpx-sync".equals(getLibrary())) {
345+
supportingFiles.add(new SupportingFile("httpx/rest.mustache", packagePath(), "rest.py"));
346+
additionalProperties.put("httpx", "true");
343347
} else {
344348
supportingFiles.add(new SupportingFile("rest.mustache", packagePath(), "rest.py"));
345349
}

modules/openapi-generator/src/main/resources/python/api_client.mustache

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,10 @@ class ApiClient:
101101
return self
102102

103103
def __exit__(self, exc_type, exc_value, traceback):
104-
pass
104+
self.close()
105+
106+
def close(self):
107+
self.rest_client.close()
105108
{{/async}}
106109

107110
@property

modules/openapi-generator/src/main/resources/python/httpx/rest.mustache

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ class RESTResponse(io.IOBase):
2323
self.reason = resp.reason_phrase
2424
self.data = None
2525

26-
async def read(self):
26+
{{#async}}async {{/async}}def read(self):
2727
if self.data is None:
28-
self.data = await self.response.aread()
28+
self.data = {{#async}}await {{/async}}self.response.{{#async}}a{{/async}}read()
2929
return self.data
3030

3131
@property
@@ -65,13 +65,13 @@ class RESTClientObject:
6565
self.proxy = configuration.proxy
6666
self.proxy_headers = configuration.proxy_headers
6767

68-
self.pool_manager: Optional[httpx.AsyncClient] = None
68+
self.pool_manager: Optional[httpx.{{#async}}Async{{/async}}Client] = None
6969

70-
async def close(self):
70+
{{#async}}async {{/async}}def close(self):
7171
if self.pool_manager is not None:
72-
await self.pool_manager.aclose()
72+
{{#async}}await {{/async}}self.pool_manager.{{#async}}a{{/async}}close()
7373

74-
async def request(
74+
{{#async}}async {{/async}}def request(
7575
self,
7676
method,
7777
url,
@@ -169,10 +169,10 @@ class RESTClientObject:
169169
if self.pool_manager is None:
170170
self.pool_manager = self._create_pool_manager()
171171

172-
r = await self.pool_manager.request(**args)
172+
r = {{#async}}await {{/async}}self.pool_manager.request(**args)
173173
return RESTResponse(r)
174174

175-
def _create_pool_manager(self) -> httpx.AsyncClient:
175+
def _create_pool_manager(self) -> httpx.{{#async}}Async{{/async}}Client:
176176
limits = httpx.Limits(max_connections=self.maxsize)
177177

178178
proxy = None
@@ -182,7 +182,7 @@ class RESTClientObject:
182182
headers=self.proxy_headers
183183
)
184184

185-
return httpx.AsyncClient(
185+
return httpx.{{#async}}Async{{/async}}Client(
186186
limits=limits,
187187
proxy=proxy,
188188
verify=self.ssl_context,
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# NOTE: This file is auto generated by OpenAPI Generator.
2+
# URL: https://openapi-generator.tech
3+
#
4+
# ref: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python
5+
6+
name: petstore_api Python package
7+
8+
on: [push, pull_request]
9+
10+
permissions:
11+
contents: read
12+
13+
jobs:
14+
build:
15+
16+
runs-on: ubuntu-latest
17+
strategy:
18+
matrix:
19+
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
20+
21+
steps:
22+
- uses: actions/checkout@v4
23+
- name: Set up Python ${{ matrix.python-version }}
24+
uses: actions/setup-python@v4
25+
with:
26+
python-version: ${{ matrix.python-version }}
27+
- name: Install dependencies
28+
run: |
29+
python -m pip install --upgrade pip
30+
pip install -r requirements.txt
31+
pip install -r test-requirements.txt
32+
- name: Test with pytest
33+
run: |
34+
pytest --cov=petstore_api
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# Byte-compiled / optimized / DLL files
2+
__pycache__/
3+
*.py[cod]
4+
*$py.class
5+
6+
# C extensions
7+
*.so
8+
9+
# Distribution / packaging
10+
.Python
11+
env/
12+
build/
13+
develop-eggs/
14+
dist/
15+
downloads/
16+
eggs/
17+
.eggs/
18+
lib/
19+
lib64/
20+
parts/
21+
sdist/
22+
var/
23+
*.egg-info/
24+
.installed.cfg
25+
*.egg
26+
27+
# PyInstaller
28+
# Usually these files are written by a python script from a template
29+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
30+
*.manifest
31+
*.spec
32+
33+
# Installer logs
34+
pip-log.txt
35+
pip-delete-this-directory.txt
36+
37+
# Unit test / coverage reports
38+
htmlcov/
39+
.tox/
40+
.coverage
41+
.coverage.*
42+
.cache
43+
nosetests.xml
44+
coverage.xml
45+
*,cover
46+
.hypothesis/
47+
venv/
48+
.venv/
49+
.python-version
50+
.pytest_cache
51+
52+
# Translations
53+
*.mo
54+
*.pot
55+
56+
# Django stuff:
57+
*.log
58+
59+
# Sphinx documentation
60+
docs/_build/
61+
62+
# PyBuilder
63+
target/
64+
65+
# Ipython Notebook
66+
.ipynb_checkpoints
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# NOTE: This file is auto generated by OpenAPI Generator.
2+
# URL: https://openapi-generator.tech
3+
#
4+
# ref: https://docs.gitlab.com/ee/ci/README.html
5+
# ref: https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Python.gitlab-ci.yml
6+
7+
stages:
8+
- test
9+
10+
.pytest:
11+
stage: test
12+
script:
13+
- pip install -r requirements.txt
14+
- pip install -r test-requirements.txt
15+
- pytest --cov=petstore_api
16+
17+
pytest-3.9:
18+
extends: .pytest
19+
image: python:3.9-alpine
20+
pytest-3.10:
21+
extends: .pytest
22+
image: python:3.10-alpine
23+
pytest-3.11:
24+
extends: .pytest
25+
image: python:3.11-alpine
26+
pytest-3.12:
27+
extends: .pytest
28+
image: python:3.12-alpine
29+
pytest-3.13:
30+
extends: .pytest
31+
image: python:3.13-alpine
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# OpenAPI Generator Ignore
2+
# Generated by openapi-generator https://github.com/openapitools/openapi-generator
3+
4+
# Use this file to prevent files from being overwritten by the generator.
5+
# The patterns follow closely to .gitignore or .dockerignore.
6+
7+
# As an example, the C# client generator defines ApiClient.cs.
8+
# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
9+
#ApiClient.cs
10+
11+
# You can match any string of characters against a directory, file or extension with a single asterisk (*):
12+
#foo/*/qux
13+
# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
14+
15+
# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
16+
#foo/**/qux
17+
# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
18+
19+
# You can also negate patterns with an exclamation (!).
20+
# For example, you can ignore all files in a docs folder with the file extension .md:
21+
#docs/*.md
22+
# Then explicitly reverse the ignore rule for a single file:
23+
#!docs/README.md

0 commit comments

Comments
 (0)