Docs and TypedDicts for tool.pdm table and subtables#3784
Docs and TypedDicts for tool.pdm table and subtables#3784sneakers-the-rat wants to merge 6 commits into
Conversation
| """See [pdm-scripts][pdm-scripts]""" | ||
| source: list[SourceTable] | ||
| """Repositories where packages may be found""" | ||
| version: VersionTable |
There was a problem hiding this comment.
I do not recommend adding fields that are not used by this project to the schema, since they may be changed by the consumers.
There was a problem hiding this comment.
are you referring to the version table? I am not sure what you mean 'not used by this project' - do you mean that version is interpreted by pdm-backend and not pdm and should go there? or what do you mean?
There was a problem hiding this comment.
Yes, if this table is not directly used by PDM itself, it's better to no include it here.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #3784 +/- ##
==========================================
+ Coverage 86.25% 86.31% +0.06%
==========================================
Files 118 118
Lines 12432 12492 +60
Branches 2082 2082
==========================================
+ Hits 10723 10783 +60
Misses 1139 1139
Partials 570 570
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
there we go! look at that, so nice: https://python-pdm--3784.org.readthedocs.build/en/3784/reference/tool/ got the mkdocs transformation of functional TypedDicts -> class TypedDicts working with the dict keys that can't be python names:
will annotate a few choices here but then i think this is ready for review - basically up to you on what fields need docstrings, what should go in them, etc. feel free to edit anything or ask further questions |
| for k, v in mod.members.items() | ||
| if isinstance(v, Attribute) | ||
| and "module-attribute" in v.labels | ||
| and isinstance(v.value, ExprCall) | ||
| and v.value.function.name == "TypedDict" |
There was a problem hiding this comment.
intercepting at the module level means that the members are pretty polytyped, so these checks are both to filter to only functional typeddicts and also to avoid attribute errors/satisfy mypy/etc.
| mod.members.update(classes) | ||
| return mod | ||
|
|
||
| def _extract_comment_docstring(self, key: str, td: Attribute) -> Docstring | None: |
There was a problem hiding this comment.
wrote this not to be super general, assuming we are defining things in a standard way that should be enforced by the linter (fields and comments on newlines, etc.)
the failure mode should be missing docstrings rather than failing building if any errors should occur, but it looks like it passes through all the markdown just fine
| <style> | ||
| /* Temporary hack pending guidance to show compact summary tables without double-displaying each attribute */ | ||
| .doc-class .doc-children { | ||
| display: none; | ||
| } | ||
| </style> |
There was a problem hiding this comment.
so this is the remaining hack that i'm not sure about - the purpose is to make it so we just get the summary tables but don't get the larger attribute listings. i assumed we would like the former because it's more in the style of the other docs, but reverting this back to just being normal attribute listings wouldn't be hard. one bonus is that the summary tables link out to the types.
both a) linking to types from attribute annotations and b) displaying summary tables without attribute listings are dropped features during the transition into zensical:
- feature: Support enabling
signature_crossrefswithout enablingseparate_signaturemkdocstrings/python#270 - Unable to get docstring summary, and supress the remainder of the docstring mkdocstrings/python#139
I am not sure if it would be possible for me to hack this together with the extension, since the summary table is generated from the members, so while inline CSS is ugly it is scoped to just this one page and it does do the trick.
There was a problem hiding this comment.
You could use custom mkdocstrings-python templates to avoid rendering the attributes (while still displaying the summary table). This way, no objects inventory pollution and no CSS needed.
There was a problem hiding this comment.
Is there a way to control which template is used on a per-object/per-module level? i imagine we might want to control omitting the attrs/members in some cases and not others. it seems like that issue 139 might be the fix that's needed upstream, it does feel like something that should have an intuitive control - "show me summary, attrs, both, or neither" when currently only "show me summary+attrs, attrs, or niether" is possible.
There was a problem hiding this comment.
Is there a way to control which template is used on a per-object/per-module level?
You can override, say, the base children template, in which you check each attribute metadata:
{% if not attr.extra.your_typeddict_extension_name.dont_render %}
... {# proceed #}
{% endif %}See https://mkdocstrings.github.io/griffe/guide/users/extending/?h=extra#extra-data.
I don't think the children template uses Jinja blocks though so it could mean a big copy-paste 🤔
There was a problem hiding this comment.
Heh, maybe just override the base attribute template and check the metadata to decide whether to render anything at all. This one has Jinja blocks, much easier.
There was a problem hiding this comment.
Another idea: set attr.extra["mkdocstrings"]["template"] = "empty.html.jinja". This needs either an entry-point (see https://mkdocstrings.github.io/usage/handlers/#handler-extensions), or you can just add this empty template to the folder pointed at by the custom_templates setting (see https://mkdocstrings.github.io/usage/theming/?h=custom_#templates).
There was a problem hiding this comment.
thanks for the tips! i'll wait to see what the maintainers here say to see what they think is best.
separately - since this seems like a pretty straightforward need that would probably come up pretty often (this combination of typed dict user-facing documentation and wanting to toggle between an abbreviated form for things where it makes sense vs. an expanded form when more documentation is needed. i mean if mkdocs did this more elegantly than sphinx i would switch over) would you be interested in a PR upstream to handle this? imo it seems like a three way switch: summary is "off/only/both" but i could also do the suggestion in your issue 139 et al of having it be a separate bool flag
There was a problem hiding this comment.
Happy to help!
mkdocstrings and handlers are in maintenance mode so we won't implement new features there.
There was a problem hiding this comment.
ig idk where to contribute then! lmk where if anywhere. thanks again.
|
|
||
| def get_message(self) -> str: | ||
| package_type = self.project.pyproject.settings["package-type"] | ||
| package_type = self.project.pyproject.settings["package-type"] # type: ignore[typeddict-item] |
There was a problem hiding this comment.
ignored these because this is a deprecated key and it probably doesn't go in the docs
| result: dict[str, RepositoryConfig] = {} | ||
| for source in self.pyproject.settings.get("source", []): | ||
| result[source["name"]] = RepositoryConfig(**source, config_prefix="pypi") | ||
| for project_source in self.pyproject.settings.get("source", []): |
There was a problem hiding this comment.
mypy doesn't handle changing the type of a same-named variable, so changing the name is just for satisfying mypy
| """ | ||
| try: | ||
| return reduce(operator.getitem, key.split("."), self.pyproject.settings) | ||
| return reduce(operator.getitem, key.split("."), self.pyproject.settings) # type: ignore[arg-type] |
There was a problem hiding this comment.
i am sort of a python type system head and i genuinely don't know how one would correct this mypy error:
Argument 1 to "reduce" has incompatible type overloaded function; expected "Callable[[ToolPDMTable, str], ToolPDMTable]"
something with the generic types in reduce but also it's saying that the list[str] part in arg 1 is the problem? no idea. it would probably be cleanest to just remove this method and directly access the keys, but i didn't want to touch the rest of the code outside the scope of the PR.
| """ | ||
|
|
||
|
|
||
| class OptionsTable(TypedDict, total=False): |
There was a problem hiding this comment.
this might not need a typeddict, or there might be some way to generate it dynamically, so this is just for completeness sake but could be removed/replaced with something that doesn't hardcode the command names like this.
| custom_dir: docs/overrides | ||
|
|
||
| plugins: | ||
| - autorefs |
There was a problem hiding this comment.
needed this to be able to refer to other parts of the docs from the docstrings like [Display Text][reference-to-anchor] - less fragile than direct URL references because they work locally and also the build process can warn if the link breaks.
|
I'll pitch upstream mkdocstrings-python on adding this as a builtin extension so we can take it out of pdm's responsibility |

Pull Request Checklist
news/describing what is new.Describe what you have changed in this PR.
Fix: #3783
(raising this as a draft but i have to run right now and can't do a full rundown just yet, wanted to open to see if you approved of the general approach)
So i figured out how to get mkdocs to do a summary-table style like what is done in the other refrence docs pages, but it is a bit of a hack. the big thing that is missing here is that functional typeddicts get rendered like garbage, so i think i'll need to write a small extension for that, if you would accept that ( opened a discussion: mkdocstrings/python#329 )
Getting that summary form with the correct TOC headings also required doing manual autodoc invocations for each class, which isn't so bad, but it does risk getting stale if there are a bunch of new tables, but not that bad.
I went through the docs and source to find all mentions of
[tool.pdm]entries i could find, and added some docstrings as examples, but if we generally like this approach then i can go through and fill those in more completely (or you can do that, no preference).Feel free to edit anything, if i've gotten something wrong, if you don't like my working, etc. i'm not precious - these are your docs, just trying to help out!
will be back later for more complete comment and to figure out an approach for the functional typed dicts.
todo
Union