diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index 75113f123b3..b035cbb809f 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -201,10 +201,16 @@ _MODULE_IDENTIFIER_RE = re.compile(r'^(?:\s*(\w+)\s*\.)?\s*(\w+)') class _InitVarMeta(type): def __getitem__(self, params): - return self + return InitVar(params) class InitVar(metaclass=_InitVarMeta): - pass + __slots__ = ('type', ) + + def __init__(self, type): + self.type = type + + def __repr__(self): + return f'dataclasses.InitVar[{self.type.__name__}]' # Instances of Field are only ever created from within this module, @@ -586,7 +592,8 @@ def _is_classvar(a_type, typing): def _is_initvar(a_type, dataclasses): # The module we're checking against is the module we're # currently in (dataclasses.py). - return a_type is dataclasses.InitVar + return (a_type is dataclasses.InitVar + or type(a_type) is dataclasses.InitVar) def _is_type(annotation, cls, a_module, a_type, is_type_predicate): diff --git a/Lib/test/test_dataclasses.py b/Lib/test/test_dataclasses.py index 867210688f5..53e8443c2ad 100755 --- a/Lib/test/test_dataclasses.py +++ b/Lib/test/test_dataclasses.py @@ -1097,6 +1097,12 @@ class TestCase(unittest.TestCase): c = C(init_param=10) self.assertEqual(c.x, 20) + def test_init_var_preserve_type(self): + self.assertEqual(InitVar[int].type, int) + + # Make sure the repr is correct. + self.assertEqual(repr(InitVar[int]), 'dataclasses.InitVar[int]') + def test_init_var_inheritance(self): # Note that this deliberately tests that a dataclass need not # have a __post_init__ function if it has an InitVar field. diff --git a/Misc/NEWS.d/next/Library/2018-08-28-03-00-12.bpo-33569.45YlGG.rst b/Misc/NEWS.d/next/Library/2018-08-28-03-00-12.bpo-33569.45YlGG.rst new file mode 100644 index 00000000000..adafa2803ae --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-08-28-03-00-12.bpo-33569.45YlGG.rst @@ -0,0 +1 @@ +dataclasses.InitVar: Exposes the type used to create the init var.