Supporting Multiple Versions

If you are a library maintainer, you may want to support multiple versions of Click. See the Pallets version policy for information about our version numbers and support policy.

Most features of Click are stable across releases, and don’t require special handling. However, feature releases may deprecate and change APIs. Occasionally, a change will require special handling.

Use Feature Detection

Prefer using feature detection. Looking at the version can be tempting, but is often more brittle or results in more complicated code. Try to use if or try blocks to decide whether to use a new or old pattern.

If you do need to look at the version, use importlib.metadata.version(), the standardized way to get versions for any installed Python package.

Changes in 8.2

ParamType methods require ctx

In 8.2, several methods of ParamType now have a ctx: click.Context argument. Because this changes the signature of the methods from 8.1, it’s not obvious how to support both when subclassing or calling.

This example uses ParamType.get_metavar, and the same technique should be applicable to other methods such as get_missing_message.

Update your methods overrides to take the new ctx argument. Use the following decorator to wrap each method. In 8.1, it will get the context where possible and pass it using the 8.2 signature.

import functools
import typing as t
import click

F = t.TypeVar("F", bound=t.Callable[..., t.Any])

def add_ctx_arg(f: F) -> F:
    @functools.wraps(f)
    def wrapper(*args: t.Any, **kwargs: t.Any) -> t.Any:
        if "ctx" not in kwargs:
            kwargs["ctx"] = click.get_current_context(silent=True)

        return f(*args, **kwargs)

    return wrapper  # type: ignore[return-value]

Here’s an example ParamType subclass which uses this:

class CommaDelimitedString(click.ParamType):
    @add_ctx_arg
    def get_metavar(self, param: click.Parameter, ctx: click.Context | None) -> str:
        return "TEXT,TEXT,..."