This is an automated email from the ASF dual-hosted git repository.

arm pushed a commit to branch arm
in repository https://gitbox.apache.org/repos/asf/tooling-trusted-releases.git


The following commit(s) were added to refs/heads/arm by this push:
     new 2e6c48b8 #1000 - make sure optional parameters get validated
2e6c48b8 is described below

commit 2e6c48b8a58b8b4dfbe7cd9d60d05df6d4bd9454
Author: Alastair McFarlane <[email protected]>
AuthorDate: Tue Apr 7 15:12:06 2026 +0100

    #1000 - make sure optional parameters get validated
---
 atr/blueprints/common.py      |  7 ++++--
 tests/unit/test_blueprints.py | 50 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 55 insertions(+), 2 deletions(-)

diff --git a/atr/blueprints/common.py b/atr/blueprints/common.py
index 704c906f..25a2a41d 100644
--- a/atr/blueprints/common.py
+++ b/atr/blueprints/common.py
@@ -167,7 +167,8 @@ def build_api_path(
         if is_optional:
             segments.append(_param_to_segment(param_name, inner, 
func.__name__))
             optional_params.append(param_name)
-            # Note - this means that safe types which are optional will not 
get validated - no current use case for this
+            if inner in VALIDATED_TYPES:
+                validated_params.append((param_name, inner))
             continue
 
         _classify_url_param(param_name, hint, func.__name__, segments, 
validated_params, literal_params)
@@ -202,7 +203,9 @@ def safe_params_for_type(cls: type) -> list[tuple[str, 
type]]:
 async def validate_params(kwargs: dict[str, Any], known_params: 
list[tuple[str, type]]) -> None:
     """Validate URL parameters in order, using the type-specific validators."""
     for param_name, param_type in known_params:
-        raw = kwargs[param_name]
+        raw = kwargs.get(param_name)
+        if raw is None:
+            continue
         if param_type is unsafe.UnsafeStr:
             kwargs[param_name] = unsafe.UnsafeStr(raw)
         elif issubclass(param_type, safe.SafeType):
diff --git a/tests/unit/test_blueprints.py b/tests/unit/test_blueprints.py
index d1bd31ac..84a75396 100644
--- a/tests/unit/test_blueprints.py
+++ b/tests/unit/test_blueprints.py
@@ -114,6 +114,33 @@ def test_build_api_path_optional_param():
     assert optional == ["_category"]
 
 
+def test_build_api_path_optional_safe_type_included_in_validated():
+    async def route(
+        _session: web.Committer,
+        _page: Literal["project"],
+        _project_key: safe.ProjectKey | None = None,
+    ) -> str:
+        return ""
+
+    path, validated, _, _, _, _, optional = common.build_api_path(route)
+    assert path == "/project/<_project_key>"
+    assert optional == ["_project_key"]
+    assert ("_project_key", safe.ProjectKey) in validated
+
+
+def test_build_api_path_optional_non_safe_type_not_in_validated():
+    async def route(
+        _session: web.Committer,
+        _page: Literal["items"],
+        _category: str | None = None,
+    ) -> str:
+        return ""
+
+    _, validated, _, _, _, _, optional = common.build_api_path(route)
+    assert optional == ["_category"]
+    assert all(name != "_category" for name, _ in validated)
+
+
 def test_build_api_path_query_param():
     @dataclasses.dataclass
     class Filters:
@@ -300,3 +327,26 @@ def test_setup_wrapper_sets_metadata():
     assert wrapper.__name__ == "index"
     assert wrapper.__doc__ == "Doc string."
     assert wrapper.__annotations__["endpoint"] == 
"get_blueprint.atr_get_dashboard_index"
+
+
[email protected]
+async def test_validate_params_skips_absent_optional():
+    kwargs: dict = {}
+    await common.validate_params(kwargs, [("project_key", safe.ProjectKey)])
+    assert "project_key" not in kwargs
+
+
[email protected]
+async def test_validate_params_validates_present_optional():
+    kwargs: dict = {"project_key": "myproject"}
+    await common.validate_params(kwargs, [("project_key", safe.ProjectKey)])
+    assert isinstance(kwargs["project_key"], safe.ProjectKey)
+
+
[email protected]
+async def test_validate_params_raises_on_invalid_optional():
+    import asfquart.base as base
+
+    kwargs: dict = {"project_key": "INVALID KEY WITH SPACES"}
+    with pytest.raises(base.ASFQuartException):
+        await common.validate_params(kwargs, [("project_key", 
safe.ProjectKey)])


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to