From 7438f44fcb54954f7c30854bddc23dcb3a217d45 Mon Sep 17 00:00:00 2001 From: Patrick Avery Date: Sat, 2 Apr 2022 07:56:16 -0500 Subject: [PATCH] feat(paraview): add paraview to sys.path when requested Trame can now find and add the paraview python library path to the sys.path if `trame.env.paraview` was imported and the path to paraview was specified. It can be specified either via the `TRAME_PARAVIEW` environment variable or a `--paraview ` argument on the command line. This enables paraview to be imported and used. Signed-off-by: Patrick Avery --- trame/env/__init__.py | 0 trame/env/paraview.py | 59 ++++++++++++++++++++++++++++++++++++++ trame/env/utils.py | 66 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 125 insertions(+) create mode 100644 trame/env/__init__.py create mode 100644 trame/env/paraview.py create mode 100644 trame/env/utils.py diff --git a/trame/env/__init__.py b/trame/env/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/trame/env/paraview.py b/trame/env/paraview.py new file mode 100644 index 00000000..3bc5daf7 --- /dev/null +++ b/trame/env/paraview.py @@ -0,0 +1,59 @@ +"""Set up sys.path to include ParaView, if available + +This checks the TRAME_PARAVIEW environment variable and the --paraview +argument in sys.argv. The specified path will then be automatically +searched for the python library directory and, if found, it will be +added to the sys.path so that the ParaView libraries may be imported. + +To use: specify one of the following, and then import this file: + - `--paraview /path/to/paraview/release` argument + - environment variable `TRAME_PARAVIEW=/path/to/paraview/release` +""" +import platform +import sys + +from .utils import prepend_python_path, find_env_setting + +PV_LOADED = False + +PV_HOME = find_env_setting("--paraview", "TRAME_PARAVIEW") + +if PV_HOME is None: + msg = ( + "trame.env.paraview was imported, but the paraview location was not " + "defined. Define it with either the argument '--paraview ' or " + "the TRAME_PARAVIEW environment variable" + ) + raise Exception(msg) + + +# Each of the following functions returns a list of paths to try +# for the specified OS. +def linux_paths(): + py_major, py_minor = sys.version_info[:2] + return [f"lib/python{py_major}.{py_minor}/site-packages"] + + +def mac_paths(): + return ["Contents/Python"] + + +def windows_paths(): + return ["bin/Lib/site-packages"] + + +search_paths_dict = { + "Linux": linux_paths, + "Darwin": mac_paths, + "Windows": windows_paths, +} + +if platform.system() == "Darwin": + # We haven't been able to successfully run this on the Mac yet. So warn + # the user that it might fail. + print("WARNING: prepending the ParaView environment on Mac has not been " + "demonstrated to work successfully. It will likely fail.") + +PV_LOADED = prepend_python_path(PV_HOME, search_paths_dict) +if not PV_LOADED: + raise Exception(f"Failed to add paraview python libraries at {PV_HOME}") diff --git a/trame/env/utils.py b/trame/env/utils.py new file mode 100644 index 00000000..44fffef3 --- /dev/null +++ b/trame/env/utils.py @@ -0,0 +1,66 @@ +import os +import platform +import site +import sys + + +def find_env_setting(arg, env_var_name): + # We check sys.argv for the arg, and os.environ for the env_var_name + # The argument gets precedence + if arg in sys.argv: + return os.path.abspath(sys.argv[sys.argv.index(arg) + 1]) + + if os.environ.get(env_var_name): + return os.path.abspath(os.environ.get(env_var_name)) + + +def prepend_python_path(root_dir, search_paths_dict): + # root_dir is the root directory which we will search + # search_paths_dict is a dictionary with "Linux", "Darwin" (Mac), + # and "Windows" keys, with niladic functions for the values that + # returns a list of the paths to search. The paths for the current + # OS will be used. + + # Returns True on success, False on failure + + # Make sure the python lib dir can be found + python_lib_path = find_python_path(root_dir, search_paths_dict) + if python_lib_path is None: + # A warning should be printed already from find_python_path() + return False + + # Use site.addsitedir() to automatically process .pth files. + # This also appends the paths to sys.path. We will move the new + # paths to the front of sys.path. + prev_length = len(sys.path) + site.addsitedir(python_lib_path) + sys.path[:] = sys.path[prev_length:] + sys.path[0:prev_length] + + return True + + +def find_python_path(root_dir, search_paths_dict): + # Returns the python path, or None if it was not found + + if not os.path.exists(root_dir): + print(f"Warning: path '{root_dir}' does not exist") + return None + + if platform.system() not in search_paths_dict: + raise Exception(f"Unhandled system: {platform.system()}") + + paths_to_try = search_paths_dict[platform.system()]() + found = False + for path in paths_to_try: + full_path = os.path.join(root_dir, path) + if os.path.exists(full_path): + found = True + break + + if not found: + paths_str = "\n".join(paths_to_try) + print("Warning: python library path could not be found in " + f"'{root_dir}'. Tried:\n{paths_str}\n") + return None + + return full_path