Navigation Menu

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

Put qualname in the objects.inv #4826

Closed
flying-sheep opened this issue Apr 9, 2018 · 17 comments
Closed

Put qualname in the objects.inv #4826

flying-sheep opened this issue Apr 9, 2018 · 17 comments
Labels
extensions type:proposal a feature suggestion
Milestone

Comments

@flying-sheep
Copy link
Contributor

flying-sheep commented Apr 9, 2018

Due to type annotations, more and more tools retrieve qualified object names from live objects and expect them to serve as object ID.

However, code like the following fails when the object is reexported, when its canonical location doesn’t fit its qualified name:

from scipy.sparse import spmatrix

qualname = f'{spmatrix.__module__}.{spmatrix.__qualname__}'  # 'scipy.sparse.base.spmatrix'


from sphinx.ext.intersphinx import inspect_main

sys.stdout = StringIO()
inspect_main(['https://docs.scipy.org/doc/scipy/reference/objects.inv'])

assert qualname in sys.stdout.getvalue()  # nope, only 'scipy.sparse.spmatrix'

a fix could either go into the inventory dumping or the python domain (if adding objects goes through a domain API and isn’t just doing env.domains['py'].objects.append(…))

@tk0miya
Copy link
Member

tk0miya commented Apr 10, 2018

Please let me know your goal. The inventory file of intersphinx is generated for cross reference.
Did you mean that you want to reference spmatrix by qualname (ex. :mod:scipy.sparse.base.spmatrix)?

@flying-sheep
Copy link
Contributor Author

Yes, since there is no automatic way of knowing what the “canonical” place for an object is.

@flying-sheep
Copy link
Contributor Author

flying-sheep commented Jul 23, 2018

@tk0miya do you need more information? I’d do a PR, but I don’t know enough about the inner workings here and how to start best.

@tk0miya
Copy link
Member

tk0miya commented Aug 26, 2018

Sorry for late response.

I feel a bit strange for your proposal. I think the qualified names are not undocumented. That means it is private members. I don't think it is good way to expose qualified names automatically.

@flying-sheep
Copy link
Contributor Author

You’re right, but I didn’t propose to just add the qualname to the objects.inv. I do want a solution for the case where I know the qualname but not the canonical documentation location.

Each documented object has 1–∞ aliases, one of which is the the canonical documented location (in objects.inv) and one of which is the canonical qualified name (thing.__module__ + '.' + thing.__(qual)name__). Those to names might be (but aren’t always) the same.

I don’t think it’s necessary to support all alias names, just the qualified name as well as the documented one. I can imagine two solutions, but maybe there are more:

  1. provide a function that returns the canonical documentation location given the qualified name. Without additional information in objects.inv, that means importing the module, getting all objects by their documented location, and searching the one with a matching qualname.
  2. extend objects.inv and the machinery so that :class:`actual.qualified.Name` renders as <a class="py-class" href="...">canonical.Name</a>

The latter would be much more practical, because people won’t have to change autodoc templates and so on, also it would be faster and work without having access to and implementing other modules. The former would work without rebuilding every other project’s documentation.

@tk0miya
Copy link
Member

tk0miya commented Sep 1, 2018

Most important thing is whether the author of the document want to expose the qualname to readers. I can agree with adding an option for it if they want.
But, as a developer, I feel qualname is a kind of private interface. So I don't want that if I was author.

@tk0miya tk0miya added the type:proposal a feature suggestion label Sep 1, 2018
@flying-sheep
Copy link
Contributor Author

flying-sheep commented Sep 2, 2018

i think you didn’t understand me. the point is that sometimes someone just has the qualname and needs to get a link out of the objects.inv using it.

nobody will ever see the qualname, it’s just for finding a class or function in the docs: using the qualname, you shoud be able to get a link to the documented location. the link should look like if you used the documented location.

this is about an implementation detail and enhanced functionality, not design, so an option would be counter productive, annoying, and have no benefit.

@flying-sheep
Copy link
Contributor Author

so what do you think is the best approach (from my second-to-last comment)? 1 or 2?

@tk0miya
Copy link
Member

tk0miya commented Nov 11, 2018

nobody will ever see the qualname, it’s just for finding a class or function in the docs: using the qualname, you shoud be able to get a link to the documented location.

If we'll expose qualname into objects.inv, users can refer objects using qualified name like :py:class:`scipy.sparse.base.spmatrix` as you said. It means the qualname has appeared in the document. But I think qualname is not promised interface. So it might be fragile. But documents usually alive longer than source code.

I'm afraid of that the exposure causes the document network fragile. I can understand it is useful for IDE or tooling, but...

@flying-sheep
Copy link
Contributor Author

flying-sheep commented Nov 11, 2018

Actually this is not a problem. The qualname will only appear

  1. in objects.inv (in new special alias lines)
  2. in generated rst code that doesn’t get committed to version control

the links that appear in the HTML will point to the documented name. e.g.

  1. the user writes .. autodoc:: some_function, where def some_function(df: pd.DataFrame): ...
  2. sphinx-autodoc-typehints generates temporary rst code for the function docs containing :class:`pandas.core.frame.DataFrame` .
  3. The pandas objects.inv contains an alias line pandas.core.frame.DataFrame → pandas.DataFrame
  4. a new version of intersphinx that understands the new alias lines gives back the correct, documented location
  5. that location ends up in the HTML.

@goerz
Copy link
Contributor

goerz commented Dec 18, 2018

A big +1 from me. Without this, the Sphinx documentation for projects that uses type annotations are broken, with no workaround. In fact, this is one reason why I think people should stay away from type annotations for the time being.

@tk0miya
Copy link
Member

tk0miya commented Dec 23, 2018

Sorry for late.

@flying-sheep Finally I can understand your goal. Thank you for explanation. I agree to add qualnames to inventory as alias. I think they should be also added into internal indices data; which is origin of inventory file. Because other extension would also be able to refer it by qualname.

@tk0miya tk0miya added this to the some future version milestone Dec 23, 2018
@flying-sheep
Copy link
Contributor Author

flying-sheep commented Dec 25, 2018

Great to hear! Merry Christmas!

@flying-sheep
Copy link
Contributor Author

It’s one year later. Merry Christmas and a happy new year again! 😉

with no workaround

Actually scanpydoc.elegant_typehints has a (manual) workaround (check the docs for qualname_overrides) behind the link.

@eric-wieser
Copy link
Contributor

I think they should be also added into internal indices data; which is origin of inventory file.

Related to #5589 I think

@tk0miya
Copy link
Member

tk0miya commented Mar 27, 2021

Now I merged #9026 that generates :canonical: option for the imported classes. It allows to refer the python objects by its canonical name. It resolves the problem pandas.DataFrame and pandas.core.frame.DataFrame!

@tk0miya tk0miya closed this as completed Mar 27, 2021
@flying-sheep
Copy link
Contributor Author

flying-sheep commented Mar 27, 2021

Great, thank you so much! This will help in many many cases.

This PR is only a partial solution for autodoc though, as it only touches the class documenter. What about

  1. reexported functions? Their documenter should do the same.
  2. Methods: When a reexported class documented as api.Class has :canonical: orig.Class set, will referring to orig.Class.method work the same as referring to api.Class.method?

Let’s fix up #9039

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jul 12, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
extensions type:proposal a feature suggestion
Projects
None yet
Development

No branches or pull requests

4 participants