fastapi-deprecation 0.2.1__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 (29) hide show
  1. fastapi_deprecation-0.2.1/.github/workflows/publish.yml +28 -0
  2. fastapi_deprecation-0.2.1/.github/workflows/test.yml +34 -0
  3. fastapi_deprecation-0.2.1/.gitignore +12 -0
  4. fastapi_deprecation-0.2.1/.pre-commit-config.yaml +22 -0
  5. fastapi_deprecation-0.2.1/.python-version +1 -0
  6. fastapi_deprecation-0.2.1/LICENSE +21 -0
  7. fastapi_deprecation-0.2.1/PKG-INFO +184 -0
  8. fastapi_deprecation-0.2.1/README.md +151 -0
  9. fastapi_deprecation-0.2.1/docs/index.md +138 -0
  10. fastapi_deprecation-0.2.1/docs/reference/core.md +30 -0
  11. fastapi_deprecation-0.2.1/docs/reference/dependencies.md +41 -0
  12. fastapi_deprecation-0.2.1/docs/reference/openapi.md +34 -0
  13. fastapi_deprecation-0.2.1/docs/reference/utils.md +20 -0
  14. fastapi_deprecation-0.2.1/mkdocs.yml +56 -0
  15. fastapi_deprecation-0.2.1/pyproject.toml +35 -0
  16. fastapi_deprecation-0.2.1/src/fastapi_deprecation/__init__.py +15 -0
  17. fastapi_deprecation-0.2.1/src/fastapi_deprecation/_version.py +34 -0
  18. fastapi_deprecation-0.2.1/src/fastapi_deprecation/core.py +109 -0
  19. fastapi_deprecation-0.2.1/src/fastapi_deprecation/dependencies.py +111 -0
  20. fastapi_deprecation-0.2.1/src/fastapi_deprecation/openapi.py +47 -0
  21. fastapi_deprecation-0.2.1/src/fastapi_deprecation/py.typed +0 -0
  22. fastapi_deprecation-0.2.1/src/fastapi_deprecation/utils.py +59 -0
  23. fastapi_deprecation-0.2.1/tests/test_brownouts.py +71 -0
  24. fastapi_deprecation-0.2.1/tests/test_core.py +92 -0
  25. fastapi_deprecation-0.2.1/tests/test_extended.py +56 -0
  26. fastapi_deprecation-0.2.1/tests/test_openapi.py +48 -0
  27. fastapi_deprecation-0.2.1/tests/test_recursive_openapi.py +48 -0
  28. fastapi_deprecation-0.2.1/tests/test_utils.py +46 -0
  29. fastapi_deprecation-0.2.1/uv.lock +1135 -0
@@ -0,0 +1,28 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ jobs:
9
+ build-n-publish:
10
+ name: Build and Publish
11
+ runs-on: ubuntu-latest
12
+ environment:
13
+ name: pypi
14
+ url: https://pypi.org/p/fastapi-deprecation
15
+ permissions:
16
+ id-token: write # IMPORTANT: this permission is mandatory for trusted publishing
17
+
18
+ steps:
19
+ - uses: actions/checkout@v4
20
+
21
+ - name: Install uv
22
+ uses: astral-sh/setup-uv@v5
23
+
24
+ - name: Build package
25
+ run: uv build
26
+
27
+ - name: Publish distribution 📦 to PyPI
28
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,34 @@
1
+ name: Test
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - master
7
+ pull_request:
8
+ types: [opener, synchronize, reopened]
9
+
10
+ jobs:
11
+ test:
12
+ name: Test
13
+ runs-on: ubuntu-latest
14
+ strategy:
15
+ matrix:
16
+ python-version: ["3.10", "3.11", "3.12"]
17
+
18
+ steps:
19
+ - uses: actions/checkout@v4
20
+
21
+ - name: Install uv
22
+ uses: astral-sh/setup-uv@v5
23
+
24
+ - name: Set up Python ${{ matrix.python-version }}
25
+ run: uv python install ${{ matrix.python-version }}
26
+
27
+ - name: Install the project
28
+ run: uv sync --all-extras --dev
29
+
30
+ - name: Run tests
31
+ run: uv run pytest tests
32
+
33
+ - name: Lint with Ruff
34
+ run: uv run ruff check .
@@ -0,0 +1,12 @@
1
+ # Python-generated files
2
+ __pycache__/
3
+ *.py[oc]
4
+ _version.py
5
+ build/
6
+ dist/
7
+ wheels/
8
+ *.egg-info
9
+
10
+ # Virtual environments
11
+ .venv
12
+ site/
@@ -0,0 +1,22 @@
1
+ repos:
2
+ - repo: https://github.com/pre-commit/pre-commit-hooks
3
+ rev: v4.5.0
4
+ hooks:
5
+ - id: trailing-whitespace
6
+ - id: end-of-file-fixer
7
+ - id: check-yaml
8
+ - id: check-added-large-files
9
+
10
+ - repo: https://github.com/astral-sh/ruff-pre-commit
11
+ rev: v0.1.6
12
+ hooks:
13
+ - id: ruff
14
+ args: [--fix, --exit-non-zero-on-fix]
15
+ - id: ruff-format
16
+
17
+ - repo: https://github.com/compilerla/conventional-pre-commit
18
+ rev: v3.2.0
19
+ hooks:
20
+ - id: conventional-pre-commit
21
+ stages: [commit-msg]
22
+ args: []
@@ -0,0 +1 @@
1
+ 3.10
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Fractal Vision
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,184 @@
1
+ Metadata-Version: 2.4
2
+ Name: fastapi-deprecation
3
+ Version: 0.2.1
4
+ Summary: Endpoint deprecation management for FastAPI made easy
5
+ License: MIT License
6
+
7
+ Copyright (c) 2026 Fractal Vision
8
+
9
+ Permission is hereby granted, free of charge, to any person obtaining a copy
10
+ of this software and associated documentation files (the "Software"), to deal
11
+ in the Software without restriction, including without limitation the rights
12
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
+ copies of the Software, and to permit persons to whom the Software is
14
+ furnished to do so, subject to the following conditions:
15
+
16
+ The above copyright notice and this permission notice shall be included in all
17
+ copies or substantial portions of the Software.
18
+
19
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25
+ SOFTWARE.
26
+ License-File: LICENSE
27
+ Requires-Python: >=3.10
28
+ Requires-Dist: fastapi>=0.129.0
29
+ Requires-Dist: pydantic>=2.12.5
30
+ Requires-Dist: python-dateutil>=2.9.0.post0
31
+ Requires-Dist: typing-extensions>=4.15.0
32
+ Description-Content-Type: text/markdown
33
+
34
+ # FastAPI Deprecation
35
+
36
+ <div align="center">
37
+ <p align="center">
38
+ <strong>RFC 9745 compliant API deprecation for FastAPI.</strong>
39
+ </p>
40
+ <p align="center">
41
+ <a href="https://github.com/fractalvision/fastapi-deprecation/actions/workflows/test.yml">
42
+ <img src="https://github.com/fractalvision/fastapi-deprecation/actions/workflows/test.yml/badge.svg" alt="Test Status"/>
43
+ </a>
44
+ </p>
45
+ </div>
46
+
47
+ ---
48
+
49
+ **FastAPI Deprecation** helps you manage the lifecycle of your API endpoints using standard HTTP headers (`Deprecation`, `Sunset`, `Link`) and automated blocking logic. It allows you to gracefully warn clients about upcoming deprecations and automatically shut down endpoints when they reach their sunset date.
50
+
51
+ ## Features
52
+
53
+ - **Standard Compliance**: Fully implements [RFC 9745](https://datatracker.ietf.org/doc/rfc9745/) and [RFC 8594](https://datatracker.ietf.org/doc/rfc8594/).
54
+ - **Decorator-based**: Simple `@deprecated` decorator for your path operations.
55
+ - **Automated Blocking**: Automatically returns `410 Gone` or `301 Moved Permanently` after the `sunset_date`.
56
+ - **OpenAPI Integration**: Automatically marks endpoints as deprecated in Swagger UI and ReDoc.
57
+ - **Router Support**: Deprecate entire routers or sub-applications with `DeprecationDependency`.
58
+ - **Extended Features**:
59
+ - **Telemetry**: Track usage of deprecated endpoints.
60
+ - **Brownouts**: Schedule temporary shutdowns to simulate future removal.
61
+ - **Future Deprecation**: Announce upcoming deprecations before they become active.
62
+
63
+ ## Installation
64
+
65
+ ```bash
66
+ pip install fastapi-deprecation
67
+ # or with uv
68
+ uv add fastapi-deprecation
69
+ ```
70
+
71
+ ## Documentation
72
+
73
+ To run the documentation locally:
74
+
75
+ ```bash
76
+ uv run zensical serve
77
+ ```
78
+
79
+ ## Quick Start
80
+
81
+ ```python
82
+ from fastapi import FastAPI
83
+ from fastapi_deprecation import deprecated, auto_deprecate_openapi
84
+
85
+ app = FastAPI()
86
+
87
+ @app.get("/old-endpoint")
88
+ @deprecated(
89
+ deprecation_date="2024-01-01",
90
+ sunset_date="2025-01-01",
91
+ alternative="/new-endpoint",
92
+ detail="This endpoint is old and tired."
93
+ )
94
+ async def old():
95
+ return {"message": "Enjoy it while it lasts!"}
96
+
97
+ # Don't forget to update the schema at the end!
98
+ auto_deprecate_openapi(app)
99
+ ```
100
+
101
+ ## How It Works
102
+
103
+ 1. **Warning Phase** (Before Sunset):
104
+ * Requests return `200 OK`.
105
+ * Response headers include:
106
+ * `Deprecation: @1704067200` (Unix timestamp of `deprecation_date`)
107
+ * `Sunset: Wed, 01 Jan 2025 00:00:00 GMT`
108
+ * `Link: </new-endpoint>; rel="alternative"`
109
+
110
+ 2. **Blocking Phase** (After Sunset):
111
+ * Requests return `410 Gone` (or `301 Moved Permanently` if `alternative` is set).
112
+ * The `detail` message is returned in the response body.
113
+
114
+ ## Advanced Usage
115
+
116
+ ### 1. Brownouts (Scheduled Unavailability)
117
+ You can simulate future shutdowns by scheduling "brownouts" — temporary periods where the endpoint returns `410 Gone` (or `301` if alternative is set). This forces clients to notice the deprecation before the final sunset.
118
+
119
+ ```python
120
+ @deprecated(
121
+ sunset_date="2025-12-31",
122
+ brownouts=[
123
+ # 1-hour brownout
124
+ ("2025-11-01T09:00:00Z", "2025-11-01T10:00:00Z"),
125
+ # 1-day brownout
126
+ ("2025-12-01T00:00:00Z", "2025-12-02T00:00:00Z"),
127
+ ],
128
+ detail="Service is temporarily unavailable due to scheduled brownout."
129
+ )
130
+ async def my_endpoint(): ...
131
+ ```
132
+
133
+ ### 2. Telemetry & Logging
134
+ Track usage of deprecated endpoints using a global callback. This is useful for monitoring which clients are still using old APIs.
135
+
136
+ ```python
137
+ import logging
138
+ from fastapi import Request, Response
139
+ from fastapi_deprecation import set_deprecation_callback, DeprecationDependency
140
+
141
+ logger = logging.getLogger("deprecation")
142
+
143
+ def log_usage(request: Request, response: Response, dep: DeprecationDependency):
144
+ logger.warning(
145
+ f"Deprecated endpoint {request.url} accessed. "
146
+ f"Deprecation date: {dep.deprecation_date}"
147
+ )
148
+
149
+ set_deprecation_callback(log_usage)
150
+ ```
151
+
152
+ ### 3. Deprecating Entire Routers
153
+ To deprecate a whole group of endpoints, use `DeprecationDependency` on the `APIRouter`.
154
+
155
+ ```python
156
+ from fastapi import APIRouter, Depends
157
+ from fastapi_deprecation import DeprecationDependency
158
+
159
+ router = APIRouter(
160
+ dependencies=[Depends(DeprecationDependency(deprecation_date="2024-01-01"))]
161
+ )
162
+
163
+ @router.get("/sub-route")
164
+ async def sub(): ...
165
+ ```
166
+
167
+ ### 4. Recursive OpenAPI Support
168
+ When using `auto_deprecate_openapi(app)`, it automatically traverses potentially mounted sub-applications (`app.mount(...)`) and marks their routes as deprecated if configured.
169
+
170
+ ```python
171
+ root_app.mount("/v1", v1_app)
172
+ # This will update OpenAPI for both root_app AND v1_app
173
+ auto_deprecate_openapi(root_app)
174
+ ```
175
+
176
+ ### 5. Future Deprecation
177
+ You can announce a *future* deprecation date. The `Deprecation` header will still be sent (as per RFC 9745), allowing clients to prepare in advance.
178
+
179
+ ```python
180
+ @deprecated(deprecation_date="2030-01-01")
181
+ async def future_proof(): ...
182
+ ```
183
+
184
+ See the [Documentation](https://example.com/docs) for full details on API reference and advanced configuration.
@@ -0,0 +1,151 @@
1
+ # FastAPI Deprecation
2
+
3
+ <div align="center">
4
+ <p align="center">
5
+ <strong>RFC 9745 compliant API deprecation for FastAPI.</strong>
6
+ </p>
7
+ <p align="center">
8
+ <a href="https://github.com/fractalvision/fastapi-deprecation/actions/workflows/test.yml">
9
+ <img src="https://github.com/fractalvision/fastapi-deprecation/actions/workflows/test.yml/badge.svg" alt="Test Status"/>
10
+ </a>
11
+ </p>
12
+ </div>
13
+
14
+ ---
15
+
16
+ **FastAPI Deprecation** helps you manage the lifecycle of your API endpoints using standard HTTP headers (`Deprecation`, `Sunset`, `Link`) and automated blocking logic. It allows you to gracefully warn clients about upcoming deprecations and automatically shut down endpoints when they reach their sunset date.
17
+
18
+ ## Features
19
+
20
+ - **Standard Compliance**: Fully implements [RFC 9745](https://datatracker.ietf.org/doc/rfc9745/) and [RFC 8594](https://datatracker.ietf.org/doc/rfc8594/).
21
+ - **Decorator-based**: Simple `@deprecated` decorator for your path operations.
22
+ - **Automated Blocking**: Automatically returns `410 Gone` or `301 Moved Permanently` after the `sunset_date`.
23
+ - **OpenAPI Integration**: Automatically marks endpoints as deprecated in Swagger UI and ReDoc.
24
+ - **Router Support**: Deprecate entire routers or sub-applications with `DeprecationDependency`.
25
+ - **Extended Features**:
26
+ - **Telemetry**: Track usage of deprecated endpoints.
27
+ - **Brownouts**: Schedule temporary shutdowns to simulate future removal.
28
+ - **Future Deprecation**: Announce upcoming deprecations before they become active.
29
+
30
+ ## Installation
31
+
32
+ ```bash
33
+ pip install fastapi-deprecation
34
+ # or with uv
35
+ uv add fastapi-deprecation
36
+ ```
37
+
38
+ ## Documentation
39
+
40
+ To run the documentation locally:
41
+
42
+ ```bash
43
+ uv run zensical serve
44
+ ```
45
+
46
+ ## Quick Start
47
+
48
+ ```python
49
+ from fastapi import FastAPI
50
+ from fastapi_deprecation import deprecated, auto_deprecate_openapi
51
+
52
+ app = FastAPI()
53
+
54
+ @app.get("/old-endpoint")
55
+ @deprecated(
56
+ deprecation_date="2024-01-01",
57
+ sunset_date="2025-01-01",
58
+ alternative="/new-endpoint",
59
+ detail="This endpoint is old and tired."
60
+ )
61
+ async def old():
62
+ return {"message": "Enjoy it while it lasts!"}
63
+
64
+ # Don't forget to update the schema at the end!
65
+ auto_deprecate_openapi(app)
66
+ ```
67
+
68
+ ## How It Works
69
+
70
+ 1. **Warning Phase** (Before Sunset):
71
+ * Requests return `200 OK`.
72
+ * Response headers include:
73
+ * `Deprecation: @1704067200` (Unix timestamp of `deprecation_date`)
74
+ * `Sunset: Wed, 01 Jan 2025 00:00:00 GMT`
75
+ * `Link: </new-endpoint>; rel="alternative"`
76
+
77
+ 2. **Blocking Phase** (After Sunset):
78
+ * Requests return `410 Gone` (or `301 Moved Permanently` if `alternative` is set).
79
+ * The `detail` message is returned in the response body.
80
+
81
+ ## Advanced Usage
82
+
83
+ ### 1. Brownouts (Scheduled Unavailability)
84
+ You can simulate future shutdowns by scheduling "brownouts" — temporary periods where the endpoint returns `410 Gone` (or `301` if alternative is set). This forces clients to notice the deprecation before the final sunset.
85
+
86
+ ```python
87
+ @deprecated(
88
+ sunset_date="2025-12-31",
89
+ brownouts=[
90
+ # 1-hour brownout
91
+ ("2025-11-01T09:00:00Z", "2025-11-01T10:00:00Z"),
92
+ # 1-day brownout
93
+ ("2025-12-01T00:00:00Z", "2025-12-02T00:00:00Z"),
94
+ ],
95
+ detail="Service is temporarily unavailable due to scheduled brownout."
96
+ )
97
+ async def my_endpoint(): ...
98
+ ```
99
+
100
+ ### 2. Telemetry & Logging
101
+ Track usage of deprecated endpoints using a global callback. This is useful for monitoring which clients are still using old APIs.
102
+
103
+ ```python
104
+ import logging
105
+ from fastapi import Request, Response
106
+ from fastapi_deprecation import set_deprecation_callback, DeprecationDependency
107
+
108
+ logger = logging.getLogger("deprecation")
109
+
110
+ def log_usage(request: Request, response: Response, dep: DeprecationDependency):
111
+ logger.warning(
112
+ f"Deprecated endpoint {request.url} accessed. "
113
+ f"Deprecation date: {dep.deprecation_date}"
114
+ )
115
+
116
+ set_deprecation_callback(log_usage)
117
+ ```
118
+
119
+ ### 3. Deprecating Entire Routers
120
+ To deprecate a whole group of endpoints, use `DeprecationDependency` on the `APIRouter`.
121
+
122
+ ```python
123
+ from fastapi import APIRouter, Depends
124
+ from fastapi_deprecation import DeprecationDependency
125
+
126
+ router = APIRouter(
127
+ dependencies=[Depends(DeprecationDependency(deprecation_date="2024-01-01"))]
128
+ )
129
+
130
+ @router.get("/sub-route")
131
+ async def sub(): ...
132
+ ```
133
+
134
+ ### 4. Recursive OpenAPI Support
135
+ When using `auto_deprecate_openapi(app)`, it automatically traverses potentially mounted sub-applications (`app.mount(...)`) and marks their routes as deprecated if configured.
136
+
137
+ ```python
138
+ root_app.mount("/v1", v1_app)
139
+ # This will update OpenAPI for both root_app AND v1_app
140
+ auto_deprecate_openapi(root_app)
141
+ ```
142
+
143
+ ### 5. Future Deprecation
144
+ You can announce a *future* deprecation date. The `Deprecation` header will still be sent (as per RFC 9745), allowing clients to prepare in advance.
145
+
146
+ ```python
147
+ @deprecated(deprecation_date="2030-01-01")
148
+ async def future_proof(): ...
149
+ ```
150
+
151
+ See the [Documentation](https://example.com/docs) for full details on API reference and advanced configuration.
@@ -0,0 +1,138 @@
1
+ # FastAPI Deprecation
2
+
3
+ <div align="center">
4
+ <p align="center">
5
+ <strong>RFC 9745 compliant API deprecation for FastAPI.</strong>
6
+ </p>
7
+ </div>
8
+
9
+ ---
10
+
11
+ **FastAPI Deprecation** helps you manage the lifecycle of your API endpoints using standard HTTP headers (`Deprecation`, `Sunset`, `Link`) and automated blocking logic. It allows you to gracefully warn clients about upcoming deprecations and automatically shut down endpoints when they reach their sunset date.
12
+
13
+ ## Features
14
+
15
+ - **Standard Compliance**: Fully implements [RFC 9745](https://datatracker.ietf.org/doc/rfc9745/) and [RFC 8594](https://datatracker.ietf.org/doc/rfc8594/).
16
+ - **Decorator-based**: Simple `@deprecated` decorator for your path operations.
17
+ - **Automated Blocking**: Automatically returns `410 Gone` or `301 Moved Permanently` after the `sunset_date`.
18
+ - **OpenAPI Integration**: Automatically marks endpoints as deprecated in Swagger UI and ReDoc.
19
+ - **Router Support**: Deprecate entire routers or sub-applications with `DeprecationDependency`.
20
+ - **Extended Features**:
21
+ - **Telemetry**: Track usage of deprecated endpoints.
22
+ - **Brownouts**: Schedule temporary shutdowns to simulate future removal.
23
+ - **Future Deprecation**: Announce upcoming deprecations before they become active.
24
+
25
+ ## Installation
26
+
27
+ ```bash
28
+ pip install fastapi-deprecation
29
+ # or with uv
30
+ uv add fastapi-deprecation
31
+ ```
32
+
33
+ ## Quick Start
34
+
35
+ ```python
36
+ from fastapi import FastAPI
37
+ from fastapi_deprecation import deprecated, auto_deprecate_openapi
38
+
39
+ app = FastAPI()
40
+
41
+ @app.get("/old-endpoint")
42
+ @deprecated(
43
+ deprecation_date="2024-01-01",
44
+ sunset_date="2025-01-01",
45
+ alternative="/new-endpoint",
46
+ detail="This endpoint is old and tired."
47
+ )
48
+ async def old():
49
+ return {"message": "Enjoy it while it lasts!"}
50
+
51
+ # Don't forget to update the schema at the end!
52
+ auto_deprecate_openapi(app)
53
+ ```
54
+
55
+ ## How It Works
56
+
57
+ 1. **Warning Phase** (Before Sunset):
58
+ * Requests return `200 OK`.
59
+ * Response headers include:
60
+ * `Deprecation: @1704067200` (Unix timestamp of `deprecation_date`)
61
+ * `Sunset: Wed, 01 Jan 2025 00:00:00 GMT`
62
+ * `Link: </new-endpoint>; rel="alternative"`
63
+
64
+ 2. **Blocking Phase** (After Sunset):
65
+ * Requests return `410 Gone` (or `301 Moved Permanently` if `alternative` is set).
66
+ * The `detail` message is returned in the response body.
67
+
68
+ ## Advanced Usage
69
+
70
+ ### 1. Brownouts (Scheduled Unavailability)
71
+ You can simulate future shutdowns by scheduling "brownouts" — temporary periods where the endpoint returns `410 Gone` (or `301` if alternative is set). This forces clients to notice the deprecation before the final sunset.
72
+
73
+ ```python
74
+ @deprecated(
75
+ sunset_date="2025-12-31",
76
+ brownouts=[
77
+ # 1-hour brownout
78
+ ("2025-11-01T09:00:00Z", "2025-11-01T10:00:00Z"),
79
+ # 1-day brownout
80
+ ("2025-12-01T00:00:00Z", "2025-12-02T00:00:00Z"),
81
+ ],
82
+ detail="Service is temporarily unavailable due to scheduled brownout."
83
+ )
84
+ async def my_endpoint(): ...
85
+ ```
86
+
87
+ ### 2. Telemetry & Logging
88
+ Track usage of deprecated endpoints using a global callback. This is useful for monitoring which clients are still using old APIs.
89
+
90
+ ```python
91
+ import logging
92
+ from fastapi import Request, Response
93
+ from fastapi_deprecation import set_deprecation_callback, DeprecationDependency
94
+
95
+ logger = logging.getLogger("deprecation")
96
+
97
+ def log_usage(request: Request, response: Response, dep: DeprecationDependency):
98
+ logger.warning(
99
+ f"Deprecated endpoint {request.url} accessed. "
100
+ f"Deprecation date: {dep.deprecation_date}"
101
+ )
102
+
103
+ set_deprecation_callback(log_usage)
104
+ ```
105
+
106
+ ### 3. Deprecating Entire Routers
107
+ To deprecate a whole group of endpoints, use `DeprecationDependency` on the `APIRouter`.
108
+
109
+ ```python
110
+ from fastapi import APIRouter, Depends
111
+ from fastapi_deprecation import DeprecationDependency
112
+
113
+ router = APIRouter(
114
+ dependencies=[Depends(DeprecationDependency(deprecation_date="2024-01-01"))]
115
+ )
116
+
117
+ @router.get("/sub-route")
118
+ async def sub(): ...
119
+ ```
120
+
121
+ ### 4. Recursive OpenAPI Support
122
+ When using `auto_deprecate_openapi(app)`, it automatically traverses potentially mounted sub-applications (`app.mount(...)`) and marks their routes as deprecated if configured.
123
+
124
+ ```python
125
+ root_app.mount("/v1", v1_app)
126
+ # This will update OpenAPI for both root_app AND v1_app
127
+ auto_deprecate_openapi(root_app)
128
+ ```
129
+
130
+ ### 5. Future Deprecation
131
+ You can announce a *future* deprecation date. The `Deprecation` header will still be sent (as per RFC 9745), allowing clients to prepare in advance.
132
+
133
+ ```python
134
+ @deprecated(deprecation_date="2030-01-01")
135
+ async def future_proof(): ...
136
+ ```
137
+
138
+ Check the [API Reference](reference/core.md) for full details.
@@ -0,0 +1,30 @@
1
+ # Core API
2
+
3
+ The `core` module provides the primary interface for deprecating endpoints in FastAPI: the `@deprecated` decorator.
4
+
5
+ ## Usage
6
+
7
+ The `@deprecated` decorator should be placed *above* your path operation function but *below* the FastAPI router decorator (though order usually doesn't matter for functionality, it keeps the code clean).
8
+
9
+ ```python
10
+ from fastapi import FastAPI
11
+ from fastapi_deprecation import deprecated
12
+
13
+ app = FastAPI()
14
+
15
+ @app.get("/items")
16
+ @deprecated(
17
+ deprecation_date="2024-01-01",
18
+ sunset_date="2025-01-01",
19
+ alternative="/new_items"
20
+ )
21
+ async def read_items():
22
+ return [{"item_id": "Foo"}]
23
+ ```
24
+
25
+ ## Reference
26
+
27
+ ::: fastapi_deprecation.core
28
+ options:
29
+ show_root_heading: true
30
+ show_source: true
@@ -0,0 +1,41 @@
1
+ # Dependencies API
2
+
3
+ The `dependencies` module contains the underlying logic for handling deprecation lifecycles. It allows for more advanced usage patterns, such as applying deprecation to entire routers or registering global callbacks.
4
+
5
+ ## Router Deprecation
6
+
7
+ You can deprecate an entire `APIRouter` by adding `DeprecationDependency` to its dependencies list.
8
+
9
+ ```python
10
+ from fastapi import APIRouter, Depends
11
+ from fastapi_deprecation import DeprecationDependency
12
+
13
+ router = APIRouter(
14
+ dependencies=[
15
+ Depends(DeprecationDependency(deprecation_date="2024-06-01"))
16
+ ]
17
+ )
18
+ ```
19
+
20
+ ## Telemetry Callbacks
21
+
22
+ You can register a callback to be notified whenever a deprecated endpoint is accessed. This is useful for logging, analytics, or alerting.
23
+
24
+ ```python
25
+ import logging
26
+ from fastapi_deprecation import set_deprecation_callback
27
+
28
+ logger = logging.getLogger("deprecation")
29
+
30
+ def on_deprecation(request, response, dep):
31
+ logger.warning(f"Deprecated usage: {request.url}")
32
+
33
+ set_deprecation_callback(on_deprecation)
34
+ ```
35
+
36
+ ## Reference
37
+
38
+ ::: fastapi_deprecation.dependencies
39
+ options:
40
+ show_root_heading: true
41
+ show_source: true