brain_pathlib.py 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
  2. # For details: https://github.com/pylint-dev/astroid/blob/main/LICENSE
  3. # Copyright (c) https://github.com/pylint-dev/astroid/blob/main/CONTRIBUTORS.txt
  4. from __future__ import annotations
  5. from collections.abc import Iterator
  6. from astroid import bases, context, nodes
  7. from astroid.builder import _extract_single_node
  8. from astroid.const import PY313
  9. from astroid.exceptions import InferenceError, UseInferenceDefault
  10. from astroid.inference_tip import inference_tip
  11. from astroid.manager import AstroidManager
  12. PATH_TEMPLATE = """
  13. from pathlib import Path
  14. Path
  15. """
  16. def _looks_like_parents_subscript(node: nodes.Subscript) -> bool:
  17. if not (
  18. isinstance(node.value, nodes.Attribute) and node.value.attrname == "parents"
  19. ):
  20. return False
  21. try:
  22. value = next(node.value.infer())
  23. except (InferenceError, StopIteration):
  24. return False
  25. parents = "builtins.tuple" if PY313 else "pathlib._PathParents"
  26. return (
  27. isinstance(value, bases.Instance)
  28. and isinstance(value._proxied, nodes.ClassDef)
  29. and value.qname() == parents
  30. )
  31. def infer_parents_subscript(
  32. subscript_node: nodes.Subscript, ctx: context.InferenceContext | None = None
  33. ) -> Iterator[bases.Instance]:
  34. if isinstance(subscript_node.slice, nodes.Const):
  35. path_cls = next(_extract_single_node(PATH_TEMPLATE).infer())
  36. return iter([path_cls.instantiate_class()])
  37. raise UseInferenceDefault
  38. def register(manager: AstroidManager) -> None:
  39. manager.register_transform(
  40. nodes.Subscript,
  41. inference_tip(infer_parents_subscript),
  42. _looks_like_parents_subscript,
  43. )