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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

馃憣 Add CoreEvent enum as argument for Sphinx.callback #12259

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

chrisjsewell
Copy link
Member

@chrisjsewell chrisjsewell commented Apr 10, 2024

When creating sphinx extensions (or looking at existing ones), it is always a source of annoyance/confusion trying to remember what callback events are available, what their purpose is, and also what their signatures should be.

Here I add the sphinx.events.CoreEvent enum, and allow this to be passed to Sphinx.connect, as an alternative to a str name.
This makes it easier to write and introspect extensions, and also more type safe.

I could also add @overload functions to the EventManager.callback, with specific function signatures for each of the items,
but I will wait to get feedback first.

It would also be interesting to consider using this to "auto-generate" some of https://www.sphinx-doc.org/en/master/extdev/appapi.html#sphinx-core-events, but that is likely beyond the scope of this PR.
(I am definitely a fan of co-locating API documentation close to where it is implemented 馃槃 )

@danieleades
Copy link
Contributor

Yay typesafety!

@chrisjsewell chrisjsewell changed the title 馃憣 Add CoreEvent enum 馃憣 Add CoreEvent enum as argument for Sphinx.callback Apr 10, 2024
@@ -64,8 +171,10 @@ def add(self, name: str) -> None:
raise ExtensionError(__('Event %r already present') % name)
self.events[name] = ''

def connect(self, name: str, callback: Callable, priority: int) -> int:
def connect(self, name: str | CoreEvent, callback: Callable, priority: int) -> int:
Copy link
Contributor

Choose a reason for hiding this comment

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

we could take this further and make the CoreEvent enum the preferred approach (without breaking existing code)

Suggested change
def connect(self, name: str | CoreEvent, callback: Callable, priority: int) -> int:
@deprecated(reason="...")
@overload
def connect(self, name: str, callback: Callable, priority: int) -> int: ...
@overload
def connect(self, name: CoreEvent, callback: Callable, priority: int) -> int: ...
def connect(self, name: str | CoreEvent, callback: Callable, priority: int) -> int:

Copy link
Member

Choose a reason for hiding this comment

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

The deprecated decorator is only a 3.13 feature :(

Copy link
Member

Choose a reason for hiding this comment

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

(In addition, you still want to connect with your own events)

Copy link
Member

@picnixz picnixz left a comment

Choose a reason for hiding this comment

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

I think it's fine but the issue is that people would need to import the events module if they want to use the enumeration. So you should put it in a standalone module to avoid possible circular imports.

On the other hand, you could instead use Literal strings maybe? it could probably help if you want overloads since enumerations + literals are not happy together sometimes (I had an issue with that but I don't remember whether it's fixed or not).

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

Successfully merging this pull request may close these issues.

None yet

3 participants