diff --git a/beets/device.py b/beets/device.py index 73d98fe3f..efcf62b9b 100644 --- a/beets/device.py +++ b/beets/device.py @@ -20,6 +20,7 @@ FIELD_MAP = { class PodLibrary(BaseLibrary): def __init__(self, path): self.db = gpod.Database(path) + self.syncing = False @classmethod def by_name(cls, name): @@ -28,41 +29,40 @@ class PodLibrary(BaseLibrary): def _start_sync(self): # Make sure we have a version of libgpod with these # iPhone-specific functions. + if self.syncing: + return if hasattr(gpod, 'itdb_start_sync'): gpod.itdb_start_sync(self.db._itdb) + self.syncing = True def _stop_sync(self): + if not self.syncing: + return if hasattr(gpod, 'itdb_stop_sync'): gpod.itdb_stop_sync(self.db._itdb) + self.syncing = False - def add_items(self, items): + def add(self, item): self._start_sync() - try: - for item in items: - track = self.db.new_Track() - track['userdata'] = { - 'transferred': 0, - 'hostname': socket.gethostname(), - 'charset': locale.getpreferredencoding(), - 'pc_mtime': os.stat(item.path).st_mtime, - } - track._set_userdata_utf8('filename', item.path.encode()) - for dname, bname in FIELD_MAP.items(): - track[dname] = getattr(item, bname) - track['tracklen'] = int(item.length * 1000) - self.db.copy_delayed_files() - finally: - self.db.close() - self._stop_sync() - - def add(self, path): - raise NotImplementedError + track = self.db.new_Track() + track['userdata'] = { + 'transferred': 0, + 'hostname': socket.gethostname(), + 'charset': locale.getpreferredencoding(), + 'pc_mtime': os.stat(item.path).st_mtime, + } + track._set_userdata_utf8('filename', item.path.encode()) + for dname, bname in FIELD_MAP.items(): + track[dname] = getattr(item, bname) + track['tracklen'] = int(item.length * 1000) + self.db.copy_delayed_files() def get(self, query=None): raise NotImplementedError def save(self): - raise NotImplementedError + self._stop_sync() + gpod.itdb_write(self.pod._itdb, None) # Browsing convenience. def artists(self, query=None): diff --git a/beets/library.py b/beets/library.py index 5f59e4938..15d8882af 100644 --- a/beets/library.py +++ b/beets/library.py @@ -141,7 +141,18 @@ class Item(object): self.dirty = {} self._fill_record(values) self._clear_dirty() - + + @classmethod + def from_path(cls, path, library=None): + """Creates a new item from the media file at the specified path. Sets + the item's library (but does not add the item) if library is + specified. + """ + i = cls({}) + i.read(path) + i.library = library + return i + def _fill_record(self, values): self.record = {} for key in item_keys: @@ -156,8 +167,7 @@ class Item(object): self.dirty[key] = False def __repr__(self): - return 'Item(' + repr(self.record) + \ - ', library=' + repr(self.library) + ')' + return 'Item(' + repr(self.record) + ')' #### item field accessors #### @@ -283,28 +293,7 @@ class Item(object): # Either copying or moving succeeded, so update the stored path. self.path = dest - - def delete(self): - """Deletes the item from the filesystem. If the item is located - in the library directory, any empty parent directories are trimmed. - Also calls remove(), deleting the appropriate row from the database. - - As with move(), library.save() should almost certainly be called after - invoking this (although store() should not). - """ - os.unlink(self.path) - self.remove() - - @classmethod - def from_path(cls, path, library=None): - """Creates a new item from the media file at the specified path. Sets - the item's library (but does not add the item) if library is - specified. - """ - i = cls({}) - i.read(path) - i.library = library - return i + diff --git a/bts b/bts index 8b94ca60f..2915c09c4 100755 --- a/bts +++ b/bts @@ -188,8 +188,11 @@ class BeetsApp(cmdln.Cmdln): from beets import device pod = device.PodLibrary.by_name(name) - pod.add_items(items) + for item in items: + pod.add(item) + pod.save() if __name__ == '__main__': app = BeetsApp() sys.exit(app.main()) + diff --git a/test/test_files.py b/test/test_files.py index 19df33b04..e40ad5166 100755 --- a/test/test_files.py +++ b/test/test_files.py @@ -71,30 +71,6 @@ class MoveTest(unittest.TestCase): self.i.move() self.assertEqual(self.i.path, beets.library._normpath(self.dest)) -class DeleteTest(unittest.TestCase): - def setUp(self): - # make a temporary file - self.path = join('rsrc', 'temp.mp3') - shutil.copy(join('rsrc', 'full.mp3'), self.path) - - # add it to a temporary library - self.lib = beets.library.Library(':memory:') - self.i = beets.library.Item.from_path(self.path) - self.i.add(self.lib) - def tearDown(self): - # make sure the temp file is gone - if os.path.exists(self.path): - os.remove(self.path) - - def test_delete_deletes_file(self): - self.i.delete() - self.assertTrue(not os.path.exists(self.path)) - - def test_delete_removes_from_db(self): - self.i.delete() - c = self.lib.conn.execute('select * from items where 1') - self.assertEqual(c.fetchone(), None) - class WalkTest(unittest.TestCase): def setUp(self): # create a directory structure for testing