From f337310b43369e54f3874d733adec515615d629d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 10 Apr 2021 15:30:29 +1000 Subject: Cleanup: minor improvements & type hints for man-page generator - Use main() function. - Use argparse for parsing arguments. - Keep under 120 column width. - Use type hints (passes `mypy --strict`). --- doc/manpage/blender.1.py | 181 +++++++++++++++++++++++++++++++---------------- 1 file changed, 119 insertions(+), 62 deletions(-) (limited to 'doc/manpage/blender.1.py') diff --git a/doc/manpage/blender.1.py b/doc/manpage/blender.1.py index 150548072d5..932141be1a0 100755 --- a/doc/manpage/blender.1.py +++ b/doc/manpage/blender.1.py @@ -22,7 +22,7 @@ This script generates the blender.1 man page, embedding the help text from the Blender executable itself. Invoke it as follows: - blender.1.py + blender.1.py --blender --output where is the path to the Blender executable, and is where to write the generated man page. @@ -30,108 +30,137 @@ and is where to write the generated man page. # +import argparse import os import subprocess import sys - import time +from typing import ( + Dict, + TextIO, +) + -def man_format(data): +def man_format(data: str) -> str: data = data.replace("-", "\\-") data = data.replace("\t", " ") return data -if len(sys.argv) != 3: - import getopt - raise getopt.GetoptError("Usage: %s " % sys.argv[0]) +def blender_extract_info(blender_bin: str) -> Dict[str, str]: + + blender_env={ + "ASAN_OPTIONS": "exitcode=0:" + os.environ.get("ASAN_OPTIONS", ""), + } + + blender_help = subprocess.run( + [blender_bin, "--help"], + env=blender_env, + check=True, + stdout=subprocess.PIPE, + ).stdout.decode(encoding="utf-8") + + blender_version = subprocess.run( + [blender_bin, "--version"], + env=blender_env, + check=True, + stdout=subprocess.PIPE, + ).stdout.decode(encoding="utf-8").strip() -blender_bin = sys.argv[1] -outfilename = sys.argv[2] + blender_version, blender_date = (blender_version.split("build") + ["", ""])[0:2] + blender_version = blender_version.rstrip().partition(" ")[2] # Remove 'Blender' prefix. + + if not blender_date: + # Happens when built without WITH_BUILD_INFO e.g. + date_string = time.strftime("%B %d, %Y", time.gmtime(int(os.environ.get('SOURCE_DATE_EPOCH', time.time())))) + else: + blender_date = blender_date.strip().partition(" ")[2] # Remove 'date:' prefix. + date_string = time.strftime("%B %d, %Y", time.strptime(blender_date, "%Y-%m-%d")) + + return { + "help": blender_help, + "version": blender_version, + "date": date_string, + } -cmd = [blender_bin, "--help"] -print(" executing:", " ".join(cmd)) -ASAN_OPTIONS = "exitcode=0:" + os.environ.get("ASAN_OPTIONS", "") -blender_help = subprocess.run( - cmd, env={"ASAN_OPTIONS": ASAN_OPTIONS}, check=True, stdout=subprocess.PIPE).stdout.decode(encoding="utf-8") -blender_version = subprocess.run( - [blender_bin, "--version"], env={"ASAN_OPTIONS": ASAN_OPTIONS}, check=True, stdout=subprocess.PIPE).stdout.decode(encoding="utf-8").strip() -blender_version, blender_date = (blender_version.split("build") + [None, None])[0:2] -blender_version = blender_version.rstrip().partition(" ")[2] # remove 'Blender' prefix. -if blender_date is None: - # Happens when built without WITH_BUILD_INFO e.g. - date_string = time.strftime("%B %d, %Y", time.gmtime(int(os.environ.get('SOURCE_DATE_EPOCH', time.time())))) -else: - blender_date = blender_date.strip().partition(" ")[2] # remove 'date:' prefix - date_string = time.strftime("%B %d, %Y", time.strptime(blender_date, "%Y-%m-%d")) -outfile = open(outfilename, "w") -fw = outfile.write +def man_page_from_blender_help(fh: TextIO, blender_bin: str) -> None: + blender_info = blender_extract_info(blender_bin) -fw('.TH "BLENDER" "1" "%s" "Blender %s"\n' % (date_string, blender_version.replace(".", "\\&."))) + # Header Content. + fh.write( + '.TH "BLENDER" "1" "%s" "Blender %s"\n' % + (blender_info["date"], blender_info["version"].replace(".", "\\&.")) + ) -fw(''' + fh.write(''' .SH NAME blender \- a full-featured 3D application''') -fw(''' + fh.write(''' .SH SYNOPSIS .B blender [args ...] [file] [args ...]''') -fw(''' + fh.write(''' .br .SH DESCRIPTION .PP .B blender -is a full-featured 3D application. It supports the entirety of the 3D pipeline - modeling, rigging, animation, simulation, rendering, compositing, motion tracking, and video editing. +is a full-featured 3D application. It supports the entirety of the 3D pipeline - \ +modeling, rigging, animation, simulation, rendering, compositing, motion tracking, and video editing. -Use Blender to create 3D images and animations, films and commercials, content for games, architectural and industrial visualizatons, and scientific visualizations. +Use Blender to create 3D images and animations, films and commercials, content for games, \ +architectural and industrial visualizatons, and scientific visualizations. https://www.blender.org''') -fw(''' + fh.write(''' .SH OPTIONS''') -fw("\n\n") + fh.write("\n\n") -lines = [line.rstrip() for line in blender_help.split("\n")] + # Body Content. -while lines: - l = lines.pop(0) - if l.startswith("Environment Variables:"): - fw('.SH "ENVIRONMENT VARIABLES"\n') - elif l.endswith(":"): # one line - fw('.SS "%s"\n\n' % l) - elif l.startswith("-") or l.startswith("/"): # can be multi line + lines = [line.rstrip() for line in blender_info["help"].split("\n")] - fw('.TP\n') - fw('.B %s\n' % man_format(l)) + while lines: + l = lines.pop(0) + if l.startswith("Environment Variables:"): + fh.write('.SH "ENVIRONMENT VARIABLES"\n') + elif l.endswith(":"): # One line. + fh.write('.SS "%s"\n\n' % l) + elif l.startswith("-") or l.startswith("/"): # Can be multi line. + fh.write('.TP\n') + fh.write('.B %s\n' % man_format(l)) - while lines: - # line with no - if lines[0].strip() and len(lines[0].lstrip()) == len(lines[0]): # no white space - break + while lines: + # line with no + if lines[0].strip() and len(lines[0].lstrip()) == len(lines[0]): # No white space. + break - if not l: # second blank line - fw('.IP\n') - else: - fw('.br\n') + if not l: # Second blank line. + fh.write('.IP\n') + else: + fh.write('.br\n') - l = lines.pop(0) - l = l[1:] # remove first whitespace (tab) + l = lines.pop(0) + if l: + assert(l.startswith('\t')) + l = l[1:] # Remove first white-space (tab). - fw('%s\n' % man_format(l)) + fh.write('%s\n' % man_format(l)) - else: - if not l.strip(): - fw('.br\n') else: - fw('%s\n' % man_format(l)) + if not l.strip(): + fh.write('.br\n') + else: + fh.write('%s\n' % man_format(l)) -# footer + # Footer Content. -fw(''' + fh.write( + ''' .br .SH SEE ALSO .B luxrender(1) @@ -143,5 +172,33 @@ This manpage was written for a Debian GNU/Linux system by Daniel Mester and Dan Eicher . ''') -outfile.close() -print("written:", outfilename) + +def create_argparse() -> argparse.ArgumentParser: + parser = argparse.ArgumentParser() + parser.add_argument( + "--output", + required=True, + help="The man page to write to." + ) + parser.add_argument( + "--blender", + required=True, + help="Path to the blender binary." + ) + + return parser + + +def main() -> None: + parser = create_argparse() + args = parser.parse_args() + + blender_bin = args.blender + output_filename = args.output + + with open(output_filename, "w", encoding="utf-8") as fh: + man_page_from_blender_help(fh, blender_bin) + + +if __name__ == "__main__": + main() -- cgit v1.2.3