anon-iclr-submission/benchname-bug-localization huggingface dataset:
Repository: mopidy/mopidy
Issue: Hidden directory not skipped when at top level

When building a local library with `mopidy local scan`, hidden directories are being skipped, but only if they are in a subdirectory of the `media_dir`. If they are directly in the `media_dir`, they are scanned.

I believe the offending code is in class `ScanCommand#121`, which checks for `/.` in the relative path.


Changed files:
mopidy/local/commands.py

diff --git a/mopidy/local/commands.py b/mopidy/local/commands.py
index ead874a0..862d1d0b 100644
--- a/mopidy/local/commands.py
+++ b/mopidy/local/commands.py
@@ -118,7 +118,7 @@ class ScanCommand(commands.Command):
             relpath = os.path.relpath(abspath, media_dir)
             uri = translator.path_to_local_track_uri(relpath)
 
-            if b'/.' in relpath:
+            if b'/.' in relpath or relpath.startswith(b'.'):
                 logger.debug('Skipped %s: Hidden directory/file.', uri)
             elif relpath.lower().endswith(excluded_file_extensions):
                 logger.debug('Skipped %s: File extension excluded.', uri)
Repository: mopidy/mopidy
Issue: Position freezes after seek in FLAC via HTTP

Mopidy 2.0 9c05cc8d0581a5b4edfdf9ce069c8b358701c4d7. To reproduce:
- play FLAC audio from UPnP server (or internet)
- seek
- -> position freezes

Problem: core.PlaybackController._on_position_changed is called with 0 instead of the expected position 171150, so seek never finishes. 

https://github.com/mopidy/mopidy/blob/develop/mopidy/core/playback.py#L233

```
INFO     seek pending_pos=171150
INFO     Audio event: position_changed(position=0L)
INFO     _on_position_changed pos=0 pen_pos=171150
```


Changed files:
tests/core/test_playback.py, mopidy/core/playback.py

diff --git a/mopidy/core/playback.py b/mopidy/core/playback.py
index ab96171e..da505b22 100644
--- a/mopidy/core/playback.py
+++ b/mopidy/core/playback.py
@@ -230,8 +230,8 @@ class PlaybackController(object):
                 self._seek(self._pending_position)
 
     def _on_position_changed(self, position):
-        if self._pending_position == position:
-            self._trigger_seeked(position)
+        if self._pending_position is not None:
+            self._trigger_seeked(self._pending_position)
             self._pending_position = None
 
     def _on_about_to_finish_callback(self):
diff --git a/tests/core/test_playback.py b/tests/core/test_playback.py
index 3572800c..34c9d367 100644
--- a/tests/core/test_playback.py
+++ b/tests/core/test_playback.py
@@ -734,6 +734,7 @@ class EventEmissionTest(BaseTest):
 
         self.core.playback.play(tl_tracks[0])
         self.trigger_about_to_finish(replay_until='stream_changed')
+        self.replay_events()
         listener_mock.reset_mock()
 
         self.core.playback.seek(1000)
Repository: mopidy/mopidy
Issue: ValueError from bad audio tags

audio/tags.py:

> def convert_taglist(taglist):
> ...
> date = datetime.date(
>                     value.get_year(), value.get_month(), value.get_day())

This raises a ValueError that is not catched when audio track has badly set year. 
I suggest that if the year exceeds datetime.MAXYEAR then use datetime.MAXYEAR or 0 as the audio itself is probably not broken.


Changed files:
tests/audio/test_tags.py, mopidy/audio/tags.py

diff --git a/mopidy/audio/tags.py b/mopidy/audio/tags.py
index 5ae86468..7fabefd6 100644
--- a/mopidy/audio/tags.py
+++ b/mopidy/audio/tags.py
@@ -44,10 +44,15 @@ gstreamer-GstTagList.html
             value = taglist.get_value_index(tag, i)
 
             if isinstance(value, GLib.Date):
-                date = datetime.date(
-                    value.get_year(), value.get_month(), value.get_day())
-                result[tag].append(date.isoformat().decode('utf-8'))
-            if isinstance(value, Gst.DateTime):
+                try:
+                    date = datetime.date(
+                        value.get_year(), value.get_month(), value.get_day())
+                    result[tag].append(date.isoformat().decode('utf-8'))
+                except ValueError:
+                    logger.debug(
+                        'Ignoring dodgy date value: %d-%d-%d',
+                        value.get_year(), value.get_month(), value.get_day())
+            elif isinstance(value, Gst.DateTime):
                 result[tag].append(value.to_iso8601_string().decode('utf-8'))
             elif isinstance(value, bytes):
                 result[tag].append(value.decode('utf-8', 'replace'))
diff --git a/tests/audio/test_tags.py b/tests/audio/test_tags.py
index 01475124..d85bcc12 100644
--- a/tests/audio/test_tags.py
+++ b/tests/audio/test_tags.py
@@ -44,6 +44,14 @@ class TestConvertTaglist(object):
         assert isinstance(result[Gst.TAG_DATE][0], compat.text_type)
         assert result[Gst.TAG_DATE][0] == '2014-01-07'
 
+    def test_date_tag_bad_value(self):
+        date = GLib.Date.new_dmy(7, 1, 10000)
+        taglist = self.make_taglist(Gst.TAG_DATE, [date])
+
+        result = tags.convert_taglist(taglist)
+
+        assert len(result[Gst.TAG_DATE]) == 0
+
     def test_date_time_tag(self):
         taglist = self.make_taglist(Gst.TAG_DATE_TIME, [
             Gst.DateTime.new_from_iso8601_string(b'2014-01-07 14:13:12')
Repository: mopidy/mopidy
Issue: MPD: Stream Name/Title are reversed compared to mpd 0.19

Compare these two outputs:

Mopidy:

```
currentsong
file: http://xstream1.somafm.com:3000
Time: 0
Artist: 
Title: Groove Salad [SomaFM]
Album: 
Name: Org Lounge - Oslo
Track: 0
Pos: 0
Id: 11
Genre: Techno Ambient
OK
```

MPD:

```
OK MPD 0.19.0
currentsong
file: http://xstream1.somafm.com:3000
Title: Org Lounge - Oslo
Name: Groove Salad [SomaFM]
Pos: 0
Id: 2
OK
```

I know the empty fields have their own issue raised, but this is about the 'Title' and 'Name' fields being 'reversed'. MPD uses 'Name' to present the radio station's ID as returned in its Metadata, and changes 'Title' whenever the track metadata changes. Mopidy appears to do the reverse.

I had a quick look in the code but I have a feeling this is something that goes a lot deeper than just switching the output around in the mpd frontend.


Changed files:
mopidy/mpd/translator.py

diff --git a/mopidy/mpd/translator.py b/mopidy/mpd/translator.py
index 025ccdc9..04abc682 100644
--- a/mopidy/mpd/translator.py
+++ b/mopidy/mpd/translator.py
@@ -38,12 +38,15 @@ def track_to_mpd_format(track, position=None, stream_title=None):
         # https://github.com/mopidy/mopidy/issues/923#issuecomment-79584110
         ('Time', track.length and (track.length // 1000) or 0),
         ('Artist', concat_multi_values(track.artists, 'name')),
-        ('Title', track.name or ''),
         ('Album', track.album and track.album.name or ''),
     ]
 
-    if stream_title:
-        result.append(('Name', stream_title))
+    if stream_title is not None:
+        result.append(('Title', stream_title))
+        if track.name:
+            result.append(('Name', track.name))
+    else:
+        result.append(('Title', track.name or ''))
 
     if track.date:
         result.append(('Date', track.date))
Repository: mopidy/mopidy
Issue: Gst.NotInitialized exception on startup

When starting mopidy built from git develop branch, starting mopidy failed with `gi.overrides.Gst.NotInitialized: Please call Gst.init(argv) before using GStreamer`. It seems the call to `Gst.is_initialized()` before `Gst.init()` in `mopidy/internal/gi.py` is causing it. When I changed it to call `Gst.init([])` without checking if it's already initialized, the problem went away. `Gst.init()` also needed an argv-array as argument in my version, so I also passed an empty list as argument. Don't know if these changes are compatible with earlier versions of gst-python.

I'm on Archlinux, running gstreamer 1.6.3 and gst-python 1.6.2.

<!---
@huboard:{"custom_state":"archived"}
-->


Changed files:
mopidy/internal/gi.py

diff --git a/mopidy/internal/gi.py b/mopidy/internal/gi.py
index 1407a657..7fa51f09 100644
--- a/mopidy/internal/gi.py
+++ b/mopidy/internal/gi.py
@@ -7,8 +7,7 @@ import textwrap
 try:
     import gi
     gi.require_version('Gst', '1.0')
-    gi.require_version('GstPbutils', '1.0')
-    from gi.repository import GLib, GObject, Gst, GstPbutils
+    from gi.repository import GLib, GObject, Gst
 except ImportError:
     print(textwrap.dedent("""
         ERROR: A GObject Python package was not found.
@@ -22,7 +21,9 @@ except ImportError:
     """))
     raise
 else:
-    Gst.is_initialized() or Gst.init()
+    Gst.init([])
+    gi.require_version('GstPbutils', '1.0')
+    from gi.repository import GstPbutils
 
 
 REQUIRED_GST_VERSION = (1, 2, 3)
Repository: mopidy/mopidy
Issue: .local/share/mopidy is empty

I'm using Arch Linux and installed Mopidy using pacman.

When trying to scan for my local library I encountered the issue that the file or directory `~/.local/share/mopidy/local/library.json.gz` isn't there.

Simply creating the folder `~/.local/share/mopidy/local` made the scan work.


Changed files:
mopidy/local/json.py

diff --git a/mopidy/local/json.py b/mopidy/local/json.py
index 10611f6f..8f4ec5c0 100644
--- a/mopidy/local/json.py
+++ b/mopidy/local/json.py
@@ -31,6 +31,9 @@ def write_library(json_file, data):
     data['version'] = mopidy.__version__
     directory, basename = os.path.split(json_file)
 
+    if not os.path.exists(directory):
+        os.makedirs(directory)
+
     # TODO: cleanup directory/basename.* files.
     tmp = tempfile.NamedTemporaryFile(
         prefix=basename + '.', dir=directory, delete=False)
Repository: mopidy/mopidy
Issue: Backend with multiple URI schemes shows up multiple times when browsing

Given a `Backend` that supports multiple `uri_schemes` (such as the `local` backend), and also supports browsing, i.e. has a library that sets `root_directory` and implements `browse()`, the backend library's `root_directory` will show up multiple times (once for each URI scheme) when running `mpc ls`.  This is only an issue in the _root_ directory, which is (I think) served by Mopidy core. Browsing subdirectories _within_ the backend, where the backend's `browse()` method gets actually called, works fine.

AFAICS, the code for serving the root is in `mopidy.core.LibraryController.browse()`:

``` python
    if uri is None:
        backends = self.backends.with_library_browse.values()
        return [b.library.root_directory.get() for b in backends]
```

IMHO only unique `root_directory`s should be returned here, and not a copy for each URI scheme a backend supports.


Changed files:
mopidy/core/library.py, tests/core/test_library.py

diff --git a/mopidy/core/library.py b/mopidy/core/library.py
index 1ff4e874..903f25ae 100644
--- a/mopidy/core/library.py
+++ b/mopidy/core/library.py
@@ -62,7 +62,8 @@ class LibraryController(object):
         """
         if uri is None:
             backends = self.backends.with_library_browse.values()
-            return [b.library.root_directory.get() for b in backends]
+            root = [b.library.root_directory.get() for b in backends]
+            return list(collections.OrderedDict.fromkeys(root))
 
         scheme = urlparse.urlparse(uri).scheme
         backend = self.backends.with_library_browse.get(scheme)
diff --git a/tests/core/test_library.py b/tests/core/test_library.py
index a1daa0bd..1db22688 100644
--- a/tests/core/test_library.py
+++ b/tests/core/test_library.py
@@ -19,7 +19,7 @@ class CoreLibraryTest(unittest.TestCase):
 
         dummy2_root = Ref.directory(uri='dummy2:directory', name='dummy2')
         self.backend2 = mock.Mock()
-        self.backend2.uri_schemes.get.return_value = ['dummy2']
+        self.backend2.uri_schemes.get.return_value = ['dummy2', 'du2']
         self.library2 = mock.Mock(spec=backend.LibraryProvider)
         self.library2.root_directory.get.return_value = dummy2_root
         self.backend2.library = self.library2
@@ -138,7 +138,7 @@ class CoreLibraryTest(unittest.TestCase):
         self.core.library.refresh()
 
         self.library1.refresh.assert_called_once_with(None)
-        self.library2.refresh.assert_called_once_with(None)
+        self.library2.refresh.assert_called_twice_with(None)
 
     def test_find_exact_combines_results_from_all_backends(self):
         track1 = Track(uri='dummy1:a')
Repository: mopidy/mopidy
Issue: http/hostname set as :: does not work

I have the following config:

``` [mpd]
hostname = ::

[local]
enabled = true
media_dir = /media/equinox-music/
playlists_dir = /home/lasse/Music/playlists
tag_cache_file = /home/lasse/.config/mopidy/tag_cache

[http]
enabled = true
#hostname = 0.0.0.0
hostname = ::
port = 6680
static_dir = /home/lasse/dev/mopidy
```

When I start mopidy with this, I get:

```
INFO     2014-06-27 16:43:41,945 [8860:MainThread] mopidy.commands
  Starting Mopidy frontends: HttpFrontend, MpdFrontend
DEBUG    2014-06-27 16:43:41,946 [8860:Thread-9] mopidy.http.actor
  Starting HTTP server
DEBUG    2014-06-27 16:43:41,947 [8860:Thread-9] mopidy.http.actor
  Loaded HTTP extension: mopidy
INFO     2014-06-27 16:43:41,947 [8860:MainThread] mopidy.mpd.actor
  MPD server running at [::]:6600
DEBUG    2014-06-27 16:43:41,948 [8860:Thread-9] mopidy.http.actor
  Loaded HTTP extension: lux
DEBUG    2014-06-27 16:43:41,948 [8860:Thread-9] mopidy.http.actor
  Loaded static HTTP extension: lux
DEBUG    2014-06-27 16:43:41,948 [8860:Thread-9] mopidy.http.actor
  Loaded static HTTP extension: moped
DEBUG    2014-06-27 16:43:41,948 [8860:Thread-9] mopidy.http.actor
  HTTP routes from extensions: [(u'/mopidy', <class 'mopidy.http.handlers.AddSlashHandler'>), (u'/mopidy/ws/?', <class 'mopidy.http.handlers.WebSocketHandler'>), (u'/mopidy/rpc', <class 'mopidy.http.handlers.JsonRpcHandler'>), (u'/mopidy/(.+)', <class 'mopidy.http.handlers.StaticFileHandler'>), (u'/mopidy/', <class 'mopidy.http.handlers.ClientListHandler'>), (u'/lux', <class 'mopidy.http.handlers.AddSlashHandler'>), (u'/lux/lux/playlist', <class 'mopidy_lux.router.Playlists'>), (u'/lux/lux/loved', <class 'mopidy_lux.router.Loved'>), (u'/lux/lux/cover', <class 'mopidy_lux.router.CoverArt'>), (u'/lux', <class 'mopidy.http.handlers.AddSlashHandler'>), (u'/lux/(.*)', <class 'mopidy.http.handlers.StaticFileHandler'>), (u'/moped', <class 'mopidy.http.handlers.AddSlashHandler'>), (u'/moped/(.*)', <class 'mopidy.http.handlers.StaticFileHandler'>), (u'/(.*)', <class 'mopidy.http.handlers.StaticFileHandler'>)]
DEBUG    2014-06-27 16:43:41,956 [8860:MainThread] mopidy.listener
  Sending playlists_loaded to BackendListener: {}
INFO     2014-06-27 16:43:41,958 [8860:Thread-9] mopidy.http.actor
  HTTP server running at http://:::6680
```

As you can see, the MPD front-end binds correctly, but the HTTP one does not.


Changed files:
mopidy/http/actor.py

diff --git a/mopidy/http/actor.py b/mopidy/http/actor.py
index 5a11c3aa..af12c782 100644
--- a/mopidy/http/actor.py
+++ b/mopidy/http/actor.py
@@ -44,7 +44,8 @@ class HttpFrontend(pykka.ThreadingActor, CoreListener):
     def _startup(self):
         logger.debug('Starting HTTP server')
         self.app = tornado.web.Application(self._get_request_handlers())
-        self.app.listen(self.port, self.hostname)
+        self.app.listen(self.port,
+                        self.hostname if self.hostname != '::' else None)
         logger.info(
             'HTTP server running at http://%s:%s', self.hostname, self.port)
         tornado.ioloop.IOLoop.instance().start()
Repository: mopidy/mopidy
Issue: unable to open playlist containing quoted URIs

Hi there,

When trying to  open `http://bassdrive.com/v2/streams/BassDrive.pls`, mopidy fails with:

```
 GStreamer-CRITICAL **: 05:00:20.205: gst_element_make_from_uri: assertion 'gst_uri_is_valid (uri)' failed
WARNING  Download of '"http://bassdrive.radioca.st:80"' failed due to unsupported schema
INFO     Unwrapping stream from URI (http://bassdrive.com/v2/streams/BassDrive.pls) failed: error downloading URI "http://bassdrive.radioca.st:80"
WARNING  Track is not playable: http://bassdrive.com/v2/streams/BassDrive.pls
```
Looking at the content of  `http://bassdrive.com/v2/streams/BassDrive.pls` I can see that the FileX entries (the URIs) are quoted:
```
[playlist]
numberofentries=10
File1="http://bassdrive.radioca.st:80"
Title1="(#1) Bassdrive - Worldwide Drum and Bass Radio"
Length1=-1
...
```
I have tried the following hack and it seems to work for me, confirming that the issue is in the decoding:
```
diff --git a/mopidy/stream/actor.py b/mopidy/stream/actor.py
index 1bdd05ca..a4ab36b1 100644
--- a/mopidy/stream/actor.py
+++ b/mopidy/stream/actor.py
@@ -160,4 +160,4 @@ def _unwrap_stream(uri, timeout, scanner, requests_session):
         # TODO Test streams and return first that seems to be playable
         logger.debug(
             'Parsed playlist (%s) and found new URI: %s', uri, uris[0])
-        uri = uris[0]
+        uri = uris[0].strip('\\"')
```
Let me know if you want me to create a PR with this fix if it is deemed appropriate enough, and I'll try to add a test case.

Cheers,
Gildas

Changed files:
mopidy/internal/playlists.py, tests/internal/test_playlists.py

diff --git a/mopidy/internal/playlists.py b/mopidy/internal/playlists.py
index 5c7c8fc4..59c28d4b 100644
--- a/mopidy/internal/playlists.py
+++ b/mopidy/internal/playlists.py
@@ -84,7 +84,7 @@ def parse_pls(data):
         if section.lower() != 'playlist':
             continue
         for i in range(cp.getint(section, 'numberofentries')):
-            yield cp.get(section, 'file%d' % (i + 1))
+            yield cp.get(section, 'file%d' % (i + 1)).strip('\\"\\'')
 
 
 def parse_xspf(data):
diff --git a/tests/internal/test_playlists.py b/tests/internal/test_playlists.py
index 9a1c49d5..1abbf57c 100644
--- a/tests/internal/test_playlists.py
+++ b/tests/internal/test_playlists.py
@@ -31,11 +31,11 @@ file:///tmp/baz
 
 PLS = b"""[Playlist]
 NumberOfEntries=3
-File1=file:///tmp/foo
+File1="file:///tmp/foo"
 Title1=Sample Title
 Length1=123
 
-File2=file:///tmp/bar
+File2='file:///tmp/bar'
 Title2=Example \\xc5\\xa7\\xc5\\x95
 Length2=321
 File3=file:///tmp/baz
Repository: mopidy/mopidy
Issue: Get rid of gdk import warning.

When running mopidy in headless mode we keep getting a gdk import error that can safely be ignored. Ideally we should find a way to suppress this warning.


Changed files:
mopidy/frontends/mpris/actor.py, mopidy/frontends/mpris/__init__.py

diff --git a/mopidy/frontends/mpris/__init__.py b/mopidy/frontends/mpris/__init__.py
index 813e03a2..5be9c6cf 100644
--- a/mopidy/frontends/mpris/__init__.py
+++ b/mopidy/frontends/mpris/__init__.py
@@ -1,5 +1,7 @@
 from __future__ import unicode_literals
 
+import os
+
 import mopidy
 from mopidy import exceptions, ext
 from mopidy.utils import formatting, config
@@ -89,6 +91,10 @@ class Extension(ext.Extension):
         return schema
 
     def validate_environment(self):
+        if 'DISPLAY' not in os.environ:
+            raise exceptions.ExtensionError(
+                'An X11 $DISPLAY is needed to use D-Bus')
+
         try:
             import dbus  # noqa
         except ImportError as e:
diff --git a/mopidy/frontends/mpris/actor.py b/mopidy/frontends/mpris/actor.py
index 92805bd3..fae8618f 100644
--- a/mopidy/frontends/mpris/actor.py
+++ b/mopidy/frontends/mpris/actor.py
@@ -1,6 +1,7 @@
 from __future__ import unicode_literals
 
 import logging
+import os
 
 import pykka
 
@@ -10,10 +11,14 @@ from mopidy.frontends.mpris import objects
 logger = logging.getLogger('mopidy.frontends.mpris')
 
 try:
-    import indicate
-except ImportError as import_error:
-    indicate = None  # noqa
-    logger.debug('Startup notification will not be sent (%s)', import_error)
+    indicate = None
+    if 'DISPLAY' in os.environ:
+        import indicate
+except ImportError:
+    pass
+
+if indicate is None:
+    logger.debug('Startup notification will not be sent')
 
 
 class MprisFrontend(pykka.ThreadingActor, CoreListener):