routedef 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.
- routedef-0.1.0/.ci/max-loc-baseline.json +5 -0
- routedef-0.1.0/.ci/mutation-baseline.json +4 -0
- routedef-0.1.0/.ci/xenon-baseline.json +6 -0
- routedef-0.1.0/.github/workflows/ci.yml +120 -0
- routedef-0.1.0/.gitignore +14 -0
- routedef-0.1.0/.pre-commit-config.yaml +127 -0
- routedef-0.1.0/.secrets.baseline +106 -0
- routedef-0.1.0/LICENSE +21 -0
- routedef-0.1.0/LICENSES/MIT.txt +21 -0
- routedef-0.1.0/PKG-INFO +119 -0
- routedef-0.1.0/README.md +103 -0
- routedef-0.1.0/REUSE.toml +48 -0
- routedef-0.1.0/VERSION +1 -0
- routedef-0.1.0/docs/architecture.md +84 -0
- routedef-0.1.0/docs/diagrams/routedef-flow.puml +31 -0
- routedef-0.1.0/docs/diagrams/routedef-flow.svg +1 -0
- routedef-0.1.0/docs/diagrams/runtime-adapters.puml +50 -0
- routedef-0.1.0/docs/diagrams/runtime-adapters.svg +1 -0
- routedef-0.1.0/docs/migration.md +131 -0
- routedef-0.1.0/docs/superpowers/plans/2026-07-03-routedef-package-implementation.md +323 -0
- routedef-0.1.0/docs/superpowers/specs/2026-07-03-routedef-package-architecture-design.md +243 -0
- routedef-0.1.0/examples/cloudflare-worker/pyproject.toml +12 -0
- routedef-0.1.0/examples/cloudflare-worker/src/entry.py +44 -0
- routedef-0.1.0/examples/cloudflare-worker/wrangler.jsonc +11 -0
- routedef-0.1.0/pyproject.toml +128 -0
- routedef-0.1.0/scripts/check_build_install.py +87 -0
- routedef-0.1.0/scripts/check_cloudflare_worker.py +286 -0
- routedef-0.1.0/scripts/check_licenses.py +20 -0
- routedef-0.1.0/scripts/check_max_loc.py +91 -0
- routedef-0.1.0/scripts/check_spdx_headers.py +73 -0
- routedef-0.1.0/scripts/check_xenon.py +40 -0
- routedef-0.1.0/scripts/mutation_gate.py +54 -0
- routedef-0.1.0/scripts/retry_command.py +54 -0
- routedef-0.1.0/src/routedef/__init__.py +38 -0
- routedef-0.1.0/src/routedef/adapters/__init__.py +2 -0
- routedef-0.1.0/src/routedef/adapters/cloudflare.py +316 -0
- routedef-0.1.0/src/routedef/adapters/errors.py +17 -0
- routedef-0.1.0/src/routedef/adapters/fastapi.py +184 -0
- routedef-0.1.0/src/routedef/contracts.py +165 -0
- routedef-0.1.0/src/routedef/errors.py +10 -0
- routedef-0.1.0/src/routedef/headers.py +16 -0
- routedef-0.1.0/src/routedef/matching.py +97 -0
- routedef-0.1.0/src/routedef/py.typed +1 -0
- routedef-0.1.0/src/routedef/request.py +31 -0
- routedef-0.1.0/src/routedef/response.py +36 -0
- routedef-0.1.0/src/routedef/table.py +73 -0
- routedef-0.1.0/src/routedef/types.py +9 -0
- routedef-0.1.0/src/routedef/version.py +23 -0
- routedef-0.1.0/tests/cloudflare_fakes.py +136 -0
- routedef-0.1.0/tests/test_build_install_script.py +49 -0
- routedef-0.1.0/tests/test_cloudflare_adapter.py +459 -0
- routedef-0.1.0/tests/test_cloudflare_adapter_errors.py +113 -0
- routedef-0.1.0/tests/test_cloudflare_integration_script.py +122 -0
- routedef-0.1.0/tests/test_contracts.py +312 -0
- routedef-0.1.0/tests/test_fastapi_adapter.py +377 -0
- routedef-0.1.0/tests/test_headers.py +20 -0
- routedef-0.1.0/tests/test_logging_policy.py +44 -0
- routedef-0.1.0/tests/test_matching.py +125 -0
- routedef-0.1.0/tests/test_mutation_gate.py +65 -0
- routedef-0.1.0/tests/test_package_metadata.py +73 -0
- routedef-0.1.0/tests/test_quality_scripts.py +115 -0
- routedef-0.1.0/tests/test_request.py +36 -0
- routedef-0.1.0/tests/test_response.py +67 -0
- routedef-0.1.0/tests/test_retry_command.py +44 -0
- routedef-0.1.0/tests/test_table.py +112 -0
- routedef-0.1.0/tests/test_undef_style.py +329 -0
- routedef-0.1.0/tests/test_uwarp_style.py +101 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: ["main", "feature/**"]
|
|
6
|
+
tags: ["v*"]
|
|
7
|
+
pull_request:
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
|
|
10
|
+
permissions:
|
|
11
|
+
contents: read
|
|
12
|
+
|
|
13
|
+
env:
|
|
14
|
+
UV_FROZEN: "0"
|
|
15
|
+
UV_LINK_MODE: copy
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
quality:
|
|
19
|
+
name: Quality (${{ matrix.python-version }})
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
strategy:
|
|
22
|
+
fail-fast: false
|
|
23
|
+
matrix:
|
|
24
|
+
python-version: ["3.11", "3.12", "3.13"]
|
|
25
|
+
steps:
|
|
26
|
+
- name: Check out source
|
|
27
|
+
uses: actions/checkout@v7
|
|
28
|
+
|
|
29
|
+
- name: Prepare git metadata for act
|
|
30
|
+
if: ${{ env.ACT == 'true' }}
|
|
31
|
+
run: |
|
|
32
|
+
rm -rf .git
|
|
33
|
+
git init
|
|
34
|
+
git config user.email "act@example.invalid"
|
|
35
|
+
git config user.name "act"
|
|
36
|
+
git add .
|
|
37
|
+
|
|
38
|
+
- name: Install uv
|
|
39
|
+
run: |
|
|
40
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
41
|
+
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
|
|
42
|
+
|
|
43
|
+
- name: Install Python
|
|
44
|
+
run: |
|
|
45
|
+
uv python install ${{ matrix.python-version }}
|
|
46
|
+
|
|
47
|
+
- name: Install dependencies
|
|
48
|
+
run: uv sync --python ${{ matrix.python-version }} --all-extras --dev
|
|
49
|
+
|
|
50
|
+
- name: Run pre-commit
|
|
51
|
+
run: uv run pre-commit run --all-files
|
|
52
|
+
|
|
53
|
+
- name: Run coverage gate
|
|
54
|
+
run: uv run python scripts/retry_command.py --exit-code 139 -- uv run pytest -q --cov=src/routedef --cov-branch --cov-report=term-missing --cov-fail-under=100
|
|
55
|
+
|
|
56
|
+
package:
|
|
57
|
+
name: Package
|
|
58
|
+
runs-on: ubuntu-latest
|
|
59
|
+
steps:
|
|
60
|
+
- name: Check out source
|
|
61
|
+
uses: actions/checkout@v7
|
|
62
|
+
|
|
63
|
+
- name: Install uv
|
|
64
|
+
run: |
|
|
65
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
66
|
+
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
|
|
67
|
+
|
|
68
|
+
- name: Install Python
|
|
69
|
+
run: |
|
|
70
|
+
uv python install 3.13
|
|
71
|
+
|
|
72
|
+
- name: Install dependencies
|
|
73
|
+
run: uv sync --python 3.13 --all-extras --dev
|
|
74
|
+
|
|
75
|
+
- name: Build and smoke-test wheel
|
|
76
|
+
run: uv run python scripts/check_build_install.py
|
|
77
|
+
|
|
78
|
+
cloudflare-worker:
|
|
79
|
+
name: Cloudflare Worker
|
|
80
|
+
runs-on: ubuntu-latest
|
|
81
|
+
steps:
|
|
82
|
+
- name: Check out source
|
|
83
|
+
uses: actions/checkout@v7
|
|
84
|
+
|
|
85
|
+
- name: Install uv
|
|
86
|
+
run: |
|
|
87
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
88
|
+
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
|
|
89
|
+
|
|
90
|
+
- name: Install Python
|
|
91
|
+
run: |
|
|
92
|
+
uv python install 3.13
|
|
93
|
+
|
|
94
|
+
- name: Install dependencies
|
|
95
|
+
run: uv sync --python 3.13 --all-extras --dev
|
|
96
|
+
|
|
97
|
+
- name: Run Cloudflare Python Worker integration
|
|
98
|
+
run: uv run python scripts/check_cloudflare_worker.py
|
|
99
|
+
|
|
100
|
+
mutation:
|
|
101
|
+
name: Mutation
|
|
102
|
+
runs-on: ubuntu-latest
|
|
103
|
+
steps:
|
|
104
|
+
- name: Check out source
|
|
105
|
+
uses: actions/checkout@v7
|
|
106
|
+
|
|
107
|
+
- name: Install uv
|
|
108
|
+
run: |
|
|
109
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
110
|
+
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
|
|
111
|
+
|
|
112
|
+
- name: Install Python
|
|
113
|
+
run: |
|
|
114
|
+
uv python install 3.13
|
|
115
|
+
|
|
116
|
+
- name: Install dependencies
|
|
117
|
+
run: uv sync --python 3.13 --all-extras --dev
|
|
118
|
+
|
|
119
|
+
- name: Run mutation gate
|
|
120
|
+
run: uv run python scripts/mutation_gate.py
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
repos:
|
|
2
|
+
- repo: local
|
|
3
|
+
hooks:
|
|
4
|
+
- id: detect-secrets
|
|
5
|
+
name: Detect secrets
|
|
6
|
+
entry: uv run python scripts/retry_command.py --exit-code 139 -- uv run detect-secrets-hook --baseline .secrets.baseline
|
|
7
|
+
language: system
|
|
8
|
+
|
|
9
|
+
- id: ruff-check
|
|
10
|
+
name: ruff check
|
|
11
|
+
entry: uv run ruff check --exit-non-zero-on-fix
|
|
12
|
+
language: system
|
|
13
|
+
types: [python]
|
|
14
|
+
|
|
15
|
+
- id: ruff-format
|
|
16
|
+
name: ruff format
|
|
17
|
+
entry: uv run ruff format --check
|
|
18
|
+
language: system
|
|
19
|
+
types: [python]
|
|
20
|
+
|
|
21
|
+
- id: codespell
|
|
22
|
+
name: codespell
|
|
23
|
+
entry: uv run python scripts/retry_command.py --exit-code 139 -- uv run codespell
|
|
24
|
+
language: system
|
|
25
|
+
|
|
26
|
+
- id: max-loc
|
|
27
|
+
name: python max loc
|
|
28
|
+
entry: uv run python scripts/check_max_loc.py --max-lines 500 --roots .
|
|
29
|
+
language: system
|
|
30
|
+
pass_filenames: false
|
|
31
|
+
always_run: true
|
|
32
|
+
|
|
33
|
+
- id: spdx-headers
|
|
34
|
+
name: Provide.io SPDX headers
|
|
35
|
+
entry: uv run python scripts/check_spdx_headers.py src tests scripts
|
|
36
|
+
language: system
|
|
37
|
+
pass_filenames: false
|
|
38
|
+
always_run: true
|
|
39
|
+
types: [python]
|
|
40
|
+
|
|
41
|
+
- id: licenses
|
|
42
|
+
name: license compliance
|
|
43
|
+
entry: uv run python scripts/check_licenses.py
|
|
44
|
+
language: system
|
|
45
|
+
pass_filenames: false
|
|
46
|
+
always_run: true
|
|
47
|
+
|
|
48
|
+
- id: mypy
|
|
49
|
+
name: mypy strict
|
|
50
|
+
entry: uv run mypy src tests
|
|
51
|
+
language: system
|
|
52
|
+
pass_filenames: false
|
|
53
|
+
always_run: true
|
|
54
|
+
types: [python]
|
|
55
|
+
|
|
56
|
+
- id: ty
|
|
57
|
+
name: ty check
|
|
58
|
+
entry: uv run ty check src tests
|
|
59
|
+
language: system
|
|
60
|
+
pass_filenames: false
|
|
61
|
+
always_run: true
|
|
62
|
+
types: [python]
|
|
63
|
+
|
|
64
|
+
- id: bandit
|
|
65
|
+
name: bandit
|
|
66
|
+
entry: uv run bandit -r src -ll
|
|
67
|
+
language: system
|
|
68
|
+
pass_filenames: false
|
|
69
|
+
always_run: true
|
|
70
|
+
types: [python]
|
|
71
|
+
|
|
72
|
+
- id: pytest
|
|
73
|
+
name: pytest
|
|
74
|
+
entry: uv run pytest -q
|
|
75
|
+
language: system
|
|
76
|
+
pass_filenames: false
|
|
77
|
+
always_run: true
|
|
78
|
+
types: [python]
|
|
79
|
+
|
|
80
|
+
- id: pip-audit
|
|
81
|
+
name: pip-audit vulnerability scan
|
|
82
|
+
entry: uv run python -m pip_audit
|
|
83
|
+
language: system
|
|
84
|
+
pass_filenames: false
|
|
85
|
+
always_run: true
|
|
86
|
+
types: [python]
|
|
87
|
+
|
|
88
|
+
- id: xenon
|
|
89
|
+
name: xenon complexity
|
|
90
|
+
entry: uv run python scripts/check_xenon.py --max-absolute C --max-modules B --max-average A --paths src/routedef
|
|
91
|
+
language: system
|
|
92
|
+
pass_filenames: false
|
|
93
|
+
always_run: true
|
|
94
|
+
types: [python]
|
|
95
|
+
|
|
96
|
+
- id: vulture
|
|
97
|
+
name: vulture dead code
|
|
98
|
+
entry: uv run vulture --min-confidence 80 src tests
|
|
99
|
+
language: system
|
|
100
|
+
pass_filenames: false
|
|
101
|
+
always_run: true
|
|
102
|
+
types: [python]
|
|
103
|
+
|
|
104
|
+
- id: mutation-sweep
|
|
105
|
+
name: mutmut gate (manual)
|
|
106
|
+
entry: uv run python scripts/mutation_gate.py
|
|
107
|
+
language: system
|
|
108
|
+
pass_filenames: false
|
|
109
|
+
always_run: true
|
|
110
|
+
stages: [manual]
|
|
111
|
+
types: [python]
|
|
112
|
+
|
|
113
|
+
- id: cloudflare-worker-integration
|
|
114
|
+
name: Cloudflare Python Worker integration (manual)
|
|
115
|
+
entry: uv run python scripts/check_cloudflare_worker.py
|
|
116
|
+
language: system
|
|
117
|
+
pass_filenames: false
|
|
118
|
+
always_run: true
|
|
119
|
+
stages: [manual]
|
|
120
|
+
|
|
121
|
+
- id: build-install-smoke
|
|
122
|
+
name: build and install smoke (manual)
|
|
123
|
+
entry: uv run python scripts/check_build_install.py
|
|
124
|
+
language: system
|
|
125
|
+
pass_filenames: false
|
|
126
|
+
always_run: true
|
|
127
|
+
stages: [manual]
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "1.5.0",
|
|
3
|
+
"plugins_used": [
|
|
4
|
+
{
|
|
5
|
+
"name": "ArtifactoryDetector"
|
|
6
|
+
},
|
|
7
|
+
{
|
|
8
|
+
"name": "AWSKeyDetector"
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"name": "AzureStorageKeyDetector"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"name": "BasicAuthDetector"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"name": "CloudantDetector"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"name": "DiscordBotTokenDetector"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"name": "GitHubTokenDetector"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"name": "GitLabTokenDetector"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"name": "JwtTokenDetector"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"name": "KeywordDetector"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"name": "MailchimpDetector"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"name": "NpmDetector"
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"name": "OpenAIDetector"
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"name": "PrivateKeyDetector"
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"name": "SendGridDetector"
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"name": "SlackDetector"
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"name": "SoftlayerDetector"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"name": "SquareOAuthDetector"
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"name": "StripeDetector"
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"name": "TelegramBotTokenDetector"
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"name": "TwilioKeyDetector"
|
|
66
|
+
}
|
|
67
|
+
],
|
|
68
|
+
"filters_used": [
|
|
69
|
+
{
|
|
70
|
+
"path": "detect_secrets.filters.allowlist.is_line_allowlisted"
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"path": "detect_secrets.filters.common.is_ignored_due_to_verification_policies",
|
|
74
|
+
"min_level": 2
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"path": "detect_secrets.filters.heuristic.is_indirect_reference"
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"path": "detect_secrets.filters.heuristic.is_likely_id_string"
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"path": "detect_secrets.filters.heuristic.is_lock_file"
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"path": "detect_secrets.filters.heuristic.is_not_alphanumeric_string"
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"path": "detect_secrets.filters.heuristic.is_potential_uuid"
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"path": "detect_secrets.filters.heuristic.is_prefixed_with_dollar_sign"
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
"path": "detect_secrets.filters.heuristic.is_sequential_string"
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
"path": "detect_secrets.filters.heuristic.is_swagger_file"
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"path": "detect_secrets.filters.heuristic.is_templated_secret"
|
|
102
|
+
}
|
|
103
|
+
],
|
|
104
|
+
"results": {},
|
|
105
|
+
"generated_at": "2026-07-03T00:00:00Z"
|
|
106
|
+
}
|
routedef-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 provide.io llc
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 provide.io llc
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
routedef-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: routedef
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Route definition primitives for Python services.
|
|
5
|
+
Project-URL: Homepage, https://github.com/provide-io/routedef
|
|
6
|
+
Project-URL: Repository, https://github.com/provide-io/routedef
|
|
7
|
+
Project-URL: Documentation, https://github.com/provide-io/routedef/blob/main/docs/architecture.md
|
|
8
|
+
Project-URL: Issues, https://github.com/provide-io/routedef/issues
|
|
9
|
+
Author: provide.io llc
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Requires-Python: >=3.11
|
|
13
|
+
Provides-Extra: fastapi
|
|
14
|
+
Requires-Dist: fastapi>=0.116.0; extra == 'fastapi'
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
|
|
17
|
+
# RouteDef ๐งญ
|
|
18
|
+
|
|
19
|
+
Runtime-neutral route definitions for Python services.
|
|
20
|
+
|
|
21
|
+
`routedef` gives applications one route contract that can be mounted into multiple runtimes. The core package has
|
|
22
|
+
no FastAPI, Cloudflare, ASGI, auth, database, or application dependency. Runtime-specific code lives in adapters.
|
|
23
|
+
|
|
24
|
+
## What It Provides โ
|
|
25
|
+
|
|
26
|
+
- `RouteDef`: method, path template, handler, and metadata.
|
|
27
|
+
- `RouteRequest`: canonical request object for handlers.
|
|
28
|
+
- `RouteResponse`: canonical response object for handlers.
|
|
29
|
+
- `RouteTable`: ordered method/path matching with `{path_param}` extraction.
|
|
30
|
+
- `build_fastapi_router`: FastAPI router integration.
|
|
31
|
+
- `CloudflareDispatcher`: direct Cloudflare Python Workers integration.
|
|
32
|
+
|
|
33
|
+
## Why Use It ๐ฏ
|
|
34
|
+
|
|
35
|
+
Use `RouteDef` when you need the same route definitions to work across more than one Python runtime, especially
|
|
36
|
+
when migrating between framework-hosted APIs and Cloudflare Python Workers.
|
|
37
|
+
|
|
38
|
+
- One handler contract instead of per-runtime handler shapes.
|
|
39
|
+
- App-owned auth and authorization through metadata, auth providers, and enforcers.
|
|
40
|
+
- Dependency-free core package with optional runtime adapters.
|
|
41
|
+
- Testable route behavior without starting a web server.
|
|
42
|
+
- Migration-friendly wrappers for legacy split-argument handlers.
|
|
43
|
+
|
|
44
|
+
## Why Not ๐ง
|
|
45
|
+
|
|
46
|
+
Do not use `RouteDef` as a full web framework, ORM, dependency injection container, auth library, or request
|
|
47
|
+
validation system. It intentionally does not own app policy, storage, schemas, background jobs, or runtime
|
|
48
|
+
lifecycle. If a service will only ever run in one framework and already has a stable route layer, the adapter
|
|
49
|
+
boundary may not be worth adding.
|
|
50
|
+
|
|
51
|
+
## Architecture ๐๏ธ
|
|
52
|
+
|
|
53
|
+

|
|
54
|
+
|
|
55
|
+

|
|
56
|
+
|
|
57
|
+
See [docs/architecture.md](https://github.com/provide-io/routedef/blob/main/docs/architecture.md) for package
|
|
58
|
+
boundaries and [docs/migration.md](https://github.com/provide-io/routedef/blob/main/docs/migration.md) for migration
|
|
59
|
+
examples covering undef-style roles, admin authorization callbacks, Taybols JWT auth, and uwarp split-argument
|
|
60
|
+
handlers.
|
|
61
|
+
|
|
62
|
+
## Basic Usage ๐
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
from routedef import RouteDef, RouteRequest, RouteResponse, RouteTable
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
async def get_item(request: RouteRequest[None, dict[str, object]]) -> RouteResponse:
|
|
69
|
+
return RouteResponse.json({"id": request.path_params["id"]})
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
routes = RouteTable([RouteDef("GET", "/v1/items/{id}", get_item)])
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## FastAPI
|
|
76
|
+
|
|
77
|
+
```python
|
|
78
|
+
from fastapi import FastAPI
|
|
79
|
+
from routedef.adapters.fastapi import build_fastapi_router
|
|
80
|
+
|
|
81
|
+
app = FastAPI()
|
|
82
|
+
app.include_router(build_fastapi_router(routes))
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Cloudflare Python Workers
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
from routedef.adapters.cloudflare import CloudflareDispatcher
|
|
89
|
+
from workers import WorkerEntrypoint
|
|
90
|
+
|
|
91
|
+
dispatcher = CloudflareDispatcher(routes)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
class Default(WorkerEntrypoint):
|
|
95
|
+
async def fetch(self, request):
|
|
96
|
+
return await dispatcher.dispatch(request)
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
A real local Cloudflare fixture lives in
|
|
100
|
+
[examples/cloudflare-worker](https://github.com/provide-io/routedef/blob/main/examples/cloudflare-worker). Run it with:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
uv run python scripts/check_cloudflare_worker.py
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
The integration script vendors the local `src/routedef` package into a temporary Python Worker project, runs
|
|
107
|
+
`pywrangler sync`, starts `wrangler@latest dev`, and probes routes over HTTP.
|
|
108
|
+
|
|
109
|
+
## Quality Gates ๐งช
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
uv run pre-commit run --all-files
|
|
113
|
+
uv run pytest -q --cov=src/routedef --cov-branch --cov-report=term-missing --cov-fail-under=100
|
|
114
|
+
uv run pre-commit run mutation-sweep --hook-stage manual
|
|
115
|
+
uv run pre-commit run cloudflare-worker-integration --hook-stage manual
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
The project requires 100% branch coverage, strict typing, security/dead-code/complexity checks, REUSE compliance,
|
|
119
|
+
max-LOC checks, mutation testing, and a Cloudflare Worker runtime integration gate.
|
routedef-0.1.0/README.md
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# RouteDef ๐งญ
|
|
2
|
+
|
|
3
|
+
Runtime-neutral route definitions for Python services.
|
|
4
|
+
|
|
5
|
+
`routedef` gives applications one route contract that can be mounted into multiple runtimes. The core package has
|
|
6
|
+
no FastAPI, Cloudflare, ASGI, auth, database, or application dependency. Runtime-specific code lives in adapters.
|
|
7
|
+
|
|
8
|
+
## What It Provides โ
|
|
9
|
+
|
|
10
|
+
- `RouteDef`: method, path template, handler, and metadata.
|
|
11
|
+
- `RouteRequest`: canonical request object for handlers.
|
|
12
|
+
- `RouteResponse`: canonical response object for handlers.
|
|
13
|
+
- `RouteTable`: ordered method/path matching with `{path_param}` extraction.
|
|
14
|
+
- `build_fastapi_router`: FastAPI router integration.
|
|
15
|
+
- `CloudflareDispatcher`: direct Cloudflare Python Workers integration.
|
|
16
|
+
|
|
17
|
+
## Why Use It ๐ฏ
|
|
18
|
+
|
|
19
|
+
Use `RouteDef` when you need the same route definitions to work across more than one Python runtime, especially
|
|
20
|
+
when migrating between framework-hosted APIs and Cloudflare Python Workers.
|
|
21
|
+
|
|
22
|
+
- One handler contract instead of per-runtime handler shapes.
|
|
23
|
+
- App-owned auth and authorization through metadata, auth providers, and enforcers.
|
|
24
|
+
- Dependency-free core package with optional runtime adapters.
|
|
25
|
+
- Testable route behavior without starting a web server.
|
|
26
|
+
- Migration-friendly wrappers for legacy split-argument handlers.
|
|
27
|
+
|
|
28
|
+
## Why Not ๐ง
|
|
29
|
+
|
|
30
|
+
Do not use `RouteDef` as a full web framework, ORM, dependency injection container, auth library, or request
|
|
31
|
+
validation system. It intentionally does not own app policy, storage, schemas, background jobs, or runtime
|
|
32
|
+
lifecycle. If a service will only ever run in one framework and already has a stable route layer, the adapter
|
|
33
|
+
boundary may not be worth adding.
|
|
34
|
+
|
|
35
|
+
## Architecture ๐๏ธ
|
|
36
|
+
|
|
37
|
+

|
|
38
|
+
|
|
39
|
+

|
|
40
|
+
|
|
41
|
+
See [docs/architecture.md](https://github.com/provide-io/routedef/blob/main/docs/architecture.md) for package
|
|
42
|
+
boundaries and [docs/migration.md](https://github.com/provide-io/routedef/blob/main/docs/migration.md) for migration
|
|
43
|
+
examples covering undef-style roles, admin authorization callbacks, Taybols JWT auth, and uwarp split-argument
|
|
44
|
+
handlers.
|
|
45
|
+
|
|
46
|
+
## Basic Usage ๐
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
from routedef import RouteDef, RouteRequest, RouteResponse, RouteTable
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
async def get_item(request: RouteRequest[None, dict[str, object]]) -> RouteResponse:
|
|
53
|
+
return RouteResponse.json({"id": request.path_params["id"]})
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
routes = RouteTable([RouteDef("GET", "/v1/items/{id}", get_item)])
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## FastAPI
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
from fastapi import FastAPI
|
|
63
|
+
from routedef.adapters.fastapi import build_fastapi_router
|
|
64
|
+
|
|
65
|
+
app = FastAPI()
|
|
66
|
+
app.include_router(build_fastapi_router(routes))
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Cloudflare Python Workers
|
|
70
|
+
|
|
71
|
+
```python
|
|
72
|
+
from routedef.adapters.cloudflare import CloudflareDispatcher
|
|
73
|
+
from workers import WorkerEntrypoint
|
|
74
|
+
|
|
75
|
+
dispatcher = CloudflareDispatcher(routes)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
class Default(WorkerEntrypoint):
|
|
79
|
+
async def fetch(self, request):
|
|
80
|
+
return await dispatcher.dispatch(request)
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
A real local Cloudflare fixture lives in
|
|
84
|
+
[examples/cloudflare-worker](https://github.com/provide-io/routedef/blob/main/examples/cloudflare-worker). Run it with:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
uv run python scripts/check_cloudflare_worker.py
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
The integration script vendors the local `src/routedef` package into a temporary Python Worker project, runs
|
|
91
|
+
`pywrangler sync`, starts `wrangler@latest dev`, and probes routes over HTTP.
|
|
92
|
+
|
|
93
|
+
## Quality Gates ๐งช
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
uv run pre-commit run --all-files
|
|
97
|
+
uv run pytest -q --cov=src/routedef --cov-branch --cov-report=term-missing --cov-fail-under=100
|
|
98
|
+
uv run pre-commit run mutation-sweep --hook-stage manual
|
|
99
|
+
uv run pre-commit run cloudflare-worker-integration --hook-stage manual
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
The project requires 100% branch coverage, strict typing, security/dead-code/complexity checks, REUSE compliance,
|
|
103
|
+
max-LOC checks, mutation testing, and a Cloudflare Worker runtime integration gate.
|