mirror of
https://github.com/ciromattia/kcc
synced 2025-12-13 01:36:27 +00:00
Version 4.0 - first draft for Python3 conversion
This commit is contained in:
2
kcc.iss
2
kcc.iss
@@ -1,5 +1,5 @@
|
||||
#define MyAppName "Kindle Comic Converter"
|
||||
#define MyAppVersion "3.6"
|
||||
#define MyAppVersion "4.0"
|
||||
#define MyAppPublisher "Ciro Mattia Gonano, Paweł Jastrzębski"
|
||||
#define MyAppURL "http://kcc.vulturis.eu/"
|
||||
#define MyAppExeName "KCC.exe"
|
||||
|
||||
12
kcc.py
12
kcc.py
@@ -18,7 +18,7 @@
|
||||
# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
# PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
__version__ = '3.6'
|
||||
__version__ = '4.0'
|
||||
__license__ = 'ISC'
|
||||
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
@@ -29,13 +29,13 @@ try:
|
||||
#noinspection PyUnresolvedReferences
|
||||
from PyQt4 import QtCore, QtGui, QtNetwork
|
||||
except ImportError:
|
||||
print "ERROR: PyQT4 is not installed!"
|
||||
print("ERROR: PyQT4 is not installed!")
|
||||
if sys.platform.startswith('linux'):
|
||||
import Tkinter
|
||||
import tkMessageBox
|
||||
importRoot = Tkinter.Tk()
|
||||
import tkinter
|
||||
import tkinter.messagebox
|
||||
importRoot = tkinter.Tk()
|
||||
importRoot.withdraw()
|
||||
tkMessageBox.showerror("KCC - Error", "PyQT4 is not installed!")
|
||||
tkinter.messagebox.showerror("KCC - Error", "PyQT4 is not installed!")
|
||||
exit(1)
|
||||
from kcc import KCC_gui
|
||||
from multiprocessing import freeze_support
|
||||
|
||||
181
kcc/KCC_gui.py
181
kcc/KCC_gui.py
@@ -17,7 +17,7 @@
|
||||
# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
# PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
__version__ = '3.6'
|
||||
__version__ = '4.0'
|
||||
__license__ = 'ISC'
|
||||
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
@@ -25,39 +25,38 @@ __docformat__ = 'restructuredtext en'
|
||||
import os
|
||||
import sys
|
||||
import traceback
|
||||
import urllib2
|
||||
import urllib.request, urllib.error, urllib.parse
|
||||
import socket
|
||||
import comic2ebook
|
||||
import kindlesplit
|
||||
from string import split
|
||||
from . import comic2ebook
|
||||
from . import kindlesplit
|
||||
from time import sleep
|
||||
from shutil import move
|
||||
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
|
||||
from SocketServer import ThreadingMixIn
|
||||
from image import ProfileData
|
||||
from http.server import BaseHTTPRequestHandler, HTTPServer
|
||||
from socketserver import ThreadingMixIn
|
||||
from .image import ProfileData
|
||||
from subprocess import STDOUT, PIPE
|
||||
from PyQt4 import QtGui, QtCore
|
||||
from xml.dom.minidom import parse
|
||||
from HTMLParser import HTMLParser
|
||||
from KCC_rc_web import WebContent
|
||||
from html.parser import HTMLParser
|
||||
from .KCC_rc_web import WebContent
|
||||
try:
|
||||
#noinspection PyUnresolvedReferences
|
||||
from psutil import TOTAL_PHYMEM, Popen
|
||||
except ImportError:
|
||||
print "ERROR: Psutil is not installed!"
|
||||
print("ERROR: Psutil is not installed!")
|
||||
if sys.platform.startswith('linux'):
|
||||
import Tkinter
|
||||
import tkMessageBox
|
||||
importRoot = Tkinter.Tk()
|
||||
import tkinter
|
||||
import tkinter.messagebox
|
||||
importRoot = tkinter.Tk()
|
||||
importRoot.withdraw()
|
||||
tkMessageBox.showerror("KCC - Error", "Psutil is not installed!")
|
||||
tkinter.messagebox.showerror("KCC - Error", "Psutil is not installed!")
|
||||
exit(1)
|
||||
if sys.platform.startswith('darwin'):
|
||||
import KCC_ui_osx as KCC_ui
|
||||
from . import KCC_ui_osx as KCC_ui
|
||||
elif sys.platform.startswith('linux'):
|
||||
import KCC_ui_linux as KCC_ui
|
||||
from . import KCC_ui_linux as KCC_ui
|
||||
else:
|
||||
import KCC_ui
|
||||
from . import KCC_ui
|
||||
|
||||
|
||||
class Icons:
|
||||
@@ -130,8 +129,8 @@ class WebServerHandler(BaseHTTPRequestHandler):
|
||||
'<p style="font-size:50px">- <img style="vertical-align: middle" '
|
||||
'alt="KCC Logo" src="' + GUI.webContent.logo + '" /> -</p>\n')
|
||||
if len(GUI.completedWork) > 0 and not GUI.conversionAlive:
|
||||
for key in sorted(GUI.completedWork.iterkeys()):
|
||||
self.wfile.write('<p><a href="' + key + '">' + split(key, '.')[0] + '</a></p>\n')
|
||||
for key in sorted(GUI.completedWork.keys()):
|
||||
self.wfile.write('<p><a href="' + key + '">' + key.split('.')[0] + '</a></p>\n')
|
||||
else:
|
||||
self.wfile.write('<p style="font-weight: bold">No downloads are available.<br/>'
|
||||
'Convert some files and refresh this page.</p>\n')
|
||||
@@ -139,7 +138,7 @@ class WebServerHandler(BaseHTTPRequestHandler):
|
||||
'</body>\n'
|
||||
'</html>\n')
|
||||
elif sendReply:
|
||||
outputFile = GUI.completedWork[urllib2.unquote(self.path[1:])].decode('utf-8')
|
||||
outputFile = GUI.completedWork[urllib.parse.unquote(self.path[1:])].decode('utf-8')
|
||||
fp = open(outputFile, 'rb')
|
||||
self.send_response(200)
|
||||
self.send_header('Content-type', mimetype)
|
||||
@@ -173,7 +172,7 @@ class WebServerThread(QtCore.QThread):
|
||||
try:
|
||||
# Sweet cross-platform one-liner to get LAN ip address
|
||||
lIP = [ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith("127.")][:1][0]
|
||||
except StandardError:
|
||||
except Exception:
|
||||
# Sadly it can fail on some Linux configurations
|
||||
lIP = None
|
||||
try:
|
||||
@@ -186,7 +185,7 @@ class WebServerThread(QtCore.QThread):
|
||||
self.emit(QtCore.SIGNAL("addMessage"), '<b>Content server</b> started on port 4242.', 'info')
|
||||
while self.running:
|
||||
self.server.handle_request()
|
||||
except StandardError:
|
||||
except Exception:
|
||||
self.emit(QtCore.SIGNAL("addMessage"), '<b>Content server</b> failed to start!', 'error')
|
||||
|
||||
def stop(self):
|
||||
@@ -202,9 +201,9 @@ class VersionThread(QtCore.QThread):
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
XML = urllib2.urlopen('http://kcc.vulturis.eu/Version.php')
|
||||
XML = urllib.request.urlopen('http://kcc.vulturis.eu/Version.php')
|
||||
XML = parse(XML)
|
||||
except StandardError:
|
||||
except Exception:
|
||||
return
|
||||
latestVersion = XML.childNodes[0].getElementsByTagName('latest')[0].childNodes[0].toxml()
|
||||
if tuple(map(int, (latestVersion.split(".")))) > tuple(map(int, (__version__.split(".")))):
|
||||
@@ -253,9 +252,10 @@ class KindleGenThread(QtCore.QRunnable):
|
||||
kindlegenError = ''
|
||||
try:
|
||||
if os.path.getsize(self.work) < 367001600:
|
||||
output = Popen('kindlegen -locale en "' + self.work.encode(sys.getfilesystemencoding()) + '"',
|
||||
stdout=PIPE, stderr=STDOUT, shell=True)
|
||||
output = Popen('kindlegen -locale en "' + self.work.encode(sys.getfilesystemencoding()).decode('utf-8')
|
||||
+ '"', stdout=PIPE, stderr=STDOUT, shell=True)
|
||||
for line in output.stdout:
|
||||
line = line.decode('utf-8')
|
||||
# ERROR: Generic error
|
||||
if "Error(" in line:
|
||||
kindlegenErrorCode = 1
|
||||
@@ -269,9 +269,10 @@ class KindleGenThread(QtCore.QRunnable):
|
||||
# ERROR: EPUB too big
|
||||
kindlegenErrorCode = 23026
|
||||
self.signals.result.emit([kindlegenErrorCode, kindlegenError, self.work])
|
||||
except StandardError:
|
||||
# ERROR: Unknown generic error
|
||||
except Exception as err:
|
||||
# ERROR: KCC unknown generic error
|
||||
kindlegenErrorCode = 1
|
||||
kindlegenError = format(err)
|
||||
self.signals.result.emit([kindlegenErrorCode, kindlegenError, self.work])
|
||||
|
||||
|
||||
@@ -297,8 +298,9 @@ class KindleUnpackThread(QtCore.QRunnable):
|
||||
mobisplit = kindlesplit.mobi_split(mobiPath + '_toclean', newKindle)
|
||||
open(mobiPath, 'wb').write(mobisplit.getResult())
|
||||
self.signals.result.emit([True])
|
||||
except StandardError:
|
||||
self.signals.result.emit([False])
|
||||
except Exception as err:
|
||||
traceback.print_exc()
|
||||
self.signals.result.emit([False, format(err)])
|
||||
|
||||
|
||||
class WorkerThread(QtCore.QThread):
|
||||
@@ -385,7 +387,7 @@ class WorkerThread(QtCore.QThread):
|
||||
for i in range(GUI.JobList.count()):
|
||||
# Make sure that we don't consider any system message as job to do
|
||||
if GUI.JobList.item(i).icon().isNull():
|
||||
currentJobs.append(unicode(GUI.JobList.item(i).text()))
|
||||
currentJobs.append(str(GUI.JobList.item(i).text()))
|
||||
GUI.JobList.clear()
|
||||
for job in currentJobs:
|
||||
sleep(0.5)
|
||||
@@ -466,42 +468,45 @@ class WorkerThread(QtCore.QThread):
|
||||
if self.kindlegenErrorCode[0] == 0:
|
||||
GUI.progress.content = ''
|
||||
self.emit(QtCore.SIGNAL("addMessage"), 'Creating MOBI files... <b>Done!</b>', 'info', True)
|
||||
self.emit(QtCore.SIGNAL("addMessage"), 'Cleaning MOBI files', 'info')
|
||||
GUI.progress.content = 'Cleaning MOBI files'
|
||||
self.workerOutput = []
|
||||
# Multithreading KindleUnpack in current form is a waste of resources.
|
||||
# Unless we higly optimise KindleUnpack or drop 32bit support this will not change.
|
||||
self.pool.setMaxThreadCount(1)
|
||||
for item in outputPath:
|
||||
worker = KindleUnpackThread([item, profile])
|
||||
worker.signals.result.connect(self.addResult)
|
||||
self.pool.start(worker)
|
||||
self.pool.waitForDone()
|
||||
sleep(0.5)
|
||||
for success in self.workerOutput:
|
||||
if not success:
|
||||
self.errors = True
|
||||
break
|
||||
if not self.errors:
|
||||
for item in outputPath:
|
||||
GUI.progress.content = ''
|
||||
mobiPath = item.replace('.epub', '.mobi')
|
||||
os.remove(mobiPath + '_toclean')
|
||||
GUI.completedWork[os.path.basename(mobiPath).encode('utf-8')] = \
|
||||
mobiPath.encode('utf-8')
|
||||
self.emit(QtCore.SIGNAL("addMessage"), 'Cleaning MOBI files... <b>Done!</b>', 'info',
|
||||
True)
|
||||
else:
|
||||
GUI.progress.content = ''
|
||||
for item in outputPath:
|
||||
mobiPath = item.replace('.epub', '.mobi')
|
||||
if os.path.exists(mobiPath):
|
||||
os.remove(mobiPath)
|
||||
if os.path.exists(mobiPath + '_toclean'):
|
||||
os.remove(mobiPath + '_toclean')
|
||||
self.emit(QtCore.SIGNAL("addMessage"), 'KindleUnpack failed to clean MOBI file!', 'error')
|
||||
self.emit(QtCore.SIGNAL("addTrayMessage"), 'KindleUnpack failed to clean MOBI file!',
|
||||
'Critical')
|
||||
self.emit(QtCore.SIGNAL("addMessage"), 'Cleaning MOBI files is currently disabled in this branch', 'info')
|
||||
GUI.progress.content = 'Cleaning MOBI files is currently disabled in this branch'
|
||||
#self.emit(QtCore.SIGNAL("addMessage"), 'Cleaning MOBI files', 'info')
|
||||
#GUI.progress.content = 'Cleaning MOBI files'
|
||||
#self.workerOutput = []
|
||||
## Multithreading KindleUnpack in current form is a waste of resources.
|
||||
## Unless we higly optimise KindleUnpack or drop 32bit support this will not change.
|
||||
#self.pool.setMaxThreadCount(1)
|
||||
#for item in outputPath:
|
||||
# worker = KindleUnpackThread([item, profile])
|
||||
# worker.signals.result.connect(self.addResult)
|
||||
# self.pool.start(worker)
|
||||
#self.pool.waitForDone()
|
||||
#sleep(0.5)
|
||||
#for success in self.workerOutput:
|
||||
# if not success[0]:
|
||||
# self.errors = True
|
||||
# print(success[1])
|
||||
# break
|
||||
#if not self.errors:
|
||||
# for item in outputPath:
|
||||
# GUI.progress.content = ''
|
||||
# mobiPath = item.replace('.epub', '.mobi')
|
||||
# os.remove(mobiPath + '_toclean')
|
||||
# GUI.completedWork[os.path.basename(mobiPath).encode('utf-8')] = \
|
||||
# mobiPath.encode('utf-8')
|
||||
# self.emit(QtCore.SIGNAL("addMessage"), 'Cleaning MOBI files... <b>Done!</b>', 'info',
|
||||
# True)
|
||||
#else:
|
||||
# GUI.progress.content = ''
|
||||
# for item in outputPath:
|
||||
# mobiPath = item.replace('.epub', '.mobi')
|
||||
# if os.path.exists(mobiPath):
|
||||
# os.remove(mobiPath)
|
||||
# if os.path.exists(mobiPath + '_toclean'):
|
||||
# os.remove(mobiPath + '_toclean')
|
||||
# self.emit(QtCore.SIGNAL("addMessage"), 'KindleUnpack failed to clean MOBI file!', 'error')
|
||||
# self.emit(QtCore.SIGNAL("addTrayMessage"), 'KindleUnpack failed to clean MOBI file!',
|
||||
# 'Critical')
|
||||
else:
|
||||
GUI.progress.content = ''
|
||||
epubSize = (os.path.getsize(self.kindlegenErrorCode[2]))/1024/1024
|
||||
@@ -571,10 +576,10 @@ class KCCGUI(KCC_ui.Ui_KCC):
|
||||
else:
|
||||
dnames = ""
|
||||
for dname in dnames:
|
||||
if unicode(dname) != "":
|
||||
if str(dname) != "":
|
||||
if sys.platform == 'win32':
|
||||
dname = dname.replace('/', '\\')
|
||||
self.lastPath = os.path.abspath(os.path.join(unicode(dname), os.pardir))
|
||||
self.lastPath = os.path.abspath(os.path.join(str(dname), os.pardir))
|
||||
GUI.JobList.addItem(dname)
|
||||
MW.setFocus()
|
||||
|
||||
@@ -597,8 +602,8 @@ class KCCGUI(KCC_ui.Ui_KCC):
|
||||
fnames = QtGui.QFileDialog.getOpenFileNames(MW, 'Select file', self.lastPath,
|
||||
'*.cbz *.zip *.pdf')
|
||||
for fname in fnames:
|
||||
if unicode(fname) != "":
|
||||
self.lastPath = os.path.abspath(os.path.join(unicode(fname), os.pardir))
|
||||
if str(fname) != "":
|
||||
self.lastPath = os.path.abspath(os.path.join(str(fname), os.pardir))
|
||||
GUI.JobList.addItem(fname)
|
||||
|
||||
def clearJobs(self):
|
||||
@@ -884,19 +889,19 @@ class KCCGUI(KCC_ui.Ui_KCC):
|
||||
self.settings.setValue('currentFormat', GUI.FormatBox.currentIndex())
|
||||
self.settings.setValue('currentMode', self.currentMode)
|
||||
self.settings.setValue('firstStart', False)
|
||||
self.settings.setValue('options', QtCore.QVariant({'MangaBox': GUI.MangaBox.checkState(),
|
||||
'RotateBox': GUI.RotateBox.checkState(),
|
||||
'QualityBox': GUI.QualityBox.checkState(),
|
||||
'ProcessingBox': GUI.ProcessingBox.checkState(),
|
||||
'UpscaleBox': GUI.UpscaleBox.checkState(),
|
||||
'NoRotateBox': GUI.NoRotateBox.checkState(),
|
||||
'BorderBox': GUI.BorderBox.checkState(),
|
||||
'WebtoonBox': GUI.WebtoonBox.checkState(),
|
||||
'NoDitheringBox': GUI.NoDitheringBox.checkState(),
|
||||
'ColorBox': GUI.ColorBox.checkState(),
|
||||
'customWidth': GUI.customWidth.text(),
|
||||
'customHeight': GUI.customHeight.text(),
|
||||
'GammaSlider': float(self.GammaValue)*100}))
|
||||
self.settings.setValue('options', {'MangaBox': GUI.MangaBox.checkState(),
|
||||
'RotateBox': GUI.RotateBox.checkState(),
|
||||
'QualityBox': GUI.QualityBox.checkState(),
|
||||
'ProcessingBox': GUI.ProcessingBox.checkState(),
|
||||
'UpscaleBox': GUI.UpscaleBox.checkState(),
|
||||
'NoRotateBox': GUI.NoRotateBox.checkState(),
|
||||
'BorderBox': GUI.BorderBox.checkState(),
|
||||
'WebtoonBox': GUI.WebtoonBox.checkState(),
|
||||
'NoDitheringBox': GUI.NoDitheringBox.checkState(),
|
||||
'ColorBox': GUI.ColorBox.checkState(),
|
||||
'customWidth': GUI.customWidth.text(),
|
||||
'customHeight': GUI.customHeight.text(),
|
||||
'GammaSlider': float(self.GammaValue)*100})
|
||||
self.settings.sync()
|
||||
|
||||
def handleMessage(self, message):
|
||||
@@ -947,8 +952,7 @@ class KCCGUI(KCC_ui.Ui_KCC):
|
||||
self.currentMode = self.settings.value('currentMode', 1, type=int)
|
||||
self.currentFormat = self.settings.value('currentFormat', 0, type=int)
|
||||
self.firstStart = self.settings.value('firstStart', True, type=bool)
|
||||
self.options = self.settings.value('options', QtCore.QVariant({'GammaSlider': 0}))
|
||||
self.options = self.options.toPyObject()
|
||||
self.options = self.settings.value('options', {'GammaSlider': 0})
|
||||
self.worker = WorkerThread()
|
||||
self.versionCheck = VersionThread()
|
||||
self.contentServer = WebServerThread()
|
||||
@@ -996,7 +1000,8 @@ class KCCGUI(KCC_ui.Ui_KCC):
|
||||
formats = ['MOBI', 'EPUB', 'CBZ']
|
||||
versionCheck = Popen('kindlegen -locale en', stdout=PIPE, stderr=STDOUT, shell=True)
|
||||
for line in versionCheck.stdout:
|
||||
if "Amazon kindlegen" in line:
|
||||
line = line.decode("utf-8")
|
||||
if 'Amazon kindlegen' in line:
|
||||
versionCheck = line.split('V')[1].split(' ')[0]
|
||||
if tuple(map(int, (versionCheck.split(".")))) < tuple(map(int, ('2.9'.split(".")))):
|
||||
self.addMessage('Your <a href="http://www.amazon.com/gp/feature.html?ie=UTF8&docId='
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
|
||||
# Resource object code
|
||||
#
|
||||
# Created: N 6. paź 13:26:15 2013
|
||||
# by: The Resource Compiler for PyQt (Qt v4.8.5)
|
||||
# Created: mer nov 13 21:20:16 2013
|
||||
# by: The Resource Compiler for PyQt (Qt v4.8.6)
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
||||
from PyQt4 import QtCore
|
||||
|
||||
qt_resource_data = "\
|
||||
qt_resource_data = b"\
|
||||
\x00\x00\x09\x59\
|
||||
\x89\
|
||||
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
|
||||
@@ -8360,7 +8360,7 @@ qt_resource_data = "\
|
||||
\xfc\xce\x76\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
|
||||
"
|
||||
|
||||
qt_resource_name = "\
|
||||
qt_resource_name = b"\
|
||||
\x00\x07\
|
||||
\x0a\xcc\xf9\x43\
|
||||
\x00\x44\
|
||||
@@ -8444,7 +8444,7 @@ qt_resource_name = "\
|
||||
\x00\x74\x00\x68\x00\x65\x00\x72\x00\x2e\x00\x70\x00\x6e\x00\x67\
|
||||
"
|
||||
|
||||
qt_resource_struct = "\
|
||||
qt_resource_struct = b"\
|
||||
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x05\x00\x00\x00\x01\
|
||||
\x00\x00\x00\x28\x00\x02\x00\x00\x00\x01\x00\x00\x00\x17\
|
||||
\x00\x00\x00\x36\x00\x02\x00\x00\x00\x01\x00\x00\x00\x11\
|
||||
|
||||
@@ -321,4 +321,4 @@ class Ui_KCC(object):
|
||||
self.ActionBasic.setText(_translate("KCC", "Basic", None))
|
||||
self.ActionAdvanced.setText(_translate("KCC", "Advanced", None))
|
||||
|
||||
import KCC_rc
|
||||
from . import KCC_rc
|
||||
|
||||
@@ -390,4 +390,4 @@ class Ui_KCC(object):
|
||||
self.ActionBasic.setText(_translate("KCC", "Basic", None))
|
||||
self.ActionAdvanced.setText(_translate("KCC", "Advanced", None))
|
||||
|
||||
import KCC_rc
|
||||
from . import KCC_rc
|
||||
|
||||
@@ -408,4 +408,4 @@ class Ui_KCC(object):
|
||||
self.ActionBasic.setText(_translate("KCC", "Basic", None))
|
||||
self.ActionAdvanced.setText(_translate("KCC", "Advanced", None))
|
||||
|
||||
import KCC_rc
|
||||
from . import KCC_rc
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
__version__ = '3.6'
|
||||
__version__ = '4.0'
|
||||
__license__ = 'ISC'
|
||||
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
2
kcc/__main__.py
Normal file
2
kcc/__main__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
from kcc.comic2ebook import main
|
||||
main()
|
||||
@@ -21,7 +21,7 @@ __docformat__ = 'restructuredtext en'
|
||||
|
||||
import os
|
||||
import zipfile
|
||||
import rarfile
|
||||
from . import rarfile
|
||||
import locale
|
||||
from subprocess import STDOUT, PIPE
|
||||
from psutil import Popen
|
||||
@@ -52,7 +52,7 @@ class CBxArchive:
|
||||
elif f.endswith('/'):
|
||||
try:
|
||||
os.makedirs(os.path.join(targetdir, f))
|
||||
except StandardError:
|
||||
except Exception:
|
||||
pass # the dir exists so we are going to extract the images only.
|
||||
else:
|
||||
filelist.append(f)
|
||||
@@ -67,7 +67,7 @@ class CBxArchive:
|
||||
elif f.endswith('/'):
|
||||
try:
|
||||
os.makedirs(os.path.join(targetdir, f))
|
||||
except StandardError:
|
||||
except Exception:
|
||||
pass # the dir exists so we are going to extract the images only.
|
||||
else:
|
||||
filelist.append(f.encode(locale.getpreferredencoding()))
|
||||
@@ -85,7 +85,7 @@ class CBxArchive:
|
||||
raise OSError
|
||||
|
||||
def extract(self, targetdir):
|
||||
print "\n" + targetdir + "\n"
|
||||
print("\n" + targetdir + "\n")
|
||||
if self.compressor == 'rar':
|
||||
self.extractCBR(targetdir)
|
||||
elif self.compressor == 'zip':
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python2
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2012-2013 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||
@@ -18,7 +18,7 @@
|
||||
# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
# PERFORMANCE OF THIS SOFTWARE.
|
||||
#
|
||||
__version__ = '3.6'
|
||||
__version__ = '4.0'
|
||||
__license__ = 'ISC'
|
||||
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
@@ -35,14 +35,15 @@ from optparse import OptionParser, OptionGroup
|
||||
from multiprocessing import Pool, freeze_support
|
||||
from xml.dom.minidom import parse
|
||||
from uuid import uuid4
|
||||
from slugify import slugify
|
||||
try:
|
||||
from PyQt4 import QtCore
|
||||
except ImportError:
|
||||
QtCore = None
|
||||
import comic2panel
|
||||
import image
|
||||
import cbxarchive
|
||||
import pdfjpgextract
|
||||
from . import comic2panel
|
||||
from . import image
|
||||
from . import cbxarchive
|
||||
from . import pdfjpgextract
|
||||
|
||||
|
||||
def buildHTML(path, imgfile):
|
||||
@@ -172,7 +173,6 @@ def buildHTML(path, imgfile):
|
||||
|
||||
def buildNCX(dstdir, title, chapters):
|
||||
options.uuid = str(uuid4())
|
||||
options.uuid = options.uuid.encode('utf-8')
|
||||
ncxfile = os.path.join(dstdir, 'OEBPS', 'toc.ncx')
|
||||
f = open(ncxfile, "w")
|
||||
f.writelines(["<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n",
|
||||
@@ -186,7 +186,7 @@ def buildNCX(dstdir, title, chapters):
|
||||
"<meta name=\"dtb:maxPageNumber\" content=\"0\"/>\n",
|
||||
"<meta name=\"generated\" content=\"true\"/>\n",
|
||||
"</head>\n",
|
||||
"<docTitle><text>", title.encode('utf-8'), "</text></docTitle>\n",
|
||||
"<docTitle><text>", title, "</text></docTitle>\n",
|
||||
"<navMap>"
|
||||
])
|
||||
for chapter in chapters:
|
||||
@@ -195,7 +195,7 @@ def buildNCX(dstdir, title, chapters):
|
||||
title = os.path.basename(folder)
|
||||
filename = getImageFileName(os.path.join(folder, chapter[1]))
|
||||
f.write("<navPoint id=\"" + folder.replace('/', '_').replace('\\', '_') + "\"><navLabel><text>"
|
||||
+ title.encode('utf-8') + "</text></navLabel><content src=\"" + filename[0].replace("\\", "/")
|
||||
+ title + "</text></navLabel><content src=\"" + filename[0].replace("\\", "/")
|
||||
+ ".html\"/></navPoint>\n")
|
||||
f.write("</navMap>\n</ncx>")
|
||||
f.close()
|
||||
@@ -216,11 +216,11 @@ def buildOPF(dstdir, title, filelist, cover=None):
|
||||
"xmlns=\"http://www.idpf.org/2007/opf\">\n",
|
||||
"<metadata xmlns:opf=\"http://www.idpf.org/2007/opf\" ",
|
||||
"xmlns:dc=\"http://purl.org/dc/elements/1.1/\">\n",
|
||||
"<dc:title>", title.encode('utf-8'), "</dc:title>\n",
|
||||
"<dc:title>", title, "</dc:title>\n",
|
||||
"<dc:language>en-US</dc:language>\n",
|
||||
"<dc:identifier id=\"BookID\" opf:scheme=\"UUID\">", options.uuid, "</dc:identifier>\n"])
|
||||
for author in options.authors:
|
||||
f.writelines(["<dc:Creator>", author.encode('utf-8'), "</dc:Creator>\n"])
|
||||
f.writelines(["<dc:Creator>", author, "</dc:Creator>\n"])
|
||||
f.writelines(["<meta name=\"generator\" content=\"KindleComicConverter-" + __version__ + "\"/>\n",
|
||||
"<meta name=\"RegionMagnification\" content=\"true\"/>\n",
|
||||
"<meta name=\"region-mag\" content=\"true\"/>\n",
|
||||
@@ -356,9 +356,9 @@ def fileImgProcess(work):
|
||||
dirpath = work[1]
|
||||
opt = work[2]
|
||||
if opt.verbose:
|
||||
print "Optimizing " + afile + " for " + opt.profile
|
||||
print("Optimizing " + afile + " for " + opt.profile)
|
||||
else:
|
||||
print ".",
|
||||
print(".", end=' ')
|
||||
img = image.ComicPage(os.path.join(dirpath, afile), opt.profileData)
|
||||
if opt.quality == 2:
|
||||
wipe = False
|
||||
@@ -370,7 +370,7 @@ def fileImgProcess(work):
|
||||
split = img.splitPage(dirpath, opt.righttoleft, opt.rotate)
|
||||
if split is not None:
|
||||
if opt.verbose:
|
||||
print "Splitted " + afile
|
||||
print("Splitted " + afile)
|
||||
img0 = image.ComicPage(split[0], opt.profileData)
|
||||
applyImgOptimization(img0, opt)
|
||||
img0.saveToDir(dirpath, opt.forcepng, opt.forcecolor, wipe)
|
||||
@@ -394,7 +394,9 @@ def fileImgProcess(work):
|
||||
img2.rotated = True
|
||||
applyImgOptimization(img2, opt, 0)
|
||||
img2.saveToDir(dirpath, opt.forcepng, opt.forcecolor, True)
|
||||
except StandardError:
|
||||
except Exception:
|
||||
import traceback
|
||||
traceback.print_tb(sys.exc_info()[2])
|
||||
return str(sys.exc_info()[1])
|
||||
|
||||
|
||||
@@ -565,7 +567,7 @@ def getWorkFolder(afile):
|
||||
path = cbx.extract(workdir)
|
||||
except OSError:
|
||||
rmtree(workdir, True)
|
||||
print 'UnRAR/7za not found or file failed to extract!'
|
||||
print('UnRAR/7za not found or file failed to extract!')
|
||||
sys.exit(21)
|
||||
else:
|
||||
rmtree(workdir, True)
|
||||
@@ -592,7 +594,7 @@ def checkComicInfo(path, originalPath):
|
||||
if os.path.exists(xmlPath):
|
||||
try:
|
||||
xml = parse(xmlPath)
|
||||
except StandardError:
|
||||
except Exception:
|
||||
os.remove(xmlPath)
|
||||
return
|
||||
options.authors = []
|
||||
@@ -628,18 +630,14 @@ def checkComicInfo(path, originalPath):
|
||||
os.remove(xmlPath)
|
||||
|
||||
|
||||
def slugify(value):
|
||||
# Normalizes string, converts to lowercase, removes non-alpha characters and converts spaces to hyphens.
|
||||
if isinstance(value, str):
|
||||
#noinspection PyArgumentList
|
||||
value = unicodedata.normalize('NFKD', unicode(value, 'latin1')).encode('ascii', 'ignore')
|
||||
elif isinstance(value, unicode):
|
||||
value = unicodedata.normalize('NFKD', value).encode('ascii', 'ignore')
|
||||
value = re.sub('[^\w\s\.-]', '', value).strip().lower()
|
||||
value = re.sub('[-\.\s]+', '-', value)
|
||||
value = re.sub(r'([0-9]+)', r'00000\1', value)
|
||||
value = re.sub(r'0*([0-9]{6,})', r'\1', value)
|
||||
return value
|
||||
#def slugify(value):
|
||||
# # Normalizes string, converts to lowercase, removes non-alpha characters and converts spaces to hyphens.
|
||||
# value = unicodedata.normalize('NFKD', value).encode('ascii', 'ignore')
|
||||
# value = re.sub('[^\w\s\.-]', '', value).strip().lower()
|
||||
# value = re.sub('[-\.\s]+', '-', value)
|
||||
# value = re.sub(r'([0-9]+)', r'00000\1', value)
|
||||
# value = re.sub(r'0*([0-9]{6,})', r'\1', value)
|
||||
# return value
|
||||
|
||||
|
||||
def sanitizeTree(filetree):
|
||||
@@ -775,7 +773,7 @@ def preSplitDirectory(path):
|
||||
mode = 0
|
||||
else:
|
||||
if filesNumber > 0:
|
||||
print '\nWARNING: Automatic output splitting failed.'
|
||||
print('\nWARNING: Automatic output splitting failed.')
|
||||
if GUI:
|
||||
GUI.emit(QtCore.SIGNAL("addMessage"), 'Automatic output splitting failed. <a href='
|
||||
'"https://github.com/ciromattia/kcc/wiki'
|
||||
@@ -790,7 +788,7 @@ def preSplitDirectory(path):
|
||||
if len(dirs) != 0:
|
||||
detectedSubSubdirectories = True
|
||||
elif len(dirs) == 0 and detectedSubSubdirectories:
|
||||
print '\nWARNING: Automatic output splitting failed.'
|
||||
print('\nWARNING: Automatic output splitting failed.')
|
||||
if GUI:
|
||||
GUI.emit(QtCore.SIGNAL("addMessage"), 'Automatic output splitting failed. <a href='
|
||||
'"https://github.com/ciromattia/kcc/wiki'
|
||||
@@ -807,7 +805,7 @@ def preSplitDirectory(path):
|
||||
# One level of subdirectories
|
||||
mode = 1
|
||||
if detectedFilesInSubdirectories and detectedSubSubdirectories:
|
||||
print '\nWARNING: Automatic output splitting failed.'
|
||||
print('\nWARNING: Automatic output splitting failed.')
|
||||
if GUI:
|
||||
GUI.emit(QtCore.SIGNAL("addMessage"), 'Automatic output splitting failed. <a href='
|
||||
'"https://github.com/ciromattia/kcc/wiki'
|
||||
@@ -827,12 +825,12 @@ def preSplitDirectory(path):
|
||||
|
||||
|
||||
def Copyright():
|
||||
print ('comic2ebook v%(__version__)s. '
|
||||
'Written 2013 by Ciro Mattia Gonano and Pawel Jastrzebski.' % globals())
|
||||
print(('comic2ebook v%(__version__)s. '
|
||||
'Written 2013 by Ciro Mattia Gonano and Pawel Jastrzebski.' % globals()))
|
||||
|
||||
|
||||
def Usage():
|
||||
print "Generates EPUB/CBZ comic ebook from a bunch of images."
|
||||
print("Generates EPUB/CBZ comic ebook from a bunch of images.")
|
||||
parser.print_help()
|
||||
|
||||
|
||||
@@ -916,7 +914,7 @@ def main(argv=None, qtGUI=None):
|
||||
else:
|
||||
comic2panel.main(['-y ' + str(image.ProfileData.Profiles[options.profile][1][1]), '-i', path], qtGUI)
|
||||
if options.imgproc:
|
||||
print "\nProcessing images..."
|
||||
print("\nProcessing images...")
|
||||
if GUI:
|
||||
GUI.emit(QtCore.SIGNAL("progressBarTick"), 'status', 'Processing images')
|
||||
dirImgProcess(path + "/OEBPS/Images/")
|
||||
@@ -943,14 +941,14 @@ def main(argv=None, qtGUI=None):
|
||||
options.title = options.baseTitle + ' [' + str(tomeNumber) + '/' + str(len(tomes)) + ']'
|
||||
if options.cbzoutput:
|
||||
# if CBZ output wanted, compress all images and return filepath
|
||||
print "\nCreating CBZ file..."
|
||||
print("\nCreating CBZ file...")
|
||||
if len(tomes) > 1:
|
||||
filepath.append(getOutputFilename(args[0], options.output, '.cbz', ' ' + str(tomeNumber)))
|
||||
else:
|
||||
filepath.append(getOutputFilename(args[0], options.output, '.cbz', ''))
|
||||
make_archive(tome + '_comic', 'zip', tome + '/OEBPS/Images')
|
||||
else:
|
||||
print "\nCreating EPUB structure..."
|
||||
print("\nCreating EPUB structure...")
|
||||
genEpubStruct(tome)
|
||||
# actually zip the ePub
|
||||
if len(tomes) > 1:
|
||||
@@ -1017,7 +1015,7 @@ def checkOptions():
|
||||
options.quality = 0
|
||||
# Kindle for Android profile require target resolution.
|
||||
if options.profile == 'KFA' and (options.customwidth == 0 or options.customheight == 0):
|
||||
print "ERROR: Kindle for Android profile require --customwidth and --customheight options!"
|
||||
print("ERROR: Kindle for Android profile require --customwidth and --customheight options!")
|
||||
sys.exit(1)
|
||||
# Override profile data
|
||||
if options.customwidth != 0 or options.customheight != 0:
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
# PERFORMANCE OF THIS SOFTWARE.
|
||||
#
|
||||
__version__ = '3.6'
|
||||
__version__ = '4.0'
|
||||
__license__ = 'ISC'
|
||||
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
@@ -32,26 +32,26 @@ try:
|
||||
#noinspection PyUnresolvedReferences
|
||||
from PIL import Image, ImageStat
|
||||
if tuple(map(int, ('2.2.1'.split(".")))) > tuple(map(int, (Image.PILLOW_VERSION.split(".")))):
|
||||
print "ERROR: Pillow 2.2.1 or newer is required!"
|
||||
print("ERROR: Pillow 2.2.1 or newer is required!")
|
||||
if sys.platform.startswith('linux'):
|
||||
#noinspection PyUnresolvedReferences
|
||||
import Tkinter
|
||||
import tkinter
|
||||
#noinspection PyUnresolvedReferences
|
||||
import tkMessageBox
|
||||
importRoot = Tkinter.Tk()
|
||||
import tkinter.messagebox
|
||||
importRoot = tkinter.Tk()
|
||||
importRoot.withdraw()
|
||||
tkMessageBox.showerror("KCC - Error", "Pillow 2.2.1 or newer is required!")
|
||||
tkinter.messagebox.showerror("KCC - Error", "Pillow 2.2.1 or newer is required!")
|
||||
exit(1)
|
||||
except ImportError:
|
||||
print "ERROR: Pillow is not installed!"
|
||||
print("ERROR: Pillow is not installed!")
|
||||
if sys.platform.startswith('linux'):
|
||||
#noinspection PyUnresolvedReferences
|
||||
import Tkinter
|
||||
import tkinter
|
||||
#noinspection PyUnresolvedReferences
|
||||
import tkMessageBox
|
||||
importRoot = Tkinter.Tk()
|
||||
import tkinter.messagebox
|
||||
importRoot = tkinter.Tk()
|
||||
importRoot.withdraw()
|
||||
tkMessageBox.showerror("KCC - Error", "Pillow 2.2.1 or newer is required!")
|
||||
tkinter.messagebox.showerror("KCC - Error", "Pillow 2.2.1 or newer is required!")
|
||||
exit(1)
|
||||
try:
|
||||
from PyQt4 import QtCore
|
||||
@@ -118,7 +118,7 @@ def splitImage(work):
|
||||
# Harcoded opttions
|
||||
threshold = 1.0
|
||||
delta = 15
|
||||
print ".",
|
||||
print(".", end=' ')
|
||||
fileExpanded = os.path.splitext(name)
|
||||
filePath = os.path.join(path, name)
|
||||
# Detect corrupted files
|
||||
@@ -210,13 +210,13 @@ def splitImage(work):
|
||||
str(pageNumber) + '.png'), 'PNG')
|
||||
pageNumber += 1
|
||||
os.remove(filePath)
|
||||
except StandardError:
|
||||
except Exception:
|
||||
return str(sys.exc_info()[1])
|
||||
|
||||
|
||||
def Copyright():
|
||||
print ('comic2panel v%(__version__)s. '
|
||||
'Written 2013 by Ciro Mattia Gonano and Pawel Jastrzebski.' % globals())
|
||||
print(('comic2panel v%(__version__)s. '
|
||||
'Written 2013 by Ciro Mattia Gonano and Pawel Jastrzebski.' % globals()))
|
||||
|
||||
|
||||
def main(argv=None, qtGUI=None):
|
||||
@@ -245,7 +245,7 @@ def main(argv=None, qtGUI=None):
|
||||
if options.height > 0:
|
||||
options.sourceDir = args[0]
|
||||
options.targetDir = args[0] + "-Splitted"
|
||||
print "\nSplitting images..."
|
||||
print("\nSplitting images...")
|
||||
if os.path.isdir(options.sourceDir):
|
||||
rmtree(options.targetDir, True)
|
||||
copytree(options.sourceDir, options.targetDir)
|
||||
|
||||
24
kcc/image.py
24
kcc/image.py
@@ -26,26 +26,26 @@ try:
|
||||
# noinspection PyUnresolvedReferences
|
||||
from PIL import Image, ImageOps, ImageStat, ImageChops
|
||||
if tuple(map(int, ('2.2.1'.split(".")))) > tuple(map(int, (Image.PILLOW_VERSION.split(".")))):
|
||||
print "ERROR: Pillow 2.2.1 or newer is required!"
|
||||
print("ERROR: Pillow 2.2.1 or newer is required!")
|
||||
if platform.startswith('linux'):
|
||||
#noinspection PyUnresolvedReferences
|
||||
import Tkinter
|
||||
import tkinter
|
||||
#noinspection PyUnresolvedReferences
|
||||
import tkMessageBox
|
||||
importRoot = Tkinter.Tk()
|
||||
import tkinter.messagebox
|
||||
importRoot = tkinter.Tk()
|
||||
importRoot.withdraw()
|
||||
tkMessageBox.showerror("KCC - Error", "Pillow 2.2.1 or newer is required!")
|
||||
tkinter.messagebox.showerror("KCC - Error", "Pillow 2.2.1 or newer is required!")
|
||||
exit(1)
|
||||
except ImportError:
|
||||
print "ERROR: Pillow is not installed!"
|
||||
print("ERROR: Pillow is not installed!")
|
||||
if platform.startswith('linux'):
|
||||
#noinspection PyUnresolvedReferences
|
||||
import Tkinter
|
||||
import tkinter
|
||||
#noinspection PyUnresolvedReferences
|
||||
import tkMessageBox
|
||||
importRoot = Tkinter.Tk()
|
||||
import tkinter.messagebox
|
||||
importRoot = tkinter.Tk()
|
||||
importRoot.withdraw()
|
||||
tkMessageBox.showerror("KCC - Error", "Pillow 2.2.1 or newer is required!")
|
||||
tkinter.messagebox.showerror("KCC - Error", "Pillow 2.2.1 or newer is required!")
|
||||
exit(1)
|
||||
|
||||
|
||||
@@ -287,10 +287,10 @@ class ComicPage:
|
||||
ratioDev = float(self.size[0]) / float(self.size[1])
|
||||
if (float(self.image.size[0]) / float(self.image.size[1])) < ratioDev:
|
||||
diff = int(self.image.size[1] * ratioDev) - self.image.size[0]
|
||||
self.image = ImageOps.expand(self.image, border=(diff / 2, 0), fill=fill)
|
||||
self.image = ImageOps.expand(self.image, border=(int(diff / 2), 0), fill=fill)
|
||||
elif (float(self.image.size[0]) / float(self.image.size[1])) > ratioDev:
|
||||
diff = int(self.image.size[0] / ratioDev) - self.image.size[1]
|
||||
self.image = ImageOps.expand(self.image, border=(0, diff / 2), fill=fill)
|
||||
self.image = ImageOps.expand(self.image, border=(0, int(diff / 2)), fill=fill)
|
||||
self.image = ImageOps.fit(self.image, size, method=method, centering=(0.5, 0.5))
|
||||
if generateBorder:
|
||||
if fill == 'white':
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Based on initial version of KindleUnpack. Copyright (C) 2009 Charles M. Hannum <root@ihack.net>
|
||||
# Improvements Copyright (C) 2009-2012 P. Durrant, K. Hendricks, S. Siebert, fandrieu, DiapDealer, nickredding
|
||||
# Copyright (C) 2013 Pawel Jastrzebski <pawelj@vulturis.eu>
|
||||
@@ -105,8 +108,8 @@ def nullsection(datain, secno): # make it zero-length without deleting it
|
||||
datalst.append('\0' * lpad)
|
||||
datalst.append(datain[zerosecstart: secstart])
|
||||
datalst.append(datain[secend:])
|
||||
dataout = "".join(datalst)
|
||||
return dataout
|
||||
dataout = "".join(str(datalst)[1:-1])
|
||||
return dataout.encode('utf-8')
|
||||
|
||||
|
||||
def deletesectionrange(datain, firstsec, lastsec): # delete a range of sections
|
||||
@@ -135,8 +138,8 @@ def deletesectionrange(datain, firstsec, lastsec): # delete a range of sections
|
||||
datalst.append('\0' * lpad)
|
||||
datalst.append(datain[zerosecstart:firstsecstart])
|
||||
datalst.append(datain[lastsecend:])
|
||||
dataout = "".join(datalst)
|
||||
return dataout
|
||||
dataout = "".join(str(datalst)[1:-1])
|
||||
return dataout.encode('utf-8')
|
||||
|
||||
|
||||
def insertsection(datain, secno, secdata): # insert a new section
|
||||
@@ -166,13 +169,14 @@ def insertsection(datain, secno, secdata): # insert a new section
|
||||
datalst.append(datain[zerosecstart:secstart])
|
||||
datalst.append(secdata)
|
||||
datalst.append(datain[secstart:])
|
||||
dataout = "".join(datalst)
|
||||
return dataout
|
||||
dataout = "".join(str(datalst)[1:-1])
|
||||
return dataout.encode('utf-8')
|
||||
|
||||
|
||||
def insertsectionrange(sectionsource, firstsec, lastsec, sectiontarget, targetsec): # insert a range of sections
|
||||
dataout = sectiontarget
|
||||
for idx in range(lastsec, firstsec-1, -1):
|
||||
print(dataout)
|
||||
dataout = insertsection(dataout, targetsec, readsection(sectionsource, idx))
|
||||
return dataout
|
||||
|
||||
@@ -381,4 +385,10 @@ class mobi_split:
|
||||
raise
|
||||
|
||||
def getResult(self):
|
||||
return self.result_file
|
||||
return self.result_file
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
mobi_split(sys.argv[1], False)
|
||||
sys.exit(0)
|
||||
|
||||
@@ -63,7 +63,7 @@ class PdfJpgExtract:
|
||||
|
||||
istart += startfix
|
||||
iend += endfix
|
||||
print "JPG %d from %d to %d" % (njpg, istart, iend)
|
||||
print("JPG %d from %d to %d" % (njpg, istart, iend))
|
||||
jpg = pdf[istart:iend]
|
||||
jpgfile = file(self.path + "/jpg%d.jpg" % njpg, "wb")
|
||||
jpgfile.write(jpg)
|
||||
|
||||
@@ -633,7 +633,7 @@ class RarFile(object):
|
||||
def printdir(self):
|
||||
"""Print archive file list to stdout."""
|
||||
for f in self._info_list:
|
||||
print(f.filename)
|
||||
print((f.filename))
|
||||
|
||||
def extract(self, member, path=None, pwd=None):
|
||||
"""Extract single file into current directory.
|
||||
@@ -1138,7 +1138,7 @@ class RarFile(object):
|
||||
if self._crc_check:
|
||||
crc = crc32(cmt)
|
||||
if crc < 0:
|
||||
crc += (long(1) << 32)
|
||||
crc += (int(1) << 32)
|
||||
if crc != inf.CRC:
|
||||
return None
|
||||
|
||||
@@ -1342,7 +1342,7 @@ class RarExtFile(RawIOBase):
|
||||
raise BadRarFile("Failed the read enough data")
|
||||
crc = self.CRC
|
||||
if crc < 0:
|
||||
crc += (long(1) << 32)
|
||||
crc += (int(1) << 32)
|
||||
if crc != self.inf.CRC:
|
||||
raise BadRarFile("Corrupt file - CRC check failed: " + self.inf.filename)
|
||||
|
||||
|
||||
4
requirements.txt
Normal file
4
requirements.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
Pillow==2.2.1
|
||||
Unidecode==0.04.14
|
||||
psutil==1.1.3
|
||||
python-slugify==0.0.6
|
||||
8
setup.py
8
setup.py
@@ -11,7 +11,7 @@ Usage (Windows):
|
||||
from sys import platform
|
||||
|
||||
NAME = "KindleComicConverter"
|
||||
VERSION = "3.6"
|
||||
VERSION = "4.0"
|
||||
MAIN = "kcc.py"
|
||||
|
||||
if platform == "darwin":
|
||||
@@ -72,7 +72,7 @@ elif platform == "win32":
|
||||
appendScriptToLibrary=False,
|
||||
compress=True)])
|
||||
else:
|
||||
print 'Please use setup.sh to build Linux package.'
|
||||
print('Please use setup.sh to build Linux package.')
|
||||
exit()
|
||||
|
||||
#noinspection PyUnboundLocalVariable
|
||||
@@ -91,5 +91,5 @@ setup(
|
||||
|
||||
if platform == "darwin":
|
||||
from os import chmod
|
||||
chmod('dist/' + NAME + '.app/Contents/Resources/unrar', 0777)
|
||||
chmod('dist/' + NAME + '.app/Contents/Resources/7za', 0777)
|
||||
chmod('dist/' + NAME + '.app/Contents/Resources/unrar', 0o777)
|
||||
chmod('dist/' + NAME + '.app/Contents/Resources/7za', 0o777)
|
||||
Reference in New Issue
Block a user