[issue43918] anext builtin docstring has no signature text or info about default argument

2021-04-22 Thread Erik Welch


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

2021-04-22 Thread Erik Welch


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

2021-04-24 Thread Erik Welch


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__

2020-10-18 Thread Erik Welch


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__

2020-10-18 Thread Erik Welch


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

2020-10-18 Thread Erik Welch


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

2016-04-10 Thread Erik Welch

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

2016-04-11 Thread Erik Welch

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

2016-04-11 Thread Erik Welch

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

2016-04-12 Thread Erik Welch

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