quater 0.1.0__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 (256) hide show
  1. quater-0.1.0/.github/ISSUE_TEMPLATE/bug_report.md +34 -0
  2. quater-0.1.0/.github/ISSUE_TEMPLATE/config.yml +1 -0
  3. quater-0.1.0/.github/ISSUE_TEMPLATE/documentation.md +20 -0
  4. quater-0.1.0/.github/ISSUE_TEMPLATE/feature_request.md +27 -0
  5. quater-0.1.0/.github/PULL_REQUEST_TEMPLATE.md +24 -0
  6. quater-0.1.0/.github/dependabot.yml +31 -0
  7. quater-0.1.0/.github/workflows/ci.yml +126 -0
  8. quater-0.1.0/.github/workflows/release.yml +272 -0
  9. quater-0.1.0/.gitignore +35 -0
  10. quater-0.1.0/.pre-commit-config.yaml +20 -0
  11. quater-0.1.0/CONTRIBUTING.md +290 -0
  12. quater-0.1.0/Cargo.lock +140 -0
  13. quater-0.1.0/Cargo.toml +18 -0
  14. quater-0.1.0/LICENSE +21 -0
  15. quater-0.1.0/PKG-INFO +356 -0
  16. quater-0.1.0/README.md +326 -0
  17. quater-0.1.0/agent-skills/README.md +36 -0
  18. quater-0.1.0/agent-skills/quater-apps/SKILL.md +113 -0
  19. quater-0.1.0/agent-skills/quater-apps/agents/openai.yaml +4 -0
  20. quater-0.1.0/agent-skills/quater-apps/references/auth.md +67 -0
  21. quater-0.1.0/agent-skills/quater-apps/references/cli-actions.md +291 -0
  22. quater-0.1.0/agent-skills/quater-apps/references/mcp.md +151 -0
  23. quater-0.1.0/agent-skills/quater-apps/references/safety.md +99 -0
  24. quater-0.1.0/agent-skills/quater-framework/SKILL.md +82 -0
  25. quater-0.1.0/agent-skills/quater-framework/agents/openai.yaml +4 -0
  26. quater-0.1.0/agent-skills/quater-framework/references/app-patterns.md +112 -0
  27. quater-0.1.0/agent-skills/quater-framework/references/deployment.md +68 -0
  28. quater-0.1.0/agent-skills/quater-framework/references/resources-testing.md +114 -0
  29. quater-0.1.0/agent-skills/quater-framework/references/surfaces.md +79 -0
  30. quater-0.1.0/benchmarks/.gitignore +1 -0
  31. quater-0.1.0/benchmarks/README.md +279 -0
  32. quater-0.1.0/benchmarks/apps/db_fastapi.py +222 -0
  33. quater-0.1.0/benchmarks/apps/db_quater.py +201 -0
  34. quater-0.1.0/benchmarks/apps/no_db_fastapi.py +105 -0
  35. quater-0.1.0/benchmarks/apps/no_db_quater.py +107 -0
  36. quater-0.1.0/benchmarks/assets/no-db-p95.svg +46 -0
  37. quater-0.1.0/benchmarks/assets/no-db-throughput.svg +46 -0
  38. quater-0.1.0/benchmarks/assets/postgres-p95.svg +46 -0
  39. quater-0.1.0/benchmarks/assets/postgres-throughput.svg +46 -0
  40. quater-0.1.0/benchmarks/docker-compose.yml +19 -0
  41. quater-0.1.0/benchmarks/scripts/generate_charts.py +261 -0
  42. quater-0.1.0/benchmarks/scripts/run_suite.py +322 -0
  43. quater-0.1.0/docs/.vitepress/config.mts +307 -0
  44. quater-0.1.0/docs/.vitepress/theme/components/MermaidDiagram.vue +75 -0
  45. quater-0.1.0/docs/.vitepress/theme/index.ts +11 -0
  46. quater-0.1.0/docs/.vitepress/theme/style.css +75 -0
  47. quater-0.1.0/docs/en/dev/actions.md +445 -0
  48. quater-0.1.0/docs/en/dev/api.md +444 -0
  49. quater-0.1.0/docs/en/dev/auth-model.md +229 -0
  50. quater-0.1.0/docs/en/dev/changelog.md +244 -0
  51. quater-0.1.0/docs/en/dev/contributing.md +259 -0
  52. quater-0.1.0/docs/en/dev/deployment.md +234 -0
  53. quater-0.1.0/docs/en/dev/index.md +219 -0
  54. quater-0.1.0/docs/en/dev/known-limitations.md +60 -0
  55. quater-0.1.0/docs/en/dev/mcp.md +326 -0
  56. quater-0.1.0/docs/en/dev/middleware-errors.md +230 -0
  57. quater-0.1.0/docs/en/dev/quickstart.md +322 -0
  58. quater-0.1.0/docs/en/dev/reference/application.md +358 -0
  59. quater-0.1.0/docs/en/dev/reference/auth.md +236 -0
  60. quater-0.1.0/docs/en/dev/reference/index.md +58 -0
  61. quater-0.1.0/docs/en/dev/reference/observability.md +149 -0
  62. quater-0.1.0/docs/en/dev/reference/parameters.md +283 -0
  63. quater-0.1.0/docs/en/dev/reference/request.md +309 -0
  64. quater-0.1.0/docs/en/dev/reference/resources.md +148 -0
  65. quater-0.1.0/docs/en/dev/reference/responses.md +168 -0
  66. quater-0.1.0/docs/en/dev/reference/testing.md +210 -0
  67. quater-0.1.0/docs/en/dev/resources.md +427 -0
  68. quater-0.1.0/docs/en/dev/routes-handlers.md +175 -0
  69. quater-0.1.0/docs/en/dev/security.md +314 -0
  70. quater-0.1.0/docs/en/dev/stability.md +129 -0
  71. quater-0.1.0/docs/en/dev/surfaces.md +149 -0
  72. quater-0.1.0/docs/en/dev/testing.md +363 -0
  73. quater-0.1.0/docs/en/dev/why-quater.md +92 -0
  74. quater-0.1.0/docs/index.md +121 -0
  75. quater-0.1.0/docs/public/logo-black-bg.svg +8 -0
  76. quater-0.1.0/docs/public/logo-no-bg.svg +7 -0
  77. quater-0.1.0/docs/public/logo-white-bg.svg +8 -0
  78. quater-0.1.0/docs/public/robots.txt +4 -0
  79. quater-0.1.0/examples/__init__.py +1 -0
  80. quater-0.1.0/examples/asgi_compat.py +5 -0
  81. quater-0.1.0/examples/auth_and_mcp.py +48 -0
  82. quater-0.1.0/examples/basic_app.py +20 -0
  83. quater-0.1.0/examples/wsgi_compat.py +5 -0
  84. quater-0.1.0/native/router/src/lib.rs +238 -0
  85. quater-0.1.0/package-lock.json +3826 -0
  86. quater-0.1.0/package.json +23 -0
  87. quater-0.1.0/pyproject.toml +107 -0
  88. quater-0.1.0/release/0.1.0a1.md +54 -0
  89. quater-0.1.0/scripts/build-docs-site.mjs +325 -0
  90. quater-0.1.0/scripts/generate_reference.py +2392 -0
  91. quater-0.1.0/src/quater/__init__.py +72 -0
  92. quater-0.1.0/src/quater/_api_boundary.py +89 -0
  93. quater-0.1.0/src/quater/_finalize.py +84 -0
  94. quater-0.1.0/src/quater/_parameters.py +198 -0
  95. quater-0.1.0/src/quater/_router.pyi +22 -0
  96. quater-0.1.0/src/quater/_state.py +21 -0
  97. quater-0.1.0/src/quater/actions/__init__.py +1 -0
  98. quater-0.1.0/src/quater/actions/approval.py +81 -0
  99. quater-0.1.0/src/quater/actions/descriptions.py +45 -0
  100. quater-0.1.0/src/quater/actions/executor.py +497 -0
  101. quater-0.1.0/src/quater/actions/registry.py +83 -0
  102. quater-0.1.0/src/quater/adapters/__init__.py +7 -0
  103. quater-0.1.0/src/quater/adapters/_shared.py +108 -0
  104. quater-0.1.0/src/quater/adapters/asgi.py +222 -0
  105. quater-0.1.0/src/quater/adapters/rsgi.py +159 -0
  106. quater-0.1.0/src/quater/adapters/wsgi.py +165 -0
  107. quater-0.1.0/src/quater/app.py +1442 -0
  108. quater-0.1.0/src/quater/auth.py +258 -0
  109. quater-0.1.0/src/quater/cli/__init__.py +1 -0
  110. quater-0.1.0/src/quater/cli/apps.py +57 -0
  111. quater-0.1.0/src/quater/cli/client.py +134 -0
  112. quater-0.1.0/src/quater/cli/discovery.py +229 -0
  113. quater-0.1.0/src/quater/cli/errors.py +54 -0
  114. quater-0.1.0/src/quater/cli/main.py +515 -0
  115. quater-0.1.0/src/quater/cli/output.py +380 -0
  116. quater-0.1.0/src/quater/cli/parsing.py +83 -0
  117. quater-0.1.0/src/quater/cli/remotes.py +140 -0
  118. quater-0.1.0/src/quater/cli/server.py +130 -0
  119. quater-0.1.0/src/quater/config.py +480 -0
  120. quater-0.1.0/src/quater/cookies.py +87 -0
  121. quater-0.1.0/src/quater/core.py +95 -0
  122. quater-0.1.0/src/quater/cors.py +246 -0
  123. quater-0.1.0/src/quater/datastructures.py +183 -0
  124. quater-0.1.0/src/quater/dependencies.py +472 -0
  125. quater-0.1.0/src/quater/deployment.py +41 -0
  126. quater-0.1.0/src/quater/docs/__init__.py +1 -0
  127. quater-0.1.0/src/quater/docs/html.py +277 -0
  128. quater-0.1.0/src/quater/docs/openapi.py +279 -0
  129. quater-0.1.0/src/quater/docs/swagger.py +87 -0
  130. quater-0.1.0/src/quater/exceptions.py +120 -0
  131. quater-0.1.0/src/quater/formdata.py +377 -0
  132. quater-0.1.0/src/quater/groups.py +605 -0
  133. quater-0.1.0/src/quater/lifespan.py +86 -0
  134. quater-0.1.0/src/quater/middleware.py +262 -0
  135. quater-0.1.0/src/quater/observability.py +152 -0
  136. quater-0.1.0/src/quater/params.py +902 -0
  137. quater-0.1.0/src/quater/protocol/__init__.py +1 -0
  138. quater-0.1.0/src/quater/protocol/actions.py +125 -0
  139. quater-0.1.0/src/quater/py.typed +1 -0
  140. quater-0.1.0/src/quater/request.py +462 -0
  141. quater-0.1.0/src/quater/response.py +268 -0
  142. quater-0.1.0/src/quater/router.py +357 -0
  143. quater-0.1.0/src/quater/routing.py +114 -0
  144. quater-0.1.0/src/quater/schema.py +153 -0
  145. quater-0.1.0/src/quater/security.py +276 -0
  146. quater-0.1.0/src/quater/serialization.py +45 -0
  147. quater-0.1.0/src/quater/testing.py +725 -0
  148. quater-0.1.0/src/quater/tools/__init__.py +46 -0
  149. quater-0.1.0/src/quater/tools/audit.py +29 -0
  150. quater-0.1.0/src/quater/tools/descriptions.py +40 -0
  151. quater-0.1.0/src/quater/tools/mcp.py +532 -0
  152. quater-0.1.0/src/quater/tools/registry.py +104 -0
  153. quater-0.1.0/src/quater/tools/schema.py +31 -0
  154. quater-0.1.0/src/quater/types.py +20 -0
  155. quater-0.1.0/src/quater/typing.py +88 -0
  156. quater-0.1.0/tests/__init__.py +1 -0
  157. quater-0.1.0/tests/conftest.py +26 -0
  158. quater-0.1.0/tests/integration/__init__.py +1 -0
  159. quater-0.1.0/tests/integration/test_action_protocol.py +652 -0
  160. quater-0.1.0/tests/integration/test_asgi_adapter.py +705 -0
  161. quater-0.1.0/tests/integration/test_auth_per_surface.py +590 -0
  162. quater-0.1.0/tests/integration/test_body_default_parity.py +291 -0
  163. quater-0.1.0/tests/integration/test_cross_surface_parity.py +550 -0
  164. quater-0.1.0/tests/integration/test_cross_transport_behavior.py +545 -0
  165. quater-0.1.0/tests/integration/test_examples_run.py +134 -0
  166. quater-0.1.0/tests/integration/test_mcp_audit.py +132 -0
  167. quater-0.1.0/tests/integration/test_mcp_auth_and_origin.py +296 -0
  168. quater-0.1.0/tests/integration/test_mcp_docs.py +165 -0
  169. quater-0.1.0/tests/integration/test_mcp_lifecycle.py +350 -0
  170. quater-0.1.0/tests/integration/test_mcp_tools_call.py +629 -0
  171. quater-0.1.0/tests/integration/test_mcp_tools_list.py +80 -0
  172. quater-0.1.0/tests/integration/test_openapi_docs.py +436 -0
  173. quater-0.1.0/tests/integration/test_resource_database_async.py +247 -0
  174. quater-0.1.0/tests/integration/test_resource_database_surfaces.py +311 -0
  175. quater-0.1.0/tests/integration/test_resource_database_sync.py +148 -0
  176. quater-0.1.0/tests/integration/test_rsgi_adapter.py +543 -0
  177. quater-0.1.0/tests/integration/test_wsgi_adapter.py +308 -0
  178. quater-0.1.0/tests/security/__init__.py +1 -0
  179. quater-0.1.0/tests/security/helpers.py +94 -0
  180. quater-0.1.0/tests/security/test_auth_fail_closed.py +261 -0
  181. quater-0.1.0/tests/security/test_cross_surface_exposure.py +175 -0
  182. quater-0.1.0/tests/security/test_form_file_safety.py +173 -0
  183. quater-0.1.0/tests/security/test_request_and_error_safety.py +201 -0
  184. quater-0.1.0/tests/security/test_request_context_isolation.py +241 -0
  185. quater-0.1.0/tests/security/test_router_path_safety.py +152 -0
  186. quater-0.1.0/tests/support/__init__.py +1 -0
  187. quater-0.1.0/tests/support/database.py +242 -0
  188. quater-0.1.0/tests/typing/public_api.py +42 -0
  189. quater-0.1.0/tests/typing/test_action_types.py +52 -0
  190. quater-0.1.0/tests/typing/test_adapter_types.py +15 -0
  191. quater-0.1.0/tests/typing/test_auth_types.py +83 -0
  192. quater-0.1.0/tests/typing/test_mcp_types.py +42 -0
  193. quater-0.1.0/tests/typing/test_middleware_types.py +43 -0
  194. quater-0.1.0/tests/typing/test_public_app_api.py +62 -0
  195. quater-0.1.0/tests/typing/test_quickstart_types.py +50 -0
  196. quater-0.1.0/tests/typing/test_request_response_types.py +66 -0
  197. quater-0.1.0/tests/typing/test_resource_types.py +67 -0
  198. quater-0.1.0/tests/typing/test_route_decorator_types.py +55 -0
  199. quater-0.1.0/tests/typing/test_test_client_types.py +61 -0
  200. quater-0.1.0/tests/unit/__init__.py +1 -0
  201. quater-0.1.0/tests/unit/cli/__init__.py +1 -0
  202. quater-0.1.0/tests/unit/cli/helpers.py +14 -0
  203. quater-0.1.0/tests/unit/cli/test_apps.py +110 -0
  204. quater-0.1.0/tests/unit/cli/test_discovery.py +115 -0
  205. quater-0.1.0/tests/unit/cli/test_local.py +723 -0
  206. quater-0.1.0/tests/unit/cli/test_output.py +260 -0
  207. quater-0.1.0/tests/unit/cli/test_parsing.py +120 -0
  208. quater-0.1.0/tests/unit/cli/test_remote_client.py +220 -0
  209. quater-0.1.0/tests/unit/cli/test_remote_commands.py +421 -0
  210. quater-0.1.0/tests/unit/cli/test_remote_config.py +189 -0
  211. quater-0.1.0/tests/unit/cli/test_server.py +709 -0
  212. quater-0.1.0/tests/unit/test_action_executor.py +629 -0
  213. quater-0.1.0/tests/unit/test_action_protocol_payloads.py +99 -0
  214. quater-0.1.0/tests/unit/test_action_registry.py +205 -0
  215. quater-0.1.0/tests/unit/test_adapter_shared.py +106 -0
  216. quater-0.1.0/tests/unit/test_allowed_hosts.py +340 -0
  217. quater-0.1.0/tests/unit/test_app_config.py +488 -0
  218. quater-0.1.0/tests/unit/test_auth_hook.py +290 -0
  219. quater-0.1.0/tests/unit/test_body_limits.py +105 -0
  220. quater-0.1.0/tests/unit/test_body_reading.py +113 -0
  221. quater-0.1.0/tests/unit/test_cors_policy.py +392 -0
  222. quater-0.1.0/tests/unit/test_datastructures.py +154 -0
  223. quater-0.1.0/tests/unit/test_debug_error_responses.py +70 -0
  224. quater-0.1.0/tests/unit/test_deployment.py +31 -0
  225. quater-0.1.0/tests/unit/test_exception_handling.py +111 -0
  226. quater-0.1.0/tests/unit/test_exceptions.py +10 -0
  227. quater-0.1.0/tests/unit/test_form_file_binding.py +266 -0
  228. quater-0.1.0/tests/unit/test_formdata_parsing.py +326 -0
  229. quater-0.1.0/tests/unit/test_handler_binding.py +121 -0
  230. quater-0.1.0/tests/unit/test_lifespan.py +146 -0
  231. quater-0.1.0/tests/unit/test_middleware_order.py +108 -0
  232. quater-0.1.0/tests/unit/test_middleware_short_circuit.py +34 -0
  233. quater-0.1.0/tests/unit/test_observability.py +237 -0
  234. quater-0.1.0/tests/unit/test_parameter_markers.py +277 -0
  235. quater-0.1.0/tests/unit/test_public_package_surface.py +153 -0
  236. quater-0.1.0/tests/unit/test_query_and_body_binding.py +188 -0
  237. quater-0.1.0/tests/unit/test_request_lazy_parsing.py +61 -0
  238. quater-0.1.0/tests/unit/test_request_resource_scope.py +605 -0
  239. quater-0.1.0/tests/unit/test_resource_dependencies.py +507 -0
  240. quater-0.1.0/tests/unit/test_resource_injection.py +541 -0
  241. quater-0.1.0/tests/unit/test_response_finalizers.py +99 -0
  242. quater-0.1.0/tests/unit/test_response_serialization.py +126 -0
  243. quater-0.1.0/tests/unit/test_route_conflicts.py +436 -0
  244. quater-0.1.0/tests/unit/test_route_group.py +591 -0
  245. quater-0.1.0/tests/unit/test_route_parsing.py +107 -0
  246. quater-0.1.0/tests/unit/test_router_matching.py +373 -0
  247. quater-0.1.0/tests/unit/test_schema_generation.py +119 -0
  248. quater-0.1.0/tests/unit/test_secure_headers.py +203 -0
  249. quater-0.1.0/tests/unit/test_signed_cookies.py +93 -0
  250. quater-0.1.0/tests/unit/test_state.py +257 -0
  251. quater-0.1.0/tests/unit/test_test_client.py +327 -0
  252. quater-0.1.0/tests/unit/test_tool_registry.py +156 -0
  253. quater-0.1.0/tests/unit/test_tool_schema_generation.py +183 -0
  254. quater-0.1.0/tests/unit/test_tools_public_surface.py +23 -0
  255. quater-0.1.0/uv.lock +1980 -0
  256. quater-0.1.0/vercel.json +18 -0
@@ -0,0 +1,34 @@
1
+ ---
2
+ name: Bug report
3
+ about: Report something that is broken or confusing
4
+ title: ""
5
+ assignees: ""
6
+ ---
7
+
8
+ ## What happened?
9
+
10
+
11
+ ## Expected behavior
12
+
13
+
14
+ ## Reproduction
15
+
16
+ Please share a small code example, command, or test case if possible.
17
+
18
+ ```python
19
+
20
+ ```
21
+
22
+ ## Environment
23
+
24
+ - Quater version:
25
+ - Python version:
26
+ - OS:
27
+
28
+ ## Extra context
29
+
30
+
31
+ ## Working on this?
32
+
33
+ Please wait until a maintainer marks the issue `accepted`. After that, comment
34
+ before starting and make sure nobody else is assigned or already working on it.
@@ -0,0 +1 @@
1
+ blank_issues_enabled: true
@@ -0,0 +1,20 @@
1
+ ---
2
+ name: Documentation
3
+ about: Report missing, confusing, or outdated docs
4
+ title: ""
5
+ assignees: ""
6
+ ---
7
+
8
+ ## Which docs page?
9
+
10
+
11
+ ## What is confusing or missing?
12
+
13
+
14
+ ## Suggested change
15
+
16
+
17
+ ## Working on this?
18
+
19
+ Please wait until a maintainer marks the issue `accepted`. After that, comment
20
+ before starting and make sure nobody else is assigned or already working on it.
@@ -0,0 +1,27 @@
1
+ ---
2
+ name: Feature request
3
+ about: Suggest a new feature or API change
4
+ title: ""
5
+ assignees: ""
6
+ ---
7
+
8
+ ## Problem
9
+
10
+ What are you trying to do, and what is hard today?
11
+
12
+ ## Proposed behavior
13
+
14
+
15
+ ## Alternatives considered
16
+
17
+
18
+ ## API sketch
19
+
20
+ ```python
21
+
22
+ ```
23
+
24
+ ## Working on this?
25
+
26
+ Please wait until a maintainer marks the issue `accepted`. After that, comment
27
+ before starting and make sure nobody else is assigned or already working on it.
@@ -0,0 +1,24 @@
1
+ ## Summary
2
+
3
+ <!-- Write 2-3 short bullets about what changed. -->
4
+
5
+ ## Linked Issue
6
+
7
+ Fixes #
8
+
9
+ ## Contributor Checklist
10
+
11
+ - [ ] The linked issue was marked `accepted` before I started.
12
+ - [ ] Nobody else was assigned or already working on the issue before I started.
13
+ - [ ] My branch is named `issue_{issue_number}`.
14
+ - [ ] The PR is focused on one issue with no unrelated changes.
15
+ - [ ] Tests are added or updated when behavior changes.
16
+ - [ ] Docs are updated when user-facing behavior changes.
17
+ - [ ] Changelog is updated when the change is release-visible.
18
+ - [ ] I listed the checks I ran below.
19
+
20
+ ## Checks Run
21
+
22
+ ```text
23
+
24
+ ```
@@ -0,0 +1,31 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: github-actions
4
+ directory: /
5
+ schedule:
6
+ interval: monthly
7
+ open-pull-requests-limit: 1
8
+ groups:
9
+ github-actions:
10
+ patterns:
11
+ - "*"
12
+
13
+ - package-ecosystem: npm
14
+ directory: /
15
+ schedule:
16
+ interval: monthly
17
+ open-pull-requests-limit: 1
18
+ groups:
19
+ docs-dependencies:
20
+ patterns:
21
+ - "*"
22
+
23
+ - package-ecosystem: cargo
24
+ directory: /
25
+ schedule:
26
+ interval: monthly
27
+ open-pull-requests-limit: 1
28
+ groups:
29
+ native-dependencies:
30
+ patterns:
31
+ - "*"
@@ -0,0 +1,126 @@
1
+ name: ci
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ pull_request:
8
+ branches:
9
+ - main
10
+
11
+ permissions:
12
+ contents: read
13
+
14
+ jobs:
15
+ checks:
16
+ runs-on: ubuntu-latest
17
+ steps:
18
+ - name: Checkout
19
+ uses: actions/checkout@v6
20
+
21
+ - name: Setup Python
22
+ uses: actions/setup-python@v6
23
+ with:
24
+ python-version: "3.13"
25
+
26
+ - name: Setup Rust
27
+ uses: dtolnay/rust-toolchain@stable
28
+
29
+ - name: Install uv
30
+ uses: astral-sh/setup-uv@v8.1.0
31
+ with:
32
+ enable-cache: true
33
+
34
+ - name: Install Python dependencies
35
+ run: uv sync --frozen --group dev --group release
36
+
37
+ - name: Format check
38
+ run: uv run --no-sync ruff format --check .
39
+
40
+ - name: Lint
41
+ run: uv run --no-sync ruff check .
42
+
43
+ - name: Type check
44
+ run: uv run --no-sync mypy src examples tests
45
+
46
+ - name: Security lint
47
+ run: uv run --no-sync bandit -q -c pyproject.toml -r src/quater
48
+
49
+ - name: Dependency audit
50
+ run: uv run --no-sync pip-audit
51
+
52
+ - name: Test Rust router
53
+ run: cargo test --locked
54
+
55
+ - name: Build package distributions
56
+ run: uv build
57
+
58
+ - name: Check package metadata
59
+ run: uv run --no-sync twine check dist/*
60
+
61
+ - name: Setup Node
62
+ uses: actions/setup-node@v6
63
+ with:
64
+ node-version: "20"
65
+ cache: npm
66
+
67
+ - name: Install docs dependencies
68
+ run: npm ci
69
+
70
+ - name: Audit docs dependencies
71
+ run: npm audit --audit-level=moderate
72
+
73
+ - name: Build docs
74
+ run: npm run docs:build
75
+
76
+ tests:
77
+ runs-on: ubuntu-latest
78
+ permissions:
79
+ contents: read
80
+ id-token: write
81
+ strategy:
82
+ fail-fast: false
83
+ matrix:
84
+ python-version:
85
+ - "3.11"
86
+ - "3.12"
87
+ - "3.13"
88
+ - "3.14"
89
+
90
+ steps:
91
+ - name: Checkout
92
+ uses: actions/checkout@v6
93
+
94
+ - name: Setup Python
95
+ uses: actions/setup-python@v6
96
+ with:
97
+ python-version: ${{ matrix.python-version }}
98
+
99
+ - name: Setup Rust
100
+ uses: dtolnay/rust-toolchain@stable
101
+
102
+ - name: Install uv
103
+ uses: astral-sh/setup-uv@v8.1.0
104
+ with:
105
+ enable-cache: true
106
+
107
+ - name: Install dependencies
108
+ run: uv sync --frozen --group dev
109
+
110
+ - name: Run tests with coverage
111
+ run: uv run --no-sync coverage run -m pytest -q
112
+
113
+ - name: Coverage report
114
+ run: uv run --no-sync coverage report
115
+
116
+ - name: Generate coverage XML
117
+ if: matrix.python-version == '3.13'
118
+ run: uv run --no-sync coverage xml -o coverage.xml
119
+
120
+ - name: Upload coverage to Codecov
121
+ if: ${{ matrix.python-version == '3.13' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) }}
122
+ uses: codecov/codecov-action@v6
123
+ with:
124
+ files: ./coverage.xml
125
+ fail_ci_if_error: true
126
+ use_oidc: true
@@ -0,0 +1,272 @@
1
+ name: release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+ workflow_dispatch:
8
+ inputs:
9
+ repository:
10
+ description: "Package index to publish to"
11
+ required: true
12
+ default: testpypi
13
+ type: choice
14
+ options:
15
+ - testpypi
16
+ - pypi
17
+
18
+ permissions:
19
+ contents: read
20
+
21
+ jobs:
22
+ verify:
23
+ runs-on: ubuntu-latest
24
+ steps:
25
+ - name: Checkout
26
+ uses: actions/checkout@v6
27
+
28
+ - name: Setup Python
29
+ uses: actions/setup-python@v6
30
+ with:
31
+ python-version: "3.13"
32
+
33
+ - name: Setup Rust
34
+ uses: dtolnay/rust-toolchain@stable
35
+
36
+ - name: Install uv
37
+ uses: astral-sh/setup-uv@v8.1.0
38
+ with:
39
+ enable-cache: true
40
+
41
+ - name: Install Python dependencies
42
+ run: uv sync --frozen --group dev --group release
43
+
44
+ - name: Format check
45
+ run: uv run --no-sync ruff format --check .
46
+
47
+ - name: Lint
48
+ run: uv run --no-sync ruff check .
49
+
50
+ - name: Type check
51
+ run: uv run --no-sync mypy src examples tests
52
+
53
+ - name: Run tests
54
+ run: uv run --no-sync pytest -q
55
+
56
+ - name: Test Rust router
57
+ run: cargo test --locked
58
+
59
+ - name: Setup Node
60
+ uses: actions/setup-node@v6
61
+ with:
62
+ node-version: "20"
63
+ cache: npm
64
+
65
+ - name: Install docs dependencies
66
+ run: npm ci
67
+
68
+ - name: Audit docs dependencies
69
+ run: npm audit --audit-level=moderate
70
+
71
+ - name: Build docs
72
+ run: npm run docs:build
73
+
74
+ build-sdist:
75
+ needs: verify
76
+ runs-on: ubuntu-latest
77
+ steps:
78
+ - name: Checkout
79
+ uses: actions/checkout@v6
80
+
81
+ - name: Setup Python
82
+ uses: actions/setup-python@v6
83
+ with:
84
+ python-version: "3.13"
85
+
86
+ - name: Install uv
87
+ uses: astral-sh/setup-uv@v8.1.0
88
+ with:
89
+ enable-cache: true
90
+
91
+ - name: Build source distribution
92
+ run: uv build --sdist --out-dir dist
93
+
94
+ - name: Upload source distribution
95
+ uses: actions/upload-artifact@v7
96
+ with:
97
+ name: sdist
98
+ path: dist/*
99
+
100
+ build-linux-wheels:
101
+ needs: verify
102
+ runs-on: ubuntu-latest
103
+ strategy:
104
+ fail-fast: false
105
+ matrix:
106
+ target:
107
+ - x86_64
108
+ - aarch64
109
+ steps:
110
+ - name: Checkout
111
+ uses: actions/checkout@v6
112
+
113
+ - name: Build wheels
114
+ uses: PyO3/maturin-action@v1
115
+ with:
116
+ command: build
117
+ target: ${{ matrix.target }}
118
+ args: --release --out dist --strip
119
+ manylinux: "2014"
120
+ sccache: "true"
121
+
122
+ - name: Upload wheels
123
+ uses: actions/upload-artifact@v7
124
+ with:
125
+ name: wheels-linux-${{ matrix.target }}
126
+ path: dist/*
127
+
128
+ build-macos-wheels:
129
+ needs: verify
130
+ runs-on: macos-latest
131
+ strategy:
132
+ fail-fast: false
133
+ matrix:
134
+ target:
135
+ - x86_64
136
+ - aarch64
137
+ steps:
138
+ - name: Checkout
139
+ uses: actions/checkout@v6
140
+
141
+ - name: Build wheels
142
+ uses: PyO3/maturin-action@v1
143
+ with:
144
+ command: build
145
+ target: ${{ matrix.target }}
146
+ args: --release --out dist --strip
147
+ sccache: "true"
148
+
149
+ - name: Upload wheels
150
+ uses: actions/upload-artifact@v7
151
+ with:
152
+ name: wheels-macos-${{ matrix.target }}
153
+ path: dist/*
154
+
155
+ build-windows-wheels:
156
+ needs: verify
157
+ runs-on: windows-latest
158
+ steps:
159
+ - name: Checkout
160
+ uses: actions/checkout@v6
161
+
162
+ - name: Build wheels
163
+ uses: PyO3/maturin-action@v1
164
+ with:
165
+ command: build
166
+ target: x64
167
+ args: --release --out dist --strip
168
+ sccache: "true"
169
+
170
+ - name: Upload wheels
171
+ uses: actions/upload-artifact@v7
172
+ with:
173
+ name: wheels-windows-x64
174
+ path: dist/*
175
+
176
+ validate-distributions:
177
+ needs:
178
+ - build-sdist
179
+ - build-linux-wheels
180
+ - build-macos-wheels
181
+ - build-windows-wheels
182
+ runs-on: ubuntu-latest
183
+ steps:
184
+ - name: Checkout
185
+ uses: actions/checkout@v6
186
+
187
+ - name: Download distributions
188
+ uses: actions/download-artifact@v8
189
+ with:
190
+ path: dist
191
+ merge-multiple: true
192
+
193
+ - name: Setup Python
194
+ uses: actions/setup-python@v6
195
+ with:
196
+ python-version: "3.13"
197
+
198
+ - name: Install uv
199
+ uses: astral-sh/setup-uv@v8.1.0
200
+ with:
201
+ enable-cache: true
202
+
203
+ - name: Install release dependencies
204
+ run: uv sync --frozen --no-default-groups --group release --no-install-project
205
+
206
+ - name: Check package metadata
207
+ run: uv run --no-sync twine check dist/*
208
+
209
+ - name: Upload checked distributions
210
+ uses: actions/upload-artifact@v7
211
+ with:
212
+ name: python-package-distributions
213
+ path: dist/*
214
+
215
+ publish-testpypi:
216
+ needs: validate-distributions
217
+ if: github.event_name == 'workflow_dispatch' && inputs.repository == 'testpypi'
218
+ runs-on: ubuntu-latest
219
+ environment:
220
+ name: testpypi
221
+ url: https://test.pypi.org/p/quater
222
+ permissions:
223
+ contents: read
224
+ id-token: write
225
+ steps:
226
+ - name: Download distributions
227
+ uses: actions/download-artifact@v8
228
+ with:
229
+ name: python-package-distributions
230
+ path: dist
231
+
232
+ - name: Publish to TestPyPI
233
+ uses: pypa/gh-action-pypi-publish@release/v1
234
+ with:
235
+ repository-url: https://test.pypi.org/legacy/
236
+
237
+ publish-pypi:
238
+ needs: validate-distributions
239
+ if: (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')) || (github.event_name == 'workflow_dispatch' && inputs.repository == 'pypi')
240
+ runs-on: ubuntu-latest
241
+ environment:
242
+ name: pypi
243
+ url: https://pypi.org/p/quater
244
+ permissions:
245
+ contents: read
246
+ id-token: write
247
+ steps:
248
+ - name: Download distributions
249
+ uses: actions/download-artifact@v8
250
+ with:
251
+ name: python-package-distributions
252
+ path: dist
253
+
254
+ - name: Publish to PyPI
255
+ uses: pypa/gh-action-pypi-publish@release/v1
256
+
257
+ refresh-docs:
258
+ # Stable docs track the latest release tag, so rebuild the Vercel site once
259
+ # the package actually ships. Skipped automatically for TestPyPI dry runs
260
+ # (publish-pypi does not run, so this job's dependency is unmet).
261
+ needs: publish-pypi
262
+ runs-on: ubuntu-latest
263
+ steps:
264
+ - name: Trigger Vercel docs rebuild
265
+ env:
266
+ DEPLOY_HOOK: ${{ secrets.VERCEL_DEPLOY_HOOK }}
267
+ run: |
268
+ if [ -z "$DEPLOY_HOOK" ]; then
269
+ echo "VERCEL_DEPLOY_HOOK secret not set; skipping docs rebuild." >&2
270
+ exit 0
271
+ fi
272
+ curl -fsS -X POST "$DEPLOY_HOOK"
@@ -0,0 +1,35 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.pyo
5
+
6
+ # Build artifacts
7
+ build/
8
+ dist/
9
+ *.egg-info/
10
+
11
+ # Tool caches
12
+ .mypy_cache/
13
+ .pytest_cache/
14
+ .ruff_cache/
15
+ .uv-cache/
16
+ .coverage
17
+ node_modules/
18
+ docs/.vitepress/cache/
19
+ docs/.vitepress/dist/
20
+ docs/en/stable/
21
+ .docs-channels/
22
+
23
+ # Virtual environments
24
+ .venv/
25
+ venv/
26
+
27
+ # Local environment
28
+ .env
29
+ .env.*
30
+ notes/
31
+ sample_projects
32
+ target/
33
+ src/quater/*.so
34
+ .bench-venv
35
+ .gstack/
@@ -0,0 +1,20 @@
1
+ repos:
2
+ - repo: local
3
+ hooks:
4
+ - id: ruff-format
5
+ name: ruff format
6
+ entry: uv run --no-sync ruff format --check .
7
+ language: system
8
+ pass_filenames: false
9
+
10
+ - id: ruff-check
11
+ name: ruff check
12
+ entry: uv run --no-sync ruff check .
13
+ language: system
14
+ pass_filenames: false
15
+
16
+ - id: mypy
17
+ name: mypy
18
+ entry: uv run --no-sync mypy src examples tests
19
+ language: system
20
+ pass_filenames: false