Deprecation and Removal of Functionality

During the course of development, there may be cases where it becomes necessary to deprecate or remove functionality from the standard Pyomo offering.

Deprecation

We offer a set of tools to help with deprecation in pyomo.common.deprecation.

By policy, when deprecating or moving an existing capability, one of the following utilities should be leveraged. Each has a required version argument that should be set to current development version (e.g., "6.6.2.dev0"). This version will be updated to the next actual release as part of the Pyomo release process. The current development version can be found by running pyomo --version on your local fork/branch.

deprecated([msg, logger, version, remove_in])

Decorator to indicate that a function, method, or class is deprecated.

deprecation_warning(msg[, logger, version, ...])

Standardized formatter for deprecation warnings

relocated_module(new_name[, msg, logger, ...])

Provide a deprecation path for moved / renamed modules

relocated_module_attribute(local, target, ...)

Provide a deprecation path for moved / renamed module attributes

RenamedClass(name, bases, classdict, *args, ...)

Metaclass to provide a deprecation path for renamed classes

@pyomo.common.deprecation.deprecated(msg=None, logger=None, version=None, remove_in=None)[source]

Decorator to indicate that a function, method, or class is deprecated.

This decorator will cause a warning to be logged when the wrapped function or method is called, or when the deprecated class is constructed. This decorator also updates the target object’s docstring to indicate that it is deprecated.

Parameters:
  • msg (str) – a custom deprecation message (default: “This {function|class} has been deprecated and may be removed in a future release.”)

  • logger (str) – the logger to use for emitting the warning (default: the calling pyomo package, or “pyomo”)

  • version (str) – [required] the version in which the decorated object was deprecated. General practice is to set version to the current development version (from pyomo –version) during development and update it to the actual release as part of the release process.

  • remove_in (str) – the version in which the decorated object will be removed from the code.

Example

>>> from pyomo.common.deprecation import deprecated
>>> @deprecated(version='1.2.3')
... def sample_function(x):
...     return 2*x
>>> sample_function(5)
WARNING: DEPRECATED: This function (sample_function) has been deprecated and
    may be removed in a future release.  (deprecated in 1.2.3) ...
10
pyomo.common.deprecation.deprecation_warning(msg, logger=None, version=None, remove_in=None, calling_frame=None)[source]

Standardized formatter for deprecation warnings

This is a standardized routine for formatting deprecation warnings so that things look consistent and “nice”.

Parameters:
  • msg (str) – the deprecation message to format

  • logger (str) – the logger to use for emitting the warning (default: the calling pyomo package, or “pyomo”)

  • version (str) – [required] the version in which the decorated object was deprecated. General practice is to set version to the current development version (from pyomo –version) during development and update it to the actual release as part of the release process.

  • remove_in (str) – the version in which the decorated object will be removed from the code.

  • calling_frame (frame) – the original frame context that triggered the deprecation warning.

Example

>>> from pyomo.common.deprecation import deprecation_warning
>>> deprecation_warning('This functionality is deprecated.', version='1.2.3')
WARNING: DEPRECATED: This functionality is deprecated.  (deprecated in 1.2.3) ...
pyomo.common.deprecation.relocated_module(new_name, msg=None, logger=None, version=None, remove_in=None)[source]

Provide a deprecation path for moved / renamed modules

Upon import, the old module (that called relocated_module()) will be replaced in sys.modules by an alias that points directly to the new module. As a result, the old module should have only two lines of executable Python code (the import of relocated_module and the call to it).

Parameters:
  • new_name (str) – The new (fully-qualified) module name

  • msg (str) – A custom deprecation message.

  • logger (str) – The logger to use for emitting the warning (default: the calling pyomo package, or “pyomo”)

  • version (str [required]) – The version in which the module was renamed or moved. General practice is to set version to the current development version (from pyomo –version) during development and update it to the actual release as part of the release process.

  • remove_in (str) – The version in which the module will be removed from the code.

Example

>>> from pyomo.common.deprecation import relocated_module
>>> relocated_module('pyomo.common.deprecation', version='1.2.3')
WARNING: DEPRECATED: The '...' module has been moved to
    'pyomo.common.deprecation'. Please update your import.
    (deprecated in 1.2.3) ...
pyomo.common.deprecation.relocated_module_attribute(local, target, version, remove_in=None, msg=None, f_globals=None)[source]

Provide a deprecation path for moved / renamed module attributes

This function declares that a local module attribute has been moved to another location. For Python 3.7+, it leverages a module.__getattr__ method to manage the deferred import of the object from the new location (on request), as well as emitting the deprecation warning.

Parameters:
  • local (str) – The original (local) name of the relocated attribute

  • target (str) – The new absolute import name of the relocated attribute

  • version (str) – The Pyomo version when this move was released (passed to deprecation_warning)

  • remove_in (str) – The Pyomo version when this deprecation path will be removed (passed to deprecation_warning)

  • msg (str) – If not None, then this specifies a custom deprecation message to be emitted when the attribute is accessed from its original location.

class pyomo.common.deprecation.RenamedClass(name, bases, classdict, *args, **kwargs)[source]

Metaclass to provide a deprecation path for renamed classes

This metaclass provides a mechanism for renaming old classes while still preserving isinstance / issubclass relationships.

Examples

>>> from pyomo.common.deprecation import RenamedClass
>>> class NewClass(object):
...     pass
>>> class OldClass(metaclass=RenamedClass):
...     __renamed__new_class__ = NewClass
...     __renamed__version__ = '6.0'

Deriving from the old class generates a warning:

>>> class DerivedOldClass(OldClass):
...     pass
WARNING: DEPRECATED: Declaring class 'DerivedOldClass' derived from
    'OldClass'. The class 'OldClass' has been renamed to 'NewClass'.
    (deprecated in 6.0) ...

As does instantiating the old class:

>>> old = OldClass()
WARNING: DEPRECATED: Instantiating class 'OldClass'.  The class
    'OldClass' has been renamed to 'NewClass'.  (deprecated in 6.0) ...

Finally, isinstance and issubclass still work, for example:

>>> isinstance(old, NewClass)
True
>>> class NewSubclass(NewClass):
...     pass
>>> new = NewSubclass()
>>> isinstance(new, OldClass)
WARNING: DEPRECATED: Checking type relative to 'OldClass'.  The class
    'OldClass' has been renamed to 'NewClass'.  (deprecated in 6.0) ...
True

Removal

By policy, functionality should be deprecated with reasonable warning, pending extenuating circumstances. The functionality should be deprecated, following the information above.

If the functionality is documented in the most recent edition of [Pyomo - Optimization Modeling in Python], it may not be removed until the next major version release.

For other functionality, it is preferred that ample time is given before removing the functionality. At minimum, significant functionality removal will result in a minor version bump.