`getDevicesBySerial` has no callers and the other two don't offer any value beyond their list comprehension equivalents `[d for d in dt.devices if isinstance(d, cls)]` (`getDevicesByInstance`) and `[d for d in dt.devices if d.type == devtype]` (`getDevicesByType`).
The first patch establishes a basic procedure for deprecating things in blivet. The warnings will only be logged if someone has called `blivet.util.set_up_logging`.
From: David Lehman dlehman@redhat.com
--- blivet/__init__.py | 8 ++++++++ blivet/util.py | 5 +++++ 2 files changed, 13 insertions(+)
diff --git a/blivet/__init__.py b/blivet/__init__.py index e2afc16..43e5ff7 100644 --- a/blivet/__init__.py +++ b/blivet/__init__.py @@ -51,6 +51,7 @@ def cb(self, exn):
import sys import importlib +import warnings
from . import util, arch from .flags import flags @@ -59,6 +60,13 @@ def cb(self, exn): log = logging.getLogger("blivet") program_log = logging.getLogger("program")
+# Tell the warnings module not to ignore DeprecationWarning, which it does by +# default since python-2.7. +warnings.simplefilter('module', DeprecationWarning) + +# Enable logging of python warnings. +logging.captureWarnings(True) + # XXX: respect the level? Need to translate between C and Python log levels. log_bd_message = lambda level, msg: program_log.info(msg)
diff --git a/blivet/util.py b/blivet/util.py index cf329f9..97ca3b5 100644 --- a/blivet/util.py +++ b/blivet/util.py @@ -518,6 +518,11 @@ def set_up_logging(log_file='/tmp/blivet.log'): handler.setFormatter(formatter) log.addHandler(handler) program_log.addHandler(handler) + + # capture python warnings in our logs + warning_log = logging.getLogger("py.warnings") + warning_log.addHandler(handler) + log.info("sys.argv = %s", sys.argv)
def create_sparse_tempfile(name, size):
From: David Lehman dlehman@redhat.com
--- blivet/devicetree.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+)
diff --git a/blivet/devicetree.py b/blivet/devicetree.py index 3349569..ff7d8ee 100644 --- a/blivet/devicetree.py +++ b/blivet/devicetree.py @@ -22,6 +22,7 @@
import os import re +import warnings
from gi.repository import BlockDev as blockdev
@@ -695,8 +696,15 @@ def getDevicesBySerial(self, serial, incomplete=False, hidden=False): :param bool hidden: include hidden devices in search :returns: all matching devices found :rtype: list of :class:`~.devices.Device` + + .. deprecated:: 1.7 + Use ``[d for d in dt.devices if d.serial == serial]`` instead. + """ log_method_call(self, serial=serial, incomplete=incomplete, hidden=hidden) + warnings.warn("DeviceTree.getDevicesBySerial will be removed in a " + "future version.", + DeprecationWarning) devices = self._filterDevices(incomplete=incomplete, hidden=hidden) retval = [] for device in devices: @@ -779,8 +787,15 @@ def getDevicesByType(self, device_type, incomplete=False, hidden=False): :param bool hidden: include hidden devices in search :returns: all matching device found :rtype: list of :class:`~.devices.Device` + + .. deprecated:: 1.7 + Use ``[d for d in dt.devices if d.type == dtype]`` instead. + """ log_method_call(self, device_type=device_type, incomplete=incomplete, hidden=hidden) + warnings.warn("DeviceTree.getDevicesByType will be removed in a " + "future version.", + DeprecationWarning) devices = self._filterDevices(incomplete=incomplete, hidden=hidden) result = [d for d in devices if d.type == device_type] log_method_return(self, [r.name for r in result]) @@ -794,8 +809,15 @@ def getDevicesByInstance(self, device_class, incomplete=False, hidden=False): :param bool hidden: include hidden devices in search :returns: all matching device found :rtype: list of :class:`~.devices.Device` + + .. deprecated:: 1.7 + Use ``[d for d in dt.devices if isinstance(dev, cls)]`` instead. + """ log_method_call(self, device_class=device_class, incomplete=incomplete, hidden=hidden) + warnings.warn("DeviceTree.getDevicesByInstance will be removed in a " + "future version.", + DeprecationWarning) devices = self._filterDevices(incomplete=incomplete, hidden=hidden) result = [d for d in devices if isinstance(d, device_class)] log_method_return(self, [r.name for r in result])
It's probably worth it to have a decorator, like:
``` def deprecate_method(func):
@wraps(func) def the_func(*args, **kwargs): """ generate a warning message for a deprecated function, then call the function """ warnings.warn("%s will be removed in a future version" % func.__name__, DeprecationWarning) return func(*args, **kwargs)
return the_func ```
in storage_log module and use that for getting the warnings into the deprecated methods.
This is much nicer than I expected. ACK.
Added label: ACK.
I agree, this is nice and simple. Do you think it makes sense to change the comment from "$function will be removed in a future version" to specify which future version? (If it's always going to be the next major version, at least; and it might be easier for us to keep track of as well when we go back through and do the actual deletions.)
I didn't think we made a final decision regarding how long to wait before removing deprecated methods, so I intentionally left it vague. We talked about removing it in the next major version, but also about leaving it in until the second time we increment the major version (to make sure people have a chance to see the deprecation warnings). I also noticed that most other python code that does this does not identify a specific version for the removal.
I'm definitely for removing stuff in the second future major version from where it got deprecated. Just like @dwlehman says, we should give people a chance to see the warrnings.
I considered a decorator but since it doesn't handle the sphinx part I decided against it.
Twisted's deprecated decorator handles the docstring part as well, by mangling the ```__doc__``` attribute. But that kind of thing is ugly, so I didn't want to suggest it.
But it still seems like a decorator that handled the warnings would be helpful for encouraging uniformity and recognizability and probably checkability.
I think that you could deprecate a class by deprecating its constructor using the same method as for deprecating methods.
And, while munging the docstring may be ugly, at least sphinx will generate pretty documentation from the munged doc string. So, it's a better idea than it seemed at first.
Yeah, I was looking into having the decorator munge the docstring. That would make it worth doing IMO, and I don't really care if it's ugly or not.
anaconda-patches@lists.fedorahosted.org