Skip to content

Commit d00fa42

Browse files
authored
Merge branch 'master' into 2022-11-14-mypy_primer_per_project_limit
2 parents bebf0ad + dd0503e commit d00fa42

Some content is hidden

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

79 files changed

+1101
-523
lines changed

docs/source/command_line.rst

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -448,9 +448,10 @@ potentially problematic or redundant in some way.
448448
are when:
449449

450450
- The function has a ``None`` or ``Any`` return type
451-
- The function has an empty body or a body that is just
452-
ellipsis (``...``). Empty functions are often used for
453-
abstract methods.
451+
- The function has an empty body and is marked as an abstract method,
452+
is in a protocol class, or is in a stub file
453+
- The execution path can never return; for example, if an exception
454+
is always raised
454455

455456
Passing in :option:`--no-warn-no-return` will disable these error
456457
messages in all cases.

docs/source/error_code_list2.rst

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -250,31 +250,29 @@ since unless implemented by a sub-type, the expression will always evaluate to t
250250
if foo:
251251
...
252252
253+
The check is similar in concept to ensuring that an expression's type implements an expected interface (e.g. ``Sized``),
254+
except that attempting to invoke an undefined method (e.g. ``__len__``) results in an error,
255+
while attempting to evaluate an object in boolean context without a concrete implementation results in a truthy value.
253256

254-
This check might falsely imply an error. For example, ``Iterable`` does not implement
255-
``__len__`` and so this code will be flagged:
256257

257-
.. code-block:: python
258+
Check that iterable is not implicitly true in boolean context [truthy-iterable]
259+
-------------------------------------------------------------------------------
258260

259-
# Use "mypy -enable-error-code truthy-bool ..."
261+
``Iterable`` does not implement ``__len__`` and so this code will be flagged:
262+
263+
.. code-block:: python
260264
261265
from typing import Iterable
262266
263-
def transform(items: Iterable[int]) -> Iterable[int]:
264-
# Error: "items" has type "Iterable[int]" which does not implement __bool__ or __len__ so it could always be true in boolean context [truthy-bool]
267+
def transform(items: Iterable[int]) -> list[int]:
268+
# Error: "items" has type "Iterable[int]" which can always be true in boolean context. Consider using "Collection[int]" instead. [truthy-iterable]
265269
if not items:
266270
return [42]
267271
return [x + 1 for x in items]
268272
269-
270-
271-
If called as ``transform((int(s) for s in []))``, this function would not return ``[42]`` unlike what the author
272-
might have intended. Of course it's possible that ``transform`` is only passed ``list`` objects, and so there is
273-
no error in practice. In such case, it might be prudent to annotate ``items: Sequence[int]``.
274-
275-
This is similar in concept to ensuring that an expression's type implements an expected interface (e.g. ``Sized``),
276-
except that attempting to invoke an undefined method (e.g. ``__len__``) results in an error,
277-
while attempting to evaluate an object in boolean context without a concrete implementation results in a truthy value.
273+
If called with a ``Generator`` like ``int(x) for x in []``, this function would not return ``[42]`` unlike
274+
what the author might have intended. Of course it's possible that ``transform`` is only passed ``list`` objects,
275+
and so there is no error in practice. In such case, it is recommended to annotate ``items: Collection[int]``.
278276

279277

280278
Check that function isn't used in boolean context [truthy-function]

misc/fix_annotate.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -213,8 +213,7 @@ def has_return_exprs(self, node):
213213
results = {}
214214
if self.return_expr.match(node, results):
215215
return True
216-
for child in node.children:
217-
if child.type not in (syms.funcdef, syms.classdef):
218-
if self.has_return_exprs(child):
219-
return True
220-
return False
216+
return any(
217+
child.type not in (syms.funcdef, syms.classdef) and self.has_return_exprs(child)
218+
for child in node.children
219+
)

misc/upload-pypi.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,21 @@ def is_whl_or_tar(name: str) -> bool:
2929
return name.endswith(".tar.gz") or name.endswith(".whl")
3030

3131

32+
def item_ok_for_pypi(name: str) -> bool:
33+
if not is_whl_or_tar(name):
34+
return False
35+
36+
if name.endswith(".tar.gz"):
37+
name = name[:-7]
38+
if name.endswith(".whl"):
39+
name = name[:-4]
40+
41+
if name.endswith("wasm32"):
42+
return False
43+
44+
return True
45+
46+
3247
def get_release_for_tag(tag: str) -> dict[str, Any]:
3348
with urlopen(f"{BASE}/{REPO}/releases/tags/{tag}") as f:
3449
data = json.load(f)
@@ -75,7 +90,7 @@ def check_sdist(dist: Path, version: str) -> None:
7590

7691

7792
def spot_check_dist(dist: Path, version: str) -> None:
78-
items = [item for item in dist.iterdir() if is_whl_or_tar(item.name)]
93+
items = [item for item in dist.iterdir() if item_ok_for_pypi(item.name)]
7994
assert len(items) > 10
8095
assert all(version in item.name for item in items)
8196
assert any(item.name.endswith("py3-none-any.whl") for item in items)
@@ -93,7 +108,7 @@ def tmp_twine() -> Iterator[Path]:
93108

94109
def upload_dist(dist: Path, dry_run: bool = True) -> None:
95110
with tmp_twine() as twine:
96-
files = [item for item in dist.iterdir() if is_whl_or_tar(item.name)]
111+
files = [item for item in dist.iterdir() if item_ok_for_pypi(item.name)]
97112
cmd: list[Any] = [twine, "upload"]
98113
cmd += files
99114
if dry_run:

mypy/build.py

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1940,7 +1940,7 @@ def __init__(
19401940
raise
19411941
if follow_imports == "silent":
19421942
self.ignore_all = True
1943-
elif path and is_silent_import_module(manager, path):
1943+
elif path and is_silent_import_module(manager, path) and not root_source:
19441944
self.ignore_all = True
19451945
self.path = path
19461946
if path:
@@ -2629,7 +2629,7 @@ def find_module_and_diagnose(
26292629
else:
26302630
skipping_module(manager, caller_line, caller_state, id, result)
26312631
raise ModuleNotFound
2632-
if is_silent_import_module(manager, result):
2632+
if is_silent_import_module(manager, result) and not root_source:
26332633
follow_imports = "silent"
26342634
return (result, follow_imports)
26352635
else:
@@ -2728,11 +2728,8 @@ def in_partial_package(id: str, manager: BuildManager) -> bool:
27282728
else:
27292729
parent_mod = parent_st.tree
27302730
if parent_mod is not None:
2731-
if parent_mod.is_partial_stub_package:
2732-
return True
2733-
else:
2734-
# Bail out soon, complete subpackage found
2735-
return False
2731+
# Bail out soon, complete subpackage found
2732+
return parent_mod.is_partial_stub_package
27362733
id = parent
27372734
return False
27382735

@@ -3024,7 +3021,11 @@ def load_graph(
30243021
for bs in sources:
30253022
try:
30263023
st = State(
3027-
id=bs.module, path=bs.path, source=bs.text, manager=manager, root_source=True
3024+
id=bs.module,
3025+
path=bs.path,
3026+
source=bs.text,
3027+
manager=manager,
3028+
root_source=not bs.followed,
30283029
)
30293030
except ModuleNotFound:
30303031
continue
@@ -3576,9 +3577,10 @@ def record_missing_stub_packages(cache_dir: str, missing_stub_packages: set[str]
35763577

35773578

35783579
def is_silent_import_module(manager: BuildManager, path: str) -> bool:
3579-
if not manager.options.no_silence_site_packages:
3580-
for dir in manager.search_paths.package_path + manager.search_paths.typeshed_path:
3581-
if is_sub_path(path, dir):
3582-
# Silence errors in site-package dirs and typeshed
3583-
return True
3584-
return False
3580+
if manager.options.no_silence_site_packages:
3581+
return False
3582+
# Silence errors in site-package dirs and typeshed
3583+
return any(
3584+
is_sub_path(path, dir)
3585+
for dir in manager.search_paths.package_path + manager.search_paths.typeshed_path
3586+
)

0 commit comments

Comments
 (0)