[case testNewNamedTupleOldPythonVersion]
# flags: --python-version 3.5
from typing import NamedTuple

class E(NamedTuple):  # E: NamedTuple class syntax is only supported in Python 3.6
    pass

[case testNewNamedTupleNoUnderscoreFields]
# flags: --python-version 3.6
from typing import NamedTuple

class X(NamedTuple):
    x: int
    _y: int  # E: NamedTuple field name cannot start with an underscore: _y
    _z: int  # E: NamedTuple field name cannot start with an underscore: _z

[case testNewNamedTupleAccessingAttributes]
# flags: --python-version 3.6
from typing import NamedTuple

class X(NamedTuple):
    x: int
    y: str

x: X
x.x
x.y
x.z # E: "X" has no attribute "z"

[case testNewNamedTupleAttributesAreReadOnly]
# flags: --python-version 3.6
from typing import NamedTuple

class X(NamedTuple):
    x: int

x: X
x.x = 5 # E: Property "x" defined in "X" is read-only
x.y = 5 # E: "X" has no attribute "y"

class A(X): pass
a: A
a.x = 5 # E: Property "x" defined in "X" is read-only

[case testNewNamedTupleCreateWithPositionalArguments]
# flags: --python-version 3.6
from typing import NamedTuple

class X(NamedTuple):
    x: int
    y: str

x = X(1, '2')
x.x
x.z      # E: "X" has no attribute "z"
x = X(1) # E: Too few arguments for "X"
x = X(1, '2', 3)  # E: Too many arguments for "X"

[case testNewNamedTupleShouldBeSingleBase]
# flags: --python-version 3.6
from typing import NamedTuple

class A: ...
class X(NamedTuple, A):  # E: NamedTuple should be a single base
    pass

[case testCreateNewNamedTupleWithKeywordArguments]
# flags: --python-version 3.6
from typing import NamedTuple

class X(NamedTuple):
    x: int
    y: str

x = X(x=1, y='x')
x = X(1, y='x')
x = X(x=1, z=1) # E: Unexpected keyword argument "z" for "X"
x = X(y='x') # E: Missing positional argument "x" in call to "X"

[case testNewNamedTupleCreateAndUseAsTuple]
# flags: --python-version 3.6
from typing import NamedTuple

class X(NamedTuple):
    x: int
    y: str

x = X(1, 'x')
a, b = x
a, b, c = x  # E: Need more than 2 values to unpack (3 expected)

[case testNewNamedTupleWithItemTypes]
# flags: --python-version 3.6
from typing import NamedTuple

class N(NamedTuple):
    a: int
    b: str

n = N(1, 'x')
s: str = n.a  # E: Incompatible types in assignment (expression has type "int", \
                          variable has type "str")
i: int = n.b  # E: Incompatible types in assignment (expression has type "str", \
                          variable has type "int")
x, y = n
x = y  # E: Incompatible types in assignment (expression has type "str", variable has type "int")

[case testNewNamedTupleConstructorArgumentTypes]
# flags: --python-version 3.6
from typing import NamedTuple

class N(NamedTuple):
    a: int
    b: str

n = N('x', 'x') # E: Argument 1 to "N" has incompatible type "str"; expected "int"
n = N(1, b=2)   # E: Argument "b" to "N" has incompatible type "int"; expected "str"
N(1, 'x')
N(b='x', a=1)

[case testNewNamedTupleAsBaseClass]
# flags: --python-version 3.6
from typing import NamedTuple

class N(NamedTuple):
    a: int
    b: str

class X(N):
    pass
x = X(1, 2)  # E: Argument 2 to "X" has incompatible type "int"; expected "str"
s = ''
i = 0
s = x.a  # E: Incompatible types in assignment (expression has type "int", variable has type "str")
i, s = x
s, s = x # E: Incompatible types in assignment (expression has type "int", variable has type "str")

[case testNewNamedTupleSelfTypeWithNamedTupleAsBase]
# flags: --python-version 3.6
from typing import NamedTuple

class A(NamedTuple):
    a: int
    b: str

class B(A):
    def f(self, x: int) -> None:
        self.f(self.a)
        self.f(self.b)  # E: Argument 1 to "f" of "B" has incompatible type "str"; expected "int"
        i = 0
        s = ''
        i, s = self
        i, i = self  # E: Incompatible types in assignment (expression has type "str", \
                          variable has type "int")
[out]

[case testNewNamedTupleTypeReferenceToClassDerivedFrom]
# flags: --python-version 3.6
from typing import NamedTuple

class A(NamedTuple):
    a: int
    b: str

class B(A):
    def f(self, x: 'B') -> None:
        i = 0
        s = ''
        self = x
        i, s = x
        i, s = x.a, x.b
        i, s = x.a, x.a  # E: Incompatible types in assignment (expression has type "int", \
                              variable has type "str")
        i, i = self  # E: Incompatible types in assignment (expression has type "str", \
                          variable has type "int")

[out]

[case testNewNamedTupleSubtyping]
# flags: --python-version 3.6
from typing import NamedTuple, Tuple

class A(NamedTuple):
    a: int
    b: str

class B(A): pass
a = A(1, '')
b = B(1, '')
t: Tuple[int, str]
b = a  # E: Incompatible types in assignment (expression has type "A", variable has type "B")
a = t  # E: Incompatible types in assignment (expression has type "Tuple[int, str]", variable has type "A")
b = t  # E: Incompatible types in assignment (expression has type "Tuple[int, str]", variable has type "B")
t = a
t = (1, '')
t = b
a = b

[case testNewNamedTupleSimpleTypeInference]
# flags: --python-version 3.6
from typing import NamedTuple, Tuple

class A(NamedTuple):
    a: int

l = [A(1), A(2)]
a = A(1)
a = l[0]
(i,) = l[0]
i, i = l[0]  # E: Need more than 1 value to unpack (2 expected)
l = [A(1)]
a = (1,)  # E: Incompatible types in assignment (expression has type "Tuple[int]", \
               variable has type "A")
[builtins fixtures/list.pyi]

[case testNewNamedTupleMissingClassAttribute]
# flags: --python-version 3.6
from typing import NamedTuple

class MyNamedTuple(NamedTuple):
    a: int
    b: str

MyNamedTuple.x # E: "Type[MyNamedTuple]" has no attribute "x"

[case testNewNamedTupleEmptyItems]
# flags: --python-version 3.6
from typing import NamedTuple

class A(NamedTuple):
    ...

[case testNewNamedTupleForwardRef]
# flags: --python-version 3.6
from typing import NamedTuple

class A(NamedTuple):
    b: 'B'

class B: ...

a = A(B())
a = A(1)  # E: Argument 1 to "A" has incompatible type "int"; expected "B"

[case testNewNamedTupleProperty]
# flags: --python-version 3.6
from typing import NamedTuple

class A(NamedTuple):
    a: int

class B(A):
    @property
    def b(self) -> int:
        return self.a
class C(B): pass
B(1).b
C(2).b

[builtins fixtures/property.pyi]

[case testNewNamedTupleAsDict]
# flags: --python-version 3.6
from typing import NamedTuple, Any

class X(NamedTuple):
    x: Any
    y: Any

x: X
reveal_type(x._asdict())  # E: Revealed type is 'builtins.dict[builtins.str, Any]'

[builtins fixtures/dict.pyi]

[case testNewNamedTupleReplaceTyped]
# flags: --python-version 3.6
from typing import NamedTuple

class X(NamedTuple):
    x: int
    y: str

x: X
reveal_type(x._replace())  # E: Revealed type is 'Tuple[builtins.int, builtins.str, fallback=__main__.X]'
x._replace(x=5)
x._replace(y=5)  # E: Argument "y" to "_replace" of "X" has incompatible type "int"; expected "str"

[case testNewNamedTupleFields]
# flags: --python-version 3.6
from typing import NamedTuple

class X(NamedTuple):
    x: int
    y: str

reveal_type(X._fields)  # E: Revealed type is 'Tuple[builtins.str, builtins.str]'
reveal_type(X._field_types)  # E: Revealed type is 'builtins.dict[builtins.str, Any]'
reveal_type(X._field_defaults)  # E: Revealed type is 'builtins.dict[builtins.str, Any]'
reveal_type(X.__annotations__)  # E: Revealed type is 'builtins.dict[builtins.str, Any]'

[builtins fixtures/dict.pyi]

[case testNewNamedTupleUnit]
# flags: --python-version 3.6
from typing import NamedTuple

class X(NamedTuple):
    pass

x: X = X()
x._replace()
x._fields[0]  # E: Tuple index out of range

[case testNewNamedTupleJoinNamedTuple]
# flags: --python-version 3.6
from typing import NamedTuple

class X(NamedTuple):
    x: int
    y: str
class Y(NamedTuple):
    x: int
    y: str

reveal_type([X(3, 'b'), Y(1, 'a')])  # E: Revealed type is 'builtins.list[Tuple[builtins.int, builtins.str]]'

[builtins fixtures/list.pyi]

[case testNewNamedTupleJoinTuple]
# flags: --python-version 3.6
from typing import NamedTuple

class X(NamedTuple):
    x: int
    y: str

reveal_type([(3, 'b'), X(1, 'a')])  # E: Revealed type is 'builtins.list[Tuple[builtins.int, builtins.str]]'
reveal_type([X(1, 'a'), (3, 'b')])  # E: Revealed type is 'builtins.list[Tuple[builtins.int, builtins.str]]'

[builtins fixtures/list.pyi]

[case testNewNamedTupleWithTooManyArguments]
# flags: --python-version 3.6
from typing import NamedTuple

class X(NamedTuple):
    x: int
    y = z = 2  # E: Invalid statement in NamedTuple definition; expected "field_name: field_type [= default]"
    def f(self): pass

[case testNewNamedTupleWithInvalidItems2]
# flags: --python-version 3.6
import typing

class X(typing.NamedTuple):
    x: int
    y = 1
    x.x: int
    z: str = 'z'
    aa: int

[out]
main:6: error: Invalid statement in NamedTuple definition; expected "field_name: field_type [= default]"
main:7: error: Invalid statement in NamedTuple definition; expected "field_name: field_type [= default]"
main:7: error: Type cannot be declared in assignment to non-self attribute
main:7: error: "int" has no attribute "x"
main:9: error: Non-default NamedTuple fields cannot follow default fields

[builtins fixtures/list.pyi]

[case testNewNamedTupleWithoutTypesSpecified]
# flags: --python-version 3.6
from typing import NamedTuple

class X(NamedTuple):
    x: int
    y = 2  # E: Invalid statement in NamedTuple definition; expected "field_name: field_type [= default]"

[case testTypeUsingTypeCNamedTuple]
# flags: --python-version 3.6
from typing import NamedTuple, Type

class N(NamedTuple):
    x: int
    y: str

def f(a: Type[N]):
    a()
[builtins fixtures/list.pyi]
[out]
main:8: error: Unsupported type Type["N"]

[case testNewNamedTupleWithDefaults]
# flags: --fast-parser --python-version 3.6
from typing import List, NamedTuple, Optional

class X(NamedTuple):
    x: int
    y: int = 2

reveal_type(X(1))  # E: Revealed type is 'Tuple[builtins.int, builtins.int, fallback=__main__.X]'
reveal_type(X(1, 2))  # E: Revealed type is 'Tuple[builtins.int, builtins.int, fallback=__main__.X]'

X(1, 'a')  # E: Argument 2 to "X" has incompatible type "str"; expected "int"
X(1, z=3)  # E: Unexpected keyword argument "z" for "X"

class HasNone(NamedTuple):
    x: int
    y: Optional[int] = None

reveal_type(HasNone(1))  # E: Revealed type is 'Tuple[builtins.int, Union[builtins.int, None], fallback=__main__.HasNone]'

class Parameterized(NamedTuple):
    x: int
    y: List[int] = [1] + [2]
    z: List[int] = []

reveal_type(Parameterized(1))  # E: Revealed type is 'Tuple[builtins.int, builtins.list[builtins.int], builtins.list[builtins.int], fallback=__main__.Parameterized]'
Parameterized(1, ['not an int'])  # E: List item 0 has incompatible type "str"; expected "int"

class Default:
    pass

class UserDefined(NamedTuple):
    x: Default = Default()

reveal_type(UserDefined())  # E: Revealed type is 'Tuple[__main__.Default, fallback=__main__.UserDefined]'
reveal_type(UserDefined(Default()))  # E: Revealed type is 'Tuple[__main__.Default, fallback=__main__.UserDefined]'
UserDefined(1)  # E: Argument 1 to "UserDefined" has incompatible type "int"; expected "Default"

[builtins fixtures/list.pyi]

[case testNewNamedTupleWithDefaultsStrictOptional]
# flags: --fast-parser --strict-optional --python-version 3.6
from typing import List, NamedTuple, Optional

class HasNone(NamedTuple):
    x: int
    y: Optional[int] = None

reveal_type(HasNone(1))  # E: Revealed type is 'Tuple[builtins.int, Union[builtins.int, None], fallback=__main__.HasNone]'
HasNone(None)  # E: Argument 1 to "HasNone" has incompatible type "None"; expected "int"
HasNone(1, y=None)
HasNone(1, y=2)

class CannotBeNone(NamedTuple):
    x: int
    y: int = None  # E: Incompatible types in assignment (expression has type "None", variable has type "int")

[builtins fixtures/list.pyi]

[case testNewNamedTupleWrongType]
# flags: --fast-parser --python-version 3.6
from typing import NamedTuple

class X(NamedTuple):
    x: int
    y: int = 'not an int'  # E: Incompatible types in assignment (expression has type "str", variable has type "int")

[case testNewNamedTupleErrorInDefault]
# flags: --fast-parser --python-version 3.6
from typing import NamedTuple

class X(NamedTuple):
    x: int = 1 + '1'  # E: Unsupported operand types for + ("int" and "str")

[case testNewNamedTupleInheritance]
# flags: --fast-parser --python-version 3.6
from typing import NamedTuple

class X(NamedTuple):
    x: str
    y: int = 3

class Y(X):
    def method(self) -> str:
        self.y
        return self.x

reveal_type(Y('a'))  # E: Revealed type is 'Tuple[builtins.str, builtins.int, fallback=__main__.Y]'
Y(y=1, x='1').method()

class CallsBaseInit(X):
    def __init__(self, x: str) -> None:
        super().__init__(x)

[case testNewNamedTupleWithMethods]
from typing import NamedTuple

class XMeth(NamedTuple):
    x: int
    def double(self) -> int:
        return self.x
    async def asyncdouble(self) -> int:
        return self.x

class XRepr(NamedTuple):
    x: int
    y: int = 1
    def __str__(self) -> str:
        return 'string'
    def __add__(self, other: XRepr) -> int:
        return 0

reveal_type(XMeth(1).double()) # E: Revealed type is 'builtins.int'
reveal_type(XMeth(1).asyncdouble())  # E: Revealed type is 'typing.Coroutine[Any, Any, builtins.int]'
reveal_type(XMeth(42).x)  # E: Revealed type is 'builtins.int'
reveal_type(XRepr(42).__str__())  # E: Revealed type is 'builtins.str'
reveal_type(XRepr(1, 2).__add__(XRepr(3)))  # E: Revealed type is 'builtins.int'
[typing fixtures/typing-full.pyi]

[case testNewNamedTupleOverloading]
from typing import NamedTuple, overload

class Overloader(NamedTuple):
    x: int
    @overload
    def method(self, y: str) -> str: pass
    @overload
    def method(self, y: int) -> int: pass
    def method(self, y):
        return y

reveal_type(Overloader(1).method('string'))  # E: Revealed type is 'builtins.str'
reveal_type(Overloader(1).method(1))  # E: Revealed type is 'builtins.int'
Overloader(1).method(('tuple',))  # E: No overload variant of "method" of "Overloader" matches argument type "Tuple[str]" \
                                  # N: Possible overload variants: \
                                  # N:     def method(self, y: str) -> str \
                                  # N:     def method(self, y: int) -> int

[case testNewNamedTupleMethodInheritance]
from typing import NamedTuple, TypeVar

T = TypeVar('T')

class Base(NamedTuple):
    x: int
    def copy(self: T) -> T:
        reveal_type(self)  # E: Revealed type is 'T`-1'
        return self
    def good_override(self) -> int:
        reveal_type(self)  # E: Revealed type is 'Tuple[builtins.int, fallback=__main__.Base]'
        reveal_type(self[0])  # E: Revealed type is 'builtins.int'
        self[0] = 3  # E: Unsupported target for indexed assignment
        reveal_type(self.x)  # E: Revealed type is 'builtins.int'
        self.x = 3  # E: Property "x" defined in "Base" is read-only
        self[1]  # E: Tuple index out of range
        reveal_type(self[T])  # E: Revealed type is 'builtins.int'
        return self.x
    def bad_override(self) -> int:
        return self.x

class Child(Base):
    def new_method(self) -> int:
        reveal_type(self)  # E: Revealed type is 'Tuple[builtins.int, fallback=__main__.Child]'
        reveal_type(self[0])  # E: Revealed type is 'builtins.int'
        self[0] = 3  # E: Unsupported target for indexed assignment
        reveal_type(self.x)  # E: Revealed type is 'builtins.int'
        self.x = 3  # E: Property "x" defined in "Base" is read-only
        self[1]  # E: Tuple index out of range
        return self.x
    def good_override(self) -> int:
        return 0
    def bad_override(self) -> str:  # E: Return type of "bad_override" incompatible with supertype "Base"
        return 'incompatible'

def takes_base(base: Base) -> int:
    return base.x

reveal_type(Base(1).copy())  # E: Revealed type is 'Tuple[builtins.int, fallback=__main__.Base]'
reveal_type(Child(1).copy())  # E: Revealed type is 'Tuple[builtins.int, fallback=__main__.Child]'
reveal_type(Base(1).good_override())  # E: Revealed type is 'builtins.int'
reveal_type(Child(1).good_override())  # E: Revealed type is 'builtins.int'
reveal_type(Base(1).bad_override())  # E: Revealed type is 'builtins.int'
reveal_type(takes_base(Base(1)))  # E: Revealed type is 'builtins.int'
reveal_type(takes_base(Child(1)))  # E: Revealed type is 'builtins.int'
[builtins fixtures/tuple.pyi]

[case testNewNamedTupleIllegalNames]
from typing import Callable, NamedTuple

class XMethBad(NamedTuple):
    x: int
    def _fields(self):  # E: Cannot overwrite NamedTuple attribute "_fields"
        return 'no chance for this'

class MagicalFields(NamedTuple):
    x: int
    def __slots__(self) -> None: pass  # E: Cannot overwrite NamedTuple attribute "__slots__"
    def __new__(cls) -> None: pass  # E: Cannot overwrite NamedTuple attribute "__new__"
    def _source(self) -> int: pass  # E: Cannot overwrite NamedTuple attribute "_source"
    __annotations__ = {'x': float}  # E: NamedTuple field name cannot start with an underscore: __annotations__ \
        # E: Invalid statement in NamedTuple definition; expected "field_name: field_type [= default]" \
        # E: Cannot overwrite NamedTuple attribute "__annotations__"

class AnnotationsAsAMethod(NamedTuple):
    x: int
    # This fails at runtime because typing.py assumes that __annotations__ is a dictionary.
    def __annotations__(self) -> float:  # E: Cannot overwrite NamedTuple attribute "__annotations__"
        return 1.0

class ReuseNames(NamedTuple):
    x: int
    def x(self) -> str:  # E: Name 'x' already defined on line 22
        return ''

    def y(self) -> int:
        return 0
    y: str  # E: Name 'y' already defined on line 26

class ReuseCallableNamed(NamedTuple):
    z: Callable[[ReuseNames], int]
    def z(self) -> int:  # E: Name 'z' already defined on line 31
        return 0

[builtins fixtures/dict.pyi]

[case testNewNamedTupleDocString]
from typing import NamedTuple

class Documented(NamedTuple):
    """This is a docstring."""
    x: int

reveal_type(Documented.__doc__)  # E: Revealed type is 'builtins.str'
reveal_type(Documented(1).x)  # E: Revealed type is 'builtins.int'

class BadDoc(NamedTuple):
    x: int
    def __doc__(self) -> str:
        return ''

reveal_type(BadDoc(1).__doc__())  # E: Revealed type is 'builtins.str'

[case testNewNamedTupleClassMethod]
from typing import NamedTuple

class HasClassMethod(NamedTuple):
    x: str

    @classmethod
    def new(cls, f: str) -> 'HasClassMethod':
        reveal_type(cls)  # E: Revealed type is 'def (x: builtins.str) -> Tuple[builtins.str, fallback=__main__.HasClassMethod]'
        reveal_type(HasClassMethod)  # E: Revealed type is 'def (x: builtins.str) -> Tuple[builtins.str, fallback=__main__.HasClassMethod]'
        return cls(x=f)

[builtins fixtures/classmethod.pyi]

[case testNewNamedTupleStaticMethod]
from typing import NamedTuple

class HasStaticMethod(NamedTuple):
    x: str

    @staticmethod
    def new(f: str) -> 'HasStaticMethod':
        return HasStaticMethod(x=f)

[builtins fixtures/classmethod.pyi]

[case testNewNamedTupleProperty]
from typing import NamedTuple

class HasStaticMethod(NamedTuple):
    x: str

    @property
    def size(self) -> int:
        reveal_type(self)  # E: Revealed type is 'Tuple[builtins.str, fallback=__main__.HasStaticMethod]'
        return 4

[builtins fixtures/property.pyi]
