|
1 | 1 | """Environment variable management for MDIO operations.""" |
2 | 2 |
|
3 | 3 | from os import getenv |
4 | | -from typing import Final |
5 | 4 |
|
6 | 5 | from psutil import cpu_count |
7 | 6 |
|
8 | 7 | from mdio.converters.exceptions import EnvironmentFormatError |
9 | 8 |
|
| 9 | +# Environment variable keys |
| 10 | +_EXPORT_CPUS_KEY = "MDIO__EXPORT__CPU_COUNT" |
| 11 | +_IMPORT_CPUS_KEY = "MDIO__IMPORT__CPU_COUNT" |
| 12 | +_GRID_SPARSITY_RATIO_WARN_KEY = "MDIO__GRID__SPARSITY_RATIO_WARN" |
| 13 | +_GRID_SPARSITY_RATIO_LIMIT_KEY = "MDIO__GRID__SPARSITY_RATIO_LIMIT" |
| 14 | +_SAVE_SEGY_FILE_HEADER_KEY = "MDIO__IMPORT__SAVE_SEGY_FILE_HEADER" |
| 15 | +_MDIO_SEGY_SPEC_KEY = "MDIO__SEGY__SPEC" |
| 16 | +_RAW_HEADERS_KEY = "MDIO__IMPORT__RAW_HEADERS" |
| 17 | +_IGNORE_CHECKS_KEY = "MDIO_IGNORE_CHECKS" |
| 18 | +_CLOUD_NATIVE_KEY = "MDIO__IMPORT__CLOUD_NATIVE" |
10 | 19 |
|
11 | | -class Environment: |
12 | | - """Unified API for accessing and validating MDIO environment variables.""" |
13 | | - |
14 | | - # Environment variable keys and defaults |
15 | | - _EXPORT_CPUS_KEY: Final[str] = "MDIO__EXPORT__CPU_COUNT" |
16 | | - _IMPORT_CPUS_KEY: Final[str] = "MDIO__IMPORT__CPU_COUNT" |
17 | | - _GRID_SPARSITY_RATIO_WARN_KEY: Final[str] = "MDIO__GRID__SPARSITY_RATIO_WARN" |
18 | | - _GRID_SPARSITY_RATIO_LIMIT_KEY: Final[str] = "MDIO__GRID__SPARSITY_RATIO_LIMIT" |
19 | | - _SAVE_SEGY_FILE_HEADER_KEY: Final[str] = "MDIO__IMPORT__SAVE_SEGY_FILE_HEADER" |
20 | | - _MDIO_SEGY_SPEC_KEY: Final[str] = "MDIO__SEGY__SPEC" |
21 | | - _RAW_HEADERS_KEY: Final[str] = "MDIO__IMPORT__RAW_HEADERS" |
22 | | - _IGNORE_CHECKS_KEY: Final[str] = "MDIO_IGNORE_CHECKS" |
23 | | - _CLOUD_NATIVE_KEY: Final[str] = "MDIO__IMPORT__CLOUD_NATIVE" |
24 | | - |
25 | | - # Default values |
26 | | - _EXPORT_CPUS_DEFAULT: Final[int] = cpu_count(logical=True) |
27 | | - _IMPORT_CPUS_DEFAULT: Final[int] = cpu_count(logical=True) |
28 | | - _GRID_SPARSITY_RATIO_WARN_DEFAULT: Final[str] = "2" |
29 | | - _GRID_SPARSITY_RATIO_LIMIT_DEFAULT: Final[str] = "10" |
30 | | - _SAVE_SEGY_FILE_HEADER_DEFAULT: Final[str] = "false" |
31 | | - _MDIO_SEGY_SPEC_DEFAULT: Final[None] = None |
32 | | - _RAW_HEADERS_DEFAULT: Final[str] = "false" |
33 | | - _IGNORE_CHECKS_DEFAULT: Final[str] = "false" |
34 | | - _CLOUD_NATIVE_DEFAULT: Final[str] = "false" |
35 | | - |
36 | | - @classmethod |
37 | | - def _get_env_value(cls, key: str, default: str | int | None) -> str | None: |
38 | | - """Get environment variable value with fallback to default.""" |
39 | | - if isinstance(default, int): |
40 | | - default = str(default) |
41 | | - return getenv(key, default) |
42 | | - |
43 | | - @staticmethod |
44 | | - def _parse_bool(value: str | None) -> bool: |
45 | | - """Parse string value to boolean.""" |
46 | | - if value is None: |
47 | | - return False |
48 | | - return value.lower() in ("1", "true", "yes", "on") |
49 | | - |
50 | | - @staticmethod |
51 | | - def _parse_int(value: str | None, key: str) -> int: |
52 | | - """Parse string value to integer with validation.""" |
53 | | - if value is None: |
54 | | - raise EnvironmentFormatError(key, "int") |
55 | | - try: |
56 | | - return int(value) |
57 | | - except ValueError as e: |
58 | | - raise EnvironmentFormatError(key, "int") from e |
59 | | - |
60 | | - @staticmethod |
61 | | - def _parse_float(value: str | None, key: str) -> float: |
62 | | - """Parse string value to float with validation.""" |
63 | | - if value is None: |
64 | | - raise EnvironmentFormatError(key, "float") |
65 | | - try: |
66 | | - return float(value) |
67 | | - except ValueError as e: |
68 | | - raise EnvironmentFormatError(key, "float") from e |
69 | | - |
70 | | - @classmethod |
71 | | - def export_cpus(cls) -> int: |
72 | | - """Number of CPUs to use for export operations.""" |
73 | | - value = cls._get_env_value(cls._EXPORT_CPUS_KEY, cls._EXPORT_CPUS_DEFAULT) |
74 | | - return cls._parse_int(value, cls._EXPORT_CPUS_KEY) |
75 | | - |
76 | | - @classmethod |
77 | | - def import_cpus(cls) -> int: |
78 | | - """Number of CPUs to use for import operations.""" |
79 | | - value = cls._get_env_value(cls._IMPORT_CPUS_KEY, cls._IMPORT_CPUS_DEFAULT) |
80 | | - return cls._parse_int(value, cls._IMPORT_CPUS_KEY) |
81 | | - |
82 | | - @classmethod |
83 | | - def grid_sparsity_ratio_warn(cls) -> float: |
84 | | - """Sparsity ratio threshold for warnings.""" |
85 | | - value = cls._get_env_value(cls._GRID_SPARSITY_RATIO_WARN_KEY, cls._GRID_SPARSITY_RATIO_WARN_DEFAULT) |
86 | | - return cls._parse_float(value, cls._GRID_SPARSITY_RATIO_WARN_KEY) |
87 | | - |
88 | | - @classmethod |
89 | | - def grid_sparsity_ratio_limit(cls) -> float: |
90 | | - """Sparsity ratio threshold for errors.""" |
91 | | - value = cls._get_env_value(cls._GRID_SPARSITY_RATIO_LIMIT_KEY, cls._GRID_SPARSITY_RATIO_LIMIT_DEFAULT) |
92 | | - return cls._parse_float(value, cls._GRID_SPARSITY_RATIO_LIMIT_KEY) |
93 | | - |
94 | | - @classmethod |
95 | | - def save_segy_file_header(cls) -> bool: |
96 | | - """Whether to save SEG-Y file headers.""" |
97 | | - value = cls._get_env_value(cls._SAVE_SEGY_FILE_HEADER_KEY, cls._SAVE_SEGY_FILE_HEADER_DEFAULT) |
98 | | - return cls._parse_bool(value) |
99 | | - |
100 | | - @classmethod |
101 | | - def mdio_segy_spec(cls) -> str | None: |
102 | | - """Path to MDIO SEG-Y specification file.""" |
103 | | - return cls._get_env_value(cls._MDIO_SEGY_SPEC_KEY, cls._MDIO_SEGY_SPEC_DEFAULT) |
104 | | - |
105 | | - @classmethod |
106 | | - def raw_headers(cls) -> bool: |
107 | | - """Whether to preserve raw headers.""" |
108 | | - value = cls._get_env_value(cls._RAW_HEADERS_KEY, cls._RAW_HEADERS_DEFAULT) |
109 | | - return cls._parse_bool(value) |
110 | | - |
111 | | - @classmethod |
112 | | - def ignore_checks(cls) -> bool: |
113 | | - """Whether to ignore validation checks.""" |
114 | | - value = cls._get_env_value(cls._IGNORE_CHECKS_KEY, cls._IGNORE_CHECKS_DEFAULT) |
115 | | - return cls._parse_bool(value) |
116 | | - |
117 | | - @classmethod |
118 | | - def cloud_native(cls) -> bool: |
119 | | - """Whether to use cloud-native mode for SEG-Y processing.""" |
120 | | - value = cls._get_env_value(cls._CLOUD_NATIVE_KEY, cls._CLOUD_NATIVE_DEFAULT) |
121 | | - return cls._parse_bool(value) |
| 20 | +# Default values |
| 21 | +_EXPORT_CPUS_DEFAULT = cpu_count(logical=True) |
| 22 | +_IMPORT_CPUS_DEFAULT = cpu_count(logical=True) |
| 23 | +_GRID_SPARSITY_RATIO_WARN_DEFAULT = "2" |
| 24 | +_GRID_SPARSITY_RATIO_LIMIT_DEFAULT = "10" |
| 25 | +_SAVE_SEGY_FILE_HEADER_DEFAULT = "false" |
| 26 | +_MDIO_SEGY_SPEC_DEFAULT = None |
| 27 | +_RAW_HEADERS_DEFAULT = "false" |
| 28 | +_IGNORE_CHECKS_DEFAULT = "false" |
| 29 | +_CLOUD_NATIVE_DEFAULT = "false" |
| 30 | + |
| 31 | + |
| 32 | +def _get_env_value(key: str, default: str | int | None) -> str | None: |
| 33 | + """Get environment variable value with fallback to default.""" |
| 34 | + if isinstance(default, int): |
| 35 | + default = str(default) |
| 36 | + return getenv(key, default) |
| 37 | + |
| 38 | + |
| 39 | +def _parse_bool(value: str | None) -> bool: |
| 40 | + """Parse string value to boolean.""" |
| 41 | + if value is None: |
| 42 | + return False |
| 43 | + return value.lower() in ("1", "true", "yes", "on") |
| 44 | + |
| 45 | + |
| 46 | +def _parse_int(value: str | None, key: str) -> int: |
| 47 | + """Parse string value to integer with validation.""" |
| 48 | + if value is None: |
| 49 | + raise EnvironmentFormatError(key, "int") |
| 50 | + try: |
| 51 | + return int(value) |
| 52 | + except ValueError as e: |
| 53 | + raise EnvironmentFormatError(key, "int") from e |
| 54 | + |
| 55 | + |
| 56 | +def _parse_float(value: str | None, key: str) -> float: |
| 57 | + """Parse string value to float with validation.""" |
| 58 | + if value is None: |
| 59 | + raise EnvironmentFormatError(key, "float") |
| 60 | + try: |
| 61 | + return float(value) |
| 62 | + except ValueError as e: |
| 63 | + raise EnvironmentFormatError(key, "float") from e |
| 64 | + |
| 65 | + |
| 66 | +def export_cpus() -> int: |
| 67 | + """Number of CPUs to use for export operations.""" |
| 68 | + value = _get_env_value(_EXPORT_CPUS_KEY, _EXPORT_CPUS_DEFAULT) |
| 69 | + return _parse_int(value, _EXPORT_CPUS_KEY) |
| 70 | + |
| 71 | + |
| 72 | +def import_cpus() -> int: |
| 73 | + """Number of CPUs to use for import operations.""" |
| 74 | + value = _get_env_value(_IMPORT_CPUS_KEY, _IMPORT_CPUS_DEFAULT) |
| 75 | + return _parse_int(value, _IMPORT_CPUS_KEY) |
| 76 | + |
| 77 | + |
| 78 | +def grid_sparsity_ratio_warn() -> float: |
| 79 | + """Sparsity ratio threshold for warnings.""" |
| 80 | + value = _get_env_value(_GRID_SPARSITY_RATIO_WARN_KEY, _GRID_SPARSITY_RATIO_WARN_DEFAULT) |
| 81 | + return _parse_float(value, _GRID_SPARSITY_RATIO_WARN_KEY) |
| 82 | + |
| 83 | + |
| 84 | +def grid_sparsity_ratio_limit() -> float: |
| 85 | + """Sparsity ratio threshold for errors.""" |
| 86 | + value = _get_env_value(_GRID_SPARSITY_RATIO_LIMIT_KEY, _GRID_SPARSITY_RATIO_LIMIT_DEFAULT) |
| 87 | + return _parse_float(value, _GRID_SPARSITY_RATIO_LIMIT_KEY) |
| 88 | + |
| 89 | + |
| 90 | +def save_segy_file_header() -> bool: |
| 91 | + """Whether to save SEG-Y file headers.""" |
| 92 | + value = _get_env_value(_SAVE_SEGY_FILE_HEADER_KEY, _SAVE_SEGY_FILE_HEADER_DEFAULT) |
| 93 | + return _parse_bool(value) |
| 94 | + |
| 95 | + |
| 96 | +def mdio_segy_spec() -> str | None: |
| 97 | + """Path to MDIO SEG-Y specification file.""" |
| 98 | + return _get_env_value(_MDIO_SEGY_SPEC_KEY, _MDIO_SEGY_SPEC_DEFAULT) |
| 99 | + |
| 100 | + |
| 101 | +def raw_headers() -> bool: |
| 102 | + """Whether to preserve raw headers.""" |
| 103 | + value = _get_env_value(_RAW_HEADERS_KEY, _RAW_HEADERS_DEFAULT) |
| 104 | + return _parse_bool(value) |
| 105 | + |
| 106 | + |
| 107 | +def ignore_checks() -> bool: |
| 108 | + """Whether to ignore validation checks.""" |
| 109 | + value = _get_env_value(_IGNORE_CHECKS_KEY, _IGNORE_CHECKS_DEFAULT) |
| 110 | + return _parse_bool(value) |
| 111 | + |
| 112 | + |
| 113 | +def cloud_native() -> bool: |
| 114 | + """Whether to use cloud-native mode for SEG-Y processing.""" |
| 115 | + value = _get_env_value(_CLOUD_NATIVE_KEY, _CLOUD_NATIVE_DEFAULT) |
| 116 | + return _parse_bool(value) |
0 commit comments