star-openapi 0.9.0__tar.gz → 0.9.2__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 (124) hide show
  1. {star_openapi-0.9.0 → star_openapi-0.9.2}/.github/pull_request_template.md +1 -1
  2. {star_openapi-0.9.0 → star_openapi-0.9.2}/.github/workflows/docs.yml +3 -1
  3. {star_openapi-0.9.0 → star_openapi-0.9.2}/.github/workflows/tests.yml +11 -16
  4. star_openapi-0.9.2/CHANGELOG.md +11 -0
  5. {star_openapi-0.9.0 → star_openapi-0.9.2}/CONTRIBUTING.md +4 -3
  6. star_openapi-0.9.2/PKG-INFO +166 -0
  7. {star_openapi-0.9.0 → star_openapi-0.9.2}/README.md +5 -3
  8. star_openapi-0.9.2/docs/Example.md +290 -0
  9. {star_openapi-0.9.0 → star_openapi-0.9.2}/docs/Quickstart.md +68 -21
  10. star_openapi-0.9.2/docs/Usage/CLI.md +117 -0
  11. star_openapi-0.9.2/docs/Usage/Request.md +174 -0
  12. star_openapi-0.9.2/docs/Usage/Response.md +59 -0
  13. {star_openapi-0.9.0 → star_openapi-0.9.2}/docs/Usage/Route_Operation.md +29 -25
  14. {star_openapi-0.9.0 → star_openapi-0.9.2}/docs/Usage/Specification.md +18 -18
  15. star_openapi-0.9.2/examples/form_demo.py +22 -0
  16. star_openapi-0.9.2/examples/request_body_demo.py +50 -0
  17. star_openapi-0.9.2/examples/response_demo.py +69 -0
  18. {star_openapi-0.9.0 → star_openapi-0.9.2}/examples/simple_demo.py +5 -4
  19. {star_openapi-0.9.0 → star_openapi-0.9.2}/examples/upload_file_demo.py +0 -3
  20. {star_openapi-0.9.0 → star_openapi-0.9.2}/mkdocs.yml +3 -0
  21. {star_openapi-0.9.0 → star_openapi-0.9.2}/pyproject.toml +5 -14
  22. star_openapi-0.9.2/star_openapi/__version__.py +1 -0
  23. {star_openapi-0.9.0 → star_openapi-0.9.2}/star_openapi/cli.py +61 -21
  24. star_openapi-0.9.2/star_openapi/models/__init__.py +83 -0
  25. {star_openapi-0.9.0 → star_openapi-0.9.2}/star_openapi/models/callback.py +0 -3
  26. {star_openapi-0.9.0 → star_openapi-0.9.2}/star_openapi/models/components.py +0 -3
  27. {star_openapi-0.9.0 → star_openapi-0.9.2}/star_openapi/models/contact.py +0 -4
  28. {star_openapi-0.9.0 → star_openapi-0.9.2}/star_openapi/models/data_type.py +0 -3
  29. {star_openapi-0.9.0 → star_openapi-0.9.2}/star_openapi/models/discriminator.py +0 -4
  30. {star_openapi-0.9.0 → star_openapi-0.9.2}/star_openapi/models/encoding.py +0 -3
  31. {star_openapi-0.9.0 → star_openapi-0.9.2}/star_openapi/models/example.py +0 -3
  32. {star_openapi-0.9.0 → star_openapi-0.9.2}/star_openapi/models/external_documentation.py +0 -4
  33. {star_openapi-0.9.0 → star_openapi-0.9.2}/star_openapi/models/file.py +0 -3
  34. {star_openapi-0.9.0 → star_openapi-0.9.2}/star_openapi/models/header.py +2 -6
  35. {star_openapi-0.9.0 → star_openapi-0.9.2}/star_openapi/models/info.py +0 -4
  36. {star_openapi-0.9.0 → star_openapi-0.9.2}/star_openapi/models/license.py +0 -4
  37. {star_openapi-0.9.0 → star_openapi-0.9.2}/star_openapi/models/link.py +0 -3
  38. {star_openapi-0.9.0 → star_openapi-0.9.2}/star_openapi/models/media_type.py +0 -3
  39. {star_openapi-0.9.0 → star_openapi-0.9.2}/star_openapi/models/oauth_flow.py +0 -4
  40. {star_openapi-0.9.0 → star_openapi-0.9.2}/star_openapi/models/oauth_flows.py +0 -4
  41. {star_openapi-0.9.0 → star_openapi-0.9.2}/star_openapi/models/operation.py +0 -3
  42. {star_openapi-0.9.0 → star_openapi-0.9.2}/star_openapi/models/parameter.py +0 -3
  43. {star_openapi-0.9.0 → star_openapi-0.9.2}/star_openapi/models/parameter_in_type.py +0 -3
  44. {star_openapi-0.9.0 → star_openapi-0.9.2}/star_openapi/models/path_item.py +0 -3
  45. {star_openapi-0.9.0 → star_openapi-0.9.2}/star_openapi/models/paths.py +0 -3
  46. {star_openapi-0.9.0 → star_openapi-0.9.2}/star_openapi/models/reference.py +0 -3
  47. {star_openapi-0.9.0 → star_openapi-0.9.2}/star_openapi/models/request_body.py +0 -4
  48. {star_openapi-0.9.0 → star_openapi-0.9.2}/star_openapi/models/response.py +0 -4
  49. {star_openapi-0.9.0 → star_openapi-0.9.2}/star_openapi/models/responses.py +0 -4
  50. {star_openapi-0.9.0 → star_openapi-0.9.2}/star_openapi/models/schema.py +0 -3
  51. {star_openapi-0.9.0 → star_openapi-0.9.2}/star_openapi/models/security_requirement.py +0 -3
  52. {star_openapi-0.9.0 → star_openapi-0.9.2}/star_openapi/models/security_scheme.py +0 -4
  53. {star_openapi-0.9.0 → star_openapi-0.9.2}/star_openapi/models/security_scheme_in_type.py +0 -3
  54. {star_openapi-0.9.0 → star_openapi-0.9.2}/star_openapi/models/server.py +0 -4
  55. {star_openapi-0.9.0 → star_openapi-0.9.2}/star_openapi/models/server_variable.py +0 -4
  56. {star_openapi-0.9.0 → star_openapi-0.9.2}/star_openapi/models/style_values.py +0 -3
  57. {star_openapi-0.9.0 → star_openapi-0.9.2}/star_openapi/models/validation_error.py +0 -3
  58. {star_openapi-0.9.0 → star_openapi-0.9.2}/star_openapi/models/xml.py +0 -4
  59. {star_openapi-0.9.0 → star_openapi-0.9.2}/star_openapi/openapi.py +65 -17
  60. {star_openapi-0.9.0 → star_openapi-0.9.2}/star_openapi/request.py +3 -3
  61. {star_openapi-0.9.0 → star_openapi-0.9.2}/star_openapi/router.py +54 -11
  62. {star_openapi-0.9.0 → star_openapi-0.9.2}/star_openapi/templates.py +0 -5
  63. {star_openapi-0.9.0 → star_openapi-0.9.2}/star_openapi/types.py +2 -4
  64. {star_openapi-0.9.0 → star_openapi-0.9.2}/star_openapi/utils.py +58 -42
  65. star_openapi-0.9.2/tests/test_cli.py +26 -0
  66. star_openapi-0.9.2/tests/test_form.py +26 -0
  67. star_openapi-0.9.2/tests/test_nested_api_router.py +46 -0
  68. star_openapi-0.9.2/tests/test_request_body.py +58 -0
  69. star_openapi-0.9.2/tests/test_response.py +79 -0
  70. {star_openapi-0.9.0 → star_openapi-0.9.2}/uv.lock +66 -199
  71. star_openapi-0.9.0/CHANGELOG.md +0 -3
  72. star_openapi-0.9.0/PKG-INFO +0 -45
  73. star_openapi-0.9.0/docs/Example.md +0 -287
  74. star_openapi-0.9.0/docs/Usage/Request.md +0 -109
  75. star_openapi-0.9.0/star_openapi/__version__.py +0 -1
  76. star_openapi-0.9.0/star_openapi/models/__init__.py +0 -86
  77. star_openapi-0.9.0/star_openapi/websocket.py +0 -0
  78. {star_openapi-0.9.0 → star_openapi-0.9.2}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  79. {star_openapi-0.9.0 → star_openapi-0.9.2}/.github/dependabot.yml +0 -0
  80. {star_openapi-0.9.0 → star_openapi-0.9.2}/.github/workflows/publish.yml +0 -0
  81. {star_openapi-0.9.0 → star_openapi-0.9.2}/.github/workflows/stale.yml +0 -0
  82. {star_openapi-0.9.0 → star_openapi-0.9.2}/.gitignore +0 -0
  83. {star_openapi-0.9.0 → star_openapi-0.9.2}/LICENSE +0 -0
  84. {star_openapi-0.9.0 → star_openapi-0.9.2}/docs/Changelog.md +0 -0
  85. {star_openapi-0.9.0 → star_openapi-0.9.2}/docs/Contributing.md +0 -0
  86. {star_openapi-0.9.0 → star_openapi-0.9.2}/docs/LICENSE.md +0 -0
  87. {star_openapi-0.9.0 → star_openapi-0.9.2}/docs/Reference/APIRouter.md +0 -0
  88. {star_openapi-0.9.0 → star_openapi-0.9.2}/docs/Reference/Models.md +0 -0
  89. {star_openapi-0.9.0 → star_openapi-0.9.2}/docs/Reference/OpenAPI.md +0 -0
  90. {star_openapi-0.9.0 → star_openapi-0.9.2}/docs/Usage/Configuration.md +0 -0
  91. {star_openapi-0.9.0 → star_openapi-0.9.2}/docs/Usage/UI_Templates.md +0 -0
  92. {star_openapi-0.9.0 → star_openapi-0.9.2}/docs/assets/Snipaste_2022-03-19_15-10-06.png +0 -0
  93. {star_openapi-0.9.0 → star_openapi-0.9.2}/docs/assets/Snipaste_2022-09-04_10-10-03.png +0 -0
  94. {star_openapi-0.9.0 → star_openapi-0.9.2}/docs/assets/Snipaste_2023-06-02_11-05-11.png +0 -0
  95. {star_openapi-0.9.0 → star_openapi-0.9.2}/docs/assets/Snipaste_2023-06-02_11-06-59.png +0 -0
  96. {star_openapi-0.9.0 → star_openapi-0.9.2}/docs/assets/Snipaste_2023-06-02_11-08-40.png +0 -0
  97. {star_openapi-0.9.0 → star_openapi-0.9.2}/docs/assets/image-20210525160157057.png +0 -0
  98. {star_openapi-0.9.0 → star_openapi-0.9.2}/docs/assets/image-20210525160744617.png +0 -0
  99. {star_openapi-0.9.0 → star_openapi-0.9.2}/docs/assets/image-20210525165350520.png +0 -0
  100. {star_openapi-0.9.0 → star_openapi-0.9.2}/docs/assets/image-20210526104627124.png +0 -0
  101. {star_openapi-0.9.0 → star_openapi-0.9.2}/docs/assets/image-20210605115557426.png +0 -0
  102. {star_openapi-0.9.0 → star_openapi-0.9.2}/docs/assets/openapi-all.png +0 -0
  103. {star_openapi-0.9.0 → star_openapi-0.9.2}/docs/images/logo-animation.svg +0 -0
  104. {star_openapi-0.9.0 → star_openapi-0.9.2}/docs/images/logo-blue.svg +0 -0
  105. {star_openapi-0.9.0 → star_openapi-0.9.2}/docs/images/logo-text.gif +0 -0
  106. {star_openapi-0.9.0 → star_openapi-0.9.2}/docs/images/logo-text.svg +0 -0
  107. {star_openapi-0.9.0 → star_openapi-0.9.2}/docs/images/logo-white.svg +0 -0
  108. {star_openapi-0.9.0 → star_openapi-0.9.2}/docs/index.md +0 -0
  109. {star_openapi-0.9.0 → star_openapi-0.9.2}/examples/api_router_demo.py +0 -0
  110. {star_openapi-0.9.0 → star_openapi-0.9.2}/examples/query_list_demo.py +0 -0
  111. {star_openapi-0.9.0 → star_openapi-0.9.2}/examples/restapi_demo.py +0 -0
  112. {star_openapi-0.9.0 → star_openapi-0.9.2}/examples/websocket_demo.py +0 -0
  113. {star_openapi-0.9.0 → star_openapi-0.9.2}/star_openapi/__init__.py +0 -0
  114. {star_openapi-0.9.0 → star_openapi-0.9.2}/star_openapi/__main__.py +0 -0
  115. {star_openapi-0.9.0 → star_openapi-0.9.2}/star_openapi/config.py +0 -0
  116. {star_openapi-0.9.0 → star_openapi-0.9.2}/star_openapi/endpoint.py +0 -0
  117. {star_openapi-0.9.0 → star_openapi-0.9.2}/star_openapi/models/tag.py +0 -0
  118. {star_openapi-0.9.0 → star_openapi-0.9.2}/star_openapi/plugins.py +0 -0
  119. {star_openapi-0.9.0 → star_openapi-0.9.2}/star_openapi/py.typed +0 -0
  120. {star_openapi-0.9.0 → star_openapi-0.9.2}/tests/test_api_router.py +0 -0
  121. {star_openapi-0.9.0 → star_openapi-0.9.2}/tests/test_query_list.py +0 -0
  122. {star_openapi-0.9.0 → star_openapi-0.9.2}/tests/test_restapi.py +0 -0
  123. {star_openapi-0.9.0 → star_openapi-0.9.2}/tests/test_upload_file.py +0 -0
  124. {star_openapi-0.9.0 → star_openapi-0.9.2}/tests/test_websocket.py +0 -0
@@ -3,5 +3,5 @@ Checklist:
3
3
  - [ ] Run `pytest tests` and no failed.
4
4
  - [ ] Run `ruff check star_openapi tests examples` and no failed.
5
5
  - [ ] Run `ruff format star_openapi tests examples` and no failed.
6
- - [ ] Run `mypy star_openapi` and no failed.
6
+ - [ ] Run `ty check star_openapi` and no failed.
7
7
  - [ ] Run `mkdocs serve` and no failed.
@@ -12,6 +12,8 @@ jobs:
12
12
  - uses: actions/checkout@v6
13
13
 
14
14
  - uses: astral-sh/setup-uv@v7
15
+ with:
16
+ enable-cache: true
15
17
 
16
18
  - name: Install dependencies
17
19
  run: uv sync
@@ -21,5 +23,5 @@ jobs:
21
23
  git config --local user.email "action@github.com"
22
24
  git config --local user.name "GitHub Action"
23
25
  git fetch origin gh-pages:gh-pages
24
- uv run mike deploy v0.9.x
26
+ uv run mike deploy v0.x latest --update-aliases
25
27
  git push origin gh-pages
@@ -3,17 +3,15 @@ name: tests
3
3
  on:
4
4
  push:
5
5
  branches: [ main ]
6
- paths-ignore:
7
- - "docs/**"
8
- - "*.md"
9
- - "*.rst"
6
+ paths:
7
+ - "star_openapi/**"
8
+ - "tests/**"
10
9
 
11
10
  pull_request:
12
11
  branches: [ main ]
13
- paths-ignore:
14
- - "docs/**"
15
- - "*.md"
16
- - "*.rst"
12
+ paths:
13
+ - "star_openapi/**"
14
+ - "tests/**"
17
15
 
18
16
  jobs:
19
17
  tests:
@@ -40,14 +38,11 @@ jobs:
40
38
  - name: Test with pytest
41
39
  run: uv run pytest tests
42
40
 
43
- - name: ruff
41
+ - name: ruff check
44
42
  run: uv run ruff check star_openapi tests examples
45
43
 
46
- - name: Cache mypy
47
- uses: actions/cache@v5
48
- with:
49
- path: ./.mypy_cache
50
- key: mypy|${{ matrix.python-version }}|${{ hashFiles('pyproject.toml') }}
44
+ - name: ruff format
45
+ run: uv run ruff format --check star_openapi tests examples
51
46
 
52
- - name: Run mypy
53
- run: uv run mypy star_openapi
47
+ - name: Run ty
48
+ run: uv run ty check star_openapi
@@ -0,0 +1,11 @@
1
+ ## v0.9.2 2026-01-26
2
+
3
+ - Add parameter app to StarGroup by @luolingchun in #4
4
+
5
+ ## v0.9.1 2026-01-12
6
+
7
+ - Support multi content type in request body and responses by @luolingchun in #2
8
+
9
+ ## v0.9.0 2026-01-04
10
+
11
+ - first version
@@ -27,15 +27,16 @@ Before submitting pr, you need to complete the following steps:
27
27
  ruff check star_openapi tests examples
28
28
  ```
29
29
 
30
- 4. Running the mypy
30
+ 4. Running the ty
31
31
 
32
32
  ```bash
33
- mypy star_openapi
33
+ ty check star_openapi
34
34
  ```
35
35
 
36
36
  5. Building the docs
37
37
 
38
- Serve the live docs with [Material for MkDocs](https://github.com/squidfunk/mkdocs-material), and make sure it's correct.
38
+ Serve the live docs with [Material for MkDocs](https://github.com/squidfunk/mkdocs-material), and make sure it's
39
+ correct.
39
40
 
40
41
  ```bash
41
42
  mkdocs serve
@@ -0,0 +1,166 @@
1
+ Metadata-Version: 2.4
2
+ Name: star-openapi
3
+ Version: 0.9.2
4
+ Summary: A simple async API framework based on Starlette.
5
+ Project-URL: Homepage, https://github.com/luolingchun/star-openapi
6
+ Project-URL: Documentation, https://luolingchun.github.io/star-openapi
7
+ Maintainer-email: llc <luolingchun@outlook.com>
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Environment :: Web Environment
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3 :: Only
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Programming Language :: Python :: 3.14
21
+ Requires-Python: >=3.11
22
+ Requires-Dist: click>=8.0.0
23
+ Requires-Dist: jinja2>=3.1.2
24
+ Requires-Dist: pydantic>=2.0.0
25
+ Requires-Dist: starlette>=0.50.0
26
+ Requires-Dist: uvicorn[standard]>=0.40.0
27
+ Provides-Extra: elements
28
+ Requires-Dist: star-openapi-elements; extra == 'elements'
29
+ Provides-Extra: full
30
+ Requires-Dist: httpx; extra == 'full'
31
+ Requires-Dist: itsdangerous; extra == 'full'
32
+ Requires-Dist: python-multipart; extra == 'full'
33
+ Requires-Dist: pyyaml; extra == 'full'
34
+ Provides-Extra: rapidoc
35
+ Requires-Dist: star-openapi-rapidoc; extra == 'rapidoc'
36
+ Provides-Extra: rapipdf
37
+ Requires-Dist: star-openapi-rapipdf; extra == 'rapipdf'
38
+ Provides-Extra: redoc
39
+ Requires-Dist: star-openapi-redoc; extra == 'redoc'
40
+ Provides-Extra: scalar
41
+ Requires-Dist: star-openapi-scalar; extra == 'scalar'
42
+ Provides-Extra: swagger
43
+ Requires-Dist: star-openapi-swagger; extra == 'swagger'
44
+ Description-Content-Type: text/markdown
45
+
46
+ <div align="center">
47
+ <a href="https://luolingchun.github.io/star-openapi/" target="_blank">
48
+ <img class="off-glb" src="https://raw.githubusercontent.com/luolingchun/star-openapi/main/docs/images/logo-text.svg"
49
+ width="60%" height="auto" alt="logo">
50
+ </a>
51
+ </div>
52
+ <p align="center">
53
+ <em>A simple async API framework based on Starlette.</em>
54
+ </p>
55
+ <p align="center">
56
+ <a href="https://github.com/luolingchun/star-openapi/actions/workflows/tests.yml" target="_blank">
57
+ <img class="off-glb" src="https://img.shields.io/github/actions/workflow/status/luolingchun/star-openapi/tests.yml?branch=main" alt="test">
58
+ </a>
59
+ <a href="https://pypi.org/project/star-openapi/" target="_blank">
60
+ <img class="off-glb" src="https://img.shields.io/pypi/v/star-openapi" alt="pypi">
61
+ </a>
62
+ <a href="https://pypistats.org/packages/star-openapi" target="_blank">
63
+ <img class="off-glb" src="https://img.shields.io/pypi/dm/star-openapi" alt="pypistats">
64
+ </a>
65
+ <a href="https://pypi.org/project/star-openapi/" target="_blank">
66
+ <img class="off-glb" src="https://img.shields.io/pypi/pyversions/star-openapi" alt="pypi versions">
67
+ </a>
68
+ </p>
69
+
70
+ **Star OpenAPI** is a web API framework based on **Starlette**. It uses **Pydantic** to verify data and automatic
71
+ generation of interaction documentation.
72
+
73
+ The key features are:
74
+
75
+ - **Easy to code:** Easy to use and easy to learn
76
+
77
+ - **Standard document specification:** Based on [OpenAPI Specification](https://spec.openapis.org/oas/v3.1.0)
78
+
79
+ - **Interactive OpenAPI documentation:**
80
+ [Swagger](https://github.com/swagger-api/swagger-ui), [Redoc](https://github.com/Redocly/redoc), [RapiDoc](https://github.com/rapi-doc/RapiDoc), [RapiPdf](https://mrin9.github.io/RapiPdf/), [Scalar](https://github.com/scalar/scalar), [Elements](https://github.com/stoplightio/elements)
81
+
82
+ - **Data validation:** Fast data verification based on [Pydantic](https://github.com/pydantic/pydantic)
83
+
84
+ - **Websocket**: Support for websocket
85
+
86
+ ## Requirements
87
+
88
+ Python 3.11+
89
+
90
+ star-openapi is dependent on the following libraries:
91
+
92
+ - [Starlette](https://github.com/Kludex/starlette) for the web app.
93
+ - [Pydantic](https://github.com/pydantic/pydantic) for the data validation.
94
+
95
+ ## Installation
96
+
97
+ ```bash
98
+ pip install -U star-openapi[swagger]
99
+ ```
100
+
101
+ <details markdown="block">
102
+ <summary>Optional dependencies</summary>
103
+
104
+ - [`httpx`](https://github.com/encode/httpx/) - Required if you want to use the `TestClient`.
105
+ - [`python-multipart`](https://github.com//kludex/python-multipart) - Required if you want to support form parsing, with
106
+ `request.form()`.
107
+ - [`itsdangerous`](https://github.com/pallets/itsdangerous) - Required for `SessionMiddleware` support.
108
+ - [`pyyaml`](https://github.com/yaml/pyyaml) - Required for `SchemaGenerator` support.
109
+
110
+ You can install all of these with `pip install star-openapi[full]`.
111
+
112
+ - [star-openapi-plugins](https://github.com/luolingchun/star-openapi-plugins) Provide OpenAPI UI for star-openapi.
113
+
114
+ You can install all of these with `pip install star-openapi[swagger,redoc,rapidoc,rapipdf,scalar,elements]`.
115
+
116
+ </details>
117
+
118
+ ## A Simple Example
119
+
120
+ Here's a simple example, further go to the [Example](https://luolingchun.github.io/star-openapi/v0.x/Example/).
121
+
122
+ ```python
123
+ import uvicorn
124
+ from pydantic import BaseModel
125
+ from starlette.responses import JSONResponse
126
+
127
+ from star_openapi import OpenAPI
128
+
129
+ info = {"title": "Star API", "version": "1.0.0"}
130
+ app = OpenAPI(info=info)
131
+
132
+ book_tag = {"name": "book", "description": "book tag"}
133
+
134
+
135
+ class BookModel(BaseModel):
136
+ name: str
137
+ age: int
138
+
139
+
140
+ @app.post("/book", summary="get books", tags=[book_tag])
141
+ async def create_user(body: BookModel):
142
+ """
143
+ get all books
144
+ """
145
+ print(body.model_dump_json())
146
+ return JSONResponse({"message": "Hello World"})
147
+
148
+
149
+ if __name__ == "__main__":
150
+ print(app.routes)
151
+ uvicorn.run(app)
152
+ ```
153
+
154
+ ## API Document
155
+
156
+ Run the [simple example](https://github.com/luolingchun/star-openapi/blob/main/examples/simple_demo.py), and go
157
+ to http://127.0.0.1:8000/openapi.
158
+
159
+ > OpenAPI UI plugins are optional dependencies that require manual installation.
160
+ >
161
+ > `pip install -U star-openapi[swagger,redoc,rapidoc,rapipdf,scalar,elements]`
162
+ >
163
+ > More optional ui templates goto the document
164
+ > about [UI_Templates](https://luolingchun.github.io/star-openapi/v0.x/Usage/UI_Templates/).
165
+
166
+ ![openapi](https://raw.githubusercontent.com/luolingchun/star-openapi/main/docs/assets/openapi-all.png)
@@ -5,7 +5,7 @@
5
5
  </a>
6
6
  </div>
7
7
  <p align="center">
8
- <em>A simple API framework based on Starlette.</em>
8
+ <em>A simple async API framework based on Starlette.</em>
9
9
  </p>
10
10
  <p align="center">
11
11
  <a href="https://github.com/luolingchun/star-openapi/actions/workflows/tests.yml" target="_blank">
@@ -36,6 +36,8 @@ The key features are:
36
36
 
37
37
  - **Data validation:** Fast data verification based on [Pydantic](https://github.com/pydantic/pydantic)
38
38
 
39
+ - **Websocket**: Support for websocket
40
+
39
41
  ## Requirements
40
42
 
41
43
  Python 3.11+
@@ -85,13 +87,13 @@ app = OpenAPI(info=info)
85
87
  book_tag = {"name": "book", "description": "book tag"}
86
88
 
87
89
 
88
- class TestModel(BaseModel):
90
+ class BookModel(BaseModel):
89
91
  name: str
90
92
  age: int
91
93
 
92
94
 
93
95
  @app.post("/book", summary="get books", tags=[book_tag])
94
- async def create_user(body: TestModel):
96
+ async def create_user(body: BookModel):
95
97
  """
96
98
  get all books
97
99
  """
@@ -0,0 +1,290 @@
1
+ ## Simple Demo
2
+
3
+ ```python
4
+ import uvicorn
5
+ from pydantic import BaseModel
6
+ from starlette.responses import JSONResponse
7
+
8
+ from star_openapi import OpenAPI
9
+
10
+ info = {"title": "Star API", "version": "1.0.0"}
11
+ app = OpenAPI(info=info)
12
+
13
+ book_tag = {"name": "book", "description": "book tag"}
14
+
15
+
16
+ class BookModel(BaseModel):
17
+ name: str
18
+ age: int
19
+
20
+
21
+ @app.get("/book", summary="get books", tags=[book_tag])
22
+ async def get_book(query: BookModel):
23
+ """
24
+ get all books
25
+ """
26
+ print(query.model_dump_json())
27
+ return JSONResponse({"message": "Hello World"})
28
+
29
+
30
+ if __name__ == "__main__":
31
+ print(app.routes)
32
+ uvicorn.run(app)
33
+ ```
34
+
35
+ ## REST Demo
36
+
37
+ ```python
38
+ from http import HTTPStatus
39
+
40
+ from pydantic import BaseModel, Field
41
+ from starlette.responses import JSONResponse
42
+
43
+ from star_openapi import Info, OpenAPI, Tag
44
+
45
+ info = Info(title="book API", version="1.0.0")
46
+ # Basic Authentication Sample
47
+ basic = {"type": "http", "scheme": "basic"}
48
+ # JWT Bearer Sample
49
+ jwt = {"type": "http", "scheme": "bearer", "bearerFormat": "JWT"}
50
+ # API Key Sample
51
+ api_key = {"type": "apiKey", "name": "api_key", "in": "header"}
52
+ # Implicit OAuth2 Sample
53
+ oauth2 = {
54
+ "type": "oauth2",
55
+ "flows": {
56
+ "implicit": {
57
+ "authorizationUrl": "https://example.com/api/oauth/dialog",
58
+ "scopes": {"write:pets": "modify pets in your account", "read:pets": "read your pets"},
59
+ }
60
+ },
61
+ }
62
+ security_schemes = {"jwt": jwt, "api_key": api_key, "oauth2": oauth2, "basic": basic}
63
+
64
+
65
+ class NotFoundResponse(BaseModel):
66
+ code: int = Field(-1, description="Status Code")
67
+ message: str = Field("Resource not found!", description="Exception Information")
68
+
69
+
70
+ app = OpenAPI(info=info, security_schemes=security_schemes)
71
+
72
+ book_tag = Tag(name="book", description="Some Book")
73
+ security = [{"jwt": []}, {"oauth2": ["write:pets", "read:pets"]}]
74
+
75
+
76
+ class BookPath(BaseModel):
77
+ id: int = Field(..., description="book id")
78
+
79
+
80
+ class BookQuery(BaseModel):
81
+ age: int | None = Field(None, description="Age")
82
+ s_list: list[str] = Field(None, alias="s_list[]", description="some array")
83
+
84
+
85
+ class BookBody(BaseModel):
86
+ age: int | None = Field(..., ge=2, le=4, description="Age")
87
+ author: str | None = Field(None, min_length=2, max_length=4, description="Author")
88
+
89
+
90
+ class BookBodyWithID(BaseModel):
91
+ id: int = Field(..., description="book id")
92
+ age: int | None = Field(None, ge=2, le=4, description="Age")
93
+ author: str = Field(None, min_length=2, max_length=4, description="Author")
94
+
95
+
96
+ class BookResponse(BaseModel):
97
+ code: int = Field(0, description="Status Code")
98
+ message: str = Field("ok", description="Exception Information")
99
+ data: BookBodyWithID | None
100
+
101
+
102
+ @app.get(
103
+ "/book/{id}",
104
+ tags=[book_tag],
105
+ summary="new summary",
106
+ description="new description",
107
+ security=security,
108
+ )
109
+ async def get_book(path: BookPath):
110
+ """Get a book
111
+ to get some book by id, like:
112
+ http://localhost:8000/book/3
113
+ """
114
+ if path.id == 4:
115
+ return NotFoundResponse().model_dump_json(), 404
116
+ return JSONResponse({"code": 0, "message": "ok", "data": {"id": path.id, "age": 3, "author": "no"}})
117
+
118
+
119
+ # set doc_ui False disable openapi UI
120
+ @app.get("/book", doc_ui=True, deprecated=True)
121
+ async def get_books(query: BookQuery):
122
+ """get books
123
+ to get all books
124
+ """
125
+ print(query)
126
+ return JSONResponse(
127
+ {
128
+ "code": 0,
129
+ "message": "ok",
130
+ "data": [{"id": 1, "age": query.age, "author": "a1"}, {"id": 2, "age": query.age, "author": "a2"}],
131
+ }
132
+ )
133
+
134
+
135
+ @app.post("/book", tags=[book_tag])
136
+ async def create_book(body: BookBody):
137
+ print(body)
138
+ return JSONResponse({"code": 0, "message": "ok"})
139
+
140
+
141
+ @app.put("/book/{id}", tags=[book_tag])
142
+ async def update_book(path: BookPath, body: BookBody):
143
+ print(path)
144
+ print(body)
145
+ return JSONResponse({"code": 0, "message": "ok"})
146
+
147
+
148
+ @app.delete("/book/{id}", tags=[book_tag], doc_ui=False)
149
+ async def delete_book(path: BookPath):
150
+ print(path)
151
+ return JSONResponse({"code": 0, "message": "ok"})
152
+
153
+
154
+ if __name__ == "__main__":
155
+ import uvicorn
156
+
157
+ uvicorn.run(app)
158
+ ```
159
+
160
+ ## APIRouter
161
+
162
+ ```python
163
+ import uvicorn
164
+ from pydantic import BaseModel
165
+ from starlette.responses import JSONResponse
166
+
167
+ from star_openapi import OpenAPI
168
+ from star_openapi.router import APIRouter
169
+
170
+ app = OpenAPI()
171
+
172
+ api1 = APIRouter(url_prefix="/api1")
173
+ api2 = APIRouter(url_prefix="/api2")
174
+
175
+
176
+ class IdModel(BaseModel):
177
+ id: int
178
+
179
+
180
+ class BookModel(BaseModel):
181
+ name: str
182
+ age: int
183
+
184
+
185
+ @api1.get("/book")
186
+ async def ge_book():
187
+ return JSONResponse({"message": "Hello World1"})
188
+
189
+
190
+ @api1.post("/book")
191
+ async def create_book(body: BookModel):
192
+ return JSONResponse(body.model_dump())
193
+
194
+
195
+ @api1.put("/book/{id}")
196
+ async def update_book(path: IdModel, body: BookModel):
197
+ return JSONResponse({"id": path.id, "name": body.name, "age": body.age})
198
+
199
+
200
+ @api1.delete("/book/{id}")
201
+ async def delete_book(path: IdModel):
202
+ return JSONResponse({"id": path.id})
203
+
204
+
205
+ @api2.get("/")
206
+ async def get_api2():
207
+ return JSONResponse({"message": "Hello World2"})
208
+
209
+
210
+ api1.register_api(api2)
211
+
212
+ app.register_api(api1)
213
+ app.register_api(api2)
214
+
215
+ if __name__ == "__main__":
216
+ print(app.routes)
217
+ uvicorn.run(app)
218
+ ```
219
+
220
+ ## Upload File Demo
221
+
222
+ ```python
223
+ import uvicorn
224
+ from pydantic import BaseModel, Field
225
+ from starlette.responses import JSONResponse
226
+
227
+ from star_openapi import OpenAPI, UploadFile
228
+
229
+ app = OpenAPI()
230
+
231
+
232
+ class UploadFileForm(BaseModel):
233
+ file: UploadFile
234
+ file_type: str = Field(None, description="File Type")
235
+
236
+
237
+ class UploadFilesForm(BaseModel):
238
+ files: list[UploadFile]
239
+ file_type: str = Field(None, description="File Type")
240
+
241
+
242
+ @app.post("/upload/file")
243
+ async def upload_file(form: UploadFileForm):
244
+ print(form.file.filename)
245
+ print(form.file_type)
246
+
247
+ content = await form.file.read()
248
+ with open(form.file.filename, "wb") as f:
249
+ f.write(content)
250
+ return JSONResponse({"code": 0, "message": "ok"})
251
+
252
+
253
+ @app.post("/upload/files")
254
+ async def upload_files(form: UploadFilesForm):
255
+ print(form.files)
256
+ print(form.file_type)
257
+ return JSONResponse({"code": 0, "message": "ok"})
258
+
259
+
260
+ if __name__ == "__main__":
261
+ print(app.routes)
262
+ uvicorn.run(app)
263
+ ```
264
+
265
+ ## Websocket Demo
266
+
267
+ ```python
268
+ import uvicorn
269
+ from starlette.websockets import WebSocket
270
+
271
+ from star_openapi import OpenAPI
272
+
273
+ app = OpenAPI()
274
+
275
+
276
+ @app.websocket("/ws")
277
+ async def websocket_endpoint(websocket: WebSocket):
278
+ await websocket.accept()
279
+ while True:
280
+ data = await websocket.receive_text()
281
+ await websocket.send_text(data)
282
+
283
+
284
+ if __name__ == "__main__":
285
+ uvicorn.run("websocket:app", reload=True)
286
+ ```
287
+
288
+ ## A complete project
289
+
290
+ see [star-api-demo](https://github.com/luolingchun/star-api-demo)