Repository: Pyomo/pyomo

Issue:
[PEP] Process for Deprecation and Removal of Pyomo Capabilities
## Proposal

For any functionality that is documented in the Pyomo book, the decision to deprecate or not should be decided by the PMC with a vote. This vote should be held before the PR is merged. Wherever possible, when deprecating code in Pyomo, we should use the deprecation decorators.

## Motivation

We want to take care when deprecating functionality and make sure that the entire team is aware of the impact, and that alternative options have been discussed and explored.


Discussion:
I think this should be generalized to consider changes in pyomo related to online documentation and journal/conference publications as well.
I'm uncomfortable with the implicit assumption that our APIs are "fixed" after they have been documented.  I believe that this will discourage the team from documenting their work, since this provides a penalty for penalty w.r.t. future changes.

We should generalize this PEP to define a mechanism for documenting APIs that we are not committing to supporting long term. 
I agree that we should not assume that the APIs are fixed. However, I do think we should have a discussion before deprecating functionality that is documented in the Pyomo book. (This does not mean that we won't agree to deprecate - just that a discussion happens.)

Also, I think it is difficult to know ahead of time which APIs you will want to change. I think we need to be more flexible here and discuss it on a case-by-case basis. I don't think I would be able to tell you ahead of time which APIs were "long-term" and which were not.
I think APIs documented in the online docs are less critical than APIs documented in the book because the online docs can be updated quickly and easily (while the book cannot).

Resolving patch:
diff --git a/pyomo/common/deprecation.py b/pyomo/common/deprecation.py
--- a/pyomo/common/deprecation.py
+++ b/pyomo/common/deprecation.py
@@ -178,6 +178,12 @@ def deprecation_warning(msg, logger=None, version=None,
         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) ...
+
     """
     if logger is None:
         if calling_frame is not None:
@@ -224,7 +230,7 @@ def deprecation_warning(msg, logger=None, version=None,
 
 
 def deprecated(msg=None, logger=None, version=None, remove_in=None):
-    """Decorator to indicate that a function, method or class is deprecated.
+    """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
@@ -247,6 +253,17 @@ def deprecated(msg=None, logger=None, version=None, remove_in=None):
         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
+
     """
     def wrap(obj):
         if inspect.isclass(obj):


Test patch: