Repository: quora/pyanalyze (python)

Issue:
open() signature is not picked up from typeshed
Probably because at runtime open() pretends to be io.open.

Pull request description:
pick up open() signature from typeshed
Fixes #437

Patch:
diff --git a/docs/changelog.md b/docs/changelog.md
index c6c0460..eba61c7 100644
--- a/docs/changelog.md
+++ b/docs/changelog.md
@@ -2,6 +2,7 @@
 
 ## Unreleased
 
+- Pick up the signature of `open()` from typeshed correctly (#463)
 - Do not strip away generic parameters explicitly set to
   `Any` (#467)
 - Fix bug that led to some overloaded calls incorrectly
diff --git a/pyanalyze/typeshed.py b/pyanalyze/typeshed.py
index fbc6324..db781c0 100644
--- a/pyanalyze/typeshed.py
+++ b/pyanalyze/typeshed.py
@@ -651,6 +651,9 @@ class TypeshedFinder:
     def _get_fq_name(self, obj: Any) -> Optional[str]:
         if obj is GeneratorType:
             return "typing.Generator"
+        # It claims to be io.open, but typeshed puts it in builtins
+        if obj is open:
+            return "builtins.open"
         if IS_PRE_38:
             if obj is Sized:
                 return "typing.Sized"


Test patch:
diff --git a/pyanalyze/test_typeshed.py b/pyanalyze/test_typeshed.py
index fdc648e..7daa37b 100644
--- a/pyanalyze/test_typeshed.py
+++ b/pyanalyze/test_typeshed.py
@@ -616,3 +616,19 @@ class TestParamSpec(TestNameCheckVisitorBase):
                 GenericValue(contextlib._GeneratorContextManager, [TypedValue(str)]),
             )
             wrapped("x")  # E: incompatible_argument
+
+
+class TestOpen(TestNameCheckVisitorBase):
+    @assert_passes()
+    def test_basic(self):
+        import io
+        from typing import BinaryIO, IO, Any
+        from pyanalyze.extensions import assert_type
+
+        def capybara(buffering: int, mode: str):
+            assert_type(open("x"), io.TextIOWrapper)
+            assert_type(open("x", "r"), io.TextIOWrapper)
+            assert_type(open("x", "rb"), io.BufferedReader)
+            assert_type(open("x", "rb", buffering=0), io.FileIO)
+            assert_type(open("x", "rb", buffering=buffering), BinaryIO)
+            assert_type(open("x", mode, buffering=buffering), IO[Any])