Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bpo-37645: add new function _PyObject_FunctionStr() #14890

Merged
merged 9 commits into from Nov 5, 2019

Conversation

jdemeyer
Copy link
Contributor

@jdemeyer jdemeyer commented Jul 21, 2019

Additional note: the method_check_args function in Objects/descrobject.c is written in such a way that it applies to all kinds of descriptors. In particular, a future re-implementation of wrapper_descriptor could use that code.

CC @vstinner @encukou

https://bugs.python.org/issue37645

Automerge-Triggered-By: @encukou

Objects/object.c Outdated Show resolved Hide resolved
@vstinner
Copy link
Member

vstinner commented Jul 29, 2019

I would prefer to make it private at the beginning: replace Py with _Py.

@jdemeyer
Copy link
Contributor Author

jdemeyer commented Aug 4, 2019

I would prefer to make it private at the beginning: replace Py with _Py.

Done.

@jdemeyer jdemeyer changed the title bpo-37645: add new function PyObject_FunctionStr() bpo-37645: add new function _PyObject_FunctionStr() Aug 4, 2019
Copy link
Member

@vstinner vstinner left a comment

Objects/object.c Outdated Show resolved Hide resolved
Objects/object.c Show resolved Hide resolved
Return a user-friendly string representation of the function-like object
*func*. This returns ``func.__qualname__ + "()"`` if there is a
``__qualname__`` attribute and ``type(func).__name__ + " object"``
otherwise. Note that there is no check that *func* is actually callable.
Copy link
Member

@vstinner vstinner Aug 12, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not using the qualified name for type(func)?

Would it be possible to also add the module, except for builtin functions?

Copy link
Contributor Author

@jdemeyer jdemeyer Aug 18, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not using the qualified name for type(func)?

I decided to use str(func) as fallback, which looks more useful than f"{type(func)} object".

@jdemeyer
Copy link
Contributor Author

jdemeyer commented Aug 13, 2019

Before changing this PR, could you reply on my last comment on bpo-37645? It might be a better solution to just use str(func) in the error message and then changing some __str__ implementations.

Objects/object.c Outdated Show resolved Hide resolved
Doc/c-api/object.rst Outdated Show resolved Hide resolved
Python/ceval.c Outdated Show resolved Hide resolved
@@ -1967,7 +1967,7 @@ def test_methods_in_c(self):
# different error messages.
set_add = set.add

expected_errmsg = "descriptor 'add' of 'set' object needs an argument"
expected_errmsg = "set.add() needs an argument"
Copy link
Member

@encukou encukou Sep 11, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I consider this a regression: the message is now too similar to calling the method on an instance, but missing an argument.

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: set.add() takes exactly one argument (0 given)

>>> set.add()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: set.add() needs an argument

Copy link
Member

@serhiy-storchaka serhiy-storchaka Sep 13, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree, this is confusing.

Copy link
Contributor Author

@jdemeyer jdemeyer Sep 13, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can change the error message to anything you like, except that it must contain the string set.add (the function name). So it could be

TypeError: unbound method set.add() needs an argument

or whatever (surely, this is better than anything mentioning descriptors).


Small rant: the bug is really this:

>>> set().add()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: add() takes exactly one argument (0 given)

For a Python method, it would correctly note that 2 arguments are required. This is difficult to fix in CPython since builtin_function_or_method doesn't really know whether it's a function or method. This was one of the things that the rejected PEP 580 would have addressed.

.. c:function:: PyObject* _PyObject_FunctionStr(PyObject *func)

Return a user-friendly string representation of the function-like object
*func*. This returns ``func.__qualname__ + "()"`` if there is a
Copy link
Member

@serhiy-storchaka serhiy-storchaka Sep 13, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Returning __qualname__ without module is not particularly useful.

If you want to return a full qualified name (long but unambiguous), return __module__ + '.' + __qualname__. __module__ can be omitted if it is 'builtins'.

If you want to return a short name (it is enough in many times), return __name__.

if __qualname__ is not available, you can use __name__ instead.

Copy link
Contributor Author

@jdemeyer jdemeyer Sep 13, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if __qualname__ is not available, you can use __name__ instead.

This is mainly meant as replacement for PyEval_GetFuncName and all classes supported by that function implement __qualname__. So I see little reason for the additional complexity of supporting __name__.

Doc/c-api/object.rst Outdated Show resolved Hide resolved
@@ -1967,7 +1967,7 @@ def test_methods_in_c(self):
# different error messages.
set_add = set.add

expected_errmsg = "descriptor 'add' of 'set' object needs an argument"
expected_errmsg = "set.add() needs an argument"
Copy link
Member

@serhiy-storchaka serhiy-storchaka Sep 13, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree, this is confusing.

Objects/object.c Outdated Show resolved Hide resolved
@jdemeyer
Copy link
Contributor Author

jdemeyer commented Sep 13, 2019

I tried to address all comments.

Objects/object.c Show resolved Hide resolved
@encukou
Copy link
Member

encukou commented Oct 8, 2019

One more nitpick above. Otherwise, this does look like an improvement in the error messages – not only in custom extension callables!

@encukou encukou added the 🤖 automerge PR will be merged once it's been approved and all CI passed label Oct 22, 2019
@miss-islington
Copy link
Contributor

miss-islington commented Oct 22, 2019

@jdemeyer: Status check is done, and it's a success .

@miss-islington
Copy link
Contributor

miss-islington commented Oct 22, 2019

Sorry, I can't merge this PR. Reason: Required status check "Azure Pipelines PR" is expected..

@miss-islington
Copy link
Contributor

miss-islington commented Oct 22, 2019

@jdemeyer: Status check is done, and it's a success .

@miss-islington
Copy link
Contributor

miss-islington commented Oct 22, 2019

Sorry, I can't merge this PR. Reason: Required status check "Azure Pipelines PR" is expected..

@miss-islington
Copy link
Contributor

miss-islington commented Oct 22, 2019

@jdemeyer: Status check is done, and it's a success .

@miss-islington
Copy link
Contributor

miss-islington commented Oct 22, 2019

Sorry, I can't merge this PR. Reason: Required status check "Azure Pipelines PR" is expected..

@encukou
Copy link
Member

encukou commented Oct 22, 2019

@zooba What's the best way to get Azure Pipelines to run on this PR?
I asked the same at #16497 (comment) and things got moving when I did. Was that you pushing a button somewhere?

@jdemeyer
Copy link
Contributor Author

jdemeyer commented Oct 22, 2019

Thanks for going through with this.

@rlamy
Copy link
Contributor

rlamy commented Oct 31, 2019

Shouldn't format_kwargs_error be changed as well, to stay consistent with check_args_iterable?

@encukou
Copy link
Member

encukou commented Nov 5, 2019

Good catch, thank you!

The conflicting change in master is to use _PyErr_Format
(with explicit thread state argument) instead of PyErr_Format
@miss-islington
Copy link
Contributor

miss-islington commented Nov 5, 2019

@jdemeyer: Status check is done, and it's a success .

@miss-islington miss-islington merged commit bf17d41 into python:master Nov 5, 2019
jacobneiltaylor pushed a commit to jacobneiltaylor/cpython that referenced this pull request Dec 5, 2019
Additional note: the `method_check_args` function in `Objects/descrobject.c` is written in such a way that it applies to all kinds of descriptors. In particular, a future re-implementation of `wrapper_descriptor` could use that code.

CC @vstinner @encukou 


https://bugs.python.org/issue37645



Automerge-Triggered-By: @encukou
shihai1991 pushed a commit to shihai1991/cpython that referenced this pull request Jan 31, 2020
Additional note: the `method_check_args` function in `Objects/descrobject.c` is written in such a way that it applies to all kinds of descriptors. In particular, a future re-implementation of `wrapper_descriptor` could use that code.

CC @vstinner @encukou 


https://bugs.python.org/issue37645



Automerge-Triggered-By: @encukou
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🤖 automerge PR will be merged once it's been approved and all CI passed
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

9 participants