Skip to content

Fix comment confusion bug in update_lib#7802

Merged
youknowone merged 3 commits into
RustPython:mainfrom
ShaharNaveh:comment-confusion-bug
May 9, 2026
Merged

Fix comment confusion bug in update_lib#7802
youknowone merged 3 commits into
RustPython:mainfrom
ShaharNaveh:comment-confusion-bug

Conversation

@ShaharNaveh

@ShaharNaveh ShaharNaveh commented May 9, 2026

Copy link
Copy Markdown
Contributor

Before this fix. the script would do:

@unittest.expectedSuccess  # TODO: RUSTPYTHON; The `expectedFailure` here is from CPython, so this test must fail
@unittest.expectedFailure  # TODO: RUSTPYTHON; The `expectedFailure` here is from CPython, so this test must fail
def test_bad_new(self):
  ...

Because the logic was: "search the current and the previous line for the comment, if you find it, take it".

Now we have a different logic

Summary by CodeRabbit

  • Bug Fixes

    • Improved extraction of patch comments so the correct patch reason is identified when multiple decorators are present, preventing misattribution.
  • Tests

    • Added a unit test that verifies patch extraction behavior with multiple decorators to prevent regressions.

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 9, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 242f84fd-a5e2-4bec-846d-952eff2fab30

📥 Commits

Reviewing files that changed from the base of the PR and between 6b9f9e3 and 4789717.

📒 Files selected for processing (2)
  • scripts/update_lib/patch_spec.py
  • scripts/update_lib/tests/test_patch_spec.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • scripts/update_lib/patch_spec.py
  • scripts/update_lib/tests/test_patch_spec.py

📝 Walkthrough

Walkthrough

This PR changes COMMENT reason extraction: the code compiles the COMMENT regex once, checks the decorator line first, then only the immediately preceding line if it starts with #. A unit test verifies behavior when multiple unittest decorators exist.

Changes

Patch Reason Extraction Logic

Layer / File(s) Summary
Core Extraction Logic
scripts/update_lib/patch_spec.py
PatchEntry.iter_patch_entries now uses a compiled COMMENT regex to search the decorator line first and then only the immediately preceding comment line (if it begins with #), replacing the prior short reverse-scan loop.
Test Coverage
scripts/update_lib/tests/test_patch_spec.py
Added test_comment_confusion which places an inline COMMENT on one of multiple unittest decorators and asserts extract_patches returns the single expected PatchSpec with reason="reason" and cond=None.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • RustPython/RustPython#7750: Modifies scripts/update_lib/patch_spec.py and touches UtMethod handling and decorator COMMENT extraction.

Suggested reviewers

  • fanninpm
  • youknowone

Poem

🐰 A rabbit parses decorators with glee,
Hops to the line where the COMMENT might be,
Checks the decorator first, then one line behind,
No more tangled loops to confuse its mind.
🥕✨ Reason found, it bounds merrily!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Fix comment confusion bug in update_lib' directly corresponds to the PR's main objective of fixing a comment-detection bug in the update_lib script. It is concise, specific, and accurately summarizes the primary change.
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 unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@github-actions

github-actions Bot commented May 9, 2026

Copy link
Copy Markdown
Contributor

📦 Library Dependencies

The following Lib/ modules were modified. Here are their dependencies:

[x] test: cpython/Lib/test/test_descr.py (TODO: 36)
[ ] test: cpython/Lib/test/test_descrtut.py (TODO: 3)

dependencies:

dependent tests: (no tests depend on descr)

Legend:

  • [+] path exists in CPython
  • [x] up-to-date, [ ] outdated

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 2

🧹 Nitpick comments (1)
scripts/update_lib/tests/test_patch_spec.py (1)

152-174: ⚡ Quick win

Consider adding edge case: both decorator line and previous line have comments.

The current test validates extraction when the comment is on the decorator line. Consider adding another test case to clarify expected behavior when both the decorator line AND the previous line contain COMMENT:

# TODO: RUSTPYTHON; reason1  
`@unittest.expectedFailure`  # TODO: RUSTPYTHON; reason2
def test_one(self):
    pass

Should this extract reason1 (previous line) or reason2 (inline)? This would help validate the fix proposed in the previous review comments and prevent regression.

Suggested additional test case
def test_comment_on_both_lines(self):
    """Test extraction precedence when comment appears on both decorator and previous line."""
    code = f"""
class TestFoo(unittest.TestCase):
    # {COMMENT}; previous line
    `@unittest.expectedFailure`  # {COMMENT}; inline
    def test_one(self):
        pass
    """
    
    patches = extract_patches(code)
    specs = patches["TestFoo"]["test_one"]
    self.assertEqual(len(specs), 1)
    
    # Verify which comment takes precedence (inline expected based on "check decorator first")
    self.assertIn("inline", specs[0].reason)
    self.assertNotIn("previous", specs[0].reason)
🤖 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 `@scripts/update_lib/tests/test_patch_spec.py` around lines 152 - 174, Add a
new unit test to cover the edge case where both the decorator line and the
previous line contain the marker comment to assert which comment wins; create a
test method (e.g., test_comment_on_both_lines) alongside test_comment_confusion
that builds a class with a commented previous line and an inline decorator
comment, calls extract_patches(code), inspects patches["TestFoo"]["test_one"],
and asserts there is exactly one PatchSpec and that its reason matches the
inline decorator comment (i.e., contains the inline text and not the
previous-line text) to enforce the "check decorator first" precedence
implemented by extract_patches.
🤖 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 `@scripts/update_lib/patch_spec.py`:
- Line 203: The code risks indexing out of bounds when dec_line == 0 because
prev_line = lines[dec_line - 1] will access lines[-1]; update the logic around
dec_line to defensively check bounds (e.g., if dec_line > 0 then set prev_line =
lines[dec_line - 1] else set prev_line to a safe default like "" or None) so
that the decorator-at-first-line case is handled without reading the last file
line; apply this change where prev_line and dec_line are used in patch_spec.py
to ensure safe access.
- Around line 193-211: The code currently assigns reason from the decorator line
then unconditionally re-checks the previous line which can overwrite it; update
the logic in the block that uses pattern, dec_line, reason and lines so the
previous-line search only runs if reason is still None and dec_line > 0 (i.e.,
use an elif/guard: only compute prev_line and run pattern.search(prev_line) when
reason is None and dec_line-1 is in bounds and
prev_line.strip().startswith("#")), and when a match is found set reason =
found.group() as before.

---

Nitpick comments:
In `@scripts/update_lib/tests/test_patch_spec.py`:
- Around line 152-174: Add a new unit test to cover the edge case where both the
decorator line and the previous line contain the marker comment to assert which
comment wins; create a test method (e.g., test_comment_on_both_lines) alongside
test_comment_confusion that builds a class with a commented previous line and an
inline decorator comment, calls extract_patches(code), inspects
patches["TestFoo"]["test_one"], and asserts there is exactly one PatchSpec and
that its reason matches the inline decorator comment (i.e., contains the inline
text and not the previous-line text) to enforce the "check decorator first"
precedence implemented by extract_patches.
🪄 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: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: b563e144-15cd-48b3-8f05-ee10a9d6f0ce

📥 Commits

Reviewing files that changed from the base of the PR and between e10a27b and 5e6ef4a.

⛔ Files ignored due to path filters (1)
  • Lib/test/test_descr.py is excluded by !Lib/**
📒 Files selected for processing (2)
  • scripts/update_lib/patch_spec.py
  • scripts/update_lib/tests/test_patch_spec.py

Comment thread scripts/update_lib/patch_spec.py
Comment thread scripts/update_lib/patch_spec.py Outdated

# Search the previous line of the decorator,
# only take the comment if the line starts with a `#`
prev_line = lines[dec_line - 1]

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.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Index out of bounds risk when dec_line == 0.

If a decorator somehow appears on line 1 of the file (lineno=1), then dec_line = 0 and lines[dec_line - 1] becomes lines[-1], which incorrectly accesses the last line of the file instead of checking bounds.

While unlikely in practice (decorators are inside class methods), defensive programming requires a bounds check.

Proposed fix (standalone)
-# Search the previous line of the decorator,
-# only take the comment if the line starts with a `#`
-prev_line = lines[dec_line - 1]
-if prev_line.strip().startswith("#") and (
-    found := pattern.search(prev_line)
-):
-    reason = found.group()
+# Search the previous line of the decorator,
+# only take the comment if the line starts with a `#`
+if dec_line > 0:
+    prev_line = lines[dec_line - 1]
+    if prev_line.strip().startswith("#") and (
+        found := pattern.search(prev_line)
+    ):
+        reason = found.group()

Note: This issue is also addressed in the previous comment's combined fix.

🤖 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 `@scripts/update_lib/patch_spec.py` at line 203, The code risks indexing out of
bounds when dec_line == 0 because prev_line = lines[dec_line - 1] will access
lines[-1]; update the logic around dec_line to defensively check bounds (e.g.,
if dec_line > 0 then set prev_line = lines[dec_line - 1] else set prev_line to a
safe default like "" or None) so that the decorator-at-first-line case is
handled without reading the last file line; apply this change where prev_line
and dec_line are used in patch_spec.py to ensure safe access.

@ShaharNaveh ShaharNaveh force-pushed the comment-confusion-bug branch from 5e6ef4a to 6b9f9e3 Compare May 9, 2026 09:26
@ShaharNaveh ShaharNaveh force-pushed the comment-confusion-bug branch from 6b9f9e3 to 4789717 Compare May 9, 2026 09:29
@youknowone youknowone merged commit 002fc11 into RustPython:main May 9, 2026
17 checks passed
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