Skip to content

feat: rename pytest.mark.parametrize parameters (#165)#167

Merged
bellini666 merged 5 commits into
masterfrom
feat/rename-parametrize-params
Jun 4, 2026
Merged

feat: rename pytest.mark.parametrize parameters (#165)#167
bellini666 merged 5 commits into
masterfrom
feat/rename-parametrize-params

Conversation

@bellini666
Copy link
Copy Markdown
Owner

Closes #165.

Renaming a parametrized parameter now updates the name in the @pytest.mark.parametrize(...) decorator string, the test signature, and the test body in one edit. The rename works from any of those three spots, matching what PyCharm does. There was no rename provider before this.

Scope and design

This server runs alongside a general Python LSP, so the design avoids stepping on it:

  • Only parametrize parameters are renamed. On a fixture or any other symbol, prepareRename/rename return nothing, so pyright/pylsp answers instead.
  • indirect=True parameters are skipped. They route to a fixture, and a local-only rename would quietly break the test.
  • The edit is self-contained (decorator string + signature + body), so it produces correct code when this server is the only one handling rename.

What it handles

All argname forms: a single name, a comma string ("a,b" and "a, b"), a list, a tuple, and the argnames= keyword. Stacked parametrize decorators work too. Attribute access (obj.foo), string literals, and keyword-arg names in the body are left alone since they aren't references to the parameter.

Body usages are collected with the generated rustpython-ast Visitor (enabled via the visitor feature) rather than a hand-rolled walk, so no node type slips through and leaves a stale reference.

Known gap: a nested scope inside the test body that shadows the parameter name will be over-collected. It doesn't happen in practice.

Tests

  • tests/test_decorators.rs: argname extraction for every form, asserting the ranges land on the identifier and not the quotes or whitespace.
  • tests/test_lsp.rs: rename across all forms and all three trigger sites, stacked decorators, plus the guards (indirect, fixture, invalid identifier, prepareRename).
  • tests/test_project/test_parametrize.py: sample file for the end-to-end scans.

Add an LSP rename provider for parametrized test parameters. Triggering
rename from the parametrize decorator string, the test signature parameter,
or a body usage rewrites all three together.

Handles every argname form (single, comma string, list, tuple, argnames=
keyword) and stacked decorators. Indirect (indirect=True) params and plain
fixtures are declined so a general Python language server handles them.
Copilot AI review requested due to automatic review settings June 4, 2026 17:35
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 4, 2026

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

OpenSSF Scorecard

PackageVersionScoreDetails
cargo/rustpython-ast >= 0.4.0, < 0.5.0 UnknownUnknown

Scanned Files

  • Cargo.toml

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 08219c8e63

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/providers/rename.rs Outdated
Comment thread src/fixtures/decorators.rs Outdated
@codecov
Copy link
Copy Markdown

codecov Bot commented Jun 4, 2026

Codecov Report

❌ Patch coverage is 92.83489% with 23 lines in your changes missing coverage. Please review.
✅ Project coverage is 81.95%. Comparing base (4d38e66) to head (9b5e360).
⚠️ Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
src/providers/rename.rs 93.44% 15 Missing ⚠️
src/fixtures/decorators.rs 90.80% 8 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #167      +/-   ##
==========================================
+ Coverage   80.99%   81.95%   +0.96%     
==========================================
  Files          28       29       +1     
  Lines        4363     4684     +321     
==========================================
+ Hits         3534     3839     +305     
- Misses        829      845      +16     

☔ 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.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Address review findings:

- Locate argname tokens from source text instead of assuming a single
  opening quote, so prefixed (r/b/u/f) and triple-quoted argname strings
  get correct ranges; reject non-identifier names (implicit concatenation)
  rather than emit a corrupting edit.
- Detect indirect params for keyword argnames=, list/tuple argnames, and
  positional indirect, so those are declined instead of locally renamed.
- Make body-usage collection scope-aware: nested function/lambda params and
  comprehension targets that shadow the name are no longer renamed, while
  enclosing-scope refs (defaults, annotations, first comprehension iterable,
  closures) still are.
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 12 out of 13 changed files in this pull request and generated 1 comment.

Comment thread src/providers/rename.rs Outdated
… rustpython-ast license

- Replace extract_word_at_position (char-index, end-exclusive) with a
  byte-offset, end-inclusive identifier lookup so rename resolves when the
  caret rests just past the parameter and on non-ASCII lines (Copilot).
- Add tests covering nested scopes (all comprehension forms, lambda, nested
  sync/async functions, *args/**kwargs, unpacking targets), closures and
  enclosing-scope refs (defaults, annotations, return annotation, comp ifs),
  caret-at-end, decline paths (module level, syntax error, unanalyzed file),
  and decorator argname/indirect edge cases.
- Exempt rustpython-ast from the dependency-review license check; it is MIT
  but GitHub's dependency graph reports it as unknown.
Apply review polish: skip non-whole-word matches in the position_of test
helper so a future fixture edit can't silently trigger on the wrong token,
assert a superset identifier (foobar) is left untouched, and note the
global/nonlocal scope gap in the collector doc comment.
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

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

Comment thread src/providers/rename.rs
Comment thread src/fixtures/decorators.rs
Address Copilot review:

- Select the innermost *parametrized* function containing the cursor, so a
  rename triggered from inside a nested closure that references the parameter
  resolves to the enclosing parametrized test and still rewrites the decorator
  string, instead of declining because the closure has no parametrize decorator.
- Make is_plain_identifier ASCII-only to match identifier_at and
  is_valid_python_identifier, so Unicode argnames are handled consistently
  (declined) rather than half-supported.
@bellini666 bellini666 merged commit d0af9fb into master Jun 4, 2026
20 checks passed
@bellini666 bellini666 deleted the feat/rename-parametrize-params branch June 4, 2026 21:31
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.

Support renaming on parametrizations

2 participants