8000 Add option to selectively disable --disallow-untyped-calls by ilevkivskyi · Pull Request #15845 · python/mypy · GitHub
[go: up one dir, main page]

Skip to content

Add option to selectively disable --disallow-untyped-calls #15845

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Aug 13, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Address CR
  • Loading branch information
Ivan Levkivskyi committed Aug 11, 2023
commit 8055516d2a1d13d86a962d5abf4d84944e204c09
29 changes: 11 additions & 18 deletions docs/source/command_line.rst
Original file line number Diff line number Diff line change
Expand Up @@ -354,36 +354,29 @@ definitions or calls.

This flag allows to selectively disable :option:`--disallow-untyped-calls`
for functions and methods defined in specific packages, modules, or classes.
Note that each exception entry acts as a prefix. For example:
Note that each exception entry acts as a prefix. For example (assuming there
are no type annotations for ``numpy`` available):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Numpy's probably not a great example here, as they ship with a py.typed file these days and have pretty complete type annotations. Maybe one of matplotlib, requests or TensorFlow might be a better example? Third-party stubs exist for all three packages, but none of them ships with a py.typed file

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any example of a popular library might become a bad example over time, maybe limit ourselves to something generic like third_party_lib?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, let's use some generic name.


.. code-block:: python

# mypy --disallow-untyped-calls --untyped-call-exception=foo --untyped-call-exception=bar.A
from foo import test_foo
from bar import A, B
from baz import test_baz
# mypy --disallow-untyped-calls
# --untyped-call-exception=numpy.random
# --untyped-call-exception=foo.A
import numpy as np
from foo import A, B

test_foo(42) # OK, function comes from module `foo`
test_baz(42) # E: Call to untyped function "test_baz" in typed context
np.random.gamma(1.0) # OK, function comes from package `numpy.random`
np.fft.fft([1, 2, 3]) # E: Call to untyped function "fft" in typed context

a: A
b: B
a.meth() # OK, method was defined in class `bar.A`
b.meth() # E: Call to untyped function "meth" in typed context
A().meth() # OK, method was defined in class `bar.A`
B().meth() # E: Call to untyped function "meth" in typed context

# file foo.py
def test_foo(x): pass

# file bar.py
class A:
def meth(self): pass
class B:
def meth(self): pass

# file baz.py
def test_baz(x): pass


.. option:: --disallow-untyped-defs

This flag reports an error whenever it encounters a function definition
Expand Down
5 changes: 3 additions & 2 deletions docs/source/config_file.rst
Original file line number Diff line number Diff line change
Expand Up @@ -519,8 +519,9 @@ section of the command line docs.

Selectively excludes functions and methods defined in specific packages,
modules, and classes from action of :confval:`disallow_untyped_calls`.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mention that this also applies to submodules of packages (i.e. everything inside that prefix).

Note, this option does not support per-file configuration, the exception
list is defined globally for all your code.
This also applies to all submodules of packages (i.e. everything inside
a given prefix). Note, this option does not support per-file configuration,
the exception list is defined globally for all your code.

.. confval:: disallow_untyped_defs

Expand Down
3 changes: 2 additions & 1 deletion mypy/checkexpr.py
Original file line number Diff line number Diff line change
Expand Up @@ -565,7 +565,8 @@ def visit_call_expr_inner(self, e: CallExpr, allow_none_return: bool = False) ->
assert object_type is not None
fullname = self.method_fullname(object_type, member)
if not fullname or not any(
fullname.startswith(p) for p in self.chk.options.untyped_call_exception
fullname == p or fullname.startswith(f"{p}.")
for p in self.chk.options.untyped_call_exception
):
self.msg.untyped_function_call(callee_type, e)

Expand Down
4 changes: 4 additions & 0 deletions test-data/unit/check-flags.test
Original file line number Diff line number Diff line change
Expand Up @@ -2082,16 +2082,20 @@ f(reveal_type(y)) # E: Call to untyped function "f" in typed context \
from foo import test_foo
from bar import A, B
from baz import test_baz
from foobar import bad

test_foo(42) # OK
test_baz(42) # E: Call to untyped function "test_baz" in typed context
bad(42) # E: Call to untyped function "bad" in typed context

a: A
b: B
a.meth() # OK
b.meth() # E: Call to untyped function "meth" in typed context
[file foo.py]
def test_foo(x): pass
[file foobar.py]
def bad(x): pass
[file bar.py]
class A:
def meth(self): pass
Expand Down
0