File: datadir.py

package info (click to toggle)
python-pyproj 3.7.1-2
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 1,720 kB
  • sloc: python: 13,468; sh: 273; makefile: 90
file content (120 lines) | stat: -rw-r--r-- 3,814 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
"""
Module for managing the PROJ data directory.
"""

# pylint: disable=global-statement
import os
import shutil
import sys
from pathlib import Path

from pyproj._context import (  # noqa: F401  pylint: disable=unused-import
    _set_context_data_dir,
    get_user_data_dir,
)
from pyproj.exceptions import DataDirError

_USER_PROJ_DATA = None
_VALIDATED_PROJ_DATA = None


def set_data_dir(proj_data_dir: str | Path) -> None:
    """
    Set the data directory for PROJ to use.

    Parameters
    ----------
    proj_data_dir: str | Path
        The path to the PROJ data directory.
    """
    global _USER_PROJ_DATA
    global _VALIDATED_PROJ_DATA
    _USER_PROJ_DATA = str(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.
    _set_context_data_dir()


def append_data_dir(proj_data_dir: str | Path) -> None:
    """
    Add an additional data directory for PROJ to use.

    Parameters
    ----------
    proj_data_dir: str | Path
        The path to the PROJ data directory.
    """
    set_data_dir(os.pathsep.join([get_data_dir(), str(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_DATA (PROJ 9.1+) | PROJ_LIB (PROJ<9.1) (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
    internal_datadir = Path(__file__).absolute().parent / "proj_dir" / "share" / "proj"
    proj_lib_dirs = os.environ.get("PROJ_DATA", os.environ.get("PROJ_LIB", ""))
    prefix_datadir = Path(sys.prefix, "share", "proj")
    conda_windows_prefix_datadir = Path(sys.prefix, "Library", "share", "proj")

    def valid_data_dir(potential_data_dir):
        if (
            potential_data_dir is not None
            and Path(potential_data_dir, "proj.db").exists()
        ):
            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 = str(internal_datadir)
    elif valid_data_dirs(proj_lib_dirs):
        _VALIDATED_PROJ_DATA = proj_lib_dirs
    elif valid_data_dir(prefix_datadir):
        _VALIDATED_PROJ_DATA = str(prefix_datadir)
    elif valid_data_dir(conda_windows_prefix_datadir):
        _VALIDATED_PROJ_DATA = str(conda_windows_prefix_datadir)
    else:
        proj_exe = shutil.which("proj", path=sys.prefix)
        if proj_exe is None:
            proj_exe = shutil.which("proj")
        if proj_exe is not None:
            system_proj_dir = Path(proj_exe).parent.parent / "share" / "proj"
            if valid_data_dir(system_proj_dir):
                _VALIDATED_PROJ_DATA = str(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_DATA (PROJ 9.1+) | PROJ_LIB (PROJ<9.1) or "
            "with `pyproj.datadir.set_data_dir`."
        )
    return _VALIDATED_PROJ_DATA