Skip to content
Snippets Groups Projects
Commit 2be01abe authored by Gigg, Martyn Anthony's avatar Gigg, Martyn Anthony
Browse files

Allow runsphinx_*.py scripts to be called by anyone

The driver script for running the sphinx process can now be called by a
user without any special requirements. The main use case will be
running a doctest individually.

It should be noted that even restricting the run to a single file with the
new -R option will actually still cause Sphinx to read every source file
at least once. This is baked in to Sphinx and cannot be avoided. However,
the config pickling does mean that all source files are only read once and
then after this only changed files are reread.
Refs #9639
Refs #
parent 84cf682b
No related branches found
No related tags found
No related merge requests found
...@@ -2,57 +2,172 @@ ...@@ -2,57 +2,172 @@
module. This script calls the sphinx entry point with the necessary module. This script calls the sphinx entry point with the necessary
arguments arguments
""" """
from optparse import OptionParser
import os import os
import re
import sys import sys
#----------------------------------------------------------------------------------------------- DOC_EXT = ".rst"
def pathjoin(left, *args):
###############################################################################
# CMake-populated variables
###############################################################################
BUILDER = "@BUILDER@"
SRC_DIR = "@SPHINX_SRC_DIR@"
CONF_DIR = "@SPHINX_CONF_DIR@"
SPHINX_BUILD_DIR = "@SPHINX_BUILD_DIR@"
SCREENSHOTS_DIR = "@SCREENSHOTS_DIR@"
###############################################################################
# Main
###############################################################################
def main(sysarg):
""" """
Similar to os.path.join but just uses "/" as it's populated with CMake-style paths that are Execute the Sphinx build.
always "/" separated, even on Windows.
Args:
sysarg (list): A list of strings giving arguments to the script,
where it is assumed that the path to the script is the
first argument
""" """
return left + "/" + "/".join(args) opts, args = parseargs(sysarg)
if len(args) > 0:
raise RuntimeError("Unexpected command line arguments: %s. "
"Use -h for help" % ' '.join(args))
#----------------------------------------------------------------------------------------------- # Update sys path if we need to
update_path(opts.mantidpath)
def main(): # Find test files
# Update path to find mantid testpaths = find_test_files(SRC_DIR, opts.testinclude)
package_dir = "@CMAKE_LIBRARY_OUTPUT_DIRECTORY@"
runtime_config = os.environ.get("RUNTIME_CONFIG", "") # for visual studio and xcode # Update environment with screenshots path if necessary
if runtime_config != "": if SCREENSHOTS_DIR != "":
package_dir = pathjoin(package_dir, runtime_config) os.environ["SCREENSHOTS_DIR"] = SCREENSHOTS_DIR
sys.path.insert(0, package_dir)
# Update environment with screenshots path
screenshots_dir = "@SCREENSHOTS_DIR@"
if screenshots_dir != "":
os.environ["SCREENSHOTS_DIR"] = screenshots_dir
# All paths are cmake style so are "/" separated, even on Windows
builder = "@BUILDER@"
src_dir = "@SPHINX_SRC_DIR@"
conf_dir = "@SPHINX_CONF_DIR@"
sphinx_build_dir = "@SPHINX_BUILD_DIR@"
output_dir = pathjoin(sphinx_build_dir, builder)
doctree_dir = pathjoin(sphinx_build_dir, "doctrees")
# Arguments for main # Arguments for main
output_dir = pathjoin(SPHINX_BUILD_DIR, BUILDER)
doctree_dir = pathjoin(SPHINX_BUILD_DIR, "doctrees")
argv = [sys.executable, argv = [sys.executable,
"-b", builder, "-b", BUILDER,
"-d", doctree_dir, "-d", doctree_dir,
"-c", conf_dir, "-c", CONF_DIR,
src_dir, output_dir] SRC_DIR, output_dir]
# See if we have been told to only process a particular file if testpaths is not None:
src_file = os.environ.get("SPHINX_SRC_FILE", None) if len(testpaths) > 0:
if src_file is not None: argv.extend(testpaths)
argv.append(src_file) else:
raise RuntimeError("No tests matched regex '%s'"
% opts.testinclude)
# Run # Run
import sphinx import sphinx
sys.exit(sphinx.main(argv)) sys.exit(sphinx.main(argv))
#-----------------------------------------------------------------------------------------------
def parseargs(arglist):
"""
Split script arguments into options and arguments.
Args:
arglist: List of strings to control program
"""
parser = OptionParser(usage="Usage: %prog [options]",
conflict_handler='error')
parser.add_option("-m", "--mantidpath", dest="mantidpath",
help="Location of mantid package. Has no effect if run inside MantidPlot")
parser.add_option("-R", "--tests-regex", dest="testinclude",
help="Regex specifying which tests to run. It is matched against the "
"filename when considering whether to run a test.")
return parser.parse_args(arglist[1:]) # hack off filename
#-----------------------------------------------------------------------------------------------
def update_path(mantidpath):
"""
If not inside MantidPlot (current check is whether we can import _qti)
then insert given path as first directory in sys.path
Args:
mantidpath (str): A string giving the location of the mantid module
"""
try:
import _qti
gui = True
except ImportError:
gui = False
# If it's MantidPlot then we already know what our paths should be so ignore it
if gui:
return
# check for directory
if not os.path.isdir(os.path.join(mantidpath, "mantid")):
raise ValueError("Unable to find mantid package in '%s'" % mantidpath)
# is package valid
if not os.path.isfile(os.path.join(mantidpath, "mantid", "__init__.py")):
raise ValueError("Invalid mantid package. No __init__ found in '%s' %s")
# Update sys.path
sys.path.insert(0, mantidpath)
#-----------------------------------------------------------------------------------------------
def find_test_files(src_dir, name_re):
"""
Find the test files that should be run based on a source directory
and regex.
Args:
src_dir (str): A string giving the source directory of doc files
name_re (str): A regex to match against a test filename.
Returns:
A list of paths to the chosen test files.
"""
name_re_comp = re.compile(name_re)
testpaths = []
for dirpath, dirnames, filenames in os.walk(src_dir):
testfiles = find_matching_tests(filenames, name_re_comp)
# Join each filename with the current path and extend the list
testpaths.extend(map(lambda x: os.path.join(dirpath, x), testfiles))
return testpaths
def find_matching_tests(filenames, name_re):
"""
For a list of filenames, return the list that matches the given
regex
Args:
filenames: A list of filenames
name_re (re.regex): A compiled regex object
Returns:
A list of matching test names
"""
testfiles = []
for filename in filenames:
if not filename.endswith(DOC_EXT):
continue
if name_re.match(filename.rstrip(DOC_EXT)):
testfiles.append(filename)
return testfiles
#-----------------------------------------------------------------------------------------------
def pathjoin(left, *args):
"""
Similar to os.path.join but just uses "/" as it's populated with CMake-style paths that are
always "/" separated, even on Windows.
"""
return left + "/" + "/".join(args)
#-----------------------------------------------------------------------------------------------
################################################################################## ##################################################################################
if __name__ == "__main__": if __name__ == "__main__":
main() main(sys.argv)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment