From 49917d576a578c8c29b8dbcbd5257c366a53d498 Mon Sep 17 00:00:00 2001 From: "Miss Islington (bot)" <31488909+miss-islington@users.noreply.github.com> Date: Tue, 15 Sep 2020 16:37:13 -0700 Subject: bpo-41780: Fix __dir__ of types.GenericAlias (GH-22262) Automerge-Triggered-By: @gvanrossum (cherry picked from commit 2e87774df1a0eaf2a1fe8cc4d958df60f7125b6e) Co-authored-by: Batuhan Taskaya --- Lib/test/test_genericalias.py | 5 +++ .../2020-09-15-23-29-49.bpo-41780.bOBUIH.rst | 2 ++ Objects/genericaliasobject.c | 39 ++++++++++++++++++++++ 3 files changed, 46 insertions(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2020-09-15-23-29-49.bpo-41780.bOBUIH.rst diff --git a/Lib/test/test_genericalias.py b/Lib/test/test_genericalias.py index 4f3798e..ec1acd4 100644 --- a/Lib/test/test_genericalias.py +++ b/Lib/test/test_genericalias.py @@ -283,6 +283,11 @@ class BaseTest(unittest.TestCase): self.assertEqual(a.__args__, (list[T], tuple[T, ...])) self.assertEqual(a.__parameters__, (T,)) + def test_dir(self): + dir_of_gen_alias = set(dir(list[int])) + self.assertTrue(dir_of_gen_alias.issuperset(dir(list))) + for generic_alias_property in ("__origin__", "__args__", "__parameters__"): + self.assertIn(generic_alias_property, dir_of_gen_alias) if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-09-15-23-29-49.bpo-41780.bOBUIH.rst b/Misc/NEWS.d/next/Core and Builtins/2020-09-15-23-29-49.bpo-41780.bOBUIH.rst new file mode 100644 index 0000000..9a7594f --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2020-09-15-23-29-49.bpo-41780.bOBUIH.rst @@ -0,0 +1,2 @@ +Fix :meth:`__dir__` of :class:`types.GenericAlias`. Patch by Batuhan +Taskaya. diff --git a/Objects/genericaliasobject.c b/Objects/genericaliasobject.c index 4d511a2..4f95216 100644 --- a/Objects/genericaliasobject.c +++ b/Objects/genericaliasobject.c @@ -487,11 +487,50 @@ ga_reduce(PyObject *self, PyObject *Py_UNUSED(ignored)) alias->origin, alias->args); } +static PyObject * +ga_dir(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + gaobject *alias = (gaobject *)self; + PyObject *dir = PyObject_Dir(alias->origin); + if (dir == NULL) { + return NULL; + } + + PyObject *dir_entry = NULL; + for (const char * const *p = attr_exceptions; ; p++) { + if (*p == NULL) { + break; + } + else { + dir_entry = PyUnicode_FromString(*p); + if (dir_entry == NULL) { + goto error; + } + int contains = PySequence_Contains(dir, dir_entry); + if (contains < 0) { + goto error; + } + if (contains == 0 && PyList_Append(dir, dir_entry) < 0) { + goto error; + } + + Py_CLEAR(dir_entry); + } + } + return dir; + +error: + Py_DECREF(dir); + Py_XDECREF(dir_entry); + return NULL; +} + static PyMethodDef ga_methods[] = { {"__mro_entries__", ga_mro_entries, METH_O}, {"__instancecheck__", ga_instancecheck, METH_O}, {"__subclasscheck__", ga_subclasscheck, METH_O}, {"__reduce__", ga_reduce, METH_NOARGS}, + {"__dir__", ga_dir, METH_NOARGS}, {0} }; -- cgit v0.12