Repository: quora/pyanalyze
Pull request #687 (2023-09-21 02:19:30)

Flip the order of the arguments to is_compatible
I realized this order makes more sense, for consistency with isinstance(). Let's change it
now before a release goes out.



Patch:
diff --git a/pyanalyze/implementation.py b/pyanalyze/implementation.py
index ba3714a..4686780 100644
--- a/pyanalyze/implementation.py
+++ b/pyanalyze/implementation.py
@@ -1455,7 +1455,7 @@ def get_default_argspecs() -> Dict[object, Signature]:
             callable=assert_is_value,
         ),
         Signature.make(
-            [SigParameter("typ"), SigParameter("value")],
+            [SigParameter("value"), SigParameter("typ")],
             return_annotation=TypedValue(bool),
             impl=_is_compatible_impl,
             callable=is_compatible,
diff --git a/pyanalyze/runtime.py b/pyanalyze/runtime.py
index 04f193b..6f1ec71 100644
--- a/pyanalyze/runtime.py
+++ b/pyanalyze/runtime.py
@@ -19,16 +19,16 @@ def _get_checker() -> "pyanalyze.checker.Checker":
 
 
 @used
-def is_compatible(typ: object, value: object) -> bool:
+def is_compatible(value: object, typ: object) -> bool:
     """Return whether ``value`` is compatible with ``type``.
 
     Examples::
 
-        >>> is_compatible(list[int], 42)
+        >>> is_compatible(42, list[int])
         False
-        >>> is_compatible(list[int], [])
+        >>> is_compatible([], list[int])
         True
-        >>> is_compatible(list[int], ["x"])
+        >>> is_compatible(["x"], list[int])
         False
 
     """
@@ -38,18 +38,18 @@ def is_compatible(typ: object, value: object) -> bool:
 
 
 @used
-def get_compatibility_error(typ: object, value: object) -> Optional[str]:
+def get_compatibility_error(value: object, typ: object) -> Optional[str]:
     """Return an error message explaining why ``value`` is not
     compatible with ``type``, or None if they are compatible.
 
     Examples::
 
-        >>> print(get_compatibility_error(list[int], 42))
+        >>> print(get_compatibility_error(42, list[int]))
         Cannot assign Literal[42] to list
 
-        >>> print(get_compatibility_error(list[int], []))
+        >>> print(get_compatibility_error([], list[int]))
         None
-        >>> print(get_compatibility_error(list[int], ["x"]))
+        >>> print(get_compatibility_error(["x"], list[int]))
         In element 0
           Cannot assign Literal['x'] to int
 


Test patch:
diff --git a/pyanalyze/test_runtime.py b/pyanalyze/test_runtime.py
index c9ca939..92c661e 100644
--- a/pyanalyze/test_runtime.py
+++ b/pyanalyze/test_runtime.py
@@ -7,22 +7,22 @@ from .test_node_visitor import assert_passes
 
 
 def test_is_compatible() -> None:
-    assert not is_compatible(List[int], 42)
-    assert is_compatible(List[int], [])
-    assert not is_compatible(List[int], ["x"])
-    assert is_compatible(List[int], [1, 2, 3])
+    assert not is_compatible(42, List[int])
+    assert is_compatible([], List[int])
+    assert not is_compatible(["x"], List[int])
+    assert is_compatible([1, 2, 3], List[int])
 
 
 def test_get_compatibility_error() -> None:
     assert (
-        get_compatibility_error(List[int], 42) == "Cannot assign Literal[42] to list\n"
+        get_compatibility_error(42, List[int]) == "Cannot assign Literal[42] to list\n"
     )
-    assert get_compatibility_error(List[int], []) is None
+    assert get_compatibility_error([], List[int]) is None
     assert (
-        get_compatibility_error(List[int], ["x"])
+        get_compatibility_error(["x"], List[int])
         == "In element 0\n  Cannot assign Literal['x'] to int\n"
     )
-    assert get_compatibility_error(List[int], [1, 2, 3]) is None
+    assert get_compatibility_error([1, 2, 3], List[int]) is None
 
 
 class TestRuntimeTypeGuard(TestNameCheckVisitorBase):
@@ -39,9 +39,9 @@ class TestRuntimeTypeGuard(TestNameCheckVisitorBase):
 
         def capybara(s: str) -> None:
             want_lowercase(s)  # E: incompatible_argument
-            if is_compatible(IsLower, s):
+            if is_compatible(s, IsLower):
                 want_lowercase(s)
 
         def asserting_capybara(s: str) -> None:
-            assert is_compatible(IsLower, s)
+            assert is_compatible(s, IsLower)
             want_lowercase(s)