diff --git a/src/calibre/ebooks/metadata/opf2.py b/src/calibre/ebooks/metadata/opf2.py index f051ad8568..fbcbe533af 100644 --- a/src/calibre/ebooks/metadata/opf2.py +++ b/src/calibre/ebooks/metadata/opf2.py @@ -816,12 +816,13 @@ class OPF(object): return raw def smart_update(self, mi): - for attr in ('author_sort', 'title_sort', 'comments', 'category', + for attr in ('title', 'authors', 'author_sort', 'title_sort', 'publisher', 'series', 'series_index', 'rating', - 'isbn', 'language', 'tags', 'title', 'authors'): + 'isbn', 'language', 'tags', 'category', 'comments'): val = getattr(mi, attr, None) if val is not None and val != [] and val != (None, None): setattr(self, attr, val) + print self.render() class OPFCreator(MetaInformation): @@ -942,7 +943,7 @@ class OPFTest(unittest.TestCase): - A Cool & © ß Title + A Cool & © ß Title Monkey Kitchen, Next OneTwo 123456789 @@ -958,25 +959,39 @@ class OPFTest(unittest.TestCase): ) self.opf = OPF(self.stream, os.getcwd()) - def testReading(self): - opf = self.opf + def testReading(self, opf=None): + if opf is None: + opf = self.opf self.assertEqual(opf.title, u'A Cool & \xa9 \xdf Title') self.assertEqual(opf.authors, u'Monkey Kitchen,Next'.split(',')) self.assertEqual(opf.author_sort, 'Monkey') + self.assertEqual(opf.title_sort, 'Wow') self.assertEqual(opf.tags, ['One', 'Two']) self.assertEqual(opf.isbn, '123456789') self.assertEqual(opf.series, 'A one book series') - self.assertEqual(opf.series_index, None) + self.assertEqual(opf.series_index, 1) self.assertEqual(list(opf.itermanifest())[0].get('href'), 'a ~ b') def testWriting(self): for test in [('title', 'New & Title'), ('authors', ['One', 'Two']), ('author_sort', "Kitchen"), ('tags', ['Three']), - ('isbn', 'a'), ('rating', 3), ('series_index', 1)]: + ('isbn', 'a'), ('rating', 3), ('series_index', 1), + ('title_sort', 'ts')]: setattr(self.opf, *test) self.assertEqual(getattr(self.opf, test[0]), test[1]) self.opf.render() + + def testCreator(self): + opf = OPFCreator(os.getcwd(), self.opf) + buf = cStringIO.StringIO() + opf.render(buf) + raw = buf.getvalue() + self.testReading(opf=OPF(cStringIO.StringIO(raw), os.getcwd())) + + def testSmartUpdate(self): + self.opf.smart_update(self.opf) + self.testReading() def suite(): return unittest.TestLoader().loadTestsFromTestCase(OPFTest) diff --git a/src/calibre/library/database2.py b/src/calibre/library/database2.py index 90651b5481..209f700820 100644 --- a/src/calibre/library/database2.py +++ b/src/calibre/library/database2.py @@ -27,15 +27,6 @@ from calibre.customize.ui import run_plugins_on_import from calibre import sanitize_file_name copyfile = os.link if hasattr(os, 'link') else shutil.copyfile -iscaseinsensitive = iswindows or isosx - -def normpath(x): - # The builtin os.path.normcase doesn't work on OS X - x = os.path.abspath(x) - if iscaseinsensitive: - x = x.lower() - return x - FIELD_MAP = {'id':0, 'title':1, 'authors':2, 'publisher':3, 'rating':4, 'timestamp':5, 'size':6, 'tags':7, 'comments':8, 'series':9, 'series_index':10, @@ -355,7 +346,8 @@ class LibraryDatabase2(LibraryDatabase): if isinstance(self.dbpath, unicode): self.dbpath = self.dbpath.encode(filesystem_encoding) self.connect() - self.is_case_sensitive = not os.path.exists(self.dbpath.replace('metadata.db', 'MeTAdAtA.dB')) + self.is_case_sensitive = not iswindows and not isosx and \ + not os.path.exists(self.dbpath.replace('metadata.db', 'MeTAdAtA.dB')) # Upgrade database while True: meth = getattr(self, 'upgrade_version_%d'%self.user_version, None) @@ -489,6 +481,16 @@ class LibraryDatabase2(LibraryDatabase): name = title + ' - ' + author return name + def rmtree(self, path): + if not self.normpath(self.library_path).startswith(self.normpath(path)): + shutil.rmtree(path) + + def normpath(self, path): + path = os.path.abspath(os.path.realpath(path)) + if not self.is_case_sensitive: + path = path.lower() + return path + def set_path(self, index, index_is_id=False): ''' Set the path to the directory containing this books files based on its @@ -532,11 +534,11 @@ class LibraryDatabase2(LibraryDatabase): self.data.set(id, FIELD_MAP['path'], path, row_is_id=True) # Delete not needed directories if current_path and os.path.exists(spath): - if normpath(spath) != normpath(tpath): - shutil.rmtree(spath) + if self.normpath(spath) != self.normpath(tpath): + self.rmtree(spath) parent = os.path.dirname(spath) if len(os.listdir(parent)) == 0: - shutil.rmtree(parent) + self.rmtree(parent) def add_listener(self, listener): ''' @@ -699,10 +701,10 @@ class LibraryDatabase2(LibraryDatabase): path = os.path.join(self.library_path, self.path(id, index_is_id=True)) self.data.remove(id) if os.path.exists(path): - shutil.rmtree(path) + self.rmtree(path) parent = os.path.dirname(path) if len(os.listdir(parent)) == 0: - shutil.rmtree(parent) + self.rmtree(parent) self.conn.execute('DELETE FROM books WHERE id=?', (id,)) self.conn.commit() self.clean()