]> git.phdru.name Git - m_librarian.git/blobdiff - m_librarian/inp.py
Fix(inpx): Fix decoding filenames to unicode
[m_librarian.git] / m_librarian / inp.py
index 09cd42be2151a5e7b11dda19673cbada15578721..3789dd2e2d986c5969a7688d9651b8cfd2219095 100644 (file)
@@ -1,37 +1,39 @@
 
-__all__ = ['import_inpx']
-
 import os
 from zipfile import ZipFile
-from sqlobject import sqlhub, SQLObjectNotFound
+from sqlobject import sqlhub
+from sqlobject.sqlbuilder import Select
 from .db import Author, Book, Extension, Genre, Language, \
     insert_name, insert_author
 
+__all__ = ['import_inpx']
+
 
 EOT = chr(4)  # INP field separator
 
 
 def split_line(line):
     parts = line.strip().split(EOT)
-    l = len(parts)
-    if l < 11:
+    _l = len(parts)
+    if _l < 11:
         raise ValueError('Unknown INP structure: "%s"' % line)
-    if l == 11:  # Standard structure
+    archive = None
+    if _l == 11:  # Standard structure
         parts.append(None)  # Emulate lang
-    else:  # New structure
+    elif _l == 15:  # New structure
         parts = parts[:12]
-    return parts
+    elif _l == 17:  # Very new structure
+        archive = parts[12]
+        language = parts[13]
+        parts = parts[:11] + [language]
+    else:  # New structure
+        raise ValueError('Unknown INP structure: "%s"' % line)
+    return archive, parts
 
 
 def import_inp_line(archive, parts):
     authors, genres, title, series, ser_no, file, size, lib_id, deleted, \
         extension, date, language = parts
-    try:
-        Book.archive_file_idx.get(archive, file)
-    except SQLObjectNotFound:
-        pass
-    else:
-        return
     try:
         ser_no = int(ser_no)
     except ValueError:
@@ -70,21 +72,59 @@ def import_inp_line(archive, parts):
             book.addGenre(genre_row)
 
 
+def tounicode(s):
+    if isinstance(s, bytes):
+        return s.decode('utf-8')
+    else:
+        return s
+
+
 def import_inp(archive, inp):
+    archives = set()
+    files = set()
+    connection = sqlhub.processConnection
+    for file, in connection.queryAll(connection.sqlrepr(
+            Select(Book.q.file, Book.q.archive == archive))):
+        files.add((archive, tounicode(file)))
     for line in inp:
-        import_inp_line(archive, split_line(line))
+        line = line.decode('utf-8')
+        _archive, parts = split_line(line)
+        if _archive and (_archive not in archives):
+            archives.add(_archive)
+            for file, in connection.queryAll(connection.sqlrepr(
+                    Select(Book.q.file, Book.q.archive == _archive))):
+                files.add((_archive, tounicode(file)))
+        file = parts[5]
+        if (_archive or archive, file) not in files:
+            files.add((_archive or archive, file))
+            import_inp_line(_archive or archive, parts)
 
 
-def import_inpx(path):
+def import_inpx(path, pbar_cb=None):
     inpx = ZipFile(path)
+    if pbar_cb:
+        inp_count = 0
+        for name in inpx.namelist():
+            ext = os.path.splitext(name)[1]
+            if ext == '.inp':
+                inp_count += 1
+        pbar_cb.set_max(inp_count)
+    inp_count = 0
     for name in inpx.namelist():
         archive, ext = os.path.splitext(name)
         if ext != '.inp':
             continue
+        if pbar_cb:
+            inp_count += 1
+            pbar_cb.display(inp_count)
         inp = inpx.open(name)
         sqlhub.doInTransaction(import_inp, archive + '.zip', inp)
         inp.close()
     connection = sqlhub.processConnection
-    if connection.dbName in ('postgres', 'sqlite'):
+    if connection.dbName == 'postgres':
         for table in Author, Book, Extension, Genre, Language:
             connection.query("VACUUM %s" % table.sqlmeta.table)
+    elif connection.dbName == 'sqlite':
+        connection.query("VACUUM")
+    if pbar_cb:
+        pbar_cb.close()