8000 Merge branch 'master' into namedtuple-join · python/mypy@3bc53ca · GitHub
[go: up one dir, main page]

Skip to content

Commit 3bc53ca

Browse files
committed
Merge branch 'master' into namedtuple-join
2 parents c9dba66 + 5d85832 commit 3bc53ca

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+3089
-552
lines changed

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ place to start a discussion of any of the above or most any other
3030
topic concerning the project.
3131

3232
For less formal discussion we have a chat room on
33-
[gitter.im](https://gitter.im/python/mypy). Some Mypy core developers
33+
[gitter.im](https://gitter.im/python/typing). Some Mypy core developers
3434
are almost always present; feel free to find us there and we're happy
3535
to chat. Substantive technical discussion will be directed to the
3636
issue tracker.

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@ Mypy: Optional Static Typing for Python
22
=======================================
33

44
[![Build Status](https://travis-ci.org/python/mypy.svg)](https://travis-ci.org/python/mypy)
5-
[![Chat at https://gitter.im/python/mypy](https://badges.gitter.im/python/mypy.svg)](https://gitter.im/python/mypy?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
5+
[![Chat at https://gitter.im/python/typing](https://badges.gitter.im/python/typing.svg)](https://gitter.im/python/typing?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
66

77

88
Got a question? Join us on Gitter!
99
----------------------------------
1010

1111
We don't have a mailing list; but we are always happy to answer
12-
questions on [gitter chat](https://gitter.im/python/mypy). If you are
12+
questions on [gitter chat](https://gitter.im/python/typing). If you are
1313
sure you've found a bug please search our issue trackers for a
1414
duplicate before filing a new issue:
1515

docs/source/cheat_sheet.rst

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,15 +232,17 @@ Other stuff
232232
233233
# Use AnyStr for functions that should accept any kind of string
234234
# without allowing different kinds of strings to mix.
235-
def concat(a: AnyStr, b: AnyStr) -> AnyStr:
235+
def concat(a, b):
236+
# type: (AnyStr, AnyStr) -> AnyStr
236237
return a + b
237238
concat(u"foo", u"bar") # type: unicode
238239
concat(b"foo", b"bar") # type: bytes
239240
240241
# Use IO[] for functions that should accept or return any
241242
# object that comes from an open() call. The IO[] does not
242243
# distinguish between reading, writing or other modes.
243-
def get_sys_IO(mode='w') -> IO[str]:
244+
def get_sys_IO(mode='w'):
245+
# type: (str) -> IO[str]
244246
if mode == 'w':
245247
return sys.stdout
246248
elif mode == 'r':

docs/source/command_line.rst

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,34 @@ Here are some more useful flags:
274274
re-check your code without ``--strict-optional`` to ensure new type errors
275275
are not introduced.
276276

277+
.. _disallow-any:
278+
279+
- ``--disallow-any`` disallows various types of ``Any`` in a module.
280+
The option takes a comma-separated list of the following values:
281+
``unimported``, ``unannotated``, ``expr``, ``decorated``.
282+
283+
``unimported`` disallows usage of types that come from unfollowed imports
284+
(such types become aliases for ``Any``). Unfollowed imports occur either
285+
when the imported module does not exist or when ``--follow-imports=skip``
286+
is set.
287+
288+
``unannotated`` disallows function definitions that are not fully
289+
typed (i.e. that are missing an explicit type annotation for any
290+
of the parameters or the return type). ``unannotated`` option is
291+
interchangeable with ``--disallow-untyped-defs``.
292+
293+
``expr`` disallows all expressions in the module that have type ``Any``.
294+
If an expression of type ``Any`` appears anywhere in the module
295+
mypy will output an error unless the expression is immediately
296+
used as an argument to ``cast`` or assigned to a variable with an
297+
explicit type annotation. In addition, declaring a variable of type ``Any``
298+
or casting to type ``Any`` is not allowed. Note that calling functions
299+
that take parameters of type ``Any`` is still allowed.
300+
301+
``decorated`` disallows functions that have ``Any`` in their signature
302+
after decorator transformation.
303+
304+
277305
- ``--disallow-untyped-defs`` reports an error whenever it encounters
278306
a function definition without type annotations.
279307

docs/source/config_file.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,12 @@ overridden by the pattern sections matching the module name.
147147
- ``almost_silent`` (Boolean, deprecated) equivalent to
148148
``follow_imports=skip``.
149149

150+
- ``disallow_any`` (Comma-separated list, default empty) is an option to
151+
disallow various types of ``Any`` in a module. The flag takes a
152+
comma-separated list of the following arguments: ``unimported``,
153+
``unannotated``, ``expr``. For explanations see the discussion for the
154+
:ref:`--disallow-any <disallow-any>` option.
155+
150156
- ``disallow_untyped_calls`` (Boolean, default False) disallows
151157
calling functions without type annotations from functions with type
152158
annotations.

docs/source/kinds_of_types.rst

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1153,3 +1153,192 @@ demonstrates how to work with coroutines. One version
11531153
`uses async/await <https://github.com/python/mypy/blob/master/test-data/samples/crawl2.py>`_
11541154
and one
11551155
`uses yield from <https://github.com/python/mypy/blob/master/test-data/samples/crawl.py>`_.
1156+
1157+
TypedDict
1158+
*********
1159+
1160+
Python programs often use dictionaries with string keys to represent objects.
1161+
Here is a typical example:
1162+
1163+
.. code-block:: python
1164+
1165+
movie = {'name': 'Blade Runner 5279 ', 'year': 1982}
1166+
1167+
Only a fixed set of string keys is expected (``'name'`` and
1168+
``'year'`` above), and each key has an independent value type (``str``
1169+
for ``'name'`` and ``int`` for ``'year'`` above). We've previously
1170+
seen the ``Dict[K, V]`` type, which lets you declare uniform
1171+
dictionary types, where every value has the same type, and arbitrary keys
1172+
are supported. This is clearly not a good fit for
1173+
``movie`` above. Instead, you can use a ``TypedDict`` to give a precise
1174+
type for objects like ``movie``, where the type of each
1175+
dictionary value depends on the key:
1176+
1177+
.. code-block:: python
1178+
1179+
from mypy_extensions import TypedDict
1180+
1181+
Movie = TypedDict('Movie', {'name': str, 'year': int})
1182+
1183+
movie = {'name': 'Blade Runner', 'year': 1982} # type: Movie
1184+
1185+
``Movie`` is a TypedDict type with two items: ``'name'`` (with type ``str``)
1186+
and ``'year'`` (with type ``int``). Note that we used an explicit type
1187+
annotation for the ``movie`` variable. This type annotation is
1188+
important -- without it, mypy will try to infer a regular, uniform
1189+
``Dict`` type for ``movie``, which is not what we want here.
1190+
1191+
.. note::
1192+
1193+
If you pass a TypedDict object as an argument to a function, no
1194+
type annotation is usually necessary since mypy can infer the
1195+
desired type based on the declared argument type. Also, if an
1196+
assignment target has been previously defined, and it has a
1197+
TypedDict type, mypy will treat the assigned value as a TypedDict,
1198+
not ``Dict``.
1199+
1200+
Now mypy will recognize these as valid:
1201+
1202+
.. code-block:: python
1203+
1204+
name = movie['name'] # Okay; type of name is str
1205+
year = movie['year'] # Okay; type of year is int
1206+
1207+
Mypy will detect an invalid key as an error:
1208+
1209+
.. code-block:: python
1210+
1211+
director = movie['director'] # Error: 'director' is not a valid key
1212+
1213+
Mypy will also reject a runtime-computed expression as a key, as
1214+
it can't verify that it's a valid key. You can only use string
1215+
literals as TypedDict keys.
1216+
1217+
The ``TypedDict`` type object can also act as a constructor. It
1218+
returns a normal ``dict`` object at runtime -- a ``TypedDict`` does
1219+
not define a new runtime type:
1220+
1221+
.. code-block:: python
1222+
1223+
toy_story = Movie(name='Toy Story', year=1995)
1224+
1225+
This is equivalent to just constructing a dictionary directly using
1226+
``{ ... }`` or ``dict(key=value, ...)``. The constructor form is
1227+
sometimes convenient, since it can be used without a type annotation,
1228+
and it also makes the type of the object explicit.
1229+
1230+
Like all types, TypedDicts can be used as components to build
1231+
arbitrarily complex types. For example, you can define nested
1232+
TypedDicts and containers with TypedDict items.
1233+
Unlike most other types, mypy uses structural compatibility checking
1234+
(or structural subtyping) with TypedDicts. A TypedDict object with
1235+
extra items is compatible with a narrower TypedDict, assuming item
1236+
types are compatible (*totality* also affects
1237+
subtyping, as discussed below).
1238+
1239+
.. note::
1240+
1241+
You need to install ``mypy_extensions`` using pip to use ``TypedDict``:
1242+
1243+
.. code-block:: text
1244+
1245+
python3 -m pip install --upgrade mypy-extensions
1246+
1247+
Or, if you are using Python 2:
1248+
1249+
.. code-block:: text
1250+
1251+
pip install --upgrade mypy-extensions
1252+
1253+
.. note::
1254+
1255+
TypedDict is experimental. Details of TypedDict may change in
1256+
future mypy releases.
1257+
1258+
Totality
1259+
--------
1260+
1261+
By default mypy ensures that a TypedDict object has all the specified
1262+
keys. This will be flagged as an error:
1263+
1264+
.. code-block:: python
1265+
1266+
# Error: 'year' missing
1267+
toy_story = {'name': 'Toy Story'} # type: Movie
1268+
1269+
Sometimes you want to allow keys to be left out when creating a
1270+
TypedDict object. You can provide the ``total=False`` argument to
1271+
``TypedDict(...)`` to achieve this:
1272+
1273+
.. code-block:: python
1274+
1275+
GuiOptions = TypedDict(
1276+
'GuiOptions', {'language': str, 'color': str}, total=False)
1277+
options = {} # type: GuiOptions # Okay
1278+
options['language'] = 'en'
1279+
1280+
You may need to use ``get()`` to access items of a partial (non-total)
1281+
TypedDict, since indexing using ``[]`` could fail at runtime.
1282+
However, mypy still lets use ``[]`` with a partial TypedDict -- you
1283+
just need to be careful with it, as it could result in a ``KeyError``.
1284+
Requiring ``get()`` everywhere would be too cumbersome. (Note that you
1285+
are free to use ``get()`` with total TypedDicts as well.)
1286+
1287+
Totality also affects structural compatibility. You can't use a partial
1288+
TypedDict when a total one is expected. Also, a total typed dict is not
1289+
valid when a partial one is expected.
1290+
1291+
Class-based syntax
1292+
------------------
1293+
1294+
Python 3.6 supports an alternative, class-based syntax to define a
1295+
TypedDict:
1296+
1297+
.. code-block:: python
1298+
1299+
from mypy_extensions import TypedDict
1300+
1301+
class Movie(TypedDict):
1302+
name: str
1303+
year: int
1304+
1305+
The above definition is equivalent to the original ``Movie``
1306+
definition. It doesn't actually define a real class. This syntax also
1307+
supports a form of inheritance -- subclasses can define additional
1308+
items. However, this is primarily a notational shortcut. Since mypy
1309+
uses structural compatibility with TypedDicts, inheritance is not
1310+
required for compatibility. Here is an example of inheritance:
1311+
1312+
.. code-block:: python
1313+
1314+
class Movie(TypedDict):
1315+
name: str
1316+
year: int
1317+
1318+
class BookBasedMovie(Movie):
1319+
based_on: str
1320+
1321+
Now ``BookBasedMovie`` has keys ``name``, ``year`` and ``based_on``.
1322+
1323+
Mixing required and non-required items
1324+
--------------------------------------
1325+
1326+
In addition to allowing reuse across TypedDict types, inheritance also allows
1327+
you to mix required and non-required (using ``total=False``) items
1328+
in a single TypedDict. Example:
1329+
1330+
.. code-block:: python
1331+
1332+
class MovieBase(TypedDict):
1333+
name: str
1334+
year: int
1335+
1336+
class Movie(MovieBase, total=False):
1337+
based_on: str
1338+
1339+
Now ``Movie`` has required keys ``name`` and ``year``, while ``based_on``
1340+
can be left out when constructing an object. A TypedDict with a mix of required
1341+
and non-required keys, such as ``Movie`` above, will only be compatible with
1342+
another TypedDict if all required keys in the other TypedDict are required keys in the
1343+
first TypedDict, and all non-required keys of the other TypedDict are also non-required keys
1344+
in the first TypedDict.

extensions/mypy_extensions.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,18 @@ def _dict_new(cls, *args, **kwargs):
3030

3131

3232
def _typeddict_new(cls, _typename, _fields=None, **kwargs):
33+
total = kwargs.pop('total', True)
3334
if _fields is None:
3435
_fields = kwargs
3536
elif kwargs:
3637
raise TypeError("TypedDict takes either a dict or keyword arguments,"
3738
" but not both")
38-
return _TypedDictMeta(_typename, (), {'__annotations__': dict(_fields)})
39+
return _TypedDictMeta(_typename, (), {'__annotations__': dict(_fields),
40+
'__total__': total})
3941

4042

4143
class _TypedDictMeta(type):
42-
def __new__(cls, name, bases, ns):
44+
def __new__(cls, name, bases, ns, total=True):
4345
# Create new typed dict class object.
4446
# This method is called directly when TypedDict is subclassed,
4547
# or via _typeddict_new when TypedDict is instantiated. This way
@@ -59,6 +61,8 @@ def __new__(cls, name, bases, ns):
5961
for base in bases:
6062
anns.update(base.__dict__.get('__annotations__', {}))
6163
tp_dict.__annotations__ = anns
64+
if not hasattr(tp_dict, '__total__'):
65+
tp_dict.__total__ = total
6266
return tp_dict
6367

6468
__instancecheck__ = __subclasscheck__ = _check_fails

0 commit comments

Comments
 (0)
0