The goal of this test is to try to import some critical py scripts with the system python of the building machine. The main target is to ensure that these py scripts remain usable by all buildbot machines, as some of them are using fairly outdated python versions. Current status: * Scripts in `build_files` and `docs` are checked. * Some python scripts in `build_files` were 'reverted' to be compatible with older required python version currently (3.6). * A few scripts are excluded from the test, mostly because they use Blender's `bpy` module, which means they are only intended to be ran with Blender's python anyway. * The test is only enabled for Linux buildbots currently, as they use the oldest Python by far. Notes: * Some more scripts are likely to be moved around in the future. * Whether these tests need to be enabled on windows or macos platforms remains an open question. Pull Request: https://projects.blender.org/blender/blender/pulls/130746
231 lines
6.6 KiB
Python
Executable File
231 lines
6.6 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
# SPDX-FileCopyrightText: 2010-2023 Blender Authors
|
|
#
|
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
"""
|
|
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 <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.
|
|
"""
|
|
|
|
import argparse
|
|
import os
|
|
import subprocess
|
|
import time
|
|
|
|
from typing import (
|
|
TextIO,
|
|
Dict,
|
|
)
|
|
|
|
|
|
def man_format(data: str) -> str:
|
|
data = data.replace("-", "\\-")
|
|
data = data.replace("\t", " ")
|
|
# Single quotes prevent text rendering when found at the beginning of lines.
|
|
data = data.replace("'", "\\(aq")
|
|
return data
|
|
|
|
|
|
def blender_extract_info(blender_bin: str) -> Dict[str, str]:
|
|
blender_env = {
|
|
"ASAN_OPTIONS": (
|
|
os.environ.get("ASAN_OPTIONS", "") +
|
|
":exitcode=0:check_initialization_order=0:strict_init_order=0"
|
|
).lstrip(":"),
|
|
}
|
|
|
|
# NOTE: in some ways it's more elegant to use `bpy.app.help_text()` which was done but had to be reverted.
|
|
# however - this requires Blender to run with a full environment (initializing it's Python environment).
|
|
# See #115056 & !115320 for details.
|
|
|
|
blender_help = subprocess.run(
|
|
[blender_bin, "--help"],
|
|
env=blender_env,
|
|
check=True,
|
|
stdout=subprocess.PIPE,
|
|
).stdout.decode(encoding="utf-8")
|
|
|
|
blender_version_output = subprocess.run(
|
|
[blender_bin, "--version"],
|
|
env=blender_env,
|
|
check=True,
|
|
stdout=subprocess.PIPE,
|
|
).stdout.decode(encoding="utf-8")
|
|
|
|
# Extract information from the version string.
|
|
# Note that some internal modules may print errors (e.g. color management),
|
|
# check for each lines prefix to ensure these aren't included.
|
|
blender_version = ""
|
|
blender_date = ""
|
|
|
|
# The full text (use to manipulate `blender_version_text`).
|
|
blender_version_text = ""
|
|
|
|
for l in blender_version_output.split("\n"):
|
|
if l.startswith("Blender "):
|
|
if blender_version_text == "":
|
|
blender_version_text = l
|
|
# Remove `Blender` prefix.
|
|
blender_version = l.split(" ", 1)[1].strip()
|
|
elif l.lstrip().startswith("build date:"):
|
|
# Remove `build date:` prefix.
|
|
blender_date = l.split(":", 1)[1].strip()
|
|
if blender_version and blender_date:
|
|
break
|
|
|
|
# The `--help` text also contains the version, skip it so as not to include it twice.
|
|
if blender_version_text:
|
|
i = blender_help.find(blender_version_text)
|
|
if i != -1:
|
|
blender_help = blender_help[i + len(blender_version_text) + 1:]
|
|
del i
|
|
|
|
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:
|
|
date_string = time.strftime("%B %d, %Y", time.strptime(blender_date, "%Y-%m-%d"))
|
|
|
|
return {
|
|
"help": blender_help,
|
|
"version": blender_version,
|
|
"date": date_string,
|
|
}
|
|
|
|
|
|
def man_page_from_blender_help(fh: TextIO, blender_bin: str, verbose: bool) -> None:
|
|
if verbose:
|
|
print("Extracting help text:", blender_bin)
|
|
blender_info = blender_extract_info(blender_bin)
|
|
|
|
# Header Content.
|
|
fh.write(
|
|
'.TH "BLENDER" "1" "{:s}" "Blender {:s}"\n'.format(
|
|
blender_info["date"], blender_info["version"].replace(".", "\\&.")
|
|
)
|
|
)
|
|
|
|
fh.write(r"""
|
|
.SH NAME
|
|
blender \- a full-featured 3D application""")
|
|
|
|
fh.write(r"""
|
|
.SH SYNOPSIS
|
|
.B blender [args ...] [file] [args ...]""")
|
|
|
|
fh.write(r"""
|
|
.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.
|
|
|
|
Use Blender to create 3D images and animations, films and commercials, content for games, """
|
|
r"""architectural and industrial visualizations, and scientific visualizations.
|
|
|
|
https://www.blender.org""")
|
|
|
|
fh.write(r"""
|
|
.SH OPTIONS""")
|
|
|
|
fh.write("\n\n")
|
|
|
|
# Body Content.
|
|
|
|
lines = [line.rstrip() for line in blender_info["help"].split("\n")]
|
|
|
|
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'.format(l))
|
|
elif l.startswith("-") or l.startswith("/"): # Can be multi line.
|
|
fh.write('.TP\n')
|
|
fh.write('.B {:s}\n'.format(man_format(l)))
|
|
|
|
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.
|
|
fh.write('.IP\n')
|
|
else:
|
|
fh.write('.br\n')
|
|
|
|
l = lines.pop(0)
|
|
if l:
|
|
assert l.startswith('\t')
|
|
l = l[1:] # Remove first white-space (tab).
|
|
|
|
fh.write('{:s}\n'.format(man_format(l)))
|
|
|
|
else:
|
|
if not l.strip():
|
|
fh.write('.br\n')
|
|
else:
|
|
fh.write('{:s}\n'.format(man_format(l)))
|
|
|
|
# Footer Content.
|
|
|
|
fh.write(r"""
|
|
.br
|
|
.SH SEE ALSO
|
|
.B luxrender(1)
|
|
|
|
.br
|
|
.SH AUTHORS
|
|
This manpage was written for a Debian GNU/Linux system by Daniel Mester
|
|
<mester@uni-bremen.de> and updated by Cyril Brulebois
|
|
<cyril.brulebois@enst-bretagne.fr> and Dan Eicher <dan@trollwerks.org>.
|
|
""")
|
|
|
|
|
|
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."
|
|
)
|
|
parser.add_argument(
|
|
"--verbose",
|
|
default=False,
|
|
required=False,
|
|
action='store_true',
|
|
help="Print additional progress."
|
|
)
|
|
|
|
return parser
|
|
|
|
|
|
def main() -> None:
|
|
parser = create_argparse()
|
|
args = parser.parse_args()
|
|
|
|
output_filename = args.output
|
|
blender_bin = args.blender
|
|
verbose = args.verbose
|
|
|
|
with open(output_filename, "w", encoding="utf-8") as fh:
|
|
man_page_from_blender_help(fh, blender_bin, verbose)
|
|
if verbose:
|
|
print("Written:", output_filename)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|