move move method to model objects

This commit is contained in:
Adrian Sampson 2013-09-16 22:12:26 -07:00
parent 76b1ee434e
commit 22d5e564c6
7 changed files with 85 additions and 88 deletions

View file

@ -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()

View file

@ -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.

View file

@ -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',

View file

@ -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:

View file

@ -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)

View file

@ -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])

View file

@ -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.