From a7e5e1d5a3f9e4ade420608d7ca79661eb7a2e08 Mon Sep 17 00:00:00 2001 From: Thomas Grainger Date: Mon, 23 Jul 2018 10:51:42 +0100 Subject: [PATCH 1/2] support pep-563 -- Postponed Evaluation of Annotations --- 05-annotations.py | 3 ++- 07-metaclasses.py | 3 ++- 08-interlude_dataclasses.py | 8 +++++--- 09-meta_dataclasses.py | 3 ++- 11-ast.py | 3 ++- 5 files changed, 13 insertions(+), 7 deletions(-) diff --git a/05-annotations.py b/05-annotations.py index 8fc3a69..5071c6f 100644 --- a/05-annotations.py +++ b/05-annotations.py @@ -1,4 +1,5 @@ from math import pi +import typing class TypeChecker: @@ -17,7 +18,7 @@ def __set__(self, instance, value): def type_check(cls): - for var_name, var_type in cls.__annotations__.items(): + for var_name, var_type in typing.get_type_hints(cls).items(): class Checker(TypeChecker): required_type = var_type diff --git a/07-metaclasses.py b/07-metaclasses.py index 15a9cb4..721ff1f 100644 --- a/07-metaclasses.py +++ b/07-metaclasses.py @@ -1,4 +1,5 @@ from math import pi +import typing class TypeChecker: @@ -17,7 +18,7 @@ def __set__(self, instance, value): def type_check(cls): - for var_name, var_type in cls.__annotations__.items(): + for var_name, var_type in typing.get_type_hints(cls).items(): class Checker(TypeChecker): required_type = var_type diff --git a/08-interlude_dataclasses.py b/08-interlude_dataclasses.py index 61d7fde..6a2a8ee 100644 --- a/08-interlude_dataclasses.py +++ b/08-interlude_dataclasses.py @@ -1,9 +1,11 @@ +import typing + def dataclass(cls): def __init__(self, *args, **kwargs): - for k, v in zip(cls.__annotations__.keys(), args): + for k, v in zip(typing.get_type_hints(cls).keys(), args): setattr(self, k, v) for k, v in kwargs.items(): - if k not in cls.__annotations__: + if k not in typing.get_type_hints(cls): raise TypeError( f"__init__() got an unexpected keyword argument '{k}'" ) @@ -14,7 +16,7 @@ def __init__(self, *args, **kwargs): post_init() def __repr__(self): - kwargs = {k: getattr(self, k) for k in cls.__annotations__} + kwargs = {k: getattr(self, k) for k in typing.get_type_hints(cls)} kwstr = ', '.join([f'{k}={v}' for k, v in kwargs.items()]) return f'{cls.__name__}({kwstr})' diff --git a/09-meta_dataclasses.py b/09-meta_dataclasses.py index 6b72bcf..0f39ed1 100644 --- a/09-meta_dataclasses.py +++ b/09-meta_dataclasses.py @@ -1,5 +1,6 @@ from dataclasses import dataclass from math import pi +import typing class TypeChecker: @@ -20,7 +21,7 @@ def __set__(self, instance, value): def typed_dataclass(cls): cls = dataclass(cls) - for var_name, var_type in cls.__annotations__.items(): + for var_name, var_type in typing.get_type_hints(cls).items(): class Checker(TypeChecker): required_type = var_type diff --git a/11-ast.py b/11-ast.py index 224f154..0b1800e 100644 --- a/11-ast.py +++ b/11-ast.py @@ -1,4 +1,5 @@ import ast +import typing # This could come from a variety of sources: not just text. For instance, we # could use inspect.get_source() @@ -22,7 +23,7 @@ def __set__(self, instance, value): def type_check(cls): - for var_name, var_type in cls.__annotations__.items(): + for var_name, var_type in typing.get_type_hints(cls).items(): class Checker(TypeChecker): required_type = var_type setattr(cls, var_name, Checker(var_name)) From 41b3a554dd8ac70b4caf3f7923cd0ca1079784fa Mon Sep 17 00:00:00 2001 From: Thomas Grainger Date: Mon, 23 Jul 2018 11:56:34 +0100 Subject: [PATCH 2/2] typing.get_type_hints handles missing __annotations__ https://github.com/python/cpython/blob/e019f98dc2fdddbee7990e518ead00de2245a0c8/Lib/typing.py#L967 --- 07-metaclasses.py | 2 +- 09-meta_dataclasses.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/07-metaclasses.py b/07-metaclasses.py index 721ff1f..2fc11e0 100644 --- a/07-metaclasses.py +++ b/07-metaclasses.py @@ -33,7 +33,7 @@ def __new__(meta, name, bases, dct): class Base(metaclass=TypeCheckMeta): - __annotations__ = {} + pass class Point(Base): diff --git a/09-meta_dataclasses.py b/09-meta_dataclasses.py index 0f39ed1..bf6dd3b 100644 --- a/09-meta_dataclasses.py +++ b/09-meta_dataclasses.py @@ -36,7 +36,7 @@ def __new__(meta, name, bases, dct): class Base(metaclass=TypeCheckMeta): - __annotations__ = {} + pass class Point(Base):