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.
This commit is contained in:
Stein Magnus Jodal 2015-02-09 01:57:13 +01:00
parent 5827e45c34
commit 8f8fa4d414
5 changed files with 58 additions and 19 deletions

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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)