Skip to content

Commit

Permalink
Fixed a bug in the NewType conformance test that was based on a misre… (
Browse files Browse the repository at this point in the history
#1581)

Fixed a bug in the NewType conformance test that was based on a misreading of the spec. A NewType created from another NewType should be allowed. Also fixed a minor bug in the `protocols_class_objects` test where the test depended on an unspecified aspect of the type spec.
  • Loading branch information
erictraut authored Jan 13, 2024
1 parent fb9d920 commit 2142958
Show file tree
Hide file tree
Showing 10 changed files with 35 additions and 36 deletions.
18 changes: 10 additions & 8 deletions conformance/results/mypy/aliases_newtype.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@ aliases_newtype.py:12: error: Incompatible types in assignment (expression has t
aliases_newtype.py:20: error: Cannot use isinstance() with NewType type [misc]
aliases_newtype.py:23: error: Cannot subclass "NewType" [misc]
aliases_newtype.py:32: error: String argument 1 "BadName" to NewType(...) does not match variable name "GoodName" [misc]
aliases_newtype.py:36: error: "GoodNewType1" expects no type arguments, but 1 given [type-arg]
aliases_newtype.py:42: error: Argument 2 to NewType(...) must be subclassable (got "int | str") [valid-newtype]
aliases_newtype.py:45: error: Type variable "aliases_newtype.T" is unbound [valid-type]
aliases_newtype.py:45: note: (Hint: Use "Generic[T]" or "Protocol[T]" base class to bind "T" inside a class)
aliases_newtype.py:45: note: (Hint: Use "T" in function signature to bind "T" inside a function)
aliases_newtype.py:47: error: NewType cannot be used with protocol classes [misc]
aliases_newtype.py:49: error: Argument 2 to NewType(...) must be subclassable (got "Literal[7]") [valid-newtype]
aliases_newtype.py:56: error: Argument 2 to NewType(...) must be subclassable (got "TD1") [valid-newtype]
aliases_newtype.py:38: error: "GoodNewType1" expects no type arguments, but 1 given [type-arg]
aliases_newtype.py:41: error: Cannot redefine "GoodNewType2" as a NewType [misc]
aliases_newtype.py:41: error: Name "GoodNewType2" already defined on line 36 [no-redef]
aliases_newtype.py:44: error: Argument 2 to NewType(...) must be subclassable (got "int | str") [valid-newtype]
aliases_newtype.py:47: error: Type variable "aliases_newtype.T" is unbound [valid-type]
aliases_newtype.py:47: note: (Hint: Use "Generic[T]" or "Protocol[T]" base class to bind "T" inside a class)
aliases_newtype.py:47: note: (Hint: Use "T" in function signature to bind "T" inside a function)
aliases_newtype.py:49: error: NewType cannot be used with protocol classes [misc]
aliases_newtype.py:51: error: Argument 2 to NewType(...) must be subclassable (got "Literal[7]") [valid-newtype]
aliases_newtype.py:58: error: Argument 2 to NewType(...) must be subclassable (got "TD1") [valid-newtype]
aliases_newtype.py:60: error: NewType(...) expects exactly two positional arguments [misc]
aliases_newtype.py:62: error: Argument 2 to NewType(...) must be subclassable (got "Any") [valid-newtype]
"""
7 changes: 3 additions & 4 deletions conformance/results/pyre/aliases_newtype.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,14 @@ Does not report inconsistency between name of NewType and assigned identifier na
Does not reject use of NewType with generic class with TypeVar.
Does not reject use of NewType with protocol class.
Does not reject use of NewType with TypedDict class.
Does not reject use of NewType with another NewType.
Does not reject use of NewType with Any.
"""
output = """
aliases_newtype.py:11:7 Incompatible parameter type [6]: In call `UserId.__init__`, for 1st positional argument, expected `int` but got `str`.
aliases_newtype.py:12:0 Incompatible variable type [9]: u1 is declared to have type `UserId` but is used as type `int`.
aliases_newtype.py:36:5 Invalid type parameters [24]: Non-generic type `GoodNewType1` cannot take parameters.
aliases_newtype.py:42:37 Invalid inheritance [39]: `typing.Union[int, str]` is not a valid parent class.
aliases_newtype.py:49:37 Invalid inheritance [39]: `typing_extensions.Literal[7]` is not a valid parent class.
aliases_newtype.py:38:5 Invalid type parameters [24]: Non-generic type `GoodNewType1` cannot take parameters.
aliases_newtype.py:44:37 Invalid inheritance [39]: `typing.Union[int, str]` is not a valid parent class.
aliases_newtype.py:51:37 Invalid inheritance [39]: `typing_extensions.Literal[7]` is not a valid parent class.
aliases_newtype.py:60:14 Too many arguments [19]: Call `NewType.__init__` expects 2 positional arguments, 3 were provided.
aliases_newtype.py:62:37 Invalid inheritance [39]: `typing.Any` is not a valid parent class.
"""
1 change: 0 additions & 1 deletion conformance/results/pyre/protocols_class_objects.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,5 @@ Fails to report some class objects as incompatible with a protocol.
output = """
protocols_class_objects.py:26:11 Invalid class instantiation [45]: Cannot instantiate abstract class `Proto` with abstract method `meth`.
protocols_class_objects.py:58:0 Incompatible variable type [9]: pa1 is declared to have type `ProtoA1` but is used as type `Type[ConcreteA]`.
protocols_class_objects.py:59:0 Incompatible variable type [9]: pa2 is declared to have type `ProtoA2` but is used as type `Type[ConcreteA]`.
protocols_class_objects.py:93:0 Uninitialized attribute [13]: Attribute `attr1` is declared in class `CMeta` to have type `int` but is never initialized.
"""
19 changes: 11 additions & 8 deletions conformance/results/pyright/aliases_newtype.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
conformant = "Pass"
conformant = "Partial"
notes = """
Rejects use of NewType created with another NewType.
"""
output = """
aliases_newtype.py:11:8 - error: Argument of type "Literal['user']" cannot be assigned to parameter "_x" of type "int" in function "__init__"
  "Literal['user']" is incompatible with "int" (reportGeneralTypeIssues)
Expand All @@ -8,13 +11,13 @@ aliases_newtype.py:20:16 - error: Second argument to "isinstance" must be a clas
  Class created with NewType cannot be used with instance and class checks (reportGeneralTypeIssues)
aliases_newtype.py:23:21 - error: Base class "UserId" is marked final and cannot be subclassed
aliases_newtype.py:32:1 - error: NewType must be assigned to a variable with the same name (reportGeneralTypeIssues)
aliases_newtype.py:36:19 - error: Expected no type arguments for class "GoodNewType1" (reportGeneralTypeIssues)
aliases_newtype.py:42:38 - error: Expected class as second argument to NewType
aliases_newtype.py:45:43 - error: Type variable "T" has no meaning in this context (reportGeneralTypeIssues)
aliases_newtype.py:47:38 - error: NewType cannot be used with structural type (a protocol or TypedDict class)
aliases_newtype.py:49:38 - error: NewType cannot be used with Literal type
aliases_newtype.py:56:38 - error: NewType cannot be used with structural type (a protocol or TypedDict class)
aliases_newtype.py:58:38 - error: NewType cannot be used with a class created with NewType
aliases_newtype.py:36:40 - error: NewType cannot be used with a class created with NewType
aliases_newtype.py:38:19 - error: Expected no type arguments for class "GoodNewType1" (reportGeneralTypeIssues)
aliases_newtype.py:44:38 - error: Expected class as second argument to NewType
aliases_newtype.py:47:43 - error: Type variable "T" has no meaning in this context (reportGeneralTypeIssues)
aliases_newtype.py:49:38 - error: NewType cannot be used with structural type (a protocol or TypedDict class)
aliases_newtype.py:51:38 - error: NewType cannot be used with Literal type
aliases_newtype.py:58:38 - error: NewType cannot be used with structural type (a protocol or TypedDict class)
aliases_newtype.py:60:15 - error: NewType requires two positional arguments (reportGeneralTypeIssues)
aliases_newtype.py:62:38 - error: The second argument to NewType must be a known class, not Any or Unknown (reportGeneralTypeIssues)
"""
6 changes: 0 additions & 6 deletions conformance/results/pyright/protocols_class_objects.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,6 @@ protocols_class_objects.py:58:16 - error: Expression of type "type[ConcreteA]" c
      Parameter name mismatch: "x" versus "self"
      Parameter 1: type "int" cannot be assigned to type "ConcreteA"
        "int" is incompatible with "ConcreteA" (reportGeneralTypeIssues)
protocols_class_objects.py:59:16 - error: Expression of type "type[ConcreteA]" cannot be assigned to declared type "ProtoA2"
  "type[type]" is incompatible with "type[ConcreteA]"
  "type[type]" is incompatible with "type[ConcreteA]"
  "method1" is an incompatible type
    Type "(self: ConcreteA, x: int) -> int" cannot be assigned to type "(obj: Any, x: int) -> int"
      Parameter name mismatch: "obj" versus "self" (reportGeneralTypeIssues)
protocols_class_objects.py:74:16 - error: Expression of type "type[ConcreteB]" cannot be assigned to declared type "ProtoB1"
  "prop1" is an incompatible type
    "property" is incompatible with "int" (reportGeneralTypeIssues)
Expand Down
3 changes: 1 addition & 2 deletions conformance/results/pytype/aliases_newtype.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ Does not report inconsistency between name of NewType and assigned identifier na
Does not reject use of NewType with generic class with TypeVar.
Does not reject use of NewType with protocol class.
Does not reject use of NewType with TypedDict class.
Does not reject use of NewType with another NewType.
Does not reject use of NewType with Any.
"""
output = """
Expand All @@ -16,7 +15,7 @@ File "aliases_newtype.py", line 11, in <module>: Function UserId.__init__ was ca
File "aliases_newtype.py", line 12, in <module>: Type annotation for u1 does not match type of assignment [annotation-type-mismatch]
Annotation: UserId
Assignment: int
File "aliases_newtype.py", line 36, in <module>: class GoodNewType1 is not indexable [not-indexable]
File "aliases_newtype.py", line 38, in <module>: class GoodNewType1 is not indexable [not-indexable]
('GoodNewType1' does not subclass Generic)
File "aliases_newtype.py", line 60, in <module>: Function typing.NewType expects 2 arg(s), got 3 [wrong-arg-count]
Expected: (name, tp)
Expand Down
3 changes: 3 additions & 0 deletions conformance/results/pytype/protocols_class_objects.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,7 @@ Incorrectly reports some class objects as incompatible with a protocol.
Fails to report some class objects as incompatible with a protocol.
"""
output = """
File "protocols_class_objects.py", line 50, in method1: bad return type [bad-return-type]
Expected: int
Actually returned: None
"""
2 changes: 1 addition & 1 deletion conformance/results/results.html

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions conformance/tests/aliases_newtype.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ class UserIdDerived(UserId): # Type error: subclassing not allowed

GoodName = NewType("BadName", int) # Type error: assigned name does not match

GoodNewType1 = NewType("GoodNewType1", list)
GoodNewType1 = NewType("GoodNewType1", list) # OK

GoodNewType2 = NewType("GoodNewType2", GoodNewType1) # OK

nt1: GoodNewType1[int] # Type error: NewType cannot be generic

Expand All @@ -55,8 +57,6 @@ class TD1(TypedDict):

BadNewType5 = NewType("BadNewType5", TD1) # Type error: cannot be TypedDict

BadNewType6 = NewType("BadNewType6", GoodNewType1) # Type error: cannot be NewType

BadNewType7 = NewType("BadNewType7", int, int) # Type error: too many arguments
BadNewType6 = NewType("BadNewType6", int, int) # Type error: too many arguments

BadNewType8 = NewType("BadNewType8", Any) # Type error: cannot be Any
BadNewType7 = NewType("BadNewType7", Any) # Type error: cannot be Any
2 changes: 1 addition & 1 deletion conformance/tests/protocols_class_objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def method1(self, x: int) -> int:


class ProtoA2(Protocol):
def method1(self, obj: Any, x: int) -> int:
def method1(_self, self: Any, x: int) -> int:
...


Expand Down

0 comments on commit 2142958

Please sign in to comment.