Files
Maxim Shulga 3c7daea3c1 Annotate env_str as returning an optional string
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.
2026-08-02 18:08:38 -07:00

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}")