Skip to main content

A lightweight Python library for creating wrapper functions with enhanced argument handling using sentinel values to mark parameters as required or optional.

Project description

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-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

Overview

func_args is a lightweight Python library for creating wrapper functions with enhanced argument handling. It solves common problems when working with third-party APIs that have suboptimal interface designs.

The library provides sentinel values (REQ and OPT) that can be used as function parameter defaults to:

  • Mark parameters as required

  • Mark parameters as optional and easily exclude them from kwargs

Additionally, func_args includes dataclasses enhancements for parameter validation and conversion.

Design Philosophy

func_args follows these core principles:

  1. Explicit over implicit - Parameters are clearly marked as required or optional

  2. Fail fast - Required parameters are validated early

  3. Minimal overhead - Simple API with minimal processing cost

  4. Flexible integration - Works with any Python function without modifying the original

  5. Type hint support - Full support for Python type annotations

  6. Consistent error handling - Clear error messages for missing required parameters

The library solves several common problems:

  • Creating wrapper functions around third-party APIs with poor parameter interfaces

  • Building flexible functions with many optional parameters

  • Enforcing required parameters without complex conditional logic

  • Removing optional parameters from kwargs dictionaries to avoid passing unused parameters

Usage Examples

Basic Sentinels

In this example, we create a wrapper around an AWS S3 put_object API:

def put_object(
    Bucket: str,
    Key: str,
    Body: bytes,
    Metadata: T.Optional[dict[str, str]] = ...,
    Tags: T.Optional[dict[str, str]] = ...,
):
    ...
from func_args.api import REQ, OPT, prepare_kwargs

# Our enhanced wrapper with REQ and OPT
def better_put_object(
    Bucket: str = REQ,
    Key: str = REQ,
    Body: bytes = REQ,
    Metadata: T.Optional[dict[str, str]] = OPT,
    Tags: T.Optional[dict[str, str]] = OPT,
):
    # custom parameter handling
    if Metadata is NA:
        Metadata = {"creator": "admin"}
    if Tags is NA:
        Tags = {"creator": "admin"}

    # Prepare kwargs with validation
    kwargs = dict(
        Bucket=Bucket,
        Key=Key,
        Body=Body,
        Metadata=Metadata,
        Tags=Tags,
    )

    # This will:
    # 1. Raise ParamError if any REQ values remain
    # 2. Remove any OPT values
    # 3. Return a clean dict with only provided values
    cleaned_kwargs = prepare_kwargs(kwargs)

    # Call the original API with only the necessary parameters
    return put_object(**cleaned_kwargs)

Required Parameter Validation

from func_args.arg import REQ, check_required

# Function with required parameters
def create_user(username=REQ, email=REQ, role="user"):
    # Validate required parameters
    check_required(username=username, email=email)

    # If we got here, all required parameters were provided
    return {"username": username, "email": email, "role": role}

# This works
user = create_user(username="alice", email="alice@example.com")

# This raises ParamError: "Missing required argument: 'email'"
try:
    user = create_user(username="bob")
except ParamError as e:
    print(e)

Optional Parameter Removal

from func_args.arg import OPT, remove_optional

# Function with many optional parameters
def search_items(query, limit=10, offset=0, sort_by=OPT, filter_by=OPT, include_deleted=False):
    # Build base query parameters
    params = {
        "query": query,
        "limit": limit,
        "offset": offset,
        "sort_by": sort_by,
        "filter_by": filter_by,
        "include_deleted": include_deleted,
    }

    # Remove optional parameters that weren't provided
    clean_params = remove_optional(**params)

    # Now we can safely pass to the API without sending None values or defaults
    return api_search(**clean_params)

Enhanced Dataclasses

import dataclasses
from func_args.dataclass import BaseModel, REQ, OPT

@dataclasses.dataclass
class UserParameters(BaseModel):
    """Parameter class for user operations with validation."""

    # Required fields
    username: str = dataclasses.field(default=REQ)
    email: str = dataclasses.field(default=REQ)

    # Optional fields
    display_name: str = dataclasses.field(default=OPT)
    role: str = dataclasses.field(default="user")
    tags: list = dataclasses.field(default_factory=list)

    def validate_email(self):
        """Additional validation logic."""
        if not "@" in self.email:
            raise ValueError("Invalid email format")

    def __post_init__(self):
        # Call the base class validation
        super().__post_init__()
        # Perform additional validation
        self.validate_email()

# Usage
params = UserParameters(username="alice", email="alice@example.com")

# Convert to dict with all fields (including OPT sentinel values)
full_dict = params.to_dict()
# {"username": "alice", "email": "alice@example.com", "display_name": OPT, "role": "user", "tags": []}

# Convert to dict with only provided values (excluding OPT sentinels)
kwargs = params.to_kwargs()
# {"username": "alice", "email": "alice@example.com", "role": "user", "tags": []}

Install

func_args is released on PyPI, so all you need is to:

$ pip install func-args

To upgrade to latest version:

$ pip install --upgrade func-args

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

func_args-1.0.1.tar.gz (14.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

func_args-1.0.1-py3-none-any.whl (15.3 kB view details)

Uploaded Python 3

File details

Details for the file func_args-1.0.1.tar.gz.

File metadata

  • Download URL: func_args-1.0.1.tar.gz
  • Upload date:
  • Size: 14.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.8

File hashes

Hashes for func_args-1.0.1.tar.gz
Algorithm Hash digest
SHA256 f07c2620fa446da54eb0888d5063167b1068d566e1f9a1879fe912c3d7497821
MD5 d6fb4ee61953133fc2fab398cfcb4e1e
BLAKE2b-256 c9f0e3410fc39cb3b4d64206cb97c42a7ff1c2e4cd26516903069daf19b2102b

See more details on using hashes here.

File details

Details for the file func_args-1.0.1-py3-none-any.whl.

File metadata

  • Download URL: func_args-1.0.1-py3-none-any.whl
  • Upload date:
  • Size: 15.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.8

File hashes

Hashes for func_args-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 4562f4eaa0d68142a6ab5ad1f212959fabc2c4cc029b77446bcc377d737e3db4
MD5 19ee414fccc0a65d360fba2bf172832d
BLAKE2b-256 8f0451cce2f0ebe02fc7f15186658a9f129fba2d3b5055e3764d1bf087839988

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page