We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
ftintitle: be less verbose during import
During an import, with the ftintitle enabled it seems to have very verbose output. This causes the user to not notice any prompts that beets has, and is somewhat annoying when doing a large import.

As seen here:
![Image of ftintitle spam](http://i.imgur.com/wd0rN0R.png)

My suggestion would be to add a configuration option that would make ftintitle be less verbose. Or, making it not be verbose by default and adding a verbosity configuration option.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `beetsplug/ftintitle.py`
Content:
```
1 # This file is part of beets.
2 # Copyright 2013, Verrus, <github.com/Verrus/beets-plugin-featInTitle>
3 #
4 # Permission is hereby granted, free of charge, to any person obtaining
5 # a copy of this software and associated documentation files (the
6 # "Software"), to deal in the Software without restriction, including
7 # without limitation the rights to use, copy, modify, merge, publish,
8 # distribute, sublicense, and/or sell copies of the Software, and to
9 # permit persons to whom the Software is furnished to do so, subject to
10 # the following conditions:
11 #
12 # The above copyright notice and this permission notice shall be
13 # included in all copies or substantial portions of the Software.
14 
15 """Moves "featured" artists to the title from the artist field.
16 """
17 from beets import plugins
18 from beets import ui
19 from beets.util import displayable_path
20 from beets import config
21 import logging
22 import re
23 
24 log = logging.getLogger('beets')
25 
26 
27 def split_on_feat(artist):
28     """Given an artist string, split the "main" artist from any artist
29     on the right-hand side of a string like "feat". Return the main
30     artist, which is always a string, and the featuring artist, which
31     may be a string or None if none is present.
32     """
33     # split on the first "feat".
34     regex = re.compile(plugins.feat_tokens(), re.IGNORECASE)
35     parts = [s.strip() for s in regex.split(artist, 1)]
36     if len(parts) == 1:
37         return parts[0], None
38     else:
39         return tuple(parts)
40 
41 
42 def contains_feat(title):
43     """Determine whether the title contains a "featured" marker.
44     """
45     return bool(re.search(plugins.feat_tokens(), title, flags=re.IGNORECASE))
46 
47 
48 def update_metadata(item, feat_part, drop_feat):
49     """Choose how to add new artists to the title and set the new
50     metadata. Also, print out messages about any changes that are made.
51     If `drop_feat` is set, then do not add the artist to the title; just
52     remove it from the artist field.
53     """
54     # In all cases, update the artist fields.
55     ui.print_(u'artist: {0} -> {1}'.format(item.artist, item.albumartist))
56     item.artist = item.albumartist
57     if item.artist_sort:
58         # Just strip the featured artist from the sort name.
59         item.artist_sort, _ = split_on_feat(item.artist_sort)
60 
61     # Only update the title if it does not already contain a featured
62     # artist and if we do not drop featuring information.
63     if not drop_feat and not contains_feat(item.title):
64         new_title = u"{0} feat. {1}".format(item.title, feat_part)
65         ui.print_(u'title: {0} -> {1}'.format(item.title, new_title))
66         item.title = new_title
67 
68 
69 def ft_in_title(item, drop_feat):
70     """Look for featured artists in the item's artist fields and move
71     them to the title.
72     """
73     artist = item.artist.strip()
74     albumartist = item.albumartist.strip()
75 
76     # Check whether there is a featured artist on this track and the
77     # artist field does not exactly match the album artist field. In
78     # that case, we attempt to move the featured artist to the title.
79     _, featured = split_on_feat(artist)
80     if featured and albumartist != artist and albumartist:
81         ui.print_(displayable_path(item.path))
82         feat_part = None
83 
84         # Look for the album artist in the artist field. If it's not
85         # present, give up.
86         albumartist_split = artist.split(albumartist)
87         if len(albumartist_split) <= 1:
88             ui.print_('album artist not present in artist')
89 
90         # If the last element of the split (the right-hand side of the
91         # album artist) is nonempty, then it probably contains the
92         # featured artist.
93         elif albumartist_split[-1] != '':
94             # Extract the featured artist from the right-hand side.
95             _, feat_part = split_on_feat(albumartist_split[-1])
96 
97         # Otherwise, if there's nothing on the right-hand side, look for a
98         # featuring artist on the left-hand side.
99         else:
100             lhs, rhs = split_on_feat(albumartist_split[0])
101             if rhs:
102                 feat_part = lhs
103 
104         # If we have a featuring artist, move it to the title.
105         if feat_part:
106             update_metadata(item, feat_part, drop_feat)
107         else:
108             ui.print_(u'no featuring artists found')
109 
110         ui.print_()
111 
112 
113 class FtInTitlePlugin(plugins.BeetsPlugin):
114     def __init__(self):
115         super(FtInTitlePlugin, self).__init__()
116 
117         self.config.add({
118             'auto': True,
119             'drop': False,
120         })
121 
122         self._command = ui.Subcommand(
123             'ftintitle',
124             help='move featured artists to the title field')
125 
126         self._command.parser.add_option(
127             '-d', '--drop', dest='drop',
128             action='store_true', default=False,
129             help='drop featuring from artists and ignore title update')
130 
131         if self.config['auto']:
132             self.import_stages = [self.imported]
133 
134     def commands(self):
135 
136         def func(lib, opts, args):
137             self.config.set_args(opts)
138             drop_feat = self.config['drop'].get(bool)
139             write = config['import']['write'].get(bool)
140 
141             for item in lib.items(ui.decargs(args)):
142                 ft_in_title(item, drop_feat)
143                 item.store()
144                 if write:
145                     item.try_write()
146 
147         self._command.func = func
148         return [self._command]
149 
150     def imported(self, session, task):
151         """Import hook for moving featuring artist automatically.
152         """
153         drop_feat = self.config['drop'].get(bool)
154 
155         for item in task.imported_items():
156             ft_in_title(item, drop_feat)
157             item.store()
158
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/beetsplug/ftintitle.py b/beetsplug/ftintitle.py
--- a/beetsplug/ftintitle.py
+++ b/beetsplug/ftintitle.py
@@ -45,14 +45,15 @@
     return bool(re.search(plugins.feat_tokens(), title, flags=re.IGNORECASE))
 
 
-def update_metadata(item, feat_part, drop_feat):
+def update_metadata(item, feat_part, drop_feat, loglevel=logging.DEBUG):
     """Choose how to add new artists to the title and set the new
     metadata. Also, print out messages about any changes that are made.
     If `drop_feat` is set, then do not add the artist to the title; just
     remove it from the artist field.
     """
     # In all cases, update the artist fields.
-    ui.print_(u'artist: {0} -> {1}'.format(item.artist, item.albumartist))
+    log.log(loglevel, u'artist: {0} -> {1}'.format(
+        item.artist, item.albumartist))
     item.artist = item.albumartist
     if item.artist_sort:
         # Just strip the featured artist from the sort name.
@@ -62,11 +63,11 @@
     # artist and if we do not drop featuring information.
     if not drop_feat and not contains_feat(item.title):
         new_title = u"{0} feat. {1}".format(item.title, feat_part)
-        ui.print_(u'title: {0} -> {1}'.format(item.title, new_title))
+        log.log(loglevel, u'title: {0} -> {1}'.format(item.title, new_title))
         item.title = new_title
 
 
-def ft_in_title(item, drop_feat):
+def ft_in_title(item, drop_feat, loglevel=logging.DEBUG):
     """Look for featured artists in the item's artist fields and move
     them to the title.
     """
@@ -78,14 +79,14 @@
     # that case, we attempt to move the featured artist to the title.
     _, featured = split_on_feat(artist)
     if featured and albumartist != artist and albumartist:
-        ui.print_(displayable_path(item.path))
+        log.log(loglevel, displayable_path(item.path))
         feat_part = None
 
         # Look for the album artist in the artist field. If it's not
         # present, give up.
         albumartist_split = artist.split(albumartist)
         if len(albumartist_split) <= 1:
-            ui.print_('album artist not present in artist')
+            log.log(loglevel, 'album artist not present in artist')
 
         # If the last element of the split (the right-hand side of the
         # album artist) is nonempty, then it probably contains the
@@ -103,11 +104,9 @@
 
         # If we have a featuring artist, move it to the title.
         if feat_part:
-            update_metadata(item, feat_part, drop_feat)
+            update_metadata(item, feat_part, drop_feat, loglevel)
         else:
-            ui.print_(u'no featuring artists found')
-
-        ui.print_()
+            log.log(loglevel, u'no featuring artists found')
 
 
 class FtInTitlePlugin(plugins.BeetsPlugin):
@@ -139,7 +138,7 @@
             write = config['import']['write'].get(bool)
 
             for item in lib.items(ui.decargs(args)):
-                ft_in_title(item, drop_feat)
+                ft_in_title(item, drop_feat, logging.INFO)
                 item.store()
                 if write:
                     item.try_write()
@@ -153,5 +152,5 @@
         drop_feat = self.config['drop'].get(bool)
 
         for item in task.imported_items():
-            ft_in_title(item, drop_feat)
+            ft_in_title(item, drop_feat, logging.DEBUG)
             item.store()

{"golden_diff": "diff --git a/beetsplug/ftintitle.py b/beetsplug/ftintitle.py\n--- a/beetsplug/ftintitle.py\n+++ b/beetsplug/ftintitle.py\n@@ -45,14 +45,15 @@\n     return bool(re.search(plugins.feat_tokens(), title, flags=re.IGNORECASE))\n \n \n-def update_metadata(item, feat_part, drop_feat):\n+def update_metadata(item, feat_part, drop_feat, loglevel=logging.DEBUG):\n     \"\"\"Choose how to add new artists to the title and set the new\n     metadata. Also, print out messages about any changes that are made.\n     If `drop_feat` is set, then do not add the artist to the title; just\n     remove it from the artist field.\n     \"\"\"\n     # In all cases, update the artist fields.\n-    ui.print_(u'artist: {0} -> {1}'.format(item.artist, item.albumartist))\n+    log.log(loglevel, u'artist: {0} -> {1}'.format(\n+        item.artist, item.albumartist))\n     item.artist = item.albumartist\n     if item.artist_sort:\n         # Just strip the featured artist from the sort name.\n@@ -62,11 +63,11 @@\n     # artist and if we do not drop featuring information.\n     if not drop_feat and not contains_feat(item.title):\n         new_title = u\"{0} feat. {1}\".format(item.title, feat_part)\n-        ui.print_(u'title: {0} -> {1}'.format(item.title, new_title))\n+        log.log(loglevel, u'title: {0} -> {1}'.format(item.title, new_title))\n         item.title = new_title\n \n \n-def ft_in_title(item, drop_feat):\n+def ft_in_title(item, drop_feat, loglevel=logging.DEBUG):\n     \"\"\"Look for featured artists in the item's artist fields and move\n     them to the title.\n     \"\"\"\n@@ -78,14 +79,14 @@\n     # that case, we attempt to move the featured artist to the title.\n     _, featured = split_on_feat(artist)\n     if featured and albumartist != artist and albumartist:\n-        ui.print_(displayable_path(item.path))\n+        log.log(loglevel, displayable_path(item.path))\n         feat_part = None\n \n         # Look for the album artist in the artist field. If it's not\n         # present, give up.\n         albumartist_split = artist.split(albumartist)\n         if len(albumartist_split) <= 1:\n-            ui.print_('album artist not present in artist')\n+            log.log(loglevel, 'album artist not present in artist')\n \n         # If the last element of the split (the right-hand side of the\n         # album artist) is nonempty, then it probably contains the\n@@ -103,11 +104,9 @@\n \n         # If we have a featuring artist, move it to the title.\n         if feat_part:\n-            update_metadata(item, feat_part, drop_feat)\n+            update_metadata(item, feat_part, drop_feat, loglevel)\n         else:\n-            ui.print_(u'no featuring artists found')\n-\n-        ui.print_()\n+            log.log(loglevel, u'no featuring artists found')\n \n \n class FtInTitlePlugin(plugins.BeetsPlugin):\n@@ -139,7 +138,7 @@\n             write = config['import']['write'].get(bool)\n \n             for item in lib.items(ui.decargs(args)):\n-                ft_in_title(item, drop_feat)\n+                ft_in_title(item, drop_feat, logging.INFO)\n                 item.store()\n                 if write:\n                     item.try_write()\n@@ -153,5 +152,5 @@\n         drop_feat = self.config['drop'].get(bool)\n \n         for item in task.imported_items():\n-            ft_in_title(item, drop_feat)\n+            ft_in_title(item, drop_feat, logging.DEBUG)\n             item.store()\n", "issue": "ftintitle: be less verbose during import\nDuring an import, with the ftintitle enabled it seems to have very verbose output. This causes the user to not notice any prompts that beets has, and is somewhat annoying when doing a large import.\n\nAs seen here:\n![Image of ftintitle spam](http://i.imgur.com/wd0rN0R.png)\n\nMy suggestion would be to add a configuration option that would make ftintitle be less verbose. Or, making it not be verbose by default and adding a verbosity configuration option.\n\n", "before_files": [{"content": "# This file is part of beets.\n# Copyright 2013, Verrus, <github.com/Verrus/beets-plugin-featInTitle>\n#\n# Permission is hereby granted, free of charge, to any person obtaining\n# a copy of this software and associated documentation files (the\n# \"Software\"), to deal in the Software without restriction, including\n# without limitation the rights to use, copy, modify, merge, publish,\n# distribute, sublicense, and/or sell copies of the Software, and to\n# permit persons to whom the Software is furnished to do so, subject to\n# the following conditions:\n#\n# The above copyright notice and this permission notice shall be\n# included in all copies or substantial portions of the Software.\n\n\"\"\"Moves \"featured\" artists to the title from the artist field.\n\"\"\"\nfrom beets import plugins\nfrom beets import ui\nfrom beets.util import displayable_path\nfrom beets import config\nimport logging\nimport re\n\nlog = logging.getLogger('beets')\n\n\ndef split_on_feat(artist):\n    \"\"\"Given an artist string, split the \"main\" artist from any artist\n    on the right-hand side of a string like \"feat\". Return the main\n    artist, which is always a string, and the featuring artist, which\n    may be a string or None if none is present.\n    \"\"\"\n    # split on the first \"feat\".\n    regex = re.compile(plugins.feat_tokens(), re.IGNORECASE)\n    parts = [s.strip() for s in regex.split(artist, 1)]\n    if len(parts) == 1:\n        return parts[0], None\n    else:\n        return tuple(parts)\n\n\ndef contains_feat(title):\n    \"\"\"Determine whether the title contains a \"featured\" marker.\n    \"\"\"\n    return bool(re.search(plugins.feat_tokens(), title, flags=re.IGNORECASE))\n\n\ndef update_metadata(item, feat_part, drop_feat):\n    \"\"\"Choose how to add new artists to the title and set the new\n    metadata. Also, print out messages about any changes that are made.\n    If `drop_feat` is set, then do not add the artist to the title; just\n    remove it from the artist field.\n    \"\"\"\n    # In all cases, update the artist fields.\n    ui.print_(u'artist: {0} -> {1}'.format(item.artist, item.albumartist))\n    item.artist = item.albumartist\n    if item.artist_sort:\n        # Just strip the featured artist from the sort name.\n        item.artist_sort, _ = split_on_feat(item.artist_sort)\n\n    # Only update the title if it does not already contain a featured\n    # artist and if we do not drop featuring information.\n    if not drop_feat and not contains_feat(item.title):\n        new_title = u\"{0} feat. {1}\".format(item.title, feat_part)\n        ui.print_(u'title: {0} -> {1}'.format(item.title, new_title))\n        item.title = new_title\n\n\ndef ft_in_title(item, drop_feat):\n    \"\"\"Look for featured artists in the item's artist fields and move\n    them to the title.\n    \"\"\"\n    artist = item.artist.strip()\n    albumartist = item.albumartist.strip()\n\n    # Check whether there is a featured artist on this track and the\n    # artist field does not exactly match the album artist field. In\n    # that case, we attempt to move the featured artist to the title.\n    _, featured = split_on_feat(artist)\n    if featured and albumartist != artist and albumartist:\n        ui.print_(displayable_path(item.path))\n        feat_part = None\n\n        # Look for the album artist in the artist field. If it's not\n        # present, give up.\n        albumartist_split = artist.split(albumartist)\n        if len(albumartist_split) <= 1:\n            ui.print_('album artist not present in artist')\n\n        # If the last element of the split (the right-hand side of the\n        # album artist) is nonempty, then it probably contains the\n        # featured artist.\n        elif albumartist_split[-1] != '':\n            # Extract the featured artist from the right-hand side.\n            _, feat_part = split_on_feat(albumartist_split[-1])\n\n        # Otherwise, if there's nothing on the right-hand side, look for a\n        # featuring artist on the left-hand side.\n        else:\n            lhs, rhs = split_on_feat(albumartist_split[0])\n            if rhs:\n                feat_part = lhs\n\n        # If we have a featuring artist, move it to the title.\n        if feat_part:\n            update_metadata(item, feat_part, drop_feat)\n        else:\n            ui.print_(u'no featuring artists found')\n\n        ui.print_()\n\n\nclass FtInTitlePlugin(plugins.BeetsPlugin):\n    def __init__(self):\n        super(FtInTitlePlugin, self).__init__()\n\n        self.config.add({\n            'auto': True,\n            'drop': False,\n        })\n\n        self._command = ui.Subcommand(\n            'ftintitle',\n            help='move featured artists to the title field')\n\n        self._command.parser.add_option(\n            '-d', '--drop', dest='drop',\n            action='store_true', default=False,\n            help='drop featuring from artists and ignore title update')\n\n        if self.config['auto']:\n            self.import_stages = [self.imported]\n\n    def commands(self):\n\n        def func(lib, opts, args):\n            self.config.set_args(opts)\n            drop_feat = self.config['drop'].get(bool)\n            write = config['import']['write'].get(bool)\n\n            for item in lib.items(ui.decargs(args)):\n                ft_in_title(item, drop_feat)\n                item.store()\n                if write:\n                    item.try_write()\n\n        self._command.func = func\n        return [self._command]\n\n    def imported(self, session, task):\n        \"\"\"Import hook for moving featuring artist automatically.\n        \"\"\"\n        drop_feat = self.config['drop'].get(bool)\n\n        for item in task.imported_items():\n            ft_in_title(item, drop_feat)\n            item.store()\n", "path": "beetsplug/ftintitle.py"}], "after_files": [{"content": "# This file is part of beets.\n# Copyright 2013, Verrus, <github.com/Verrus/beets-plugin-featInTitle>\n#\n# Permission is hereby granted, free of charge, to any person obtaining\n# a copy of this software and associated documentation files (the\n# \"Software\"), to deal in the Software without restriction, including\n# without limitation the rights to use, copy, modify, merge, publish,\n# distribute, sublicense, and/or sell copies of the Software, and to\n# permit persons to whom the Software is furnished to do so, subject to\n# the following conditions:\n#\n# The above copyright notice and this permission notice shall be\n# included in all copies or substantial portions of the Software.\n\n\"\"\"Moves \"featured\" artists to the title from the artist field.\n\"\"\"\nfrom beets import plugins\nfrom beets import ui\nfrom beets.util import displayable_path\nfrom beets import config\nimport logging\nimport re\n\nlog = logging.getLogger('beets')\n\n\ndef split_on_feat(artist):\n    \"\"\"Given an artist string, split the \"main\" artist from any artist\n    on the right-hand side of a string like \"feat\". Return the main\n    artist, which is always a string, and the featuring artist, which\n    may be a string or None if none is present.\n    \"\"\"\n    # split on the first \"feat\".\n    regex = re.compile(plugins.feat_tokens(), re.IGNORECASE)\n    parts = [s.strip() for s in regex.split(artist, 1)]\n    if len(parts) == 1:\n        return parts[0], None\n    else:\n        return tuple(parts)\n\n\ndef contains_feat(title):\n    \"\"\"Determine whether the title contains a \"featured\" marker.\n    \"\"\"\n    return bool(re.search(plugins.feat_tokens(), title, flags=re.IGNORECASE))\n\n\ndef update_metadata(item, feat_part, drop_feat, loglevel=logging.DEBUG):\n    \"\"\"Choose how to add new artists to the title and set the new\n    metadata. Also, print out messages about any changes that are made.\n    If `drop_feat` is set, then do not add the artist to the title; just\n    remove it from the artist field.\n    \"\"\"\n    # In all cases, update the artist fields.\n    log.log(loglevel, u'artist: {0} -> {1}'.format(\n        item.artist, item.albumartist))\n    item.artist = item.albumartist\n    if item.artist_sort:\n        # Just strip the featured artist from the sort name.\n        item.artist_sort, _ = split_on_feat(item.artist_sort)\n\n    # Only update the title if it does not already contain a featured\n    # artist and if we do not drop featuring information.\n    if not drop_feat and not contains_feat(item.title):\n        new_title = u\"{0} feat. {1}\".format(item.title, feat_part)\n        log.log(loglevel, u'title: {0} -> {1}'.format(item.title, new_title))\n        item.title = new_title\n\n\ndef ft_in_title(item, drop_feat, loglevel=logging.DEBUG):\n    \"\"\"Look for featured artists in the item's artist fields and move\n    them to the title.\n    \"\"\"\n    artist = item.artist.strip()\n    albumartist = item.albumartist.strip()\n\n    # Check whether there is a featured artist on this track and the\n    # artist field does not exactly match the album artist field. In\n    # that case, we attempt to move the featured artist to the title.\n    _, featured = split_on_feat(artist)\n    if featured and albumartist != artist and albumartist:\n        log.log(loglevel, displayable_path(item.path))\n        feat_part = None\n\n        # Look for the album artist in the artist field. If it's not\n        # present, give up.\n        albumartist_split = artist.split(albumartist)\n        if len(albumartist_split) <= 1:\n            log.log(loglevel, 'album artist not present in artist')\n\n        # If the last element of the split (the right-hand side of the\n        # album artist) is nonempty, then it probably contains the\n        # featured artist.\n        elif albumartist_split[-1] != '':\n            # Extract the featured artist from the right-hand side.\n            _, feat_part = split_on_feat(albumartist_split[-1])\n\n        # Otherwise, if there's nothing on the right-hand side, look for a\n        # featuring artist on the left-hand side.\n        else:\n            lhs, rhs = split_on_feat(albumartist_split[0])\n            if rhs:\n                feat_part = lhs\n\n        # If we have a featuring artist, move it to the title.\n        if feat_part:\n            update_metadata(item, feat_part, drop_feat, loglevel)\n        else:\n            log.log(loglevel, u'no featuring artists found')\n\n\nclass FtInTitlePlugin(plugins.BeetsPlugin):\n    def __init__(self):\n        super(FtInTitlePlugin, self).__init__()\n\n        self.config.add({\n            'auto': True,\n            'drop': False,\n        })\n\n        self._command = ui.Subcommand(\n            'ftintitle',\n            help='move featured artists to the title field')\n\n        self._command.parser.add_option(\n            '-d', '--drop', dest='drop',\n            action='store_true', default=False,\n            help='drop featuring from artists and ignore title update')\n\n        if self.config['auto']:\n            self.import_stages = [self.imported]\n\n    def commands(self):\n\n        def func(lib, opts, args):\n            self.config.set_args(opts)\n            drop_feat = self.config['drop'].get(bool)\n            write = config['import']['write'].get(bool)\n\n            for item in lib.items(ui.decargs(args)):\n                ft_in_title(item, drop_feat, logging.INFO)\n                item.store()\n                if write:\n                    item.try_write()\n\n        self._command.func = func\n        return [self._command]\n\n    def imported(self, session, task):\n        \"\"\"Import hook for moving featuring artist automatically.\n        \"\"\"\n        drop_feat = self.config['drop'].get(bool)\n\n        for item in task.imported_items():\n            ft_in_title(item, drop_feat, logging.DEBUG)\n            item.store()\n", "path": "beetsplug/ftintitle.py"}]}