Skip to main content

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

readme_executor-0.9.1.tar.gz (5.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

readme_executor-0.9.1-py3-none-any.whl (6.8 kB view details)

Uploaded Python 3

File details

Details for the file readme_executor-0.9.1.tar.gz.

File metadata

  • Download URL: readme_executor-0.9.1.tar.gz
  • Upload date:
  • Size: 5.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: python-requests/2.25.1

File hashes

Hashes for readme_executor-0.9.1.tar.gz
Algorithm Hash digest
SHA256 bbe5573f2e59f4b85bdaa4f73c8de00f260f8b35aa3ae51dd598a261051847db
MD5 d8468c5c32d1f6b9bed145e3aa331db9
BLAKE2b-256 fa4138726a1839731f4080e98f51a545bce9d77ee1a5148c59a3bc79562d5b2b

See more details on using hashes here.

File details

Details for the file readme_executor-0.9.1-py3-none-any.whl.

File metadata

File hashes

Hashes for readme_executor-0.9.1-py3-none-any.whl
Algorithm Hash digest
SHA256 33698b574d7018ac0592284e2d23ca433c5fc380a98df81768be8f655a371d39
MD5 0946a4c4452ebc2feadeac2b49065cc8
BLAKE2b-256 74cc2aa192e72aec83f17a276dbd60824d09c4a639dc8aa336885f0c46560cd4

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page