From 22d5e564c617c7bae4ae371e8f075667c103232e Mon Sep 17 00:00:00 2001 From: Adrian Sampson Date: Mon, 16 Sep 2013 22:12:26 -0700 Subject: [PATCH] move `move` method to model objects --- beets/importer.py | 8 ++-- beets/library.py | 96 +++++++++++++++++++++---------------------- beets/ui/commands.py | 12 ++---- beetsplug/mbsync.py | 2 +- test/test_files.py | 42 +++++++++---------- test/test_importer.py | 2 +- test/test_ui.py | 11 +++-- 7 files changed, 85 insertions(+), 88 deletions(-) diff --git a/beets/importer.py b/beets/importer.py index ecffa9932..d24956a38 100644 --- a/beets/importer.py +++ b/beets/importer.py @@ -844,7 +844,7 @@ def manipulate_files(session): if config['import']['move']: # Just move the file. old_path = item.path - session.lib.move(item, False) + item.move(False) task.prune(old_path) elif config['import']['copy']: # If it's a reimport, move in-library files and copy @@ -855,16 +855,16 @@ def manipulate_files(session): # This is a reimport. Move in-library files and copy # out-of-library files. if session.lib.directory in util.ancestry(old_path): - session.lib.move(item, False) + item.move(False) # We moved the item, so remove the # now-nonexistent file from old_paths. task.old_paths.remove(old_path) else: - session.lib.move(item, True) + item.move(True) else: # A normal import. Just copy files and keep track of # old paths. - session.lib.move(item, True) + item.move(True) if config['import']['write'] and task.should_write_tags(): item.write() diff --git a/beets/library.py b/beets/library.py index ad1c7367e..d98583262 100644 --- a/beets/library.py +++ b/beets/library.py @@ -533,7 +533,7 @@ class Item(LibModel): # Files themselves. - def move(self, dest, copy=False): + def move_file(self, dest, copy=False): """Moves or copies the item's file, updating the path value if the move succeeds. If a file exists at ``dest``, then it is slightly modified to be unique. @@ -556,6 +556,9 @@ class Item(LibModel): """ return int(os.path.getmtime(syspath(self.path))) + + # Model methods. + def remove(self, delete=False, with_album=True): """Removes the item. If `delete`, then the associated file is removed from disk. If `with_album`, then the item's album (if @@ -576,6 +579,48 @@ class Item(LibModel): self._lib._memotable = {} + def move(self, copy=False, basedir=None, with_album=True): + """Move the item to its designated location within the library + directory (provided by destination()). Subdirectories are + created as needed. If the operation succeeds, the item's path + field is updated to reflect the new location. + + If copy is True, moving the file is copied rather than moved. + + basedir overrides the library base directory for the + destination. + + If the item is in an album, the album is given an opportunity to + move its art. (This can be disabled by passing + with_album=False.) + + The item is stored to the database if it is in the database, so + any dirty fields prior to the move() call will be written as a + side effect. You probably want to call save() to commit the DB + transaction. + """ + self._check_db() + dest = self._lib.destination(self, basedir=basedir) + + # Create necessary ancestry for the move. + util.mkdirall(dest) + + # Perform the move and store the change. + old_path = self.path + self.move_file(dest, copy) + self.store() + + # If this item is in an album, move its art. + if with_album: + album = self._lib.get_album(self) + if album: + album.move_art(copy) + album.store() + + # Prune vacated directory. + if not copy: + util.prune_dirs(os.path.dirname(old_path), self._lib.directory) + # Templating. @@ -730,7 +775,7 @@ class Album(LibModel): # Move items. items = list(self.items()) for item in items: - self._lib.move(item, copy, basedir=basedir, with_album=False) + item.move(copy, basedir=basedir, with_album=False) # Move art. self.move_art(copy) @@ -1658,15 +1703,13 @@ class Library(object): # Adding objects to the database. - def add(self, item, copy=False): + def add(self, item): """Add the item as a new object to the library database. The id field will be updated; the new id is returned. If copy, then each item is copied to the destination location before it is added. """ item.added = time.time() - if copy: - self.move(item, copy=True) if not item._lib: item._lib = self @@ -1734,49 +1777,6 @@ class Library(object): album = Album(self, **album_values) return album - def move(self, item, copy=False, basedir=None, - with_album=True): - """Move the item to its designated location within the library - directory (provided by destination()). Subdirectories are - created as needed. If the operation succeeds, the item's path - field is updated to reflect the new location. - - If copy is True, moving the file is copied rather than moved. - - basedir overrides the library base directory for the - destination. - - If the item is in an album, the album is given an opportunity to - move its art. (This can be disabled by passing - with_album=False.) - - The item is stored to the database if it is in the database, so - any dirty fields prior to the move() call will be written as a - side effect. You probably want to call save() to commit the DB - transaction. - """ - dest = self.destination(item, basedir=basedir) - - # Create necessary ancestry for the move. - util.mkdirall(dest) - - # Perform the move and store the change. - old_path = item.path - item.move(dest, copy) - if item.id is not None: - item.store() - - # If this item is in an album, move its art. - if with_album: - album = self.get_album(item) - if album: - album.move_art(copy) - album.store() - - # Prune vacated directory. - if not copy: - util.prune_dirs(os.path.dirname(old_path), self.directory) - # Querying. diff --git a/beets/ui/commands.py b/beets/ui/commands.py index c72ebf73f..276198d10 100644 --- a/beets/ui/commands.py +++ b/beets/ui/commands.py @@ -939,7 +939,7 @@ def update_items(lib, query, album, move, pretend): # Move the item if it's in the library. if move and lib.directory in ancestry(item.path): - lib.move(item) + item.move() item.store() affected_albums.add(item.album_id) @@ -1154,10 +1154,7 @@ def modify_items(lib, mods, query, write, move, album, confirm): cur_path = obj.item_dir() if album else obj.path if lib.directory in ancestry(cur_path): # In library? log.debug('moving object %s' % cur_path) - if album: - obj.move() - else: - lib.move(obj) + obj.move() obj.store() @@ -1212,10 +1209,7 @@ def move_items(lib, dest, query, copy, album): old_path = obj.item_dir() if album else obj.path logging.debug('moving: %s' % old_path) - if album: - obj.move(copy, basedir=dest) - else: - lib.move(obj, copy, basedir=dest) + obj.move(copy, basedir=dest) obj.store() move_cmd = ui.Subcommand('move', diff --git a/beetsplug/mbsync.py b/beetsplug/mbsync.py index ab9c14dc8..dc566ab9e 100644 --- a/beetsplug/mbsync.py +++ b/beetsplug/mbsync.py @@ -44,7 +44,7 @@ def _print_and_apply_changes(lib, item, old_data, move, pretend, write): if not pretend: # Move the item if it's in the library. if move and lib.directory in util.ancestry(item.path): - lib.move(item, with_album=False) + item.move(with_album=False) if write: try: diff --git a/test/test_files.py b/test/test_files.py index f97247c0a..1727f3392 100644 --- a/test/test_files.py +++ b/test/test_files.py @@ -52,49 +52,49 @@ class MoveTest(_common.TestCase): self.otherdir = join(self.temp_dir, 'testotherdir') def test_move_arrives(self): - self.lib.move(self.i) + self.i.move() self.assertExists(self.dest) def test_move_to_custom_dir(self): - self.lib.move(self.i, basedir=self.otherdir) + self.i.move(basedir=self.otherdir) self.assertExists(join(self.otherdir, 'one', 'two', 'three.mp3')) def test_move_departs(self): - self.lib.move(self.i) + self.i.move() self.assertNotExists(self.path) def test_move_in_lib_prunes_empty_dir(self): - self.lib.move(self.i) + self.i.move() old_path = self.i.path self.assertExists(old_path) self.i.artist = 'newArtist' - self.lib.move(self.i) + self.i.move() self.assertNotExists(old_path) self.assertNotExists(os.path.dirname(old_path)) def test_copy_arrives(self): - self.lib.move(self.i, copy=True) + self.i.move(copy=True) self.assertExists(self.dest) def test_copy_does_not_depart(self): - self.lib.move(self.i, copy=True) + self.i.move(copy=True) self.assertExists(self.path) def test_move_changes_path(self): - self.lib.move(self.i) + self.i.move() self.assertEqual(self.i.path, util.normpath(self.dest)) def test_copy_already_at_destination(self): - self.lib.move(self.i) + self.i.move() old_path = self.i.path - self.lib.move(self.i, copy=True) + self.i.move(copy=True) self.assertEqual(self.i.path, old_path) def test_move_already_at_destination(self): - self.lib.move(self.i) + self.i.move() old_path = self.i.path - self.lib.move(self.i, copy=False) + self.i.move(copy=False) self.assertEqual(self.i.path, old_path) def test_read_only_file_copied_writable(self): @@ -102,7 +102,7 @@ class MoveTest(_common.TestCase): os.chmod(self.path, 0444) try: - self.lib.move(self.i, copy=True) + self.i.move(copy=True) self.assertTrue(os.access(self.i.path, os.W_OK)) finally: # Make everything writable so it can be cleaned up. @@ -115,7 +115,7 @@ class MoveTest(_common.TestCase): os.makedirs(os.path.dirname(dest)) touch(dest) - self.lib.move(self.i) + self.i.move() self.assertNotEqual(self.i.path, dest) self.assertEqual(os.path.dirname(self.i.path), os.path.dirname(dest)) @@ -262,7 +262,7 @@ class ArtFileTest(_common.TestCase): i2.path = self.i.path i2.artist = 'someArtist' ai = self.lib.add_album((i2,)) - self.lib.move(i2, True) + i2.move(True) self.assertEqual(ai.artpath, None) ai.set_art(newart) @@ -278,7 +278,7 @@ class ArtFileTest(_common.TestCase): i2.path = self.i.path i2.artist = 'someArtist' ai = self.lib.add_album((i2,)) - self.lib.move(i2, True) + i2.move(True) ai.set_art(newart) # Set the art again. @@ -292,7 +292,7 @@ class ArtFileTest(_common.TestCase): i2.path = self.i.path i2.artist = 'someArtist' ai = self.lib.add_album((i2,)) - self.lib.move(i2, True) + i2.move(True) # Copy the art to the destination. artdest = ai.art_destination(newart) @@ -309,7 +309,7 @@ class ArtFileTest(_common.TestCase): i2.path = self.i.path i2.artist = 'someArtist' ai = self.lib.add_album((i2,)) - self.lib.move(i2, True) + i2.move(True) # Make a file at the destination. artdest = ai.art_destination(newart) @@ -333,7 +333,7 @@ class ArtFileTest(_common.TestCase): i2.path = self.i.path i2.artist = 'someArtist' ai = self.lib.add_album((i2,)) - self.lib.move(i2, True) + i2.move(True) ai.set_art(newart) mode = stat.S_IMODE(os.stat(ai.artpath).st_mode) @@ -351,7 +351,7 @@ class ArtFileTest(_common.TestCase): self.ai.album = 'different_album' self.ai.store() - self.lib.move(self.ai.items()[0]) + self.ai.items()[0].move() artpath = self.lib.albums()[0].artpath self.assertTrue('different_album' in artpath) @@ -368,7 +368,7 @@ class ArtFileTest(_common.TestCase): self.i.album = 'different_album' self.i.album_id = None # detach from album - self.lib.move(self.i) + self.i.move() artpath = self.lib.albums()[0].artpath self.assertFalse('different_album' in artpath) diff --git a/test/test_importer.py b/test/test_importer.py index 34a9e3f0e..6339c32ff 100644 --- a/test/test_importer.py +++ b/test/test_importer.py @@ -324,7 +324,7 @@ class ImportApplyTest(_common.TestCase): """It should be possible to "move" a file even when the file is already at the destination. """ - self.lib.move(self.i) # Already at destination. + self.i.move() # Already at destination. config['import']['move'] = True _call_stages(self.session, [self.i], self.info, toppath=self.srcdir, stages=[importer.manipulate_files]) diff --git a/test/test_ui.py b/test/test_ui.py index 868c4b6b3..1c024def3 100644 --- a/test/test_ui.py +++ b/test/test_ui.py @@ -124,7 +124,8 @@ class RemoveTest(_common.TestCase): # Copy a file into the library. self.lib = library.Library(':memory:', self.libdir) self.i = library.Item.from_path(os.path.join(_common.RSRC, 'full.mp3')) - self.lib.add(self.i, True) + self.lib.add(self.i) + self.i.move(True) def test_remove_items_no_delete(self): self.io.addinput('y') @@ -151,7 +152,8 @@ class ModifyTest(_common.TestCase): # Copy a file into the library. self.lib = library.Library(':memory:', self.libdir) self.i = library.Item.from_path(os.path.join(_common.RSRC, 'full.mp3')) - self.lib.add(self.i, True) + self.lib.add(self.i) + self.i.move(True) self.album = self.lib.add_album([self.i]) def _modify(self, mods, query=(), write=False, move=False, album=False): @@ -230,7 +232,7 @@ class MoveTest(_common.TestCase): # Add a file to the library but don't copy it in yet. self.lib = library.Library(':memory:', self.libdir) self.i = library.Item.from_path(self.itempath) - self.lib.add(self.i, False) + self.lib.add(self.i) self.album = self.lib.add_album([self.i]) # Alternate destination directory. @@ -292,7 +294,8 @@ class UpdateTest(_common.TestCase): # Copy a file into the library. self.lib = library.Library(':memory:', self.libdir) self.i = library.Item.from_path(os.path.join(_common.RSRC, 'full.mp3')) - self.lib.add(self.i, True) + self.lib.add(self.i) + self.i.move(True) self.album = self.lib.add_album([self.i]) # Album art.