Skip to content

Commit

Permalink
Delete open plugin (#9275)
Browse files Browse the repository at this point in the history
Improvements to typeshed types using literals should have rendered this
unnecessary.
  • Loading branch information
hauntsaninja authored Feb 9, 2022
1 parent 872c03d commit 0647570
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 78 deletions.
61 changes: 2 additions & 59 deletions mypy/plugins/default.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@
from typing import Callable, Optional, List

from mypy import message_registry
from mypy.nodes import Expression, StrExpr, IntExpr, DictExpr, UnaryExpr
from mypy.nodes import StrExpr, IntExpr, DictExpr, UnaryExpr
from mypy.plugin import (
Plugin, FunctionContext, MethodContext, MethodSigContext, AttributeContext, ClassDefContext,
CheckerPluginInterface,
Plugin, FunctionContext, MethodContext, MethodSigContext, AttributeContext, ClassDefContext
)
from mypy.plugins.common import try_getting_str_literals
from mypy.types import (
Expand All @@ -26,8 +25,6 @@ def get_function_hook(self, fullname: str

if fullname in ('contextlib.contextmanager', 'contextlib.asynccontextmanager'):
return contextmanager_callback
elif fullname == 'builtins.open' and self.python_version[0] == 3:
return open_callback
elif fullname == 'ctypes.Array':
return ctypes.array_constructor_callback
elif fullname == 'functools.singledispatch':
Expand Down Expand Up @@ -74,8 +71,6 @@ def get_method_hook(self, fullname: str
return ctypes.array_getitem_callback
elif fullname == 'ctypes.Array.__iter__':
return ctypes.array_iter_callback
elif fullname == 'pathlib.Path.open':
return path_open_callback
elif fullname == singledispatch.SINGLEDISPATCH_REGISTER_METHOD:
return singledispatch.singledispatch_register_callback
elif fullname == singledispatch.REGISTER_CALLABLE_CALL_METHOD:
Expand Down Expand Up @@ -129,58 +124,6 @@ def get_class_decorator_hook(self, fullname: str
return None


def open_callback(ctx: FunctionContext) -> Type:
"""Infer a better return type for 'open'."""
return _analyze_open_signature(
arg_types=ctx.arg_types,
args=ctx.args,
mode_arg_index=1,
default_return_type=ctx.default_return_type,
api=ctx.api,
)


def path_open_callback(ctx: MethodContext) -> Type:
"""Infer a better return type for 'pathlib.Path.open'."""
return _analyze_open_signature(
arg_types=ctx.arg_types,
args=ctx.args,
mode_arg_index=0,
default_return_type=ctx.default_return_type,
api=ctx.api,
)


def _analyze_open_signature(arg_types: List[List[Type]],
args: List[List[Expression]],
mode_arg_index: int,
default_return_type: Type,
api: CheckerPluginInterface,
) -> Type:
"""A helper for analyzing any function that has approximately
the same signature as the builtin 'open(...)' function.
Currently, the only thing the caller can customize is the index
of the 'mode' argument. If the mode argument is omitted or is a
string literal, we refine the return type to either 'TextIO' or
'BinaryIO' as appropriate.
"""
mode = None
if not arg_types or len(arg_types[mode_arg_index]) != 1:
mode = 'r'
else:
mode_expr = args[mode_arg_index][0]
if isinstance(mode_expr, StrExpr):
mode = mode_expr.value
if mode is not None:
assert isinstance(default_return_type, Instance) # type: ignore
if 'b' in mode:
return api.named_generic_type('typing.BinaryIO', [])
else:
return api.named_generic_type('typing.TextIO', [])
return default_return_type


def contextmanager_callback(ctx: FunctionContext) -> Type:
"""Infer a better return type for 'contextlib.contextmanager'."""
# Be defensive, just in case.
Expand Down
4 changes: 2 additions & 2 deletions mypy/report.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,10 +245,10 @@ def _write_out_report(self,
f.write(separator + '\n')
for row_values in rows:
r = ("{:>{}}" * len(widths)).format(*itertools.chain(*zip(row_values, widths)))
f.writelines(r + '\n')
f.write(r + '\n')
f.write(separator + '\n')
footer_str = ("{:>{}}" * len(widths)).format(*itertools.chain(*zip(footer, widths)))
f.writelines(footer_str + '\n')
f.write(footer_str + '\n')

def _report_any_exprs(self) -> None:
total_any = sum(num_any for num_any, _ in self.counts.values())
Expand Down
4 changes: 2 additions & 2 deletions mypyc/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -308,8 +308,8 @@ def write_file(path: str, contents: str) -> None:
old_contents = None
if old_contents != encoded_contents:
os.makedirs(os.path.dirname(path), exist_ok=True)
with open(path, 'wb') as f:
f.write(encoded_contents)
with open(path, 'wb') as g:
g.write(encoded_contents)

# Fudge the mtime forward because otherwise when two builds happen close
# together (like in a test) setuptools might not realize the source is newer
Expand Down
30 changes: 15 additions & 15 deletions test-data/unit/pythoneval.test
Original file line number Diff line number Diff line change
Expand Up @@ -271,8 +271,8 @@ f.write('x')
f.write(b'x')
f.foobar()
[out]
_program.py:3: error: Argument 1 to "write" of "IO" has incompatible type "bytes"; expected "str"
_program.py:4: error: "TextIO" has no attribute "foobar"
_program.py:3: error: Argument 1 to "write" of "TextIOBase" has incompatible type "bytes"; expected "str"
_program.py:4: error: "TextIOWrapper" has no attribute "foobar"

[case testOpenReturnTypeInference]
reveal_type(open('x'))
Expand All @@ -281,9 +281,9 @@ reveal_type(open('x', 'rb'))
mode = 'rb'
reveal_type(open('x', mode))
[out]
_program.py:1: note: Revealed type is "typing.TextIO"
_program.py:2: note: Revealed type is "typing.TextIO"
_program.py:3: note: Revealed type is "typing.BinaryIO"
_program.py:1: note: Revealed type is "io.TextIOWrapper"
_program.py:2: note: Revealed type is "io.TextIOWrapper"
_program.py:3: note: Revealed type is "io.BufferedReader"
_program.py:5: note: Revealed type is "typing.IO[Any]"

[case testOpenReturnTypeInferenceSpecialCases]
Expand All @@ -292,8 +292,8 @@ reveal_type(open(file='x', mode='rb'))
mode = 'rb'
reveal_type(open(mode=mode, file='r'))
[out]
_testOpenReturnTypeInferenceSpecialCases.py:1: note: Revealed type is "typing.BinaryIO"
_testOpenReturnTypeInferenceSpecialCases.py:2: note: Revealed type is "typing.BinaryIO"
_testOpenReturnTypeInferenceSpecialCases.py:1: note: Revealed type is "io.BufferedReader"
_testOpenReturnTypeInferenceSpecialCases.py:2: note: Revealed type is "io.BufferedReader"
_testOpenReturnTypeInferenceSpecialCases.py:4: note: Revealed type is "typing.IO[Any]"

[case testPathOpenReturnTypeInference]
Expand All @@ -305,21 +305,21 @@ reveal_type(p.open('rb'))
mode = 'rb'
reveal_type(p.open(mode))
[out]
_program.py:3: note: Revealed type is "typing.TextIO"
_program.py:4: note: Revealed type is "typing.TextIO"
_program.py:5: note: Revealed type is "typing.BinaryIO"
_program.py:3: note: Revealed type is "io.TextIOWrapper"
_program.py:4: note: Revealed type is "io.TextIOWrapper"
_program.py:5: note: Revealed type is "io.BufferedReader"
_program.py:7: note: Revealed type is "typing.IO[Any]"

[case testPathOpenReturnTypeInferenceSpecialCases]
from pathlib import Path
p = Path("x")
reveal_type(p.open(mode='rb', errors='replace'))
reveal_type(p.open(errors='replace', mode='rb'))
mode = 'rb'
reveal_type(p.open(mode='r', errors='replace'))
reveal_type(p.open(errors='replace', mode='r'))
mode = 'r'
reveal_type(p.open(mode=mode, errors='replace'))
[out]
_program.py:3: note: Revealed type is "typing.BinaryIO"
_program.py:4: note: Revealed type is "typing.BinaryIO"
_program.py:3: note: Revealed type is "io.TextIOWrapper"
_program.py:4: note: Revealed type is "io.TextIOWrapper"
_program.py:6: note: Revealed type is "typing.IO[Any]"

[case testGenericPatterns]
Expand Down

0 comments on commit 0647570

Please sign in to comment.