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.
- quater-0.1.0/.github/ISSUE_TEMPLATE/bug_report.md +34 -0
- quater-0.1.0/.github/ISSUE_TEMPLATE/config.yml +1 -0
- quater-0.1.0/.github/ISSUE_TEMPLATE/documentation.md +20 -0
- quater-0.1.0/.github/ISSUE_TEMPLATE/feature_request.md +27 -0
- quater-0.1.0/.github/PULL_REQUEST_TEMPLATE.md +24 -0
- quater-0.1.0/.github/dependabot.yml +31 -0
- quater-0.1.0/.github/workflows/ci.yml +126 -0
- quater-0.1.0/.github/workflows/release.yml +272 -0
- quater-0.1.0/.gitignore +35 -0
- quater-0.1.0/.pre-commit-config.yaml +20 -0
- quater-0.1.0/CONTRIBUTING.md +290 -0
- quater-0.1.0/Cargo.lock +140 -0
- quater-0.1.0/Cargo.toml +18 -0
- quater-0.1.0/LICENSE +21 -0
- quater-0.1.0/PKG-INFO +356 -0
- quater-0.1.0/README.md +326 -0
- quater-0.1.0/agent-skills/README.md +36 -0
- quater-0.1.0/agent-skills/quater-apps/SKILL.md +113 -0
- quater-0.1.0/agent-skills/quater-apps/agents/openai.yaml +4 -0
- quater-0.1.0/agent-skills/quater-apps/references/auth.md +67 -0
- quater-0.1.0/agent-skills/quater-apps/references/cli-actions.md +291 -0
- quater-0.1.0/agent-skills/quater-apps/references/mcp.md +151 -0
- quater-0.1.0/agent-skills/quater-apps/references/safety.md +99 -0
- quater-0.1.0/agent-skills/quater-framework/SKILL.md +82 -0
- quater-0.1.0/agent-skills/quater-framework/agents/openai.yaml +4 -0
- quater-0.1.0/agent-skills/quater-framework/references/app-patterns.md +112 -0
- quater-0.1.0/agent-skills/quater-framework/references/deployment.md +68 -0
- quater-0.1.0/agent-skills/quater-framework/references/resources-testing.md +114 -0
- quater-0.1.0/agent-skills/quater-framework/references/surfaces.md +79 -0
- quater-0.1.0/benchmarks/.gitignore +1 -0
- quater-0.1.0/benchmarks/README.md +279 -0
- quater-0.1.0/benchmarks/apps/db_fastapi.py +222 -0
- quater-0.1.0/benchmarks/apps/db_quater.py +201 -0
- quater-0.1.0/benchmarks/apps/no_db_fastapi.py +105 -0
- quater-0.1.0/benchmarks/apps/no_db_quater.py +107 -0
- quater-0.1.0/benchmarks/assets/no-db-p95.svg +46 -0
- quater-0.1.0/benchmarks/assets/no-db-throughput.svg +46 -0
- quater-0.1.0/benchmarks/assets/postgres-p95.svg +46 -0
- quater-0.1.0/benchmarks/assets/postgres-throughput.svg +46 -0
- quater-0.1.0/benchmarks/docker-compose.yml +19 -0
- quater-0.1.0/benchmarks/scripts/generate_charts.py +261 -0
- quater-0.1.0/benchmarks/scripts/run_suite.py +322 -0
- quater-0.1.0/docs/.vitepress/config.mts +307 -0
- quater-0.1.0/docs/.vitepress/theme/components/MermaidDiagram.vue +75 -0
- quater-0.1.0/docs/.vitepress/theme/index.ts +11 -0
- quater-0.1.0/docs/.vitepress/theme/style.css +75 -0
- quater-0.1.0/docs/en/dev/actions.md +445 -0
- quater-0.1.0/docs/en/dev/api.md +444 -0
- quater-0.1.0/docs/en/dev/auth-model.md +229 -0
- quater-0.1.0/docs/en/dev/changelog.md +244 -0
- quater-0.1.0/docs/en/dev/contributing.md +259 -0
- quater-0.1.0/docs/en/dev/deployment.md +234 -0
- quater-0.1.0/docs/en/dev/index.md +219 -0
- quater-0.1.0/docs/en/dev/known-limitations.md +60 -0
- quater-0.1.0/docs/en/dev/mcp.md +326 -0
- quater-0.1.0/docs/en/dev/middleware-errors.md +230 -0
- quater-0.1.0/docs/en/dev/quickstart.md +322 -0
- quater-0.1.0/docs/en/dev/reference/application.md +358 -0
- quater-0.1.0/docs/en/dev/reference/auth.md +236 -0
- quater-0.1.0/docs/en/dev/reference/index.md +58 -0
- quater-0.1.0/docs/en/dev/reference/observability.md +149 -0
- quater-0.1.0/docs/en/dev/reference/parameters.md +283 -0
- quater-0.1.0/docs/en/dev/reference/request.md +309 -0
- quater-0.1.0/docs/en/dev/reference/resources.md +148 -0
- quater-0.1.0/docs/en/dev/reference/responses.md +168 -0
- quater-0.1.0/docs/en/dev/reference/testing.md +210 -0
- quater-0.1.0/docs/en/dev/resources.md +427 -0
- quater-0.1.0/docs/en/dev/routes-handlers.md +175 -0
- quater-0.1.0/docs/en/dev/security.md +314 -0
- quater-0.1.0/docs/en/dev/stability.md +129 -0
- quater-0.1.0/docs/en/dev/surfaces.md +149 -0
- quater-0.1.0/docs/en/dev/testing.md +363 -0
- quater-0.1.0/docs/en/dev/why-quater.md +92 -0
- quater-0.1.0/docs/index.md +121 -0
- quater-0.1.0/docs/public/logo-black-bg.svg +8 -0
- quater-0.1.0/docs/public/logo-no-bg.svg +7 -0
- quater-0.1.0/docs/public/logo-white-bg.svg +8 -0
- quater-0.1.0/docs/public/robots.txt +4 -0
- quater-0.1.0/examples/__init__.py +1 -0
- quater-0.1.0/examples/asgi_compat.py +5 -0
- quater-0.1.0/examples/auth_and_mcp.py +48 -0
- quater-0.1.0/examples/basic_app.py +20 -0
- quater-0.1.0/examples/wsgi_compat.py +5 -0
- quater-0.1.0/native/router/src/lib.rs +238 -0
- quater-0.1.0/package-lock.json +3826 -0
- quater-0.1.0/package.json +23 -0
- quater-0.1.0/pyproject.toml +107 -0
- quater-0.1.0/release/0.1.0a1.md +54 -0
- quater-0.1.0/scripts/build-docs-site.mjs +325 -0
- quater-0.1.0/scripts/generate_reference.py +2392 -0
- quater-0.1.0/src/quater/__init__.py +72 -0
- quater-0.1.0/src/quater/_api_boundary.py +89 -0
- quater-0.1.0/src/quater/_finalize.py +84 -0
- quater-0.1.0/src/quater/_parameters.py +198 -0
- quater-0.1.0/src/quater/_router.pyi +22 -0
- quater-0.1.0/src/quater/_state.py +21 -0
- quater-0.1.0/src/quater/actions/__init__.py +1 -0
- quater-0.1.0/src/quater/actions/approval.py +81 -0
- quater-0.1.0/src/quater/actions/descriptions.py +45 -0
- quater-0.1.0/src/quater/actions/executor.py +497 -0
- quater-0.1.0/src/quater/actions/registry.py +83 -0
- quater-0.1.0/src/quater/adapters/__init__.py +7 -0
- quater-0.1.0/src/quater/adapters/_shared.py +108 -0
- quater-0.1.0/src/quater/adapters/asgi.py +222 -0
- quater-0.1.0/src/quater/adapters/rsgi.py +159 -0
- quater-0.1.0/src/quater/adapters/wsgi.py +165 -0
- quater-0.1.0/src/quater/app.py +1442 -0
- quater-0.1.0/src/quater/auth.py +258 -0
- quater-0.1.0/src/quater/cli/__init__.py +1 -0
- quater-0.1.0/src/quater/cli/apps.py +57 -0
- quater-0.1.0/src/quater/cli/client.py +134 -0
- quater-0.1.0/src/quater/cli/discovery.py +229 -0
- quater-0.1.0/src/quater/cli/errors.py +54 -0
- quater-0.1.0/src/quater/cli/main.py +515 -0
- quater-0.1.0/src/quater/cli/output.py +380 -0
- quater-0.1.0/src/quater/cli/parsing.py +83 -0
- quater-0.1.0/src/quater/cli/remotes.py +140 -0
- quater-0.1.0/src/quater/cli/server.py +130 -0
- quater-0.1.0/src/quater/config.py +480 -0
- quater-0.1.0/src/quater/cookies.py +87 -0
- quater-0.1.0/src/quater/core.py +95 -0
- quater-0.1.0/src/quater/cors.py +246 -0
- quater-0.1.0/src/quater/datastructures.py +183 -0
- quater-0.1.0/src/quater/dependencies.py +472 -0
- quater-0.1.0/src/quater/deployment.py +41 -0
- quater-0.1.0/src/quater/docs/__init__.py +1 -0
- quater-0.1.0/src/quater/docs/html.py +277 -0
- quater-0.1.0/src/quater/docs/openapi.py +279 -0
- quater-0.1.0/src/quater/docs/swagger.py +87 -0
- quater-0.1.0/src/quater/exceptions.py +120 -0
- quater-0.1.0/src/quater/formdata.py +377 -0
- quater-0.1.0/src/quater/groups.py +605 -0
- quater-0.1.0/src/quater/lifespan.py +86 -0
- quater-0.1.0/src/quater/middleware.py +262 -0
- quater-0.1.0/src/quater/observability.py +152 -0
- quater-0.1.0/src/quater/params.py +902 -0
- quater-0.1.0/src/quater/protocol/__init__.py +1 -0
- quater-0.1.0/src/quater/protocol/actions.py +125 -0
- quater-0.1.0/src/quater/py.typed +1 -0
- quater-0.1.0/src/quater/request.py +462 -0
- quater-0.1.0/src/quater/response.py +268 -0
- quater-0.1.0/src/quater/router.py +357 -0
- quater-0.1.0/src/quater/routing.py +114 -0
- quater-0.1.0/src/quater/schema.py +153 -0
- quater-0.1.0/src/quater/security.py +276 -0
- quater-0.1.0/src/quater/serialization.py +45 -0
- quater-0.1.0/src/quater/testing.py +725 -0
- quater-0.1.0/src/quater/tools/__init__.py +46 -0
- quater-0.1.0/src/quater/tools/audit.py +29 -0
- quater-0.1.0/src/quater/tools/descriptions.py +40 -0
- quater-0.1.0/src/quater/tools/mcp.py +532 -0
- quater-0.1.0/src/quater/tools/registry.py +104 -0
- quater-0.1.0/src/quater/tools/schema.py +31 -0
- quater-0.1.0/src/quater/types.py +20 -0
- quater-0.1.0/src/quater/typing.py +88 -0
- quater-0.1.0/tests/__init__.py +1 -0
- quater-0.1.0/tests/conftest.py +26 -0
- quater-0.1.0/tests/integration/__init__.py +1 -0
- quater-0.1.0/tests/integration/test_action_protocol.py +652 -0
- quater-0.1.0/tests/integration/test_asgi_adapter.py +705 -0
- quater-0.1.0/tests/integration/test_auth_per_surface.py +590 -0
- quater-0.1.0/tests/integration/test_body_default_parity.py +291 -0
- quater-0.1.0/tests/integration/test_cross_surface_parity.py +550 -0
- quater-0.1.0/tests/integration/test_cross_transport_behavior.py +545 -0
- quater-0.1.0/tests/integration/test_examples_run.py +134 -0
- quater-0.1.0/tests/integration/test_mcp_audit.py +132 -0
- quater-0.1.0/tests/integration/test_mcp_auth_and_origin.py +296 -0
- quater-0.1.0/tests/integration/test_mcp_docs.py +165 -0
- quater-0.1.0/tests/integration/test_mcp_lifecycle.py +350 -0
- quater-0.1.0/tests/integration/test_mcp_tools_call.py +629 -0
- quater-0.1.0/tests/integration/test_mcp_tools_list.py +80 -0
- quater-0.1.0/tests/integration/test_openapi_docs.py +436 -0
- quater-0.1.0/tests/integration/test_resource_database_async.py +247 -0
- quater-0.1.0/tests/integration/test_resource_database_surfaces.py +311 -0
- quater-0.1.0/tests/integration/test_resource_database_sync.py +148 -0
- quater-0.1.0/tests/integration/test_rsgi_adapter.py +543 -0
- quater-0.1.0/tests/integration/test_wsgi_adapter.py +308 -0
- quater-0.1.0/tests/security/__init__.py +1 -0
- quater-0.1.0/tests/security/helpers.py +94 -0
- quater-0.1.0/tests/security/test_auth_fail_closed.py +261 -0
- quater-0.1.0/tests/security/test_cross_surface_exposure.py +175 -0
- quater-0.1.0/tests/security/test_form_file_safety.py +173 -0
- quater-0.1.0/tests/security/test_request_and_error_safety.py +201 -0
- quater-0.1.0/tests/security/test_request_context_isolation.py +241 -0
- quater-0.1.0/tests/security/test_router_path_safety.py +152 -0
- quater-0.1.0/tests/support/__init__.py +1 -0
- quater-0.1.0/tests/support/database.py +242 -0
- quater-0.1.0/tests/typing/public_api.py +42 -0
- quater-0.1.0/tests/typing/test_action_types.py +52 -0
- quater-0.1.0/tests/typing/test_adapter_types.py +15 -0
- quater-0.1.0/tests/typing/test_auth_types.py +83 -0
- quater-0.1.0/tests/typing/test_mcp_types.py +42 -0
- quater-0.1.0/tests/typing/test_middleware_types.py +43 -0
- quater-0.1.0/tests/typing/test_public_app_api.py +62 -0
- quater-0.1.0/tests/typing/test_quickstart_types.py +50 -0
- quater-0.1.0/tests/typing/test_request_response_types.py +66 -0
- quater-0.1.0/tests/typing/test_resource_types.py +67 -0
- quater-0.1.0/tests/typing/test_route_decorator_types.py +55 -0
- quater-0.1.0/tests/typing/test_test_client_types.py +61 -0
- quater-0.1.0/tests/unit/__init__.py +1 -0
- quater-0.1.0/tests/unit/cli/__init__.py +1 -0
- quater-0.1.0/tests/unit/cli/helpers.py +14 -0
- quater-0.1.0/tests/unit/cli/test_apps.py +110 -0
- quater-0.1.0/tests/unit/cli/test_discovery.py +115 -0
- quater-0.1.0/tests/unit/cli/test_local.py +723 -0
- quater-0.1.0/tests/unit/cli/test_output.py +260 -0
- quater-0.1.0/tests/unit/cli/test_parsing.py +120 -0
- quater-0.1.0/tests/unit/cli/test_remote_client.py +220 -0
- quater-0.1.0/tests/unit/cli/test_remote_commands.py +421 -0
- quater-0.1.0/tests/unit/cli/test_remote_config.py +189 -0
- quater-0.1.0/tests/unit/cli/test_server.py +709 -0
- quater-0.1.0/tests/unit/test_action_executor.py +629 -0
- quater-0.1.0/tests/unit/test_action_protocol_payloads.py +99 -0
- quater-0.1.0/tests/unit/test_action_registry.py +205 -0
- quater-0.1.0/tests/unit/test_adapter_shared.py +106 -0
- quater-0.1.0/tests/unit/test_allowed_hosts.py +340 -0
- quater-0.1.0/tests/unit/test_app_config.py +488 -0
- quater-0.1.0/tests/unit/test_auth_hook.py +290 -0
- quater-0.1.0/tests/unit/test_body_limits.py +105 -0
- quater-0.1.0/tests/unit/test_body_reading.py +113 -0
- quater-0.1.0/tests/unit/test_cors_policy.py +392 -0
- quater-0.1.0/tests/unit/test_datastructures.py +154 -0
- quater-0.1.0/tests/unit/test_debug_error_responses.py +70 -0
- quater-0.1.0/tests/unit/test_deployment.py +31 -0
- quater-0.1.0/tests/unit/test_exception_handling.py +111 -0
- quater-0.1.0/tests/unit/test_exceptions.py +10 -0
- quater-0.1.0/tests/unit/test_form_file_binding.py +266 -0
- quater-0.1.0/tests/unit/test_formdata_parsing.py +326 -0
- quater-0.1.0/tests/unit/test_handler_binding.py +121 -0
- quater-0.1.0/tests/unit/test_lifespan.py +146 -0
- quater-0.1.0/tests/unit/test_middleware_order.py +108 -0
- quater-0.1.0/tests/unit/test_middleware_short_circuit.py +34 -0
- quater-0.1.0/tests/unit/test_observability.py +237 -0
- quater-0.1.0/tests/unit/test_parameter_markers.py +277 -0
- quater-0.1.0/tests/unit/test_public_package_surface.py +153 -0
- quater-0.1.0/tests/unit/test_query_and_body_binding.py +188 -0
- quater-0.1.0/tests/unit/test_request_lazy_parsing.py +61 -0
- quater-0.1.0/tests/unit/test_request_resource_scope.py +605 -0
- quater-0.1.0/tests/unit/test_resource_dependencies.py +507 -0
- quater-0.1.0/tests/unit/test_resource_injection.py +541 -0
- quater-0.1.0/tests/unit/test_response_finalizers.py +99 -0
- quater-0.1.0/tests/unit/test_response_serialization.py +126 -0
- quater-0.1.0/tests/unit/test_route_conflicts.py +436 -0
- quater-0.1.0/tests/unit/test_route_group.py +591 -0
- quater-0.1.0/tests/unit/test_route_parsing.py +107 -0
- quater-0.1.0/tests/unit/test_router_matching.py +373 -0
- quater-0.1.0/tests/unit/test_schema_generation.py +119 -0
- quater-0.1.0/tests/unit/test_secure_headers.py +203 -0
- quater-0.1.0/tests/unit/test_signed_cookies.py +93 -0
- quater-0.1.0/tests/unit/test_state.py +257 -0
- quater-0.1.0/tests/unit/test_test_client.py +327 -0
- quater-0.1.0/tests/unit/test_tool_registry.py +156 -0
- quater-0.1.0/tests/unit/test_tool_schema_generation.py +183 -0
- quater-0.1.0/tests/unit/test_tools_public_surface.py +23 -0
- quater-0.1.0/uv.lock +1980 -0
- 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"
|
quater-0.1.0/.gitignore
ADDED
|
@@ -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
|