Deprecation best practices#

While deprecation best practices are outlined in a Stack Overflow Answer and in this Deprecation library , there is no official guidance on deprecating features within Python. Thus, this topic provides deprecation best practices for PyAnsys libraries.

Whenever you deprecate a method, class, or function, you must either:

  • Have the old method call the new method and raise a warning

  • Raise an AttributeError if you remove the method entirely

In the docstring of the old method, provide a Sphinx Deprecated Directive that links to the new method. This way, you notify your users when you make an API change and give them a chance to change their code. Otherwise, users stop upgrading, or worse, stop using your API, due to stability concerns. For this reason, it is best to use a warning first and then use an error after a minor release or two.

import warnings


class FieldAnalysis2D:
    """Class docstring"""

    def assignmaterial(self, obj, mat):
        """Assign a material to one or more objects.

        .. deprecated:: 0.4.0
           Use :func:`FieldAnalysis2D.assign_material` instead.

        """
        # one of the following:

        # raise a DeprecationWarning. User won't have to change anything
        warnings.warn(
            "`assignmaterial` is deprecated. Use `assign_material` instead.",
            DeprecationWarning,
        )
        self.assign_material(obj, mat)

        # or raise an AttributeError (could also make a custom DeprecationError)
        raise AttributeError(
            "`assignmaterial` is deprecated. Use `assign_material` instead."
        )

    def assign_material(self, obj, mat):
        """Assign a material to one or more objects.
        ...
        """

If you remove a method entirely, there is no reason to provide a link to the old method. Simply raise an AttributeError as part of the class or raise an Exception.

def hello_world():
    """Print ``"hello_world"``

    .. deprecated:: 0.4.0
        This function has been deprecated.

    """
    raise Exception("`my_function` has been deprecated")

Because there is no built-in deprecation error within Python, an alternate approach is to create a custom DeprecationError.

class DeprecationError(RuntimeError):
    """Used for deprecated methods and functions."""

    def __init__(self, message="This feature has been deprecated."):
        """Empty init."""
        RuntimeError.__init__(self, message)

You then use this custom DeprecationError in place of an Exception.

def hello_world():
    """Print ``"hello_world"``

    .. deprecated:: 0.4.0
        This function has been deprecated.

    """
    raise DeprecationError('`my_function` has been deprecated.')