diff --git a/mypy/options.py b/mypy/options.py index 38072b821d15..479979bdaa60 100644 --- a/mypy/options.py +++ b/mypy/options.py @@ -2,6 +2,7 @@ import re import pprint import sys +import platform from typing_extensions import Final from typing import Dict, List, Mapping, Optional, Pattern, Set, Tuple, Callable, Any @@ -71,6 +72,7 @@ def __init__(self) -> None: # then mypy does not search for PEP 561 packages. self.python_executable = sys.executable # type: Optional[str] self.platform = sys.platform + self.platform_system = platform.system() self.custom_typing_module = None # type: Optional[str] self.custom_typeshed_dir = None # type: Optional[str] self.mypy_path = [] # type: List[str] diff --git a/mypy/reachability.py b/mypy/reachability.py index 5ee813dc982c..52011c5be498 100644 --- a/mypy/reachability.py +++ b/mypy/reachability.py @@ -1,5 +1,4 @@ """Utilities related to determining the reachability of code (in semantic analysis).""" - from typing import Tuple, TypeVar, Union, Optional from typing_extensions import Final @@ -92,7 +91,7 @@ def infer_condition_value(expr: Expression, options: Options) -> int: else: result = consider_sys_version_info(expr, pyversion) if result == TRUTH_VALUE_UNKNOWN: - result = consider_sys_platform(expr, options.platform) + result = consider_sys_platform(expr, options.platform,options.platform_system) if result == TRUTH_VALUE_UNKNOWN: if name == 'PY2': result = ALWAYS_TRUE if pyversion[0] == 2 else ALWAYS_FALSE @@ -150,8 +149,8 @@ def consider_sys_version_info(expr: Expression, pyversion: Tuple[int, ...]) -> i return TRUTH_VALUE_UNKNOWN -def consider_sys_platform(expr: Expression, platform: str) -> int: - """Consider whether expr is a comparison involving sys.platform. +def consider_sys_platform(expr: Expression, platform: str, platform_system: str) -> int: + """Consider whether expr is a comparison involving sys.platform and platform.system() Return ALWAYS_TRUE, ALWAYS_FALSE, or TRUTH_VALUE_UNKNOWN. """ @@ -166,9 +165,14 @@ def consider_sys_platform(expr: Expression, platform: str) -> int: op = expr.operators[0] if op not in ('==', '!='): return TRUTH_VALUE_UNKNOWN - if not is_sys_attr(expr.operands[0], 'platform'): - return TRUTH_VALUE_UNKNOWN - right = expr.operands[1] + # check if either platform or platform_system is being used + if platform_system: + if not is_platform_attr(expr.operands[0], 'platform_system'): + return TRUTH_VALUE_UNKNOWN + elif platform: + if not is_sys_attr(expr.operands[0], 'platform'): + return TRUTH_VALUE_UNKNOWN + right = expr.operands[1] if not isinstance(right, (StrExpr, UnicodeExpr)): return TRUTH_VALUE_UNKNOWN return fixed_comparison(platform, op, right.value) @@ -261,6 +265,16 @@ def is_sys_attr(expr: Expression, name: str) -> bool: return False +def is_platform_attr(expr: Expression, name: str) -> bool: + # Platform lib calls methods, it differs from sys lib + # sys.platform is of str class and platform.system is of + # function class + if isinstance(expr, MemberExpr) and expr.name == name: + if isinstance(expr.expr, CallExpr) and expr.expr.name == 'platform': + return True + return False + + def mark_block_unreachable(block: Block) -> None: block.is_unreachable = True block.accept(MarkImportsUnreachableVisitor()) diff --git a/test-data/unit/check-unreachable-code.test b/test-data/unit/check-unreachable-code.test index 262ac86e49ad..c18fb12527df 100644 --- a/test-data/unit/check-unreachable-code.test +++ b/test-data/unit/check-unreachable-code.test @@ -302,6 +302,8 @@ else: import sys if sys.platform == 'fictional': def foo() -> int: return 0 +if platform.system() == 'fake': + def foo() -> int: return 0 else: def foo() -> str: return '' foo() + ''