Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge pull request #51 from tezoulbr/master

new plugin - ihate
  • Loading branch information...
commit fb9834c4f8f84d6f51c85041460894345d6e35ef 2 parents c9fafb8 + 3eb1135
@sampsyo authored
View
142 beetsplug/ihate.py
@@ -0,0 +1,142 @@
+# This file is part of beets.
+# Copyright 2012, Blemjhoo Tezoulbr <baobab@heresiarch.info>.
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+
+"""Warns you about things you hate (or even blocks import)."""
+
+import re
+import logging
+from beets.plugins import BeetsPlugin
+from beets import ui
+from beets.importer import action
+
+
+__author__ = 'baobab@heresiarch.info'
+__version__ = '1.0'
+
+
+class IHatePlugin(BeetsPlugin):
+
+ _instance = None
+ _log = logging.getLogger('beets')
+
+ warn_genre = []
+ warn_artist = []
+ warn_album = []
+ warn_whitelist = []
+ skip_genre = []
+ skip_artist = []
+ skip_album = []
+ skip_whitelist = []
+
+ def __new__(cls, *args, **kwargs):
+ if cls._instance is None:
+ cls._instance = super(IHatePlugin,
+ cls).__new__(cls, *args, **kwargs)
+ return cls._instance
+
+ def __str__(self):
+ return ('(\n warn_genre = {0}\n'
+ ' warn_artist = {1}\n'
+ ' warn_album = {2}\n'
+ ' warn_whitelist = {3}\n'
+ ' skip_genre = {4}\n'
+ ' skip_artist = {5}\n'
+ ' skip_album = {6}\n'
+ ' skip_whitelist = {7} )\n'
+ .format(self.warn_genre, self.warn_artist, self.warn_album,
+ self.warn_whitelist, self.skip_genre, self.skip_artist,
+ self.skip_album, self.skip_whitelist))
+
+ def configure(self, config):
+ if not config.has_section('ihate'):
+ self._log.warn('[ihate] plugin is not configured')
+ return
+ self.warn_genre = ui.config_val(config, 'ihate', 'warn_genre',
+ '').split()
+ self.warn_artist = ui.config_val(config, 'ihate', 'warn_artist',
+ '').split()
+ self.warn_album = ui.config_val(config, 'ihate', 'warn_album',
+ '').split()
+ self.warn_whitelist = ui.config_val(config, 'ihate', 'warn_whitelist',
+ '').split()
+ self.skip_genre = ui.config_val(config, 'ihate', 'skip_genre',
+ '').split()
+ self.skip_artist = ui.config_val(config, 'ihate', 'skip_artist',
+ '').split()
+ self.skip_album = ui.config_val(config, 'ihate', 'skip_album',
+ '').split()
+ self.skip_whitelist = ui.config_val(config, 'ihate', 'skip_whitelist',
+ '').split()
+
+ @classmethod
+ def match_patterns(cls, s, patterns):
+ """Check if string is matching any of the patterns in the list."""
+ for p in patterns:
+ if re.findall(p, s, flags=re.IGNORECASE):
+ return True
+ return False
+
+ @classmethod
+ def do_i_hate_this(cls, task, genre_patterns, artist_patterns,
+ album_patterns, whitelist_patterns):
+ """Process group of patterns (warn or skip) and returns True if
+ task is hated and not whitelisted.
+ """
+ hate = False
+ try:
+ genre = task.items[0].genre
+ except:
+ genre = u''
+ if genre and genre_patterns:
+ if IHatePlugin.match_patterns(genre, genre_patterns):
+ hate = True
+ if not hate and task.cur_album and album_patterns:
+ if IHatePlugin.match_patterns(task.cur_album, album_patterns):
+ hate = True
+ if not hate and task.cur_artist and artist_patterns:
+ if IHatePlugin.match_patterns(task.cur_artist, artist_patterns):
+ hate = True
+ if hate and whitelist_patterns:
+ if IHatePlugin.match_patterns(task.cur_artist, whitelist_patterns):
+ hate = False
+ return hate
+
+ def job_to_do(self):
+ """Return True if at least one pattern is defined."""
+ return any([self.warn_genre, self.warn_artist, self.warn_album,
+ self.skip_genre, self.skip_artist, self.skip_album])
+
+ def import_task_choice_event(self, task, config):
+ if task.choice_flag == action.APPLY:
+ if self.job_to_do:
+ self._log.debug('[ihate] processing your hate')
+ if self.do_i_hate_this(task, self.skip_genre, self.skip_artist,
+ self.skip_album, self.skip_whitelist):
+ task.choice_flag = action.SKIP
+ self._log.info(u'[ihate] skipped: {0} - {1}'
+ .format(task.cur_artist, task.cur_album))
+ return
+ if self.do_i_hate_this(task, self.warn_genre, self.warn_artist,
+ self.warn_album, self.warn_whitelist):
+ self._log.info(u'[ihate] you maybe hate this: {0} - {1}'
+ .format(task.cur_artist, task.cur_album))
+ else:
+ self._log.debug('[ihate] nothing to do')
+ else:
+ self._log.debug('[ihate] user make a decision, nothing to do')
+
+
+@IHatePlugin.listen('import_task_choice')
+def ihate_import_task_choice(task, config):
+ IHatePlugin().import_task_choice_event(task, config)
View
35 docs/plugins/ihate.rst
@@ -0,0 +1,35 @@
+IHate Plugin
+============
+
+The ``ihate`` plugin allows you to automatically skip things you hate during
+import or warn you about them. It supports album, artist and genre patterns.
+Also there is whitelist to avoid skipping bands you still like. There are two
+groups: warn and skip. Skip group is checked first. Whitelist overrides any
+other patterns.
+
+To use plugin, enable it by including ``ihate`` into ``plugins`` line of
+your beets config::
+
+ [beets]
+ plugins = ihate
+
+You need to configure plugin before use, so add following section into config
+file and adjust it to your needs::
+
+ [ihate]
+ # you will be warned about these suspicious genres/artists (regexps):
+ warn_genre=rnb soul power\smetal
+ warn_artist=bad\band another\sbad\sband
+ warn_album=tribute\sto
+ # if you don't like genre in general, but accept some band playing it,
+ # add exceptions here:
+ warn_whitelist=hate\sexception
+ # never import any of this:
+ skip_genre=russian\srock polka
+ skip_artist=manowar
+ skip_album=christmas
+ # but import this:
+ skip_whitelist=
+
+Note: plugin will trust you decision in 'as-is' mode.
+
View
2  docs/plugins/index.rst
@@ -53,6 +53,7 @@ disabled by default, but you can turn them on as described above.
the
fuzzy_search
zero
+ ihate
Autotagger Extensions
''''''''''''''''''''''
@@ -92,6 +93,7 @@ Miscellaneous
* :doc:`rdm`: Randomly choose albums and tracks from your library.
* :doc:`fuzzy_search`: Search albums and tracks with fuzzy string matching.
* :doc:`mbcollection`: Maintain your MusicBrainz collection list.
+* :doc:`ihate`: Skip by defined patterns things you hate during import process.
* :doc:`bpd`: A music player for your beets library that emulates `MPD`_ and is
compatible with `MPD clients`_.
View
52 test/test_ihate.py
@@ -0,0 +1,52 @@
+"""Tests for the 'ihate' plugin"""
+
+from _common import unittest
+from beets.importer import ImportTask
+from beets.library import Item
+from beetsplug.ihate import IHatePlugin
+
+
+class IHatePluginTest(unittest.TestCase):
+
+ def test_hate(self):
+ genre_p = []
+ artist_p = []
+ album_p = []
+ white_p = []
+ task = ImportTask()
+ task.cur_artist = u'Test Artist'
+ task.cur_album = u'Test Album'
+ task.items = [Item({'genre': 'Test Genre'})]
+ self.assertFalse(IHatePlugin.do_i_hate_this(task, genre_p, artist_p,
+ album_p, white_p))
+ genre_p = 'some_genre test\sgenre'.split()
+ self.assertTrue(IHatePlugin.do_i_hate_this(task, genre_p, artist_p,
+ album_p, white_p))
+ genre_p = []
+ artist_p = 'bad_artist test\sartist'
+ self.assertTrue(IHatePlugin.do_i_hate_this(task, genre_p, artist_p,
+ album_p, white_p))
+ artist_p = []
+ album_p = 'tribute christmas test'.split()
+ self.assertTrue(IHatePlugin.do_i_hate_this(task, genre_p, artist_p,
+ album_p, white_p))
+ album_p = []
+ white_p = 'goodband test\sartist another_band'.split()
+ genre_p = 'some_genre test\sgenre'.split()
+ self.assertFalse(IHatePlugin.do_i_hate_this(task, genre_p, artist_p,
+ album_p, white_p))
+ genre_p = []
+ artist_p = 'bad_artist test\sartist'
+ self.assertFalse(IHatePlugin.do_i_hate_this(task, genre_p, artist_p,
+ album_p, white_p))
+ artist_p = []
+ album_p = 'tribute christmas test'.split()
+ self.assertFalse(IHatePlugin.do_i_hate_this(task, genre_p, artist_p,
+ album_p, white_p))
+
+
+def suite():
+ return unittest.TestLoader().loadTestsFromName(__name__)
+
+if __name__ == '__main__':
+ unittest.main(defaultTest='suite')
Please sign in to comment.
Something went wrong with that request. Please try again.