def lookup_concrete(self, tvar): """Find a set representative, which is either a concrete type, or the first element.""" if not isinstance(tvar, TypeVar): return tvar i = self._find(tvar) the_set = self._sets[i] rep = None for t in the_set: if rep is None: rep = t elif not _type_vars([t]): rep = t elif (isinstance(t, CallableMeta) or isinstance(t, TuplePlus) or isinstance(t, GenericMeta)) and isinstance(rep, TypeVar): rep = t if isinstance(rep, CallableMeta): return _gorg( rep)[[self.lookup_concrete(t1) for t1 in rep.__args__[:-1]], self.lookup_concrete(rep.__args__[-1])] elif isinstance(rep, GenericMeta): return _gorg(rep)[tuple( self.lookup_concrete(t1) for t1 in rep.__args__)] return rep or tvar
def __new__(cls, name, bases, namespace, tvars=None, args=None, origin=None, extra=None, orig_bases=None): # This is just a version copied from GenericMeta.__new__ that # includes "Protocol" special treatment. (Comments removed for brevity.) assert extra is None # Protocols should not have extra if tvars is not None: assert origin is not None assert all(isinstance(t, TypeVar) for t in tvars), tvars else: tvars = _type_vars(bases) gvars = None for base in bases: if base is Generic: raise TypeError("Cannot inherit from plain Generic") if (isinstance(base, GenericMeta) and base.__origin__ in (Generic, Protocol)): if gvars is not None: raise TypeError( "Cannot inherit from Generic[...] or" " Protocol[...] multiple times.") gvars = base.__parameters__ if gvars is None: gvars = tvars else: tvarset = set(tvars) gvarset = set(gvars) if not tvarset <= gvarset: raise TypeError( "Some type variables (%s) " "are not listed in %s[%s]" % (", ".join(str(t) for t in tvars if t not in gvarset), "Generic" if any(b.__origin__ is Generic for b in bases) else "Protocol", ", ".join(str(g) for g in gvars))) tvars = gvars initial_bases = bases if extra is None: extra = namespace.get('__extra__') if extra is not None and type(extra) is abc.ABCMeta and extra not in bases: bases = (extra,) + bases bases = tuple(_gorg(b) if isinstance(b, GenericMeta) else b for b in bases) if any(isinstance(b, GenericMeta) and b is not Generic for b in bases): bases = tuple(b for b in bases if b is not Generic) namespace.update({'__origin__': origin, '__extra__': extra}) self = abc.ABCMeta.__new__(cls, name, bases, namespace) abc.ABCMeta.__setattr__(self, '_gorg', self if not origin else _gorg(origin)) self.__parameters__ = tvars self.__args__ = tuple(Ellipsis if a is _TypingEllipsis else () if a is _TypingEmpty else a for a in args) if args else None self.__next_in_mro__ = _next_in_mro(self) if orig_bases is None: self.__orig_bases__ = initial_bases self.__tree_hash__ = (hash(self._subs_tree()) if origin else abc.ABCMeta.__hash__(self)) return self
def __getitem__(self, params): # We also need to copy this from GenericMeta.__getitem__ to get # special treatment of "Protocol". (Comments removed for brevity.) if not isinstance(params, tuple): params = (params, ) if not params and _gorg(self) is not Tuple: raise TypeError( "Parameter list to %s[...] cannot be empty" % self.__qualname__) msg = "Parameters to generic types must be types." params = tuple(_type_check(p, msg) for p in params) if self in (Generic, Protocol): if not all(isinstance(p, TypeVar) for p in params): raise TypeError( "Parameters to %r[...] must all be type variables" % self) if len(set(params)) != len(params): raise TypeError( "Parameters to %r[...] must all be unique" % self) tvars = params args = params elif self in (Tuple, Callable): tvars = _type_vars(params) args = params elif self.__origin__ in (Generic, Protocol): raise TypeError("Cannot subscript already-subscripted %s" % repr(self)) else: _check_generic(self, params) tvars = _type_vars(params) args = params prepend = (self, ) if self.__origin__ is None else () return self.__class__(self.__name__, prepend + self.__bases__, _no_slots_copy(self.__dict__), tvars=tvars, args=args, origin=self, extra=self.__extra__, orig_bases=self.__orig_bases__)
def __getitem__(self, params): # We also need to copy this from GenericMeta.__getitem__ to get # special treatment of "Protocol". (Comments removed for brevity.) if not isinstance(params, tuple): params = (params,) if not params and _gorg(self) is not Tuple: raise TypeError( "Parameter list to %s[...] cannot be empty" % self.__qualname__) msg = "Parameters to generic types must be types." params = tuple(_type_check(p, msg) for p in params) if self in (Generic, Protocol): if not all(isinstance(p, TypeVar) for p in params): raise TypeError( "Parameters to %r[...] must all be type variables", self) if len(set(params)) != len(params): raise TypeError( "Parameters to %r[...] must all be unique", self) tvars = params args = params elif self in (Tuple, Callable): tvars = _type_vars(params) args = params elif self.__origin__ in (Generic, Protocol): raise TypeError("Cannot subscript already-subscripted %s" % repr(self)) else: _check_generic(self, params) tvars = _type_vars(params) args = params prepend = (self,) if self.__origin__ is None else () return self.__class__(self.__name__, prepend + self.__bases__, dict(self.__dict__), tvars=tvars, args=args, origin=self, extra=self.__extra__, orig_bases=self.__orig_bases__)
def __getitem__(self, params): if not isinstance(params, tuple): params = (params, ) if self.__origin__ is not None: # specializing an instantiated type return super(AnnotatedMeta, self).__getitem__(params) elif not isinstance(params, tuple) or len(params) < 2: raise TypeError("Annotated[...] should be instantiated with at " "least two arguments (a type and an annotation).") else: msg = "Annotated[t, ...]: t must be a type." tp = typing._type_check(params[0], msg) metadata = tuple(params[1:]) return self.__class__( self.__name__, self.__bases__, dict(self.__dict__), tvars=_type_vars((tp, )), # Metadata is a tuple so it won't be touched by _replace_args et al. args=(tp, metadata), origin=self, )