A lightweight Python library for creating wrapper functions with enhanced argument handling using sentinel values to mark parameters as required or optional.
Project description
Welcome to func_args Documentation
Overview
func_args is a lightweight, zero-dependency Python library that provides sentinel values (REQ and OPT) for enhanced function argument handling. It solves common problems when creating wrapper functions around third-party APIs.
Key features:
REQ sentinel — marks parameters as required, with early validation
OPT sentinel — marks parameters as optional, automatically excluded from kwargs
prepare_kwargs() — validates required and removes optional in one pass
BaseModel / BaseFrozenModel — dataclass mixins that bypass the “default after non-default” ordering limitation
Install
$ pip install func-args
Usage
1. Wrapping Third-Party APIs
The most common use case: creating a better interface around an existing API.
from func_args.api import REQ, OPT, prepare_kwargs
# Suppose this is a third-party API you cannot modify:
def put_object(Bucket, Key, Body, Metadata=None, Tags=None):
"""AWS S3 put_object simplified."""
...
# Your enhanced wrapper:
def better_put_object(
Bucket: str = REQ,
Key: str = REQ,
Body: bytes = REQ,
Metadata: dict | None = OPT,
Tags: dict | None = OPT,
):
# You can add custom logic for optional params
if Metadata is OPT:
Metadata = {"creator": "admin"}
kwargs = dict(
Bucket=Bucket,
Key=Key,
Body=Body,
Metadata=Metadata,
Tags=Tags,
)
# prepare_kwargs will:
# 1. Raise ParamError if any value is still REQ (caller forgot it)
# 2. Remove any value that is still OPT (caller didn't provide it)
# 3. Return a clean dict ready for the real API call
return put_object(**prepare_kwargs(**kwargs))
# Works - Tags is OPT so it gets removed automatically
better_put_object(Bucket="my-bucket", Key="file.txt", Body=b"hello")
# Raises ParamError: "Missing required argument: 'Body'"
better_put_object(Bucket="my-bucket", Key="file.txt")
2. Individual Utilities
You can also use check_required and remove_optional separately:
from func_args.api import REQ, OPT, check_required, remove_optional
def create_user(username=REQ, email=REQ, nickname=OPT, role="user"):
# Step 1: validate required params
check_required(username=username, email=email)
# Step 2: build kwargs and remove OPT values
kwargs = remove_optional(
username=username,
email=email,
nickname=nickname,
role=role,
)
return kwargs
create_user(username="alice", email="alice@example.com")
# -> {"username": "alice", "email": "alice@example.com", "role": "user"}
create_user(username="bob", email="bob@example.com", nickname="Bobby")
# -> {"username": "bob", "email": "bob@example.com", "nickname": "Bobby", "role": "user"}
3. Enhanced Dataclasses
BaseModel and BaseFrozenModel let you define dataclasses with REQ/OPT defaults in any order — no more “fields without defaults must come before fields with defaults” restriction.
import dataclasses
from func_args.api import BaseModel, BaseFrozenModel, REQ, OPT
@dataclasses.dataclass
class DeployConfig(BaseModel):
"""
Note: OPT fields can appear BEFORE REQ fields.
Standard dataclasses would reject this ordering.
"""
region: str = dataclasses.field(default=OPT) # optional, listed first
env: str = dataclasses.field(default="prod") # has default
app_name: str = dataclasses.field(default=REQ) # required, listed last
tags: list = dataclasses.field(default_factory=list)
# REQ fields must be provided, OPT fields are truly optional
config = DeployConfig(app_name="my-service")
assert config.app_name == "my-service"
assert config.region is OPT
assert config.env == "prod"
# to_dict() returns all fields including sentinel values
config.to_dict()
# {"region": OPT, "env": "prod", "app_name": "my-service", "tags": []}
# to_kwargs() returns only provided values (OPT filtered out)
config.to_kwargs()
# {"env": "prod", "app_name": "my-service", "tags": []}
# Missing required field raises ParamError immediately
DeployConfig() # raises ParamError: "Field 'app_name' is required ..."
4. Frozen Dataclass with Computed Fields
@dataclasses.dataclass(frozen=True)
class Document(BaseFrozenModel):
title: str = dataclasses.field(default=REQ)
author: str = dataclasses.field(default=OPT)
version: int = dataclasses.field(default=1)
# Computed fields (init=False) work seamlessly
slug: str = dataclasses.field(init=False)
def __post_init__(self):
super().__post_init__() # validates REQ fields first
object.__setattr__(self, "slug", self.title.lower().replace(" ", "-"))
doc = Document(title="API Guide")
assert doc.slug == "api-guide"
assert doc.to_kwargs() == {"title": "API Guide", "version": 1, "slug": "api-guide"}
# "author" excluded because it's still OPT
API Reference
Symbol |
Description |
|---|---|
REQ |
Sentinel marking a required parameter |
OPT |
Sentinel marking an optional parameter |
check_required(**kw) |
Raises ParamError if any value is REQ |
remove_optional(**kw) |
Returns new dict with OPT values removed |
prepare_kwargs(**kw) |
Combines check_required + remove_optional in one pass |
BaseModel |
Mutable dataclass mixin with REQ/OPT support |
BaseFrozenModel |
Frozen (immutable) dataclass mixin with REQ/OPT support |
ParamError |
Exception raised for missing required parameters |
AI Agent Skill
This project ships a self-contained Agent skill at .claude/skills/func-args/SKILL.md. Copy this file into your project’s .claude/skills/ directory and your AI coding agent will know how to use func_args correctly — including API usage patterns, dataclass examples, and common pitfalls.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file func_args-1.0.2.tar.gz.
File metadata
- Download URL: func_args-1.0.2.tar.gz
- Upload date:
- Size: 20.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f46acb57f22fc0e95e6ac18c992e128f0bc207450f9cab9c02237296e0105d34
|
|
| MD5 |
a8673b58aeba3018b2179fce319c54d6
|
|
| BLAKE2b-256 |
9b20b6b297a845884b7f4ec3dd1f40a0b96280310efd3231b25374fbaf4fdef2
|
File details
Details for the file func_args-1.0.2-py3-none-any.whl.
File metadata
- Download URL: func_args-1.0.2-py3-none-any.whl
- Upload date:
- Size: 15.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f0f36b2aea676321f436d708c39b61c4f83ddeaa31c9aef38a71898ea5fc7adb
|
|
| MD5 |
b8ddb756abefb2c11a0e70abeea2e879
|
|
| BLAKE2b-256 |
cb9c49269f73c85a1f934db66bda4badb5ff6aa7de2747605469f6ffa226e497
|