Add a decorator for migrating to functions with keyword-only arguments.

Review Request #12555 — Created Aug. 19, 2022 and submitted — Latest diff uploaded


The RBTools codebase is old, and we have a lot of code that doesn't
quite follow best practices. These include functions that take a whole
lot of keyword arguments, but with calls passing values as positional
arguments instead.

Python 3 allows us to define keyword-only arguments, which can help us
clean things up, but as we aim to provide backwards-compatibility during
deprecation phases, we can't just simply use them.

This change introduces a decorator to help with this.

rbtools.deprecation.deprecate_non_keyword_only_args() can be used for
any function taking keyword-only arguments. Any call that supplies such
an argument via a positional argument value will trigger a deprecation
warning. The arguments will then be rewritten to pass those in as
keyword arguments.

We'll want this pattern for other codebases in time. Unfortunately, no
other packages we depend on provide a decorator like this, so we'll need
to maintain it ourselves. (Packages like debtcollector do not provide
anything for this.). For now, it will remain in RBTools.

Decorated some functions and tested calls with and without using
keyword arguments for the values. Verified the warnings only appeared
when passing values as positional arguments.

Verified that the warning's stack trace had the right stack level,
showing the call to the function.

Unit tests pass on Python 3.7-3.11.