Support TypedDicts with missing keys (total=False) (#3558)
* Basic support for TypedDicts with missing keys (total=False)
Only the functional syntax is supported.
* Support get(key, {}) and fix construction of partial typed dict
* Fix subtyping of non-total typed dicts
* Fix join with non-total typed dict
* Fix meet with non-total typed dicts
* Add serialization test case
* Support TypedDict total keyword argument with class syntax
* Attempt to fix Python 3.3
* Add minimal runtime `total` support to mypy_extensions
There is no support for introspection of `total` yet.
* Fix tests on pre-3.6 Python and improve introspection
Make TypedDict `total` introspectable.
* Fix lint
* Fix problems caused by merge
* Allow td['key'] even if td is not total
* Fix lint
* Add test case
* Address review feedback
* Update comment
diff --git a/mypy_extensions.py b/mypy_extensions.py
index 82eea32..c711e00 100644
--- a/mypy_extensions.py
+++ b/mypy_extensions.py
@@ -30,16 +30,18 @@
def _typeddict_new(cls, _typename, _fields=None, **kwargs):
+ total = kwargs.pop('total', True)
if _fields is None:
_fields = kwargs
elif kwargs:
raise TypeError("TypedDict takes either a dict or keyword arguments,"
" but not both")
- return _TypedDictMeta(_typename, (), {'__annotations__': dict(_fields)})
+ return _TypedDictMeta(_typename, (), {'__annotations__': dict(_fields),
+ '__total__': total})
class _TypedDictMeta(type):
- def __new__(cls, name, bases, ns):
+ def __new__(cls, name, bases, ns, total=True):
# Create new typed dict class object.
# This method is called directly when TypedDict is subclassed,
# or via _typeddict_new when TypedDict is instantiated. This way
@@ -59,6 +61,8 @@
for base in bases:
anns.update(base.__dict__.get('__annotations__', {}))
tp_dict.__annotations__ = anns
+ if not hasattr(tp_dict, '__total__'):
+ tp_dict.__total__ = total
return tp_dict
__instancecheck__ = __subclasscheck__ = _check_fails