[issue43918] anext builtin docstring has no signature text or info about default argument
New submission from Erik Welch : The new builtin `anext` does not have a signature (from `inspect.signature(anext)`). This is expected, because `inspect` does not yet support signatures with C NULL default value. However, `anext` also doesn't have text in its docstring that describes its signature as is typical for builtins. This means `help(anext)` in the Python REPL gives no indication how to call the function. It should. This is clearly an oversight. See comment here: https://github.com/python/cpython/pull/23847#commitcomment-45318696 Also, the "default" argument is not described in the docstring. Related issue: https://bugs.python.org/issue31861 (PR forthcoming) -- components: Interpreter Core messages: 391650 nosy: eriknw, pablogsal priority: normal severity: normal status: open title: anext builtin docstring has no signature text or info about default argument type: enhancement versions: Python 3.10 ___ Python tracker <https://bugs.python.org/issue43918> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue43918] anext builtin docstring has no signature text or info about default argument
Change by Erik Welch : -- keywords: +patch pull_requests: +24271 stage: -> patch review pull_request: https://github.com/python/cpython/pull/25551 ___ Python tracker <https://bugs.python.org/issue43918> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue43918] anext builtin docstring has no signature text or info about default argument
Erik Welch added the comment: Thanks for taking a look Terry. I saw that error as well. It is separate from this issue, and I don't think it is a bug. No other builtin functions or methods that raise this error with this text have such a notice in their docstring, so it doesn't seem appropriate to me to add it to the docstring at this point in time. Search for "" to find other functions and methods that have the same issue. `dict.pop` is one such example. `inspect.signature(anext)` and `inspect.signature(next)` both raise ValueError. The text for `next` is what one may hope to see (and why you raise a fair point): `"ValueError: no signature found for builtin "`. The difference between `anext` and `next` in this regard is that `anext` uses the argument clinic. It is the argument clinic that converts `NULL` to `""` in the signature text that inspect tries (and fails) to parse to get the AST of. I actually did poke around a bit at having the the Argument Clinic and `inspect` module more intelligently pick up this case to give a better error. I think this is doable, but should not be part of this bug report. -- ___ Python tracker <https://bugs.python.org/issue43918> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue42073] classmethod does not pass "type/owner" when invoking wrapped __get__
New submission from Erik Welch : The following is new to Python 3.9, and I consider the implementation incomplete. I have code that works for Python 3.8 and before, but not for Python 3.9: "Class methods can now wrap other :term:`descriptors ` such as :func:`property`." https://github.com/python/cpython/pull/8405 https://bugs.python.org/issue19072 As implemented, `classmethod` does not correctly wrap descriptors that mimic classmethod. Previously, __get__of wrapped objects wasn't invoked by classmethod, so it was safe to have an object with both __call__ and __get__ behave like a classmethod. Now, classmethod calling __get__ first gives incorrect results. Here is a minimal example: ``` from types import MethodType class myclassmethod: def __init__(self, func): self.func = func def __call__(self, cls): return self.func(cls) def __get__(self, instance, owner=None): if owner is None: owner = type(instance) return MethodType(self, owner) class A: @myclassmethod def f1(cls): return cls @classmethod @myclassmethod def f2(cls): return cls assert A.f1() is A assert A.f2() is A # <-- fails in 3.9, works in 3.8 and before ``` This pattern would typically be used to do something extra in __call__. For the sake of discussion, let's call the two arguments to __get__ "instance" and "owner". Typically, "instance" is an instance of "owner", or, equivalently, "owner" is the type of "instance". If "owner" is None, it is generally assumed to be the type of "instance". In bpo19072 (and gh8405), classmethod was changed to call `obj.__get__(owner)` if the wrapped object "obj" has __get__. Notice that only the "instance" argument is provided. Moreover, the type `owner` is passed as the "instance" argument. This means that the "owner" argument (which is None) will be assumed to be the type of the "instance" argument, which is the type of the `owner` type. This is wrong. The "owner" argument should be `owner`. I believe it would be better for classmethod to call `obj.__get__(owner, owner)` if "obj" has __get__. This is kind of difficult to explain. I will make a PR with more informative tests shortly. Here is the simple diff to make the above example pass: ``` diff --git a/Objects/funcobject.c b/Objects/funcobject.c index bd24f67b97..74f9167566 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -739,7 +739,7 @@ cm_descr_get(PyObject *self, PyObject *obj, PyObject *type) type = (PyObject *)(Py_TYPE(obj)); if (Py_TYPE(cm->cm_callable)->tp_descr_get != NULL) { return Py_TYPE(cm->cm_callable)->tp_descr_get(cm->cm_callable, type, - NULL); + type); } return PyMethod_New(cm->cm_callable, type); } ``` Since I consider the new behavior to have introduced a regression, I think this change should be applied to both 3.9 and 3.10. Cheers! -- components: Interpreter Core messages: 378893 nosy: berker.peksag, eriknw, rhettinger, serhiy.storchaka priority: normal severity: normal status: open title: classmethod does not pass "type/owner" when invoking wrapped __get__ type: behavior versions: Python 3.10, Python 3.9 ___ Python tracker <https://bugs.python.org/issue42073> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue42073] classmethod does not pass "type/owner" when invoking wrapped __get__
Change by Erik Welch : -- keywords: +patch pull_requests: +21720 stage: -> patch review pull_request: https://github.com/python/cpython/pull/22757 ___ Python tracker <https://bugs.python.org/issue42073> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue19072] classmethod doesn't honour descriptor protocol of wrapped callable
Change by Erik Welch : -- nosy: +eriknw nosy_count: 8.0 -> 9.0 pull_requests: +21721 pull_request: https://github.com/python/cpython/pull/22757 ___ Python tracker <https://bugs.python.org/issue19072> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue26729] Incorrect __text_signature__ for sorted
New submission from Erik Welch: The first argument to sorted is positional-only, so the text signature should be: sorted($module, iterable, /, key=None, reverse=False) instead of sorted($module, iterable, key=None, reverse=False) To reproduce the issue, attempt to use "iterable" as a keyword argument: >>> import inspect >>> sig = inspect.signature(sorted) >>> sig.bind(iterable=[]) # should raise, but doesn't >>> sorted(iterable=[]) # raises TypeError -- components: Extension Modules, Library (Lib) files: sorted_1.diff keywords: patch messages: 263145 nosy: eriknw priority: normal severity: normal status: open title: Incorrect __text_signature__ for sorted type: behavior versions: Python 3.5 Added file: http://bugs.python.org/file42422/sorted_1.diff ___ Python tracker <http://bugs.python.org/issue26729> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue26729] Incorrect __text_signature__ for sorted
Erik Welch added the comment: Interesting observation, Martin. Upon further consideration, the call signature for sorted really is quite odd. It doesn't behave like any other builtin function. Currently, "iterable" is positional-only, and "key=" and "reverse=" are keyword only. I would only expect such behavior for functions with variadic *args. I uploaded a new patch so that the call signature matches the original __text_signature__. This means "iterable" may be given as a keyword argument, and "key" and "reverse" may be given as positional arguments. I added tests for the new behavior, and all tests pass for me. -- Added file: http://bugs.python.org/file42441/sorted_2.patch ___ Python tracker <http://bugs.python.org/issue26729> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue26729] Incorrect __text_signature__ for sorted
Erik Welch added the comment: That's a fair and valid point, Raymond. "sorted_2.patch" was submitted for consideration. Either __text_signature__ is wrong, or the call argument handling is wrong. One should be fixed. Having a flexible call signature as if sorted were a user-defined function, such as "def sorted(iterable, key=None, reverse=False):", does allow for programmatic use of the introspected signature. Here, using "iterable=" as a keyword can be convenient. "sorted_1.diff" is wrong. To match the existing call signature, __text_signature__ should be: sorted($module, iterable, /, *, key=None, reverse=False) I don't know any other builtin with a signature like this. Such a signature may be a point of confusion for people learning Python ("what are those funny symbols?!"), who often encounter sorted early on. -- ___ Python tracker <http://bugs.python.org/issue26729> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue26729] Incorrect __text_signature__ for sorted
Erik Welch added the comment: sorted_3.patch corrects the __text_signature__. Behavior of sorted is unchanged. >>> def raises(err, lamda): ... try: ... lamda() ... return False ... except err: ... return True ... >>> import inspect >>> sig = inspect.signature(sorted) >>> # `iterable` is positional-only >>> assert raises(TypeError, lambda: sorted(iterable=[])) >>> assert raises(TypeError, lambda: sig.bind(iterable=[])) >>> # `key` and `reverse` are keyword-only >>> assert raises(TypeError, lambda: sorted([], lambda x: x)) >>> assert raises(TypeError, lambda: sig.bind([], lambda x: x)) -- Added file: http://bugs.python.org/file42444/sorted_3.patch ___ Python tracker <http://bugs.python.org/issue26729> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com