Snapshot idea/138.1980 from git://git.jetbrains.org/idea/community.git

Change-Id: Ib567c9c152d770212a7a3db20fbf591c210920bd
diff --git a/python/testData/dotNet/whole_namespace.py b/python/testData/dotNet/whole_namespace.py
index b07fa0e..163f6df 100644
--- a/python/testData/dotNet/whole_namespace.py
+++ b/python/testData/dotNet/whole_namespace.py
@@ -2,5 +2,5 @@
 
 clr.AddReferenceByPartialName("SingleNameSpace")
 
-<caret>ingleNameSpace
+import <caret>SingleNameSpace
 print SingleNameSpace.MyClass
\ No newline at end of file
diff --git a/python/testData/formatter/reformatOfSingleElementPossible.py b/python/testData/formatter/reformatOfSingleElementPossible.py
new file mode 100644
index 0000000..d97d8ab
--- /dev/null
+++ b/python/testData/formatter/reformatOfSingleElementPossible.py
@@ -0,0 +1,2 @@
+x=[1,2,3]
+y='spam<caret>'*2
\ No newline at end of file
diff --git a/python/testData/formatter/reformatOfSingleElementPossible_after.py b/python/testData/formatter/reformatOfSingleElementPossible_after.py
new file mode 100644
index 0000000..2528c03
--- /dev/null
+++ b/python/testData/formatter/reformatOfSingleElementPossible_after.py
@@ -0,0 +1,2 @@
+x=[1,2,3]
+y = 'spam' * 2
\ No newline at end of file
diff --git a/python/testData/highlighting/unsupportedFeaturesInPython3.py b/python/testData/highlighting/unsupportedFeaturesInPython3.py
index fce5f97..5a4f399 100644
--- a/python/testData/highlighting/unsupportedFeaturesInPython3.py
+++ b/python/testData/highlighting/unsupportedFeaturesInPython3.py
@@ -18,7 +18,7 @@
 
 <error descr="Python version 3.0 does not have module __builtin__">import __builtin__</error>
 
-<error descr="Python version 3.0 does not support this syntax. Raise with no arguments can only be used in an except block">raise</error>
+<warning descr="Python version 3.0 does not support this syntax. Raise with no arguments can only be used in an except block">raise</warning>
 
 try:
     pass
diff --git a/python/testData/inspections/DefaultArgumentEmptyList.py b/python/testData/inspections/DefaultArgumentEmptyList.py
new file mode 100644
index 0000000..55748eb
--- /dev/null
+++ b/python/testData/inspections/DefaultArgumentEmptyList.py
@@ -0,0 +1 @@
+def foo(args=<warning descr="Default argument value is mutable">[<caret>]</warning>):<EOLError descr="Indent expected"></EOLError>
\ No newline at end of file
diff --git a/python/testData/inspections/DefaultArgumentEmptyList_after.py b/python/testData/inspections/DefaultArgumentEmptyList_after.py
new file mode 100644
index 0000000..2de1bb8
--- /dev/null
+++ b/python/testData/inspections/DefaultArgumentEmptyList_after.py
@@ -0,0 +1,3 @@
+def foo(args=None):
+    if not args:
+        args = []
\ No newline at end of file
diff --git a/python/testData/inspections/DefaultArgument_after.py b/python/testData/inspections/DefaultArgument_after.py
index e2036d2..8007f94 100644
--- a/python/testData/inspections/DefaultArgument_after.py
+++ b/python/testData/inspections/DefaultArgument_after.py
@@ -1,3 +1,4 @@
 def foo(args=None):
-    if not args: args = []
+    if not args:
+        args = []
     pass
\ No newline at end of file
diff --git a/python/testData/inspections/ReplacePrintComment.py b/python/testData/inspections/ReplacePrintComment.py
new file mode 100644
index 0000000..1cf3778
--- /dev/null
+++ b/python/testData/inspections/ReplacePrintComment.py
@@ -0,0 +1 @@
+<warning descr="Statement seems to have no effect and can be replaced with function call to have effect">print</warning><error descr="End of statement expected"> </error><warning descr="Statement seems to have no effect">'%s %s %s %s' % bar</warning>  # <- doesn't work either
\ No newline at end of file
diff --git a/python/testData/inspections/ReplacePrintComment_after.py b/python/testData/inspections/ReplacePrintComment_after.py
new file mode 100644
index 0000000..416deb8
--- /dev/null
+++ b/python/testData/inspections/ReplacePrintComment_after.py
@@ -0,0 +1 @@
+print('%s %s %s %s' % bar)  # <- doesn't work either
diff --git a/python/testData/inspections/ReplacePrintEnd.py b/python/testData/inspections/ReplacePrintEnd.py
new file mode 100644
index 0000000..afc37fb
--- /dev/null
+++ b/python/testData/inspections/ReplacePrintEnd.py
@@ -0,0 +1 @@
+<warning descr="Statement seems to have no effect and can be replaced with function call to have effect">print</warning><error descr="End of statement expected"> </error><warning descr="Statement seems to have no effect">var,</warning> 
\ No newline at end of file
diff --git a/python/testData/inspections/ReplacePrintEnd_after.py b/python/testData/inspections/ReplacePrintEnd_after.py
new file mode 100644
index 0000000..bae6b0c
--- /dev/null
+++ b/python/testData/inspections/ReplacePrintEnd_after.py
@@ -0,0 +1 @@
+print(var, end=' ')
diff --git a/python/testData/intentions/afterDocStubKeywordOnly.py b/python/testData/intentions/afterDocStubKeywordOnly.py
index c65f5e9..161b9c1 100644
--- a/python/testData/intentions/afterDocStubKeywordOnly.py
+++ b/python/testData/intentions/afterDocStubKeywordOnly.py
@@ -1,4 +1,4 @@
-def f(my, *, param, **args):
+def foo(my, *, param, **args):
   """
 
   :param my:
diff --git a/python/testData/intentions/afterImportToImportFrom.py b/python/testData/intentions/afterImportToImportFrom.py
new file mode 100644
index 0000000..45b576a
--- /dev/null
+++ b/python/testData/intentions/afterImportToImportFrom.py
@@ -0,0 +1,9 @@
+from __builtin__ import staticmethod, divmod
+
+quotient, rem = divmod(42, 3)
+
+// PY-11074
+class MyClass(object):
+    @staticmethod
+    def method():
+        pass
\ No newline at end of file
diff --git a/python/testData/intentions/beforeDocStubKeywordOnly.py b/python/testData/intentions/beforeDocStubKeywordOnly.py
index b87a414..d0534c4 100644
--- a/python/testData/intentions/beforeDocStubKeywordOnly.py
+++ b/python/testData/intentions/beforeDocStubKeywordOnly.py
@@ -1,2 +1,2 @@
-def f(my, <caret>*, param, **args):
+def f<caret>oo(my, *, param, **args):
   pass
\ No newline at end of file
diff --git a/python/testData/intentions/beforeImportToImportFrom.py b/python/testData/intentions/beforeImportToImportFrom.py
new file mode 100644
index 0000000..88b5894
--- /dev/null
+++ b/python/testData/intentions/beforeImportToImportFrom.py
@@ -0,0 +1,9 @@
+import __builtin<caret>__ as b
+
+quotient, rem = b.divmod(42, 3)
+
+// PY-11074
+class MyClass(object):
+    @b.staticmethod
+    def method():
+        pass
\ No newline at end of file
diff --git a/python/testData/refactoring/inlinelocal/py5832.after.py b/python/testData/refactoring/inlinelocal/py5832.after.py
index 6b78080..bde7ba3 100644
--- a/python/testData/refactoring/inlinelocal/py5832.after.py
+++ b/python/testData/refactoring/inlinelocal/py5832.after.py
@@ -1,3 +1,5 @@
 def foo(arg):
     print arg
+
+
 foo(('a', 'b'))
\ No newline at end of file
diff --git a/python/testData/refactoring/inlinelocal/referenceInParenthesis.after.py b/python/testData/refactoring/inlinelocal/referenceInParenthesis.after.py
new file mode 100644
index 0000000..67bea27
--- /dev/null
+++ b/python/testData/refactoring/inlinelocal/referenceInParenthesis.after.py
@@ -0,0 +1,3 @@
+print ('spam!' * 42)
+('spam!' * 42)
+hex('spam!' * 42)
\ No newline at end of file
diff --git a/python/testData/refactoring/inlinelocal/referenceInParenthesis.before.py b/python/testData/refactoring/inlinelocal/referenceInParenthesis.before.py
new file mode 100644
index 0000000..da3059f
--- /dev/null
+++ b/python/testData/refactoring/inlinelocal/referenceInParenthesis.before.py
@@ -0,0 +1,5 @@
+x<caret> = 'spam!' * 42
+
+print (x)
+(x)
+hex(x)
\ No newline at end of file
diff --git a/python/testData/refactoring/inlinelocal/resultExceedsRightMargin.after.py b/python/testData/refactoring/inlinelocal/resultExceedsRightMargin.after.py
new file mode 100644
index 0000000..acc61d6
--- /dev/null
+++ b/python/testData/refactoring/inlinelocal/resultExceedsRightMargin.after.py
@@ -0,0 +1,3 @@
+result = '123456789|123456789|123456789|123456789|123456789|' + \
+         '123456789|123456789|123456789|123456789|123456789|' + \
+         '123456789|123456789|123456789|123456789|123456789|'
\ No newline at end of file
diff --git a/python/testData/refactoring/inlinelocal/resultExceedsRightMargin.before.py b/python/testData/refactoring/inlinelocal/resultExceedsRightMargin.before.py
new file mode 100644
index 0000000..8910b0d
--- /dev/null
+++ b/python/testData/refactoring/inlinelocal/resultExceedsRightMargin.before.py
@@ -0,0 +1,3 @@
+s = '123456789|123456789|123456789|123456789|123456789|'
+
+result = s + s + s
\ No newline at end of file
diff --git a/python/testData/typing/typing.py b/python/testData/typing/typing.py
new file mode 100644
index 0000000..1fbd5fc
--- /dev/null
+++ b/python/testData/typing/typing.py
@@ -0,0 +1,582 @@
+"""Static type checking helpers"""
+
+from abc import ABCMeta, abstractmethod, abstractproperty
+import inspect
+import sys
+import re
+
+
+__all__ = [
+    # Type system related
+    'AbstractGeneric',
+    'AbstractGenericMeta',
+    'Any',
+    'AnyStr',
+    'Dict',
+    'Function',
+    'Generic',
+    'GenericMeta',
+    'IO',
+    'List',
+    'Match',
+    'Pattern',
+    'Protocol',
+    'Set',
+    'Tuple',
+    'Undefined',
+    'Union',
+    'cast',
+    'forwardref',
+    'overload',
+    'typevar',
+    # Protocols and abstract base classes
+    'Container',
+    'Iterable',
+    'Iterator',
+    'Sequence',
+    'Sized',
+    'AbstractSet',
+    'Mapping',
+    'BinaryIO',
+    'TextIO',
+]
+
+
+def builtinclass(cls):
+    """Mark a class as a built-in/extension class for type checking."""
+    return cls
+
+
+def ducktype(type):
+    """Return a duck type declaration decorator.
+
+    The decorator only affects type checking.
+    """
+    def decorator(cls):
+        return cls
+    return decorator
+
+
+def disjointclass(type):
+    """Return a disjoint class declaration decorator.
+
+    The decorator only affects type checking.
+    """
+    def decorator(cls):
+        return cls
+    return decorator
+
+
+class GenericMeta(type):
+    """Metaclass for generic classes that support indexing by types."""
+    
+    def __getitem__(self, args):
+        # Just ignore args; they are for compile-time checks only.
+        return self
+
+
+class Generic(metaclass=GenericMeta):
+    """Base class for generic classes."""
+
+
+class AbstractGenericMeta(ABCMeta):
+    """Metaclass for abstract generic classes that support type indexing.
+
+    This is used for both protocols and ordinary abstract classes.
+    """
+    
+    def __new__(mcls, name, bases, namespace):
+        cls = super().__new__(mcls, name, bases, namespace)
+        # 'Protocol' must be an explicit base class in order for a class to
+        # be a protocol.
+        cls._is_protocol = name == 'Protocol' or Protocol in bases
+        return cls
+    
+    def __getitem__(self, args):
+        # Just ignore args; they are for compile-time checks only.
+        return self
+
+
+class Protocol(metaclass=AbstractGenericMeta):
+    """Base class for protocol classes."""
+
+    @classmethod
+    def __subclasshook__(cls, c):
+        if not cls._is_protocol:
+            # No structural checks since this isn't a protocol.
+            return NotImplemented
+        
+        if cls is Protocol:
+            # Every class is a subclass of the empty protocol.
+            return True
+
+        # Find all attributes defined in the protocol.
+        attrs = cls._get_protocol_attrs()
+
+        for attr in attrs:
+            if not any(attr in d.__dict__ for d in c.__mro__):
+                return NotImplemented
+        return True
+
+    @classmethod
+    def _get_protocol_attrs(cls):
+        # Get all Protocol base classes.
+        protocol_bases = []
+        for c in cls.__mro__:
+            if getattr(c, '_is_protocol', False) and c.__name__ != 'Protocol':
+                protocol_bases.append(c)
+        
+        # Get attributes included in protocol.
+        attrs = set()
+        for base in protocol_bases:
+            for attr in base.__dict__.keys():
+                # Include attributes not defined in any non-protocol bases.
+                for c in cls.__mro__:
+                    if (c is not base and attr in c.__dict__ and
+                            not getattr(c, '_is_protocol', False)):
+                        break
+                else:
+                    if (not attr.startswith('_abc_') and
+                        attr != '__abstractmethods__' and
+                        attr != '_is_protocol' and
+                        attr != '__dict__' and
+                        attr != '_get_protocol_attrs' and
+                        attr != '__module__'):
+                        attrs.add(attr)
+        
+        return attrs
+
+
+class AbstractGeneric(metaclass=AbstractGenericMeta):
+    """Base class for abstract generic classes."""
+
+
+class TypeAlias:
+    """Class for defining generic aliases for library types."""
+    
+    def __init__(self, target_type):
+        self.target_type = target_type
+    
+    def __getitem__(self, typeargs):
+        return self.target_type
+
+
+Traceback = object() # TODO proper type object
+
+
+# Define aliases for built-in types that support indexing.
+List = TypeAlias(list)
+Dict = TypeAlias(dict)
+Set = TypeAlias(set)
+Tuple = TypeAlias(tuple)
+Function = TypeAlias(callable)
+Pattern = TypeAlias(type(re.compile('')))
+Match = TypeAlias(type(re.match('', '')))
+
+def union(x): return x
+
+Union = TypeAlias(union)
+
+class typevar:
+    def __init__(self, name, *, values=None):
+        self.name = name
+        self.values = values
+
+
+# Predefined type variables.
+AnyStr = typevar('AnyStr', values=(str, bytes))
+
+
+class forwardref:
+    def __init__(self, name):
+        self.name = name
+
+
+def Any(x):
+    """The Any type; can also be used to cast a value to type Any."""
+    return x
+
+def cast(type, object):
+    """Cast a value to a type.
+
+    This only affects static checking; simply return object at runtime.
+    """
+    return object
+
+
+def overload(func):
+    """Function decorator for defining overloaded functions."""
+    frame = sys._getframe(1)
+    locals = frame.f_locals
+    # See if there is a previous overload variant available.  Also verify
+    # that the existing function really is overloaded: otherwise, replace
+    # the definition.  The latter is actually important if we want to reload
+    # a library module such as genericpath with a custom one that uses
+    # overloading in the implementation.
+    if func.__name__ in locals and hasattr(locals[func.__name__], 'dispatch'):
+        orig_func = locals[func.__name__]
+        
+        def wrapper(*args, **kwargs):
+            ret, ok = orig_func.dispatch(*args, **kwargs)
+            if ok:
+                return ret
+            return func(*args, **kwargs)
+        wrapper.isoverload = True
+        wrapper.dispatch = make_dispatcher(func, orig_func.dispatch)
+        wrapper.next = orig_func
+        wrapper.__name__ = func.__name__
+        if hasattr(func, '__isabstractmethod__'):
+            # Note that we can't reliably check that abstractmethod is
+            # used consistently across overload variants, so we let a
+            # static checker do it.
+            wrapper.__isabstractmethod__ = func.__isabstractmethod__
+        return wrapper
+    else:
+        # Return the initial overload variant.
+        func.isoverload = True
+        func.dispatch = make_dispatcher(func)
+        func.next = None
+        return func
+
+
+def is_erased_type(t):
+    return t is Any or isinstance(t, typevar)
+
+
+def make_dispatcher(func, previous=None):
+    """Create argument dispatcher for an overloaded function.
+
+    Also handle chaining of multiple overload variants.
+    """
+    (args, varargs, varkw, defaults,
+     kwonlyargs, kwonlydefaults, annotations) = inspect.getfullargspec(func)
+    
+    argtypes = []
+    for arg in args:
+        ann = annotations.get(arg)
+        if isinstance(ann, forwardref):
+            ann = ann.name
+        if is_erased_type(ann):
+            ann = None
+        elif isinstance(ann, str):
+            # The annotation is a string => evaluate it lazily when the
+            # overloaded function is first called.
+            frame = sys._getframe(2)
+            t = [None]
+            ann_str = ann
+            def check(x):
+                if not t[0]:
+                    # Evaluate string in the context of the overload caller.
+                    t[0] = eval(ann_str, frame.f_globals, frame.f_locals)
+                    if is_erased_type(t[0]):
+                        # Anything goes.
+                        t[0] = object
+                if isinstance(t[0], type):
+                    return isinstance(x, t[0])
+                else:
+                    return t[0](x)
+            ann = check
+        argtypes.append(ann)
+
+    maxargs = len(argtypes)
+    minargs = maxargs
+    if defaults:
+        minargs = len(argtypes) - len(defaults)
+    
+    def dispatch(*args, **kwargs):
+        if previous:
+            ret, ok = previous(*args, **kwargs)
+            if ok:
+                return ret, ok
+
+        nargs = len(args)
+        if nargs < minargs or nargs > maxargs:
+            # Invalid argument count.
+            return None, False
+        
+        for i in range(nargs):
+            argtype = argtypes[i]
+            if argtype:
+                if isinstance(argtype, type):
+                    if not isinstance(args[i], argtype):
+                        break
+                else:
+                    if not argtype(args[i]):
+                        break
+        else:
+            return func(*args, **kwargs), True
+        return None, False
+    return dispatch
+
+
+class Undefined:
+    """Class that represents an undefined value with a specified type.
+
+    At runtime the name Undefined is bound to an instance of this
+    class.  The intent is that any operation on an Undefined object
+    raises an exception, including use in a boolean context.  Some
+    operations cannot be disallowed: Undefined can be used as an
+    operand of 'is', and it can be assigned to variables and stored in
+    containers.
+
+    'Undefined' makes it possible to declare the static type of a
+    variable even if there is no useful default value to initialize it
+    with:
+
+      from typing import Undefined
+      x = Undefined(int)
+      y = Undefined # type: int
+
+    The latter form can be used if efficiency is of utmost importance,
+    since it saves a call operation and potentially additional
+    operations needed to evaluate a type expression.  Undefined(x)
+    just evaluates to Undefined, ignoring the argument value.
+    """
+    
+    def __repr__(self):
+        return '<typing.Undefined>'
+
+    def __setattr__(self, attr, value):
+        raise AttributeError("'Undefined' object has no attribute '%s'" % attr)
+
+    def __eq__(self, other):
+        raise TypeError("'Undefined' object cannot be compared")
+
+    def __call__(self, type):
+        return self
+
+    def __bool__(self):
+        raise TypeError("'Undefined' object is not valid as a boolean")
+
+
+Undefined = Undefined()
+
+
+# Abstract classes
+
+
+T = typevar('T')
+KT = typevar('KT')
+VT = typevar('VT')
+
+
+class SupportsInt(Protocol):
+    @abstractmethod
+    def __int__(self) -> int: pass
+
+
+class SupportsFloat(Protocol):
+    @abstractmethod
+    def __float__(self) -> float: pass
+
+
+class SupportsAbs(Protocol[T]):
+    @abstractmethod
+    def __abs__(self) -> T: pass
+
+
+class SupportsRound(Protocol[T]):
+    @abstractmethod
+    def __round__(self, ndigits: int = 0) -> T: pass
+
+
+class Reversible(Protocol[T]):
+    @abstractmethod
+    def __reversed__(self) -> 'Iterator[T]': pass
+
+
+class Sized(Protocol):
+    @abstractmethod
+    def __len__(self) -> int: pass
+
+
+class Container(Protocol[T]):
+    @abstractmethod
+    def __contains__(self, x) -> bool: pass
+
+
+class Iterable(Protocol[T]):
+    @abstractmethod
+    def __iter__(self) -> 'Iterator[T]': pass
+
+
+class Iterator(Iterable[T], Protocol[T]):
+    @abstractmethod
+    def __next__(self) -> T: pass
+
+
+class Sequence(Sized, Iterable[T], Container[T], AbstractGeneric[T]):
+    @abstractmethod
+    @overload
+    def __getitem__(self, i: int) -> T: pass
+    
+    @abstractmethod
+    @overload
+    def __getitem__(self, s: slice) -> 'Sequence[T]': pass
+    
+    @abstractmethod
+    def __reversed__(self, s: slice) -> Iterator[T]: pass
+    
+    @abstractmethod
+    def index(self, x) -> int: pass
+    
+    @abstractmethod
+    def count(self, x) -> int: pass
+
+
+for t in list, tuple, str, bytes, range:
+    Sequence.register(t)
+
+
+class AbstractSet(Sized, Iterable[T], AbstractGeneric[T]):
+    @abstractmethod
+    def __contains__(self, x: object) -> bool: pass
+    @abstractmethod
+    def __and__(self, s: 'AbstractSet[T]') -> 'AbstractSet[T]': pass
+    @abstractmethod
+    def __or__(self, s: 'AbstractSet[T]') -> 'AbstractSet[T]': pass
+    @abstractmethod
+    def __sub__(self, s: 'AbstractSet[T]') -> 'AbstractSet[T]': pass
+    @abstractmethod
+    def __xor__(self, s: 'AbstractSet[T]') -> 'AbstractSet[T]': pass
+    @abstractmethod
+    def isdisjoint(self, s: 'AbstractSet[T]') -> bool: pass
+
+
+for t in set, frozenset, type({}.keys()), type({}.items()):
+    AbstractSet.register(t)
+
+
+class Mapping(Sized, Iterable[KT], AbstractGeneric[KT, VT]):
+    @abstractmethod
+    def __getitem__(self, k: KT) -> VT: pass
+    @abstractmethod
+    def __setitem__(self, k: KT, v: VT) -> None: pass
+    @abstractmethod
+    def __delitem__(self, v: KT) -> None: pass
+    @abstractmethod
+    def __contains__(self, o: object) -> bool: pass
+
+    @abstractmethod
+    def clear(self) -> None: pass
+    @abstractmethod
+    def copy(self) -> 'Mapping[KT, VT]': pass
+    @overload
+    @abstractmethod
+    def get(self, k: KT) -> VT: pass
+    @overload
+    @abstractmethod
+    def get(self, k: KT, default: VT) -> VT: pass
+    @overload
+    @abstractmethod
+    def pop(self, k: KT) -> VT: pass
+    @overload
+    @abstractmethod
+    def pop(self, k: KT, default: VT) -> VT: pass
+    @abstractmethod
+    def popitem(self) -> Tuple[KT, VT]: pass
+    @overload
+    @abstractmethod
+    def setdefault(self, k: KT) -> VT: pass
+    @overload
+    @abstractmethod
+    def setdefault(self, k: KT, default: VT) -> VT: pass
+    
+    @overload
+    @abstractmethod
+    def update(self, m: 'Mapping[KT, VT]') -> None: pass
+    @overload
+    @abstractmethod
+    def update(self, m: Iterable[Tuple[KT, VT]]) -> None: pass
+    
+    @abstractmethod
+    def keys(self) -> AbstractSet[KT]: pass
+    @abstractmethod
+    def values(self) -> AbstractSet[VT]: pass
+    @abstractmethod
+    def items(self) -> AbstractSet[Tuple[KT, VT]]: pass
+
+
+# TODO Consider more types: os.environ, etc. However, these add dependencies.
+Mapping.register(dict)
+
+
+# Note that the BinaryIO and TextIO classes must be in sync with typing module
+# stubs.
+
+
+class IO(AbstractGeneric[AnyStr]):
+    @abstractproperty
+    def mode(self) -> str: pass
+    @abstractproperty
+    def name(self) -> str: pass
+    @abstractmethod
+    def close(self) -> None: pass
+    @abstractmethod
+    def closed(self) -> bool: pass
+    @abstractmethod
+    def fileno(self) -> int: pass
+    @abstractmethod
+    def flush(self) -> None: pass
+    @abstractmethod
+    def isatty(self) -> bool: pass
+    @abstractmethod
+    def read(self, n: int = -1) -> AnyStr: pass
+    @abstractmethod
+    def readable(self) -> bool: pass
+    @abstractmethod
+    def readline(self, limit: int = -1) -> AnyStr: pass
+    @abstractmethod
+    def readlines(self, hint: int = -1) -> List[AnyStr]: pass
+    @abstractmethod
+    def seek(self, offset: int, whence: int = 0) -> int: pass
+    @abstractmethod
+    def seekable(self) -> bool: pass
+    @abstractmethod
+    def tell(self) -> int: pass
+    @abstractmethod
+    def truncate(self, size: int = None) -> int: pass
+    @abstractmethod
+    def writable(self) -> bool: pass
+    @abstractmethod
+    def write(self, s: AnyStr) -> int: pass
+    @abstractmethod
+    def writelines(self, lines: List[AnyStr]) -> None: pass
+
+    @abstractmethod
+    def __enter__(self) -> 'IO[AnyStr]': pass
+    @abstractmethod
+    def __exit__(self, type, value, traceback) -> None: pass
+
+
+class BinaryIO(IO[bytes]):
+    @overload
+    @abstractmethod
+    def write(self, s: bytes) -> int: pass
+    @overload
+    @abstractmethod
+    def write(self, s: bytearray) -> int: pass
+
+    @abstractmethod
+    def __enter__(self) -> 'BinaryIO': pass
+
+
+class TextIO(IO[str]):
+    @abstractproperty
+    def buffer(self) -> BinaryIO: pass
+    @abstractproperty
+    def encoding(self) -> str: pass
+    @abstractproperty
+    def errors(self) -> str: pass
+    @abstractproperty
+    def line_buffering(self) -> bool: pass
+    @abstractproperty
+    def newlines(self) -> Any: pass
+    @abstractmethod
+    def __enter__(self) -> 'TextIO': pass
+
+
+# TODO Register IO/TextIO/BinaryIO as the base class of file-like types.
+
+
+del t