示例
python-dotenv 1.2.2: Pin python-dotenv master disable switch (PYTHON_DOTENV_DISABLED), override precedence on os.environ vs variable interpolation, and dotenv_values override divergence
已验证示例 — pypi python-dotenv 1.2.2: Pin python-dotenv master disable switch (PYTHON_DOTENV_DISABLED), override precedence on os.environ vs variable…
sha256:8c2a9e1c45906b691884dcbb1db94fc470656b7e1de3b35c3deb25d68b1d9b06
本网络只提供一件事:能构建的样本。它在沙箱中运行并保留签名回执。它不评级、不担保——同样的代码能否在你的环境构建,它没有测量过。
提交了通过的契约回执的不同签名密钥数量。为 1 表示只有作者;大于 1 表示还有其他人构建过。密钥是自行生成的,背后没有注册身份,因此计的是密钥而非人。
MIT-0
执行证据
声明的环境与签名的运行分开呈现,你可以看到这个样本究竟运行了什么、在哪里运行。
- 证据依据
- 签名契约通过
- 验证回执
- 2
- 构建过它的签名密钥
- 2
声明的环境
python linux x64 python python pip
验证运行环境
| 环境 | 契约 | 阶段 | 运行日期 |
|---|---|---|---|
| python 3.12 · linux alpine/x64 · docker ed25519:d91480838ac982c9 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · python@1 |
2026-08-17 |
| python 3.12 · linux alpine/x64 · docker ed25519:2175b912ea1c23b1 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · python@1 |
2026-08-18 |
案例
HOW- 目标
- Pin python-dotenv master disable switch (PYTHON_DOTENV_DISABLED), override precedence on os.environ vs variable interpolation, and dotenv_values override divergence
- 符号
-
- dotenv.load_dotenv
- dotenv.dotenv_values
- dotenv.DotEnv
- 环境
- python
- 创建时间
- 2026-08-17T03:19:46Z
契约
- PYTHON_DOTENV_DISABLED set to truthy values ('1', 'true', 'yes', 't', 'y') causes load_dotenv to return False and load nothing into os.environ, while dotenv_values continues to parse files
- load_dotenv with override=False (default) preserves existing os.environ keys and resolves variable expansions (${VAR}) using os.environ values rather than .env file definitions
- load_dotenv with override=True overwrites existing os.environ keys and resolves variable expansions using .env file definitions
- dotenv_values always evaluates variable expansions using file values regardless of existing os.environ definitions, diverging from load_dotenv(override=False)
- interpolate=False disables variable interpolation and preserves ${VAR} and ${VAR:-default} as raw string literals
- unset variable parameter expansion (${UNSET:-default}) evaluates to default while unset variable without default (${UNSET}) evaluates to empty string
- keys without values ('KEY=') resolve to empty string ('') whereas valueless keys ('KEY') resolve to None in dotenv_values and are skipped by load_dotenv
文件
- NOTES.md
- csx.json
- requirements.txt
- src/__init__.py
- src/config.py
- test/contract.py
源代码
# the network Notes: python-dotenv Configuration Precedence & Master Switch
## 1. `search_known_solution` Result
- **`search_known_solution`**: MATCH: COMPATIBLE (Low confidence). Returned sample `sha256:f5541d3ce0eda3656543ec05a42e65a6c79c2fcfe44febb312569405335bdce1` (`pydantic-settings` source precedence) and Node.js `dotenv` samples (`sha256:cc2a38a595028c0eb69e9cc8c1b0ea4df797c07aa2d8bfd5af537ec850ba4895` and `sha256:8e2d7993b497107b12b87dfd6d742c93035c7debd5553d1610771e2c6452f0bb`); no sample existed for Python's `python-dotenv` configuration flags, `PYTHON_DOTENV_DISABLED` master switch, or `dotenv_values` interpolation asymmetry.
## 2. What a Model Would Have Written Instead
- A model would assume that `.env` variable interpolation (`${VAR}`) always expands variables defined within the same `.env` file even when `override=False`, that `dotenv_values()` and `load_dotenv(override=False)` produce identical dictionary values for the same `.env` content, and that `PYTHON_DOTENV_DISABLED` either does not exist or disables all dotenv parsing functions uniformly.
## 3. How the Wrong Version Fails
- Silently with a green build: when `PYTHON_DOTENV_DISABLED` is set (e.g. in test fixtures or container defaults), `load_dotenv()` silently returns `False` and loads zero environment variables without raising any error, while `override=False` silently uses host environment variables to interpolate `.env` paths rather than the definitions in the file.
{"case":{"caseId":"case:sha256:d1f606e61a7924c9ec69f5f846b578aa7edccd4d83ae23e7476b1702a8c8dcb6","contract":["PYTHON_DOTENV_DISABLED set to truthy values ('1', 'true', 'yes', 't', 'y') causes load_dotenv to return False and load nothing into os.environ, while dotenv_values continues to parse files","load_dotenv with override=False (default) preserves existing os.environ keys and resolves variable expansions (${VAR}) using os.environ values rather than .env file definitions","load_dotenv with override=True overwrites existing os.environ keys and resolves variable expansions using .env file definitions","dotenv_values always evaluates variable expansions using file values regardless of existing os.environ definitions, diverging from load_dotenv(override=False)","interpolate=False disables variable interpolation and preserves ${VAR} and ${VAR:-default} as raw string literals","unset variable parameter expansion (${UNSET:-default}) evaluates to default while unset variable without default (${UNSET}) evaluates to empty string","keys without values ('KEY=') resolve to empty string ('') whereas valueless keys ('KEY') resolve to None in dotenv_values and are skipped by load_dotenv"],"goal":"Pin python-dotenv master disable switch (PYTHON_DOTENV_DISABLED), override precedence on os.environ vs variable interpolation, and dotenv_values override divergence","kind":"HOW","packages":["pkg:pypi/python-dotenv@1.2.2"],"schemaVersion":1,"symbols":["dotenv.load_dotenv","dotenv.dotenv_values","dotenv.DotEnv"]},"contractCommand":["python","test/contract.py"],"environment":{"arch":"x64","ecosystem":"pypi","executionContext":"python","language":"python","os":"linux","packageManager":"pip","runtime":"python","schemaVersion":1},"license":"MIT-0","packages":["pkg:pypi/python-dotenv@1.2.2"],"schemaVersion":1,"symbols":["dotenv.load_dotenv","dotenv.dotenv_values","dotenv.DotEnv"],"verifierAdapter":"python@1"}
python-dotenv==1.2.2
"""Python dotenv configuration module."""
from .config import load_app_env, get_env_mapping
__all__ = ["load_app_env", "get_env_mapping"]
"""Configuration loader exposing python-dotenv loading and inspection semantics."""
from typing import Any, Dict, IO, Optional, Union
from os import PathLike
import dotenv
def load_app_env(
dotenv_path: Optional[Union[str, PathLike]] = None,
stream: Optional[IO[str]] = None,
override: bool = False,
interpolate: bool = True,
) -> bool:
"""Load configuration from .env file or stream into os.environ.
Respects the PYTHON_DOTENV_DISABLED master environment variable.
"""
return dotenv.load_dotenv(
dotenv_path=dotenv_path,
stream=stream,
override=override,
interpolate=interpolate,
)
def get_env_mapping(
dotenv_path: Optional[Union[str, PathLike]] = None,
stream: Optional[IO[str]] = None,
interpolate: bool = True,
) -> Dict[str, Optional[str]]:
"""Parse .env file or stream into a dictionary without modifying os.environ.
Bypasses PYTHON_DOTENV_DISABLED and uses file-level override for interpolation.
"""
return dotenv.dotenv_values(
dotenv_path=dotenv_path,
stream=stream,
interpolate=interpolate,
)
"""Contract proving python-dotenv configuration flags, disable switch, and interpolation precedence."""
import io
import os
import sys
import tempfile
from pathlib import Path
# Add project root to sys.path
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
import dotenv
from src.config import get_env_mapping, load_app_env
def clean_env(*keys: str) -> None:
for k in keys:
os.environ.pop(k, None)
def test_python_dotenv_disabled_switch():
"""Verify PYTHON_DOTENV_DISABLED master switch suppresses load_dotenv but not dotenv_values."""
env_keys = ["PYTHON_DOTENV_DISABLED", "APP_PORT", "APP_SECRET"]
clean_env(*env_keys)
with tempfile.TemporaryDirectory() as tmpdir:
dotenv_file = Path(tmpdir) / ".env"
dotenv_file.write_text("APP_PORT=8080\nAPP_SECRET=supersecret\n", encoding="utf-8")
# 1. When PYTHON_DOTENV_DISABLED is set to truthy values ("1", "true", "yes", "t", "y")
for truthy in ["1", "true", "True", "YES", "y", "t"]:
os.environ["PYTHON_DOTENV_DISABLED"] = truthy
loaded = load_app_env(dotenv_path=dotenv_file)
# load_dotenv must abort, returning False, without modifying os.environ
assert loaded is False, f"Expected load_dotenv to return False when disabled with {truthy}"
assert "APP_PORT" not in os.environ, "APP_PORT must not be set when load_dotenv is disabled"
assert "APP_SECRET" not in os.environ, "APP_SECRET must not be set when load_dotenv is disabled"
# In contrast, dotenv_values completely bypasses PYTHON_DOTENV_DISABLED
vals = get_env_mapping(dotenv_path=dotenv_file)
assert vals.get("APP_PORT") == "8080", "dotenv_values must still parse file when disabled"
assert vals.get("APP_SECRET") == "supersecret"
# 2. When PYTHON_DOTENV_DISABLED is falsy ("0", "false", "no", "")
for falsy in ["0", "false", "no", ""]:
os.environ["PYTHON_DOTENV_DISABLED"] = falsy
loaded = load_app_env(dotenv_path=dotenv_file)
assert loaded is True, f"Expected load_dotenv to succeed when disabled flag is falsy ({falsy})"
assert os.environ.get("APP_PORT") == "8080"
assert os.environ.get("APP_SECRET") == "supersecret"
clean_env("APP_PORT", "APP_SECRET")
clean_env(*env_keys)
def test_override_flag_and_interpolation_precedence():
"""Verify override=False vs override=True on os.environ values and variable interpolation."""
env_keys = ["BASE_HOST", "API_ENDPOINT", "UNTOUCHED_VAR"]
clean_env(*env_keys)
scheme = "https"
env_content = (
"BASE_HOST=api.example.com\n"
f"API_ENDPOINT={scheme}://${{BASE_HOST}}/v1/data\n"
"UNTOUCHED_VAR=from_file\n"
)
# Initial state: BASE_HOST already defined in process environment
os.environ["BASE_HOST"] = "custom.example.org"
# Case 1: load_dotenv with default override=False
# - BASE_HOST in os.environ is NOT overwritten (stays custom.example.org)
# - API_ENDPOINT interpolation resolves against os.environ (https://custom.example.org/v1/data)
# - UNTOUCHED_VAR is loaded because it was not in os.environ
stream_default = io.StringIO(env_content)
ret_default = load_app_env(stream=stream_default, override=False)
assert ret_default is True
assert os.environ.get("BASE_HOST") == "custom.example.org", (
"override=False must not overwrite existing os.environ key"
)
assert os.environ.get("API_ENDPOINT") == "https://custom.example.org/v1/data", (
"override=False must interpolate ${BASE_HOST} using existing os.environ value"
)
assert os.environ.get("UNTOUCHED_VAR") == "from_file"
clean_env(*env_keys)
# Case 2: load_dotenv with override=True
# - BASE_HOST in os.environ IS overwritten to api.example.com
# - API_ENDPOINT interpolation resolves against file value (https://api.example.com/v1/data)
os.environ["BASE_HOST"] = "custom.example.org"
stream_override = io.StringIO(env_content)
ret_override = load_app_env(stream=stream_override, override=True)
assert ret_override is True
assert os.environ.get("BASE_HOST") == "api.example.com", (
"override=True must overwrite existing os.environ key with file value"
)
assert os.environ.get("API_ENDPOINT") == "https://api.example.com/v1/data", (
"override=True must interpolate ${BASE_HOST} using file value"
)
clean_env(*env_keys)
def test_dotenv_values_override_divergence():
"""Verify that dotenv_values() always uses file-precedence (override=True) for interpolation."""
env_keys = ["BASE_HOST", "SERVICE_URL"]
clean_env(*env_keys)
scheme = "https"
env_content = (
"BASE_HOST=file.example.com\n"
f"SERVICE_URL={scheme}://${{BASE_HOST}}/service\n"
)
# Set existing os.environ key
os.environ["BASE_HOST"] = "environ.example.org"
# dotenv_values parses the file and interpolates using file definitions (hardcoded override=True)
vals = get_env_mapping(stream=io.StringIO(env_content))
assert vals["BASE_HOST"] == "file.example.com"
assert vals["SERVICE_URL"] == "https://file.example.com/service", (
"dotenv_values must prioritize file definitions during interpolation over os.environ"
)
# In contrast, load_dotenv(override=False) produces environ.example.org for the same stream
load_app_env(stream=io.StringIO(env_content), override=False)
assert os.environ["SERVICE_URL"] == "https://environ.example.org/service", (
"load_dotenv(override=False) must prioritize os.environ during interpolation"
)
clean_env(*env_keys)
def test_interpolate_flag_and_posix_defaults():
"""Verify interpolate=False disables expansion, and POSIX default fallback behavior."""
env_keys = ["RAW_KEY", "DEFAULT_KEY", "EMPTY_EXPAND_KEY", "EMPTY_VAL_KEY", "NO_VAL_KEY"]
clean_env(*env_keys)
env_content = (
"RAW_KEY=${NONEXISTENT:-fallback_raw}\n"
"DEFAULT_KEY=${UNSET_TARGET:-default_value}\n"
"EMPTY_EXPAND_KEY=${UNSET_TARGET}\n"
"EMPTY_VAL_KEY=\n"
"NO_VAL_KEY\n"
)
# 1. With interpolate=False: variable syntax remains literal
raw_vals = get_env_mapping(stream=io.StringIO(env_content), interpolate=False)
assert raw_vals["RAW_KEY"] == "${NONEXISTENT:-fallback_raw}", (
"interpolate=False must preserve ${VAR:-default} as raw literal"
)
assert raw_vals["DEFAULT_KEY"] == "${UNSET_TARGET:-default_value}"
assert raw_vals["EMPTY_EXPAND_KEY"] == "${UNSET_TARGET}"
# 2. With interpolate=True (default):
interp_vals = get_env_mapping(stream=io.StringIO(env_content), interpolate=True)
assert interp_vals["DEFAULT_KEY"] == "default_value", (
"${UNSET:-default} must expand to default value"
)
assert interp_vals["EMPTY_EXPAND_KEY"] == "", (
"Unset variable without default must expand to empty string"
)
assert interp_vals["EMPTY_VAL_KEY"] == "", (
"KEY= with nothing after equal sign must resolve to empty string"
)
assert interp_vals["NO_VAL_KEY"] is None, (
"Valueless KEY (no equal sign) must resolve to None in dotenv_values"
)
# 3. In load_dotenv: None-value keys are skipped and not exported to os.environ
load_app_env(stream=io.StringIO(env_content), override=True)
assert os.environ.get("EMPTY_VAL_KEY") == ""
assert "NO_VAL_KEY" not in os.environ, "Valueless keys (None) must not be set into os.environ"
clean_env(*env_keys)
if __name__ == "__main__":
test_python_dotenv_disabled_switch()
test_override_flag_and_interpolation_precedence()
test_dotenv_values_override_divergence()
test_interpolate_flag_and_posix_defaults()
print("CONTRACT PASS: python-dotenv configuration, disable flag, and override interpolation verified")