From c4e9195c76938a7f54c9b796af3959bb879198be Mon Sep 17 00:00:00 2001 From: d3vyce Date: Tue, 20 Oct 2026 14:04:53 -0400 Subject: [PATCH 1/2] fix: support FastAPI 0.155 request parameter changes --- src/fastapi_toolsets/crud/factory.py | 13 ++++++++++--- tests/test_crud_search.py | 24 ++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/src/fastapi_toolsets/crud/factory.py b/src/fastapi_toolsets/crud/factory.py index 404a513..bc6b908 100644 --- a/src/fastapi_toolsets/crud/factory.py +++ b/src/fastapi_toolsets/crud/factory.py @@ -114,6 +114,12 @@ def _decode_cursor(cursor: str) -> tuple[str, list[str] | None, _CursorDirection def _page_size_query(default: int, max_size: int) -> int: """Return a FastAPI ``Query`` for the ``items_per_page`` parameter.""" + # FastAPI >= 0.148 no longer validates defaults, so ge/le would not catch this. + if not 1 <= default <= max_size: + raise ValueError( + f"default_page_size must be between 1 and max_page_size ({max_size}), " + f"got {default}" + ) return Query( default, ge=1, @@ -683,7 +689,7 @@ def _build_paginate_params( default=Query( default=None, description="Restrict search to a single column", - enum=search_keys, + json_schema_extra={"enum": search_keys}, ), ), ] @@ -729,7 +735,7 @@ def _build_paginate_params( default=Query( None, description=f"Field to order by. Valid values: {order_valid_keys}", - enum=order_valid_keys, + json_schema_extra={"enum": order_valid_keys}, ), ), inspect.Parameter( @@ -982,7 +988,8 @@ def paginate_params( inspect.Parameter.KEYWORD_ONLY, annotation=PaginationType, default=Query( - default_pagination_type, description="Pagination strategy" + PaginationType(default_pagination_type), + description="Pagination strategy", ), ), inspect.Parameter( diff --git a/tests/test_crud_search.py b/tests/test_crud_search.py index 5fecab6..ea17f2a 100644 --- a/tests/test_crud_search.py +++ b/tests/test_crud_search.py @@ -1715,6 +1715,30 @@ def test_each_dependency_exposes_its_pagination_params(self, factory, fixed, nam assert size.default == 42 assert next(m.le for m in size.metadata if hasattr(m, "le")) == 50 + @pytest.mark.parametrize( + "factory", + ["offset_paginate_params", "cursor_paginate_params", "paginate_params"], + ) + @pytest.mark.parametrize("default_page_size", [0, 51]) + def test_default_page_size_outside_bounds_is_rejected( + self, factory, default_page_size + ): + with pytest.raises(ValueError, match="default_page_size"): + getattr(RoleCursorCrud, factory)( + default_page_size=default_page_size, max_page_size=50 + ) + + def test_default_pagination_type_is_coerced_to_the_enum(self): + dep = RoleCursorCrud.paginate_params( + default_pagination_type="cursor", # ty:ignore[invalid-argument-type] + search=False, + filter=False, + order=False, + ) + default = inspect.signature(dep).parameters["pagination_type"].default + + assert default.default is PaginationType.CURSOR + @pytest.mark.anyio async def test_fixed_options_are_forwarded_not_exposed(self): offset = RoleCrud.offset_paginate_params( From de3c944f1db8e1ec38ae3fd3da39a99e4cf36a21 Mon Sep 17 00:00:00 2001 From: d3vyce Date: Tue, 20 Oct 2026 14:04:54 -0400 Subject: [PATCH 2/2] fix: lock FastAPI 0.156.0 --- uv.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/uv.lock b/uv.lock index 1864e9d..efeacec 100644 --- a/uv.lock +++ b/uv.lock @@ -333,7 +333,7 @@ wheels = [ [[package]] name = "fastapi" -version = "0.143.0" +version = "0.156.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "annotated-doc" }, @@ -343,9 +343,9 @@ dependencies = [ { name = "typing-extensions" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/0b/d7/6a8753ab6c1d432dc53703c3e1b92974a94531b7d047c32bbaae461ea844/fastapi-0.143.0.tar.gz", hash = "sha256:1acffe48206a80917cf7dac21992b5c44b25384e8902bf745c1fd9dabcf6c51f", size = 468391, upload-time = "2026-10-08T12:29:46.54Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ea/e6/0a20e411ef7672fcd6c43bae391f0979fb64e5c91fe31820e052c8d626fa/fastapi-0.156.0.tar.gz", hash = "sha256:f522582abed9988b8503a478c30999dbd622f2c6ebbfd895864cb5dd20be53ed", size = 492339, upload-time = "2026-10-20T17:31:52.578Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/bd/f4/27e386913417ad32aae42bba48b0c0cce40e9ff2fba1a871ca2702c37324/fastapi-0.143.0-py3-none-any.whl", hash = "sha256:3e9395fd35276425b61b516a31fdd7c77fe2af83e41b4da22e30696fb1304c5d", size = 144665, upload-time = "2026-10-08T12:29:44.853Z" }, + { url = "https://files.pythonhosted.org/packages/3e/e4/b54f176c7baa88329be30c50cc2a118491168d6692a53fe3a588315b144b/fastapi-0.156.0-py3-none-any.whl", hash = "sha256:bc96f668b0aa423969e56fe21833d0b33a6d40b84d6094e8b12627e44564eb37", size = 146704, upload-time = "2026-10-20T17:31:50.973Z" }, ] [[package]]