Release v1.0.2 (What’s new?).

Documentation Status https://github.com/MacHu-GWU/func_args-project/actions/workflows/main.yml/badge.svg https://codecov.io/gh/MacHu-GWU/func_args-project/branch/main/graph/badge.svg https://img.shields.io/pypi/v/func-args.svg https://img.shields.io/pypi/l/func-args.svg https://img.shields.io/pypi/pyversions/func-args.svg https://img.shields.io/badge/✍️_Release_History!--None.svg?style=social&logo=github https://img.shields.io/badge/⭐_Star_me_on_GitHub!--None.svg?style=social&logo=github
https://img.shields.io/badge/Link-API-blue.svg https://img.shields.io/badge/Link-Install-blue.svg https://img.shields.io/badge/Link-GitHub-blue.svg https://img.shields.io/badge/Link-Submit_Issue-blue.svg https://img.shields.io/badge/Link-Request_Feature-blue.svg https://img.shields.io/badge/Link-Download-blue.svg

Welcome to func_args Documentation

https://func-args.readthedocs.io/en/latest/_static/func_args-logo.png

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.

Table of Content

About the Author

(\ (\
( -.-)o
o_(")(")

Sanhe Hu is a seasoned software engineer with a deep passion for Python development since 2010. As an author and maintainer of 150+ open-source Python projects, with over 15 million monthly downloads, I bring a wealth of experience to the table. As a Senior Solution Architect and Subject Matter Expert in AI, Data, Amazon Web Services, Cloud Engineering, DevOps, I thrive on helping clients with platform design, enterprise architecture, and strategic roadmaps.

Talk is cheap, show me the code:

API Document