How to deprecate a function input argument and maintain backward compatibility

Viewed 119

I would like to change the input arguments of a function. This will also lead to changes within the function body. What's a pythonic way to mark an input argument "deprecated" and maintain backward compatibility at the same time? Here's a toy example:

from typing import List


# original function
def sum_numbers(numbers: List[int]):
    return sum(numbers)


# function with changed input arguments and function body
def sum_numbers(a: int, b: int) -> int:
    return a + b

The user should be able to call sum_numbers either with numbers: List[int] argument or by using a: int, b: int. However, I want to submit a DeprecationWarning when the user uses the original call method.

2 Answers

An option is to overload the function using multipledispatch module:

from multipledispatch import dispatch

@dispatch(int, int)
def sum_numbers(a, b):
    print("Deprecated")
    return a + b

@dispatch(list)
def sum_numbers(numbers):
    return sum(numbers)

An alternative to multipledispatch is to take in *args or have an optional arg and dispatch internally:

# original function
def sum_numbers(a, b=None):
    if isinstance(a, list):
        warnings.warn("...", DeprecationWarning, stacklevel=2)
        return sum(numbers)
    return a + b

then for typing purposes you can use typing.overload:

@typing.overload
def sum_numbers(numbers: list[int]) -> int:
    """deprecated"""
@typing.overload
def sum_numbers(a: int, b: int) -> int:
    ...

(note that as documented the overloads should come first and the actual implementation last)

Related