class BaseValue(object): def __init__(self, inference_state, parent_context=None): self.inference_state = inference_state self.parent_context = parent_context def get_root_context(self): value = self while True: if value.parent_context is None: return value value = value.parent_context def infer_type_vars(self, value_set, is_class_value=False): """ When the current instance represents a type annotation, this method tries to find information about undefined type vars and returns a dict from type var name to value set. This is for example important to understand what `iter([1])` returns. According to typeshed, `iter` returns an `Iterator[_T]`: def iter(iterable: Iterable[_T]) -> Iterator[_T]: ... This functions would generate `int` for `_T` in this case, because it unpacks the `Iterable`. Parameters ---------- `self`: represents the annotation of the current parameter to infer the value for. In the above example, this would initially be the `Iterable[_T]` of the `iterable` parameter and then, when recursing, just the `_T` generic parameter. `value_set`: represents the actual argument passed to the parameter we're inferrined for, or (for recursive calls) their types. In the above example this would first be the representation of the list `[1]` and then, when recursing, just of `1`. `is_class_value`: tells us whether or not to treat the `value_set` as representing the instances or types being passed, which is neccesary to correctly cope with `Type[T]` annotations. When it is True, this means that we are being called with a nested portion of an annotation and that the `value_set` represents the types of the arguments, rather than their actual instances. Note: not all recursive calls will neccesarily set this to True. """ return {} class BaseValueSet(object): def __init__(self, iterable): self._set = frozenset(iterable) for value in iterable: assert not isinstance(value, BaseValueSet) @classmethod def _from_frozen_set(cls, frozenset_): self = cls.__new__(cls) self._set = frozenset_ return self @classmethod def from_sets(cls, sets): """ Used to work with an iterable of set. """ aggregated = set() for set_ in sets: if isinstance(set_, BaseValueSet): aggregated |= set_._set else: aggregated |= frozenset(set_) return cls._from_frozen_set(frozenset(aggregated)) def __or__(self, other): return self._from_frozen_set(self._set | other._set) def __and__(self, other): return self._from_frozen_set(self._set & other._set) def __iter__(self): for element in self._set: yield element def __bool__(self): return bool(self._set) def __len__(self): return len(self._set) def __repr__(self): return 'S{%s}' % (', '.join(str(s) for s in self._set)) def filter(self, filter_func): return self.__class__(filter(filter_func, self._set)) def __getattr__(self, name): def mapper(*args, **kwargs): return self.from_sets( getattr(value, name)(*args, **kwargs) for value in self._set ) return mapper def __eq__(self, other): return self._set == other._set def __ne__(self, other): return not self.__eq__(other) def __hash__(self): return hash(self._set)