[Bf-blender-cvs] [f337310b433] master: Cleanup: minor improvements & type hints for man-page generator

Campbell Barton noreply at git.blender.org
Sat Apr 10 09:55:30 CEST 2021


Commit: f337310b43369e54f3874d733adec515615d629d
Author: Campbell Barton
Date:   Sat Apr 10 15:30:29 2021 +1000
Branches: master
https://developer.blender.org/rBf337310b43369e54f3874d733adec515615d629d

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`).

===================================================================

M	doc/manpage/blender.1.py
M	source/creator/CMakeLists.txt

===================================================================

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 <path-to-blender> <output-filename>
+    blender.1.py --blender <path-to-blender> --output <output-filename>
 
 where <path-to-blender> is the path to the Blender executable,
 and <output-filename> is where to write the generated man page.
@@ -30,108 +30,137 @@ and <output-filename> is where to write the generated man page.
 
 # <pep8 compliant>
 
+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 <path-to-blender> <output-filename>" % 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
 <cyril.brulebois at enst-bretagne.fr> and Dan Eicher <dan at trollwerks.org>.
 ''')
 
-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()
diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt
index 90840aa8358..cb5fc538e69 100644
--- a/source/creator/CMakeLists.txt
+++ b/source/creator/CMakeLists.txt
@@ -463,8 +463,8 @@ if(UNIX AND NOT APPLE)
       add_custom_target(
         blender_man_page ALL
         COMMAND ${CMAKE_SOURCE_DIR}/doc/manpage/blender.1.py
-                ${EXECUTABLE_OUTPUT_PATH}/blender
-                ${CMAKE_CURRENT_BINARY_DIR}/blender.1)
+                --blender ${EXECUTABLE_OUTPUT_PATH}/blender
+                --output ${CMAKE_CURRENT_BINARY_DIR}/blender.1)
       add_dependencies(blender_man_page blender)
     endif()
   endif()



More information about the Bf-blender-cvs mailing list