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

Custom type hint doc formatting for TypeAlias, TypeVar #2645

Closed
wants to merge 4 commits into from

Conversation

rmartin16
Copy link
Member

@rmartin16 rmartin16 commented Jun 13, 2024

Changes

  • An experiment with custom type hint doc formatting
  • While this approach would not scale well....it does allow us to cleanup each problematic TypeAlias and TypeVar
    • Unfortunately, the TypeAlias has already been resolved, so we need to match on the aliased types

This POC is crude but what do you think about the idea?

PR Checklist:

  • All new features have been tested
  • All new features have been documented
  • I have read the CONTRIBUTING.md file
  • I will abide by the code of conduct

@rmartin16 rmartin16 force-pushed the doc-type-hints branch 2 times, most recently from 1df4a8b to 59feb63 Compare June 13, 2024 02:04
else:
# sphinx-autodoc-typehints errors when these are gated with TYPE_CHECKING...
PositionT = None
SizeT = None
Copy link
Member

Choose a reason for hiding this comment

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

Any idea why it only affects PositionT and SizeT, and not any of the other type aliases?

Copy link
Member Author

Choose a reason for hiding this comment

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

I didn't look in to it too far yet....but I think it could be related to the circular import

@freakboy3742
Copy link
Member

It's a little unwieldy that we need to manually configure each type alias that we want to support, but the I can't argue with the end product - that's pretty much exactly what I had in mind.

The only nitpick I'd have is that the fallback behavior looks like it's currently TypeVar(SomeT) (e.g., the handling of ImageT in ImageView); but if I'm reading the configuration right, it should be possible to return {name of type} as a default?

Even better would be to have a warning/error raised if there's a type alias that is falling back to this default. Having the docs actively complain if we don't document a new type alias will guarantee that we at least describe what the type means (and, in the case of StyleT, will force us to describe what that actually means).

@rmartin16
Copy link
Member Author

The only nitpick I'd have is that the fallback behavior looks like it's currently TypeVar(SomeT) (e.g., the handling of ImageT in ImageView); but if I'm reading the configuration right, it should be possible to return {name of type} as a default?

Even better would be to have a warning/error raised if there's a type alias that is falling back to this default. Having the docs actively complain if we don't document a new type alias will guarantee that we at least describe what the type means (and, in the case of StyleT, will force us to describe what that actually means).

For TypeVars, it should be possible to do this; that is, we could add a if isinstance(annotation, TypeVar) at the end and throw some kind of warning/error. For TypeAliass, the situation is more complicated because sphinx-autodoc-typehints has already resolved the TypeAlias to its actual types by the time this code is running.

@rmartin16
Copy link
Member Author

13a5556 is an experiment with making each TypeAlias importable at runtime.

Specific to this effort, it makes it much easier to replace the existing type annotations in the docs using these TypeAliases if I can properly import them in to conf.py. This, however, had a lot of interesting side effects...

The current use of typing-extensions requires that all imports from it are done in a if TYPE_CHECKING block. This is because of typing-extensions is only installed with the dev dependencies. Therefore, any TypeAlias must also be defined within the same block. And of course then any use of a TypeAlias in another module requires its import in a if TYPE_CHECKING block.

But we can't do any of this if we want a TypeAlias to be importable at runtime. So, in lieu of promoting typing-extensions to a full dependency, we could, at least, stop annotating type aliases as TypeAlias. The benefit of this annotation is to resolve ambiguities between a regular module global variable and something a type checker should allow for type checking. However, type checkers will assume a module global is a TypeAlias if it's a valid type....and all of our use-cases meet that requirement.

But then...the real fun begins. If you dig in to how sphinx-autodoc-typehints works....it does tremendously more magic than I would have ever imagined. Unlike a full blown type checker, sphinx-autodoc-typehints can't resolve all of the references in each TypeAlias.....but if you import the missing references in to the module where the TyleAlias is defined, the TypeAlias can be fully resolved for the purposes of documentation.

This became more and more of a mess the further I went with it...but I wanted to at least document it...

@freakboy3742
Copy link
Member

@rmartin16 What do you consider the state of this experiment? Should we close this out, or leave it as a potential WIP?

@rmartin16
Copy link
Member Author

I'll clean it up this week and see if we want to merge it.

There are inherent issues with identifying some of the TypeAliases; so, we may only be able to use this strategy for some of them. I can confirm which ones those are.

@rmartin16
Copy link
Member Author

I'm going to say this isn't really working. There are several issues.

First, several of these TypeAliases don't exist at runtime since they are gated with if TYPE_CHECKING. Therefore, detecting if a specific annotation is the one you want can be difficult since you can't just import the TypeAlias from where it is defined to check; you have to actually recreate the definition to compare.

And that's the second issue; you have to recreate some of these complicated type definitions to identify the correct annotation to replace. For several reasons, such as typing's forward references, this is less than straightforward and quite frustrating.

Third, this hook is provided by sphinx-autodoc-typehints; this plugin was previously removed because replaced the TypeAlias names in the docs with their literal definitions. So, unless this hook is able to catch all of them, those verbose definitions will exist in the docs again.

I left the current state usable in case anyone wants to make their own attempt.

@rmartin16 rmartin16 closed this Sep 20, 2024
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.

2 participants