cadwyn 4.4.1__tar.gz → 4.4.3__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.
Potentially problematic release.
This version of cadwyn might be problematic. Click here for more details.
- {cadwyn-4.4.1 → cadwyn-4.4.3}/CHANGELOG.md +18 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/Makefile +1 -1
- {cadwyn-4.4.1 → cadwyn-4.4.3}/PKG-INFO +2 -1
- {cadwyn-4.4.1 → cadwyn-4.4.3}/cadwyn/route_generation.py +26 -6
- {cadwyn-4.4.1 → cadwyn-4.4.3}/cadwyn/schema_generation.py +20 -7
- {cadwyn-4.4.1 → cadwyn-4.4.3}/pyproject.toml +12 -11
- cadwyn-4.4.3/tests/test_auth_dependencies.py +67 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/uv.lock +50 -50
- {cadwyn-4.4.1 → cadwyn-4.4.3}/.github/CODE_OF_CONDUCT.md +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/.github/actions/setup-python-uv/action.yaml +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/.github/workflows/ci.yaml +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/.github/workflows/daily_tests.yaml +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/.github/workflows/publish_docs.yaml +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/.github/workflows/release.yaml +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/.github/workflows/validate_links.yaml +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/.gitignore +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/.pre-commit-config.yaml +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/LICENSE +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/README.md +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/cadwyn/__init__.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/cadwyn/__main__.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/cadwyn/_asts.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/cadwyn/_importer.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/cadwyn/_render.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/cadwyn/_utils.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/cadwyn/applications.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/cadwyn/changelogs.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/cadwyn/exceptions.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/cadwyn/middleware.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/cadwyn/py.typed +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/cadwyn/routing.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/cadwyn/static/__init__.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/cadwyn/static/docs.html +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/cadwyn/structure/__init__.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/cadwyn/structure/common.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/cadwyn/structure/data.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/cadwyn/structure/endpoints.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/cadwyn/structure/enums.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/cadwyn/structure/schemas.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/cadwyn/structure/versions.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs/CNAME +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs/__init__.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs/concepts/api_version_header_and_context_variables.md +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs/concepts/beware_of_data_versioning.md +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs/concepts/changelogs.md +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs/concepts/cli.md +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs/concepts/endpoint_migrations.md +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs/concepts/enum_migrations.md +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs/concepts/index.md +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs/concepts/main_app.md +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs/concepts/methodology.md +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs/concepts/schema_generation.md +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs/concepts/schema_migrations.md +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs/concepts/testing.md +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs/concepts/version_changes.md +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs/home/CONTRIBUTING.md +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs/how_to/change_business_logic/index.md +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs/how_to/change_endpoints/index.md +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs/how_to/change_openapi_schemas/add_field.md +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs/how_to/change_openapi_schemas/change_field_type.md +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs/how_to/change_openapi_schemas/changing_constraints.md +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs/how_to/change_openapi_schemas/remove_field.md +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs/how_to/change_openapi_schemas/rename_a_field_in_schema.md +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs/how_to/index.md +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs/img/dashboard_with_one_version.png +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs/img/dashboard_with_two_versions.png +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs/img/get_users_endpoint_from_prior_version.png +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs/img/simplified_migration_model.png +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs/img/sponsor_logos/monite.png +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs/img/unversioned_dashboard.png +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs/index.md +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs/plugin.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs/quickstart/setup.md +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs/quickstart/tutorial.md +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs/theory/how_to_build_versioning_framework.md +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs/theory/how_we_got_here.md +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs/theory/literature.md +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs_src/__init__.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs_src/quickstart/__init__.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs_src/quickstart/setup/__init__.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs_src/quickstart/setup/block001.sh +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs_src/quickstart/setup/block002.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs_src/quickstart/setup/tests/__init__.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs_src/quickstart/setup/tests/test_block002.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs_src/quickstart/tutorial/__init__.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs_src/quickstart/tutorial/block001.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs_src/quickstart/tutorial/block002.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs_src/quickstart/tutorial/block003.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs_src/quickstart/tutorial/tests/__init__.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs_src/quickstart/tutorial/tests/test_block001.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs_src/quickstart/tutorial/tests/test_block002.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/docs_src/quickstart/tutorial/tests/test_block003.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/mkdocs.yml +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/ruff.toml +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/scripts/fix_links.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/scripts/split_md.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/tests/__init__.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/tests/_data/__init__.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/tests/_data/unversioned_schema_dir/__init__.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/tests/_data/unversioned_schema_dir/unversioned_schemas.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/tests/_data/unversioned_schemas.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/tests/_resources/__init__.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/tests/_resources/app_for_testing_routing.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/tests/_resources/render/__init__.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/tests/_resources/render/classes.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/tests/_resources/render/complex/__init__.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/tests/_resources/render/complex/classes.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/tests/_resources/render/complex/versions.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/tests/_resources/render/versions.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/tests/_resources/utils.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/tests/_resources/versioned_app/__init__.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/tests/_resources/versioned_app/app.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/tests/_resources/versioned_app/v2021_01_01.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/tests/_resources/versioned_app/v2022_01_02.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/tests/_resources/versioned_app/webhooks.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/tests/conftest.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/tests/test_applications.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/tests/test_changelog.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/tests/test_cli.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/tests/test_data_migrations.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/tests/test_render.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/tests/test_router_generation.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/tests/test_routing.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/tests/test_schema_generation/__init__.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/tests/test_schema_generation/test_enum.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/tests/test_schema_generation/test_schema.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/tests/test_schema_generation/test_schema_field.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/tests/test_schema_generation/test_schema_validator.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/tests/test_structure.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/tests/tutorial/__init__.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/tests/tutorial/main.py +0 -0
- {cadwyn-4.4.1 → cadwyn-4.4.3}/tests/tutorial/test_example.py +0 -0
|
@@ -5,6 +5,24 @@ Please follow [the Keep a Changelog standard](https://keepachangelog.com/en/1.0.
|
|
|
5
5
|
|
|
6
6
|
## [Unreleased]
|
|
7
7
|
|
|
8
|
+
## [4.4.3]
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
* Bumped package versions
|
|
13
|
+
|
|
14
|
+
## [4.4.2]
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
|
|
18
|
+
* Non-function (object instances) dependencies not supporting dependency overrides in testing
|
|
19
|
+
|
|
20
|
+
## [4.4.1]
|
|
21
|
+
|
|
22
|
+
### Added
|
|
23
|
+
|
|
24
|
+
* Python 3.13 to CI
|
|
25
|
+
|
|
8
26
|
## [4.4.0]
|
|
9
27
|
|
|
10
28
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: cadwyn
|
|
3
|
-
Version: 4.4.
|
|
3
|
+
Version: 4.4.3
|
|
4
4
|
Summary: Production-ready community-driven modern Stripe-like API versioning in FastAPI
|
|
5
5
|
Project-URL: Source code, https://github.com/zmievsa/cadwyn
|
|
6
6
|
Project-URL: Documentation, https://docs.cadwyn.dev
|
|
@@ -23,6 +23,7 @@ Classifier: Programming Language :: Python :: 3
|
|
|
23
23
|
Classifier: Programming Language :: Python :: 3.10
|
|
24
24
|
Classifier: Programming Language :: Python :: 3.11
|
|
25
25
|
Classifier: Programming Language :: Python :: 3.12
|
|
26
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
26
27
|
Classifier: Topic :: Internet
|
|
27
28
|
Classifier: Topic :: Internet :: WWW/HTTP
|
|
28
29
|
Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import re
|
|
2
2
|
from collections import defaultdict
|
|
3
3
|
from collections.abc import Callable, Sequence
|
|
4
|
-
from copy import deepcopy
|
|
4
|
+
from copy import copy, deepcopy
|
|
5
5
|
from dataclasses import dataclass
|
|
6
6
|
from typing import (
|
|
7
7
|
TYPE_CHECKING,
|
|
@@ -49,6 +49,7 @@ if TYPE_CHECKING:
|
|
|
49
49
|
_Call = TypeVar("_Call", bound=Callable[..., Any])
|
|
50
50
|
_R = TypeVar("_R", bound=APIRouter)
|
|
51
51
|
_WR = TypeVar("_WR", bound=APIRouter, default=APIRouter)
|
|
52
|
+
_RouteT = TypeVar("_RouteT", bound=BaseRoute)
|
|
52
53
|
# This is a hack we do because we can't guarantee how the user will use the router.
|
|
53
54
|
_DELETED_ROUTE_TAG = "_CADWYN_DELETED_ROUTE"
|
|
54
55
|
|
|
@@ -90,6 +91,25 @@ class VersionedAPIRouter(fastapi.routing.APIRouter):
|
|
|
90
91
|
return endpoint
|
|
91
92
|
|
|
92
93
|
|
|
94
|
+
def copy_router(router: _R) -> _R:
|
|
95
|
+
router = copy(router)
|
|
96
|
+
router.routes = [copy_route(r) for r in router.routes]
|
|
97
|
+
return router
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def copy_route(route: _RouteT) -> _RouteT:
|
|
101
|
+
if not isinstance(route, APIRoute):
|
|
102
|
+
return copy(route)
|
|
103
|
+
|
|
104
|
+
# This is slightly wasteful in terms of resources but it makes it easy for us
|
|
105
|
+
# to make sure that new versions of FastAPI are going to be supported even if
|
|
106
|
+
# APIRoute gets new attributes.
|
|
107
|
+
new_route = deepcopy(route)
|
|
108
|
+
new_route.dependant = copy(route.dependant)
|
|
109
|
+
new_route.dependencies = copy(route.dependencies)
|
|
110
|
+
return new_route
|
|
111
|
+
|
|
112
|
+
|
|
93
113
|
class _EndpointTransformer(Generic[_R, _WR]):
|
|
94
114
|
def __init__(self, parent_router: _R, versions: VersionBundle, webhooks: _WR) -> None:
|
|
95
115
|
super().__init__()
|
|
@@ -103,8 +123,8 @@ class _EndpointTransformer(Generic[_R, _WR]):
|
|
|
103
123
|
]
|
|
104
124
|
|
|
105
125
|
def transform(self) -> GeneratedRouters[_R, _WR]:
|
|
106
|
-
router =
|
|
107
|
-
webhook_router =
|
|
126
|
+
router = copy_router(self.parent_router)
|
|
127
|
+
webhook_router = copy_router(self.parent_webhooks_router)
|
|
108
128
|
routers: dict[VersionDate, _R] = {}
|
|
109
129
|
webhook_routers: dict[VersionDate, _WR] = {}
|
|
110
130
|
|
|
@@ -117,8 +137,8 @@ class _EndpointTransformer(Generic[_R, _WR]):
|
|
|
117
137
|
routers[version.value] = router
|
|
118
138
|
webhook_routers[version.value] = webhook_router
|
|
119
139
|
# Applying changes for the next version
|
|
120
|
-
router =
|
|
121
|
-
webhook_router =
|
|
140
|
+
router = copy_router(router)
|
|
141
|
+
webhook_router = copy_router(webhook_router)
|
|
122
142
|
self._apply_endpoint_changes_to_router(router.routes + webhook_router.routes, version)
|
|
123
143
|
|
|
124
144
|
if self.routes_that_never_existed:
|
|
@@ -134,7 +154,7 @@ class _EndpointTransformer(Generic[_R, _WR]):
|
|
|
134
154
|
if not isinstance(head_route, APIRoute):
|
|
135
155
|
continue
|
|
136
156
|
_add_request_and_response_params(head_route)
|
|
137
|
-
copy_of_dependant =
|
|
157
|
+
copy_of_dependant = copy(head_route.dependant)
|
|
138
158
|
|
|
139
159
|
for older_router in list(routers.values()):
|
|
140
160
|
older_route = older_router.routes[route_index]
|
|
@@ -367,6 +367,10 @@ class _PydanticModelWrapper(Generic[_T_PYDANTIC_MODEL]):
|
|
|
367
367
|
return model_copy
|
|
368
368
|
|
|
369
369
|
|
|
370
|
+
def is_regular_function(call: Callable):
|
|
371
|
+
return isinstance(call, types.FunctionType | types.MethodType)
|
|
372
|
+
|
|
373
|
+
|
|
370
374
|
class _CallableWrapper:
|
|
371
375
|
"""__eq__ and __hash__ are needed to make sure that dependency overrides work correctly.
|
|
372
376
|
They are based on putting dependencies (functions) as keys for the dictionary so if we want to be able to
|
|
@@ -376,6 +380,8 @@ class _CallableWrapper:
|
|
|
376
380
|
def __init__(self, original_callable: Callable) -> None:
|
|
377
381
|
super().__init__()
|
|
378
382
|
self._original_callable = original_callable
|
|
383
|
+
if not is_regular_function(original_callable):
|
|
384
|
+
original_callable = original_callable.__call__
|
|
379
385
|
functools.update_wrapper(self, original_callable)
|
|
380
386
|
|
|
381
387
|
@property
|
|
@@ -458,6 +464,12 @@ class _AnnotationTransformer:
|
|
|
458
464
|
def _change_version_of_a_non_container_annotation(self, annotation: Any) -> Any:
|
|
459
465
|
if isinstance(annotation, _BaseGenericAlias | types.GenericAlias):
|
|
460
466
|
return get_origin(annotation)[tuple(self.change_version_of_annotation(arg) for arg in get_args(annotation))]
|
|
467
|
+
elif isinstance(annotation, fastapi.params.Security):
|
|
468
|
+
return fastapi.params.Security(
|
|
469
|
+
self.change_version_of_annotation(annotation.dependency),
|
|
470
|
+
scopes=annotation.scopes,
|
|
471
|
+
use_cache=annotation.use_cache,
|
|
472
|
+
)
|
|
461
473
|
elif isinstance(annotation, fastapi.params.Depends):
|
|
462
474
|
return fastapi.params.Depends(
|
|
463
475
|
self.change_version_of_annotation(annotation.dependency),
|
|
@@ -475,7 +487,7 @@ class _AnnotationTransformer:
|
|
|
475
487
|
elif callable(annotation):
|
|
476
488
|
if type(annotation).__module__.startswith(
|
|
477
489
|
("fastapi.", "pydantic.", "pydantic_core.", "starlette.")
|
|
478
|
-
) or isinstance(annotation, fastapi.
|
|
490
|
+
) or isinstance(annotation, fastapi.security.base.SecurityBase):
|
|
479
491
|
return annotation
|
|
480
492
|
|
|
481
493
|
def modifier(annotation: Any):
|
|
@@ -568,8 +580,12 @@ class _AnnotationTransformer:
|
|
|
568
580
|
def _copy_function_through_class_based_wrapper(cls, call: Any):
|
|
569
581
|
"""Separate from copy_endpoint because endpoints MUST be functions in FastAPI, they cannot be cls instances"""
|
|
570
582
|
call = cls._unwrap_callable(call)
|
|
571
|
-
|
|
572
|
-
|
|
583
|
+
if not is_regular_function(call):
|
|
584
|
+
# This means that the callable is actually an instance of a regular class
|
|
585
|
+
actual_call = call.__call__
|
|
586
|
+
else:
|
|
587
|
+
actual_call = call
|
|
588
|
+
if inspect.iscoroutinefunction(actual_call):
|
|
573
589
|
return _AsyncCallableWrapper(call)
|
|
574
590
|
else:
|
|
575
591
|
return _CallableWrapper(call)
|
|
@@ -578,9 +594,6 @@ class _AnnotationTransformer:
|
|
|
578
594
|
def _unwrap_callable(call: Any) -> Any:
|
|
579
595
|
while hasattr(call, "_original_callable"):
|
|
580
596
|
call = call._original_callable
|
|
581
|
-
if not isinstance(call, types.FunctionType | types.MethodType):
|
|
582
|
-
# This means that the callable is actually an instance of a regular class
|
|
583
|
-
call = call.__call__
|
|
584
597
|
|
|
585
598
|
return call
|
|
586
599
|
|
|
@@ -618,7 +631,7 @@ class SchemaGenerator:
|
|
|
618
631
|
wrapper = self._get_wrapper_for_model(model)
|
|
619
632
|
model_copy = wrapper.generate_model_copy(self)
|
|
620
633
|
self.concrete_models[model] = model_copy
|
|
621
|
-
return model_copy
|
|
634
|
+
return cast(type[_T_ANY_MODEL], model_copy)
|
|
622
635
|
|
|
623
636
|
@overload
|
|
624
637
|
def _get_wrapper_for_model(self, model: type[BaseModel]) -> "_PydanticModelWrapper[BaseModel]": ...
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "cadwyn"
|
|
3
|
-
version = "4.4.
|
|
3
|
+
version = "4.4.3"
|
|
4
4
|
description = "Production-ready community-driven modern Stripe-like API versioning in FastAPI"
|
|
5
5
|
authors = [{ name = "Stanislav Zmiev", email = "zmievsa@gmail.com" }]
|
|
6
6
|
license = "MIT"
|
|
@@ -31,6 +31,7 @@ classifiers = [
|
|
|
31
31
|
"Programming Language :: Python :: 3.10",
|
|
32
32
|
"Programming Language :: Python :: 3.11",
|
|
33
33
|
"Programming Language :: Python :: 3.12",
|
|
34
|
+
"Programming Language :: Python :: 3.13",
|
|
34
35
|
"Topic :: Internet",
|
|
35
36
|
"Topic :: Software Development :: Libraries :: Application Frameworks",
|
|
36
37
|
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
@@ -57,24 +58,16 @@ dependencies = [
|
|
|
57
58
|
"typing-extensions>=4.8.0",
|
|
58
59
|
]
|
|
59
60
|
|
|
61
|
+
|
|
60
62
|
[project.optional-dependencies]
|
|
61
63
|
standard = ["fastapi[standard]>=0.112.3", "typer>=0.7.0"]
|
|
62
64
|
|
|
63
|
-
[project.urls]
|
|
64
|
-
"Source code" = "https://github.com/zmievsa/cadwyn"
|
|
65
|
-
Documentation = "https://docs.cadwyn.dev"
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
[project.scripts]
|
|
69
|
-
cadwyn = "cadwyn.__main__:app"
|
|
70
|
-
|
|
71
65
|
[tool.uv]
|
|
72
66
|
dev-dependencies = [
|
|
73
67
|
"pdbpp ~=0.10.3",
|
|
74
68
|
"python-multipart >=0.0.6",
|
|
75
69
|
"better-devtools ~=0.13.3",
|
|
76
70
|
"pytest-sugar ~=1.0.0",
|
|
77
|
-
|
|
78
71
|
# tests
|
|
79
72
|
"svcs ~=24.1.0",
|
|
80
73
|
"httpx >=0.26.0",
|
|
@@ -83,7 +76,6 @@ dev-dependencies = [
|
|
|
83
76
|
"pytest-cov >=4.0.0",
|
|
84
77
|
"dirty-equals >=0.6.0",
|
|
85
78
|
"uvicorn ~=0.23.0",
|
|
86
|
-
|
|
87
79
|
# docs
|
|
88
80
|
"mkdocs >=1.5.2",
|
|
89
81
|
"mkdocs-material >=9.3.1",
|
|
@@ -92,6 +84,15 @@ dev-dependencies = [
|
|
|
92
84
|
"mike >=2.1.2, <3",
|
|
93
85
|
]
|
|
94
86
|
|
|
87
|
+
[project.urls]
|
|
88
|
+
"Source code" = "https://github.com/zmievsa/cadwyn"
|
|
89
|
+
Documentation = "https://docs.cadwyn.dev"
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
[project.scripts]
|
|
93
|
+
cadwyn = "cadwyn.__main__:app"
|
|
94
|
+
|
|
95
|
+
|
|
95
96
|
[tool.coverage.run]
|
|
96
97
|
data_file = "coverage/coverage"
|
|
97
98
|
parallel = true
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
from typing import NoReturn
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
from fastapi import APIRouter, HTTPException, Security
|
|
5
|
+
from fastapi.testclient import TestClient
|
|
6
|
+
|
|
7
|
+
from cadwyn.applications import Cadwyn
|
|
8
|
+
from cadwyn.structure.versions import Version, VersionBundle
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class ScarySecurity:
|
|
12
|
+
"""It's IMPORTANT that we use an instance of a class instead of a function because it can be properly copied.
|
|
13
|
+
|
|
14
|
+
It's an edge case.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
async def __call__(self) -> NoReturn:
|
|
18
|
+
raise HTTPException(status_code=401, detail="Unauthorized")
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
scary_security = ScarySecurity()
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@pytest.fixture
|
|
25
|
+
def cadwyn_app():
|
|
26
|
+
router = APIRouter()
|
|
27
|
+
|
|
28
|
+
@router.get("/hello")
|
|
29
|
+
async def world(user=Security(scary_security)):
|
|
30
|
+
return {"hello": "world", "user": user}
|
|
31
|
+
|
|
32
|
+
app = Cadwyn(versions=VersionBundle(Version("2023-11-16")))
|
|
33
|
+
app.include_router(router)
|
|
34
|
+
app.generate_and_include_versioned_routers(router)
|
|
35
|
+
|
|
36
|
+
return app
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@pytest.fixture
|
|
40
|
+
def user_client(cadwyn_app: Cadwyn):
|
|
41
|
+
with TestClient(app=cadwyn_app, base_url="http://test") as ac:
|
|
42
|
+
yield ac
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@pytest.fixture
|
|
46
|
+
def _override_auth_dependency(cadwyn_app: Cadwyn) -> None:
|
|
47
|
+
cadwyn_app.dependency_overrides[scary_security] = lambda: {"id": 123}
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def test__no_dependency_overrides_with_unversioned_routes(user_client: TestClient):
|
|
51
|
+
response = user_client.get("/hello")
|
|
52
|
+
assert response.status_code == 401, response.json()
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def test__no_dependency_overrides_with_versioned_routes(user_client: TestClient):
|
|
56
|
+
response = user_client.get("/hello", headers={"x-api-version": "2023-11-16"})
|
|
57
|
+
assert response.status_code == 401, response.json()
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def test__dependency_overrides_with_unversioned_routes(user_client: TestClient, _override_auth_dependency: None):
|
|
61
|
+
response = user_client.get("/hello")
|
|
62
|
+
assert response.status_code == 200, response.json()
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def test__dependency_overrides_with_versioned_routes(user_client: TestClient, _override_auth_dependency: None):
|
|
66
|
+
response = user_client.get("/hello", headers={"x-api-version": "2023-11-16"})
|
|
67
|
+
assert response.status_code == 200, response.json()
|
|
@@ -84,7 +84,7 @@ wheels = [
|
|
|
84
84
|
|
|
85
85
|
[[package]]
|
|
86
86
|
name = "cadwyn"
|
|
87
|
-
version = "4.4.
|
|
87
|
+
version = "4.4.2"
|
|
88
88
|
source = { editable = "." }
|
|
89
89
|
dependencies = [
|
|
90
90
|
{ name = "backports-strenum", marker = "python_full_version < '3.11'" },
|
|
@@ -391,16 +391,16 @@ wheels = [
|
|
|
391
391
|
|
|
392
392
|
[[package]]
|
|
393
393
|
name = "fastapi"
|
|
394
|
-
version = "0.115.
|
|
394
|
+
version = "0.115.4"
|
|
395
395
|
source = { registry = "https://pypi.org/simple" }
|
|
396
396
|
dependencies = [
|
|
397
397
|
{ name = "pydantic" },
|
|
398
398
|
{ name = "starlette" },
|
|
399
399
|
{ name = "typing-extensions" },
|
|
400
400
|
]
|
|
401
|
-
sdist = { url = "https://files.pythonhosted.org/packages/a9/
|
|
401
|
+
sdist = { url = "https://files.pythonhosted.org/packages/a9/db/5781f19bd30745885e0737ff3fdd4e63e7bc691710f9da691128bb0dc73b/fastapi-0.115.4.tar.gz", hash = "sha256:db653475586b091cb8b2fec2ac54a680ac6a158e07406e1abae31679e8826349", size = 300737 }
|
|
402
402
|
wheels = [
|
|
403
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
403
|
+
{ url = "https://files.pythonhosted.org/packages/99/f6/af0d1f58f86002be0cf1e2665cdd6f7a4a71cdc8a7a9438cdc9e3b5375fe/fastapi-0.115.4-py3-none-any.whl", hash = "sha256:0b504a063ffb3cf96a5e27dc1bc32c80ca743a2528574f9cdc77daa2d31b4742", size = 94732 },
|
|
404
404
|
]
|
|
405
405
|
|
|
406
406
|
[package.optional-dependencies]
|
|
@@ -747,7 +747,7 @@ wheels = [
|
|
|
747
747
|
|
|
748
748
|
[[package]]
|
|
749
749
|
name = "mkdocs-material"
|
|
750
|
-
version = "9.5.
|
|
750
|
+
version = "9.5.43"
|
|
751
751
|
source = { registry = "https://pypi.org/simple" }
|
|
752
752
|
dependencies = [
|
|
753
753
|
{ name = "babel" },
|
|
@@ -762,9 +762,9 @@ dependencies = [
|
|
|
762
762
|
{ name = "regex" },
|
|
763
763
|
{ name = "requests" },
|
|
764
764
|
]
|
|
765
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
765
|
+
sdist = { url = "https://files.pythonhosted.org/packages/0f/81/88039be572a6b063a3ebc99421cf523b56e3560c0baccd7e0c45569469b1/mkdocs_material-9.5.43.tar.gz", hash = "sha256:83be7ff30b65a1e4930dfa4ab911e75780a3afc9583d162692e434581cb46979", size = 3962873 }
|
|
766
766
|
wheels = [
|
|
767
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
767
|
+
{ url = "https://files.pythonhosted.org/packages/6d/22/af8d23818887a39613f821672346776d585c2544938be2561e6e0374cb2d/mkdocs_material-9.5.43-py3-none-any.whl", hash = "sha256:4aae0664c456fd12837a3192e0225c17960ba8bf55d7f0a7daef7e4b0b914a34", size = 8672197 },
|
|
768
768
|
]
|
|
769
769
|
|
|
770
770
|
[[package]]
|
|
@@ -939,15 +939,15 @@ wheels = [
|
|
|
939
939
|
|
|
940
940
|
[[package]]
|
|
941
941
|
name = "pymdown-extensions"
|
|
942
|
-
version = "10.
|
|
942
|
+
version = "10.12"
|
|
943
943
|
source = { registry = "https://pypi.org/simple" }
|
|
944
944
|
dependencies = [
|
|
945
945
|
{ name = "markdown" },
|
|
946
946
|
{ name = "pyyaml" },
|
|
947
947
|
]
|
|
948
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
948
|
+
sdist = { url = "https://files.pythonhosted.org/packages/d8/0b/32f05854cfd432e9286bb41a870e0d1a926b72df5f5cdb6dec962b2e369e/pymdown_extensions-10.12.tar.gz", hash = "sha256:b0ee1e0b2bef1071a47891ab17003bfe5bf824a398e13f49f8ed653b699369a7", size = 840790 }
|
|
949
949
|
wheels = [
|
|
950
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
950
|
+
{ url = "https://files.pythonhosted.org/packages/53/32/95a164ddf533bd676cbbe878e36e89b4ade3efde8dd61d0148c90cbbe57e/pymdown_extensions-10.12-py3-none-any.whl", hash = "sha256:49f81412242d3527b8b4967b990df395c89563043bc51a3d2d7d500e52123b77", size = 263448 },
|
|
951
951
|
]
|
|
952
952
|
|
|
953
953
|
[[package]]
|
|
@@ -990,15 +990,15 @@ wheels = [
|
|
|
990
990
|
|
|
991
991
|
[[package]]
|
|
992
992
|
name = "pytest-cov"
|
|
993
|
-
version = "
|
|
993
|
+
version = "6.0.0"
|
|
994
994
|
source = { registry = "https://pypi.org/simple" }
|
|
995
995
|
dependencies = [
|
|
996
996
|
{ name = "coverage", extra = ["toml"] },
|
|
997
997
|
{ name = "pytest" },
|
|
998
998
|
]
|
|
999
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
999
|
+
sdist = { url = "https://files.pythonhosted.org/packages/be/45/9b538de8cef30e17c7b45ef42f538a94889ed6a16f2387a6c89e73220651/pytest-cov-6.0.0.tar.gz", hash = "sha256:fde0b595ca248bb8e2d76f020b465f3b107c9632e6a1d1705f17834c89dcadc0", size = 66945 }
|
|
1000
1000
|
wheels = [
|
|
1001
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1001
|
+
{ url = "https://files.pythonhosted.org/packages/36/3b/48e79f2cd6a61dbbd4807b4ed46cb564b4fd50a76166b1c4ea5c1d9e2371/pytest_cov-6.0.0-py3-none-any.whl", hash = "sha256:eee6f1b9e61008bd34975a4d5bab25801eb31898b032dd55addc93e96fcaaa35", size = 22949 },
|
|
1002
1002
|
]
|
|
1003
1003
|
|
|
1004
1004
|
[[package]]
|
|
@@ -1051,11 +1051,11 @@ wheels = [
|
|
|
1051
1051
|
|
|
1052
1052
|
[[package]]
|
|
1053
1053
|
name = "python-multipart"
|
|
1054
|
-
version = "0.0.
|
|
1054
|
+
version = "0.0.17"
|
|
1055
1055
|
source = { registry = "https://pypi.org/simple" }
|
|
1056
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
1056
|
+
sdist = { url = "https://files.pythonhosted.org/packages/40/22/edea41c2d4a22e666c0c7db7acdcbf7bc8c1c1f7d3b3ca246ec982fec612/python_multipart-0.0.17.tar.gz", hash = "sha256:41330d831cae6e2f22902704ead2826ea038d0419530eadff3ea80175aec5538", size = 36452 }
|
|
1057
1057
|
wheels = [
|
|
1058
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1058
|
+
{ url = "https://files.pythonhosted.org/packages/b4/fb/275137a799169392f1fa88fff2be92f16eee38e982720a8aaadefc4a36b2/python_multipart-0.0.17-py3-none-any.whl", hash = "sha256:15dc4f487e0a9476cc1201261188ee0940165cffc94429b6fc565c4d3045cb5d", size = 24453 },
|
|
1059
1059
|
]
|
|
1060
1060
|
|
|
1061
1061
|
[[package]]
|
|
@@ -1209,16 +1209,16 @@ wheels = [
|
|
|
1209
1209
|
|
|
1210
1210
|
[[package]]
|
|
1211
1211
|
name = "rich"
|
|
1212
|
-
version = "13.9.
|
|
1212
|
+
version = "13.9.4"
|
|
1213
1213
|
source = { registry = "https://pypi.org/simple" }
|
|
1214
1214
|
dependencies = [
|
|
1215
1215
|
{ name = "markdown-it-py" },
|
|
1216
1216
|
{ name = "pygments" },
|
|
1217
1217
|
{ name = "typing-extensions", marker = "python_full_version < '3.11'" },
|
|
1218
1218
|
]
|
|
1219
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
1219
|
+
sdist = { url = "https://files.pythonhosted.org/packages/ab/3a/0316b28d0761c6734d6bc14e770d85506c986c85ffb239e688eeaab2c2bc/rich-13.9.4.tar.gz", hash = "sha256:439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098", size = 223149 }
|
|
1220
1220
|
wheels = [
|
|
1221
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1221
|
+
{ url = "https://files.pythonhosted.org/packages/19/71/39c7c0d87f8d4e6c020a393182060eaefeeae6c01dab6a84ec346f2567df/rich-13.9.4-py3-none-any.whl", hash = "sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90", size = 242424 },
|
|
1222
1222
|
]
|
|
1223
1223
|
|
|
1224
1224
|
[[package]]
|
|
@@ -1250,14 +1250,14 @@ wheels = [
|
|
|
1250
1250
|
|
|
1251
1251
|
[[package]]
|
|
1252
1252
|
name = "starlette"
|
|
1253
|
-
version = "0.41.
|
|
1253
|
+
version = "0.41.2"
|
|
1254
1254
|
source = { registry = "https://pypi.org/simple" }
|
|
1255
1255
|
dependencies = [
|
|
1256
1256
|
{ name = "anyio" },
|
|
1257
1257
|
]
|
|
1258
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
1258
|
+
sdist = { url = "https://files.pythonhosted.org/packages/3e/da/1fb4bdb72ae12b834becd7e1e7e47001d32f91ec0ce8d7bc1b618d9f0bd9/starlette-0.41.2.tar.gz", hash = "sha256:9834fd799d1a87fd346deb76158668cfa0b0d56f85caefe8268e2d97c3468b62", size = 2573867 }
|
|
1259
1259
|
wheels = [
|
|
1260
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1260
|
+
{ url = "https://files.pythonhosted.org/packages/54/43/f185bfd0ca1d213beb4293bed51d92254df23d8ceaf6c0e17146d508a776/starlette-0.41.2-py3-none-any.whl", hash = "sha256:fbc189474b4731cf30fcef52f18a8d070e3f3b46c6a04c97579e85e6ffca942d", size = 73259 },
|
|
1261
1261
|
]
|
|
1262
1262
|
|
|
1263
1263
|
[[package]]
|
|
@@ -1391,34 +1391,34 @@ wheels = [
|
|
|
1391
1391
|
|
|
1392
1392
|
[[package]]
|
|
1393
1393
|
name = "watchdog"
|
|
1394
|
-
version = "
|
|
1395
|
-
source = { registry = "https://pypi.org/simple" }
|
|
1396
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
1397
|
-
wheels = [
|
|
1398
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1399
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1400
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1401
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1402
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1403
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1404
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1405
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1406
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1407
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1408
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1409
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1410
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1411
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1412
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1413
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1414
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1415
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1416
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1417
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1418
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1419
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1420
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1421
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1394
|
+
version = "6.0.0"
|
|
1395
|
+
source = { registry = "https://pypi.org/simple" }
|
|
1396
|
+
sdist = { url = "https://files.pythonhosted.org/packages/db/7d/7f3d619e951c88ed75c6037b246ddcf2d322812ee8ea189be89511721d54/watchdog-6.0.0.tar.gz", hash = "sha256:9ddf7c82fda3ae8e24decda1338ede66e1c99883db93711d8fb941eaa2d8c282", size = 131220 }
|
|
1397
|
+
wheels = [
|
|
1398
|
+
{ url = "https://files.pythonhosted.org/packages/0c/56/90994d789c61df619bfc5ce2ecdabd5eeff564e1eb47512bd01b5e019569/watchdog-6.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d1cdb490583ebd691c012b3d6dae011000fe42edb7a82ece80965b42abd61f26", size = 96390 },
|
|
1399
|
+
{ url = "https://files.pythonhosted.org/packages/55/46/9a67ee697342ddf3c6daa97e3a587a56d6c4052f881ed926a849fcf7371c/watchdog-6.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bc64ab3bdb6a04d69d4023b29422170b74681784ffb9463ed4870cf2f3e66112", size = 88389 },
|
|
1400
|
+
{ url = "https://files.pythonhosted.org/packages/44/65/91b0985747c52064d8701e1075eb96f8c40a79df889e59a399453adfb882/watchdog-6.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c897ac1b55c5a1461e16dae288d22bb2e412ba9807df8397a635d88f671d36c3", size = 89020 },
|
|
1401
|
+
{ url = "https://files.pythonhosted.org/packages/e0/24/d9be5cd6642a6aa68352ded4b4b10fb0d7889cb7f45814fb92cecd35f101/watchdog-6.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6eb11feb5a0d452ee41f824e271ca311a09e250441c262ca2fd7ebcf2461a06c", size = 96393 },
|
|
1402
|
+
{ url = "https://files.pythonhosted.org/packages/63/7a/6013b0d8dbc56adca7fdd4f0beed381c59f6752341b12fa0886fa7afc78b/watchdog-6.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ef810fbf7b781a5a593894e4f439773830bdecb885e6880d957d5b9382a960d2", size = 88392 },
|
|
1403
|
+
{ url = "https://files.pythonhosted.org/packages/d1/40/b75381494851556de56281e053700e46bff5b37bf4c7267e858640af5a7f/watchdog-6.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:afd0fe1b2270917c5e23c2a65ce50c2a4abb63daafb0d419fde368e272a76b7c", size = 89019 },
|
|
1404
|
+
{ url = "https://files.pythonhosted.org/packages/39/ea/3930d07dafc9e286ed356a679aa02d777c06e9bfd1164fa7c19c288a5483/watchdog-6.0.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:bdd4e6f14b8b18c334febb9c4425a878a2ac20efd1e0b231978e7b150f92a948", size = 96471 },
|
|
1405
|
+
{ url = "https://files.pythonhosted.org/packages/12/87/48361531f70b1f87928b045df868a9fd4e253d9ae087fa4cf3f7113be363/watchdog-6.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c7c15dda13c4eb00d6fb6fc508b3c0ed88b9d5d374056b239c4ad1611125c860", size = 88449 },
|
|
1406
|
+
{ url = "https://files.pythonhosted.org/packages/5b/7e/8f322f5e600812e6f9a31b75d242631068ca8f4ef0582dd3ae6e72daecc8/watchdog-6.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6f10cb2d5902447c7d0da897e2c6768bca89174d0c6e1e30abec5421af97a5b0", size = 89054 },
|
|
1407
|
+
{ url = "https://files.pythonhosted.org/packages/68/98/b0345cabdce2041a01293ba483333582891a3bd5769b08eceb0d406056ef/watchdog-6.0.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:490ab2ef84f11129844c23fb14ecf30ef3d8a6abafd3754a6f75ca1e6654136c", size = 96480 },
|
|
1408
|
+
{ url = "https://files.pythonhosted.org/packages/85/83/cdf13902c626b28eedef7ec4f10745c52aad8a8fe7eb04ed7b1f111ca20e/watchdog-6.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:76aae96b00ae814b181bb25b1b98076d5fc84e8a53cd8885a318b42b6d3a5134", size = 88451 },
|
|
1409
|
+
{ url = "https://files.pythonhosted.org/packages/fe/c4/225c87bae08c8b9ec99030cd48ae9c4eca050a59bf5c2255853e18c87b50/watchdog-6.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a175f755fc2279e0b7312c0035d52e27211a5bc39719dd529625b1930917345b", size = 89057 },
|
|
1410
|
+
{ url = "https://files.pythonhosted.org/packages/30/ad/d17b5d42e28a8b91f8ed01cb949da092827afb9995d4559fd448d0472763/watchdog-6.0.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:c7ac31a19f4545dd92fc25d200694098f42c9a8e391bc00bdd362c5736dbf881", size = 87902 },
|
|
1411
|
+
{ url = "https://files.pythonhosted.org/packages/5c/ca/c3649991d140ff6ab67bfc85ab42b165ead119c9e12211e08089d763ece5/watchdog-6.0.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:9513f27a1a582d9808cf21a07dae516f0fab1cf2d7683a742c498b93eedabb11", size = 88380 },
|
|
1412
|
+
{ url = "https://files.pythonhosted.org/packages/a9/c7/ca4bf3e518cb57a686b2feb4f55a1892fd9a3dd13f470fca14e00f80ea36/watchdog-6.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:7607498efa04a3542ae3e05e64da8202e58159aa1fa4acddf7678d34a35d4f13", size = 79079 },
|
|
1413
|
+
{ url = "https://files.pythonhosted.org/packages/5c/51/d46dc9332f9a647593c947b4b88e2381c8dfc0942d15b8edc0310fa4abb1/watchdog-6.0.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:9041567ee8953024c83343288ccc458fd0a2d811d6a0fd68c4c22609e3490379", size = 79078 },
|
|
1414
|
+
{ url = "https://files.pythonhosted.org/packages/d4/57/04edbf5e169cd318d5f07b4766fee38e825d64b6913ca157ca32d1a42267/watchdog-6.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:82dc3e3143c7e38ec49d61af98d6558288c415eac98486a5c581726e0737c00e", size = 79076 },
|
|
1415
|
+
{ url = "https://files.pythonhosted.org/packages/ab/cc/da8422b300e13cb187d2203f20b9253e91058aaf7db65b74142013478e66/watchdog-6.0.0-py3-none-manylinux2014_ppc64.whl", hash = "sha256:212ac9b8bf1161dc91bd09c048048a95ca3a4c4f5e5d4a7d1b1a7d5752a7f96f", size = 79077 },
|
|
1416
|
+
{ url = "https://files.pythonhosted.org/packages/2c/3b/b8964e04ae1a025c44ba8e4291f86e97fac443bca31de8bd98d3263d2fcf/watchdog-6.0.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:e3df4cbb9a450c6d49318f6d14f4bbc80d763fa587ba46ec86f99f9e6876bb26", size = 79078 },
|
|
1417
|
+
{ url = "https://files.pythonhosted.org/packages/62/ae/a696eb424bedff7407801c257d4b1afda455fe40821a2be430e173660e81/watchdog-6.0.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:2cce7cfc2008eb51feb6aab51251fd79b85d9894e98ba847408f662b3395ca3c", size = 79077 },
|
|
1418
|
+
{ url = "https://files.pythonhosted.org/packages/b5/e8/dbf020b4d98251a9860752a094d09a65e1b436ad181faf929983f697048f/watchdog-6.0.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:20ffe5b202af80ab4266dcd3e91aae72bf2da48c0d33bdb15c66658e685e94e2", size = 79078 },
|
|
1419
|
+
{ url = "https://files.pythonhosted.org/packages/07/f6/d0e5b343768e8bcb4cda79f0f2f55051bf26177ecd5651f84c07567461cf/watchdog-6.0.0-py3-none-win32.whl", hash = "sha256:07df1fdd701c5d4c8e55ef6cf55b8f0120fe1aef7ef39a1c6fc6bc2e606d517a", size = 79065 },
|
|
1420
|
+
{ url = "https://files.pythonhosted.org/packages/db/d9/c495884c6e548fce18a8f40568ff120bc3a4b7b99813081c8ac0c936fa64/watchdog-6.0.0-py3-none-win_amd64.whl", hash = "sha256:cbafb470cf848d93b5d013e2ecb245d4aa1c8fd0504e863ccefa32445359d680", size = 79070 },
|
|
1421
|
+
{ url = "https://files.pythonhosted.org/packages/33/e8/e40370e6d74ddba47f002a32919d91310d6074130fe4e17dabcafc15cbf1/watchdog-6.0.0-py3-none-win_ia64.whl", hash = "sha256:a1914259fa9e1454315171103c6a30961236f508b9b623eae470268bbcc6a22f", size = 79067 },
|
|
1422
1422
|
]
|
|
1423
1423
|
|
|
1424
1424
|
[[package]]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cadwyn-4.4.1 → cadwyn-4.4.3}/docs/how_to/change_openapi_schemas/rename_a_field_in_schema.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|