]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-45755: [typing] Reveal class attributes of generic in generic aliases in `dir...
authorKen Jin <28750310+Fidget-Spinner@users.noreply.github.com>
Thu, 16 Dec 2021 14:29:59 +0000 (22:29 +0800)
committerGitHub <noreply@github.com>
Thu, 16 Dec 2021 14:29:59 +0000 (22:29 +0800)
Lib/test/test_typing.py
Lib/typing.py
Misc/NEWS.d/next/Library/2021-12-07-21-55-22.bpo-45755.bRqKGa.rst [new file with mode: 0644]

index 90d6bea59f899ce84b87a1471a13d21027ebc110..a94d77d4edf4be725630349f4ab93edc1c585a29 100644 (file)
@@ -5040,6 +5040,17 @@ class SpecialAttrsTests(BaseTestCase):
             loaded = pickle.loads(s)
             self.assertIs(SpecialAttrsP, loaded)
 
+    def test_genericalias_dir(self):
+        class Foo(Generic[T]):
+            def bar(self):
+                pass
+            baz = 3
+        # The class attributes of the original class should be visible even
+        # in dir() of the GenericAlias. See bpo-45755.
+        self.assertIn('bar', dir(Foo[int]))
+        self.assertIn('baz', dir(Foo[int]))
+
+
 class AllTests(BaseTestCase):
     """Tests for __all__."""
 
index bdd19cadb471a674674897460a5b3109f93d0914..ae1dd5c2d768919c74da7fe53698ecb95e19bc74 100644 (file)
@@ -991,6 +991,9 @@ class _BaseGenericAlias(_Final, _root=True):
         raise TypeError("Subscripted generics cannot be used with"
                         " class and instance checks")
 
+    def __dir__(self):
+        return list(set(super().__dir__()
+                + [attr for attr in dir(self.__origin__) if not _is_dunder(attr)]))
 
 # Special typing constructs Union, Optional, Generic, Callable and Tuple
 # use three special attributes for internal bookkeeping of generic types:
diff --git a/Misc/NEWS.d/next/Library/2021-12-07-21-55-22.bpo-45755.bRqKGa.rst b/Misc/NEWS.d/next/Library/2021-12-07-21-55-22.bpo-45755.bRqKGa.rst
new file mode 100644 (file)
index 0000000..e5201b0
--- /dev/null
@@ -0,0 +1,3 @@
+:mod:`typing` generic aliases now reveal the class attributes of the
+original generic class when passed to ``dir()``. This was the behavior up to
+Python 3.6, but was changed in 3.7-3.9.