Skip to content

Commit

Permalink
Release v3.0.2
Browse files Browse the repository at this point in the history
  • Loading branch information
jodal committed Apr 2, 2020
2 parents 9f39bdd + 56cacc5 commit 49508ee
Show file tree
Hide file tree
Showing 13 changed files with 69 additions and 19 deletions.
1 change: 1 addition & 0 deletions .mailmap
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,4 @@ Jarryd Tilbrook <[email protected]>
Matthieu Melquiond <[email protected]>
Geoffroy Youri Berret <[email protected]>
Hugo van Kemenade <[email protected]>
Tobias Girstmair <[email protected]>
2 changes: 2 additions & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -118,3 +118,5 @@
- Simon <[email protected]>
- Vivien Henry <[email protected]>
- Hugo van Kemenade <[email protected]>
- Tobias Girstmair <[email protected]>
- Jakub Fijałkowski <[email protected]>
2 changes: 1 addition & 1 deletion docs/authors.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
Authors
*******

Mopidy is copyright 2009-2019 Stein Magnus Jodal and contributors. Mopidy is
Mopidy is copyright 2009-2020 Stein Magnus Jodal and contributors. Mopidy is
licensed under the `Apache License, Version 2.0
<http://www.apache.org/licenses/LICENSE-2.0>`_.

Expand Down
21 changes: 21 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,27 @@ This changelog is used to track all major changes to Mopidy.
For older releases, see :ref:`history`.


v3.0.2 (2020-04-02)
===================

Bugfix release.

- Core: Reset stream title on receipt of any ``title`` audio tag change.
Fixes: :issue:`1871`, PR: :issue:`1875`)

- Core: Hide the methods :meth:`~mopidy.core.Core.setup` and
:meth:`~mopidy.core.Core.teardown` from other actors and JSON-RPC API
clients. The methods have always been clearly documented as internal. (PR:
:issue:`1865`)

- Config: Log a warning if unknown config sections are found. (Fixes:
:issue:`1878`, PR: :issue:`1890`)

- Config: Fix crash when reading values from keyring. (PR: :issue:`1887`)

- Various documentation updates.


v3.0.1 (2019-12-22)
===================

Expand Down
4 changes: 2 additions & 2 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,14 +79,14 @@ def setup(app):
master_doc = "index"

project = "Mopidy"
copyright = "2009-2019, Stein Magnus Jodal and contributors"
copyright = "2009-2020, Stein Magnus Jodal and contributors"


release = get_version()
version = ".".join(release.split(".")[:2])

# To make the build reproducible, avoid using today's date in the manpages
today = "2019"
today = "2020"

exclude_trees = ["_build"]

Expand Down
9 changes: 6 additions & 3 deletions mopidy/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import sys

import pykka
from pykka.messages import ProxyCall

from mopidy import config as config_lib
from mopidy import exceptions
Expand Down Expand Up @@ -344,7 +345,7 @@ def on_sigterm(loop):
if mixer_class is not None:
self.stop_mixer(mixer_class)
process.stop_remaining_actors()
return exit_status_code
return exit_status_code

def get_mixer_class(self, config, mixer_classes):
logger.debug(
Expand Down Expand Up @@ -421,7 +422,8 @@ def start_core(self, config, mixer, backends, audio):
core = Core.start(
config=config, mixer=mixer, backends=backends, audio=audio
).proxy()
core.setup().get()
call = ProxyCall(attr_path=["_setup"], args=[], kwargs={})
core.actor_ref.ask(call, block=True)
return core

def start_frontends(self, config, frontend_classes, core):
Expand All @@ -443,7 +445,8 @@ def stop_frontends(self, frontend_classes):
def stop_core(self, core):
logger.info("Stopping Mopidy core")
if core:
core.teardown().get()
call = ProxyCall(attr_path=["_teardown"], args=[], kwargs={})
core.actor_ref.ask(call, block=True)
process.stop_actors_by_class(Core)

def stop_backends(self, backend_classes):
Expand Down
5 changes: 4 additions & 1 deletion mopidy/config/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,10 @@ def _validate(raw_config, schemas):
config[schema.name] = result

for section in sections:
logger.debug(f"Ignoring unknown config section: {section}")
logger.warning(
f"Ignoring config section {section!r} "
f"because no matching extension was found"
)

return config, errors

Expand Down
2 changes: 1 addition & 1 deletion mopidy/config/keyring.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ def _prompt(bus, path):
def _item_attributes(bus, path):
item = _interface(bus, path, "org.freedesktop.DBus.Properties")
result = item.Get("org.freedesktop.Secret.Item", "Attributes")
return {bytes(k): bytes(v) for k, v in result.items()}
return {str(k): str(v) for k, v in result.items()}


def _interface(bus, path, interface):
Expand Down
10 changes: 5 additions & 5 deletions mopidy/core/actor.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,17 +125,17 @@ def tags_changed(self, tags):
if not tags:
return

# TODO: this is a hack to make sure we don't emit stream title changes
# for plain tracks. We need a better way to decide if something is a
# stream.
self.playback._stream_title = None
# TODO: Do not emit stream title changes for plain tracks. We need a
# better way to decide if something is a stream.
if "title" in tags and tags["title"]:
title = tags["title"][0]
current_track = self.playback.get_current_track()
if current_track is not None and current_track.name != title:
self.playback._stream_title = title
CoreListener.send("stream_title_changed", title=title)

def setup(self):
def _setup(self):
"""Do not call this function. It is for internal use at startup."""
try:
coverage = []
Expand All @@ -153,7 +153,7 @@ def setup(self):
except Exception as e:
logger.warn("Restore state: Unexpected error: %s", str(e))

def teardown(self):
def _teardown(self):
"""Do not call this function. It is for internal use at shutdown."""
try:
if self._config and "restore_state" in self._config["core"]:
Expand Down
2 changes: 1 addition & 1 deletion mopidy/internal/gi.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
number of dependencies itself, and cannot be installed with the regular
Python tools like pip.
Please see http://docs.mopidy.com/en/latest/installation/ for
Please see https://docs.mopidy.com/en/latest/installation/ for
instructions on how to install the required dependencies.
"""
)
Expand Down
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[metadata]
name = Mopidy
version = 3.0.1
version = 3.0.2
url = https://mopidy.com/
project_urls =
Documentation = https://docs.mopidy.com/
Expand Down
8 changes: 4 additions & 4 deletions tests/core/test_actor.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ def tearDown(self): # noqa: N802
shutil.rmtree(self.temp_dir)

def test_save_state(self):
self.core.teardown()
self.core._teardown()

assert self.state_file.is_file()
reload_data = storage.load(self.state_file)
Expand All @@ -107,7 +107,7 @@ def test_save_state(self):
assert data == reload_data

def test_load_state_no_file(self):
self.core.setup()
self.core._setup()

assert self.core.mixer.get_mute() is None
assert self.core.mixer.get_volume() is None
Expand Down Expand Up @@ -152,7 +152,7 @@ def test_load_state_with_data(self):
)
storage.dump(self.state_file, data)

self.core.setup()
self.core._setup()

assert self.core.mixer.get_mute() is True
assert self.core.mixer.get_volume() == 12
Expand All @@ -171,6 +171,6 @@ def test_delete_state_file_on_restore(self):
storage.dump(self.state_file, data)
assert self.state_file.is_file()

self.core.setup()
self.core._setup()

assert not self.state_file.exists()
20 changes: 20 additions & 0 deletions tests/core/test_playback.py
Original file line number Diff line number Diff line change
Expand Up @@ -1009,6 +1009,26 @@ def test_get_stream_title_after_stop(self):
assert self.playback.get_stream_title() is None


class TestBug1871Regression(BaseTest):
def test(self):
track = Track(uri="dummy:d", length=1234, name="baz")
with deprecation.ignore():
self.core.tracklist.add(tracks=[track], at_position=1)

self.core.playback.play()
self.replay_events()

self.trigger_about_to_finish(replay_until="stream_changed")
self.audio.trigger_fake_tags_changed({"title": ["foo"]}).get()
self.replay_events()

self.audio.trigger_fake_tags_changed({"title": ["baz"]}).get()
self.replay_events()

assert self.playback.get_current_track().uri == "dummy:d"
assert self.playback.get_stream_title() is None


class TestBackendSelection:
def setup_method(self, method):
config = {"core": {"max_tracklist_length": 10000}}
Expand Down

0 comments on commit 49508ee

Please sign in to comment.