/usr/lib/python2.7/dist-packages/eyed3/plugins/__init__.py is in python-eyed3 0.7.10-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 | # -*- coding: utf-8 -*-
################################################################################
# Copyright (C) 2012 Travis Shirk <travis@pobox.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, see <http://www.gnu.org/licenses/>.
#
################################################################################
from __future__ import print_function
import os, sys, types
try:
from collections import OrderedDict
except ImportError:
from ordereddict import OrderedDict
from eyed3 import core, utils
from eyed3.utils import guessMimetype
from eyed3.utils.console import printMsg, printError
_PLUGINS = {}
from ..utils.log import getLogger
log = getLogger(__name__)
def load(name=None, reload=False, paths=None):
'''Returns the eyed3.plugins.Plugin *class* identified by ``name``.
If ``name`` is ``None`` then the full list of plugins is returned.
Once a plugin is loaded its class object is cached, and future calls to
this function will returned the cached version. Use ``reload=True`` to
refresh the cache.'''
global _PLUGINS
if len(list(_PLUGINS.keys())) and not reload:
# Return from the cache if possible
try:
return _PLUGINS[name] if name else _PLUGINS
except KeyError:
# It's not in the cache, look again and refresh cash
_PLUGINS = {}
else:
_PLUGINS = {}
def _isValidModule(f, d):
'''Determine if file ``f`` is a valid module file name.'''
# 1) tis a file
# 2) does not start with '_', or '.'
# 3) avoid the .pyc dup
return bool(os.path.isfile(os.path.join(d, f))
and f[0] not in ('_', '.')
and f.endswith(".py"))
log.debug("Extra plugin paths: %s" % paths)
for d in [os.path.dirname(__file__)] + (paths if paths else []):
log.debug("Searching '%s' for plugins", d)
if not os.path.isdir(d):
continue
if d not in sys.path:
sys.path.append(d)
try:
for f in os.listdir(d):
if not _isValidModule(f, d):
continue
mod_name = os.path.splitext(f)[0]
try:
mod = __import__(mod_name, globals=globals(),
locals=locals())
except ImportError as ex:
log.warning("Plugin '%s' requires packages that are not "
"installed: %s" % ((f, d), ex))
continue
except Exception as ex:
log.exception("Bad plugin '%s'", (f, d))
continue
for attr in [getattr(mod, a) for a in dir(mod)]:
if (type(attr) == type and issubclass(attr, Plugin)):
# This is a eyed3.plugins.Plugin
PluginClass = attr
if (PluginClass not in list(_PLUGINS.values()) and
len(PluginClass.NAMES)):
log.debug("loading plugin '%s' from '%s%s%s'",
mod, d, os.path.sep, f)
# Setting the main name outside the loop to ensure
# there is at least one, otherwise a KeyError is
# thrown.
main_name = PluginClass.NAMES[0]
_PLUGINS[main_name] = PluginClass
for alias in PluginClass.NAMES[1:]:
# Add alternate names
_PLUGINS[alias] = PluginClass
# If 'plugin' is found return it immediately
if name and name in PluginClass.NAMES:
return PluginClass
finally:
if d in sys.path:
sys.path.remove(d)
log.debug("Plugins loaded: %s", _PLUGINS)
if name:
# If a specific plugin was requested and we've not returned yet...
return None
return _PLUGINS
class Plugin(utils.FileHandler):
'''Base class for all eyeD3 plugins'''
SUMMARY = u"eyeD3 plugin"
'''One line about the plugin'''
DESCRIPTION = u""
'''Detailed info about the plugin'''
NAMES = []
'''A list of **at least** one name for invoking the plugin, values [1:]
are treated as alias'''
def __init__(self, arg_parser):
self.arg_parser = arg_parser
self.arg_group = arg_parser.add_argument_group("Plugin options",
"%s\n%s" % (self.SUMMARY,
self.DESCRIPTION))
def start(self, args, config):
'''Called after command line parsing but before any paths are
processed. The ``self.args`` argument (the parsed command line) and
``self.config`` (the user config, if any) is set here.'''
self.args = args
self.config = config
def handleFile(self, f):
pass
def handleDone(self):
'''Called after all file/directory processing; before program exit.
The return value is passed to sys.exit (None results in 0).'''
pass
class LoaderPlugin(Plugin):
'''A base class that provides auto loading of audio files'''
def __init__(self, arg_parser, cache_files=False, track_images=False):
'''Constructor. If ``cache_files`` is True (off by default) then each
AudioFile is appended to ``_file_cache`` during ``handleFile`` and
the list is cleared by ``handleDirectory``.'''
super(LoaderPlugin, self).__init__(arg_parser)
self._num_loaded = 0
self._file_cache = [] if cache_files else None
self._dir_images = [] if track_images else None
def handleFile(self, f, *args, **kwargs):
'''Loads ``f`` and sets ``self.audio_file`` to an instance of
:class:`eyed3.core.AudioFile` or ``None`` if an error occurred or the
file is not a recognized type.
The ``*args`` and ``**kwargs`` are passed to :func:`eyed3.core.load`.
'''
self.audio_file = None
try:
self.audio_file = core.load(f, *args, **kwargs)
except NotImplementedError as ex:
# Frame decryption, for instance...
printError(str(ex))
return
if self.audio_file:
self._num_loaded += 1
if self._file_cache is not None:
self._file_cache.append(self.audio_file)
elif self._dir_images is not None:
mt = guessMimetype(f)
if mt and mt.startswith("image/"):
self._dir_images.append(f)
def handleDirectory(self, d, _):
'''Override to make use of ``self._file_cache``. By default the list
is cleared, subclasses should consider doing the same otherwise every
AudioFile will be cached.'''
if self._file_cache is not None:
self._file_cache = []
if self._dir_images is not None:
self._dir_images = []
def handleDone(self):
'''If no audio files were loaded this simply prints "Nothing to do".'''
if self._num_loaded == 0:
printMsg("Nothing to do")
|