generics.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. """
  2. This module is about generics, like the `int` in `List[int]`. It's not about
  3. the Generic class.
  4. """
  5. from jedi import debug
  6. from jedi.cache import memoize_method
  7. from jedi.inference.utils import to_tuple
  8. from jedi.inference.base_value import ValueSet, NO_VALUES
  9. from jedi.inference.value.iterable import SequenceLiteralValue
  10. from jedi.inference.helpers import is_string
  11. def _resolve_forward_references(context, value_set):
  12. for value in value_set:
  13. if is_string(value):
  14. from jedi.inference.gradual.annotation import _get_forward_reference_node
  15. node = _get_forward_reference_node(context, value.get_safe_value())
  16. if node is not None:
  17. for c in context.infer_node(node):
  18. yield c
  19. else:
  20. yield value
  21. class _AbstractGenericManager:
  22. def get_index_and_execute(self, index):
  23. try:
  24. return self[index].execute_annotation()
  25. except IndexError:
  26. debug.warning('No param #%s found for annotation %s', index, self)
  27. return NO_VALUES
  28. def get_type_hint(self):
  29. return '[%s]' % ', '.join(t.get_type_hint(add_class_info=False) for t in self.to_tuple())
  30. class LazyGenericManager(_AbstractGenericManager):
  31. def __init__(self, context_of_index, index_value):
  32. self._context_of_index = context_of_index
  33. self._index_value = index_value
  34. @memoize_method
  35. def __getitem__(self, index):
  36. return self._tuple()[index]()
  37. def __len__(self):
  38. return len(self._tuple())
  39. @memoize_method
  40. @to_tuple
  41. def _tuple(self):
  42. def lambda_scoping_in_for_loop_sucks(lazy_value):
  43. return lambda: ValueSet(_resolve_forward_references(
  44. self._context_of_index,
  45. lazy_value.infer()
  46. ))
  47. if isinstance(self._index_value, SequenceLiteralValue):
  48. for lazy_value in self._index_value.py__iter__(contextualized_node=None):
  49. yield lambda_scoping_in_for_loop_sucks(lazy_value)
  50. else:
  51. yield lambda: ValueSet(_resolve_forward_references(
  52. self._context_of_index,
  53. ValueSet([self._index_value])
  54. ))
  55. @to_tuple
  56. def to_tuple(self):
  57. for callable_ in self._tuple():
  58. yield callable_()
  59. def is_homogenous_tuple(self):
  60. if isinstance(self._index_value, SequenceLiteralValue):
  61. entries = self._index_value.get_tree_entries()
  62. if len(entries) == 2 and entries[1] == '...':
  63. return True
  64. return False
  65. def __repr__(self):
  66. return '<LazyG>[%s]' % (', '.join(repr(x) for x in self.to_tuple()))
  67. class TupleGenericManager(_AbstractGenericManager):
  68. def __init__(self, tup):
  69. self._tuple = tup
  70. def __getitem__(self, index):
  71. return self._tuple[index]
  72. def __len__(self):
  73. return len(self._tuple)
  74. def to_tuple(self):
  75. return self._tuple
  76. def is_homogenous_tuple(self):
  77. return False
  78. def __repr__(self):
  79. return '<TupG>[%s]' % (', '.join(repr(x) for x in self.to_tuple()))