In Python, is there a common pattern to using methods that have arguments that are only used a method's decorator?

Viewed 65

Goal

To have a type hinted argument on a method that doesn't get caught by linters like pylint as unused.

Context

We have an argument called context that we work with within a decorator.

  • This context arg isn't used within the decorated method.
  • context is an optional arg.

Solutions

Current Solution

As of today, we simply pass in the arg to the decorated method even though the method itself doesn't declare this arg and we have the decorator remove this arg from the set of args so that when the func is actually called within the decorator, the arg is not present, thus avoiding issues.

def wrapper(func):
    @functools.wraps(func)
    def handler(*args, **kwargs):
        
        # Here we run our logic that used the arg passed in when calling the method

        # Since the method itself doesn't need this arg, we remove it
        try:
            del kwargs['context']
        except KeyError:
            pass

        return func(*args, **kwargs)

     return handler

Downsides

What this does is removes the ability for us to type hint or offer up this additional arg as a documented arg (read: documented as in available via IDE hinting or auto-docs).

Upsides

Pylint and other linters leave us alone without having to add exceptions everywhere :)

Previous Solution

The other solution we had before coming to the current solution was to simply do something like this:

@wrapper
def my_method(arg1: str, arg2: str, dec_arg: bool):
    _ = dec_arg
    print(arg1)
    print(arg2)

Downsides

  • Busy work keeping up on the _.

Upsides

  • Type hints / docs

Final Notes

While not optimal in terms of type hinting, I'm ok with the current solution, I just want to make sure I'm not missing out on doing something in a better way :)

Thanks in advance!

1 Answers

Just because it's optional doesn't mean you can't explicitly declare it.

def wrapper(func):
    @functools.wraps(func)
    def handler(*args, context: str = None, **kwargs):
        
        # Here we run our logic that used the arg passed in when calling the method

        return func(*args, **kwargs)

     return handler

This makes context an optional keyword-only argument that is not captured by kwargs.

Related