brain_fstrings.py 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
  2. # For details: https://github.com/PyCQA/astroid/blob/main/LICENSE
  3. # Copyright (c) https://github.com/PyCQA/astroid/blob/main/CONTRIBUTORS.txt
  4. from __future__ import annotations
  5. import collections.abc
  6. from typing import TypeVar
  7. from astroid import nodes
  8. from astroid.manager import AstroidManager
  9. _NodeT = TypeVar("_NodeT", bound=nodes.NodeNG)
  10. def _clone_node_with_lineno(
  11. node: _NodeT, parent: nodes.NodeNG, lineno: int | None
  12. ) -> _NodeT:
  13. cls = node.__class__
  14. other_fields = node._other_fields
  15. _astroid_fields = node._astroid_fields
  16. init_params = {"lineno": lineno, "col_offset": node.col_offset, "parent": parent}
  17. postinit_params = {param: getattr(node, param) for param in _astroid_fields}
  18. if other_fields:
  19. init_params.update({param: getattr(node, param) for param in other_fields})
  20. new_node = cls(**init_params)
  21. if hasattr(node, "postinit") and _astroid_fields:
  22. for param, child in postinit_params.items():
  23. if child and not isinstance(child, collections.abc.Sequence):
  24. cloned_child = _clone_node_with_lineno(
  25. node=child, lineno=new_node.lineno, parent=new_node
  26. )
  27. postinit_params[param] = cloned_child
  28. new_node.postinit(**postinit_params)
  29. return new_node
  30. def _transform_formatted_value( # pylint: disable=inconsistent-return-statements
  31. node: nodes.FormattedValue,
  32. ) -> nodes.FormattedValue | None:
  33. if node.value and node.value.lineno == 1:
  34. if node.lineno != node.value.lineno:
  35. new_node = nodes.FormattedValue(
  36. lineno=node.lineno, col_offset=node.col_offset, parent=node.parent
  37. )
  38. new_value = _clone_node_with_lineno(
  39. node=node.value, lineno=node.lineno, parent=new_node
  40. )
  41. new_node.postinit(
  42. value=new_value,
  43. conversion=node.conversion,
  44. format_spec=node.format_spec,
  45. )
  46. return new_node
  47. # TODO: this fix tries to *patch* http://bugs.python.org/issue29051
  48. # The problem is that FormattedValue.value, which is a Name node,
  49. # has wrong line numbers, usually 1. This creates problems for pylint,
  50. # which expects correct line numbers for things such as message control.
  51. AstroidManager().register_transform(nodes.FormattedValue, _transform_formatted_value)