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
ENH: Support source files in any language #1192
Conversation
0899482
to
066b1ec
Compare
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.
Looks like a clean implementation so far! Just some preliminary comments from me. Just for background, how will this help you(r project) specifically? I assume you have some mix of Python and something else, and being able to link to non-executed something-else code will make your doc better...
f343517
to
2855a9b
Compare
I updated the PR description to provide some context. |
One last testing idea -- can you modify |
30c742d
to
eb4f15e
Compare
Thanks for the pointers on setting up some integration tests using the The
Is apparently caused by the fact that I tried to use π in a Julia example. I'm not sure how to fix this other than by not using Unicode in the example. The failure on
Doesn't seem to have anything to do with the changes in this PR. |
Yes sphinx dev is unrelated so you can ignore it for now. Can you avoid Unicode for now and we can fix it later if needed? |
ef7e565
to
d13963d
Compare
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.
Other than a few minor comments, looks good to me!
@lucyleeow will you have time to look? If not I think we can rely on our unit tests in addition to my review here, but this touches some core code so if you can look that's better if possible
Currently, all generated notebooks specify Python as the kernel. After downloading, | ||
the user will need to manually change to the correct kernel. |
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.
Maybe a follow-up PR? I think in principle changing the skeleton might do it
But I have no experience with this so...
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.
Yes, this is on my list for follow-on work.
@@ -10,7 +10,7 @@ clean: | |||
rm -rf gen_modules/ | |||
|
|||
html: | |||
sphinx-build -b html -d _build/doctrees $(SPHINXOPTS) . _build/html | |||
sphinx-build -b html -v -d _build/doctrees $(SPHINXOPTS) . _build/html |
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'd rather move the -v
to SPHINXOPTS at the top
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.
Sorry, I didn't mean to commit that in the first place.
Change signature of rst_blocks rather than changing contents of file_conf.
Also make parsing of almost all extensions opt-out
for more information, see https://pre-commit.ci
Allow just '%%' instead of '% %%'. Also, treat the rest of the line as a heading, which is what Matlab does. This is enabled for all languages, as it provides a nice short syntax for just adding headings to the code.
Include non-Python source files in the source code zip, and adjust the file name if it includes non-Python sources. Only generate Jupyter notebook zip file and link if at least some of the files are Jupyter compatible.
0157d3f
to
439eca5
Compare
I'll have a look next week. |
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.
Thanks @speth , this is great and well tested, only some nits.
doc/configuration.rst
Outdated
@@ -211,6 +214,25 @@ consult the `regular expressions`_ module for more details. | |||
|
|||
$ sphinx-build -D sphinx_gallery_conf.filename_pattern=plot_specific_example\.py ... | |||
|
|||
To parse examples in other languages, add their extensions to ``example_extensions``. |
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.
Maybe we could be more explicit in saying this is only parsing and syntax highlighting, not executing (I know its obvious for us)? Something like:
"You can also parse and highlight syntax examples in other languages by adding their extensions to example_extensions
, though they will not be executed."
doc/configuration.rst
Outdated
determined by the file extension. To override Pygments' default file associations, the | ||
``filetype_parsers`` option can be used to specify a ``dict`` mapping a file extension | ||
to any of the `pygments language names <https://pygments.org/languages/>`__. For | ||
example:: |
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.
If we specify a non default file association, should the extension in example_extensions
above be the default one or non-default one? Could we state 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 tried to clarify. This option isn't so much about handling the case of an extension with no corresponding lexer (though it can be used that way), but for the case where an extension corresponds to several lexers and Pygments' defaults to the wrong one. For example, Pygments lists '.m
as a known extension for Matlab, Objective-C, and Mason, with the default being Objective-C.
downloads can be enabled using the ``notebook_extensions`` option. For example:: | ||
|
||
sphinx_gallery_conf = { | ||
"notebook_extensions": {".py", ".jl"} |
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.
Again, if a non default extension is used in filetype_parsers
, should this be the default or non default extension? Could we state this?
doc/syntax.rst
Outdated
|
||
For such examples, the header for the example is defined by the first comment block | ||
in the file, which must contain a reST title, and may contain any additional reST | ||
content that should appear above the example. For example, A C++ example could start |
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.
content that should appear above the example. For example, A C++ example could start | |
content that should appear above the first code block. For example, a C++ example could start |
Any text following the special delimiter on the same line will be converted into a reST | ||
heading (underlined with ``-``). The reST block continues until a line that does not |
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.
Does the "(underlined with -
)" mean that the header should be underlined with -
or it will become a reST header as if it was underlined with e.g., -
?
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.
Also I am not so familiar with other languages, does 'single line' (?) comment languages make supporting the current header syntax not possible? e.g.,
# %%
# Header
# -----------
?
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.
It means that the underlining will be added, using the -
character. I specified this so the user would know what character to use if they wanted other headings at either the same or a different level.
The existing header syntax is also supported. However, in the case of Matlab, which has had the notion of "code cells" for a long time (possibly where this idea originated), the style is that text appearing on the same line as the %%
delimiter is treated as a heading, rather than ignored as sphinx-gallery currently does for Python scripts. Beyond Matlab, I thought it was a handy syntax especially in the case where all you want to add is the heading.
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.
Ah yes, sorry I think I got confused.
thumb, _ = _find_image_ext( | ||
os.path.join(target_dir, "images", "thumb", f"sphx_glr_{fname[:-3]}_thumb.png") | ||
os.path.join(target_dir, "images", "thumb", f"sphx_glr_{fname.stem}_thumb.png") |
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 is nice!
sphinx_gallery/block_parser.py
Outdated
@@ -0,0 +1,361 @@ | |||
"""BlockParser divides source files into blocks of code and markup text.""" |
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.
"""BlockParser divides source files into blocks of code and markup text.""" | |
"""BlockParser divides non `.py` source files into blocks of code and markup text.""" |
nitpick
sphinx_gallery/block_parser.py
Outdated
flag_start = rf"^[\ \t]*(?:{comment_start})\s*" | ||
|
||
self.infile_config_pattern = re.compile( | ||
flag_start + r"sphinx_gallery_([A-Za-z0-9_]+)(\s*=\s*(.+))?[\ \t]*\n?", |
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.
Nit, r"sphinx_gallery_([A-Za-z0-9_]+)(\s*=\s*(.+))?[\ \t]*\n?"
is repeated in py_source_parser.py
and is complex enough that we could use a variable? (Even if we refactor in future)
sphinx_gallery/block_parser.py
Outdated
("#= comment =#", "#=", "=#", None), # Julia multiline | ||
("# comment", "#", None, "#{20,}"), | ||
("// comment", "//", None, "/{20,}"), | ||
("/* comment */", r"/\*", r"\*/", r"/\*{20,}/"), | ||
("% comment", "%", None, "%{20,}"), | ||
("! comment", "!", None, "!{20,}"), | ||
("c comment", r"^c(?:$| )", None, None), |
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.
Do each of these correspond to a (or more) language? Could we add a comment specifying the associated language?
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.
Yes. I added some examples for each. There are others, but I didn't want to go overboard.
Thanks for the review, @lucyleeow and @larsoner. I think I've addressed all the review comments. |
Thank you @speth ! This is a great addition! |
… to version 0.15.0 v0.15.0 ------- Support for Python 3.7 dropped in this release. Requirement is now Python >=3.8. Pillow added as a dependency. **Implemented enhancements:** - ENH: Improve logging visibility of errors and filenames `#1225 <https://github.com/sphinx-gallery/sphinx-gallery/pull/1225>`__ (`larsoner <https://github.com/larsoner>`__) - ENH: Improve API usage graph `#1203 <https://github.com/sphinx-gallery/sphinx-gallery/pull/1203>`__ (`larsoner <https://github.com/larsoner>`__) - ENH: Always write sg_execution_times and make DataTable `#1198 <https://github.com/sphinx-gallery/sphinx-gallery/pull/1198>`__ (`larsoner <https://github.com/larsoner>`__) - ENH: Write all computation times `#1197 <https://github.com/sphinx-gallery/sphinx-gallery/pull/1197>`__ (`larsoner <https://github.com/larsoner>`__) - ENH: Support source files in any language `#1192 <https://github.com/sphinx-gallery/sphinx-gallery/pull/1192>`__ (`speth <https://github.com/speth>`__) - FEA Add examples recommender system `#1125 <https://github.com/sphinx-gallery/sphinx-gallery/pull/1125>`__ (`ArturoAmorQ <https://github.com/ArturoAmorQ>`__) (NEWS truncated at 15 lines)
This PR adds support for reading source files in any language supported by Pygments and generating annotated HTML files from them.
I saw the previous work that was attempted on multi-language support (#196/#197), and it's clear that some of the refactoring work that's been done since allowed this feature to be introduced with relatively few changes to the existing code base.
Obviously, this is a fair bit short of being able to execute such examples and collect outputs, but I think it's a useful capability for projects that have multiple language interfaces to be able to present examples this way, even if only the Python ones have all the bells and whistles.
There are a few things that still need to be resolved here, including additional tests and documentation, but I wanted to get some feedback first before going too much further. There is a bit of refactoring of
py_source_parser.py
that could be done to share some of the implementation with the newBlockParser
class, which I'd be happy to do if desired.For context, I'm one of the developers of Cantera, a library for chemical kinetics that provides interfaces in Python, Matlab, C++, and Fortran. I'm currently working toward a replacement for our home-grown index of examples, which is implemented as a set of extensions to Nikola as we move these examples into our Sphinx-generated site. I think
sphinx-gallery
provides a great set of features for our Python examples, but I don't want to leave our other interfaces behind. I'm hoping this will also be useful for other projects that include interfaces in multiple languages.