Skip to content

Fixed #37240 -- Fixed simplify_regex() with multiple unnamed groups. - #21698

Closed
SEPURI-SAI-KRISHNA wants to merge 1 commit into
django:mainfrom
SEPURI-SAI-KRISHNA:ticket_37240
Closed

Fixed #37240 -- Fixed simplify_regex() with multiple unnamed groups.#21698
SEPURI-SAI-KRISHNA wants to merge 1 commit into
django:mainfrom
SEPURI-SAI-KRISHNA:ticket_37240

Conversation

@SEPURI-SAI-KRISHNA

@SEPURI-SAI-KRISHNA SEPURI-SAI-KRISHNA commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Trac ticket number

ticket-37240

Branch description

simplify_regex() re-emits the whole pattern prefix once per capture group, so any re_path() containing two or more unnamed capture groups was rendered with a duplicated, malformed path.

>>> simplify_regex(r'^articles/(\w+)/comments/(\d+)/$')
'/articles/<var>/comments/articles/(\w)/comments/<var>/'   # expected '/articles/<var>/comments/<var>/'

The corruption compounds with each additional group — three unnamed groups produce /a/<var>/b/a/(\w)/b/<var>/c/a/(\w)/b/(\d)/c/<var>.

Both callers are affected: the admindocs "Views" page (ViewIndexView.get_context_data() passes simplify_regex(regex) straight into the url context value) and the listurls management command added in 6.2.

Cause. In replace_unnamed_groups(), the first iteration correctly emits pattern[:start] because prev_end is None. Every later iteration appends the text between the previous group and this one (correct) and then appends pattern[:start] again, duplicating the entire prefix from index 0:

if prev_end:
    final_pattern += pattern[prev_end:start]
final_pattern += pattern[:start] + "<var>"     # re-emits the prefix

The sibling remove_non_capturing_groups() in the same module already has the correct shape, relying on pattern[None:start] == pattern[:start] for the first iteration. This change collapses the three lines into the same idiom:

final_pattern += pattern[prev_end:start] + "<var>"

Why it went unnoticed. SimplifyRegexTests.test_simplify_regex has over 100 cases, but every one of them contains at most one unnamed group, so the second-iteration path was never executed. This patch adds six cases covering two and three unnamed groups, unnamed groups mixed with named ones, nested alternations, and escaped parentheses. All six fail before the fix.

Long-standing, not a regression. Verified by running the reproduction against released wheels:

Version Output for ^articles/(\w+)/comments/(\d+)/$
2.2.28 ^articles/<var>/comments/^articles/(\w+)/comments/<var>/$
4.2.16 /articles/<var>/comments/articles/(\w)/comments/<var>/
5.2.9 /articles/<var>/comments/articles/(\w)/comments/<var>/
6.0.7 /articles/<var>/comments/articles/(\w)/comments/<var>/
main /articles/<var>/comments/articles/(\w)/comments/<var>/

The 2.2 result confirms the defect predates both the move of these helpers to django/urls/utils.py in 6.2 and the changes made for #30731. A release note is included in docs/releases/6.0.8.txt since the fix qualifies for backport.

AI Assistance Disclosure (REQUIRED)

  • No AI tools were used in preparing this PR.
  • If AI tools were used, I have disclosed which ones, and fully reviewed and verified their output.

Claude Code (Claude Opus 5) was used to locate the bug, write the fix and the regression tests, and run the verification against released versions. I have reviewed and verified all of it myself.

Checklist

  • This PR follows the contribution guidelines.

  • This PR does not disclose a security vulnerability (see vulnerability reporting).

  • This PR targets the main branch.

  • The commit message is written in past tense, mentions the ticket number (if applicable), and ends with a period (see guidelines).

  • I have not requested, and will not request, an automated AI review for this PR.

  • I have checked the "Has patch" ticket flag in the Trac system.

  • I have added or updated relevant tests.

  • I have added or updated relevant docs, including release notes if applicable.

  • I have attached screenshots in both light and dark modes for any UI changes.

@github-actions github-actions Bot closed this Jul 30, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Hello! Thank you for your contribution 💪

As it's your first contribution be sure to check out the patch review checklist.

If you're fixing a ticket from Trac make sure to set the "Has patch" flag and include a link to this PR in the ticket!

If you have any design or process questions then you can ask in the Django forum.

Welcome aboard ⛵️!

@SEPURI-SAI-KRISHNA SEPURI-SAI-KRISHNA changed the title Fixed #37240 -- Fixed simplify_regex() with multiple unnamed groups Fixed #37240 -- Fixed simplify_regex() with multiple unnamed groups . Jul 30, 2026
@SEPURI-SAI-KRISHNA SEPURI-SAI-KRISHNA changed the title Fixed #37240 -- Fixed simplify_regex() with multiple unnamed groups . Fixed #37240 -- Fixed simplify_regex() with multiple unnamed groups. Jul 30, 2026
@github-actions

Copy link
Copy Markdown

Thank you for your contribution to Django! This pull request has one or more items that need attention before it can be accepted for review.

❗ Error: Trac Ticket Not Ready for a Pull Request

The referenced ticket ticket-37240 is not ready for a pull request. A ticket must be in the Accepted or Ready for checkin stage, assigned status, and have no resolution.

Current state: stage='Unreviewed'

What to do:

  1. Check the ticket at https://code.djangoproject.com/ticket/37240.
  2. If Unreviewed, wait for a community member to accept it. A ticket cannot be accepted by its reporter.
  3. If Someday/Maybe, discuss on the Django Forum before proceeding.
  4. If resolved or closed, it is not eligible for a PR.
  5. If not assigned, claim it by setting yourself as the owner.

For more information on the Django triage process see https://docs.djangoproject.com/en/dev/internals/contributing/triaging-tickets/.

If you have questions about these requirements, please review the contributing guidelines or ask for help on the Django Forum.

@SEPURI-SAI-KRISHNA

Copy link
Copy Markdown
Contributor Author

Superseded by #21700. This PR was auto-closed before review and could not be reopened after the commit was amended.

@sarahboyce sarahboyce 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.

This looks really good - thank you for the ticket and PR!
Can you remove the release note and make sure your commit message ends with a full stop and then reopen please? ⭐

Comment thread docs/releases/6.0.8.txt
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