Skip to content

Update version to 1.5.4.dev1 and enhance query parameter handling#185

Open
julietteceb16 wants to merge 4 commits into
mainfrom
feat/users-filter-by-ids-and-blocked
Open

Update version to 1.5.4.dev1 and enhance query parameter handling#185
julietteceb16 wants to merge 4 commits into
mainfrom
feat/users-filter-by-ids-and-blocked

Conversation

@julietteceb16
Copy link
Copy Markdown

@julietteceb16 julietteceb16 commented May 29, 2026

Summary by CodeRabbit

  • Bug Fixes

    • Pagination now preserves and correctly serializes repeated query parameters (e.g., multiple ids) across pages.
  • Refactor

    • Query-parameter parsing and validation consolidated into a shared utility for consistent behavior across REST endpoints.
  • Tests

    • Added coverage for repeated and scalar query parameters, validation rules, empty-query behavior, and pagination links (including a regression case).
  • Examples

    • Example query model now includes an optional ids list filter.
  • Chores

    • Version bumped to a new dev iteration.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 29, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f21a7321-cb02-44bb-89a9-f68a3c1bf731

📥 Commits

Reviewing files that changed from the base of the PR and between ce4e91c and b217854.

📒 Files selected for processing (1)
  • agave/version.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • agave/version.py

Walkthrough

Adds validate_query_params and EmptyQueryMapping for mapping HTTP query params into Pydantic models, uses them in Chalice and FastAPI GET handlers (falling back to EmptyQueryMapping), changes pagination encoding to urlencode(..., doseq=True), excludes ids from filter construction, adds an optional ids field to an example query model, expands unit tests for list-detection and mapping behavior (including a UnionType reload regression), adds integration tests for repeated ids and pagination preservation, and bumps version to 1.5.4.dev2.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Title check ⚠️ Warning The PR title mentions updating version to 1.5.4.dev1, but the actual change updates it to 1.5.4.dev2; the main focus is query parameter handling enhancements across multiple modules. Update the title to reflect the actual version change (1.5.4.dev2) or use a more accurate version-agnostic title like 'Enhance query parameter handling with validation utilities'.
Docstring Coverage ⚠️ Warning Docstring coverage is 17.86% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/users-filter-by-ids-and-blocked

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link
Copy Markdown

codecov Bot commented May 29, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (bd63e02) to head (b217854).

Additional details and impacted files
@@            Coverage Diff            @@
##              main      #185   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           19        20    +1     
  Lines          716       751   +35     
  Branches        75        79    +4     
=========================================
+ Hits           716       751   +35     
Flag Coverage Δ
unittests 100.00% <100.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
tests/core/test_query_params.py (2)

75-79: ⚡ Quick win

Add a regression test for the empty-query mapping path.

Please add a test that calls validate_query_params(EmptyQueryMapping(), SampleQuery) and asserts it does not raise and keeps all optional fields as None.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/core/test_query_params.py` around lines 75 - 79, Add a new regression
test that calls validate_query_params with an EmptyQueryMapping and SampleQuery
and asserts it does not raise and returns a mapping where all optional
SampleQuery fields are None; specifically, create a test function (e.g.,
test_validate_query_params_accepts_empty_mapping) that does: result =
validate_query_params(EmptyQueryMapping(), SampleQuery) and then asserts no
exception and that for each optional field defined on SampleQuery the result
mapping has a key with value None (use the same field names as in SampleQuery to
locate them).

48-53: ⚡ Quick win

Rename this test to match its behavior.

The current name says “rejects invalid list”, but it verifies successful normalization to ['a', 'b']. This is misleading during failure triage.

Suggested rename
-def test_validate_query_params_rejects_invalid_list() -> None:
+def test_validate_query_params_normalizes_list_fields() -> None:
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/core/test_query_params.py` around lines 48 - 53, Rename the test
function test_validate_query_params_rejects_invalid_list to a name that reflects
its behavior (it verifies normalization rather than rejection), e.g.
test_validate_query_params_normalizes_list_field or
test_validate_query_params_returns_list_for_multiple_values; update the function
definition and any references accordingly so the test still calls
QueryParams('ids=a&ids=b'), invokes validate_query_params(query, SampleQuery),
and asserts validated.ids == ['a', 'b'].
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@agave/core/query_params.py`:
- Around line 64-72: EmptyQueryMapping is missing iteration support required by
build_query_dict and the QueryParamMapping protocol; implement __iter__ to yield
no keys and __len__ to return 0 (and keep existing __contains__, get, getlist)
so EmptyQueryMapping behaves like an empty mapping when iterated by
build_query_dict, e.g., add an __iter__(self) -> Iterator[str] that yields
nothing and a __len__(self) -> int that returns 0 to satisfy consumers expecting
an iterable mapping.

In `@tests/blueprint/test_blueprint.py`:
- Around line 289-297: The test test_query_with_repeated_ids_param currently
only checks status and presence of 'items' but doesn't assert filtering; modify
it to parse resp.json(), extract the list under 'items', and assert that every
returned item's id is one of the requested ids ('US1' or 'US2') and that no
other ids are present (optionally assert the set of returned ids equals
{'US1','US2'} or that length matches expected). Use the existing
client.get('/accounts?ids=US1&ids=US2') response object (resp) and its
resp.json() to perform these assertions so the test fails if ids filtering is
ignored.

---

Nitpick comments:
In `@tests/core/test_query_params.py`:
- Around line 75-79: Add a new regression test that calls validate_query_params
with an EmptyQueryMapping and SampleQuery and asserts it does not raise and
returns a mapping where all optional SampleQuery fields are None; specifically,
create a test function (e.g., test_validate_query_params_accepts_empty_mapping)
that does: result = validate_query_params(EmptyQueryMapping(), SampleQuery) and
then asserts no exception and that for each optional field defined on
SampleQuery the result mapping has a key with value None (use the same field
names as in SampleQuery to locate them).
- Around line 48-53: Rename the test function
test_validate_query_params_rejects_invalid_list to a name that reflects its
behavior (it verifies normalization rather than rejection), e.g.
test_validate_query_params_normalizes_list_field or
test_validate_query_params_returns_list_for_multiple_values; update the function
definition and any references accordingly so the test still calls
QueryParams('ids=a&ids=b'), invokes validate_query_params(query, SampleQuery),
and asserts validated.ids == ['a', 'b'].
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4f0f809e-0417-47be-b8f1-e535d2006294

📥 Commits

Reviewing files that changed from the base of the PR and between bd63e02 and 6a81f13.

📒 Files selected for processing (8)
  • agave/chalice/rest_api.py
  • agave/core/filters.py
  • agave/core/query_params.py
  • agave/fastapi/rest_api.py
  • agave/version.py
  • examples/validators.py
  • tests/blueprint/test_blueprint.py
  • tests/core/test_query_params.py

Comment thread agave/core/query_params.py Outdated
Comment on lines +289 to +297
def test_query_with_repeated_ids_param(
client_fixture: str,
request: pytest.FixtureRequest,
) -> None:
client = request.getfixturevalue(client_fixture)
resp = client.get('/accounts?ids=US1&ids=US2')
assert resp.status_code == 200
assert 'items' in resp.json()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Test does not verify that ids filtering actually works.

At Line 294, this test sends repeated ids, but current assertions only check status and key existence, so it still passes if ids is ignored.

✅ Suggested test hardening
 `@pytest.mark.parametrize`(
     "client_fixture", ["fastapi_client", "chalice_client"]
 )
 `@pytest.mark.usefixtures`('accounts')
 def test_query_with_repeated_ids_param(
     client_fixture: str,
     request: pytest.FixtureRequest,
+    accounts: list[Account],
 ) -> None:
     client = request.getfixturevalue(client_fixture)
-    resp = client.get('/accounts?ids=US1&ids=US2')
+    account_ids = [accounts[0].id, accounts[1].id]
+    query = '&'.join(f'ids={account_id}' for account_id in account_ids)
+    resp = client.get(f'/accounts?{query}')
     assert resp.status_code == 200
-    assert 'items' in resp.json()
+    json_body = resp.json()
+    assert 'items' in json_body
+    returned_ids = {item['id'] for item in json_body['items']}
+    assert returned_ids == set(account_ids)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/blueprint/test_blueprint.py` around lines 289 - 297, The test
test_query_with_repeated_ids_param currently only checks status and presence of
'items' but doesn't assert filtering; modify it to parse resp.json(), extract
the list under 'items', and assert that every returned item's id is one of the
requested ids ('US1' or 'US2') and that no other ids are present (optionally
assert the set of returned ids equals {'US1','US2'} or that length matches
expected). Use the existing client.get('/accounts?ids=US1&ids=US2') response
object (resp) and its resp.json() to perform these assertions so the test fails
if ids filtering is ignored.

Comment on lines +7 to +14
try:
from types import UnionType
except ImportError: # Python < 3.10
UnionType = None # type: ignore[misc, assignment]

_UNION_ORIGINS: Tuple[Any, ...] = (
(Union, UnionType) if UnionType is not None else (Union,)
)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quitar soporte para <3.10 y dejar más simple el import

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants