mirror of
https://github.com/beetbox/beets.git
synced 2025-12-26 18:43:38 +01:00
Simplified the configuration of the regular expressions for th ihate plugin
Added the docs
This commit is contained in:
parent
11008494c3
commit
8addf3ef39
3 changed files with 43 additions and 278 deletions
|
|
@ -15,7 +15,6 @@
|
|||
"""Warns you about things you hate (or even blocks import)."""
|
||||
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
from beets import config
|
||||
from beets.plugins import BeetsPlugin
|
||||
|
|
@ -51,57 +50,24 @@ class IHatePlugin(BeetsPlugin):
|
|||
self.config.add({
|
||||
'warn': [],
|
||||
'skip': [],
|
||||
'regex_ignore_case': False,
|
||||
'regex_invert_folder_result': False,
|
||||
'regex_invert_file_result': False,
|
||||
'regex_folder_name': '.*',
|
||||
'regex_file_name': '.*'
|
||||
'path': '.*'
|
||||
})
|
||||
|
||||
flags = re.IGNORECASE if self.config['regex_ignore_case'].get() else 0
|
||||
|
||||
self.invert_folder_album_result = \
|
||||
self.invert_folder_singleton_result = \
|
||||
self.config['regex_invert_folder_result'].get()
|
||||
self.invert_file_album_result = \
|
||||
self.invert_file_singleton_result = \
|
||||
self.config['regex_invert_file_result'].get()
|
||||
self.folder_name_album_regex = \
|
||||
self.folder_name_singleton_regex = \
|
||||
re.compile(self.config['regex_folder_name'].get(), flags)
|
||||
self.file_name_album_regex = \
|
||||
self.file_name_singleton_regex = \
|
||||
re.compile(self.config['regex_file_name'].get(), flags)
|
||||
self.path_album_regex = \
|
||||
self.path_singleton_regex = \
|
||||
re.compile(self.config['path'].get())
|
||||
|
||||
if 'album' in self.config:
|
||||
album_config = self.config['album']
|
||||
if 'regex_invert_folder_result' in album_config:
|
||||
self.invert_folder_album_result = album_config[
|
||||
'regex_invert_folder_result'].get()
|
||||
if 'regex_invert_file_result' in album_config:
|
||||
self.invert_file_album_result = album_config[
|
||||
'regex_invert_file_result'].get()
|
||||
if 'regex_folder_name' in album_config:
|
||||
self.folder_name_album_regex = re.compile(
|
||||
album_config['regex_folder_name'].get(), flags)
|
||||
if 'regex_file_name' in album_config:
|
||||
self.file_name_album_regex = re.compile(
|
||||
album_config['regex_file_name'].get(), flags)
|
||||
if 'path' in album_config:
|
||||
self.path_album_regex = re.compile(
|
||||
album_config['path'].get())
|
||||
|
||||
if 'singleton' in self.config:
|
||||
singleton_config = self.config['singleton']
|
||||
if 'regex_invert_folder_result' in singleton_config:
|
||||
self.invert_folder_singleton_result = singleton_config[
|
||||
'regex_invert_folder_result'].get()
|
||||
if 'regex_invert_file_result' in singleton_config:
|
||||
self.invert_file_singleton_result = singleton_config[
|
||||
'regex_invert_file_result'].get()
|
||||
if 'regex_folder_name' in singleton_config:
|
||||
self.folder_name_singleton_regex = re.compile(
|
||||
singleton_config['regex_folder_name'].get(), flags)
|
||||
if 'regex_file_name' in singleton_config:
|
||||
self.file_name_singleton_regex = re.compile(
|
||||
singleton_config['regex_file_name'].get(), flags)
|
||||
if 'path' in singleton_config:
|
||||
self.path_singleton_regex = re.compile(
|
||||
singleton_config['path'].get())
|
||||
|
||||
@classmethod
|
||||
def do_i_hate_this(cls, task, action_patterns):
|
||||
|
|
@ -142,76 +108,25 @@ class IHatePlugin(BeetsPlugin):
|
|||
if task.items and len(task.items) > 0:
|
||||
items_to_import = []
|
||||
for item in task.items:
|
||||
if self.file_filter(item['path'], session.paths):
|
||||
if self.file_filter(item['path']):
|
||||
items_to_import.append(item)
|
||||
if len(items_to_import) > 0:
|
||||
task.items = items_to_import
|
||||
else:
|
||||
task.choice_flag = action.SKIP
|
||||
elif isinstance(task, SingletonImportTask):
|
||||
if not self.file_filter(task.item['path'], session.paths):
|
||||
if not self.file_filter(task.item['path']):
|
||||
task.choice_flag = action.SKIP
|
||||
|
||||
def file_filter(self, full_path, base_paths):
|
||||
def file_filter(self, full_path):
|
||||
"""Checks if the configured regular expressions allow the import of the
|
||||
file given in full_path.
|
||||
"""
|
||||
# The folder regex only checks the folder names starting from the
|
||||
# longest base path. Find this folder.
|
||||
matched_base_path = ''
|
||||
for base_path in base_paths:
|
||||
if full_path.startswith(base_path) and len(base_path) > len(
|
||||
matched_base_path):
|
||||
matched_base_path = base_path
|
||||
relative_path = full_path[len(matched_base_path):]
|
||||
|
||||
if os.path.isdir(full_path):
|
||||
path = relative_path
|
||||
file_name = None
|
||||
else:
|
||||
path, file_name = os.path.split(relative_path)
|
||||
path, folder_name = os.path.split(path)
|
||||
|
||||
import_config = dict(config['import'])
|
||||
if 'singletons' not in import_config or not import_config[
|
||||
'singletons']:
|
||||
# Album
|
||||
|
||||
# Folder
|
||||
while len(folder_name) > 0:
|
||||
matched = self.folder_name_album_regex.match(
|
||||
folder_name) is not None
|
||||
matched = not matched if self.invert_folder_album_result else \
|
||||
matched
|
||||
if not matched:
|
||||
return False
|
||||
path, folder_name = os.path.split(path)
|
||||
|
||||
# File
|
||||
matched = self.file_name_album_regex.match(
|
||||
file_name) is not None
|
||||
matched = not matched if self.invert_file_album_result else matched
|
||||
if not matched:
|
||||
return False
|
||||
return True
|
||||
return self.path_album_regex.match(full_path) is not None
|
||||
else:
|
||||
# Singleton
|
||||
|
||||
# Folder
|
||||
while len(folder_name) > 0:
|
||||
matched = self.folder_name_singleton_regex.match(
|
||||
folder_name) is not None
|
||||
matched = not matched if \
|
||||
self.invert_folder_singleton_result else matched
|
||||
if not matched:
|
||||
return False
|
||||
path, folder_name = os.path.split(path)
|
||||
|
||||
# File
|
||||
matched = self.file_name_singleton_regex.match(
|
||||
file_name) is not None
|
||||
matched = not matched if self.invert_file_singleton_result else \
|
||||
matched
|
||||
if not matched:
|
||||
return False
|
||||
return True
|
||||
return self.path_singleton_regex.match(full_path) is not None
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@ IHate Plugin
|
|||
The ``ihate`` plugin allows you to automatically skip things you hate during
|
||||
import or warn you about them. You specify queries (see
|
||||
:doc:`/reference/query`) and the plugin skips (or warns about) albums or items
|
||||
that match any query.
|
||||
that match any query. You can also specify regular expressions to filter files
|
||||
to import regarding of their path and name.
|
||||
|
||||
To use the ``ihate`` plugin, enable it in your configuration (see
|
||||
:ref:`using-plugins`).
|
||||
|
|
@ -19,6 +20,13 @@ file. The available options are:
|
|||
Default: ``[]`` (empty list).
|
||||
- **warn**: Print a warning message for matches in this list of queries.
|
||||
Default: ``[]``.
|
||||
- **path**: A regular expression to filter files based on its path and name.
|
||||
Default: ``.*`` (everything)
|
||||
- **album** and **singleton**: You may specify different regular expressions
|
||||
used for imports of albums and singletons. This way, you can automatically
|
||||
skip singletons when importing albums if the names (and paths) of the files
|
||||
are distinguishable via a regex. The path regex defined here take precedence
|
||||
over the global ``path`` option.
|
||||
|
||||
Here's an example::
|
||||
|
||||
|
|
@ -33,5 +41,12 @@ Here's an example::
|
|||
- genre:polka
|
||||
- artist:manowar
|
||||
- album:christmas
|
||||
path: .*\d\d[^/]+$
|
||||
# will only import files which names start with two digits
|
||||
album:
|
||||
path: .*\d\d[^/]+$
|
||||
singleton:
|
||||
path: .*/(?!\d\d)[^/]+$
|
||||
|
||||
The plugin trusts your decision in "as-is" imports.
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ from test.helper import capture_log
|
|||
from test.test_importer import ImportHelper
|
||||
|
||||
|
||||
class IHatePluginTest(ImportHelper):
|
||||
class IHatePluginTest(unittest.TestCase, ImportHelper):
|
||||
def setUp(self):
|
||||
self.setup_beets()
|
||||
self.__create_import_dir(2)
|
||||
|
|
@ -142,207 +142,42 @@ class IHatePluginTest(ImportHelper):
|
|||
|
||||
def test_import_nothing(self):
|
||||
self.__reset_config()
|
||||
config['ihate']['regex_invert_folder_result'] = True
|
||||
config['ihate']['regex_invert_file_result'] = True
|
||||
config['ihate']['path'] = 'not_there'
|
||||
self.__run([])
|
||||
|
||||
# Global options
|
||||
def test_import_global_match_folder(self):
|
||||
def test_import_global(self):
|
||||
self.__reset_config()
|
||||
config['ihate']['regex_folder_name'] = 'artist'
|
||||
config['ihate']['path'] = '.*track_1.*\.mp3'
|
||||
self.__run([self.artist_paths[0],
|
||||
self.artist_paths[1]])
|
||||
|
||||
def test_import_global_invert_folder(self):
|
||||
self.__reset_config()
|
||||
config['ihate']['regex_folder_name'] = 'artist'
|
||||
config['ihate']['regex_invert_folder_result'] = True
|
||||
self.__run([self.misc_paths[0],
|
||||
self.misc_paths[1]])
|
||||
|
||||
def test_import_global_match_file(self):
|
||||
self.__reset_config()
|
||||
config['ihate']['regex_file_name'] = '.*2.*'
|
||||
self.__run([self.artist_paths[1],
|
||||
self.album_paths[1],
|
||||
self.misc_paths[1]])
|
||||
|
||||
def test_import_global_invert_file(self):
|
||||
self.__reset_config()
|
||||
config['ihate']['regex_file_name'] = '.*2.*'
|
||||
config['ihate']['regex_invert_file_result'] = True
|
||||
self.__run([self.artist_paths[0],
|
||||
self.album_paths[0],
|
||||
self.misc_paths[0]])
|
||||
|
||||
def test_import_global_match_folder_case_sensitive(self):
|
||||
self.__reset_config()
|
||||
config['ihate']['regex_folder_name'] = 'Artist'
|
||||
self.__run([])
|
||||
|
||||
def test_import_global_match_folder_ignore_case(self):
|
||||
self.__reset_config()
|
||||
config['ihate']['regex_ignore_case'] = True
|
||||
config['ihate']['regex_folder_name'] = 'Artist'
|
||||
self.__run([self.artist_paths[0],
|
||||
self.artist_paths[1]])
|
||||
self.misc_paths[0]], singletons=True)
|
||||
|
||||
# Album options
|
||||
def test_import_album_match_folder(self):
|
||||
def test_import_album(self):
|
||||
self.__reset_config()
|
||||
config['ihate']['album']['regex_folder_name'] = 'artist'
|
||||
config['ihate']['album']['path'] = '.*track_1.*\.mp3'
|
||||
self.__run([self.artist_paths[0],
|
||||
self.artist_paths[1]])
|
||||
self.__run(self.all_paths, singletons=True)
|
||||
|
||||
def test_import_album_invert_folder(self):
|
||||
self.__reset_config()
|
||||
config['ihate']['album']['regex_folder_name'] = 'artist'
|
||||
config['ihate']['album']['regex_invert_folder_result'] = True
|
||||
self.__run([self.misc_paths[0],
|
||||
self.misc_paths[1]])
|
||||
self.__run(self.all_paths, singletons=True)
|
||||
|
||||
def test_import_album_match_file(self):
|
||||
self.__reset_config()
|
||||
config['ihate']['album']['regex_file_name'] = '.*2.*'
|
||||
self.__run([self.artist_paths[1],
|
||||
self.album_paths[1],
|
||||
self.misc_paths[1]])
|
||||
self.__run(self.all_paths, singletons=True)
|
||||
|
||||
def test_import_album_invert_file(self):
|
||||
self.__reset_config()
|
||||
config['ihate']['album']['regex_file_name'] = '.*2.*'
|
||||
config['ihate']['album']['regex_invert_file_result'] = True
|
||||
self.__run([self.artist_paths[0],
|
||||
self.album_paths[0],
|
||||
self.misc_paths[0]])
|
||||
self.__run(self.all_paths, singletons=True)
|
||||
|
||||
def test_import_album_match_folder_case_sensitive(self):
|
||||
self.__reset_config()
|
||||
config['ihate']['album']['regex_folder_name'] = 'Artist'
|
||||
self.__run([])
|
||||
self.__run(self.all_paths, singletons=True)
|
||||
|
||||
def test_import_album_match_folder_ignore_case(self):
|
||||
self.__reset_config()
|
||||
config['ihate']['regex_ignore_case'] = True
|
||||
config['ihate']['album']['regex_folder_name'] = 'Artist'
|
||||
self.__run([self.artist_paths[0],
|
||||
self.artist_paths[1]])
|
||||
self.__run(self.all_paths, singletons=True)
|
||||
|
||||
# Singleton options
|
||||
def test_import_singleton_match_folder(self):
|
||||
def test_import_singleton(self):
|
||||
self.__reset_config()
|
||||
config['ihate']['singleton']['regex_folder_name'] = 'artist'
|
||||
config['ihate']['singleton']['path'] = '.*track_1.*\.mp3'
|
||||
self.__run([self.artist_paths[0],
|
||||
self.artist_paths[1]], singletons=True)
|
||||
self.__run(self.all_paths)
|
||||
|
||||
def test_import_singleton_invert_folder(self):
|
||||
self.__reset_config()
|
||||
config['ihate']['singleton']['regex_folder_name'] = 'artist'
|
||||
config['ihate']['singleton']['regex_invert_folder_result'] = True
|
||||
self.__run([self.misc_paths[0],
|
||||
self.misc_paths[1]], singletons=True)
|
||||
self.__run(self.all_paths)
|
||||
|
||||
def test_import_singleton_match_file(self):
|
||||
self.__reset_config()
|
||||
config['ihate']['singleton']['regex_file_name'] = '.*2.*'
|
||||
self.__run([self.artist_paths[1],
|
||||
self.album_paths[1],
|
||||
self.misc_paths[1]], singletons=True)
|
||||
self.__run(self.all_paths)
|
||||
|
||||
def test_import_singleton_invert_file(self):
|
||||
self.__reset_config()
|
||||
config['ihate']['singleton']['regex_file_name'] = '.*2.*'
|
||||
config['ihate']['singleton']['regex_invert_file_result'] = True
|
||||
self.__run([self.artist_paths[0],
|
||||
self.album_paths[0],
|
||||
self.misc_paths[0]], singletons=True)
|
||||
self.__run(self.all_paths)
|
||||
|
||||
def test_import_singleton_match_folder_case_sensitive(self):
|
||||
self.__reset_config()
|
||||
config['ihate']['singleton']['regex_folder_name'] = 'Artist'
|
||||
self.__run([], singletons=True)
|
||||
self.__run(self.all_paths)
|
||||
|
||||
def test_import_singleton_match_folder_ignore_case(self):
|
||||
self.__reset_config()
|
||||
config['ihate']['regex_ignore_case'] = True
|
||||
config['ihate']['singleton']['regex_folder_name'] = 'Artist'
|
||||
self.__run([self.artist_paths[0],
|
||||
self.artist_paths[1]], singletons=True)
|
||||
self.__run(self.all_paths)
|
||||
|
||||
# Album and singleton options
|
||||
def test_import_both_match_folder(self):
|
||||
def test_import_both(self):
|
||||
self.__reset_config()
|
||||
config['ihate']['album']['regex_folder_name'] = 'artist'
|
||||
config['ihate']['singleton']['regex_folder_name'] = 'misc'
|
||||
config['ihate']['album']['path'] = '.*track_1.*\.mp3'
|
||||
config['ihate']['singleton']['path'] = '.*track_2.*\.mp3'
|
||||
self.__run([self.artist_paths[0],
|
||||
self.artist_paths[1]])
|
||||
self.__run([self.misc_paths[0],
|
||||
self.misc_paths[1]], singletons=True)
|
||||
|
||||
def test_import_both_invert_folder(self):
|
||||
self.__reset_config()
|
||||
config['ihate']['album']['regex_folder_name'] = 'artist'
|
||||
config['ihate']['album']['regex_invert_folder_result'] = True
|
||||
config['ihate']['singleton']['regex_folder_name'] = 'misc'
|
||||
config['ihate']['singleton']['regex_invert_folder_result'] = True
|
||||
self.__run([self.misc_paths[0],
|
||||
self.misc_paths[1]])
|
||||
self.__run([self.artist_paths[0],
|
||||
self.artist_paths[1],
|
||||
self.album_paths[0],
|
||||
self.album_paths[1]], singletons=True)
|
||||
|
||||
def test_import_both_match_file(self):
|
||||
self.__reset_config()
|
||||
config['ihate']['album']['regex_file_name'] = '.*2.*'
|
||||
config['ihate']['singleton']['regex_file_name'] = '.*1.*'
|
||||
self.__run([self.artist_paths[1],
|
||||
self.album_paths[1],
|
||||
self.misc_paths[1]])
|
||||
self.__run([self.artist_paths[0],
|
||||
self.album_paths[0],
|
||||
self.misc_paths[0]], singletons=True)
|
||||
|
||||
def test_import_both_invert_file(self):
|
||||
self.__reset_config()
|
||||
config['ihate']['album']['regex_file_name'] = '.*2.*'
|
||||
config['ihate']['album']['regex_invert_file_result'] = True
|
||||
config['ihate']['singleton']['regex_file_name'] = '.*1.*'
|
||||
config['ihate']['singleton']['regex_invert_file_result'] = True
|
||||
self.__run([self.artist_paths[0],
|
||||
self.album_paths[0],
|
||||
self.misc_paths[0]])
|
||||
self.__run([self.artist_paths[1],
|
||||
self.album_paths[1],
|
||||
self.misc_paths[1]], singletons=True)
|
||||
|
||||
def test_import_both_match_folder_case_sensitive(self):
|
||||
self.__reset_config()
|
||||
config['ihate']['album']['regex_folder_name'] = 'Artist'
|
||||
config['ihate']['singleton']['regex_folder_name'] = 'Misc'
|
||||
self.__run([])
|
||||
self.__run([], singletons=True)
|
||||
|
||||
def test_import_both_match_folder_ignore_case(self):
|
||||
self.__reset_config()
|
||||
config['ihate']['regex_ignore_case'] = True
|
||||
config['ihate']['album']['regex_folder_name'] = 'Artist'
|
||||
config['ihate']['singleton']['regex_folder_name'] = 'Misc'
|
||||
self.__run([self.artist_paths[0],
|
||||
self.artist_paths[1]])
|
||||
self.__run([self.misc_paths[0],
|
||||
self.misc_paths[1]], singletons=True)
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue