Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/jedi-0.20.1-py3.11.egg/jedi/inference/utils.py: 65%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

46 statements  

1""" A universal module with functions / classes without dependencies. """ 

2import functools 

3import re 

4import os 

5from typing import ParamSpec, TypeVar, Callable, Iterable 

6 

7 

8_sep = os.path.sep 

9if os.path.altsep is not None: 

10 _sep += os.path.altsep 

11_path_re = re.compile(r'(?:\.[^{0}]+|[{0}]__init__\.py)$'.format(re.escape(_sep))) 

12del _sep 

13 

14P = ParamSpec("P") 

15T = TypeVar("T") 

16 

17 

18def to_list(func: Callable[P, Iterable[T]]) -> Callable[P, list[T]]: 

19 def wrapper(*args, **kwargs): 

20 return list(func(*args, **kwargs)) 

21 return wrapper 

22 

23 

24def to_tuple(func): 

25 def wrapper(*args, **kwargs): 

26 return tuple(func(*args, **kwargs)) 

27 return wrapper 

28 

29 

30def unite(iterable): 

31 """Turns a two dimensional array into a one dimensional.""" 

32 return set(typ for types in iterable for typ in types) 

33 

34 

35class UncaughtAttributeError(Exception): 

36 """ 

37 Important, because `__getattr__` and `hasattr` catch AttributeErrors 

38 implicitly. This is really evil (mainly because of `__getattr__`). 

39 Therefore this class originally had to be derived from `BaseException` 

40 instead of `Exception`. But because I removed relevant `hasattr` from 

41 the code base, we can now switch back to `Exception`. 

42 

43 :param base: return values of sys.exc_info(). 

44 """ 

45 

46 

47def safe_property(func): 

48 return property(reraise_uncaught(func)) 

49 

50 

51def reraise_uncaught(func): 

52 """ 

53 Re-throw uncaught `AttributeError`. 

54 

55 Usage: Put ``@rethrow_uncaught`` in front of the function 

56 which does **not** suppose to raise `AttributeError`. 

57 

58 AttributeError is easily get caught by `hasattr` and another 

59 ``except AttributeError`` clause. This becomes problem when you use 

60 a lot of "dynamic" attributes (e.g., using ``@property``) because you 

61 can't distinguish if the property does not exist for real or some code 

62 inside of the "dynamic" attribute through that error. In a well 

63 written code, such error should not exist but getting there is very 

64 difficult. This decorator is to help us getting there by changing 

65 `AttributeError` to `UncaughtAttributeError` to avoid unexpected catch. 

66 This helps us noticing bugs earlier and facilitates debugging. 

67 """ 

68 @functools.wraps(func) 

69 def wrapper(*args, **kwds): 

70 try: 

71 return func(*args, **kwds) 

72 except AttributeError as e: 

73 raise UncaughtAttributeError(e) from e 

74 return wrapper 

75 

76 

77class PushBackIterator: 

78 def __init__(self, iterator): 

79 self.pushes = [] 

80 self.iterator = iterator 

81 

82 def push_back(self, value): 

83 self.pushes.append(value) 

84 

85 def __iter__(self): 

86 return self 

87 

88 def __next__(self): 

89 if self.pushes: 

90 self.current = self.pushes.pop() 

91 else: 

92 self.current = next(self.iterator) 

93 return self.current