mkdocs plugin
Addresses #617
@relativityhd @danielgafni testing and feedback would be appreciated!
Codecov Report
:x: Patch coverage is 79.80769% with 189 lines in your changes missing coverage. Please review.
:white_check_mark: Project coverage is 89.37%. Comparing base (9b3a1db) to head (08265f8).
:warning: Report is 41 commits behind head on main.
Additional details and impacted files
@@ Coverage Diff @@
## main #621 +/- ##
==========================================
+ Coverage 88.10% 89.37% +1.26%
==========================================
Files 69 70 +1
Lines 7820 7934 +114
Branches 1791 1802 +11
==========================================
+ Hits 6890 7091 +201
+ Misses 556 479 -77
+ Partials 374 364 -10
| Flag | Coverage Δ | |
|---|---|---|
| unittests | 89.31% <79.80%> (+1.26%) |
:arrow_up: |
Flags with carried forward coverage won't be shown. Click here to find out more.
:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.
:rocket: New features to boost your workflow:
- :snowflake: Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
Seems to work! I have tested it with our rather complex CLI which has a meta app, dataclasses and super nested commands.
I would suggest you get in contact with squidfunk to add cyclopts in the plugins schema file: https://squidfunk.github.io/mkdocs-material/schema/plugins.json so that yaml language server dont say that cyclopts is not a valid plugin
I've found one thing which is odd: Some of my commands have two "Options" headers where one is also present in the toc:
Same thing happens with arguments.
Always the second "Option" or "Argument" is without a ":" and is instead marked as a header.
This seems to only occur on commands which are part of double-nested apps. E.g. in my screenshots you can see that I have an app inside an app inside an app -> 3 subcommands
Ah, and the filtering commands dont seem to work as I would expect:
:commands: training
:exclude-commands: training.create-dataset
Will show all training commands, including the create-dataset command and subcommands. On the other side:
:commands: training.create-dataset
/* no exclude */
Will hide the create-dataset sub-commands but show all other training commands.
thanks for the testing! I'll try and address these tomorrow.
I will be testing it with my CLI tomorrow.
@relativityhd @danielgafni can you guys give this another round of testing? thanks!
Definitely an improvement for env vars and the TOC entries!
I think the last issue to address is the Markdown TOC which is still weird
I'll get on it! Thanks for testing!
Actually sorry, I was still running the old version. And confused positional arguments with env docs :man_facepalming:
TOC is fine, only the missing env vars is an issue for me.
Markdown TOC is actually fine now, sorry for the confusion.
Thanks! I'm going to do a bit of a refactor (including your suggestions). I'm saving the env-var stuff for a separate PR because this is already quite a large PR, and it'll make it easier to review that functionality.
Once i have these changes in, i think we should have one more round of testing then merge. Then i'll work on the env var stuff!
Understood! Thanks for your efforts Brian
My previous reported bugs seem to be correct now.
But I found now several other problems, I tried to show them in this screenshot:
The mkdocs code for this is basically
## Create Dataset Commands
::: cyclopts
:module: darts.cli:app
:commands: training.create_dataset
:generate-toc: false
:flatten-commands: true
:heading-level: 3
Where training.create_dataset is a further subapp with multiple commands inside.
I know that we have a super nested CLI, it is awesome that it is possible to have such nesting, and it makes our lives so much easier! I understand that this makes debugging of this PR super hard. So if you like, I can create a minimal reproducible version of our CLI if you need one. Or also help writing Code for it.
Either way: Thanks for your efforts Brian!
@danielgafni @relativityhd I'm kind of a noob at mkdocs, but i'm getting the vibe that the sphinx-like plugin syntax isn't idiomatic? Is it more common/prefered to use yaml syntax within the directive block? Because if so, i can easily switch to that (rather than emulating sphinx syntax).
I think you can use MkDocsStrings-Python as an example, it is quite commonly used in the Python community as far as I can tell. Stuff in the directive block looks e.g. like this:
::: package.module.class
options:
do_something: false
But at the end, I think as long as you document how to do stuff, it doesn't matter a lot. I didn't notice the difference in declaration-syntax until you asked me about it. :D
While it doesn't matter technically, it's better to conform to the current widespread style, IMO.
Yaml it is! I'll update this.
@danielgafni can you give this another round of testing?
@relativityhd same for you. Is there a branch of darts that I can play with to manually test some document generation? Thanks!
Hi Brian, I've pushed my local changes to this branch: https://github.com/awi-response/darts-nextgen/tree/feature/cycloptsv4
You would need to sync stuff with uv sync --extra cpu --extra training --all-groups to ensure all dependencies are loaded correctly.
Currently, we're still doing a lot of imports in the functions themselves to avoid long load times when calling --help on the CLI. I know that the new lazy-loading feature should help with that, but unfortunately this only works for nested subcommands, at least on another test I did. ("Lazy commands are resolved/imported in these situations: [...] Help Generation - When displaying help that includes the command") Maybe I will open another issue after having a closer look at this problem.
thanks for posting! I'll play around with doc-generation in the darts-nextgen repo.
As for the lazy-loading stuff, yes lets handle that separately in another issue/pr later!
@relativityhd I think we're getting closer; i'll continue to fiddle around with it, but I tweaked it to definitely be more in-line with what you would want.
Hey Brian, I noticed these dataclass options are all rendered as both position arguments (UPPERCASE) and options (--lower-case), is this expected?
In fact they are all optional.
probably intentional! you probably want to mark your dataclass kw_only=True (or use KW_ONLY)
Any idea if we could use mkdocstrings from Cyclopts docstrings or parameters help?
Better treatment for newlines in "long" help docstrings
I've attempted to do something like this:
@app.command()
def my_command():
"""My short description.
My long description.
Example:
$ my-command ...
"""
But the example got stripped from the generated markdown since the second newline ends the long description.
Any idea if this behavior could be changed for markdown help format?
Document parameter types
I have this dict[str, str] argument but it's impossible to tell whether it accepts a dot-notation dict from the docs. I have to document this myself in the parameter help.
Same issue stands with other types. Seems more like a general cyclopts problem since the CLI help is missing this info as well? Am I missing some configuration option here?
Enable relative links to other docs
Ideally I want to be able to link to my main docs from the CLI docs. This is typically done via relative links:
[learn more here](../learn/concept)
However, this would break the urls displayed in CLI --hepl.
It sounds like this could be solved by allowing the user to specify a base URL pointing to the actual docs website and prefix the relative links with this base URL? Example:
app = cyclopts.App("app", docs_site_url="https://my.docs")
@app.command()
def my_command():
"""Learn more in [my docs](./learn/my-command)"""
$ app my-command --help
...
Learn more in [my docs](https://my.docs/learn/my-command)
Hey @BrianPugh , could you please make a dev release from this branch?
sure! just a moment; I'm finally a bit more available after Thanksgiving madness, so I'll refocus on this PR!
this is now available as v4.4.0a1! I'll have to review your above message soon and see what kind of improvements i can make.
Thanks!
I didn't realize until now this PR wasn't based on the 5.0.0 version of Cyclopts.
@danielgafni sorry for the slower iterations this time around, but here's what I'll be working on this morning:
Any idea if we could use mkdocstrings from Cyclopts docstrings or parameters help?
Not really (unless I'm completely misunderstanding); in order to work with everything else in Cyclopts, we have to be using our parsing system.
But the example got stripped from the generated markdown since the second newline ends the long description.
I also share this frustration; this is because docstring_parser parses the section and we would somehow have to "unparse" it. We explore it a bit in #477. We also explore it in the docstring_parser repo a bit here; but I honestly don't really have the will-power to deal with it. We could sort of hack-in support by find/replacing these section titles prior to docstring-parser, and then undo the find/replace afterwards; just seems quite fragile.
TLDR I agree!
it's impossible to tell whether it accepts a dot-notation dict from the docs
hmmm, yes this definitely does seem like a valid issue. What would be a good programmatic output? I agree it is a bit cumbersome to have to manually present an example. What if instead it instead displayed -t.<KEY> --tags.<KEY>? I'll tackle this in a separate, independent PR since it's a fairly independent issue.
Ideally I want to be able to link to my main docs from the CLI docs.
I'll try and implement this feature now. It might be difficult, but I think it would be a good value add.
My TODO list for this PR
Given all of the above, I think this PR is in a "good enough" state for a merge; we can continue to refine the idea in subsequent releases. However, I'll try and sneak in the docs-linking feature. What do you think @danielgafni @relativityhd ?
Not really (unless I'm completely misunderstanding); in order to work with everything else in Cyclopts, we have to be using our parsing system.
I mean this was an introduction to the rest of my post :)
Being able to write mkdocstrings-compatible markdown is all we'd need, but the beeline issue makes it quite challenging.
In general, I just want a way to attach mkdocs markdown to CLI commands in order for it to be rendered in the docs automatically. It doesn't necessarily need to be present in the Cli help (probably better if it's not since it can be large and confusing).
Ideally I'd have CLI docs attached to CLI commands definitions so information stays local and automatically injected into the website.