Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bpo-46644: Remove callable() requirement from typing._type_check #31151

Merged
merged 9 commits into from
Mar 12, 2022
2 changes: 1 addition & 1 deletion Lib/test/test_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -835,7 +835,7 @@ def test_union_parameter_substitution_errors(self):
T = typing.TypeVar("T")
x = int | T
with self.assertRaises(TypeError):
x[42]
GBeauregard marked this conversation as resolved.
Show resolved Hide resolved
x[int, str]

def test_or_type_operator_with_forward(self):
T = typing.TypeVar('T')
Expand Down
31 changes: 4 additions & 27 deletions Lib/test/test_typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ def test_cannot_instantiate_vars(self):

def test_bound_errors(self):
with self.assertRaises(TypeError):
TypeVar('X', bound=42)
GBeauregard marked this conversation as resolved.
Show resolved Hide resolved
TypeVar('X', bound=Union)
with self.assertRaises(TypeError):
TypeVar('X', str, float, bound=Employee)

Expand Down Expand Up @@ -1994,9 +1994,6 @@ def test_extended_generic_rules_eq(self):
class Base: ...
class Derived(Base): ...
self.assertEqual(Union[T, Base][Union[Base, Derived]], Union[Base, Derived])
with self.assertRaises(TypeError):
Union[T, int][1]

self.assertEqual(Callable[[T], T][KT], Callable[[KT], KT])
self.assertEqual(Callable[..., List[T]][int], Callable[..., List[int]])

Expand Down Expand Up @@ -2497,8 +2494,6 @@ class Foo(obj):
class ClassVarTests(BaseTestCase):

def test_basics(self):
with self.assertRaises(TypeError):
ClassVar[1]
with self.assertRaises(TypeError):
ClassVar[int, str]
with self.assertRaises(TypeError):
Expand Down Expand Up @@ -2537,8 +2532,6 @@ class FinalTests(BaseTestCase):

def test_basics(self):
Final[int] # OK
with self.assertRaises(TypeError):
Final[1]
with self.assertRaises(TypeError):
Final[int, str]
with self.assertRaises(TypeError):
Expand Down Expand Up @@ -2923,14 +2916,6 @@ def foo(a: 'Node[T'):
with self.assertRaises(SyntaxError):
get_type_hints(foo)

def test_type_error(self):

def foo(a: Tuple['42']):
pass

with self.assertRaises(TypeError):
get_type_hints(foo)

def test_name_error(self):

def foo(a: 'Noode[T]'):
Expand Down Expand Up @@ -4222,8 +4207,6 @@ def test_namedtuple_keyword_usage(self):
self.assertEqual(LocalEmployee.__annotations__, dict(name=str, age=int))
with self.assertRaises(TypeError):
NamedTuple('Name', [('x', int)], y=str)
with self.assertRaises(TypeError):
NamedTuple('Name', x=1, y='a')

def test_namedtuple_special_keyword_names(self):
NT = NamedTuple("NT", cls=type, self=object, typename=str, fields=list)
Expand Down Expand Up @@ -4259,8 +4242,6 @@ def test_namedtuple_errors(self):
NamedTuple('Emp', [('_name', str)])
with self.assertRaises(TypeError):
NamedTuple(typename='Emp', name=str, id=int)
with self.assertRaises(TypeError):
NamedTuple('Emp', fields=[('name', str), ('id', int)])

def test_copy_and_pickle(self):
global Emp # pickle wants to reference the class by name
Expand Down Expand Up @@ -4333,11 +4314,8 @@ def test_typeddict_create_errors(self):
TypedDict()
with self.assertRaises(TypeError):
TypedDict('Emp', [('name', str)], None)

with self.assertRaises(TypeError):
TypedDict(_typename='Emp', name=str, id=int)
with self.assertRaises(TypeError):
TypedDict('Emp', _fields={'name': str, 'id': int})

def test_typeddict_errors(self):
Emp = TypedDict('Emp', {'name': str, 'id': int})
Expand All @@ -4349,10 +4327,6 @@ def test_typeddict_errors(self):
isinstance(jim, Emp)
with self.assertRaises(TypeError):
issubclass(dict, Emp)
with self.assertRaises(TypeError):
TypedDict('Hi', x=1)
with self.assertRaises(TypeError):
TypedDict('Hi', [('x', int), ('y', 1)])
with self.assertRaises(TypeError):
TypedDict('Hi', [('x', int)], y=int)

Expand Down Expand Up @@ -5066,6 +5040,9 @@ def test_basics(self):
def foo(arg) -> TypeGuard[int]: ...
self.assertEqual(gth(foo), {'return': TypeGuard[int]})

with self.assertRaises(TypeError):
TypeGuard[int, str]

def test_repr(self):
self.assertEqual(repr(TypeGuard), 'typing.TypeGuard')
cv = TypeGuard[int]
Expand Down
4 changes: 1 addition & 3 deletions Lib/typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,9 +178,7 @@ def _type_check(arg, msg, is_argument=True, module=None, *, allow_special_forms=
return arg
if isinstance(arg, _SpecialForm) or arg in (Generic, Protocol):
raise TypeError(f"Plain {arg} is not valid as type argument")
if isinstance(arg, (type, TypeVar, ForwardRef, types.UnionType, ParamSpec)):
return arg
if not callable(arg):
if type(arg) is tuple:
raise TypeError(f"{msg} Got {arg!r:.100}.")
return arg

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
No longer require valid typeforms to be callable. This allows :data:`typing.Annotated` to wrap :data:`typing.ParamSpecArgs` and :data:`dataclasses.InitVar`. Patch by Gregory Beauregard.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Each line should be under 80 chars. However since this is usually merged into the next release's changelog anyways I'm not sure if it matters.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think blurb takes care of that when it generates the full changelog.