Skip to content

Commit e6b91bd

Browse files
authored
Imporves __div__ with __future__ import on py2 (#11276)
1 parent d0a41a0 commit e6b91bd

File tree

4 files changed

+39
-5
lines changed

4 files changed

+39
-5
lines changed

mypy/build.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -2178,8 +2178,11 @@ def type_checker(self) -> TypeChecker:
21782178
if not self._type_checker:
21792179
assert self.tree is not None, "Internal error: must be called on parsed file only"
21802180
manager = self.manager
2181-
self._type_checker = TypeChecker(manager.errors, manager.modules, self.options,
2182-
self.tree, self.xpath, manager.plugin)
2181+
self._type_checker = TypeChecker(
2182+
manager.errors, manager.modules, self.options,
2183+
self.tree, self.xpath, manager.plugin,
2184+
self.manager.semantic_analyzer.future_import_flags,
2185+
)
21832186
return self._type_checker
21842187

21852188
def type_map(self) -> Dict[Expression, Type]:

mypy/checker.py

+7-1
Original file line numberDiff line numberDiff line change
@@ -216,8 +216,12 @@ class TypeChecker(NodeVisitor[None], CheckerPluginInterface):
216216
# functions such as open(), etc.
217217
plugin: Plugin
218218

219+
# Future flags that we get from semantic analyzer.
220+
future_import_flags: Set[str]
221+
219222
def __init__(self, errors: Errors, modules: Dict[str, MypyFile], options: Options,
220-
tree: MypyFile, path: str, plugin: Plugin) -> None:
223+
tree: MypyFile, path: str, plugin: Plugin,
224+
future_import_flags: Set[str]) -> None:
221225
"""Construct a type checker.
222226
223227
Use errors to report type check errors.
@@ -263,6 +267,8 @@ def __init__(self, errors: Errors, modules: Dict[str, MypyFile], options: Option
263267
# argument through various `checker` and `checkmember` functions.
264268
self._is_final_def = False
265269

270+
self.future_import_flags = future_import_flags
271+
266272
@property
267273
def type_context(self) -> List[Optional[Type]]:
268274
return self.expr_checker.type_context

mypy/checkexpr.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -2373,8 +2373,7 @@ def dangerous_comparison(self, left: Type, right: Type,
23732373

23742374
def get_operator_method(self, op: str) -> str:
23752375
if op == '/' and self.chk.options.python_version[0] == 2:
2376-
# TODO also check for "from __future__ import division"
2377-
return '__div__'
2376+
return '__truediv__' if 'division' in self.chk.future_import_flags else '__div__'
23782377
else:
23792378
return operators.op_methods[op]
23802379

test-data/unit/check-expressions.test

+26
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,32 @@ class C:
221221
pass
222222
[builtins fixtures/tuple.pyi]
223223

224+
[case testDivPython2]
225+
# flags: --python-version 2.7
226+
class A(object):
227+
def __div__(self, other):
228+
# type: (A, str) -> str
229+
return 'a'
230+
231+
a = A()
232+
reveal_type(a / 'b') # N: Revealed type is "builtins.str"
233+
a / 1 # E: Unsupported operand types for / ("A" and "int")
234+
[builtins fixtures/bool.pyi]
235+
236+
[case testDivPython2FutureImport]
237+
# flags: --python-version 2.7
238+
from __future__ import division
239+
240+
class A(object):
241+
def __truediv__(self, other):
242+
# type: (A, str) -> str
243+
return 'a'
244+
245+
a = A()
246+
reveal_type(a / 'b') # N: Revealed type is "builtins.str"
247+
a / 1 # E: Unsupported operand types for / ("A" and "int")
248+
[builtins fixtures/bool.pyi]
249+
224250
[case testIntDiv]
225251
a, b, c = None, None, None # type: (A, B, C)
226252
if int():

0 commit comments

Comments
 (0)