Skip to content

How to use arguments with default value? #277

@NellyWhads

Description

@NellyWhads

I have a simple decorator constructed like so:

def public_api(stage: Literal["alpha", "beta", "stable"] = "stable"):
    """Decorate public APIs with versioning.

    Parameters
    ----------
    stage : {'alpha', 'beta', 'stable'}, default='stable'
        Stage of the API.
    """
    logger = logging.getLogger(__name__)
    _pub_api_tracker = threading.local()

    def decorator(wrapped: Callable):
        @wrapt.decorator
        def wrapper(wrapped, _instance, args, kwargs):
            if stage != "stable" and not hasattr(_pub_api_tracker, "used"):
                logger.info(
                    f"{stage.title()} API: {wrapped.__module__}.{wrapped.__qualname__} "
                    f"is in {stage} stage and may have breaking changes."
                )
                _pub_api_tracker.used = True

            if stage == "stable":
                # Verify that the function or method is fully type annotated
                sig = inspect.signature(wrapped)
                for param in sig.parameters.values():
                    if param.annotation is param.empty:
                        raise TypeError(f"Parameter '{param.name}' in {wrapped.__name__} is missing a type annotation.")
                if sig.return_annotation is sig.empty:
                    raise TypeError(f"Return type of {wrapped.__name__} is missing a type annotation.")
            return wrapped(*args, **kwargs)

        return wrapper(wrapped)

    return decorator

I can of course use the default argument of this decorator by applying it like so:

@public_api()
def my_func(input: str) -> str:
    return input

However, it does not behave well when used like this:

@public_api
def my_func(input: str) -> str:
    return input

Is there a way to make the latter work as well without losing all of the clean typing on the decorator?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions