Пример #1
0
    def test_logging_management(self):
        l1 = log.getLogger("foo123")
        l2 = blog.getLogger("foo123")
        self.assertEqual(l1, l2)
        self.assertEqual(l1.__class__, log.Logger)

        l3 = blog.getLogger("bar123")
        l4 = log.getLogger("bar123")
        self.assertEqual(l3, l4)
        self.assertEqual(l3.__class__, blog.StrFormatLogger)

        l5 = l3.getChild("shalala")
        self.assertEqual(l5.__class__, blog.StrFormatLogger)
Пример #2
0
    def test_logging_management(self):
        l1 = log.getLogger("foo123")
        l2 = blog.getLogger("foo123")
        self.assertEqual(l1, l2)
        self.assertEqual(l1.__class__, log.Logger)

        l3 = blog.getLogger("bar123")
        l4 = log.getLogger("bar123")
        self.assertEqual(l3, l4)
        self.assertEqual(l3.__class__, blog.BeetsLogger)
        self.assertIsInstance(
            l3, (blog.StrFormatLogger, blog.ThreadLocalLevelLogger))

        l5 = l3.getChild("shalala")
        self.assertEqual(l5.__class__, blog.BeetsLogger)
Пример #3
0
    def test_logging_management(self):
        l1 = log.getLogger("foo123")
        l2 = blog.getLogger("foo123")
        self.assertEqual(l1, l2)
        self.assertEqual(l1.__class__, log.Logger)

        l3 = blog.getLogger("bar123")
        l4 = log.getLogger("bar123")
        self.assertEqual(l3, l4)
        self.assertEqual(l3.__class__, blog.BeetsLogger)
        self.assertIsInstance(l3, (blog.StrFormatLogger,
                                   blog.ThreadLocalLevelLogger))

        l5 = l3.getChild("shalala")
        self.assertEqual(l5.__class__, blog.BeetsLogger)
Пример #4
0
    def test_embed_non_image_file(self):
        album = self.add_album_fixture()
        logging.getLogger('beets.embedart').setLevel(logging.DEBUG)

        handle, tmp_path = tempfile.mkstemp()
        os.write(handle, b'I am not an image.')
        os.close(handle)

        try:
            self.run_command('embedart', '-y', '-f', tmp_path)
        finally:
            os.remove(tmp_path)

        mediafile = MediaFile(syspath(album.items()[0].path))
        self.assertFalse(mediafile.images)  # No image added.
Пример #5
0
    def test_embed_non_image_file(self):
        album = self.add_album_fixture()
        logging.getLogger('beets.embedart').setLevel(logging.DEBUG)

        handle, tmp_path = tempfile.mkstemp()
        os.write(handle, 'I am not an image.')
        os.close(handle)

        try:
            self.run_command('embedart', '-f', tmp_path)
        finally:
            os.remove(tmp_path)

        mediafile = MediaFile(syspath(album.items()[0].path))
        self.assertFalse(mediafile.images)  # No image added.
Пример #6
0
    def test_imagemagick_response(self, mock_extract, mock_subprocess):
        mock_extract.return_value = True
        proc = mock_subprocess.Popen.return_value
        log = logging.getLogger('beets.embedart')

        # everything is fine
        proc.returncode = 0
        proc.communicate.return_value = "10", "tagada"
        self.assertTrue(art.check_art_similarity(log, None, None, 20))
        self.assertFalse(art.check_art_similarity(log, None, None, 5))

        # small failure
        proc.returncode = 1
        proc.communicate.return_value = "tagada", "10"
        self.assertTrue(art.check_art_similarity(log, None, None, 20))
        self.assertFalse(art.check_art_similarity(log, None, None, 5))

        # bigger failure
        proc.returncode = 2
        self.assertIsNone(art.check_art_similarity(log, None, None, 20))

        # IM result parsing problems
        proc.returncode = 0
        proc.communicate.return_value = "foo", "bar"
        self.assertIsNone(art.check_art_similarity(log, None, None, 20))

        proc.returncode = 1
        self.assertIsNone(art.check_art_similarity(log, None, None, 20))
Пример #7
0
    def test_imagemagick_response(self, mock_extract, mock_subprocess):
        mock_extract.return_value = True
        proc = mock_subprocess.Popen.return_value
        log = logging.getLogger('beets.embedart')

        # everything is fine
        proc.returncode = 0
        proc.communicate.return_value = "10", "tagada"
        self.assertTrue(art.check_art_similarity(log, None, None, 20))
        self.assertFalse(art.check_art_similarity(log, None, None, 5))

        # small failure
        proc.returncode = 1
        proc.communicate.return_value = "tagada", "10"
        self.assertTrue(art.check_art_similarity(log, None, None, 20))
        self.assertFalse(art.check_art_similarity(log, None, None, 5))

        # bigger failure
        proc.returncode = 2
        self.assertIsNone(art.check_art_similarity(log, None, None, 20))

        # IM result parsing problems
        proc.returncode = 0
        proc.communicate.return_value = "foo", "bar"
        self.assertIsNone(art.check_art_similarity(log, None, None, 20))

        proc.returncode = 1
        self.assertIsNone(art.check_art_similarity(log, None, None, 20))
Пример #8
0
def capture_log(logger='beets'):
    capture = LogCapture()
    log = logging.getLogger(logger)
    log.addHandler(capture)
    try:
        yield capture.messages
    finally:
        log.removeHandler(capture)
Пример #9
0
def capture_log(logger='beets'):
    capture = LogCapture()
    log = logging.getLogger(logger)
    log.addHandler(capture)
    try:
        yield capture.messages
    finally:
        log.removeHandler(capture)
Пример #10
0
    def func(self, lib: Library, options, arguments):
        self.cfg_quiet = options.quiet
        self.cfg_count = options.count
        self.cfg_dry_run = options.dry_run

        self.lib = lib
        self.query = decargs(arguments)

        # Determine if -v option was set for more verbose logging
        logger = logging.getLogger('beets')
        self.verbose_log = True if logger.level == logging.DEBUG else False

        # TEMPORARY: Verify configuration upgrade!
        # There is a major backward incompatible upgrade in version 1.1.1
        try:
            self.verify_configuration_upgrade()
        except RuntimeError as e:
            self._say("*" * 80)
            self._say(
                "********************   INCOMPATIBLE PLUGIN CONFIGURATION   "
                "*********************")
            self._say("*" * 80)
            self._say(
                "* Your configuration has been created for an older version "
                "of the plugin.")
            self._say(
                "* Since version 1.1.1 the plugin has implemented changes "
                "that require your "
                "current configuration to be updated.")
            self._say(
                "* Please read the updated documentation here and update your "
                "configuration.")
            self._say(
                "* Documentation: "
                "https://github.com/adamjakab/BeetsPluginGoingRunning/blob"
                "/master/README.md"
                "#configuration")
            self._say("* I promise it will not happen again ;)")
            self._say("* " + str(e))
            self._say("* The plugin will exit now.")
            common.say("*" * 80)
            return

        # You must either pass a training name or request listing
        if len(self.query) < 1 and not (options.list or options.version):
            self.parser.print_help()
            return

        if options.version:
            self.show_version_information()
            return
        elif options.list:
            self.list_trainings()
            return

        self.handle_training()
Пример #11
0
    def test_embed_art_remove_art_file(self):
        self._setup_data()
        album = self.add_album_fixture()

        logging.getLogger('beets.embedart').setLevel(logging.DEBUG)

        handle, tmp_path = tempfile.mkstemp()
        os.write(handle, self.image_data)
        os.close(handle)

        album.artpath = tmp_path
        album.store()

        config['embedart']['remove_art_file'] = True
        self.run_command('embedart', '-y')

        if os.path.isfile(tmp_path):
            os.remove(tmp_path)
            self.fail(f'Artwork file {tmp_path} was not deleted')
Пример #12
0
    def test_embed_art_remove_art_file(self):
        self._setup_data()
        album = self.add_album_fixture()

        logging.getLogger('beets.embedart').setLevel(logging.DEBUG)

        handle, tmp_path = tempfile.mkstemp()
        os.write(handle, self.image_data)
        os.close(handle)

        album.artpath = tmp_path
        album.store()

        config['embedart']['remove_art_file'] = True
        self.run_command('embedart', '-y')

        if os.path.isfile(tmp_path):
            os.remove(tmp_path)
            self.fail(u'Artwork file {0} was not deleted'.format(tmp_path))
Пример #13
0
    def test_str_format_logging(self):
        l = blog.getLogger("baz123")
        stream = StringIO()
        handler = log.StreamHandler(stream)

        l.addHandler(handler)
        l.propagate = False

        l.warning(u"foo {0} {bar}", "oof", bar=u"baz")
        handler.flush()
        self.assertTrue(stream.getvalue(), u"foo oof baz")
Пример #14
0
    def test_str_format_logging(self):
        l = blog.getLogger("baz123")
        stream = StringIO()
        handler = log.StreamHandler(stream)

        l.addHandler(handler)
        l.propagate = False

        l.warning(u"foo {0} {bar}", "oof", bar=u"baz")
        handler.flush()
        self.assertTrue(stream.getvalue(), u"foo oof baz")
Пример #15
0
def capture_log(logger='beets', suppress_output=True):
    capture = LogCapture()
    log = logging.getLogger(logger)
    log.propagate = True
    if suppress_output:
        # Is this too violent?
        log.handlers = []
    log.addHandler(capture)
    try:
        yield capture.messages
    finally:
        log.removeHandler(capture)
Пример #16
0
def capture_log(logger=_default_logger_name_):
    """Capture Logger output
    >>> with capture_log() as logs:
    ...     log.info("Message")

    >>> full_log = ""\n"".join(logs)
    """
    capture = LogCapture()
    log = logging.getLogger(logger)
    log.addHandler(capture)
    try:
        yield capture.messages
    finally:
        log.removeHandler(capture)
Пример #17
0
    def setUp(self):
        """Set up test environment for bare ASCII query matching."""
        self.setup_beets()
        self.log = logging.getLogger('beets.web')
        self.config['bareasc']['prefix'] = u'#'
        self.load_plugins('bareasc')

        # Add library elements. Note that self.lib.add overrides any "id=<n>"
        # and assigns the next free id number.
        self.add_item(title=u'with accents',
                      album_id=2,
                      artist=u'Antonín Dvořák')
        self.add_item(title=u'without accents', artist=u'Antonín Dvorak')
        self.add_item(title=u'with umlaut', album_id=2, artist=u'Brüggen')
        self.add_item(title=u'without umlaut or e', artist=u'Bruggen')
        self.add_item(title=u'without umlaut with e', artist=u'Brueggen')
Пример #18
0
    def setUp(self):

        super(WebPluginTest, self).setUp()
        self.log = logging.getLogger('beets.web')

        if platform.system() == 'Windows':
            self.path_prefix = u'C:'
        else:
            self.path_prefix = u''

        # Add fixtures
        for track in self.lib.items():
            track.remove()

        # Add library elements. Note that self.lib.add overrides any "id=<n>"
        # and assigns the next free id number.
        # The following adds will create items #1, #2 and #3
        path1 = self.path_prefix + os.sep + \
            os.path.join(b'path_1').decode('utf-8')
        self.lib.add(Item(title=u'title',
                          path=path1,
                          album_id=2,
                          artist='AAA Singers'))
        path2 = self.path_prefix + os.sep + \
            os.path.join(b'somewhere', b'a').decode('utf-8')
        self.lib.add(Item(title=u'another title',
                          path=path2,
                          artist='AAA Singers'))
        path3 = self.path_prefix + os.sep + \
            os.path.join(b'somewhere', b'abc').decode('utf-8')
        self.lib.add(Item(title=u'and a third',
                          testattr='ABC',
                          path=path3,
                          album_id=2))
        # The following adds will create albums #1 and #2
        self.lib.add(Album(album=u'album',
                           albumtest='xyz'))
        path4 = self.path_prefix + os.sep + \
            os.path.join(b'somewhere2', b'art_path_2').decode('utf-8')
        self.lib.add(Album(album=u'other album',
                           artpath=path4))

        web.app.config['TESTING'] = True
        web.app.config['lib'] = self.lib
        web.app.config['INCLUDE_PATHS'] = False
        web.app.config['READONLY'] = True
        self.client = web.app.test_client()
Пример #19
0
class IHatePlugin(BeetsPlugin):
    _log = logging.getLogger('beets')

    def __init__(self):
        super(IHatePlugin, self).__init__()
        self.register_listener('import_task_choice',
                               self.import_task_choice_event)
        self.config.add({
            'warn': [],
            'skip': [],
        })

    @classmethod
    def do_i_hate_this(cls, task, action_patterns):
        """Process group of patterns (warn or skip) and returns True if
        task is hated and not whitelisted.
        """
        if action_patterns:
            for query_string in action_patterns:
                query, _ = parse_query_string(
                    query_string,
                    Album if task.is_album else Item,
                )
                if any(query.match(item) for item in task.imported_items()):
                    return True
        return False

    def import_task_choice_event(self, session, task):
        skip_queries = self.config['skip'].as_str_seq()
        warn_queries = self.config['warn'].as_str_seq()

        if task.choice_flag == action.APPLY:
            if skip_queries or warn_queries:
                self._log.debug(u'[ihate] processing your hate')
                if self.do_i_hate_this(task, skip_queries):
                    task.choice_flag = action.SKIP
                    self._log.info(u'[ihate] skipped: {0}', summary(task))
                    return
                if self.do_i_hate_this(task, warn_queries):
                    self._log.info(u'[ihate] you maybe hate this: {0}',
                                   summary(task))
            else:
                self._log.debug(u'[ihate] nothing to do')
        else:
            self._log.debug(u'[ihate] user made a decision, nothing to do')
Пример #20
0
    def test_root_logger_levels(self):
        """Root logger level should be shared between threads.
        """
        self.config['threaded'] = True

        blog.getLogger('beets').set_global_level(blog.WARNING)
        with helper.capture_log() as logs:
            importer = self.create_importer()
            importer.run()
        self.assertEqual(logs, [])

        blog.getLogger('beets').set_global_level(blog.INFO)
        with helper.capture_log() as logs:
            importer = self.create_importer()
            importer.run()
        for l in logs:
            self.assertIn(u"import", l)
            self.assertIn(u"album", l)

        blog.getLogger('beets').set_global_level(blog.DEBUG)
        with helper.capture_log() as logs:
            importer = self.create_importer()
            importer.run()
        self.assertIn(u"Sending event: database_change", logs)
Пример #21
0
    def test_root_logger_levels(self):
        """Root logger level should be shared between threads.
        """
        self.config['threaded'] = True

        blog.getLogger('beets').set_global_level(blog.WARNING)
        with helper.capture_log() as logs:
            importer = self.create_importer()
            importer.run()
        self.assertEqual(logs, [])

        blog.getLogger('beets').set_global_level(blog.INFO)
        with helper.capture_log() as logs:
            importer = self.create_importer()
            importer.run()
        for l in logs:
            self.assertIn(u"import", l)
            self.assertIn(u"album", l)

        blog.getLogger('beets').set_global_level(blog.DEBUG)
        with helper.capture_log() as logs:
            importer = self.create_importer()
            importer.run()
        self.assertIn(u"Sending event: database_change", logs)
Пример #22
0
from beets import logging
from beets.plugins import BeetsPlugin
from musicbrainzngs.musicbrainz import get_artist_by_id

log = logging.getLogger('beets.artistcountry')

class ArtistCountryPlugin(BeetsPlugin):
    pass

def memoize_artist(f):
    cache = {}
    def memf(item):
        artist_id = item['mb_artistid']
        if artist_id not in cache:
            cache[artist_id] = f(item)
        return cache[artist_id]
    return memf

@ArtistCountryPlugin.template_field('artist_country')
@memoize_artist
def _tmpl_artist_country(item):
    artist_fields = get_artist_by_id(item['mb_artistid'])
    artist_country = artist_fields['artist'].get('country', '')
    if not artist_country:
        log.debug('No country found for: %s' % artist_fields['artist']['name'])
        return ''
    return artist_country
Пример #23
0
from beets.autotag.hooks import AlbumInfo, TrackInfo, Distance
from beets.plugins import BeetsPlugin
from beets.util import confit
from discogs_client import Release, Client
from discogs_client.exceptions import DiscogsAPIError
from requests.exceptions import ConnectionError
from six.moves import http_client
import beets
import re
import time
import json
import socket
import os

# Silence spurious INFO log lines generated by urllib3.
urllib3_logger = logging.getLogger('requests.packages.urllib3')
urllib3_logger.setLevel(logging.CRITICAL)

USER_AGENT = u'beets/{0} +http://beets.io/'.format(beets.__version__)

# Exceptions that discogs_client should really handle but does not.
CONNECTION_ERRORS = (
    ConnectionError,
    socket.error,
    http_client.HTTPException,
    ValueError,  # JSON decoding raises a ValueError.
    DiscogsAPIError)


class DiscogsPlugin(BeetsPlugin):
    def __init__(self):
Пример #24
0
from pkg_resources import parse_version

from mock import patch

import beets
from beets import logging
from beets import plugins
from beets import ui
from beets import util
from beets.library import Item
from beets.util import syspath, bytestring_path

from beetsplug import alternatives
from beetsplug import convert

logging.getLogger('beets').propagate = True

if parse_version(beets.__version__) < parse_version("1.4.6"):

    def _move_item(item):
        item.move(copy=True)
else:
    from beets.util import MoveOperation

    def _move_item(item):
        item.move(operation=MoveOperation.COPY)


class LogCapture(logging.Handler):
    def __init__(self):
        super(LogCapture, self).__init__()
Пример #25
0
from __future__ import print_function

from beets.plugins import BeetsPlugin
from beets.ui import Subcommand
from beets import logging
from beets import ui
from beets import config
import musicbrainzngs

import re

SUBMISSION_CHUNK_SIZE = 200
UUID_REGEX = r'^[a-f0-9]{8}(-[a-f0-9]{4}){3}-[a-f0-9]{12}$'

log = logging.getLogger('beets.bpd')


def mb_call(func, *args, **kwargs):
    """Call a MusicBrainz API function and catch exceptions.
    """
    try:
        return func(*args, **kwargs)
    except musicbrainzngs.AuthenticationError:
        raise ui.UserError('authentication with MusicBrainz failed')
    except (musicbrainzngs.ResponseError, musicbrainzngs.NetworkError) as exc:
        raise ui.UserError('MusicBrainz API error: {0}'.format(exc))
    except musicbrainzngs.UsageError:
        raise ui.UserError('MusicBrainz credentials missing')

Пример #26
0
from mock import patch

from test import _common
from test.helper import capture_log
from beetsplug import fetchart
from beets.autotag import AlbumInfo, AlbumMatch
from beets import config
from beets import library
from beets import importer
from beets import logging
from beets import util
from beets.util.artresizer import ArtResizer, WEBPROXY
import confuse


logger = logging.getLogger('beets.test_art')


class Settings():
    """Used to pass settings to the ArtSources when the plugin isn't fully
    instantiated.
    """
    def __init__(self, **kwargs):
        for k, v in kwargs.items():
            setattr(self, k, v)


class UseThePlugin(_common.TestCase):
    def setUp(self):
        super(UseThePlugin, self).setUp()
        self.plugin = fetchart.FetchArtPlugin()
Пример #27
0
VOLUME_MIN = 0
VOLUME_MAX = 100

SAFE_COMMANDS = (
    # Commands that are available when unauthenticated.
    u"close",
    u"commands",
    u"notcommands",
    u"password",
    u"ping",
)

ITEM_KEYS_WRITABLE = set(MediaFile.fields()).intersection(Item._fields.keys())

# Loggers.
log = logging.getLogger("beets.bpd")
global_log = logging.getLogger("beets")


# Gstreamer import error.
class NoGstreamerError(Exception):
    pass


# Error-handling, exceptions, parameter parsing.


class BPDError(Exception):
    """An error that should be exposed to the client to the BPD
    server.
    """
Пример #28
0
"""Adds Discogs album search support to the autotagger. Requires the
discogs-client library.
"""
from beets import logging
from beets.autotag.hooks import AlbumInfo, TrackInfo, Distance
from beets.plugins import BeetsPlugin
from beets.util import confit
from discogs_client import Release, Client
from discogs_client.exceptions import DiscogsAPIError
from requests.exceptions import ConnectionError
import beets
import re
import time
import json

log = logging.getLogger('beets')

# Silence spurious INFO log lines generated by urllib3.
urllib3_logger = logging.getLogger('requests.packages.urllib3')
urllib3_logger.setLevel(logging.CRITICAL)

USER_AGENT = 'beets/{0} +http://beets.radbox.org/'.format(beets.__version__)


class DiscogsPlugin(BeetsPlugin):

    def __init__(self):
        super(DiscogsPlugin, self).__init__()
        self.config.add({
            'apikey': 'rAzVUQYRaoFjeBjyWuWZ',
            'apisecret': 'plxtUTqoCzwxZpqdPysCwGuBSmZNdZVy',
Пример #29
0
)
from confuse import Subview, Dumper, LazyConfig, ConfigSource
from beetsplug import goingrunning
from beetsplug.goingrunning import common
from six import StringIO

# Values from about.py
PACKAGE_TITLE = common.plg_ns['__PACKAGE_TITLE__']
PACKAGE_NAME = common.plg_ns['__PACKAGE_NAME__']
PLUGIN_NAME = common.plg_ns['__PLUGIN_NAME__']
PLUGIN_ALIAS = common.plg_ns['__PLUGIN_ALIAS__']
PLUGIN_SHORT_DESCRIPTION = common.plg_ns['__PLUGIN_SHORT_DESCRIPTION__']
PLUGIN_VERSION = common.plg_ns['__version__']

_default_logger_name_ = 'beets.{plg}'.format(plg=PLUGIN_NAME)
logging.getLogger(_default_logger_name_).propagate = False


class LogCapture(logging.Handler):
    def __init__(self):
        super(LogCapture, self).__init__()
        self.messages = []

    def emit(self, record):
        self.messages.append(six.text_type(record.msg))


@contextmanager
def capture_log(logger=_default_logger_name_):
    """Capture Logger output
    >>> with capture_log() as logs:
Пример #30
0
import os.path
import threading
from argparse import ArgumentParser
from concurrent import futures

import beets
from beets import util, art, logging
from beets.plugins import BeetsPlugin
from beets.ui import Subcommand, get_path_formats, input_yn, UserError, print_
from beets.library import parse_query_string, Item
from beets.util import syspath, displayable_path, cpu_count, bytestring_path

from beetsplug import convert

log = logging.getLogger('beets.alternatives')


def get_unicode_config(config, key):
    ret = config[key].get(str)
    if type(ret) != unicode:
        ret = unicode(ret, 'utf8')
    return ret


class AlternativesPlugin(BeetsPlugin):

    def __init__(self):
        super(AlternativesPlugin, self).__init__()

    def commands(self):
Пример #31
0
# 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.
"""Creates freedesktop.org-compliant .directory files on an album level.
"""

from beets import logging
from beets.plugins import BeetsPlugin
from beets.ui import Subcommand
from beets.ui import decargs

import os

log = logging.getLogger('beets.freedesktop')


def process_query(lib, opts, args):
    for album in lib.albums(decargs(args)):
        process_album(album)


def process_album(album):
    albumpath = album.item_dir()
    if album.artpath:
        fullartpath = album.artpath
        artfile = os.path.split(fullartpath)[1]
        create_file(albumpath, artfile)
    else:
        log.debug(u'freedesktop: album has no art')
Пример #32
0
 def setUp(self):
     self.item = _common.item()
     self.log = logging.getLogger('beets.embedart')
     self.artresizer = DummyArtResizer()
Пример #33
0
 def setUp(self):
     self.item = _common.item()
     self.log = logging.getLogger('beets.embedart')
Пример #34
0
import os.path
import threading
from argparse import ArgumentParser
from concurrent import futures

import beets
from beets import util, art, logging
from beets.plugins import BeetsPlugin
from beets.ui import Subcommand, get_path_formats, input_yn, UserError, print_
from beets.library import parse_query_string, Item
from beets.util import syspath, displayable_path, cpu_count, bytestring_path

from beetsplug import convert

log = logging.getLogger('beets.alternatives')


def get_unicode_config(config, key):
    ret = config[key].get(str)
    if type(ret) != unicode:
        ret = unicode(ret, 'utf8')
    return ret


class AlternativesPlugin(BeetsPlugin):
    def __init__(self):
        super(AlternativesPlugin, self).__init__()

    def commands(self):
        return [AlternativesCommand(self)]
Пример #35
0
 def test_art_file_missing(self):
     self.add_album_fixture()
     logging.getLogger('beets.embedart').setLevel(logging.DEBUG)
     with self.assertRaises(ui.UserError):
         self.run_command('embedart', '-f', '/doesnotexist')
Пример #36
0
# -*- coding: utf-8 -*-

from __future__ import division, absolute_import, print_function

import unittest

from datetime import datetime, timedelta
from freezegun import freeze_time
from dateutil import parser
import time
from ago import human
from tabulate import tabulate

from beets import logging

logging.getLogger('beets.radio-stream-settings').setLevel(logging.ERROR)

from beets.library import Item
from beetsplug.radio_stream import playlist_generator
from beetsplug.radio_stream.settings import Rules


class TestLib:
    def __init__(self, items):
        self._items = items

    def items(self, query):
        return self._items


class PlaylistGeneratorTest(unittest.TestCase):
Пример #37
0
from beets.util import bytestring_path, syspath, normpath, samefile
from beets.util.functemplate import Template
from beets import dbcore
from beets.dbcore import types
import beets

# To use the SQLite "blob" type, it doesn't suffice to provide a byte
# string; SQLite treats that as encoded text. Wrapping it in a `buffer` or a
# `memoryview`, depending on the Python version, tells it that we
# actually mean non-text data.
if six.PY2:
    BLOB_TYPE = buffer  # noqa: F821
else:
    BLOB_TYPE = memoryview

log = logging.getLogger("beets")


# Library-specific query types.


class PathQuery(dbcore.FieldQuery):
    """A query that matches all items under a given path.

    Matching can either be case-insensitive or case-sensitive. By
    default, the behavior depends on the OS: case-insensitive on Windows
    and case-sensitive otherwise.
    """

    def __init__(self, field, pattern, fast=True, case_sensitive=None):
        """Create a path query. `pattern` must be a path, either to a
Пример #38
0
 def setUp(self):
     self.item = _common.item()
     self.log = logging.getLogger('beets.embedart')
Пример #39
0
from mock import patch

import beets
from beets import logging
from beets import plugins
from beets import ui
from beets import util
from beets.library import Item
from beets.util import syspath, bytestring_path

from beetsplug import alternatives
from beetsplug import convert


logging.getLogger('beets').propagate = True


if parse_version(beets.__version__) < parse_version("1.4.6"):
    def _move_item(item):
        item.move(copy=True)
else:
    from beets.util import MoveOperation

    def _move_item(item):
        item.move(operation=MoveOperation.COPY)


class LogCapture(logging.Handler):

    def __init__(self):
Пример #40
0
                        unicode_literals)

import os
from test import _common
import sys
import re

from mock import MagicMock

from test._common import unittest
from beetsplug import lyrics
from beets.library import Item
from beets.util import confit
from beets import logging

log = logging.getLogger('beets.test_lyrics')
raw_backend = lyrics.Backend({}, log)
google = lyrics.Google(MagicMock(), log)


class LyricsPluginTest(unittest.TestCase):
    def setUp(self):
        """Set up configuration"""
        lyrics.LyricsPlugin()

    def test_search_artist(self):
        item = Item(artist='Alice ft. Bob', title='song')
        self.assertIn(('Alice ft. Bob', ['song']),
                      lyrics.search_pairs(item))
        self.assertIn(('Alice', ['song']),
                      lyrics.search_pairs(item))
Пример #41
0
from __future__ import division, absolute_import, print_function, unicode_literals

import os
from test import _common
import sys
import re

from mock import MagicMock

from test._common import unittest
from beetsplug import lyrics
from beets.library import Item
from beets.util import confit
from beets import logging

log = logging.getLogger("beets.test_lyrics")
raw_backend = lyrics.Backend({}, log)
google = lyrics.Google(MagicMock(), log)


class LyricsPluginTest(unittest.TestCase):
    def setUp(self):
        """Set up configuration"""
        lyrics.LyricsPlugin()

    def test_search_artist(self):
        item = Item(artist="Alice ft. Bob", title="song")
        self.assertIn(("Alice ft. Bob", ["song"]), lyrics.search_pairs(item))
        self.assertIn(("Alice", ["song"]), lyrics.search_pairs(item))

        item = Item(artist="Alice feat Bob", title="song")
Пример #42
0
from __future__ import print_function

from beets.plugins import BeetsPlugin
from beets.ui import Subcommand
from beets import logging
from beets import ui
from beets import config
import musicbrainzngs

import re

SUBMISSION_CHUNK_SIZE = 200
UUID_REGEX = r'^[a-f0-9]{8}(-[a-f0-9]{4}){3}-[a-f0-9]{12}$'

log = logging.getLogger('beets.bpd')


def mb_call(func, *args, **kwargs):
    """Call a MusicBrainz API function and catch exceptions.
    """
    try:
        return func(*args, **kwargs)
    except musicbrainzngs.AuthenticationError:
        raise ui.UserError('authentication with MusicBrainz failed')
    except (musicbrainzngs.ResponseError, musicbrainzngs.NetworkError) as exc:
        raise ui.UserError('MusicBrainz API error: {0}'.format(exc))
    except musicbrainzngs.UsageError:
        raise ui.UserError('MusicBrainz credentials missing')

Пример #43
0
 def test_art_file_missing(self):
     self.add_album_fixture()
     logging.getLogger('beets.embedart').setLevel(logging.DEBUG)
     with self.assertRaises(ui.UserError):
         self.run_command('embedart', '-f', '/doesnotexist')
Пример #44
0
ERROR_UPDATE_ALREADY = 54
ERROR_PLAYER_SYNC = 55
ERROR_EXIST = 56

VOLUME_MIN = 0
VOLUME_MAX = 100

SAFE_COMMANDS = (
    # Commands that are available when unauthenticated.
    u'close', u'commands', u'notcommands', u'password', u'ping',
)

ITEM_KEYS_WRITABLE = set(MediaFile.fields()).intersection(Item._fields.keys())

# Loggers.
log = logging.getLogger('beets.bpd')
global_log = logging.getLogger('beets')


# Gstreamer import error.
class NoGstreamerError(Exception):
    pass


# Error-handling, exceptions, parameter parsing.

class BPDError(Exception):
    """An error that should be exposed to the client to the BPD
    server.
    """
    def __init__(self, code, message, cmd_name='', index=0):
Пример #45
0
import responses
from mock import patch

from test import _common
from test._common import unittest
from beetsplug import fetchart
from beets.autotag import AlbumInfo, AlbumMatch
from beets import library
from beets import importer
from beets import config
from beets import logging
from beets import util
from beets.util.artresizer import ArtResizer, WEBPROXY


logger = logging.getLogger('beets.test_art')


class UseThePlugin(_common.TestCase):
    def setUp(self):
        super(UseThePlugin, self).setUp()
        self.plugin = fetchart.FetchArtPlugin()


class FetchImageTest(UseThePlugin):
    @responses.activate
    def run(self, *args, **kwargs):
        super(FetchImageTest, self).run(*args, **kwargs)

    def mock_response(self, content_type):
        responses.add(responses.GET, 'http://example.com',
Пример #46
0
import os
import re
import six
import sys
import unittest

import confuse
from mock import MagicMock, patch

from beets import logging
from beets.library import Item
from beets.util import bytestring_path
from beetsplug import lyrics
from test import _common

log = logging.getLogger('beets.test_lyrics')
raw_backend = lyrics.Backend({}, log)
google = lyrics.Google(MagicMock(), log)
genius = lyrics.Genius(MagicMock(), log)


class LyricsPluginTest(unittest.TestCase):
    def setUp(self):
        """Set up configuration."""
        lyrics.LyricsPlugin()

    def test_search_artist(self):
        item = Item(artist='Alice ft. Bob', title='song')
        self.assertIn(('Alice ft. Bob', ['song']), lyrics.search_pairs(item))
        self.assertIn(('Alice', ['song']), lyrics.search_pairs(item))
Пример #47
0
# included in all copies or substantial portions of the Software.

import subprocess
import os
import collections
import itertools
import sys
import warnings

from beets import logging
from beets import ui
from beets.plugins import BeetsPlugin
from beets.util import syspath, command_output, displayable_path
from beets import config

log = logging.getLogger('beets.replaygain')


# Utilities.

class ReplayGainError(Exception):
    """Raised when a local (to a track or an album) error occurs in one
    of the backends.
    """


class FatalReplayGainError(Exception):
    """Raised when a fatal error occurs in one of the backends.
    """

Пример #48
0
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
"""Synchronize information from music player libraries
"""

from beets import ui, logging
from beets.plugins import BeetsPlugin
from beets.dbcore import types
from beets.library import DateType
from sys import modules
import inspect

# Loggers.
log = logging.getLogger('beets.metasync')


class MetaSyncPlugin(BeetsPlugin):

    item_types = {
        'amarok_rating': types.INTEGER,
        'amarok_score': types.FLOAT,
        'amarok_uid': types.STRING,
        'amarok_playcount': types.INTEGER,
        'amarok_firstplayed': DateType(),
        'amarok_lastplayed': DateType()
    }

    def __init__(self):
        super(MetaSyncPlugin, self).__init__()
Пример #49
0
VOLUME_MIN = 0
VOLUME_MAX = 100

SAFE_COMMANDS = (
    # Commands that are available when unauthenticated.
    u'close',
    u'commands',
    u'notcommands',
    u'password',
    u'ping',
)

ITEM_KEYS_WRITABLE = set(MediaFile.fields()).intersection(Item._fields.keys())

# Loggers.
log = logging.getLogger('beets.bpd')
global_log = logging.getLogger('beets')


# Gstreamer import error.
class NoGstreamerError(Exception):
    pass


# Error-handling, exceptions, parameter parsing.


class BPDError(Exception):
    """An error that should be exposed to the client to the BPD
    server.
    """
Пример #50
0
import sys
import traceback
from PyQt5.QtCore import QObject, QThreadPool, QRunnable
from PyQt5.QtCore import pyqtSignal, pyqtSlot, pyqtProperty, QUrl
from beets.ui import UserError  # TODO Change to own error type
from beets import config, logging
from importer import TurnipImporter
from importadapter import ImportAdapter
from beet import BeetsFacade
from models import Item, ImportEvent, UserAction, ActionType, EventType

logger = logging.getLogger("turnip")
# logging.debug("")  # A hack to force log level
# logger.setLevel(logging.DEBUG)


class ImportHandler(QObject):
    """
    Responsible for updating the UI and responding to user input
    and communicating back and forth with `TurnipImportSession`.
    """

    _current_item: Item
    _is_busy = False

    def __init__(self, beets: BeetsFacade, adapter: ImportAdapter):
        QObject.__init__(self)
        self._threadpool = QThreadPool()
        self._lib = beets.lib()
        self.adapter = adapter
        self.adapter.on_event(self.handle_event)
Пример #51
0
# -*- coding: utf-8 -*-

from __future__ import division, absolute_import, print_function

import unittest

from datetime import datetime, timedelta
from freezegun import freeze_time
from dateutil import parser
import time
from ago import human
from tabulate import tabulate

from beets import logging

logging.getLogger('beets.radio-stream-settings').setLevel(logging.ERROR)

from beets.library import Item
from beetsplug.radio_stream import playlist_generator
from beetsplug.radio_stream.settings import Rules


class TestLib:
    def __init__(self, items):
        self._items = items

    def items(self, query):
        return self._items


class PlaylistGeneratorTest(unittest.TestCase):
Пример #52
0
from mock import patch

from test import _common
from test._common import unittest
from beetsplug import fetchart
from beets.autotag import AlbumInfo, AlbumMatch
from beets import config
from beets import library
from beets import importer
from beets import logging
from beets import util
from beets.util.artresizer import ArtResizer, WEBPROXY
from beets.util import confit


logger = logging.getLogger("beets.test_art")


class UseThePlugin(_common.TestCase):
    def setUp(self):
        super(UseThePlugin, self).setUp()
        self.plugin = fetchart.FetchArtPlugin()


class FetchImageHelper(_common.TestCase):
    """Helper mixin for mocking requests when fetching images
    with remote art sources.
    """

    @responses.activate
    def run(self, *args, **kwargs):
Пример #53
0
"""Glue between metadata sources and the matching logic."""
from __future__ import (division, absolute_import, print_function,
                        unicode_literals)

from collections import namedtuple
import re

from beets import logging
from beets import plugins
from beets import config
from beets.autotag import mb
from jellyfish import levenshtein_distance
from unidecode import unidecode

log = logging.getLogger('beets')


# Classes used to represent candidate options.

class AlbumInfo(object):
    """Describes a canonical release that may be used to match a release
    in the library. Consists of these data members:

    - ``album``: the release title
    - ``album_id``: MusicBrainz ID; UUID fragment only
    - ``artist``: name of the release's primary artist
    - ``artist_id``
    - ``tracks``: list of TrackInfo objects making up the release
    - ``asin``: Amazon ASIN
    - ``albumtype``: string describing the kind of release
Пример #54
0
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.

"""Synchronize information from music player libraries
"""

from beets import ui, logging
from beets.plugins import BeetsPlugin
from beets.dbcore import types
from beets.library import DateType
from sys import modules
import inspect

# Loggers.
log = logging.getLogger('beets.metasync')


class MetaSyncPlugin(BeetsPlugin):

    item_types = {
        'amarok_rating':      types.INTEGER,
        'amarok_score':       types.FLOAT,
        'amarok_uid':         types.STRING,
        'amarok_playcount':   types.INTEGER,
        'amarok_firstplayed': DateType(),
        'amarok_lastplayed':  DateType()
    }

    def __init__(self):
        super(MetaSyncPlugin, self).__init__()