diff --git a/mypy/checker.py b/mypy/checker.py index 2af33533a25f..f48be72c1d3d 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -1504,6 +1504,9 @@ def check_override(self, override: FunctionLike, original: FunctionLike, if original_class_or_static and not override_class_or_static: fail = True + if is_private(name): + fail = False + if fail: emitted_msg = False if (isinstance(override, CallableType) and @@ -1649,6 +1652,8 @@ def check_multiple_inheritance(self, typ: TypeInfo) -> None: # Normal checks for attribute compatibility should catch any problems elsewhere. non_overridden_attrs = base.names.keys() - typ.names.keys() for name in non_overridden_attrs: + if is_private(name): + continue for base2 in mro[i + 1:]: # We only need to check compatibility of attributes from classes not # in a subclass relationship. For subclasses, normal (single inheritance) @@ -1940,6 +1945,9 @@ def check_compatibility_all_supers(self, lvalue: RefExpr, lvalue_type: Optional[ if lvalue_node.name() == "__slots__" and base.fullname() != "builtins.object": continue + if is_private(lvalue_node.name()): + continue + base_type, base_node = self.lvalue_type_from_base(lvalue_node, base) if base_type: @@ -4396,3 +4404,8 @@ def is_subtype_no_promote(left: Type, right: Type) -> bool: def is_overlapping_types_no_promote(left: Type, right: Type) -> bool: return is_overlapping_types(left, right, ignore_promotions=True) + + +def is_private(node_name: str) -> bool: + """Check if node is private to class definition.""" + return node_name.startswith('__') and not node_name.endswith('__') diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index f40373c30211..80a52857980d 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -5899,3 +5899,34 @@ class A: class B: @dec # E: Unsupported decorated constructor type def __new__(cls, x: int) -> B: ... + +[case testIgnorePrivateAttributesTypeCheck] +class B: + __foo_: int +class C(B): + __foo_: str +[out] + +[case testIgnorePrivateMethodsTypeCheck] +class B: + def __foo_(self) -> int: ... +class C(B): + def __foo_(self) -> str: ... +[out] + +[case testCheckForPrivateMethodsWhenPublicCheck] +class B: + __foo__: int +class C(B): + __foo__: str +[out] +main:4: error: Incompatible types in assignment (expression has type "str", base class "B" defined the type as "int") + +[case testIgnorePrivateMethodsTypeCheck] +class A: + def __foo_(self) -> int: ... +class B: + def __foo_(self) -> str: ... + +class C(A, B): pass +[out]