cadwyn 5.1.1__tar.gz → 5.1.2__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-5.1.1 → cadwyn-5.1.2}/CHANGELOG.md +10 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/PKG-INFO +1 -1
- {cadwyn-5.1.1 → cadwyn-5.1.2}/cadwyn/__init__.py +2 -0
- cadwyn-5.1.2/cadwyn/dependencies.py +5 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/cadwyn/schema_generation.py +19 -1
- {cadwyn-5.1.1 → cadwyn-5.1.2}/cadwyn/structure/versions.py +9 -1
- {cadwyn-5.1.1 → cadwyn-5.1.2}/pyproject.toml +4 -1
- {cadwyn-5.1.1 → cadwyn-5.1.2}/tests/test_router_generation.py +56 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/uv.lock +18 -1
- {cadwyn-5.1.1 → cadwyn-5.1.2}/.github/CODE_OF_CONDUCT.md +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/.github/actions/setup-python-uv/action.yaml +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/.github/workflows/ci.yaml +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/.github/workflows/daily_tests.yaml +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/.github/workflows/publish_docs.yaml +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/.github/workflows/release.yaml +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/.gitignore +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/.pre-commit-config.yaml +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/LICENSE +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/Makefile +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/README.md +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/cadwyn/__main__.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/cadwyn/_asts.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/cadwyn/_importer.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/cadwyn/_render.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/cadwyn/_utils.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/cadwyn/applications.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/cadwyn/changelogs.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/cadwyn/exceptions.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/cadwyn/middleware.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/cadwyn/py.typed +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/cadwyn/route_generation.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/cadwyn/routing.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/cadwyn/static/__init__.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/cadwyn/static/docs.html +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/cadwyn/structure/__init__.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/cadwyn/structure/common.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/cadwyn/structure/data.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/cadwyn/structure/endpoints.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/cadwyn/structure/enums.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/cadwyn/structure/schemas.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs/CNAME +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs/__init__.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs/concepts/api_version_parameter_and_context_variables.md +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs/concepts/beware_of_data_versioning.md +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs/concepts/changelogs.md +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs/concepts/cli.md +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs/concepts/endpoint_migrations.md +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs/concepts/enum_migrations.md +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs/concepts/index.md +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs/concepts/main_app.md +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs/concepts/methodology.md +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs/concepts/schema_generation.md +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs/concepts/schema_migrations.md +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs/concepts/testing.md +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs/concepts/version_changes.md +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs/concepts/where_to_put_the_version_and_how_to_format_it.md +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs/home/CONTRIBUTING.md +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs/how_to/change_business_logic/index.md +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs/how_to/change_endpoints/index.md +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs/how_to/change_openapi_schemas/add_field.md +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs/how_to/change_openapi_schemas/change_field_type.md +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs/how_to/change_openapi_schemas/change_schema_without_endpoint.md +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs/how_to/change_openapi_schemas/changing_constraints.md +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs/how_to/change_openapi_schemas/remove_field.md +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs/how_to/change_openapi_schemas/rename_a_field_in_schema.md +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs/how_to/index.md +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs/how_to/version_with_paths_and_numbers_instead_of_headers_and_dates.md +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs/img/dashboard_with_one_version.png +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs/img/dashboard_with_two_versions.png +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs/img/get_users_endpoint_from_prior_version.png +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs/img/simplified_migration_model.png +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs/img/sponsor_logos/monite.png +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs/img/unversioned_dashboard.png +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs/index.md +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs/plugin.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs/quickstart/setup.md +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs/quickstart/tutorial.md +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs/theory/how_to_build_versioning_framework.md +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs/theory/how_we_got_here.md +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs/theory/literature.md +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs_src/__init__.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs_src/how_to/__init__.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs_src/how_to/change_openapi_schemas/__init__.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs_src/how_to/change_openapi_schemas/change_schema_without_endpoint/__init__.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs_src/how_to/change_openapi_schemas/change_schema_without_endpoint/block001.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs_src/how_to/change_openapi_schemas/change_schema_without_endpoint/block002.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs_src/how_to/change_openapi_schemas/change_schema_without_endpoint/tests/__init__.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs_src/how_to/change_openapi_schemas/change_schema_without_endpoint/tests/test_block001.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs_src/how_to/change_openapi_schemas/change_schema_without_endpoint/tests/test_block002.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs_src/how_to/version_with_path_and_numbers_instead_of_headers_and_dates/__init__.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs_src/how_to/version_with_path_and_numbers_instead_of_headers_and_dates/block001.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs_src/how_to/version_with_path_and_numbers_instead_of_headers_and_dates/tests/__init__.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs_src/how_to/version_with_path_and_numbers_instead_of_headers_and_dates/tests/test_block_001.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs_src/quickstart/__init__.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs_src/quickstart/setup/__init__.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs_src/quickstart/setup/block001.sh +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs_src/quickstart/setup/block002.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs_src/quickstart/setup/tests/__init__.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs_src/quickstart/setup/tests/test_block002.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs_src/quickstart/tutorial/__init__.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs_src/quickstart/tutorial/block001.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs_src/quickstart/tutorial/block002.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs_src/quickstart/tutorial/block003.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs_src/quickstart/tutorial/tests/__init__.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs_src/quickstart/tutorial/tests/test_block001.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs_src/quickstart/tutorial/tests/test_block002.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs_src/quickstart/tutorial/tests/test_block003.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/docs_src/ruff.toml +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/mkdocs.yml +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/ruff.toml +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/scripts/fix_links.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/scripts/split_md.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/tests/__init__.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/tests/_data/__init__.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/tests/_data/unversioned_schema_dir/__init__.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/tests/_data/unversioned_schema_dir/unversioned_schemas.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/tests/_data/unversioned_schemas.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/tests/_resources/__init__.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/tests/_resources/app_for_testing_routing.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/tests/_resources/render/__init__.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/tests/_resources/render/classes.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/tests/_resources/render/complex/__init__.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/tests/_resources/render/complex/classes.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/tests/_resources/render/complex/versions.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/tests/_resources/render/versions.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/tests/_resources/utils.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/tests/_resources/versioned_app/__init__.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/tests/_resources/versioned_app/app.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/tests/_resources/versioned_app/v2021_01_01.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/tests/_resources/versioned_app/v2022_01_02.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/tests/_resources/versioned_app/webhooks.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/tests/conftest.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/tests/test_applications.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/tests/test_auth_dependencies.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/tests/test_changelog.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/tests/test_cli.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/tests/test_data_migrations.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/tests/test_render.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/tests/test_router_generation_with_from_future_annotations.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/tests/test_routing.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/tests/test_schema_generation/__init__.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/tests/test_schema_generation/test_enum.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/tests/test_schema_generation/test_schema.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/tests/test_schema_generation/test_schema_field.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/tests/test_schema_generation/test_schema_validator.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/tests/test_schema_generation/test_schema_with_future_annotations.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/tests/test_structure.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/tests/tutorial/__init__.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/tests/tutorial/main.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/tests/tutorial/test_example.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/tests/versioning_styles/__init__.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/tests/versioning_styles/test_versioning_formats.py +0 -0
- {cadwyn-5.1.1 → cadwyn-5.1.2}/tox.ini +0 -0
|
@@ -5,6 +5,16 @@ Please follow [the Keep a Changelog standard](https://keepachangelog.com/en/1.0.
|
|
|
5
5
|
|
|
6
6
|
## [Unreleased]
|
|
7
7
|
|
|
8
|
+
## [5.1.2]
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
* Generators not being called when fastapi validates the initial request
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
* `cadwyn.current_dependency_solver` function to check whether cadwyn or fastapi is currently solving dependencies. It can be used as a dependency for versioned endpoints like so: `current_dependency_solver: Annotated[Literal["fastapi", "cadwyn"], Depends(current_dependency_solver)]`. If your dependency has side effects, you would likely want to only run it once per request. If you want to run it once we migrated the request to the latest version, you should only run it when `current_dependency_solver` is `"cadwyn"`. If you want your dependency to run at the very beginning of handling the request, you should only run it when `current_dependency_solver` is `"fastapi"`.
|
|
17
|
+
|
|
8
18
|
## [5.1.1]
|
|
9
19
|
|
|
10
20
|
### Fixed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cadwyn
|
|
3
|
-
Version: 5.1.
|
|
3
|
+
Version: 5.1.2
|
|
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
|
|
@@ -2,6 +2,7 @@ import importlib.metadata
|
|
|
2
2
|
|
|
3
3
|
from .applications import Cadwyn
|
|
4
4
|
from .changelogs import hidden
|
|
5
|
+
from .dependencies import current_dependency_solver
|
|
5
6
|
from .route_generation import VersionedAPIRouter, generate_versioned_routers
|
|
6
7
|
from .schema_generation import generate_versioned_models, migrate_response_body
|
|
7
8
|
from .structure import (
|
|
@@ -32,6 +33,7 @@ __all__ = [
|
|
|
32
33
|
"VersionedAPIRouter",
|
|
33
34
|
"convert_request_to_next_version_for",
|
|
34
35
|
"convert_response_to_previous_version_for",
|
|
36
|
+
"current_dependency_solver",
|
|
35
37
|
"endpoint",
|
|
36
38
|
"enum",
|
|
37
39
|
"generate_versioned_models",
|
|
@@ -20,6 +20,7 @@ import pydantic
|
|
|
20
20
|
import pydantic._internal._decorators
|
|
21
21
|
import typing_extensions
|
|
22
22
|
from fastapi import Response
|
|
23
|
+
from fastapi.dependencies.utils import is_async_gen_callable, is_coroutine_callable, is_gen_callable
|
|
23
24
|
from fastapi.routing import APIRoute
|
|
24
25
|
from pydantic import BaseModel, Field, RootModel
|
|
25
26
|
from pydantic._internal import _decorators
|
|
@@ -77,6 +78,7 @@ from cadwyn.structure.versions import _CADWYN_REQUEST_PARAM_NAME, _CADWYN_RESPON
|
|
|
77
78
|
if TYPE_CHECKING:
|
|
78
79
|
from cadwyn.structure.versions import HeadVersion, Version, VersionBundle
|
|
79
80
|
|
|
81
|
+
|
|
80
82
|
if sys.version_info >= (3, 10):
|
|
81
83
|
from typing import _BaseGenericAlias # pyright: ignore[reportAttributeAccessIssue]
|
|
82
84
|
else:
|
|
@@ -486,6 +488,7 @@ class _CallableWrapper:
|
|
|
486
488
|
self._original_callable = original_callable
|
|
487
489
|
if not is_regular_function(original_callable):
|
|
488
490
|
original_callable = original_callable.__call__
|
|
491
|
+
|
|
489
492
|
functools.update_wrapper(self, original_callable)
|
|
490
493
|
|
|
491
494
|
@property
|
|
@@ -510,6 +513,17 @@ class _AsyncCallableWrapper(_CallableWrapper):
|
|
|
510
513
|
return await self._original_callable(*args, **kwargs)
|
|
511
514
|
|
|
512
515
|
|
|
516
|
+
class _GeneratorCallableWrapper(_CallableWrapper):
|
|
517
|
+
def __call__(self, *args: Any, **kwargs: Any):
|
|
518
|
+
yield from self._original_callable(*args, **kwargs)
|
|
519
|
+
|
|
520
|
+
|
|
521
|
+
class _AsyncGeneratorCallableWrapper(_CallableWrapper):
|
|
522
|
+
async def __call__(self, *args: Any, **kwargs: Any):
|
|
523
|
+
async for value in self._original_callable(*args, **kwargs):
|
|
524
|
+
yield value
|
|
525
|
+
|
|
526
|
+
|
|
513
527
|
@final
|
|
514
528
|
class _AnnotationTransformer:
|
|
515
529
|
def __init__(self, generator: "SchemaGenerator") -> None:
|
|
@@ -690,8 +704,12 @@ class _AnnotationTransformer:
|
|
|
690
704
|
actual_call = call.__call__
|
|
691
705
|
else:
|
|
692
706
|
actual_call = call
|
|
693
|
-
if
|
|
707
|
+
if is_async_gen_callable(actual_call):
|
|
708
|
+
return _AsyncGeneratorCallableWrapper(call)
|
|
709
|
+
elif is_coroutine_callable(actual_call):
|
|
694
710
|
return _AsyncCallableWrapper(call)
|
|
711
|
+
elif is_gen_callable(actual_call):
|
|
712
|
+
return _GeneratorCallableWrapper(call)
|
|
695
713
|
else:
|
|
696
714
|
return _CallableWrapper(call)
|
|
697
715
|
|
|
@@ -23,7 +23,7 @@ from fastapi.routing import APIRoute, _prepare_response_content
|
|
|
23
23
|
from pydantic import BaseModel
|
|
24
24
|
from pydantic_core import PydanticUndefined
|
|
25
25
|
from starlette._utils import is_async_callable
|
|
26
|
-
from typing_extensions import Any, ParamSpec, TypeAlias, TypeVar, assert_never, deprecated, get_args
|
|
26
|
+
from typing_extensions import Any, Literal, ParamSpec, TypeAlias, TypeVar, assert_never, deprecated, get_args
|
|
27
27
|
|
|
28
28
|
from cadwyn._utils import classproperty
|
|
29
29
|
from cadwyn.exceptions import (
|
|
@@ -51,6 +51,11 @@ _CADWYN_REQUEST_PARAM_NAME = "cadwyn_request_param"
|
|
|
51
51
|
_CADWYN_RESPONSE_PARAM_NAME = "cadwyn_response_param"
|
|
52
52
|
_P = ParamSpec("_P")
|
|
53
53
|
_R = TypeVar("_R")
|
|
54
|
+
_CURRENT_DEPENDENCY_SOLVER_OPTIONS = Literal["cadwyn", "fastapi"]
|
|
55
|
+
_CURRENT_DEPENDENCY_SOLVER_VAR: ContextVar[_CURRENT_DEPENDENCY_SOLVER_OPTIONS] = ContextVar(
|
|
56
|
+
"cadwyn_dependencies_dry_run"
|
|
57
|
+
)
|
|
58
|
+
|
|
54
59
|
PossibleInstructions: TypeAlias = Union[
|
|
55
60
|
AlterSchemaSubInstruction, AlterEndpointSubInstruction, AlterEnumSubInstruction, SchemaHadInstruction, staticmethod
|
|
56
61
|
]
|
|
@@ -276,6 +281,7 @@ class VersionBundle:
|
|
|
276
281
|
|
|
277
282
|
if api_version_var is None:
|
|
278
283
|
api_version_var = ContextVar("cadwyn_api_version")
|
|
284
|
+
|
|
279
285
|
self.version_values = tuple(version.value for version in self.versions)
|
|
280
286
|
self.reversed_version_values = tuple(reversed(self.version_values))
|
|
281
287
|
self.api_version_var = api_version_var
|
|
@@ -379,6 +385,8 @@ class VersionBundle:
|
|
|
379
385
|
instruction(request_info)
|
|
380
386
|
request.scope["headers"] = tuple((key.encode(), value.encode()) for key, value in request_info.headers.items())
|
|
381
387
|
del request._headers
|
|
388
|
+
# This gives us the ability to tell the user whether cadwyn is running its dependencies or FastAPI
|
|
389
|
+
_CURRENT_DEPENDENCY_SOLVER_VAR.set("cadwyn")
|
|
382
390
|
# Remember this: if len(body_params) == 1, then route.body_schema == route.dependant.body_params[0]
|
|
383
391
|
result = await solve_dependencies(
|
|
384
392
|
request=request,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "cadwyn"
|
|
3
|
-
version = "5.1.
|
|
3
|
+
version = "5.1.2"
|
|
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"
|
|
@@ -87,6 +87,7 @@ dev-dependencies = [
|
|
|
87
87
|
"mike >=2.1.2, <3",
|
|
88
88
|
"pdbpp>=0.10.3",
|
|
89
89
|
"markdown-include-variants>=0.0.4",
|
|
90
|
+
"inline-snapshot>=0.20.7",
|
|
90
91
|
]
|
|
91
92
|
|
|
92
93
|
[project.urls]
|
|
@@ -97,6 +98,8 @@ Documentation = "https://docs.cadwyn.dev"
|
|
|
97
98
|
[project.scripts]
|
|
98
99
|
cadwyn = "cadwyn.__main__:app"
|
|
99
100
|
|
|
101
|
+
[tool.inline-snapshot]
|
|
102
|
+
format-command = "ruff format --stdin-filename {filename}"
|
|
100
103
|
|
|
101
104
|
[tool.coverage.run]
|
|
102
105
|
parallel = true
|
|
@@ -13,12 +13,14 @@ from fastapi.routing import APIRoute
|
|
|
13
13
|
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
|
|
14
14
|
from fastapi.security.http import HTTPBasic
|
|
15
15
|
from fastapi.testclient import TestClient
|
|
16
|
+
from inline_snapshot import snapshot
|
|
16
17
|
from pydantic import BaseModel
|
|
17
18
|
from pytest_fixture_classes import fixture_class
|
|
18
19
|
from starlette.responses import FileResponse
|
|
19
20
|
from typing_extensions import Any, NewType, TypeAlias, get_args
|
|
20
21
|
|
|
21
22
|
from cadwyn import VersionBundle, VersionedAPIRouter
|
|
23
|
+
from cadwyn.dependencies import current_dependency_solver
|
|
22
24
|
from cadwyn.exceptions import CadwynError, RouterGenerationError, RouterPathParamsModifiedError
|
|
23
25
|
from cadwyn.route_generation import generate_versioned_routers
|
|
24
26
|
from cadwyn.schema_generation import generate_versioned_models
|
|
@@ -1205,6 +1207,60 @@ def test__basic_router_generation__subclass_of_security_class_based_dependency_w
|
|
|
1205
1207
|
]
|
|
1206
1208
|
|
|
1207
1209
|
|
|
1210
|
+
def test__router_generation__with_generator_dependencies(
|
|
1211
|
+
router: VersionedAPIRouter,
|
|
1212
|
+
create_versioned_app: CreateVersionedApp,
|
|
1213
|
+
):
|
|
1214
|
+
dependency_cache = []
|
|
1215
|
+
|
|
1216
|
+
async def my_async_dependency(current_dependency_runner: Annotated[str, Depends(current_dependency_solver)]):
|
|
1217
|
+
dependency_cache.append(f"{current_dependency_runner} async dependency start")
|
|
1218
|
+
yield "async dependency"
|
|
1219
|
+
dependency_cache.append(f"{current_dependency_runner} async dependency end")
|
|
1220
|
+
|
|
1221
|
+
def my_sync_dependency(current_dependency_runner: Annotated[str, Depends(current_dependency_solver)]):
|
|
1222
|
+
dependency_cache.append(f"{current_dependency_runner} sync dependency start")
|
|
1223
|
+
yield "sync dependency"
|
|
1224
|
+
dependency_cache.append(f"{current_dependency_runner} sync dependency end")
|
|
1225
|
+
|
|
1226
|
+
@router.get("/test")
|
|
1227
|
+
async def test(
|
|
1228
|
+
my_async_dep: Annotated[str, Depends(my_async_dependency)],
|
|
1229
|
+
my_sync_dep: Annotated[str, Depends(my_sync_dependency)],
|
|
1230
|
+
):
|
|
1231
|
+
assert my_async_dep == "async dependency"
|
|
1232
|
+
assert my_sync_dep == "sync dependency"
|
|
1233
|
+
|
|
1234
|
+
client = TestClient(create_versioned_app(version_change()))
|
|
1235
|
+
assert client.get("/test", headers={"x-api-version": "2000-01-01"}).status_code == 200
|
|
1236
|
+
assert dependency_cache == snapshot(
|
|
1237
|
+
[
|
|
1238
|
+
"fastapi async dependency start",
|
|
1239
|
+
"fastapi sync dependency start",
|
|
1240
|
+
"cadwyn async dependency start",
|
|
1241
|
+
"cadwyn sync dependency start",
|
|
1242
|
+
"cadwyn sync dependency end",
|
|
1243
|
+
"cadwyn async dependency end",
|
|
1244
|
+
"fastapi sync dependency end",
|
|
1245
|
+
"fastapi async dependency end",
|
|
1246
|
+
]
|
|
1247
|
+
)
|
|
1248
|
+
dependency_cache.clear()
|
|
1249
|
+
assert client.get("/test", headers={"x-api-version": "2001-01-01"}).status_code == 200
|
|
1250
|
+
assert dependency_cache == snapshot(
|
|
1251
|
+
[
|
|
1252
|
+
"fastapi async dependency start",
|
|
1253
|
+
"fastapi sync dependency start",
|
|
1254
|
+
"cadwyn async dependency start",
|
|
1255
|
+
"cadwyn sync dependency start",
|
|
1256
|
+
"cadwyn sync dependency end",
|
|
1257
|
+
"cadwyn async dependency end",
|
|
1258
|
+
"fastapi sync dependency end",
|
|
1259
|
+
"fastapi async dependency end",
|
|
1260
|
+
]
|
|
1261
|
+
)
|
|
1262
|
+
|
|
1263
|
+
|
|
1208
1264
|
######################
|
|
1209
1265
|
# External lib testing
|
|
1210
1266
|
######################
|
|
@@ -94,7 +94,7 @@ wheels = [
|
|
|
94
94
|
|
|
95
95
|
[[package]]
|
|
96
96
|
name = "cadwyn"
|
|
97
|
-
version = "5.1.
|
|
97
|
+
version = "5.1.2"
|
|
98
98
|
source = { editable = "." }
|
|
99
99
|
dependencies = [
|
|
100
100
|
{ name = "backports-strenum", marker = "python_full_version < '3.11'" },
|
|
@@ -117,6 +117,7 @@ dev = [
|
|
|
117
117
|
{ name = "better-devtools" },
|
|
118
118
|
{ name = "dirty-equals" },
|
|
119
119
|
{ name = "httpx" },
|
|
120
|
+
{ name = "inline-snapshot" },
|
|
120
121
|
{ name = "markdown-include-variants" },
|
|
121
122
|
{ name = "mdx-include" },
|
|
122
123
|
{ name = "mike" },
|
|
@@ -153,6 +154,7 @@ dev = [
|
|
|
153
154
|
{ name = "better-devtools", specifier = "~=0.13.3" },
|
|
154
155
|
{ name = "dirty-equals", specifier = ">=0.6.0" },
|
|
155
156
|
{ name = "httpx", specifier = ">=0.26.0" },
|
|
157
|
+
{ name = "inline-snapshot", specifier = ">=0.20.7" },
|
|
156
158
|
{ name = "markdown-include-variants", specifier = ">=0.0.4" },
|
|
157
159
|
{ name = "mdx-include", specifier = "~=1.4.2" },
|
|
158
160
|
{ name = "mike", specifier = ">=2.1.2,<3" },
|
|
@@ -597,6 +599,21 @@ wheels = [
|
|
|
597
599
|
{ url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374", size = 5892 },
|
|
598
600
|
]
|
|
599
601
|
|
|
602
|
+
[[package]]
|
|
603
|
+
name = "inline-snapshot"
|
|
604
|
+
version = "0.20.7"
|
|
605
|
+
source = { registry = "https://pypi.org/simple" }
|
|
606
|
+
dependencies = [
|
|
607
|
+
{ name = "asttokens" },
|
|
608
|
+
{ name = "executing" },
|
|
609
|
+
{ name = "rich" },
|
|
610
|
+
{ name = "tomli", marker = "python_full_version < '3.11'" },
|
|
611
|
+
]
|
|
612
|
+
sdist = { url = "https://files.pythonhosted.org/packages/b0/41/9bd2ecd10ef789e8aff6fb68dcc7677dc31b33b2d27c306c0d40fc982fbc/inline_snapshot-0.20.7.tar.gz", hash = "sha256:d55bbb6254d0727dc304729ca7998cde1c1e984c4bf50281514aa9d727a56cf2", size = 92643 }
|
|
613
|
+
wheels = [
|
|
614
|
+
{ url = "https://files.pythonhosted.org/packages/01/8f/1bf23da63ad1a0b14ca2d9114700123ef76732e375548f4f9ca94052817e/inline_snapshot-0.20.7-py3-none-any.whl", hash = "sha256:2df6dd8710d1f0def2c1f9d6c25fd03d7beba01f3addf52fc370343d9ee9959f", size = 48108 },
|
|
615
|
+
]
|
|
616
|
+
|
|
600
617
|
[[package]]
|
|
601
618
|
name = "issubclass"
|
|
602
619
|
version = "0.1.2"
|
|
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-5.1.1 → cadwyn-5.1.2}/docs/concepts/where_to_put_the_version_and_how_to_format_it.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cadwyn-5.1.1 → cadwyn-5.1.2}/docs/how_to/change_openapi_schemas/change_schema_without_endpoint.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cadwyn-5.1.1 → cadwyn-5.1.2}/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
|
|
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-5.1.1 → cadwyn-5.1.2}/tests/test_schema_generation/test_schema_with_future_annotations.py
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
|