local/docs: Update based on review comments

- Bunch of typos and wording improvements from review.
- Fixed mopidy.backends.local.scan botched merge.
- Document and enforce that sub-command name needs to be bytes.
This commit is contained in:
Thomas Adamcik 2013-11-09 18:20:22 +01:00
parent df953ea1e6
commit 4e6ebbe955
5 changed files with 39 additions and 32 deletions

View File

@ -25,8 +25,8 @@ v0.17.0 (UNRELEASED)
**Sub-commands**
- Swtiched to sub-commands for mopidy this implies the following changes
(fixes :issue:`437`):
- Switched to sub-commands for the ``mopidy`` command , this implies the
following changes (fixes :issue:`437`):
===================== =============
Old command New command

View File

@ -53,7 +53,7 @@ Options
.. cmdoption:: --config <file>
Specify config file to use. To use multiple config files, separate them
with colon. The later files override the earlier ones if there's a
with a colon. The later files override the earlier ones if there's a
conflict.
.. cmdoption:: -o <option>, --option <option>

View File

@ -43,7 +43,8 @@ def main():
for extension in installed_extensions:
for cls in extension.get_sub_commands():
cmd_parser = subparser.add_parser(cls.name, help=cls.help)
cmd_parser = subparser.add_parser(bytes(cls.name),
help=cls.help)
extension_sub_commands[cls.name] = (extension, cls(cmd_parser))
args = parser.parse_args(args=mopidy_args)
@ -58,13 +59,13 @@ def main():
enabled_extensions = []
for extension in installed_extensions:
if not ext.validate_extension(extension):
config[extension.ext_name] = {b'enabled': False}
config[extension.ext_name] = {'enabled': False}
config_errors[extension.ext_name] = {
b'enabled': b'extension disabled by self check.'}
'enabled': 'extension disabled by self check.'}
elif not config[extension.ext_name]['enabled']:
config[extension.ext_name] = {b'enabled': False}
config[extension.ext_name] = {'enabled': False}
config_errors[extension.ext_name] = {
b'enabled': b'extension disabled by user config.'}
'enabled': 'extension disabled by user config.'}
else:
enabled_extensions.append(extension)

View File

@ -289,9 +289,10 @@ class BaseSubCommandProvider(object):
"""
name = None
"""What the sub-command should be called. Will be run as ``mopidy NAME``
"""What the sub-command should be called. Will be run as ``mopidy NAME``.
Example: ``scan``
Will be converted to :type:`bytes` and should be limited to ASCII
characters. Example: ``scan``
"""
help = None
@ -306,7 +307,7 @@ class BaseSubCommandProvider(object):
*MUST be implemented by subclass.*
:param args: the argments object from argpase.
:param config: read only version of the mopidy config.
:param config: read-only version of the mopidy config.
:param extensions: list of enabled extensions.
:returns: integer exit value for the process.
"""

View File

@ -9,12 +9,14 @@ from mopidy.audio import scan
from mopidy.backends import base
from mopidy.utils import path
from . import translator
logger = logging.getLogger('mopidy.backends.local.scan')
class ScanSubCommand(base.BaseSubCommandProvider):
name = b'scan'
help = b'scan local media files'
name = 'scan'
help = 'scan local media files'
def run(self, args, config, extensions):
media_dir = config['local']['media_dir']
@ -28,49 +30,51 @@ class ScanSubCommand(base.BaseSubCommandProvider):
updaters[e.ext_name] = updater_class
if not updaters:
logging.error('No usable library updaters found.')
logger.error('No usable library updaters found.')
return 1
elif len(updaters) > 1:
logging.error('More than one library updater found. '
logger.error('More than one library updater found. '
'Provided by: %s', ', '.join(updaters.keys()))
return 1
local_updater = updaters.values()[0](config)
# TODO: cleanup to consistently use local urls, not a random mix of local
# and file uris depending on how the data was loaded.
uris_library = set()
uris_update = set()
uris_remove = set()
logging.info('Checking tracks from library.')
logger.info('Checking tracks from library.')
for track in local_updater.load():
try:
# TODO: convert local to file uri / path
stat = os.stat(path.uri_to_path(track.uri))
uri = translator.local_to_file_uri(track.uri, media_dir)
stat = os.stat(path.uri_to_path(uri))
if int(stat.st_mtime) > track.last_modified:
uris_update.add(track.uri)
uris_library.add(track.uri)
uris_update.add(uri)
uris_library.add(uri)
except OSError:
logging.debug('Missing file %s', track.uri)
logger.debug('Missing file %s', track.uri)
uris_remove.add(track.uri)
logging.info('Removing %d moved or deleted tracks.', len(uris_remove))
logger.info('Removing %d missing tracks.', len(uris_remove))
for uri in uris_remove:
local_updater.remove(uri)
logging.info('Checking %s for new or modified tracks.', media_dir)
for uri in path.find_uris(config['local']['media_dir']):
logger.info('Checking %s for unknown tracks.', media_dir)
for uri in path.find_uris(media_dir):
file_extension = os.path.splitext(path.uri_to_path(uri))[1]
if file_extension in excluded_file_extensions:
logging.debug('Skipped %s: File extension excluded.', uri)
logger.debug('Skipped %s: File extension excluded.', uri)
continue
if uri not in uris_library:
uris_update.add(uri)
logging.info('Found %d new or modified tracks.', len(uris_update))
logging.info('Scanning new and modified tracks.')
logger.info('Found %d unknown tracks.', len(uris_update))
logger.info('Scanning...')
scanner = scan.Scanner(scan_timeout)
scanner = scan.Scanner(config['local']['scan_timeout'])
progress = Progress(len(uris_update))
for uri in sorted(uris_update):
@ -78,17 +82,18 @@ class ScanSubCommand(base.BaseSubCommandProvider):
data = scanner.scan(uri)
track = scan.audio_data_to_track(data)
local_updater.add(track)
logging.debug('Added %s', track.uri)
logger.debug('Added %s', track.uri)
except exceptions.ScannerError as error:
logging.warning('Failed %s: %s', uri, error)
logger.warning('Failed %s: %s', uri, error)
progress.increment()
logging.info('Commiting changes.')
logger.info('Commiting changes.')
local_updater.commit()
return 0
# TODO: move to utils?
class Progress(object):
def __init__(self, total):
@ -101,5 +106,5 @@ class Progress(object):
if self.count % 1000 == 0 or self.count == self.total:
duration = time.time() - self.start
remainder = duration / self.count * (self.total - self.count)
logging.info('Scanned %d of %d files in %ds, ~%ds left.',
logger.info('Scanned %d of %d files in %ds, ~%ds left.',
self.count, self.total, duration, remainder)