Source code for schrodinger.utils.postinstall
"""
This file contains post-installation steps common to all platforms.
This allows post installation steps to be tested and used in and outside
the installers. Migrate more post-installation steps here in the future.
"""
import argparse
import glob
import os
import pathlib
import shutil
from enum import Enum
from enum import unique
import pymmlibs
pymmlibs.mmerr_set_mmlibs()
# isort: split
from schrodinger.utils import mmutil
from schrodinger.utils.fileutils import get_mmshare_data_dir
[docs]@unique
class CustomConfigFiles(str, Enum):
    """
    Customized configuration files used during the postinstall stage of an
    installation. These files are optional during the installation, but may be
    required depending on the environment.
    featureflags.json   global and product settings for the suite
    server.json         required for queuing system installation on Linux
    suitepref.xml       required for local installation on Windows
    """
    FEATURE_FLAGS = 'featureflags.json'
    SERVER = 'server.json'
    PREFERENCES = 'suitepref.xml' 
CONFIG_DIRECTORY = pathlib.Path(os.environ['SCHRODINGER']) / 'config'
MMSHARE_DATA_DIRECTORY = pathlib.Path(get_mmshare_data_dir())
[docs]def copy_customized_files(customized_files_dir: pathlib.Path):
    """
    Checks the specified directory for a customized configuration file and
    deploys it to $SCHRODINGER/config.
    NOTE: suitepref.xml is the only exception, this file is copied to
    $SCHRODINGER/mmshare-v*/data/ - SHARED-8207
    The custom configuration file types are stored in the global variable
    CUSTOMIZED_CONFIGURATION_FILES.
    :type customized_files_dir: pathlib.Path
    :param featureflags_dir: path to the directory where the customized config
                            file(s) is located.
    """
    for expected_config_filename in CustomConfigFiles:
        source_file = customized_files_dir / expected_config_filename.value
        if not custom_config_file_exists(customized_files_dir, source_file):
            continue
        if CustomConfigFiles.PREFERENCES.value in str(source_file):
            dest_file = MMSHARE_DATA_DIRECTORY / expected_config_filename.value
        else:
            dest_file = CONFIG_DIRECTORY / expected_config_filename.value
        print(
            f'Copying custom configuration file {source_file=} to {dest_file=}')
        copy_custom_config_file(source_file, dest_file) 
[docs]def custom_config_file_exists(customized_files_dir: pathlib.Path,
                              source_file: pathlib.Path) -> bool:
    """
    Check if source_file exists on file system, return boolean.
    """
    if not source_file.exists():
        print(
            f'Customized configuration file {source_file.name} not found in '
            f'{customized_files_dir}. Using default settings for installation.')
        return False
    return True 
[docs]def copy_custom_config_file(source_file: pathlib.Path, dest_file: pathlib.Path):
    """
    Copy customized configuration file to the specified destination.
    Ensure the destination directory (e.g. $SCHRODINGER/config) exists
    before copying.
    """
    os.makedirs(os.path.dirname(dest_file), exist_ok=True)
    shutil.copy(source_file, dest_file) 
[docs]def get_lib_dir():
    """
    Don't use hunt because we are getting rid of and it requires feature
    flags which requires licenses.
    """
    return glob.glob(os.environ["SCHRODINGER"] + "/mmshare-v*/lib/*")[0] 
[docs]def create_config_dir():
    """
    Create $SCHRODINGER/config
    """
    target_directory = mmutil.mmfile_get_config_dir()
    os.makedirs(target_directory, exist_ok=True) 
[docs]def get_disabled_lib_dir():
    lib_directory = get_lib_dir()
    deconstructed_path = lib_directory.split(os.path.sep)
    deconstructed_path[-2] = "disabled_lib"
    disabled_lib_directory = os.path.sep.join(deconstructed_path)
    return disabled_lib_directory 
[docs]def parse_args(argv=None):
    parser = argparse.ArgumentParser(__doc__)
    parser.add_argument(
        '--customized-files-dir',
        type=pathlib.Path,
        help='Path to customized configuration files. These files will be '
        'copied to $SCHRODINGER/config directory.')
    return parser.parse_args(argv) 
[docs]def main(argv=None):
    args = parse_args(argv)
    create_config_dir()
    if args.customized_files_dir:
        copy_customized_files(args.customized_files_dir)
    return args 
if __name__ == '__main__':
    main()