Skip to content

fix(urls): preserve repeated query parameters#40877

Open
EricAraujoBsB wants to merge 4 commits into
apache:masterfrom
PedroHhenriq:fix/modify-url-query-repeated-params
Open

fix(urls): preserve repeated query parameters#40877
EricAraujoBsB wants to merge 4 commits into
apache:masterfrom
PedroHhenriq:fix/modify-url-query-repeated-params

Conversation

@EricAraujoBsB

@EricAraujoBsB EricAraujoBsB commented Jun 9, 2026

Copy link
Copy Markdown

Preserve Repeated Query Parameters

SUMMARY

This PR fixes modify_url_query so repeated query parameters are preserved when
updating or adding URL parameters.

Previously, modify_url_query parsed query parameters into lists using
parse_qs, but rebuilt the query string manually by taking only the first value
of each parameter. As a result, URLs containing repeated parameters such as:

/explore/?filter=a&filter=b

could be incorrectly serialized, after adding another parameter, as:

/explore/?filter=a&standalone=1

This change replaces the manual query string serialization with
urllib.parse.urlencode(..., doseq=True), allowing multiple values for the same
query parameter to be correctly expanded and preserved.

The implementation keeps the existing URL encoding behavior by using
quote_via=urllib.parse.quote and safe="/", ensuring spaces are encoded as
%20 and path-like values containing / remain readable.

Additional unit tests were added to cover:

  • preserving repeated query parameters already present in the URL;
  • adding list values as repeated query parameters.

Existing tests continue to cover scalar query parameter replacement.

TESTING INSTRUCTIONS

Run:

python -m pytest -q tests/unit_tests/utils/urls_tests.py

Or run only the tests related to this change:

python -m pytest -q \
  tests/unit_tests/utils/urls_tests.py::test_modify_url_query_preserves_repeated_existing_parameters \
  tests/unit_tests/utils/urls_tests.py::test_modify_url_query_adds_list_values_as_repeated_parameters

ADDITIONAL INFORMATION

  • Has associated issue:
  • Required feature flags:
  • Changes UI
  • Includes DB Migration (follow approval process in SIP-59)
    • Migration is atomic, supports rollback & is backwards-compatible
    • Confirm DB migration upgrade and downgrade tested
    • Runtime estimates and downtime expectations provided
  • Introduces new feature or API
  • Removes existing feature or API

@bito-code-review

bito-code-review Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Code Review Agent Run #418e36

Actionable Suggestions - 0
Review Details
  • Files reviewed - 2 · Commit Range: f148b2f..d94d0f3
    • superset/utils/urls.py
    • tests/unit_tests/utils/urls_tests.py
  • Files skipped - 0
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers a full AI review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

@netlify

netlify Bot commented Jun 9, 2026

Copy link
Copy Markdown

Deploy Preview for superset-docs-preview ready!

Name Link
🔨 Latest commit d94d0f3
🔍 Latest deploy log https://app.netlify.com/projects/superset-docs-preview/deploys/6a27713418a9ac00082d7dd3
😎 Deploy Preview https://deploy-preview-40877--superset-docs-preview.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@codecov

codecov Bot commented Jun 9, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 64.13%. Comparing base (21189ae) to head (d94d0f3).
⚠️ Report is 29 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master   #40877      +/-   ##
==========================================
- Coverage   64.14%   64.13%   -0.02%     
==========================================
  Files        2652     2652              
  Lines      143488   143561      +73     
  Branches    33110    33123      +13     
==========================================
+ Hits        92042    92071      +29     
- Misses      49837    49876      +39     
- Partials     1609     1614       +5     
Flag Coverage Δ
hive 39.51% <0.00%> (-0.02%) ⬇️
mysql 58.25% <100.00%> (-0.03%) ⬇️
postgres 58.31% <100.00%> (-0.03%) ⬇️
presto 41.10% <0.00%> (-0.02%) ⬇️
python 59.79% <100.00%> (-0.03%) ⬇️
sqlite 57.94% <100.00%> (-0.02%) ⬇️
unit 100.00% <ø> (ø)

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

☔ View full report in Codecov by Harness.
📢 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.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@sadpandajoe

Copy link
Copy Markdown
Member

Superset uses Git pre-commit hooks courtesy of pre-commit. To install run the following:

pip3 install -r requirements/development.txt
pre-commit install

A series of checks will now run when you make a git commit.

Alternatively it is possible to run pre-commit by running pre-commit manually:

pre-commit run --all-files

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes superset.utils.urls.modify_url_query to correctly preserve repeated query parameters when updating/adding URL query args, aligning URL serialization behavior with how Superset URLs can legitimately encode multi-valued parameters.

Changes:

  • Replace manual query-string rebuilding (which collapsed repeated params) with urllib.parse.urlencode(..., doseq=True).
  • Preserve existing encoding behavior by using quote_via=urllib.parse.quote (spaces as %20) and safe="/".
  • Add unit tests covering (1) preserving existing repeated parameters and (2) adding list values as repeated parameters.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
superset/utils/urls.py Switch query serialization to urlencode(..., doseq=True) to keep repeated parameters.
tests/unit_tests/utils/urls_tests.py Add coverage for repeated existing params and list-valued params becoming repeated query args.

@eschutho eschutho left a comment

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.

Summary

modify_url_query previously rebuilt the query string by taking only the first value (v[0]) from each parameter list, silently dropping all but the first value of repeated parameters like filter=a&filter=b. This PR replaces that manual serialization with urllib.parse.urlencode(..., doseq=True), which correctly expands multi-value lists into repeated key=value pairs. The quote_via=urllib.parse.quote, safe="/" arguments preserve the existing encoding behavior (spaces as %20, slashes unencoded). Two new unit tests cover the fixed behavior, and all callers in the codebase pass scalar kwargs so there's no backward-compatibility risk.

Findings

LOW

Docstring doesn't mention list-kwarg behavior (superset/utils/urls.py:53-55) — the fix makes passing a list a meaningful, supported input, but the docstring still just says "Replace or add parameters to a URL." WDYT about a one-liner addition like "Passing a list value produces repeated parameters (e.g., tag=['a','b']tag=a&tag=b)."? Would make the contract discoverable without reading the implementation.

Missing test for overwriting a multi-value param with a scalar — the existing tests cover overwriting a scalar param with another scalar; the new tests cover preserving and adding multi-value params. A case like modify_url_query("?filter=a&filter=b", filter="c")?filter=c would round out coverage and document the intent that kwargs replace rather than append. Totally optional since the behavior is obvious from params[k] = v, but could be handy for future readers.

LOW / NIT

Implicit string concatenation in test assertion (tests/unit_tests/utils/urls_tests.py:60-63) — the last test joins the expected string across two lines via implicit concatenation:

assert (
    test_url
    == "http://localhost:9000/explore/?existing=ok"
    "&tag=alpha%20value&tag=beta/value"
)

Not wrong at all, but could we put it on a single line (or use an explicit +) to stay consistent with the other test assertions in the file?

Overall

Approve — clean, well-scoped fix using the right stdlib tool; encoding behavior is preserved, all existing tests pass, and the new cases directly cover the reported bug.

@johan-rocha johan-rocha force-pushed the fix/modify-url-query-repeated-params branch from d94d0f3 to f93b46d Compare June 10, 2026 00:47
@pull-request-size pull-request-size Bot added size/S and removed size/M labels Jun 10, 2026
@bito-code-review

bito-code-review Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Code Review Agent Run #be50b9

Actionable Suggestions - 0
Review Details
  • Files reviewed - 2 · Commit Range: f148b2f..f93b46d
    • superset/utils/urls.py
    • tests/unit_tests/utils/urls_tests.py
  • Files skipped - 0
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers a full AI review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants