-
Notifications
You must be signed in to change notification settings - Fork 120
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
Python auto doc #665
Python auto doc #665
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #665 +/- ##
=======================================
Coverage 91.66% 91.66%
=======================================
Files 37 37
Lines 4737 4737
=======================================
Hits 4342 4342
Misses 395 395 ☔ View full report in Codecov by Sentry. |
For overloads, we can probably use the parameter names as keys. It will be nice if we can make some macro that set the |
While parsing parameters names and types would be nice, I fear it quickly spirals into general-purpose c++ parsing, which is more than a 100-line python script can handle |
I think the function signature is simple in our case, we can make sure that there are no parenthesis in the parameter type. This can make it readable using regex. We can just change our source file to make it easy to parse, instead of changing the script to parse whatever c++ madness. |
Ah I'm reminded why I prefer to amend and force-push when working on PR. Rebasing this branch on master is a huge mess |
69ef783
to
9e97798
Compare
No need to bother with rebasing - just use a regular merge. That's why we squash. |
bindings/python/docstrings.inl
Outdated
#pragma once | ||
#include <string> | ||
namespace manifold_docs { | ||
const auto cross_section__area_f5458809be32 = R"___(Return the total area covered by complex polygons making up the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this file generated by your script? Would be great to have some documentation about how the system works and the right way to maintain it. Looks promising though!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generated a comment in the file, and added comments in the gen_docs.py script.
This is looking great - is it ready for review? |
Is the “_1”, “_2” overload handling mechanism still in there; how does it work? (I would be kind of sad if callers had to disambiguate overloads by appending the number of the overload to the function name… OpenCascade.js eventually went this direction for typescript annotations) If that’s the case, perhaps a lesser evil would be marking non-intersecting args as optional? |
I think the auto doc is just for documentation, it does not affect overload resolution in the runtime. And it is using the argument names as suffices to disambiguate different overloads, e.g. |
Yes I think it's ready for review. And yes the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks great to me, thank you! So the CI builds these docs automatically and they'll get packaged up into our Python releases? How do we test them?
|
||
# we don't handle inline functions in classes properly | ||
# so instead just white-list functions we want | ||
def select_functions(s): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we add something in a README somewhere that when a new non-member function is added to the API it needs to also be added to this list?
|
||
|
||
collect(f"{base}/src/manifold/src/manifold.cpp", lambda s: method_re.search(s)) | ||
collect(f"{base}/src/manifold/src/constructors.cpp", lambda s: method_re.search(s)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps also add to a README that when new files are added with API documentation, they need to also be added as a collect
line?
|
||
|
||
def method_key(name): | ||
name = re.sub("\+", "_plus", name) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We might need to add a substitution of MeshGL
to mesh
, since several docs refer to this data structure by its C++ name.
@elalish What specifically are you hoping to test? At least right now empty doc-strings are omitted, which would result in compile errors if a code change caused one of them to get lost somehow. But other than that, I'm not sure automated testing can know if a doc-string is "correct". I guess we could also run the |
Well, it doesn't have to be automation. I just feel like before I publish a release I'd like to be able to see the python docs in context and verify they look right. More of some README steps; maybe run the script and then hover over some python in VSCode and see if the doc string looks right? I just want to make sure I'm looking at the most recent version and such. |
If all it takes to build locally is to just run CMake on this branch, then, I think I have a few examples: Here's an example of Github Copilot giving suggestions based on context alongside the docs: Also, it seems like |
I think for some language servers you need the stub file. |
For basic human QA of python docs, I would recommend the following:
Open |
Thanks @wrongbad, but Would you mind adding these directions to your README? I'm guessing there's a step missing, or my python setup is weird somehow. @zalo does it work for you now? Would also be great if you could paste |
I also got the same warning, it seems that it is related to enum codegen, which I guess is complaining the lack of class JoinType:
"""
<attribute '__doc__' of 'JoinType' objects>
"""
@entries: dict
Miter: JoinType
Round: JoinType
Square: JoinType
def __init__(*args, **kwargs):
"""
Initialize self. See help(type(self)) for accurate signature.
"""
... There are also other issues, copying (and updating) my previous comment to here:
|
I think for now we can use a postprocessor to fix some of the issues, and open a PR in the upstream to make the real fix later. |
Yeah I get the warnings too but it seems non-critical. I updated the readme and included a simpler option as well:
|
@pca006132 It seems like most of what you're referring to is working for me, unless I'm not understanding this right: overloads:
static methods:
This is looking pretty decent to me - @pca006132 should we merge this, or is there some kind of regression you see? |
ok, maybe it is a version problem on my side, I installed it earlier. yeah we can merge this. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm going to assume this is all good - it certainly cleans up our code nicely. I wish I knew Python well enough to feel some confidence in verifying it, but I'll assume our users will file issues if they notice problems. Thank you!
* python autogen docstrings * use function signature hashes in docstring key * remove sys.path debug code * docstrings use param names * autogen docstrings during cmake * document gen_docs.py * more readme, remap mesh_gl references * readme about verify python docstrings, autogen depend on sources
This is based on top of the "more numpy" branch, so look at just the top commit for now.
I threw together a quick proof of concept. Obviously the script can use a lot of refactoring to add more sources with less redundancy.
One pain point already is method overloading and how to generate keys/ids to reference them. I put a simple "_1", "_2" mechanism in, but this can cause problems when adding new overloads and docstrings silently get shifted to wrong functions. I looked at doxygen XML outputs and it seems they generate some arbitrary hash for overloads, so it would likely not be a stable reference from the binding cpp file.
I could also try parentheses matching to scoop the full function name, remove all whitespace and hash it, then you only need to update the key if the function signature changes.