From 8f8fa4d414e80d9039cef157eb61311b22e13666 Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Mon, 9 Feb 2015 01:57:13 +0100 Subject: [PATCH] core: Emit deprecation warnings The warnings appear as warning level log messages if running Python on the mopidy/ directory like this: python -W all mopidy -v or: python -W all mopidy -o loglevels/py.warnings=warning We don't suppress warnings when Pykka is the caller in general, but just when Pykka is looking at all properties to create its actor proxies. When a deprecated property is used from another Pykka actor, only the stack for the current actor thread is available for inspection, so the warning cannot show where the actual call site in the other actor thread is. Though, if the warnings are made exceptions with: python -W error mopidy then the stack traces will include the frames from all involved actor threads, showing where the original call site is. --- mopidy/core/actor.py | 5 +++-- mopidy/core/playback.py | 16 +++++++++------- mopidy/core/playlists.py | 5 +++-- mopidy/core/tracklist.py | 17 +++++++++-------- mopidy/utils/deprecation.py | 34 ++++++++++++++++++++++++++++++++++ 5 files changed, 58 insertions(+), 19 deletions(-) create mode 100644 mopidy/utils/deprecation.py diff --git a/mopidy/core/actor.py b/mopidy/core/actor.py index 4eabd0ad..cc1cdd9d 100644 --- a/mopidy/core/actor.py +++ b/mopidy/core/actor.py @@ -16,6 +16,7 @@ from mopidy.core.playlists import PlaylistsController from mopidy.core.tracklist import TracklistController from mopidy.models import TlTrack, Track from mopidy.utils import versioning +from mopidy.utils.deprecation import deprecated_property class Core( @@ -68,7 +69,7 @@ class Core( uri_schemes = itertools.chain(*results) return sorted(uri_schemes) - uri_schemes = property(get_uri_schemes) + uri_schemes = deprecated_property(get_uri_schemes) """ .. deprecated:: 0.20 Use :meth:`get_uri_schemes` instead. @@ -78,7 +79,7 @@ class Core( """Get version of the Mopidy core API""" return versioning.get_version() - version = property(get_version) + version = deprecated_property(get_version) """ .. deprecated:: 0.20 Use :meth:`get_version` instead. diff --git a/mopidy/core/playback.py b/mopidy/core/playback.py index 62e83abe..fc273965 100644 --- a/mopidy/core/playback.py +++ b/mopidy/core/playback.py @@ -5,6 +5,7 @@ import urlparse from mopidy.audio import PlaybackState from mopidy.core import listener +from mopidy.utils.deprecation import deprecated_property logger = logging.getLogger(__name__) @@ -50,7 +51,8 @@ class PlaybackController(object): """ self._current_tl_track = value - current_tl_track = property(get_current_tl_track, set_current_tl_track) + current_tl_track = deprecated_property( + get_current_tl_track, set_current_tl_track) """ .. deprecated:: 0.20 Use :meth:`get_current_tl_track` instead. @@ -68,7 +70,7 @@ class PlaybackController(object): if tl_track is not None: return tl_track.track - current_track = property(get_current_track) + current_track = deprecated_property(get_current_track) """ .. deprecated:: 0.20 Use :meth:`get_current_track` instead. @@ -83,7 +85,7 @@ class PlaybackController(object): """ return self._current_metadata_track - current_metadata_track = property(get_current_metadata_track) + current_metadata_track = deprecated_property(get_current_metadata_track) """ .. deprecated:: 0.20 Use :meth:`get_current_metadata_track` instead. @@ -116,7 +118,7 @@ class PlaybackController(object): self._trigger_playback_state_changed(old_state, new_state) - state = property(get_state, set_state) + state = deprecated_property(get_state, set_state) """ .. deprecated:: 0.20 Use :meth:`get_state` and :meth:`set_state` instead. @@ -130,7 +132,7 @@ class PlaybackController(object): else: return 0 - time_position = property(get_time_position) + time_position = deprecated_property(get_time_position) """ .. deprecated:: 0.20 Use :meth:`get_time_position` instead. @@ -162,7 +164,7 @@ class PlaybackController(object): # For testing self._volume = volume - volume = property(get_volume, set_volume) + volume = deprecated_property(get_volume, set_volume) """ .. deprecated:: 0.20 Use :meth:`get_volume` and :meth:`set_volume` instead. @@ -191,7 +193,7 @@ class PlaybackController(object): # For testing self._mute = value - mute = property(get_mute, set_mute) + mute = deprecated_property(get_mute, set_mute) """ .. deprecated:: 0.20 Use :meth:`get_mute` and :meth:`set_mute` instead. diff --git a/mopidy/core/playlists.py b/mopidy/core/playlists.py index 16b29b85..3d368c29 100644 --- a/mopidy/core/playlists.py +++ b/mopidy/core/playlists.py @@ -5,7 +5,8 @@ import urlparse import pykka -from . import listener +from mopidy.core import listener +from mopidy.utils.deprecation import deprecated_property class PlaylistsController(object): @@ -29,7 +30,7 @@ class PlaylistsController(object): playlists = [p.copy(tracks=[]) for p in playlists] return playlists - playlists = property(get_playlists) + playlists = deprecated_property(get_playlists) """ .. deprecated:: 0.20 Use :meth:`get_playlists` instead. diff --git a/mopidy/core/tracklist.py b/mopidy/core/tracklist.py index a9d05570..c54e6784 100644 --- a/mopidy/core/tracklist.py +++ b/mopidy/core/tracklist.py @@ -7,6 +7,7 @@ import random from mopidy import compat from mopidy.core import listener from mopidy.models import TlTrack +from mopidy.utils.deprecation import deprecated_property logger = logging.getLogger(__name__) @@ -29,7 +30,7 @@ class TracklistController(object): """Get tracklist as list of :class:`mopidy.models.TlTrack`.""" return self._tl_tracks[:] - tl_tracks = property(get_tl_tracks) + tl_tracks = deprecated_property(get_tl_tracks) """ .. deprecated:: 0.20 Use :meth:`get_tl_tracks` instead. @@ -39,7 +40,7 @@ class TracklistController(object): """Get tracklist as list of :class:`mopidy.models.Track`.""" return [tl_track.track for tl_track in self._tl_tracks] - tracks = property(get_tracks) + tracks = deprecated_property(get_tracks) """ .. deprecated:: 0.20 Use :meth:`get_tracks` instead. @@ -49,7 +50,7 @@ class TracklistController(object): """Get length of the tracklist.""" return len(self._tl_tracks) - length = property(get_length) + length = deprecated_property(get_length) """ .. deprecated:: 0.20 Use :meth:`get_length` instead. @@ -69,7 +70,7 @@ class TracklistController(object): self.core.playback.on_tracklist_change() self._trigger_tracklist_changed() - version = property(get_version) + version = deprecated_property(get_version) """ .. deprecated:: 0.20 Use :meth:`get_version` instead. @@ -97,7 +98,7 @@ class TracklistController(object): self._trigger_options_changed() return setattr(self, '_consume', value) - consume = property(get_consume, set_consume) + consume = deprecated_property(get_consume, set_consume) """ .. deprecated:: 0.20 Use :meth:`get_consume` and :meth:`set_consume` instead. @@ -129,7 +130,7 @@ class TracklistController(object): random.shuffle(self._shuffled) return setattr(self, '_random', value) - random = property(get_random, set_random) + random = deprecated_property(get_random, set_random) """ .. deprecated:: 0.20 Use :meth:`get_random` and :meth:`set_random` instead. @@ -162,7 +163,7 @@ class TracklistController(object): self._trigger_options_changed() return setattr(self, '_repeat', value) - repeat = property(get_repeat, set_repeat) + repeat = deprecated_property(get_repeat, set_repeat) """ .. deprecated:: 0.20 Use :meth:`get_repeat` and :meth:`set_repeat` instead. @@ -192,7 +193,7 @@ class TracklistController(object): self._trigger_options_changed() return setattr(self, '_single', value) - single = property(get_single, set_single) + single = deprecated_property(get_single, set_single) """ .. deprecated:: 0.20 Use :meth:`get_single` and :meth:`set_single` instead. diff --git a/mopidy/utils/deprecation.py b/mopidy/utils/deprecation.py new file mode 100644 index 00000000..1b744702 --- /dev/null +++ b/mopidy/utils/deprecation.py @@ -0,0 +1,34 @@ +from __future__ import unicode_literals + +import inspect +import warnings + + +def _is_pykka_proxy_creation(): + stack = inspect.stack() + try: + calling_frame = stack[3] + except IndexError: + return False + else: + filename = calling_frame[1] + funcname = calling_frame[3] + return 'pykka' in filename and funcname == '_get_attributes' + + +def deprecated_property( + getter=None, setter=None, message='Property is deprecated'): + + def deprecated_getter(*args): + if not _is_pykka_proxy_creation(): + warnings.warn(message, DeprecationWarning, stacklevel=2) + return getter(*args) + + def deprecated_setter(*args): + if not _is_pykka_proxy_creation(): + warnings.warn(message, DeprecationWarning, stacklevel=2) + return setter(*args) + + new_getter = getter and deprecated_getter + new_setter = setter and deprecated_setter + return property(new_getter, new_setter)