Python3 and QT5 upgrade (#109)

* Tweaked search string based on new comic vine search behavior
Placated Beaufitul Soup by passing the parser

* First cut at porting to Python 3 and PyQt5

* remove debug print

* tweaked progress dialog handling for issues on ubuntu gui

* Handle bad key more gracefullu

* More integration of unrarlib into settings and rest of app

* Better handling of "personal" unrar lib setting

* PEP 440-compliant version string

* Tuned linux rar help strings

* Got setup working again
* Attempts to build unrar on install
* Some minimal desktop integration on various platforms

* Fix wrong shortfile

* More setup.py enhancements
* Use proper temp file
* Added comment block at top

* Comment out desktop integration attempt for now

* Updated some links and info

* Fixed the html a bit

* Repaired some images that caused libpng to complain

* update readme re:  py3qt5 branch changes

* another note

* #108 feat: try to simplify windows build using only pip and python3

* #108 feat: fix python location on appveyor (try 1)

* #108 feat: use venv (try 2)

* #108 feat: use venv (try 3)

* #108 feat: update to latest pyinstaller develop branch

* #108 feat: update to latest pyinstaller develop branch (again)

* #108: add ssl libraries for windows packaging

* #108: refresh env in win build to pick the right mingw

* #108: change order of win build script operations

* #113: fix subprocess usage in pyinstaller package

* bump version
This commit is contained in:
davide-romanini 2018-09-19 22:05:39 +02:00 committed by GitHub
parent d05133bd57
commit 8918369b05
8 changed files with 97 additions and 86 deletions

View File

@ -19,8 +19,8 @@ import xml.etree.ElementTree as ET
#from pprint import pprint
#import zipfile
from genericmetadata import GenericMetadata
import utils
from .genericmetadata import GenericMetadata
from . import utils
class CoMet:
@ -76,7 +76,7 @@ class CoMet:
# helper func
def assign(comet_entry, md_entry):
if md_entry is not None:
ET.SubElement(root, comet_entry).text = u"{0}".format(md_entry)
ET.SubElement(root, comet_entry).text = "{0}".format(md_entry)
# title is manditory
if md.title is None:
@ -131,43 +131,43 @@ class CoMet:
if credit['role'].lower() in set(self.writer_synonyms):
ET.SubElement(
root,
'writer').text = u"{0}".format(
'writer').text = "{0}".format(
credit['person'])
if credit['role'].lower() in set(self.penciller_synonyms):
ET.SubElement(
root,
'penciller').text = u"{0}".format(
'penciller').text = "{0}".format(
credit['person'])
if credit['role'].lower() in set(self.inker_synonyms):
ET.SubElement(
root,
'inker').text = u"{0}".format(
'inker').text = "{0}".format(
credit['person'])
if credit['role'].lower() in set(self.colorist_synonyms):
ET.SubElement(
root,
'colorist').text = u"{0}".format(
'colorist').text = "{0}".format(
credit['person'])
if credit['role'].lower() in set(self.letterer_synonyms):
ET.SubElement(
root,
'letterer').text = u"{0}".format(
'letterer').text = "{0}".format(
credit['person'])
if credit['role'].lower() in set(self.cover_synonyms):
ET.SubElement(
root,
'coverDesigner').text = u"{0}".format(
'coverDesigner').text = "{0}".format(
credit['person'])
if credit['role'].lower() in set(self.editor_synonyms):
ET.SubElement(
root,
'editor').text = u"{0}".format(
'editor').text = "{0}".format(
credit['person'])
# self pretty-print

View File

@ -23,7 +23,7 @@ import subprocess
import platform
import ctypes
import time
import StringIO
import io
#import io
#import locale
#import shutil
@ -65,12 +65,13 @@ try:
self._data += chunk
return 1
rarfile._ReadIntoMemory._callback = _rar_cb
except:
print "WARNING: cannot find libunrar, rar support is disabled"
except Exception as e:
print(e)
print("WARNING: cannot find libunrar, rar support is disabled")
pass
if platform.system() == "Windows":
import _subprocess
#if platform.system() == "Windows":
# import _subprocess
try:
import Image
@ -78,11 +79,11 @@ try:
except ImportError:
pil_available = False
from comicinfoxml import ComicInfoXml
from comicbookinfo import ComicBookInfo
from comet import CoMet
from genericmetadata import GenericMetadata, PageType
from filenameparser import FileNameParser
from .comicinfoxml import ComicInfoXml
from .comicbookinfo import ComicBookInfo
from .comet import CoMet
from .genericmetadata import GenericMetadata, PageType
from .filenameparser import FileNameParser
#from settings import ComicTaggerSettings
@ -109,7 +110,10 @@ class ZipArchiver:
return comment
def setArchiveComment(self, comment):
return self.writeZipComment(self.path, comment)
zf = zipfile.ZipFile(self.path, 'a')
zf.comment = bytes(comment, 'utf-8')
zf.close()
return True
def readArchiveFile(self, archive_file):
data = ""
@ -118,14 +122,13 @@ class ZipArchiver:
try:
data = zf.read(archive_file)
except zipfile.BadZipfile as e:
print >> sys.stderr, u"bad zipfile [{0}]: {1} :: {2}".format(
e, self.path, archive_file)
print("bad zipfile [{0}]: {1} :: {2}".format(e, self.path, archive_file), file=sys.stderr)
zf.close()
raise IOError
except Exception as e:
zf.close()
print >> sys.stderr, u"bad zipfile [{0}]: {1} :: {2}".format(
e, self.path, archive_file)
print("bad zipfile [{0}]: {1} :: {2}".format(
e, self.path, archive_file), file=sys.stderr)
raise IOError
finally:
zf.close()
@ -164,8 +167,8 @@ class ZipArchiver:
zf.close()
return namelist
except Exception as e:
print >> sys.stderr, u"Unable to get zipfile list [{0}]: {1}".format(
e, self.path)
print("Unable to get zipfile list [{0}]: {1}".format(
e, self.path), file=sys.stderr)
return []
def rebuildZipFile(self, exclude_list):
@ -253,12 +256,12 @@ class ZipArchiver:
fo.seek(pos + 2, 2)
# write out the comment itself
fo.write(comment)
fo.write(bytes(comment))
fo.truncate()
fo.close()
else:
raise Exception('Failed to write comment to zip file!')
except:
except Exception as e:
return False
else:
return True
@ -280,8 +283,8 @@ class ZipArchiver:
if not self.writeZipComment(self.path, comment):
return False
except Exception as e:
print >> sys.stderr, u"Error while copying to {0}: {1}".format(
self.path, e)
print("Error while copying to {0}: {1}".format(
self.path, e), file=sys.stderr)
return False
else:
return True
@ -305,7 +308,7 @@ class RarArchiver:
# windows only, keeps the cmd.exe from popping up
if platform.system() == "Windows":
self.startupinfo = subprocess.STARTUPINFO()
self.startupinfo.dwFlags |= _subprocess.STARTF_USESHOWWINDOW
self.startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
else:
self.startupinfo = None
@ -314,37 +317,38 @@ class RarArchiver:
pass
def getArchiveComment(self):
rarc = self.getRARObj()
return rarc.comment
def setArchiveComment(self, comment):
if self.rar_exe_path is not None:
try:
# write comment to temp file
tmp_fd, tmp_name = tempfile.mkstemp()
f = os.fdopen(tmp_fd, 'w+b')
f = os.fdopen(tmp_fd, 'w+')
f.write(comment)
f.close()
working_dir = os.path.dirname(os.path.abspath(self.path))
# use external program to write comment to Rar archive
subprocess.call([self.rar_exe_path,
proc_args = [self.rar_exe_path,
'c',
'-w' + working_dir,
'-c-',
'-z' + tmp_name,
self.path],
self.path]
subprocess.call(proc_args,
startupinfo=self.startupinfo,
stdout=RarArchiver.devnull)
stdout=RarArchiver.devnull,
stdin=RarArchiver.devnull,
stderr=RarArchiver.devnull)
if platform.system() == "Darwin":
time.sleep(1)
os.remove(tmp_name)
except:
except Exception as e:
print(e)
return False
else:
return True
@ -376,26 +380,26 @@ class RarArchiver:
#entries = rarc.read_files( archive_file )
if entries[0][0].file_size != len(entries[0][1]):
print >> sys.stderr, u"readArchiveFile(): [file is not expected size: {0} vs {1}] {2}:{3} [attempt # {4}]".format(
print("readArchiveFile(): [file is not expected size: {0} vs {1}] {2}:{3} [attempt # {4}]".format(
entries[0][0].file_size, len(
entries[0][1]), self.path, archive_file, tries)
entries[0][1]), self.path, archive_file, tries), file=sys.stderr)
continue
except (OSError, IOError) as e:
print >> sys.stderr, u"readArchiveFile(): [{0}] {1}:{2} attempt#{3}".format(
str(e), self.path, archive_file, tries)
print("readArchiveFile(): [{0}] {1}:{2} attempt#{3}".format(
str(e), self.path, archive_file, tries), file=sys.stderr)
time.sleep(1)
except Exception as e:
print >> sys.stderr, u"Unexpected exception in readArchiveFile(): [{0}] for {1}:{2} attempt#{3}".format(
str(e), self.path, archive_file, tries)
print("Unexpected exception in readArchiveFile(): [{0}] for {1}:{2} attempt#{3}".format(
str(e), self.path, archive_file, tries), file=sys.stderr)
break
else:
# Success"
# entries is a list of of tuples: ( rarinfo, filedata)
if tries > 1:
print >> sys.stderr, u"Attempted read_files() {0} times".format(
tries)
print("Attempted read_files() {0} times".format(
tries), file=sys.stderr)
if (len(entries) == 1):
return entries[0][1]
else:
@ -428,7 +432,9 @@ class RarArchiver:
self.path,
tmp_file],
startupinfo=self.startupinfo,
stdout=RarArchiver.devnull)
stdout=RarArchiver.devnull,
stdin=RarArchiver.devnull,
stderr=RarArchiver.devnull)
if platform.system() == "Darwin":
time.sleep(1)
@ -451,7 +457,9 @@ class RarArchiver:
self.path,
archive_file],
startupinfo=self.startupinfo,
stdout=RarArchiver.devnull)
stdout=RarArchiver.devnull,
stdin=RarArchiver.devnull,
stderr=RarArchiver.devnull)
if platform.system() == "Darwin":
time.sleep(1)
@ -479,8 +487,8 @@ class RarArchiver:
namelist.append(item.filename)
except (OSError, IOError) as e:
print >> sys.stderr, u"getArchiveFilenameList(): [{0}] {1} attempt#{2}".format(
str(e), self.path, tries)
print("getArchiveFilenameList(): [{0}] {1} attempt#{2}".format(
str(e), self.path, tries), file=sys.stderr)
time.sleep(1)
else:
@ -497,8 +505,8 @@ class RarArchiver:
rarc = rarfile.RarFile( self.path )
except (OSError, IOError) as e:
print >> sys.stderr, u"getRARObj(): [{0}] {1} attempt#{2}".format(
str(e), self.path, tries)
print("getRARObj(): [{0}] {1} attempt#{2}".format(
str(e), self.path, tries), file=sys.stderr)
time.sleep(1)
else:
@ -634,7 +642,7 @@ class ComicArchive:
logo_data = None
class ArchiveType:
Zip, Rar, Folder, Pdf, Unknown = range(5)
Zip, Rar, Folder, Pdf, Unknown = list(range(5))
def __init__(self, path, rar_exe_path=None, default_image_path=None):
self.path = path
@ -729,7 +737,7 @@ class ComicArchive:
if self.archive_type == self.ArchiveType.Unknown:
return False
elif check_rar_status and self.isRar() and self.rar_exe_path is None:
elif check_rar_status and self.isRar() and not self.rar_exe_path:
return False
elif not os.access(self.path, os.W_OK):
@ -817,7 +825,7 @@ class ComicArchive:
try:
image_data = self.archiver.readArchiveFile(filename)
except IOError:
print >> sys.stderr, u"Error reading in page. Substituting logo page."
print("Error reading in page. Substituting logo page.", file=sys.stderr)
image_data = ComicArchive.logo_data
return image_data
@ -859,7 +867,7 @@ class ComicArchive:
# sort by most common
sorted_buckets = sorted(
length_buckets.iteritems(),
iter(length_buckets.items()),
key=lambda k_v: (
k_v[1],
k_v[0]),
@ -1006,7 +1014,7 @@ class ComicArchive:
try:
raw_cix = self.archiver.readArchiveFile(self.ci_xml_filename)
except IOError:
print "Error reading in raw CIX!"
print("Error reading in raw CIX!")
raw_cix = ""
return raw_cix
@ -1075,13 +1083,13 @@ class ComicArchive:
def readRawCoMet(self):
if not self.hasCoMet():
print >> sys.stderr, self.path, "doesn't have CoMet data!"
print(self.path, "doesn't have CoMet data!", file=sys.stderr)
return None
try:
raw_comet = self.archiver.readArchiveFile(self.comet_filename)
except IOError:
print >> sys.stderr, u"Error reading in raw CoMet!"
print("Error reading in raw CoMet!", file=sys.stderr)
raw_comet = ""
return raw_comet
@ -1136,7 +1144,7 @@ class ComicArchive:
data = self.archiver.readArchiveFile(n)
except:
data = ""
print >> sys.stderr, u"Error reading in Comet XML for validation!"
print("Error reading in Comet XML for validation!", file=sys.stderr)
if CoMet().validateString(data):
# since we found it, save it!
self.comet_filename = n
@ -1156,7 +1164,7 @@ class ComicArchive:
data = self.getPage(idx)
if data is not None:
try:
im = Image.open(StringIO.StringIO(data))
im = Image.open(io.StringIO(data))
w, h = im.size
p['ImageSize'] = str(len(data))

View File

@ -18,8 +18,8 @@ import json
from datetime import datetime
#import zipfile
from genericmetadata import GenericMetadata
import utils
from .genericmetadata import GenericMetadata
from . import utils
#import ctversion
@ -27,7 +27,7 @@ class ComicBookInfo:
def metadataFromString(self, string):
cbi_container = json.loads(unicode(string, 'utf-8'))
cbi_container = json.loads(str(string, 'utf-8'))
metadata = GenericMetadata()
@ -109,7 +109,7 @@ class ComicBookInfo:
# helper func
def toInt(s):
i = None
if type(s) in [str, unicode, int]:
if type(s) in [str, str, int]:
try:
i = int(s)
except ValueError:

View File

@ -19,8 +19,8 @@ import xml.etree.ElementTree as ET
#from pprint import pprint
#import zipfile
from genericmetadata import GenericMetadata
import utils
from .genericmetadata import GenericMetadata
from . import utils
class ComicInfoXml:
@ -54,7 +54,8 @@ class ComicInfoXml:
header = '<?xml version="1.0"?>\n'
tree = self.convertMetadataToXML(self, metadata)
return header + ET.tostring(tree.getroot())
tree_str = ET.tostring(tree.getroot()).decode()
return header + tree_str
def indent(self, elem, level=0):
# for making the XML output readable
@ -85,7 +86,7 @@ class ComicInfoXml:
def assign(cix_entry, md_entry):
if md_entry is not None:
ET.SubElement(root, cix_entry).text = u"{0}".format(md_entry)
ET.SubElement(root, cix_entry).text = "{0}".format(md_entry)
assign('Title', md.title)
assign('Series', md.series)

View File

@ -22,7 +22,7 @@ This should probably be re-written, but, well, it mostly works!
import re
import os
from urllib import unquote
from urllib.parse import unquote
class FileNameParser:

View File

@ -20,7 +20,7 @@ possible, however lossy it might be
# See the License for the specific language governing permissions and
# limitations under the License.
import utils
from . import utils
class PageType:
@ -251,7 +251,7 @@ class GenericMetadata:
return "No metadata"
def add_string(tag, val):
if val is not None and u"{0}".format(val) != "":
if val is not None and "{0}".format(val) != "":
vals.append((tag, val))
def add_attr_string(tag):
@ -314,7 +314,7 @@ class GenericMetadata:
# format the data nicely
outstr = ""
fmt_str = u"{0: <" + str(flen) + "} {1}\n"
fmt_str = "{0: <" + str(flen) + "} {1}\n"
for i in vals:
outstr += fmt_str.format(i[0] + ":", i[1])

View File

@ -44,7 +44,7 @@ class IssueString:
if len(text) == 0:
return
text = unicode(text)
text = str(text)
# skip the minus sign if it's first
if text[0] == '-':
@ -119,7 +119,7 @@ class IssueString:
def asFloat(self):
# return the float, with no suffix
if self.suffix == u"½":
if self.suffix == "½":
if self.num is not None:
return self.num + .5
else:

View File

@ -55,20 +55,22 @@ def get_recursive_filelist(pathlist):
# if path is a folder, walk it recursively, and all files underneath
if isinstance(p, str):
# make sure string is unicode
p = p.decode(filename_encoding) # , 'replace')
elif not isinstance(p, unicode):
#p = p.decode(filename_encoding) # , 'replace')
pass
elif not isinstance(p, str):
# it's probably a QString
p = unicode(p)
p = str(p)
if os.path.isdir(p):
for root, dirs, files in os.walk(p):
for f in files:
if isinstance(f, str):
# make sure string is unicode
f = f.decode(filename_encoding, 'replace')
elif not isinstance(f, unicode):
#f = f.decode(filename_encoding, 'replace')
pass
elif not isinstance(f, str):
# it's probably a QString
f = unicode(f)
f = str(f)
filelist.append(os.path.join(root, f))
else:
filelist.append(p)
@ -121,7 +123,7 @@ def which(program):
def removearticles(text):
text = text.lower()
articles = ['and', 'the', 'a', '&', 'issue']
articles = ['and', 'a', '&', 'issue']
newText = ''
for word in text.split(' '):
if word not in articles: