internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: beetbox/beets

Issue:
Only show files that are really moved when using the 'move' command
The `beet move` command is showing _ALL_ files in my collection when using the `--pretend` flag, even if the path is the same before and after the `move` operation. Wouldn't it be better to show only the files that are actually moved?



Discussion:
Sure, sounds great.

There you go then ;)

I just came here to report this behavior as well, seeing _all_ the files is definitely not what I expected and makes the command a lot scarier for me than it should be. I looked at the PR for this and I'm not quite sure if there is still anything left to do before it can be merged. I'd be happy to help out if someone pointed me in the right direction regarding failing tests e.g.

The main outstanding issue in #1584 is the need to handle album mode (`beet move -a`). Then we just need some updates to the docs! Thanks being willing to help.

I checked out the source, not quite figured out how to actually test my changes, though, as it seems running the beet executable from the main directory doesn't work. Haven't worked on any sophisticated Python apps yet. However, as far as I saw from the current master, I think this change should rather be applied inside the show_path_changes method in https://github.com/sampsyo/beets/blob/092472d750fb3d936803be6dacb7ffe09173ade2/beets/ui/__init__.py#L638-L674 – comparing source and destination and hiding output in case they are equal should easily cover items and albums alike. @fxthomas, maybe you could try and add that change and PR again? You're probably quicker than me figuring out how to properly develop on the project. :)

Great! You may be interested in the hacking wiki page: https://github.com/sampsyo/beets/wiki/Hacking

In particular, the advice about `pip install -e` will give you a `beet` executable that responds to your changes.


Resolving patch:
diff --git a/beets/ui/commands.py b/beets/ui/commands.py
--- a/beets/ui/commands.py
+++ b/beets/ui/commands.py
@@ -1427,11 +1427,16 @@ def move_items(lib, dest, query, copy, album, pretend):
     """
     items, albums = _do_query(lib, query, album, False)
     objs = albums if album else items
+    isitemmoved = lambda item: item.path != item.destination(basedir=dest)
+    isalbummoved = lambda album: any(isitemmoved(i) for i in album.items())
+    objs = [o for o in objs if (isalbummoved if album else isitemmoved)(o)]
 
     action = 'Copying' if copy else 'Moving'
     entity = 'album' if album else 'item'
     log.info(u'{0} {1} {2}{3}.', action, len(objs), entity,
-             's' if len(objs) > 1 else '')
+             's' if len(objs) != 1 else '')
+    if len(objs) == 0:
+        return
     if pretend:
         if album:
             show_path_changes([(item.path, item.destination(basedir=dest))


Test patch:
Repository: beetbox/beets

Issue:
plexupdate plugin crashed
Every time after import plexupdate plugin crashed with this error:

```
Traceback (most recent call last):
  File "/usr/local/bin/beet", line 9, in <module>
    load_entry_point('beets==1.3.15', 'console_scripts', 'beet')()
  File "/usr/local/lib/python2.7/dist-packages/beets/ui/__init__.py", line 1163, in main
    _raw_main(args)
  File "/usr/local/lib/python2.7/dist-packages/beets/ui/__init__.py", line 1155, in _raw_main
    plugins.send('cli_exit', lib=lib)
  File "/usr/local/lib/python2.7/dist-packages/beets/plugins.py", line 458, in send
    result = handler(**arguments)
  File "/usr/local/lib/python2.7/dist-packages/beets/plugins.py", line 123, in wrapper
    return func(*args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/beetsplug/plexupdate.py", line 87, in update
    config['plex']['library_name'].get())
  File "/usr/local/lib/python2.7/dist-packages/beetsplug/plexupdate.py", line 41, in update_plex
    section_key = get_music_section(host, port, token, library_name)
  File "/usr/local/lib/python2.7/dist-packages/beetsplug/plexupdate.py", line 31, in get_music_section
    tree = ET.fromstring(r.raw)
  File "/usr/lib/python2.7/xml/etree/ElementTree.py", line 1300, in XML
    parser.feed(text)
  File "/usr/lib/python2.7/xml/etree/ElementTree.py", line 1640, in feed
    self._parser.Parse(data, 0)
TypeError: must be string or read-only buffer, not HTTPResponse
```



Discussion:

Resolving patch:
diff --git a/beetsplug/plexupdate.py b/beetsplug/plexupdate.py
--- a/beetsplug/plexupdate.py
+++ b/beetsplug/plexupdate.py
@@ -28,7 +28,7 @@ def get_music_section(host, port, token, library_name):
     r = requests.get(url)
 
     # Parse xml tree and extract music section key.
-    tree = ET.fromstring(r.text)
+    tree = ET.fromstring(r.content)
     for child in tree.findall('Directory'):
         if child.get('title') == library_name:
             return child.get('key')


Test patch:
Repository: beetbox/beets

Issue:
EmbedArt Plugin: remove_art_file doesn't seem to work
I'm running beets version 1.15. The EmbedArt plugin isn't removing the art file from the file system. 
Logfile: http://pastebin.com/n10bbdpS
Config: http://pastebin.com/ztrjd16C



Discussion:
+1

Config: http://pastebin.com/bqTDtUg6
Exemplary Log (via `beet -vv import`): http://pastebin.com/DxGabj0C

have you tried with maxwidth commented out?  I know there was a time embedart was failing for me because I didnt install imagemagik or pils, not sure if it relates though

Thanks for the reports! It looks like @jackwilsdon only added the functionality for an explicit `beet embedart` command in #1591. Also covering the automatic import hook would be a good idea.


Resolving patch:
diff --git a/beetsplug/embedart.py b/beetsplug/embedart.py
--- a/beetsplug/embedart.py
+++ b/beetsplug/embedart.py
@@ -79,14 +79,7 @@ def embed_func(lib, opts, args):
                 for album in lib.albums(decargs(args)):
                     art.embed_album(self._log, album, maxwidth, False,
                                     compare_threshold, ifempty)
-
-                    if remove_art_file and album.artpath is not None:
-                        if os.path.isfile(album.artpath):
-                            self._log.debug(u'Removing album art file '
-                                            u'for {0}', album)
-                            os.remove(album.artpath)
-                            album.artpath = None
-                            album.store()
+                    self.remove_artfile(album)
 
         embed_cmd.func = embed_func
 
@@ -141,3 +134,12 @@ def process_album(self, album):
             art.embed_album(self._log, album, max_width, True,
                             self.config['compare_threshold'].get(int),
                             self.config['ifempty'].get(bool))
+            self.remove_artfile(album)
+    def remove_artfile(self, album)
+        if self.config['remove_art_file'] and album.artpath:
+            if os.path.isfile(album.artpath):
+                self._log.debug(u'Removing album art file '
+                                u'for {0}', album)
+                os.remove(album.artpath)
+                album.artpath = None
+                album.store()


Test patch:
Repository: beetbox/beets

Issue:
hook: Crash when using non-ASCII paths in command template
Using the config

```
hook:
  hooks:
    - event: album_imported
      command: beet convert -ay path:{album.path}
```

and this command

```
beet import -a -L path:/path/to/lib/Ария
```

I get an UnicodeDecodeError from `hook.py` line 50.



Discussion:

Resolving patch:
diff --git a/beetsplug/hook.py b/beetsplug/hook.py
--- a/beetsplug/hook.py
+++ b/beetsplug/hook.py
@@ -47,7 +47,9 @@ def hook_function(**kwargs):
                     self._log.error('invalid command "{0}"', command)
                     return
 
-                formatted_command = command.format(event=event, **kwargs)
+                unicode_command = command.decode('utf-8')
+                formatted_command = unicode_command.format(event=event,
+                                                           **kwargs)
                 encoded_command = formatted_command.decode(_arg_encoding())
                 command_pieces = shlex.split(encoded_command)
 


Test patch:
Repository: beetbox/beets

Issue:
bs1770gain uses wrong parameters
Applying replaygain with bs1770gain uses the parameter `-it` which means get integrated loudness and calculate true peak.

Specifying -i is just superfluous because that's the default anyway and -t is wrong for two reasons:
1. Replaygain specifies sample peak, not any other fancy peak calculation methods
2. Calculating true peak is _horrrrribly_ slow, the whole process is like 10x slower with this

Solution: invoke bs1770gain with parameter -p instead to calculate the correct peak gain and get a major speed boost as a bonus.



Discussion:

Resolving patch:
diff --git a/beetsplug/replaygain.py b/beetsplug/replaygain.py
--- a/beetsplug/replaygain.py
+++ b/beetsplug/replaygain.py
@@ -195,7 +195,7 @@ def compute_chunk_gain(self, items, is_album):
         # Construct shell command.
         cmd = [self.command]
         cmd = cmd + [self.method]
-        cmd = cmd + [b'-it']
+        cmd = cmd + [b'-p']
 
         # Workaround for Windows: the underlying tool fails on paths
         # with the \\?\ prefix, so we don't use it here. This


Test patch:
Repository: beetbox/beets

Issue:
beetsplug/fromfilename.py python3 compatability
https://github.com/beetbox/beets/blob/e8afcbe7ec4bc37bb080f6f466b98807d020753b/beetsplug/fromfilename.py#L104

python2

``` python2
d.values()
```

for python 3 this should be

``` python3
list(d.values())
```



Discussion:

Resolving patch:
diff --git a/beetsplug/fromfilename.py b/beetsplug/fromfilename.py
--- a/beetsplug/fromfilename.py
+++ b/beetsplug/fromfilename.py
@@ -101,7 +101,7 @@ def apply_matches(d):
     """Given a mapping from items to field dicts, apply the fields to
     the objects.
     """
-    some_map = d.values()[0]
+    some_map = list(d.values())[0]
     keys = some_map.keys()
 
     # Only proceed if the "tag" field is equal across all filenames.


Test patch:
Repository: beetbox/beets

Issue:
Import of a multidisc release is broken if it has subdirectories
### Problem

I have a directory structure like:
```
/music/artist/album/CD1/*.mp3
/music/artist/album/CD1/info/*.txt
/music/artist/album/CD1/covers/*.jpg
/music/artist/album/CD2/*.mp3
/music/artist/album/CD2/info/*.txt
/music/artist/album/CD2/covers/*.jpg
/music/artist/album/CD3/*.mp3
/music/artist/album/CD3/info/*.txt
/music/artist/album/CD3/covers/*.jpg
```

When importing such a directory structure with beets, the importer doesn't 
collapse the paths since it has subdirectories that "break" the pattern matching.
All the contents of CD1/CD2/CD3 directories should be colllapsed into the same release, as [the documentation says](http://beets.readthedocs.io/en/v1.3.17/guides/tagger.html#overview) :

```
First, directories that look like separate parts of a multi-disc album are tagged
together as a single release. If two adjacent albums have a common prefix,
followed by “disc,” “disk,” or “CD” and then a number, they are tagged together.
```

### Setup

* OS:  openSUSE Tumbleweed
* Python version: 3.6
* beets version: git master



Discussion:

Resolving patch:
diff --git a/beets/importer.py b/beets/importer.py
--- a/beets/importer.py
+++ b/beets/importer.py
@@ -1469,6 +1469,14 @@ def group(item):
 MULTIDISC_PAT_FMT = br'^(.*%s[\W_]*)\d'
 
 
+def is_subdir_of_any_in_list(path, dirs):
+    """Returns True if path os a subdirectory of any directory in dirs
+    (a list). In other case, returns False.
+    """
+    ancestors = ancestry(path)
+    return any(d in ancestors for d in dirs)
+
+
 def albums_in_dir(path):
     """Recursively searches the given directory and returns an iterable
     of (paths, items) where paths is a list of directories and items is
@@ -1488,7 +1496,7 @@ def albums_in_dir(path):
         # and add the current directory. If so, just add the directory
         # and move on to the next directory. If not, stop collapsing.
         if collapse_paths:
-            if (not collapse_pat and collapse_paths[0] in ancestry(root)) or \
+            if (is_subdir_of_any_in_list(root, collapse_paths)) or \
                     (collapse_pat and
                      collapse_pat.match(os.path.basename(root))):
                 # Still collapsing.


Test patch:
Repository: beetbox/beets

Issue:
Importer: option to play bell when interaction needed
It would be great if beets played a terminal bell by sending `\a` to `stdout` if the autotagger requires interaction from the user.


Discussion:
Sounds like a reasonable idea, and not too hard to accomplish! I'm marking this as a feature request.
Greetings, 
I am thinking about putting the print(\a) command in the commands.py file.

Resolving patch:
diff --git a/beets/ui/commands.py b/beets/ui/commands.py
--- a/beets/ui/commands.py
+++ b/beets/ui/commands.py
@@ -613,6 +613,9 @@ def choose_candidate(candidates, singleton, rec, cur_artist=None,
         })
         if default is None:
             require = True
+        # Bell ring when user interaction is needed.
+        if config['import']['bell']:
+            ui.print_('\a', end='')
         sel = ui.input_options((u'Apply', u'More candidates') + choice_opts,
                                require=require, default=default)
         if sel == u'a':


Test patch:
Repository: beetbox/beets

Issue:
lyrics: Detect when you get blocked by Musixmatch
### Problem

My IP seems to have been blocked by musixmatch. Some of the lyrics downloaded say:

```
We are human after all

Human After All
DAFT PUNK

We detected that your IP is blocked.
It looks like you’re a bot or more likely your network may have been blacklisted for some reason.
Please confirm you are a human by checking the box below.
```

It seems the problem is resolved now because I can't reproduce with a regular web browser. It would be nice, however, to detect such scenarios and not record the problematic lyrics. I am not sure how to do this - I don't know if a different status code gets sent, but maybe we can do a simple regex-based pattern-matching technique?

Thanks!


Discussion:
workaround: to reset the state of the database and clear those bad entries, use the following command:

```
sqlite3 ~/.config/beets/library.db "UPDATE items SET lyrics = '' WHERE lyrics LIKE '%We detected that your IP is blocked%';"
```

seems to me we should have a way to do throttling or something to workaround that block. FWIW, i was able to download about 20k titles before getting blocked.
Sure; sounds good. Just checking whether the string "We detected that your IP is blocked." is in the response should do it. Until someone writes a hit song about rate limiting… :smiley:
hehe... i also figured out this is just a CAPTCHA page you can fill in to get your free pass... so it's not as bad as a complete UA block, it seems.

Resolving patch:
diff --git a/beetsplug/lyrics.py b/beetsplug/lyrics.py
--- a/beetsplug/lyrics.py
+++ b/beetsplug/lyrics.py
@@ -301,9 +301,19 @@ def fetch(self, artist, title):
         html = self.fetch_url(url)
         if not html:
             return
+        if "We detected that your IP is blocked" in html:
+            self._log.warning(u'we are blocked at MusixMatch: url %s failed'
+                              % url)
+            return
         html_part = html.split('<p class="mxm-lyrics__content')[-1]
         lyrics = extract_text_between(html_part, '>', '</p>')
-        return lyrics.strip(',"').replace('\\n', '\n')
+        lyrics = lyrics.strip(',"').replace('\\n', '\n')
+        # another odd case: sometimes only that string remains, for
+        # missing songs. this seems to happen after being blocked
+        # above, when filling in the CAPTCHA.
+        if "Instant lyrics for all your music." in lyrics:
+            return
+        return lyrics
 
 
 class Genius(Backend):


Test patch:
Repository: beetbox/beets

Issue:
When importer is in incremental mode, offer an option to avoid recording the album
It would be useful to have a "[L]ater" plugin that allows to non-permanently skip an import in incremental mode, in order to be processed again in subsequent import runs. That would basically be the "[S]kip" functionality, minus storing the path.

Typical use case would be, in a large volume import, to skip the difficult cases for the time being and to re-visit these later.


Discussion:
Interesting idea! For what it's worth, this is only relevant in `incremental` mode. By default, we don't record (or automatically skip) any paths. I've updated the title to describe the idea in more detail.
@sampsyo Is this something that can be done with a plugin? Adding to the incremental list is done in the final stage of the pipeline, after all the plugin stages have passed.

I would also really like this feature, and I see three options for implementing it if I'm correct about not being able to do it with a plugin:

Option 1:

A config flag to bypass adding to the incremental list on `importer.action.SKIP`
All skip actions will not add to the incremental list.

Option 2:

Add a new prompt option [L]ater, only visible on incremental imports.
Continue using `importer.action.SKIP` for this option.
A special variable on `ImportTask` to indicate that a later prompt was chosen.
Conditionally skip `save_history()` on this special variable.

Option 3:

Add a new plugin action to skip all future pipeline stages for the current item.
A new Later plugin will use this to skip the `manipulate_files` stage.
Agreed; I don’t believe a plugin could do this currently.

Thanks for laying out these options! This is a good set of alternatives, and I always find it useful to map out the space of possible implementations ahead of time. :+1:

Here are some comments on each option:

1. This is the least obtrusive option, and it avoids bothering people who don’t need this feature with an extra prompt option. The only question is whether this is flexible enough—whether a “skip and record” action is ever useful in addition.
2. This is a more complex implementation, but it gets the behavior exactly as proposed.
3. This would be nice for future extensibility, but it runs the risk of unexpected consequences when aborting the pipeline early. For example, the “restartable” import feature wouldn’t get a chance to record progress.

Overall, I lean toward 1 if it doesn’t seem too limited, and probably 2 otherwise. Any opinions?
  

Resolving patch:
diff --git a/beets/importer.py b/beets/importer.py
--- a/beets/importer.py
+++ b/beets/importer.py
@@ -577,7 +577,8 @@ def finalize(self, session):
         # Update progress.
         if session.want_resume:
             self.save_progress()
-        if session.config['incremental']:
+        if (session.config['incremental'] and
+                not session.config['incremental_skip_later']):
             self.save_history()
 
         self.cleanup(copy=session.config['copy'],


Test patch:
Repository: beetbox/beets

Issue:
Lyrics plugin groups songs by 'artist' rather than 'albumartist'
### Problem

When you use the lyrics plugin to create rst files with the lyrics themselves, the resulting files are grouped by the items' `artist` field rather than `albumartist`, which would arguably be more reasonable. When an artist has many collaborations where for a song the two fields are different, it may lead to situations like this:

![image](https://user-images.githubusercontent.com/1352887/39959925-3f86ed96-562a-11e8-94d2-2b2b21285b5c.png)

after a three line change ([commit link](https://github.com/Abrackadabra/beets/commit/62d5fe3692f0e93663da6c87818578a7ccef8d7c)):

![image](https://user-images.githubusercontent.com/1352887/39959931-6a219286-562a-11e8-9e78-dc76f4a6f60e.png)

Let me know if you want me to create a push request with this.


Discussion:
Good point! Yes, this would be useful as a PR. (Especially if you include a changelog entry.) Thanks! :sparkles:

Resolving patch:
diff --git a/beetsplug/lyrics.py b/beetsplug/lyrics.py
--- a/beetsplug/lyrics.py
+++ b/beetsplug/lyrics.py
@@ -772,7 +772,7 @@ def writerest(self, directory, item):
         writing continuously to the same files.
         """
 
-        if item is None or slug(self.artist) != slug(item.artist):
+        if item is None or slug(self.artist) != slug(item.albumartist):
             if self.rest is not None:
                 path = os.path.join(directory, 'artists',
                                     slug(self.artist) + u'.rst')
@@ -781,7 +781,7 @@ def writerest(self, directory, item):
                 self.rest = None
                 if item is None:
                     return
-            self.artist = item.artist.strip()
+            self.artist = item.albumartist.strip()
             self.rest = u"%s\n%s\n\n.. contents::\n   :local:\n\n" \
                         % (self.artist,
                            u'=' * len(self.artist))


Test patch:
Repository: beetbox/beets

Issue:
%aunique fails when listing albums
### Problem

```
$ beet ls -a -f '$albumartist - $album%aunique{}'
Weezer - Make Believe<no such field 'album_id'>
Weezer - Maladroit<no such field 'album_id'>
Weezer - Pinkerton<no such field 'album_id'>
Weezer - Raditude<no such field 'album_id'>
Weezer - Weezer<no such field 'album_id'>
Weezer - Weezer<no such field 'album_id'>
Weezer - Weezer<no such field 'album_id'>
```

Looks like `aunique` assumes that it'll only ever handle `Item`s (albums don't have an `album_id` field).

This seems like a simple fix. I should have a pull request ready today or tomorrow.


Discussion:

Resolving patch:
diff --git a/beets/library.py b/beets/library.py
--- a/beets/library.py
+++ b/beets/library.py
@@ -1506,9 +1506,16 @@ def tmpl_aunique(self, keys=None, disam=None, bracket=None):
         # Fast paths: no album, no item or library, or memoized value.
         if not self.item or not self.lib:
             return u''
-        if self.item.album_id is None:
+
+        if isinstance(self.item, Item):
+            album_id = self.item.album_id
+        elif isinstance(self.item, Album):
+            album_id = self.item.id
+
+        if album_id is None:
             return u''
-        memokey = ('aunique', keys, disam, self.item.album_id)
+
+        memokey = ('aunique', keys, disam, album_id)
         memoval = self.lib._memotable.get(memokey)
         if memoval is not None:
             return memoval
@@ -1528,7 +1535,7 @@ def tmpl_aunique(self, keys=None, disam=None, bracket=None):
             bracket_l = u''
             bracket_r = u''
 
-        album = self.lib.get_album(self.item)
+        album = self.lib.get_album(album_id)
         if not album:
             # Do nothing for singletons.
             self.lib._memotable[memokey] = u''


Test patch: