Issue #28556: upstream improvements to docstrings and error messages by Ivan Levkivskyi (#331)

This commit is contained in:
Guido van Rossum 2016-11-20 18:01:29 -08:00
parent 6e723d2d11
commit b24569a19d
1 changed files with 44 additions and 40 deletions

View File

@ -100,16 +100,16 @@ def _trim_name(nm):
class TypingMeta(type): class TypingMeta(type):
"""Metaclass for every type defined below. """Metaclass for most types defined in typing module
(not a part of public API).
This overrides __new__() to require an extra keyword parameter This overrides __new__() to require an extra keyword parameter
'_root', which serves as a guard against naive subclassing of the '_root', which serves as a guard against naive subclassing of the
typing classes. Any legitimate class defined using a metaclass typing classes. Any legitimate class defined using a metaclass
derived from TypingMeta (including internal subclasses created by derived from TypingMeta must pass _root=True.
e.g. Union[X, Y]) must pass _root=True.
This also defines a dummy constructor (all the work is done in This also defines a dummy constructor (all the work for most typing
__new__) and a nicer repr(). constructs is done in __new__) and a nicer repr().
""" """
_is_protocol = False _is_protocol = False
@ -126,8 +126,8 @@ class TypingMeta(type):
def _eval_type(self, globalns, localns): def _eval_type(self, globalns, localns):
"""Override this in subclasses to interpret forward references. """Override this in subclasses to interpret forward references.
For example, Union['C'] is internally stored as For example, List['C'] is internally stored as
Union[_ForwardRef('C')], which should evaluate to _Union[C], List[_ForwardRef('C')], which should evaluate to List[C],
where C is an object found in globalns or localns (searching where C is an object found in globalns or localns (searching
localns first, of course). localns first, of course).
""" """
@ -142,7 +142,7 @@ class TypingMeta(type):
class _TypingBase(metaclass=TypingMeta, _root=True): class _TypingBase(metaclass=TypingMeta, _root=True):
"""Indicator of special typing constructs.""" """Internal indicator of special typing constructs."""
__slots__ = () __slots__ = ()
@ -179,10 +179,10 @@ class _TypingBase(metaclass=TypingMeta, _root=True):
class _FinalTypingBase(_TypingBase, _root=True): class _FinalTypingBase(_TypingBase, _root=True):
"""Mix-in class to prevent instantiation. """Internal mix-in class to prevent instantiation.
Prevents instantiation unless _root=True is given in class call. Prevents instantiation unless _root=True is given in class call.
It is used to create pseudo-singleton instances Any, Union, Tuple, etc. It is used to create pseudo-singleton instances Any, Union, Optional, etc.
""" """
__slots__ = () __slots__ = ()
@ -198,7 +198,7 @@ class _FinalTypingBase(_TypingBase, _root=True):
class _ForwardRef(_TypingBase, _root=True): class _ForwardRef(_TypingBase, _root=True):
"""Wrapper to hold a forward reference.""" """Internal wrapper to hold a forward reference."""
__slots__ = ('__forward_arg__', '__forward_code__', __slots__ = ('__forward_arg__', '__forward_code__',
'__forward_evaluated__', '__forward_value__') '__forward_evaluated__', '__forward_value__')
@ -206,11 +206,11 @@ class _ForwardRef(_TypingBase, _root=True):
def __init__(self, arg): def __init__(self, arg):
super().__init__(arg) super().__init__(arg)
if not isinstance(arg, str): if not isinstance(arg, str):
raise TypeError('ForwardRef must be a string -- got %r' % (arg,)) raise TypeError('Forward reference must be a string -- got %r' % (arg,))
try: try:
code = compile(arg, '<string>', 'eval') code = compile(arg, '<string>', 'eval')
except SyntaxError: except SyntaxError:
raise SyntaxError('ForwardRef must be an expression -- got %r' % raise SyntaxError('Forward reference must be an expression -- got %r' %
(arg,)) (arg,))
self.__forward_arg__ = arg self.__forward_arg__ = arg
self.__forward_code__ = code self.__forward_code__ = code
@ -336,7 +336,7 @@ def _eval_type(t, globalns, localns):
def _type_check(arg, msg): def _type_check(arg, msg):
"""Check that the argument is a type, and return it. """Check that the argument is a type, and return it (internal helper).
As a special case, accept None and return type(None) instead. As a special case, accept None and return type(None) instead.
Also, _TypeAlias instances (e.g. Match, Pattern) are acceptable. Also, _TypeAlias instances (e.g. Match, Pattern) are acceptable.
@ -363,7 +363,7 @@ def _type_check(arg, msg):
def _type_repr(obj): def _type_repr(obj):
"""Return the repr() of an object, special-casing types. """Return the repr() of an object, special-casing types (internal helper).
If obj is a type, we return a shorter version than the default If obj is a type, we return a shorter version than the default
type.__repr__, based on the module and qualified name, which is type.__repr__, based on the module and qualified name, which is
@ -418,7 +418,7 @@ class TypeVar(_TypingBase, _root=True):
as for generic function definitions. See class Generic for more as for generic function definitions. See class Generic for more
information on generic types. Generic functions work as follows: information on generic types. Generic functions work as follows:
def repeat(x: T, n: int) -> Sequence[T]: def repeat(x: T, n: int) -> List[T]:
'''Return a list containing n references to x.''' '''Return a list containing n references to x.'''
return [x]*n return [x]*n
@ -431,10 +431,7 @@ class TypeVar(_TypingBase, _root=True):
that if the arguments are instances of some subclass of str, that if the arguments are instances of some subclass of str,
the return type is still plain str. the return type is still plain str.
At runtime, isinstance(x, T) will raise TypeError. However, At runtime, isinstance(x, T) and issubclass(C, T) will raise TypeError.
issubclass(C, T) is true for any class C, and issubclass(str, A)
and issubclass(bytes, A) are true, and issubclass(int, A) is
false. (TODO: Why is this needed? This may change. See #136.)
Type variables defined with covariant=True or contravariant=True Type variables defined with covariant=True or contravariant=True
can be used do declare covariant or contravariant generic types. can be used do declare covariant or contravariant generic types.
@ -509,7 +506,7 @@ AnyStr = TypeVar('AnyStr', bytes, str)
def _replace_arg(arg, tvars, args): def _replace_arg(arg, tvars, args):
""" A helper fuunction: replace arg if it is a type variable """An internal helper function: replace arg if it is a type variable
found in tvars with corresponding substitution from args or found in tvars with corresponding substitution from args or
with corresponding substitution sub-tree if arg is a generic type. with corresponding substitution sub-tree if arg is a generic type.
""" """
@ -526,9 +523,15 @@ def _replace_arg(arg, tvars, args):
def _subs_tree(cls, tvars=None, args=None): def _subs_tree(cls, tvars=None, args=None):
""" Calculate substitution tree for generic cls after """An internal helper function: calculate substitution tree
replacing its type parameters with substitutions in tvars -> args (if any). for generic cls after replacing its type parameters with
Repeat the same cyclicaly following __origin__'s. substitutions in tvars -> args (if any).
Repeat the same following __origin__'s.
Return a list of arguments with all possible substitutions
performed. Arguments that are generic classes themselves are represented
as tuples (so that no new classes are created by this function).
For example: _subs_tree(List[Tuple[int, T]][str]) == [(Tuple, int, str)]
""" """
if cls.__origin__ is None: if cls.__origin__ is None:
@ -553,7 +556,7 @@ def _subs_tree(cls, tvars=None, args=None):
def _remove_dups_flatten(parameters): def _remove_dups_flatten(parameters):
""" A helper for Union creation and substitution: flatten Union's """An internal helper for Union creation and substitution: flatten Union's
among parameters, then remove duplicates and strict subclasses. among parameters, then remove duplicates and strict subclasses.
""" """
@ -594,7 +597,7 @@ def _remove_dups_flatten(parameters):
def _check_generic(cls, parameters): def _check_generic(cls, parameters):
# Check correct count for parameters of a generic cls. # Check correct count for parameters of a generic cls (internal helper).
if not cls.__parameters__: if not cls.__parameters__:
raise TypeError("%s is not a generic class" % repr(cls)) raise TypeError("%s is not a generic class" % repr(cls))
alen = len(parameters) alen = len(parameters)
@ -608,7 +611,7 @@ _cleanups = []
def _tp_cache(func): def _tp_cache(func):
""" Caching for __getitem__ of generic types with a fallback to """Internal wrapper caching __getitem__ of generic types with a fallback to
original function for non-hashable arguments. original function for non-hashable arguments.
""" """
@ -788,7 +791,7 @@ Optional = _Optional(_root=True)
def _gorg(a): def _gorg(a):
"""Return the farthest origin of a generic class.""" """Return the farthest origin of a generic class (internal helper)."""
assert isinstance(a, GenericMeta) assert isinstance(a, GenericMeta)
while a.__origin__ is not None: while a.__origin__ is not None:
a = a.__origin__ a = a.__origin__
@ -796,10 +799,10 @@ def _gorg(a):
def _geqv(a, b): def _geqv(a, b):
"""Return whether two generic classes are equivalent. """Return whether two generic classes are equivalent (internal helper).
The intention is to consider generic class X and any of its The intention is to consider generic class X and any of its
parameterized forms (X[T], X[int], etc.) as equivalent. parameterized forms (X[T], X[int], etc.) as equivalent.
However, X is not equivalent to a subclass of X. However, X is not equivalent to a subclass of X.
@ -825,6 +828,7 @@ def _next_in_mro(cls):
def _valid_for_check(cls): def _valid_for_check(cls):
"""An internal helper to prohibit isinstance([1], List[str]) etc."""
if cls is Generic: if cls is Generic:
raise TypeError("Class %r cannot be used with class " raise TypeError("Class %r cannot be used with class "
"or instance checks" % cls) "or instance checks" % cls)
@ -1083,8 +1087,8 @@ def _generic_new(base_cls, cls, *args, **kwds):
class Generic(metaclass=GenericMeta): class Generic(metaclass=GenericMeta):
"""Abstract base class for generic types. """Abstract base class for generic types.
A generic type is typically declared by inheriting from an A generic type is typically declared by inheriting from
instantiation of this class with one or more type variables. this class parameterized with one or more type variables.
For example, a generic mapping type might be defined as:: For example, a generic mapping type might be defined as::
class Mapping(Generic[KT, VT]): class Mapping(Generic[KT, VT]):
@ -1111,18 +1115,18 @@ class Generic(metaclass=GenericMeta):
class _TypingEmpty: class _TypingEmpty:
"""Placeholder for () or []. Used by TupleMeta and CallableMeta """Internal placeholder for () or []. Used by TupleMeta and CallableMeta
to allow empy list/tuple in specific places, without allowing them to allow empty list/tuple in specific places, without allowing them
to sneak in where prohibited. to sneak in where prohibited.
""" """
class _TypingEllipsis: class _TypingEllipsis:
"""Ditto for ...""" """Internal placeholder for ... (ellipsis)."""
class TupleMeta(GenericMeta): class TupleMeta(GenericMeta):
"""Metaclass for Tuple""" """Metaclass for Tuple (internal)."""
@_tp_cache @_tp_cache
def __getitem__(self, parameters): def __getitem__(self, parameters):
@ -1175,7 +1179,7 @@ class Tuple(tuple, extra=tuple, metaclass=TupleMeta):
class CallableMeta(GenericMeta): class CallableMeta(GenericMeta):
""" Metaclass for Callable.""" """Metaclass for Callable (internal)."""
def __repr__(self): def __repr__(self):
if self.__origin__ is None: if self.__origin__ is None:
@ -1199,7 +1203,7 @@ class CallableMeta(GenericMeta):
'[[%s], %s]' % (', '.join(arg_list[:-1]), arg_list[-1])) '[[%s], %s]' % (', '.join(arg_list[:-1]), arg_list[-1]))
def __getitem__(self, parameters): def __getitem__(self, parameters):
""" A thin wrapper around __getitem_inner__ to provide the latter """A thin wrapper around __getitem_inner__ to provide the latter
with hashable arguments to improve speed. with hashable arguments to improve speed.
""" """
@ -1236,7 +1240,7 @@ class Callable(extra=collections_abc.Callable, metaclass = CallableMeta):
The subscription syntax must always be used with exactly two The subscription syntax must always be used with exactly two
values: the argument list and the return type. The argument list values: the argument list and the return type. The argument list
must be a list of types; the return type must be a single type. must be a list of types or ellipsis; the return type must be a single type.
There is no syntax to indicate optional or keyword arguments, There is no syntax to indicate optional or keyword arguments,
such function types are rarely used as callback types. such function types are rarely used as callback types.
@ -1565,7 +1569,7 @@ class _ProtocolMeta(GenericMeta):
class _Protocol(metaclass=_ProtocolMeta): class _Protocol(metaclass=_ProtocolMeta):
"""Internal base class for protocol classes. """Internal base class for protocol classes.
This implements a simple-minded structural isinstance check This implements a simple-minded structural issubclass check
(similar but more general than the one-offs in collections.abc (similar but more general than the one-offs in collections.abc
such as Hashable). such as Hashable).
""" """