It returns the default when a variable is unset, and that default is None, so the previous annotation was wrong for both the parameter and the result.
67 lines
2.0 KiB
Python
67 lines
2.0 KiB
Python
"""Typed reading of the container's environment.
|
|
|
|
Everything in the environment is text, including values the client later
|
|
compares as numbers or passes to seaf-cli. Reading them directly leaves two
|
|
failures that are silent until much later: an unset variable becomes None and
|
|
reaches seaf-cli as the string "None", and a numeric setting stays a string
|
|
that never equals the integer it is compared against.
|
|
"""
|
|
|
|
import os
|
|
from typing import Optional
|
|
|
|
from dsc.errors import ConfigError
|
|
|
|
_TRUE_VALUES = {"true", "1", "yes", "on"}
|
|
_FALSE_VALUES = {"false", "0", "no", "off"}
|
|
|
|
|
|
def env_str(name: str, default: Optional[str] = None) -> Optional[str]:
|
|
"""Return a text setting. An empty variable counts as unset."""
|
|
value = os.getenv(name)
|
|
if value is None or value == "":
|
|
return default
|
|
return value
|
|
|
|
|
|
def env_int(name: str, default: int, minimum: int = 0) -> int:
|
|
"""
|
|
Return a numeric setting as an int, never as text and never as None.
|
|
|
|
Values below ``minimum`` are rejected: a negative speed limit or deletion
|
|
threshold is not something to pass on to seaf-cli and hope for the best.
|
|
"""
|
|
raw = env_str(name)
|
|
if raw is None:
|
|
return default
|
|
|
|
stripped = raw.strip()
|
|
try:
|
|
value = int(stripped, 10)
|
|
except ValueError:
|
|
raise ConfigError(
|
|
f"{name} must be a whole number, got {stripped!r}"
|
|
)
|
|
|
|
if value < minimum:
|
|
raise ConfigError(
|
|
f"{name} must be {minimum} or greater, got {stripped!r}"
|
|
)
|
|
return value
|
|
|
|
|
|
def env_bool(name: str, default: bool = False) -> bool:
|
|
"""Return a boolean setting, accepting the usual spellings."""
|
|
raw = env_str(name)
|
|
if raw is None:
|
|
return default
|
|
|
|
value = raw.strip().lower()
|
|
if value in _TRUE_VALUES:
|
|
return True
|
|
if value in _FALSE_VALUES:
|
|
return False
|
|
|
|
accepted = ", ".join(sorted(_TRUE_VALUES | _FALSE_VALUES))
|
|
raise ConfigError(f"{name} must be one of {accepted}, got {raw.strip()!r}")
|