Refactor parsers. Create a new sorter module.
This commit is contained in:
13
__main__.py
13
__main__.py
@@ -11,22 +11,23 @@
|
|||||||
✓ Search bar in toolbar
|
✓ Search bar in toolbar
|
||||||
✓ Drop down for TOC (book view)
|
✓ Drop down for TOC (book view)
|
||||||
✓ Image reflow
|
✓ Image reflow
|
||||||
|
✓ Implement book view settings with a(nother) toolbar
|
||||||
|
✓ Use format* icons for toolbar buttons
|
||||||
|
✓ Image delegates
|
||||||
|
|
||||||
Implement book view settings with a(nother) toolbar
|
|
||||||
Options:
|
Options:
|
||||||
Ignore a and the for sorting purposes
|
Ignore a and the for sorting purposes
|
||||||
Check files (hashes) upon restart
|
Check files (hashes) upon restart
|
||||||
Recursive file addition
|
Recursive file addition
|
||||||
Show what on startup
|
Show what on startup
|
||||||
mobi support
|
mobi, azw support
|
||||||
txt, doc support
|
txt, doc, djvu support
|
||||||
pdf support?
|
pdf support?
|
||||||
Goodreads API: Ratings, Read, Recommendations
|
Goodreads API: Ratings, Read, Recommendations
|
||||||
Get ISBN using python-isbnlib
|
Get ISBN using python-isbnlib
|
||||||
All ebooks should first be added to the database and then returned as HTML
|
All ebooks should first be added to the database and then returned as HTML
|
||||||
Theming
|
Theming
|
||||||
Pagination
|
Pagination
|
||||||
Use format* icons for toolbar buttons
|
|
||||||
Information dialog widget
|
Information dialog widget
|
||||||
Library context menu: Cache, Read, Edit database, delete
|
Library context menu: Cache, Read, Edit database, delete
|
||||||
Set context menu for definitions and the like
|
Set context menu for definitions and the like
|
||||||
@@ -39,7 +40,7 @@ from PyQt5 import QtWidgets, QtGui, QtCore
|
|||||||
|
|
||||||
import mainwindow
|
import mainwindow
|
||||||
import database
|
import database
|
||||||
import book_parser
|
import sorter
|
||||||
|
|
||||||
from widgets import LibraryToolBar, BookToolBar, Tab, LibraryDelegate
|
from widgets import LibraryToolBar, BookToolBar, Tab, LibraryDelegate
|
||||||
from subclasses import Settings, Library
|
from subclasses import Settings, Library
|
||||||
@@ -144,7 +145,7 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
|
|||||||
if my_file[0]:
|
if my_file[0]:
|
||||||
self.listView.setEnabled(False)
|
self.listView.setEnabled(False)
|
||||||
self.last_open_path = os.path.dirname(my_file[0][0])
|
self.last_open_path = os.path.dirname(my_file[0][0])
|
||||||
books = book_parser.BookSorter(my_file[0])
|
books = sorter.BookSorter(my_file[0])
|
||||||
parsed_books = books.initiate_threads()
|
parsed_books = books.initiate_threads()
|
||||||
database.DatabaseFunctions(self.database_path).add_to_database(parsed_books)
|
database.DatabaseFunctions(self.database_path).add_to_database(parsed_books)
|
||||||
self.listView.setEnabled(True)
|
self.listView.setEnabled(True)
|
||||||
|
0
parsers/__init__.py
Normal file
0
parsers/__init__.py
Normal file
@@ -1,9 +1,15 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# Every parser is supposed to have the following methods, even if they return None:
|
||||||
|
# read_book()
|
||||||
|
# get_title()
|
||||||
|
# get_author()
|
||||||
|
# get_year()
|
||||||
|
# get_cover_image()
|
||||||
|
# get_isbn
|
||||||
|
# TODO More for get contents, get TOC
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import hashlib
|
|
||||||
from multiprocessing.dummy import Pool
|
|
||||||
|
|
||||||
import ebooklib.epub
|
import ebooklib.epub
|
||||||
|
|
||||||
@@ -15,7 +21,7 @@ class ParseEPUB:
|
|||||||
self.filename = filename
|
self.filename = filename
|
||||||
self.book = None
|
self.book = None
|
||||||
|
|
||||||
def read_epub(self):
|
def read_book(self):
|
||||||
try:
|
try:
|
||||||
self.book = ebooklib.epub.read_epub(self.filename)
|
self.book = ebooklib.epub.read_epub(self.filename)
|
||||||
except (KeyError, AttributeError):
|
except (KeyError, AttributeError):
|
||||||
@@ -94,54 +100,3 @@ class ParseEPUB:
|
|||||||
return isbn
|
return isbn
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
class BookSorter:
|
|
||||||
def __init__(self, file_list):
|
|
||||||
# Have the GUI pass a list of files straight to here
|
|
||||||
# Then, on the basis of what is needed, pass the
|
|
||||||
# filenames to the requisite functions
|
|
||||||
# This includes getting file info for the database
|
|
||||||
# Parsing for the reader proper
|
|
||||||
# Caching upon closing
|
|
||||||
self.file_list = file_list
|
|
||||||
self.all_books = {}
|
|
||||||
|
|
||||||
def read_book(self, filename):
|
|
||||||
# filename is expected as a string containg the
|
|
||||||
# full path of the ebook file
|
|
||||||
|
|
||||||
# TODO
|
|
||||||
# See if you want to include a hash of the book's name and author
|
|
||||||
with open(filename, 'rb') as current_book:
|
|
||||||
file_md5 = hashlib.md5(current_book.read()).hexdigest()
|
|
||||||
|
|
||||||
if file_md5 in self.all_books.items():
|
|
||||||
return
|
|
||||||
|
|
||||||
# TODO
|
|
||||||
# See if tags can be generated from book content
|
|
||||||
book_ref = ParseEPUB(filename)
|
|
||||||
book_ref.read_epub()
|
|
||||||
if book_ref.book:
|
|
||||||
title = book_ref.get_title()
|
|
||||||
author = book_ref.get_author()
|
|
||||||
year = book_ref.get_year()
|
|
||||||
cover_image = book_ref.get_cover_image()
|
|
||||||
isbn = book_ref.get_isbn()
|
|
||||||
|
|
||||||
self.all_books[file_md5] = {
|
|
||||||
'title': title,
|
|
||||||
'author': author,
|
|
||||||
'year': year,
|
|
||||||
'isbn': isbn,
|
|
||||||
'path': filename,
|
|
||||||
'cover_image': cover_image}
|
|
||||||
|
|
||||||
def initiate_threads(self):
|
|
||||||
_pool = Pool(5)
|
|
||||||
_pool.map(self.read_book, self.file_list)
|
|
||||||
_pool.close()
|
|
||||||
_pool.join()
|
|
||||||
|
|
||||||
return self.all_books
|
|
65
sorter.py
Normal file
65
sorter.py
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# TODO
|
||||||
|
# Methods that return None must be quantified here if needed
|
||||||
|
|
||||||
|
import hashlib
|
||||||
|
from multiprocessing.dummy import Pool
|
||||||
|
|
||||||
|
from parsers.epub import ParseEPUB
|
||||||
|
|
||||||
|
|
||||||
|
class BookSorter:
|
||||||
|
def __init__(self, file_list):
|
||||||
|
# Have the GUI pass a list of files straight to here
|
||||||
|
# Then, on the basis of what is needed, pass the
|
||||||
|
# filenames to the requisite functions
|
||||||
|
# This includes getting file info for the database
|
||||||
|
# Parsing for the reader proper
|
||||||
|
# Caching upon closing
|
||||||
|
self.file_list = file_list
|
||||||
|
self.all_books = {}
|
||||||
|
|
||||||
|
def read_book(self, filename):
|
||||||
|
# filename is expected as a string containg the
|
||||||
|
# full path of the ebook file
|
||||||
|
|
||||||
|
# TODO
|
||||||
|
# See if you want to include a hash of the book's name and author
|
||||||
|
with open(filename, 'rb') as current_book:
|
||||||
|
file_md5 = hashlib.md5(current_book.read()).hexdigest()
|
||||||
|
|
||||||
|
if file_md5 in self.all_books.items():
|
||||||
|
return
|
||||||
|
|
||||||
|
# TODO
|
||||||
|
# See if tags can be generated from book content
|
||||||
|
# Sort according to to file extension here
|
||||||
|
book_ref = ParseEPUB(filename)
|
||||||
|
|
||||||
|
# Everything following this is standard
|
||||||
|
# Some of the None returns will have to have
|
||||||
|
# values associated with them, though
|
||||||
|
book_ref.read_book()
|
||||||
|
if book_ref.book:
|
||||||
|
title = book_ref.get_title()
|
||||||
|
author = book_ref.get_author()
|
||||||
|
year = book_ref.get_year()
|
||||||
|
cover_image = book_ref.get_cover_image()
|
||||||
|
isbn = book_ref.get_isbn()
|
||||||
|
|
||||||
|
self.all_books[file_md5] = {
|
||||||
|
'title': title,
|
||||||
|
'author': author,
|
||||||
|
'year': year,
|
||||||
|
'isbn': isbn,
|
||||||
|
'path': filename,
|
||||||
|
'cover_image': cover_image}
|
||||||
|
|
||||||
|
def initiate_threads(self):
|
||||||
|
_pool = Pool(5)
|
||||||
|
_pool.map(self.read_book, self.file_list)
|
||||||
|
_pool.close()
|
||||||
|
_pool.join()
|
||||||
|
|
||||||
|
return self.all_books
|
Reference in New Issue
Block a user