diff --git a/beets/importer.py b/beets/importer.py index 556e05367..92d910acc 100644 --- a/beets/importer.py +++ b/beets/importer.py @@ -563,8 +563,7 @@ def read_tasks(session): for toppath in session.paths: # Check whether the path is to a file. - if config['import']['singletons'] and \ - not os.path.isdir(syspath(toppath)): + if not os.path.isdir(syspath(toppath)): try: item = library.Item.from_path(toppath) except mediafile.UnreadableFileError: @@ -572,7 +571,10 @@ def read_tasks(session): util.displayable_path(toppath) )) continue - yield ImportTask.item_task(item) + if config['import']['singletons']: + yield ImportTask.item_task(item) + else: + yield ImportTask(toppath, [toppath], [item]) continue # A flat album import merges all items into one album. diff --git a/beets/ui/commands.py b/beets/ui/commands.py index d45192be1..c466eb56a 100644 --- a/beets/ui/commands.py +++ b/beets/ui/commands.py @@ -746,12 +746,8 @@ def import_files(lib, paths, query): """ # Check the user-specified directories. for path in paths: - fullpath = syspath(normpath(path)) - if not config['import']['singletons'] and not os.path.isdir(fullpath): - raise ui.UserError(u'not a directory: {0}'.format( - displayable_path(path))) - elif config['import']['singletons'] and not os.path.exists(fullpath): - raise ui.UserError(u'no such file: {0}'.format( + if not os.path.exists(syspath(normpath(path))): + raise ui.UserError(u'no such file or directory: {0}'.format( displayable_path(path))) # Check parameter consistency. diff --git a/docs/changelog.rst b/docs/changelog.rst index aee77266d..3c5efd7d2 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -38,6 +38,8 @@ New stuff: * The performance of the autotagger's matching mechanism is vastly improved. This should be noticeable when matching against very large releases such as box sets. +* The :ref:`import-cmd` command can now accept individual files as arguments + even in non-singleton mode. Files are imported as one-track albums. Fixes: diff --git a/test/test_importer.py b/test/test_importer.py index 691fde4b9..06992c7d0 100644 --- a/test/test_importer.py +++ b/test/test_importer.py @@ -327,6 +327,7 @@ class ImportSingletonTest(_common.TestCase, ImportHelper): """Test ``APPLY`` and ``ASIS`` choices for an import session with singletons config set to True. """ + def setUp(self): super(ImportSingletonTest, self).setUp() self._setup_library() @@ -391,6 +392,26 @@ class ImportSingletonTest(_common.TestCase, ImportHelper): self.importer.run() self.assertEqual(len(self.lib.items()), 1) + def test_import_single_files(self): + resource_path = os.path.join(_common.RSRC, u'empty.mp3') + single_path = os.path.join(self.import_dir, u'track_2.mp3') + + shutil.copy(resource_path, single_path) + import_files = [ + os.path.join(self.import_dir, u'the_album'), + single_path + ] + self._setup_import_session(singletons = False) + self.importer.paths = import_files + + self.importer.add_choice(importer.action.ASIS) + self.importer.add_choice(importer.action.ASIS) + self.importer.run() + + self.assertEqual(len(self.lib.items()), 2) + self.assertEqual(len(self.lib.albums()), 2) + + class ImportTest(_common.TestCase, ImportHelper): """Test APPLY, ASIS and SKIP choices. """