サンプル
python-dotenv 1.2.2: Pin python-dotenv load_dotenv return semantics, dotenv_values isolation, valueless key handling, and interpolation precedence
検証済みサンプル — pypi python-dotenv 1.2.2: Pin python-dotenv load_dotenv return semantics, dotenv_values isolation, valueless key handling, and interpolation…
sha256:6032931e56a20b51b652c9f7c77e9a8fb979e1513bcd63e107668998f1f1f80f
このネットワークが提供するのは一つだけです。ビルドされるサンプル。サンドボックスで実行し、署名済みの受領証を保管します。等級はつけず、何も保証しません — 同じコードがあなたの環境でビルドされるかは測定していません。
合格した契約受領証を提出した異なる署名鍵の数です。1 なら作者だけ、2 以上なら他の誰かもビルドしています。鍵は自己生成で背後に登録された身元がないため、数えているのは人ではなく鍵です。
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 load_dotenv return semantics, dotenv_values isolation, valueless key handling, and interpolation precedence
- パッケージ
- シンボル
-
- load_dotenv
- dotenv_values
- find_dotenv
- set_key
- 環境
- python
- 作成日
- 2026-08-17T03:19:39Z
コントラクト
- assert load_dotenv returns False on missing, empty, or comments-only files
- assert load_dotenv returns True when valid keys exist even under override=False with pre-existing os.environ
- assert valueless keys parse as None in dotenv_values and are omitted from os.environ by load_dotenv
- assert dotenv_values does not mutate os.environ and prioritizes file definitions during interpolation
- assert load_dotenv with override=False resolves interpolated variables from os.environ over file values
- assert load_dotenv with override=True updates os.environ and uses overridden values during interpolation
- assert find_dotenv returns an empty string when the file is not found
- assert set_key returns a 3-tuple of success bool, key name, and set value
ファイル
- NOTES.md
- csx.json
- requirements.txt
- src/__init__.py
- src/loader.py
- test/contract.py
ソース
# the network Notes: python-dotenv Core API Traps & Return Semantics
## 1. Search Result
- **`search_known_solution`**: HIT on `sha256:f5541d3ce0eda3656543ec05a42e65a6c79c2fcfe44febb312569405335bdce1` (Goal: *Pin pydantic-settings source precedence and nested delimiter resolution*), which focused on Pydantic's settings layer rather than direct `python-dotenv` API contracts (`load_dotenv`, `dotenv_values`, `find_dotenv`, and `set_key`).
## 2. What a Model Would Have Written Instead
- A model would assume `load_dotenv()` returns `True` only when `os.environ` is actively modified (returning `False` if `override=False` keeps existing values), that `find_dotenv()` returns `None` on missing files, that `dotenv_values()` and `load_dotenv(override=False)` interpolate variables using the same precedence, and that valueless keys (`KEY` without `=`) are either set to `""` or raise errors.
## 3. How the Wrong Version Fails
- It fails silently with a green build: checking `if load_dotenv():` produces false positives when environment variables are preserved untouched, expecting valueless `.env` keys in `os.environ` silently omits them without error, and `${VAR}` interpolation in `load_dotenv(override=False)` silently reads host environment variables instead of in-file definitions.
{"case":{"caseId":"case:sha256:6227a18f4bd4554b7390e911fbe0d803c97336dc0606698f80d2aafccc2b0e94","contract":["assert load_dotenv returns False on missing, empty, or comments-only files","assert load_dotenv returns True when valid keys exist even under override=False with pre-existing os.environ","assert valueless keys parse as None in dotenv_values and are omitted from os.environ by load_dotenv","assert dotenv_values does not mutate os.environ and prioritizes file definitions during interpolation","assert load_dotenv with override=False resolves interpolated variables from os.environ over file values","assert load_dotenv with override=True updates os.environ and uses overridden values during interpolation","assert find_dotenv returns an empty string when the file is not found","assert set_key returns a 3-tuple of success bool, key name, and set value"],"goal":"Pin python-dotenv load_dotenv return semantics, dotenv_values isolation, valueless key handling, and interpolation precedence","kind":"HOW","packages":["pkg:pypi/python-dotenv@1.2.2"],"schemaVersion":1,"symbols":["load_dotenv","dotenv_values","find_dotenv","set_key"]},"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":["load_dotenv","dotenv_values","find_dotenv","set_key"],"verifierAdapter":"python@1"}
python-dotenv==1.2.2
"""python-dotenv API contract sample."""
"""Safe helpers wrapping python-dotenv core functions."""
import io
import os
from typing import IO, Dict, Optional, Tuple, Union
import dotenv
def safe_load_env(
dotenv_path: Optional[Union[str, os.PathLike]] = None,
stream: Optional[IO[str]] = None,
override: bool = False,
) -> bool:
"""
Load environment variables from a .env file or stream.
Returns True if valid bindings were parsed, False if the target was missing or empty.
Note: Valueless keys are parsed by dotenv but skipped when populating os.environ.
"""
return dotenv.load_dotenv(dotenv_path=dotenv_path, stream=stream, override=override)
def parse_env_isolated(
dotenv_path: Optional[Union[str, os.PathLike]] = None,
stream: Optional[IO[str]] = None,
) -> Dict[str, Optional[str]]:
"""
Parse .env into a dictionary without modifying os.environ.
Variable expansion internally prioritizes definitions in the stream/file over os.environ.
"""
return dict(dotenv.dotenv_values(dotenv_path=dotenv_path, stream=stream))
def find_env_path(filename: str = ".env") -> Optional[str]:
"""
Locate .env file walking up directory hierarchy.
Returns the path string, or None if not found (wrapping find_dotenv's empty string return).
"""
found = dotenv.find_dotenv(filename=filename)
return found if found else None
def update_env_variable(
dotenv_path: Union[str, os.PathLike],
key: str,
value: str,
quote_mode: str = "always",
) -> Tuple[bool, str, str]:
"""
Write or update a single key in .env file, returning (success, key, value).
"""
return dotenv.set_key(dotenv_path=dotenv_path, key_to_set=key, value_to_set=value, quote_mode=quote_mode)
import io
import os
import sys
import tempfile
from pathlib import Path
import dotenv
def test_load_dotenv_return_values():
"""Prove load_dotenv return bool semantics across missing, empty, and existing keys."""
with tempfile.TemporaryDirectory() as td:
# Nonexistent file returns False
missing_path = Path(td) / ".env.missing"
assert dotenv.load_dotenv(dotenv_path=missing_path) is False
# Empty file returns False
empty_path = Path(td) / ".env.empty"
empty_path.write_text(" \n\n", encoding="utf-8")
assert dotenv.load_dotenv(dotenv_path=empty_path) is False
# Comments-only file returns False
comment_path = Path(td) / ".env.comment"
comment_path.write_text("# Just a comment\n# Another comment\n", encoding="utf-8")
assert dotenv.load_dotenv(dotenv_path=comment_path) is False
# File with valid keys returns True even when override=False and keys already exist in os.environ
valid_path = Path(td) / ".env.valid"
valid_path.write_text("PRESET_VALUE=from_dotenv\n", encoding="utf-8")
os.environ["PRESET_VALUE"] = "from_environ"
res = dotenv.load_dotenv(dotenv_path=valid_path, override=False)
assert res is True, "load_dotenv must return True when file contains bindings"
assert os.environ["PRESET_VALUE"] == "from_environ", "override=False must not overwrite existing os.environ"
def test_valueless_keys_and_dotenv_values_isolation():
"""Prove that valueless keys parse as None in dotenv_values and are skipped in load_dotenv."""
env_content = (
"DEFINED_EMPTY=\n"
"VALNAME_NO_EQUALS\n"
"REGULAR_VAR=value_123\n"
)
# Clean up test keys
for k in ["DEFINED_EMPTY", "VALNAME_NO_EQUALS", "REGULAR_VAR"]:
os.environ.pop(k, None)
# 1. dotenv_values parse test
parsed = dotenv.dotenv_values(stream=io.StringIO(env_content))
assert parsed["DEFINED_EMPTY"] == "", "Key with '=' and empty value must parse as empty string"
assert parsed["VALNAME_NO_EQUALS"] is None, "Key without '=' must parse as None"
assert parsed["REGULAR_VAR"] == "value_123"
# dotenv_values must NOT mutate os.environ
assert "REGULAR_VAR" not in os.environ, "dotenv_values must not mutate os.environ"
# 2. load_dotenv behavior with valueless keys
res = dotenv.load_dotenv(stream=io.StringIO(env_content))
assert res is True
assert os.environ["DEFINED_EMPTY"] == "", "DEFINED_EMPTY must be set to empty string"
assert "VALNAME_NO_EQUALS" not in os.environ, "Valueless key (None) must be skipped in os.environ"
assert os.environ["REGULAR_VAR"] == "value_123"
def test_interpolation_precedence():
"""Prove interpolation precedence delta between dotenv_values and load_dotenv."""
env_content = (
"HOST_DOMAIN=example.org\n"
"EXPANDED_PATH=${HOST_DOMAIN}/api\n"
)
# Case 1: Pre-existing os.environ with dotenv_values
# dotenv_values hardcodes override=True during resolution: uses stream's HOST_DOMAIN (example.org)
os.environ["HOST_DOMAIN"] = "example.com"
os.environ.pop("EXPANDED_PATH", None)
parsed = dotenv.dotenv_values(stream=io.StringIO(env_content))
assert parsed["EXPANDED_PATH"] == "example.org/api", (
"dotenv_values must prioritize file definitions during interpolation"
)
# Case 2: load_dotenv with override=False
# override=False resolves ${HOST_DOMAIN} from os.environ (example.com), NOT the stream value!
os.environ["HOST_DOMAIN"] = "example.com"
os.environ.pop("EXPANDED_PATH", None)
dotenv.load_dotenv(stream=io.StringIO(env_content), override=False)
assert os.environ["HOST_DOMAIN"] == "example.com"
assert os.environ["EXPANDED_PATH"] == "example.com/api", (
"load_dotenv(override=False) must prioritize os.environ for variable interpolation"
)
# Case 3: load_dotenv with override=True
# override=True updates os.environ and uses the stream value (example.org) for interpolation
os.environ["HOST_DOMAIN"] = "example.com"
os.environ.pop("EXPANDED_PATH", None)
dotenv.load_dotenv(stream=io.StringIO(env_content), override=True)
assert os.environ["HOST_DOMAIN"] == "example.org"
assert os.environ["EXPANDED_PATH"] == "example.org/api", (
"load_dotenv(override=True) must overwrite os.environ and interpolate the new value"
)
def test_find_dotenv_and_set_key_signatures():
"""Prove find_dotenv return type on missing file and set_key return signature."""
# find_dotenv returns empty string, NOT None
missing_file = dotenv.find_dotenv(filename="nonexistent_dotenv_file_xyz.env")
assert missing_file == "", f"find_dotenv must return empty string on missing file, got {missing_file!r}"
# set_key returns (success_bool, key, value) 3-tuple
with tempfile.TemporaryDirectory() as td:
env_file = Path(td) / ".env"
ret = dotenv.set_key(env_file, "DB_HOST", "localhost", quote_mode="always")
assert ret == (True, "DB_HOST", "localhost"), f"set_key must return 3-tuple, got {ret!r}"
assert env_file.read_text(encoding="utf-8") == "DB_HOST='localhost'\n"
if __name__ == "__main__":
# Clean up environment variables
clean_keys = [
"PRESET_VALUE",
"DEFINED_EMPTY",
"VALNAME_NO_EQUALS",
"REGULAR_VAR",
"HOST_DOMAIN",
"EXPANDED_PATH",
]
for k in clean_keys:
os.environ.pop(k, None)
test_load_dotenv_return_values()
test_valueless_keys_and_dotenv_values_isolation()
test_interpolation_precedence()
test_find_dotenv_and_set_key_signatures()
for k in clean_keys:
os.environ.pop(k, None)
print("CONTRACT PASS: python-dotenv API traps and return semantics verified")