Skip to content

Support positional-only parameters in classmethods #11635

Merged
AA-Turner merged 4 commits intosphinx-doc:masterfrom
AA-Turner:autodoc-preserve-classmethod-posonly
Aug 23, 2023
Merged

Support positional-only parameters in classmethods #11635
AA-Turner merged 4 commits intosphinx-doc:masterfrom
AA-Turner:autodoc-preserve-classmethod-posonly

Conversation

@AA-Turner
Copy link
Copy Markdown
Member

cc: @randolf-scholz -- please could you check that this works for you?

A

@randolf-scholz
Copy link
Copy Markdown
Contributor

@AA-Turner The patch works well for the projects I use sphinx in 👍, but I added some comments to code sections that could be problematic in some edge cases regardless.

@AA-Turner

This comment was marked as resolved.

@randolf-scholz

This comment was marked as resolved.

@AA-Turner

This comment was marked as resolved.


if args.defaults or args.kw_defaults:
sig = inspect.signature(obj)
is_classmethod = bound_method and inspect.ismethod(obj)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is it clear that this catches classmethod and classmethod only? (and not any otherwise decorated things?)
Possibly it would be better to make a helper function.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Good point, this captures all bound methods.

Comment on lines +146 to +147
if is_classmethod and hasattr(obj, '__func__'):
sig = inspect.signature(obj.__func__)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

If the is_classmethod is correct, then __func__ should always exist, so I'd rather do

if is_classmethod:
    assert hasattr(obj, '__func__')
    sig = inspect.signature(obj.__func__)

Which would help to find bugs if there are any in is_classmethod.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

As I'd like this to go in to 7.2.3 I don't want to introduce a new assert.

Comment on lines 173 to 175
if is_classmethod:
# classmethods can't be assigned __signature__ attribute.
obj.__dict__['__signature__'] = sig
Copy link
Copy Markdown
Contributor

@randolf-scholz randolf-scholz Aug 23, 2023

Choose a reason for hiding this comment

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

This is problematic since obj might not have __dict__. This can happen if it is decorated with a class that uses __slots__. It's a pretty cursed example/edge-case...

from functools import wraps


def make_cursed_decorator(func):
    class CursedDecorator:
        __slots__ = ()

        @staticmethod
        @wraps(func)
        def __call__(*args, **kwargs):
            return func(*args, **kwargs)

    return CursedDecorator()


class A:
    @classmethod
    @make_cursed_decorator
    def foo(cls, x: int, /, *, y: int = 0) -> int:
        return x + y


A.foo(1, y=2)
A.foo.__dict__  # AttributeError

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

The outer except (AttributeError, TypeError): would catch this, but it isn't very clear -- I've added a note to capture this case.

Copy link
Copy Markdown
Contributor

@randolf-scholz randolf-scholz left a comment

Choose a reason for hiding this comment

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

LGTM

@AA-Turner AA-Turner merged commit a73fb59 into sphinx-doc:master Aug 23, 2023
@AA-Turner AA-Turner deleted the autodoc-preserve-classmethod-posonly branch August 23, 2023 18:33
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Sep 23, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants