Source code for sunpy.util.config

"""
This module provides SunPy's configuration file functionality.
"""
import os
import shutil
import configparser
from pathlib import Path

import sunpy
from sunpy.extern.appdirs import AppDirs
from sunpy.util.exceptions import warn_user

__all__ = ['load_config', 'copy_default_config', 'print_config', 'CONFIG_DIR']

# This is to avoid creating a new config dir for each new dev version.
# We use AppDirs to locate and create the config directory.
dirs = AppDirs("sunpy", "sunpy")
# Default one set by AppDirs
CONFIG_DIR = dirs.user_config_dir
CACHE_DIR = dirs.user_cache_dir


[docs] def load_config(): """ Read the "sunpyrc" configuration file. If one does not exists in the user's home directory then read in the defaults from "sunpy/data/sunpyrc". """ config = configparser.RawConfigParser() # Get locations of SunPy configuration files to be loaded config_files = _find_config_files() # Read in configuration files config.read(config_files) # Specify the working directory as a default so that the user's home # directory can be located in an OS-independent manner if not config.has_option('general', 'working_dir'): config.set('general', 'working_dir', str(Path.home() / "sunpy")) # Specify the database url as a default so that the user's home # directory can be located in an OS-independent manner if not config.has_option('database', 'url'): config.set('database', 'url', "sqlite:///" + str(Path.home() / "sunpy" / "sunpydb.sqlite")) # Set the download_dir to be relative to the working_dir working_dir = Path(config.get('general', 'working_dir')) download_dir = Path(config.get('downloads', 'download_dir')) remote_data_manager_dir = Path(config.get('downloads', 'remote_data_manager_dir')) sample_dir = config.get('downloads', 'sample_dir', fallback=dirs.user_data_dir) config.set('downloads', 'sample_dir', Path(sample_dir).expanduser().resolve().as_posix()) config.set('downloads', 'download_dir', (working_dir / download_dir).expanduser().resolve().as_posix()) config.set('downloads', 'remote_data_manager_dir', (working_dir / remote_data_manager_dir).expanduser().resolve().as_posix()) return config
def _find_config_files(): """ Finds locations of SunPy configuration files. """ config_files = [] config_filename = 'sunpyrc' # find default configuration file module_dir = Path(sunpy.__file__).parent config_files.append(str(module_dir / 'data' / 'sunpyrc')) # if a site configuration file exists, add that to list of files to read # so that any values set there will override ones specified in the default # config file config_path = Path(dirs.site_config_dir) if config_path.joinpath(config_filename).exists(): config_files.append(str(config_path.joinpath(config_filename))) # if a user configuration file exists, add that to list of files to read # so that any values set there will override ones specified in the default # config file config_path = Path(_get_user_configdir()) if config_path.joinpath(config_filename).exists(): config_files.append(str(config_path.joinpath(config_filename))) return config_files def get_and_create_download_dir(): """ Get the config of download directory and create one if not present. """ download_dir = os.environ.get('SUNPY_DOWNLOADDIR') if download_dir: return download_dir download_dir = Path(sunpy.config.get('downloads', 'download_dir')).expanduser().resolve() if not _is_writable_dir(download_dir): raise RuntimeError(f'Could not write to SunPy downloads directory="{download_dir}"') return sunpy.config.get('downloads', 'download_dir') def get_and_create_sample_dir(): """ Get the config of download directory and create one if not present. """ sample_dir = Path(sunpy.config.get('downloads', 'sample_dir')).expanduser().resolve() if not _is_writable_dir(sample_dir): raise RuntimeError(f'Could not write to SunPy sample data directory="{sample_dir}"') return sunpy.config.get('downloads', 'sample_dir') def _is_writable_dir(p): """ Checks to see if a directory is writable. """ # Worried about multiple threads creating the directory at the same time. try: Path(p).mkdir(parents=True, exist_ok=True) except FileExistsError: # raised if there's an existing file instead of a directory return False else: return Path(p).is_dir() and os.access(p, os.W_OK) def _get_user_configdir(): """ Return the string representing the configuration dir. The default is set by "AppDirs" and can be accessed by importing ``sunpy.util.config.CONFIG_DIR``. You can override this with the "SUNPY_CONFIGDIR" environment variable. """ configdir = os.environ.get('SUNPY_CONFIGDIR', CONFIG_DIR) if not _is_writable_dir(configdir): raise RuntimeError(f'Could not write to SUNPY_CONFIGDIR="{configdir}"') return configdir
[docs] def copy_default_config(overwrite=False): """ Copies the default sunpy config file to the user's config directory. Parameters ---------- overwrite : `bool` If True, existing config file will be overwritten. """ config_filename = 'sunpyrc' config_file = Path(sunpy.__file__).parent / 'data' / config_filename user_config_dir = Path(_get_user_configdir()) user_config_file = user_config_dir / config_filename if not _is_writable_dir(user_config_dir): raise RuntimeError(f'Could not write to SunPy config directory {user_config_dir}') config_path = Path(dirs.site_config_dir) site_config_file = config_path.joinpath(config_filename) if site_config_file.exists(): message = (f"Site config file {str(site_config_file)} exists. " "You must update the User config file to take the " "site configuration into account manually. Consult your" "site manager." ) warn_user(message) if user_config_file.exists(): if overwrite: message = "User config file already exists. " \ "This will be overwritten with a backup written in the same location." warn_user(message) os.rename(str(user_config_file), str(user_config_file) + ".bak") shutil.copyfile(config_file, user_config_file) else: message = "User config file already exists. " \ "To overwrite it use `copy_default_config(overwrite=True)`" warn_user(message) else: shutil.copyfile(config_file, user_config_file)