pypod
PyPOD is a simple markup language used for embedding documentation in Python scripts. It is a subset of the Perl Plain-Old-Documentation (POD).
Information and software on this web site are provided under the Granite Mountain Informatics LLC End User License Agreement (EULA).
Send questions or comments to GraniteMountainInformaticsLLC@gmail.com.
"""
=pod
=head1 NAME
pypod.py
=head1 VERSION
202302141500
=head1 SYNOPSIS
python3 pypod.py FileSpecification
=head1 DESCRIPTION
PyPOD is a simple markup language used for embedding documentation in Python scripts. It is based on Perl Plain-Old-Documentation (POD).
The pypod.py Python program converts PyPOD embedded in a Python script into an HTML document.
=head2 PyPOD Blocks
There can be one or more PyPOD blocks in the Python source code file. PyPOD blocks start with the "=pod" command and end with the "=cut" command in a Python multiline string block that begins and ends with 3 consecutive double quotes on separate lines.
=head2 Paragraphs
Paragraphs consist of text that starts at the left margin and ends with the end of the line.
=head2 Plain Text
Any paragraph that begins with a space or tab and consists of text that starts at the left margin and ends with the end of the line.
Plain Text that starts with a space
Plain Text that starts with a tab
=head2 Command Statements
=head2 head commands
The "=head1" through "=head6" command statements produce headings.
=head1 Label Text
=head2 Label Text
=head3 Label Text
=head4 Label Text
=head5 Label Text
=head6 Label Text
=head2 html command
HTML statements can be embedded between "=begin html" and "=end html" statements.
=begin html
<p>This is an embedded HTML paragraph</p>
=end html
=head2 Differences Between Perl POD and Python PyPOD
PyPOD is a subset of Perl POD and only supports the previously specified functionality of Perl POD.
For example, PyPOD does not support Perl POD "Formatting Codes" since embedded HTML can be used for that purpose.
=cut
"""
# ######################################################################
# IMPORT CORE MODULES
# ######################################################################
import datetime
import glob
import os
import re
import sys
import time
print(' '.join(sys.argv))
# ######################################################################
# IMPORT CUSTOM MODULES
# ######################################################################
# ######################################################################
# DECLARE FUNCTIONS
# ######################################################################
"""
nv(n, v)
Prints the string "[DEBUG] name: value.
"""
def nv(n, v):
print(f"[DEBUG] {n}='{v}'")
# ######################################################################
# DECLARE GLOBAL CONSTANTS
# ######################################################################
yyyymmddhhmmss = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
#nv('yyyymmddhhmmss', yyyymmddhhmmss)
# ######################################################################
# DECLARE GLOBAL VARIABLES
# ######################################################################
# ######################################################################
# GET COMMAND LINE ARGUMENTS
# ######################################################################
# get the python file specification
fs = sys.argv[1]
#nv('fs', fs)
if fs == '':
print("FATAL Command line argument 'fs' is not defined")
sys.exit()
if not os.path.exists(fs):
print(f"FATAL Command line argument 'fs' does not exist: {fs}")
sys.exit()
# ######################################################################
# MAIN
# ######################################################################
# get the pod in the input file
pod_list = []
pod_bool = False
with open(fs, 'r') as fh:
for line in fh:
s = line.rstrip()
if re.match('^=pod', s):
#pod_list.append(s)
pod_bool = True
elif re.match('^=cut', s):
#pod_list.append(s)
pod_bool = False
elif pod_bool:
pod_list.append(s)
#nv('pod_list', pod_list)
# convert pod to HTML
html_head_list = []
html_body_list = []
index_list = []
for s in pod_list:
#nv('s', s)
m = re.match('^\s', s)
if m:
html_body_list.append(f"<pre>{s}</pre>")
continue
# get command statements
m = re.match('^=(.+?) (.+?)$', s)
if m:
command = m.group(1)
#nv('command', command)
text = m.group(2)
#nv('text', text)
head_index = 0
m = re.match('^head(.+?)$', command)
if m:
head_index = int(m.group(1))
#nv('head_index', head_index)
index_list.append([head_index, text])
if command == 'head1':
html_body_list.append(f"<h1 id=\"{text}\">{text}</h1>")
elif command == 'head2':
html_body_list.append(f"<h2 id=\"{text}\">{text}</h2>")
elif command == 'head3':
html_body_list.append(f"<h3 id=\"{text}\">{text}</h3>")
elif command == 'head4':
html_body_list.append(f"<h4 id=\"{text}\">{text}</h4>")
elif command == 'head5':
html_body_list.append(f"<h5 id=\"{text}\">{text}</h5>")
elif command == 'head6':
html_body_list.append(f"<h6 id=\"{text}\">{text}</h6>")
elif command == 'begin' and text == 'html':
while True:
m = re.match('^=end\s+html$', s)
if m:
break
html_body_list.append(s)
continue
html_body_list.append(f"<p>{s}</p>")
#nv('html_head_list', html_head_list)
#nv('html_body_list', html_body_list)
#nv('index_list', index_list)
# assemble the HTML index
html_index_list = ['<ul id="index">']
prev_index = 1
for row in index_list:
this_index = row[0]
this_text = row[1]
if this_index > prev_index:
html_index_list.append('<ul>')
prev_index = this_index
elif this_index == prev_index:
html_index_list.append(f"<li><a href=\"#{row[1]}\">{row[1]}</a></li>")
elif this_index < prev_index:
html_index_list.append('</ul>')
prev_index = this_index
html_index_list.append('</ul>')
#nv('html_index_list', html_index_list)
# write HTML to a file
fs_html = os.path.basename(fs) + '.html'
with open(fs_html, 'w', encoding='utf-8') as fh_html:
fh_html.write("<html>\n")
fh_html.write("<head>\n")
for s in html_head_list:
fh_html.write(s + "\n")
fh_html.write("</head>\n")
fh_html.write("<body>\n")
for s in html_index_list:
fh_html.write(s + "\n")
for s in html_body_list:
fh_html.write(s + "\n")
fh_html.write("</body>\n")
fh_html.write("</html>\n")
"""
=pod
=head1 REQUIRES
=head1 INSTALLATION
=head1 SEE ALSO
=head1 AUTHOR
Granite Mountain Informatics LLC
=head1 COPYRIGHT
Copyright 2023 Granite Mountain Informatics LLC
All Rights Reserved
=head1 PROPRIETARY SOFTWARE LICENSE
=head1 CHANGE HISTORY
=head1 TO DO
=cut
"""
The pypod.py utility can be executed using the following commands in a linux shell script:
clear
python3 pypod.py "FileName"
open -a 'Google Chrome' ./FileName.html
Executing the pypod.py utility renders the embedded PyPOD as HTML:
Finally, the function nv(n, v) in the code will print lines like "DEBUG n='v'". These "debug" lines are commented out in the code. To view the output uncomment these lines in your version of the code.