Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/jedi/inference/utils.py: 60%
43 statements
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-20 06:09 +0000
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-20 06:09 +0000
1""" A universal module with functions / classes without dependencies. """
2import functools
3import re
4import os
7_sep = os.path.sep
8if os.path.altsep is not None:
9 _sep += os.path.altsep
10_path_re = re.compile(r'(?:\.[^{0}]+|[{0}]__init__\.py)$'.format(re.escape(_sep)))
11del _sep
14def to_list(func):
15 def wrapper(*args, **kwargs):
16 return list(func(*args, **kwargs))
17 return wrapper
20def to_tuple(func):
21 def wrapper(*args, **kwargs):
22 return tuple(func(*args, **kwargs))
23 return wrapper
26def unite(iterable):
27 """Turns a two dimensional array into a one dimensional."""
28 return set(typ for types in iterable for typ in types)
31class UncaughtAttributeError(Exception):
32 """
33 Important, because `__getattr__` and `hasattr` catch AttributeErrors
34 implicitly. This is really evil (mainly because of `__getattr__`).
35 Therefore this class originally had to be derived from `BaseException`
36 instead of `Exception`. But because I removed relevant `hasattr` from
37 the code base, we can now switch back to `Exception`.
39 :param base: return values of sys.exc_info().
40 """
43def safe_property(func):
44 return property(reraise_uncaught(func))
47def reraise_uncaught(func):
48 """
49 Re-throw uncaught `AttributeError`.
51 Usage: Put ``@rethrow_uncaught`` in front of the function
52 which does **not** suppose to raise `AttributeError`.
54 AttributeError is easily get caught by `hasattr` and another
55 ``except AttributeError`` clause. This becomes problem when you use
56 a lot of "dynamic" attributes (e.g., using ``@property``) because you
57 can't distinguish if the property does not exist for real or some code
58 inside of the "dynamic" attribute through that error. In a well
59 written code, such error should not exist but getting there is very
60 difficult. This decorator is to help us getting there by changing
61 `AttributeError` to `UncaughtAttributeError` to avoid unexpected catch.
62 This helps us noticing bugs earlier and facilitates debugging.
63 """
64 @functools.wraps(func)
65 def wrapper(*args, **kwds):
66 try:
67 return func(*args, **kwds)
68 except AttributeError as e:
69 raise UncaughtAttributeError(e) from e
70 return wrapper
73class PushBackIterator:
74 def __init__(self, iterator):
75 self.pushes = []
76 self.iterator = iterator
77 self.current = None
79 def push_back(self, value):
80 self.pushes.append(value)
82 def __iter__(self):
83 return self
85 def __next__(self):
86 if self.pushes:
87 self.current = self.pushes.pop()
88 else:
89 self.current = next(self.iterator)
90 return self.current