Skip to content

Conversation

@cdce8p
Copy link
Member

@cdce8p cdce8p commented Aug 6, 2025

Description

Add the basic buildings blocks for ast.TemplateStr and ast.Interpolation nodes. Most of it is pretty similar to the f-string nodes.

The implementation isn't complete but good enough to not outright fail if a t-string is used anywhere in a file. Future PRs should look to address the following

  • Additional tests for the as_string() logic. The basics work but there might be a lot of edge case which need to be handled properly. The existing f-string tests could provide a good starting point.

    astroid/tests/test_nodes.py

    Lines 295 to 307 in f9e109e

    def test_f_strings(self):
    code = r'''
    a = f"{'a'}"
    b = f'{{b}}'
    c = f""" "{'c'}" """
    d = f'{d!r} {d!s} {d!a}'
    e = f'{e:.3}'
    f = f'{f:{x}.{y}}'
    n = f'\n'
    everything = f""" " \' \r \t \\ {{ }} {'x' + x!r:a} {["'"]!s:{a}}"""
    '''
    ast = abuilder.string_build(code)
    self.assertEqual(ast.as_string().strip(), code.strip())
  • Add proper inference similar to JoinedStr._infer.
    def _infer(
    self, context: InferenceContext | None = None, **kwargs: Any
    ) -> Generator[InferenceResult, None, InferenceErrorInfo | None]:
    if self.values:
    yield from self._infer_with_values(context)
    else:
    yield Const("")

--
https://docs.python.org/3.14/library/ast.html#ast.TemplateStr
Ref #2789

Copy link
Member

@Pierre-Sassoulas Pierre-Sassoulas left a comment

Choose a reason for hiding this comment

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

Great ! And +1 for basic support now rather than perfect support too late for 3.14 release

@Pierre-Sassoulas Pierre-Sassoulas modified the milestones: 4.0.0, 4.0.0b1 Aug 6, 2025
self,
*,
value: NodeNG,
str: str, # pylint: disable=redefined-builtin
Copy link
Member Author

Choose a reason for hiding this comment

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

@Pierre-Sassoulas Should we change the attribute name here? str is the one used by the ast node but it's a bit unfortunate in my opinion since it shadows the builtin str.

Not sure using an alias here would be better though.

https://docs.python.org/3.14/library/ast.html#ast.Interpolation

Copy link
Member

Choose a reason for hiding this comment

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

I agree, not ideal, but what should we use instead ? Any non adherence to ast's API is mental load on astroid's user and documentation burden on us.

Copy link
Member Author

Choose a reason for hiding this comment

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

Just wanted to discuss it first. I also think that str while not ideal is still the best option.

Copy link
Member

Choose a reason for hiding this comment

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

Before you merged I was writing: Let's wait to read other opinions. Some maintainers might still be ambitious enough to keep astroid a wrapper above the AST and its multiple interpreters :D

It's still possible to change this later if someone want, we're in alpha/betas atm. Being able to test this in pylint fast is good too.

Copy link
Member Author

Choose a reason for hiding this comment

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

Sorry about that. Guess I was too fast this time 😅

Yeah, we can still change it. Furthermore I think the biggest issue is actually in the postinit arg name as that's used on it's own. Accessing the attribute itself shouldn't really be an issue with node.str.

@codecov
Copy link

codecov bot commented Aug 6, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.29%. Comparing base (f9e109e) to head (6a17f53).
⚠️ Report is 97 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #2793      +/-   ##
==========================================
+ Coverage   93.26%   93.29%   +0.03%     
==========================================
  Files          91       91              
  Lines       11009    11068      +59     
==========================================
+ Hits        10267    10326      +59     
  Misses        742      742              
Flag Coverage Δ
linux 93.16% <100.00%> (+0.03%) ⬆️
pypy 93.29% <100.00%> (+0.03%) ⬆️
windows 93.27% <100.00%> (+0.03%) ⬆️

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

Files with missing lines Coverage Δ
astroid/__init__.py 100.00% <ø> (ø)
astroid/nodes/__init__.py 100.00% <ø> (ø)
astroid/nodes/as_string.py 96.94% <100.00%> (+0.15%) ⬆️
astroid/nodes/node_classes.py 94.96% <100.00%> (+0.07%) ⬆️
astroid/rebuilder.py 98.21% <100.00%> (+0.03%) ⬆️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@cdce8p cdce8p merged commit b3c72a0 into pylint-dev:main Aug 6, 2025
19 checks passed
@cdce8p cdce8p deleted the template-str branch August 6, 2025 12:31
@Pierre-Sassoulas
Copy link
Member

Do you want me to release an astroid beta ?

@cdce8p
Copy link
Member Author

cdce8p commented Aug 6, 2025

Do you want me to release an astroid beta ?

I still need to debug at least one astroid issue for 3.14. Might make sense to wait a bit.

@cdce8p
Copy link
Member Author

cdce8p commented Aug 6, 2025

Do you want me to release an astroid beta ?

I still need to debug at least one astroid issue for 3.14. Might make sense to wait a bit.

Looks like what I was seeing is an existing issue with astroid not being able to infer sys.version_info properly.
Even found an old issue for it #113. Maybe that's something I'll look into at some point.

Feel free to do a new beta release if you've some time.

@Pierre-Sassoulas
Copy link
Member

I can't find the conversation about it but I remember saying somewhere that this kind of call should be uninferable (you don't know at static analysis time what is the value for the interpreter or the os, or...). If we want to do better, we would need to use a different constant for each, maybe we can discuss this in 113.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ast Enhancement ✨ Improvement to a component python 3.14

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants