""" Module for managing the PROJ data directory. """ import os import sys from distutils.spawn import find_executable from pyproj.exceptions import DataDirError _USER_PROJ_DATA = None _VALIDATED_PROJ_DATA = None def set_data_dir(proj_data_dir: str) -> None: """ Set the data directory for PROJ to use. Parameters ---------- proj_data_dir: str The path to the PROJ data directory. """ global _USER_PROJ_DATA global _VALIDATED_PROJ_DATA _USER_PROJ_DATA = proj_data_dir # set to none to re-validate _VALIDATED_PROJ_DATA = None # need to reset the global PROJ context # to prevent core dumping if the data directory # is not found. from pyproj._datadir import pyproj_global_context_initialize pyproj_global_context_initialize() def append_data_dir(proj_data_dir: str) -> None: """ Add an additional data directory for PROJ to use. Parameters ---------- proj_data_dir: str The path to the PROJ data directory. """ set_data_dir(os.pathsep.join([get_data_dir(), proj_data_dir])) def get_data_dir() -> str: """ The order of preference for the data directory is: 1. The one set by pyproj.datadir.set_data_dir (if exists & valid) 2. The internal proj directory (if exists & valid) 3. The directory in PROJ_LIB (if exists & valid) 4. The directory on sys.prefix (if exists & valid) 5. The directory on the PATH (if exists & valid) Returns ------- str: The valid data directory. """ # to avoid re-validating global _VALIDATED_PROJ_DATA if _VALIDATED_PROJ_DATA is not None: return _VALIDATED_PROJ_DATA global _USER_PROJ_DATA internal_datadir = os.path.join( os.path.dirname(os.path.abspath(__file__)), "proj_dir", "share", "proj" ) proj_lib_dirs = os.environ.get("PROJ_LIB", "") prefix_datadir = os.path.join(sys.prefix, "share", "proj") def valid_data_dir(potential_data_dir): if potential_data_dir is not None and os.path.exists( os.path.join(potential_data_dir, "proj.db") ): return True return False def valid_data_dirs(potential_data_dirs): if potential_data_dirs is None: return False for proj_data_dir in potential_data_dirs.split(os.pathsep): if valid_data_dir(proj_data_dir): return True return None if valid_data_dirs(_USER_PROJ_DATA): _VALIDATED_PROJ_DATA = _USER_PROJ_DATA elif valid_data_dir(internal_datadir): _VALIDATED_PROJ_DATA = internal_datadir elif valid_data_dirs(proj_lib_dirs): _VALIDATED_PROJ_DATA = proj_lib_dirs elif valid_data_dir(prefix_datadir): _VALIDATED_PROJ_DATA = prefix_datadir else: proj_exe = find_executable("proj") if proj_exe is not None: system_proj_dir = os.path.join( os.path.dirname(os.path.dirname(proj_exe)), "share", "proj" ) if valid_data_dir(system_proj_dir): _VALIDATED_PROJ_DATA = system_proj_dir if _VALIDATED_PROJ_DATA is None: raise DataDirError( "Valid PROJ data directory not found. " "Either set the path using the environmental variable PROJ_LIB or " "with `pyproj.datadir.set_data_dir`." ) return _VALIDATED_PROJ_DATA