Skip to content

Files

Latest commit

f8dc0cf · Jun 7, 2023

History

History
528 lines (383 loc) · 12.5 KB

deprecation.md

File metadata and controls

528 lines (383 loc) · 12.5 KB
jupytext kernelspec
cell_metadata_filter formats text_representation
-all
md:myst
extension format_name format_version jupytext_version
.md
myst
0.13
1.14.5
display_name language name
Python 3 (ipykernel)
python
python3

Deprecations

If you use this module, ensure you pin this version in the `setup.py` file (`ploomber-core>=0.2`)

The deprecated module contains utilities for marking code as deprecated, renaming and changing default values.

When using this module, ensure you add unit tests, click here to see [sample tests.](https://github.com/ploomber/core/blob/main/tests/test_deprecated.py)
When introducing changes, we add some directives to the docstrings, consider adding them to the tutorials that use them as well.

+++

Function deprecated

To deprecate a function, use deprecated.function, and add the .. deprecated:: directive:

from ploomber_core import deprecated


@deprecated.function(deprecated_in="0.1", remove_in="0.2")
def add(x, y):
    """
    Notes
    -----
    .. deprecated:: 0.1
        ``add`` is deprecated, will be removed in version 0.2
    """
    return x + y

When a use calls the function, a warning is displayed:

add(21, 21)

Function renamed

If the function will not disappear but be renamed, pass name_new="new_name".

Furthermore, add the following directives to the docstrings (with the appropriate message):

  • .. versionadded:: {deprecated_in}: to the new function
  • .. deprecated:: {deprecated_in}: to the old function
from ploomber_core import deprecated


def sum(x, y):
    """
    Notes
    -----
    .. versionadded:: 0.1
        ``sum`` was renamed from ``add``. ``add`` removed in version 0.2
    """
    return x + y


@deprecated.function(deprecated_in="0.1", remove_in="0.2", new_name="sum")
def add(x, y):
    """
    Notes
    -----
    .. deprecated:: 0.1
        ``add`` renamed to ``sum``. ``add`` will be removed in version 0.2
    """
    return x + y

Using the old function shows a warning:

add(21, 21)

The new one doesn't show warnings:

sum(21, 21)

Custom message

If you need to customize the message, use custom_mesasge.

Furthermore, add the following directives to the docstrings (with the appropriate message):

  • .. versionadded:: {deprecated_in}: to the new function (include the custom message)
  • .. deprecated:: {deprecated_in}: to the old function
from ploomber_core import deprecated


def sum(a, b):
    """
    Notes
    -----
    .. versionadded:: 0.1
        ``sum`` was renamed from ``add``, and parameters renamed to ``a``, and ``b``.
        ``add`` removed in version 0.2
    """
    return a + b


@deprecated.function(
    deprecated_in="0.1",
    remove_in="0.3",
    new_name="sum",
    custom_message="Params renamed to a and b",
)
def add(x, y):
    """
    Notes
    -----
    .. deprecated:: 0.1
        ``add`` renamed to ``sum``. ``add`` will be removed in version 0.2
    """
    return x + y


add(21, 21)

Method deprecated

To deprecate a method in a class, use deprecated.method, also add the .. deprecated:: directive.

from ploomber_core import deprecated


class SomeClass:
    @deprecated.method(deprecated_in="0.1", remove_in="0.3")
    def do_something(self):
        """
        Notes
        -----
        .. deprecated:: 0.1
            ``do_something`` is deprecated, and it will be removed in version 0.2
        """
        return 42


obj = SomeClass()

# calling a deprecated method shows a warning
obj.do_something()

Method renamed

If a method is renamed, use deprecated.method.

Furthermore, add the following directives to the docstrings (with the appropriate message):

  • .. versionadded:: {deprecated_in}: to the new method
  • .. deprecated:: {deprecated_in}: to the old method
from ploomber_core import deprecated


class SomeClass:
    @deprecated.method(deprecated_in="0.1", remove_in="0.2", new_name="something_else")
    def do_something(self, *args, **kwargs):
        """
        Notes
        -----
        .. deprecated:: 0.1
            ``do_something`` renamed to ``do_something_else``. ``do_something`` will
            be removed in version 0.2
        """
        return self.do_something_else(*args, **kwargs)

    def do_something_else(self, a, b):
        """
        Notes
        -----
        .. versionadded:: 0.1
            ``do_something_else`` was renamed from ``do_something``. ``do_something``
            removed in version 0.2
        """
        return a + b


obj = SomeClass()
obj.do_something(1, 1)

Custom message

If the method was renamed and any other behavior changed, use custom_message.

Furthermore, add the following directives to the docstrings (with the appropriate message):

  • .. versionadded:: {deprecated_in}: to the new method (include custom message)
  • .. deprecated:: {deprecated_in}: to the old method
from ploomber_core import deprecated


class SomeClass:
    @deprecated.method(
        deprecated_in="0.1",
        remove_in="0.2",
        new_name="something_else",
        custom_message="Parameters changed from x, y to a, b",
    )
    def do_something(self, x, y):
        """
        Notes
        -----
        .. deprecated:: 0.1
            ``do_something`` renamed to ``do_something_else``. ``do_something``
            will be removed in version 0.2
        """
        return self.do_something_else(x, y)

    def do_something_else(self, a, b):
        """
        Notes
        -----
        .. versionadded:: 0.1
            ``do_something_else`` was renamed from ``do_something``. Parameters
            changed from x, y to a, b ``do_something`` removed in version 0.2
        """
        return a + b


obj = SomeClass()
obj.do_something(1, 1)

Attribute deprecated

Use deprecated.method to deprecate attributes, and add the .. deprecated:: {deprecated_in} directive:

from ploomber_core import deprecated


class SomeClass:
    @property
    @deprecated.method(deprecated_in="0.1", remove_in="0.2")
    def some_attribute(self):
        """

        Notes
        -----
        .. deprecated:: 0.1
            ``some_attribute`` is deprecated, will be removed in version 0.2
        """
        return 42


obj = SomeClass()

obj.some_attribute

Attribute renamed

If an attribute is renamed, use deprecated.method and pass the renamed argument.

Furthermore, add the following directives to the docstrings (with the appropriate message):

  • .. versionadded:: {deprecated_in}: to the new attribute
  • .. deprecated:: {deprecated_in}: to the old attribute
from ploomber_core import deprecated


class SomeClass:
    @property
    @deprecated.method(deprecated_in="0.1", remove_in="0.2", new_name="new_attribute")
    def some_attribute(self):
        """
        Notes
        -----
        .. deprecated:: 0.1
            ``some_attribute`` renamed to ``new_attribute``. ``some_attribute``
            will be removed in version 0.2
        """
        return self.new_attribute

    @property
    def new_attribute(self):
        """
        Notes
        -----
        .. versionadded:: 0.1
            ``new_attribute`` was renamed from ``some_attribute``. ``some_attribute``
            removed in version 0.2
        """
        return 42


obj = SomeClass()

obj.some_attribute

Parameter deprecated

If a function/method argument is deprecated, set the default value "deprecated" and use the following recipe (remember to add the .. deprecated:: {deprecated_in} directive):

from ploomber_core import deprecated


def example_function(k="deprecated"):
    """
    Notes
    -----
    .. deprecated:: 0.1
        ``k`` argument is deprecated, will be removed in version 0.2
    """
    deprecated.parameter_deprecated(
        deprecated_in="0.1", remove_in="0.3", name_old="k", value_passed=k
    )

This will have no effect on calls that do not use such argument:

example_function()

But will warn users if they are passing such parameter:

example_function(k=1)

Parameter renamed

If a parameter is renamed, follow these steps:

  • Add the new parameter in the same position as the old one
  • Set the old default value in the new parameter (if any)
  • Move the old parameter to the end
  • Set the default value of the old parameter to "deprecated"
  • Add the .. deprecated:: {removed_in} directive

Then, call deprecated.parameter_renamed. Example:

from ploomber_core import deprecated


def example_function(n_clusters=8, another=42, k="deprecated"):
    """

    Notes
    -----
    .. deprecated:: 0.1
        ``k`` was renamed to ``n_clusters``. ``k`` removed in 0.2
    """
    n_clusters = deprecated.parameter_renamed(
        deprecated_in="0.1",
        remove_in="0.2",
        old_name="k",
        old_value=k,
        new_name="n_clusters",
        new_value=n_clusters,
    )

    print(f"n_clusters={n_clusters!r}, k={k!r}")

    # ignore k and use n_clusters in the body of the function

If the user is not using the deprecated parameter (k), no warning is shown:

example_function()

If a user passes the deprecated argument (k), a warning is displayed and the value is assigned to the new argument n_clusters:

example_function(k=10)

Once the user migrates to the new one, no warning is displayed:

example_function(n_clusters=10)

Parameter with new default value

If a default value is changed, set it to "warn", and use the .. versionchanged:: {removed_in} directive:

from ploomber_core import deprecated


def example_function(n_clusters="warn"):
    """

    Notes
    -----
    .. versionchanged:: 0.2
        'n_clusters' default value changed from 5 to 10
    """
    n_clusters = deprecated.parameter_default_changed(
        "0.2", name="n_clusters", old_default=5, new_default=10, value=n_clusters
    )

    print(f"n_clusters is {n_clusters}")

Functions that do not rely on the default value won't show any warning:

example_function(n_clusters=3)

But if a user relies on the default value, the old default value is used but a warning is shown:

example_function()

Parameter renamed and changed

If the parameter is renamed and behavior changes:

  • Add the new parameter in the same position as the old one
  • Set the old default value in the new parameter (if any)
  • Move the old parameter to the end
  • Set the default value of the old parameter to "deprecated"
  • Add the .. deprecated:: {removed_in} directive
  • Include a message with the new default
from ploomber_core import deprecated


def example_function(n_clusters=10, another=42, k="deprecated"):
    """

    Notes
    -----
    .. deprecated:: 0.1
        ``k`` was renamed to ``n_clusters``. ``k`` removed in 0.2. Default n_clusters
        is 10
    """
    n_clusters = deprecated.parameter_renamed(
        "0.1",
        "0.2",
        old_name="k",
        old_value=k,
        new_name="n_clusters",
        new_value=n_clusters,
        custom_message="Default n_clusters is 10",
    )

    print(f"n_clusters={n_clusters!r}, k={k!r}")

    # ignore k and use n_clusters in the body of the function
example_function(k=10)

Deprecation warning with logger

deprecation_warning(telemetry, message) is designed to facilitate the logging of deprecated features in your codebase. It throws warning messages and log the information about the message, the current package name and version.

We need to provide telemetry instance and the message string:

Example

In the jupysql project, we may import the existing telemetry instance and pass to deprecation_warning

from sql.telemetry import telemetry

def some_random_func():
    deprecation_warning(telemetry, "you are using old feature")

some_random_func()

The message you are using old feature and jupysql package info will be logged

Reference

This is based on sklearn's guidelines.