Skip to content

Instantly share code, notes, and snippets.

@estasney
Created October 25, 2024 21:19
Show Gist options
  • Save estasney/9d3f19f805aca338daba8ce7052190ed to your computer and use it in GitHub Desktop.
Save estasney/9d3f19f805aca338daba8ce7052190ed to your computer and use it in GitHub Desktop.
Wrapped Env Override Decorator
import inspect
import os
from functools import wraps
def env_override(func):
sig = inspect.signature(func)
# Identify parameters with default value None
none_defaults = [
name for name, param in sig.parameters.items()
if param.default is None
]
@wraps(func)
def wrapper(*args, **kwargs):
# Bind the arguments to the function's signature
bound_args = sig.bind_partial(*args, **kwargs)
bound_args.apply_defaults()
for name in none_defaults:
# Check if the argument is missing or None
if name not in bound_args.arguments or bound_args.arguments[name] is None:
# Look up the environment variable
env_value = os.environ.get(name)
if env_value is not None:
param = sig.parameters[name]
# Attempt to cast the environment variable to the annotated type
if param.annotation != inspect.Parameter.empty:
try:
bound_args.arguments[name] = param.annotation(env_value)
except Exception as e:
raise ValueError(
f"Could not convert environment variable '{name}' to {param.annotation}"
) from e
else:
bound_args.arguments[name] = env_value
# Call the original function with updated arguments
return func(*bound_args.args, **bound_args.kwargs)
return wrapper
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment