Module to execute tagged Python code blocks in Markdown files
Project description
README EXECUTOR
A tool for executing Python code blocks in Markdown documentation.
Copyright 2022 Randall Morgan
Introduction
This script reads Markdown documents, locating tagged Python code blocks, executing them, and capturing their output. The output from the code block is then inserted into a generated Markdown document.
This script was developed to help ensure that code samples in Python project documentation actually reflected the current version of the software. Running this script as part of the CI/CD process will help you keep your docs current with the latest software version. Note that this script does not parse Python code to generate Markdown documentation. There are many good tools for that already. The focus of this tool is solely to aid in maintaining code samples in that documentation.
Usage
This script is ran on an existing Markdown document template. The template is a regular Markdown document containing specially tagged code blocks as described below. In fact, this script was used to generate this readme you are reading now. It was generated using the Markdown template file /doc_src/readme_template.md found in the doc_src folder of this project. It is recommended that you read the template file as well as this document to gain a full understanding before creating your own Markdown template files for your projects.
Since this document includes textual code snippets and actual tagged code blocks. I have denoted the textual code snippets with Rendered and the tagged code blocks that are parsed and executed with Code. This will aid in grokking the Markdown template and demonstrates how the code blocks are displayed in the final document.
Running the script:
If this script is invoked without specifying an input file, input will be taken from standard input (stdin). If an output file is not specified, output will be sent to standard out (stdout). A debug flag (-d) may be passed on the command line. When provided, the script displays the code blocks it found and parsed. A force-overwrite flag (-f) can also be specified and will cause the script to overwrite an existing output file.
Command-Line Options:
usage: Examples:
----------------
readme_executor.py # Input taken from stdin, output is stdout
readme_executor.py -i doc_src/readme.md # Input file specified, output will be stdout
readme_executor.py -i doc_src/classes.md -o docs/classes_doc.md # Input and Output filename specified in command
readme_executor.py -i doc_src/contrib.md -o docs/contributing.md -d # Display all matched code blocks for debugging
readme_executor.py -i doc_src/contrib.md -o docs/contributing.md -f # Force existing output file to be overwritten.
options:
-h, --help show this help message and exit
-i INFILE, --infile INFILE
The source markdown document
-o OUTFILE, --outfile OUTFILE
The markdown file to be generated
-d, --debug Outputs the tagged code blocks found by the parser
This is helpful for debugging when results are not as
expected
-f, --force Force output to overwrite existing file
Example Invocations
$ readme_executor.py # input will be taken from stdin, and output sent to stdout
$ readme_executor.py -i ./doc_src/readme_template.md # input file specified, output sent to stdout
$ readme_executor.py -i ./doc_src/readme_template.md -o ./docs/readme.md # input and output files specified
$ readme_executor.py -i ./doc_src/readme_template.md -o ./docs/readme.md -d # debug output
$ readme_executor.py -i ./doc_src/readme_template.md -o ./docs/readme.md -f # force the script to overwrite an existing output file
Tagging Code Blocks
Non-Tagged Code blocks
Non-tagged code blocks like this are not processed:
print('Leave this alone')
Tagged Code Blocks
Code blocks containing directives will be processed. A directive is made up of three parts:
* The delimiters: { and }.
* The language indicator: .python
* The directive: capture, replace, exception
Putting this all together a typical tagged code block would look like:
''' { .python capture }
import math
x, y = 47, 96
print(f'Coords: {math.sin(x)}, {math.cos(y)}')
'''
Note that while triple single-quotes are shown here, triple back-ticks are required in the markdown file. Note that currently Python is the only programming language supported. But this may change in the future.
Capture
The capture directive indicates that the standard output should be captured and inserted as a new code block below the code.
Rendered
''' { .python capture }
print('This output should be captured!')
print('This too')
'''
Code
print('This output should be captured!')
print('This too')
Output:
This output should be captured!
This too
Replace
The replace directive indicates that the code should be replaced by the output.
This code...
Rendered:
''' { .python replace }
print('A replace cell')
'''
Gets replaced with: Code
A replace cell
Exception
The exception directive indicates that the code should raise an Exception.
The traceback is then inserted instead of the standard output.
The exception directive is used with the capture and replace directives.
Rendered
''' { .python capture exception }
# A cell that should raise a ValueError
int('x')
'''
Code
# A cell that should raise a ValueError
int('x')
Output:
invalid literal for int() with base 10: 'x'
API
If you wish to use readme_executor as a module in your own document processor, the following text will help.
## parse_text(md_in: str, debug=False) -> str
Accepts a `str` containing Markdown text, then finds the tagged code blocks
in the markdown, executes these code blocks and captures the output, which is
then embedded into the output markdown.
### Parameters
* md_in: str
The input Markdown text string
* debug: bool
default: False, if True outputs mathing tagged code blocks
### Returns
str
The compiled markdown string
## parse_file(src: str, dest: str, debug=False)
Takes a markdown file as input, executes any code blocks contained within,
captures the output and write the result to a new file.
* src: str
The full path to the input file
* dest: str
The full path for the output file
License
This software is licensed under the GNU General Public License version 2 or later. At the user's discretion. You are free to use this script, and it's source code any way you like.
Waranty
This software is provided without warranty of any kind! The user is solely responsibility to determine the suitability of this software for their own specific use case.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file readme_executor-0.9.0.tar.gz.
File metadata
- Download URL: readme_executor-0.9.0.tar.gz
- Upload date:
- Size: 5.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: python-requests/2.25.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
959f0b73a53fc95530792fff88d2cf2bc9151c3747ae7ab6cddd2fe1e4f2ef7a
|
|
| MD5 |
b590caf9f9cea8ffe411da6013a11eec
|
|
| BLAKE2b-256 |
5697128a97a9be0587d1658a6235762538a31b53cb0ab4dac7236379dee2c0b7
|
File details
Details for the file readme_executor-0.9.0-py3-none-any.whl.
File metadata
- Download URL: readme_executor-0.9.0-py3-none-any.whl
- Upload date:
- Size: 6.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: python-requests/2.25.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a1b899659b1c8e5acbce0cf21bfd086ffb7c9b58dd302d0b45765300471acefa
|
|
| MD5 |
4dfa562b17120f2223aae1381094bfe4
|
|
| BLAKE2b-256 |
324c4e9cc78b3058a920557da0df2db2e5e9a33620cf972e3f48c97e05331a8d
|