Skip to content

Improve PythonVersions cop to reject hardcoded pythonX.Y assignment - #23479

Open
iMichka wants to merge 1 commit into
mainfrom
pythonversionstyle
Open

Improve PythonVersions cop to reject hardcoded pythonX.Y assignment#23479
iMichka wants to merge 1 commit into
mainfrom
pythonversionstyle

Conversation

@iMichka

@iMichka iMichka commented Aug 9, 2026

Copy link
Copy Markdown
Member

Enforce dynamic Python version detection in formula code by flagging hardcoded pythonX.Y strings assigned to python and autocorrecting to Language::Python.major_minor_version with libexec/bin/python. Generalize detection using a shared Python version regex and update PythonVersions specs accordingly.


  • Have you followed our Contributing guidelines?
  • Have you checked for other open Pull Requests for the same change?
  • Have you explained what your changes do? Performance claims (e.g. "this is faster") must include Hyperfine benchmarks.
  • Have you explained why you'd like these changes included, not just what they do?
  • For bug fixes, have you given step-by-step brew commands to reproduce the bug?
  • Have you written new tests (excluding integration tests)? Here's an example.
  • Have you successfully run brew lgtm (style, typechecking and tests) locally?

  • I did not use AI/LLM to create this PR, or I disclosed the tool/model below and reviewed its output; I did not attribute commits to AI and will answer maintainer questions and review comments myself without AI/LLM.

Copilot AI lite review requested due to automatic review settings August 9, 2026 15:26
@iMichka

iMichka commented Aug 9, 2026

Copy link
Copy Markdown
Member Author

I'll open a pull request in core to fix this before this can be merged: let me know if you think this is a good addition

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 tightens Homebrew鈥檚 FormulaAudit/PythonVersions RuboCop cop to discourage hardcoding pythonX.Y into formula code by detecting python = "pythonX.Y" assignments and auto-correcting them to use Language::Python.major_minor_version (with libexec/"bin/python"), and it updates the cop鈥檚 spec coverage accordingly.

Changes:

  • Add a shared PYTHON_VERSION_REFERENCE_REGEX and reuse it for Python reference detection.
  • Add a new offense + autocorrect for hardcoded python = "pythonX.Y" assignments.
  • Extend python_versions_spec.rb with new examples covering the new offense and correction.

Reviewed changes

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

File Description
Library/Homebrew/rubocops/lines.rb Adds shared regex and new Python local-assignment offense with autocorrect.
Library/Homebrew/test/rubocops/text/python_versions_spec.rb Adds new specs for the hardcoded assignment offense and dynamic-assignment non-offense.

馃挕 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

Comment thread Library/Homebrew/rubocops/lines.rb
Comment thread Library/Homebrew/test/rubocops/text/python_versions_spec.rb
@iMichka
iMichka force-pushed the pythonversionstyle branch 2 times, most recently from a6d3c96 to f682844 Compare August 9, 2026 15:33

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

Makes sense to me although a slightly shorter-hand version might be nicer?

Comment thread Library/Homebrew/test/rubocops/text/python_versions_spec.rb Outdated
depends_on "python@3.14"

def install
python3 = "python#{Language::Python.major_minor_version libexec/"bin/python"}"

@cho-m cho-m Aug 9, 2026

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.

I don't think libexec path exists? Maybe if using Formula["python@3.14"].opt_libexec but that requires hardcoding formula name. Otherwise would only work if virtualenv was created.

Also note that Language::Python.major_minor_version can output strange results if you don't guarantee the command passed is real, e.g.

brew(main):001> p Language::Python.major_minor_version("not-python-99.100")
#<Version 9.100>
=> #<Version 9.100>
brew(main):002> p Language::Python.major_minor_version("/foo/bar/1.2.3/python")
#<Version 1.2>
=> #<Version 1.2>

We currently allow parsing version from error message which may look like command not found: not-python-99.100.


For dynamic detection, most common way is to find dependency first, e.g.

It may also be possible to use sanitized environment, e.g. which("python3") or which("python"), but this could be wrong when multiple pythons are in dependency tree. We do not prioritize direct Python and instead order on versions, which means a depends_on "python@3.13" with indirect python@3.14 will lead to wrong python.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Also note that Language::Python.major_minor_version can output strange results if you don't guarantee the command passed is real, e.g.

I'm aware of that. In general people have just copy-pasted the right thing, so only the "happy path" has been used and we did not have to safeguard against wrongly formatted output yet. Not sure this is worth checking, given this syntax has been in place without issues for a very long time now.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I'm checking the best way to handle the libexec issue, you are right that this is not always correct

Enforce dynamic Python version detection in formula code by flagging hardcoded pythonX.Y strings assigned to python and autocorrecting to Language::Python.major_minor_version with libexec/bin/python.
Generalize detection using a shared Python version regex and update PythonVersions specs accordingly.
@iMichka
iMichka force-pushed the pythonversionstyle branch from f682844 to 55d4c3f Compare August 10, 2026 19:34
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.

5 participants