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

gh-103131: Convert sys.set_asyncgen_hooks to AC #103132

Closed
wants to merge 6 commits into from

Conversation

sobolevn
Copy link
Member

@sobolevn sobolevn commented Mar 30, 2023

Copy link
Member

@serhiy-storchaka serhiy-storchaka left a comment

Choose a reason for hiding this comment

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

What is the help() output for these functions?

@@ -0,0 +1,2 @@
Convert :func:`sys.getsizeof` and :func:`sys.set_asyncgen_hooks`
Copy link
Member

Choose a reason for hiding this comment

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

It is an internal refactoring. Such changes usually are not reflected in the NEWS file.

@sobolevn
Copy link
Member Author

sobolevn commented Mar 31, 2023

Hm, indeed help has gotten even worse. Before:

>>> import sys
>>> help(sys.getsizeof)
Help on built-in function getsizeof in module sys:

getsizeof(...)
    getsizeof(object [, default]) -> int
    
    Return the size of object in bytes.

>>> help(sys.set_asyncgen_hooks)
Help on built-in function set_asyncgen_hooks in module sys:

set_asyncgen_hooks(...)
    set_asyncgen_hooks(* [, firstiter] [, finalizer])
    
    Set a finalizer for async generators objects.

After:

>>> import sys
>>> help(sys.getsizeof)
Help on built-in function getsizeof in module sys:

getsizeof(...)
    Return the size of object in bytes.

>>> help(sys.set_asyncgen_hooks)
Help on built-in function set_asyncgen_hooks in module sys:

set_asyncgen_hooks(...)
    Set a finalizer for async generators objects.

>>> sys.getsizeof.__text_signature__
'($module, /, object, default=<unrepresentable>)'
>>> sys.set_asyncgen_hooks
<built-in function set_asyncgen_hooks>
>>> sys.set_asyncgen_hooks.__text_signature__
'($module, /, firstiter=<unrepresentable>,\n                   finalizer=<unrepresentable>)'

Looks like inspect cannot parse <unrepresentable> as a part of the signature.

>>> inspect.signature(sys.getsizeof)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/sobolev/Desktop/cpython/Lib/inspect.py", line 3322, in signature
    return Signature.from_callable(obj, follow_wrapped=follow_wrapped,
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/sobolev/Desktop/cpython/Lib/inspect.py", line 3066, in from_callable
    return _signature_from_callable(obj, sigcls=cls,
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/sobolev/Desktop/cpython/Lib/inspect.py", line 2558, in _signature_from_callable
    return _signature_from_builtin(sigcls, obj,
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/sobolev/Desktop/cpython/Lib/inspect.py", line 2359, in _signature_from_builtin
    return _signature_fromstr(cls, func, s, skip_bound_arg)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/sobolev/Desktop/cpython/Lib/inspect.py", line 2220, in _signature_fromstr
    raise ValueError("{!r} builtin has invalid signature".format(obj))
ValueError: <built-in function getsizeof> builtin has invalid signature

This part also looks strange:

'($module, /, firstiter=<unrepresentable>,\n                   finalizer=<unrepresentable>)'

Why \n ?

In typeshed we use ... for default values that are hard / impossible to represent.
Can we use the same technique here? So, __text_signature__ would become '($module, /, firstiter=..., finalizer=...)'

@sobolevn
Copy link
Member Author

sobolevn commented Mar 31, 2023

Ok, I've found the temporary solution. Other similar cases just copy the signature into the docs:

od.pop(key[,default]) -> v, remove specified key and return the corresponding value.

New help with it:

>>> import sys
>>> help(sys.getsizeof)
Help on built-in function getsizeof in module sys:

getsizeof(...)
    getsizeof(object [, default]) -> int

    Return the size of object in bytes.

>>> help(sys.set_asyncgen_hooks)
Help on built-in function set_asyncgen_hooks in module sys:

set_asyncgen_hooks(...)
    set_asyncgen_hooks(* [, firstiter] [, finalizer])

    Set a finalizer for async generators objects.

Copy link
Member

@AlexWaygood AlexWaygood left a comment

Choose a reason for hiding this comment

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

This now has merge conflicts

@bedevere-bot
Copy link

A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated.

Once you have made the requested changes, please leave a comment on this pull request containing the phrase I have made the requested changes; please review again. I will then notify any core developers who have left a review that you're ready for them to take another look at this pull request.

firstiter: object = NULL
finalizer: object = NULL

set_asyncgen_hooks(* [, firstiter] [, finalizer])
Copy link
Member

Choose a reason for hiding this comment

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

Maybe the doc should be modified to use this signature: https://docs.python.org/dev/library/sys.html#sys.set_asyncgen_hooks

Or this docstring should use the doc signature: sys.set_asyncgen_hooks(firstiter, finalizer).

Copy link
Contributor

Choose a reason for hiding this comment

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

The docs also read:

Accepts two optional keyword arguments [...]

IMO, the signature in the docs should be updated to reflect the actual implementation.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done in #114385

Copy link
Member

Choose a reason for hiding this comment

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

Can you please rebase your PR on top of it? There are now merge conflicts.

@AlexWaygood AlexWaygood dismissed their stale review March 18, 2024 15:48

no longer has merge conflicts

@vstinner
Copy link
Member

The help now shows the signature twice. Please remove the second signature:

>>> help(sys.set_asyncgen_hooks)
set_asyncgen_hooks(firstiter=<unrepresentable>,
                   finalizer=<unrepresentable>)
    set_asyncgen_hooks([firstiter] [, finalizer])

    Set a finalizer for async generators objects.

>>> help(sys.getsizeof)
getsizeof(object, default=<unrepresentable>)
    getsizeof(object [, default]) -> int

    Return the size of object in bytes.

sys.getsizeof

object: object
default as dflt: object = NULL
Copy link
Member

Choose a reason for hiding this comment

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

I suggest to use a longer name rather than a shorter one:

Suggested change
default as dflt: object = NULL
default as default_size: object = NULL

Copy link
Contributor

Choose a reason for hiding this comment

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

That would make the diff unnecessary bigger. IMO, it is better to align with the current naming.

@sobolevn
Copy link
Member Author

The sys.getsizeof change is incorrect. I can still convert sys.set_asyncget_hooks and change the defaults from NULL to Py_None, looks like that this will be valid.

@sobolevn sobolevn changed the title gh-103131: Convert sys.getsizeof and sys.set_asyncgen_hooks to AC gh-103131: Convert sys.set_asyncgen_hooks to AC Mar 20, 2024
@sobolevn
Copy link
Member Author

Here's the new help() output:

» ./python.exe
Python 3.13.0a5+ (heads/issue-103131:c0086505210, Mar 20 2024, 13:48:58) [Clang 15.0.0 (clang-1500.0.40.1)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> help(sys.set_asyncgen_hooks)
Help on built-in function set_asyncgen_hooks in module sys:

set_asyncgen_hooks(firstiter=None, finalizer=None)
    Set a finalizer for async generators objects.

None is supported and even tested here:

cpython/Lib/test/test_sys.py

Lines 1766 to 1790 in 8182319

def test_asyncgen_hooks(self):
old = sys.get_asyncgen_hooks()
self.assertIsNone(old.firstiter)
self.assertIsNone(old.finalizer)
firstiter = lambda *a: None
sys.set_asyncgen_hooks(firstiter=firstiter)
hooks = sys.get_asyncgen_hooks()
self.assertIs(hooks.firstiter, firstiter)
self.assertIs(hooks[0], firstiter)
self.assertIs(hooks.finalizer, None)
self.assertIs(hooks[1], None)
finalizer = lambda *a: None
sys.set_asyncgen_hooks(finalizer=finalizer)
hooks = sys.get_asyncgen_hooks()
self.assertIs(hooks.firstiter, firstiter)
self.assertIs(hooks[0], firstiter)
self.assertIs(hooks.finalizer, finalizer)
self.assertIs(hooks[1], finalizer)
sys.set_asyncgen_hooks(*old)
cur = sys.get_asyncgen_hooks()
self.assertIsNone(cur.firstiter)
self.assertIsNone(cur.finalizer)

So, this now should be a simple change :)

@sobolevn
Copy link
Member Author

Ok, I've found this branch:

else if (finalizer == Py_None && _PyEval_SetAsyncGenFinalizer(NULL) < 0) {
        return NULL;
    }

Looks like this PR is not correct either. It is better to close it.

@sobolevn sobolevn closed this Mar 20, 2024
@vstinner
Copy link
Member

Looks like this PR is not correct either. It is better to close it.

If someone wants to continue the work, I suggest to leave Argument Clinic aside, and start by fixing the implementation and the signature to prepare the API for Argument Clinic.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants