PLAIN PYTHON · ZERO RUNTIME DEPS
Missing keys, None, and defaults
Distinguish optional keys from nullable values and understand released default ownership.
Missing and None are different inputs
Optional(str) permits an absent key, which is omitted from the result. str | None accepts a present null value but still requires the key. Optional(str, 'Ada') inserts a default only when the key is absent.
from zodify import Optional, validate
assert validate({"name": Optional(str)}, {}) == {}
assert validate({"name": str | None}, {"name": None}) == {"name": None}
assert validate({"name": Optional(str, "Ada")}, {}) == {"name": "Ada"}
# Released 0.6.0 defaults are inserted as supplied, without validation or copying.
default = []
result = validate({"items": Optional([str], default)}, {})
assert result["items"] is default
assert validate({"count": Optional(int, "unchecked")}, {})["count"] == "unchecked"
try:
validate({"name": str | None}, {})
except ValueError:
pass # Nullable still requires the key.
else:
raise AssertionError("Expected missing-key failure")
print("optional-defaults: passed")
Expected output: optional-defaults: passed
Defaults in the released version
In 0.6.0, a default is inserted as supplied. It is not independently validated or copied. Mutable defaults may be shared between calls. The executable example deliberately demonstrates an invalid default being inserted; this documents behavior, not a recommended configuration.
Prefer immutable, type-correct defaults and construct fresh mutable values in application code. A future default policy belongs to a separately released migration; do not assume unreleased source changes apply to an installed package.