Skip to content

[fix] Crash when parsing an empty arbitrary expression with extract_node #2736

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 12, 2025

Conversation

Pierre-Sassoulas
Copy link
Member

Type of Changes

Type
🐛 Bug fix

Description

To be fair I'm not exactly sure of what the transient function is. It seems internal. But the fix seems self evident.

# The name of the transient function that is used to
# wrap expressions to be extracted when calling
# extract_node.
_TRANSIENT_FUNCTION = "__"

astroid/astroid/builder.py

Lines 303 to 315 in 3636bc2

def _extract_expressions(node: nodes.NodeNG) -> Iterator[nodes.NodeNG]:
"""Find expressions in a call to _TRANSIENT_FUNCTION and extract them.
The function walks the AST recursively to search for expressions that
are wrapped into a call to _TRANSIENT_FUNCTION. If it finds such an
expression, it completely removes the function call node from the tree,
replacing it by the wrapped expression inside the parent.
:param node: An astroid node.
:type node: astroid.bases.NodeNG
:yields: The sequence of wrapped expressions on the modified tree
expression can be found.
"""

astroid/astroid/builder.py

Lines 324 to 328 in 3636bc2

# Search for node in all _astng_fields (the fields checked when
# get_children is called) of its parent. Some of those fields may
# be lists or tuples, in which case the elements need to be checked.
# When we find it, replace it by real_expr, so that the AST looks
# like no call to _TRANSIENT_FUNCTION ever took place.

Closes #2734

@Pierre-Sassoulas Pierre-Sassoulas added this to the 3.3.11 milestone May 12, 2025
@Pierre-Sassoulas Pierre-Sassoulas linked an issue May 12, 2025 that may be closed by this pull request
@Pierre-Sassoulas Pierre-Sassoulas changed the title [fix] Crash when parsing '__()' (the transient function without args) [fix] Crash when parsing __() (the transient function without args) May 12, 2025
DanielNoord
DanielNoord previously approved these changes May 12, 2025
Copy link
Collaborator

@DanielNoord DanielNoord left a comment

Choose a reason for hiding this comment

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

If CI approves I approve as well :)

@Pierre-Sassoulas
Copy link
Member Author

Do you understand the transient function though ? 😄

@DanielNoord
Copy link
Collaborator

See b8dc84f

It seems to be a very bespoke way to do extraction of nodes in extract_node.

Copy link

codecov bot commented May 12, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.21%. Comparing base (3636bc2) to head (e401578).
⚠️ Report is 58 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##             main    #2736   +/-   ##
=======================================
  Coverage   93.21%   93.21%           
=======================================
  Files          93       93           
  Lines       11072    11072           
=======================================
  Hits        10321    10321           
  Misses        751      751           
Flag Coverage Δ
linux 93.08% <ø> (ø)
pypy 93.21% <ø> (ø)
windows 93.19% <ø> (ø)

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

Files with missing lines Coverage Δ
astroid/builder.py 95.13% <ø> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@Pierre-Sassoulas
Copy link
Member Author

Ha, thank you, here's the doc:

     To extract arbitrary expressions, surround them with the fake
     function call __(...). After parsing, the surrounded expression
     will be returned and the whole AST (accessible via the returned
     node's parent attribute) will look like the function call was
     never there in the first place.

     Examples:

       >>> a = __(1)

       The const node will be extracted.

       >>> def x(d=__(foo.bar)): pass

       The node containing the default argument will be extracted.

       >>> def foo(a, b):
       >>>   return 0 < __(len(a)) < b

       The node containing the function call 'len' will be extracted.

    If no statements or expressions are selected, the last toplevel
    statement will be returned.
    If the selected statement is a discard statement, (i.e. an expression
    turned into a statement), the wrapped expression is returned instead.

I'm going to update the changelog then. Learned something today.

@DanielNoord
Copy link
Collaborator

I'm going to update the changelog then. Learned something today.

Don't we all when we look at astroid 😄

@Pierre-Sassoulas Pierre-Sassoulas changed the title [fix] Crash when parsing __() (the transient function without args) [fix] Crash when parsing an empty arbitrary exception with extract_node May 12, 2025
@Pierre-Sassoulas Pierre-Sassoulas changed the title [fix] Crash when parsing an empty arbitrary exception with extract_node [fix] Crash when parsing an empty arbitrary expression with extract_node May 12, 2025
@Pierre-Sassoulas
Copy link
Member Author

Yeah, great piece of software, feels awesome.

th-3533101758

@Pierre-Sassoulas Pierre-Sassoulas enabled auto-merge (squash) May 12, 2025 20:36
@Pierre-Sassoulas Pierre-Sassoulas merged commit 59f36e7 into main May 12, 2025
20 checks passed
@Pierre-Sassoulas Pierre-Sassoulas deleted the 2734-indexerror-when-calling-extract_node branch May 12, 2025 20:43
github-actions bot pushed a commit that referenced this pull request May 12, 2025
Pierre-Sassoulas added a commit that referenced this pull request May 12, 2025
…_node`` (#2736) (#2737)

Closes #2734

(cherry picked from commit 59f36e7)

Co-authored-by: Pierre Sassoulas <[email protected]>
Pierre-Sassoulas added a commit that referenced this pull request Jul 13, 2025
* [fix] Crash when parsing an empty arbitrary expression with ``extract_node`` (#2736) (#2737)

Closes #2734

(cherry picked from commit 59f36e7)

Co-authored-by: Pierre Sassoulas <[email protected]>

* [fix] Prevent crash on slice decorator for 'six' decorated function (#2738) (#2740)

Closes #2721

(cherry picked from commit 555a128)

Co-authored-by: Pierre Sassoulas <[email protected]>

* [Backport maintenance/3.3.x] Initial fixes for Python 3.14 (#2747) (#2748)

(cherry picked from commit 43111bb)

* Improve backport job permissions (#2750)

(cherry picked from commit fe5bb6c)

* Use custom Github App to authenticate backport job (#2751) (#2752)

(cherry picked from commit a6f8d6a)

Co-authored-by: Marc Mueller <[email protected]>

* Include subclasses of standard property classes as property decorators (#2735)

* Include subclasses of standard property types as property decorators

* Modify astroid.bases and tests.test_nodes to reflect that enum.property was added in Python 3.11, not 3.10

* Apply suggestions from code review

Co-authored-by: Pierre Sassoulas <[email protected]>

---------

Co-authored-by: Pierre Sassoulas <[email protected]>
(cherry picked from commit 30128b7)

* Bump astroid to 3.3.11, update changelog (#2777)

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Marc Mueller <[email protected]>
Co-authored-by: pylint-backport-bot[bot] <212256041+pylint-backport-bot[bot]@users.noreply.github.com>
Co-authored-by: Mitch Harding <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

IndexError when calling extract_node
2 participants