Additional glyphicons for music on search and author page
Fix duplicate user and email (now case insensitive) Output of calibre on stderr is now logged (full traceback in debug-log, otherwise, only errormessage) Natural sorting for comic reader Fix for long running tasks
This commit is contained in:
parent
ad44e58c7a
commit
499a66dfb0
33
cps/admin.py
33
cps/admin.py
|
@ -603,13 +603,23 @@ def new_user():
|
||||||
return render_title_template("user_edit.html", new_user=1, content=content, translations=translations,
|
return render_title_template("user_edit.html", new_user=1, content=content, translations=translations,
|
||||||
registered_oauth=oauth_check, title=_(u"Add new user"))
|
registered_oauth=oauth_check, title=_(u"Add new user"))
|
||||||
content.password = generate_password_hash(to_save["password"])
|
content.password = generate_password_hash(to_save["password"])
|
||||||
content.nickname = to_save["nickname"]
|
existing_user = ub.session.query(ub.User).filter(func.lower(ub.User.nickname) == to_save["nickname"].lower())\
|
||||||
if config.config_public_reg and not check_valid_domain(to_save["email"]):
|
.first()
|
||||||
flash(_(u"E-mail is not from valid domain"), category="error")
|
existing_email = ub.session.query(ub.User).filter(ub.User.email == to_save["email"].lower())\
|
||||||
return render_title_template("user_edit.html", new_user=1, content=content, translations=translations,
|
.first()
|
||||||
registered_oauth=oauth_check, title=_(u"Add new user"))
|
if not existing_user and not existing_email:
|
||||||
|
content.nickname = to_save["nickname"]
|
||||||
|
if config.config_public_reg and not check_valid_domain(to_save["email"]):
|
||||||
|
flash(_(u"E-mail is not from valid domain"), category="error")
|
||||||
|
return render_title_template("user_edit.html", new_user=1, content=content, translations=translations,
|
||||||
|
registered_oauth=oauth_check, title=_(u"Add new user"))
|
||||||
|
else:
|
||||||
|
content.email = to_save["email"]
|
||||||
else:
|
else:
|
||||||
content.email = to_save["email"]
|
flash(_(u"Found an existing account for this e-mail address or nickname."), category="error")
|
||||||
|
return render_title_template("user_edit.html", new_user=1, content=content, translations=translations,
|
||||||
|
languages=languages, title=_(u"Add new user"), page="newuser",
|
||||||
|
registered_oauth=oauth_check)
|
||||||
try:
|
try:
|
||||||
ub.session.add(content)
|
ub.session.add(content)
|
||||||
ub.session.commit()
|
ub.session.commit()
|
||||||
|
@ -753,7 +763,16 @@ def edit_user(user_id):
|
||||||
if "locale" in to_save and to_save["locale"]:
|
if "locale" in to_save and to_save["locale"]:
|
||||||
content.locale = to_save["locale"]
|
content.locale = to_save["locale"]
|
||||||
if to_save["email"] and to_save["email"] != content.email:
|
if to_save["email"] and to_save["email"] != content.email:
|
||||||
content.email = to_save["email"]
|
existing_email = ub.session.query(ub.User).filter(ub.User.email == to_save["email"].lower()) \
|
||||||
|
.first()
|
||||||
|
if not existing_email:
|
||||||
|
content.email = to_save["email"]
|
||||||
|
else:
|
||||||
|
flash(_(u"Found an existing account for this e-mail address."), category="error")
|
||||||
|
return render_title_template("user_edit.html", translations=translations, languages=languages,
|
||||||
|
new_user=0, content=content, downloads=downloads, registered_oauth=oauth_check,
|
||||||
|
title=_(u"Edit User %(nick)s", nick=content.nickname), page="edituser")
|
||||||
|
|
||||||
if "kindle_mail" in to_save and to_save["kindle_mail"] != content.kindle_mail:
|
if "kindle_mail" in to_save and to_save["kindle_mail"] != content.kindle_mail:
|
||||||
content.kindle_mail = to_save["kindle_mail"]
|
content.kindle_mail = to_save["kindle_mail"]
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -30,13 +30,14 @@ import requests
|
||||||
import shutil
|
import shutil
|
||||||
import time
|
import time
|
||||||
import unicodedata
|
import unicodedata
|
||||||
from datetime import datetime
|
from datetime import datetime, timedelta
|
||||||
from functools import reduce
|
from functools import reduce
|
||||||
from tempfile import gettempdir
|
from tempfile import gettempdir
|
||||||
|
|
||||||
from babel import Locale as LC
|
from babel import Locale as LC
|
||||||
from babel.core import UnknownLocaleError
|
from babel.core import UnknownLocaleError
|
||||||
from babel.dates import format_datetime
|
from babel.dates import format_datetime, format_timedelta
|
||||||
|
from babel.units import format_unit
|
||||||
from flask import send_from_directory, make_response, redirect, abort
|
from flask import send_from_directory, make_response, redirect, abort
|
||||||
from flask_babel import gettext as _
|
from flask_babel import gettext as _
|
||||||
from flask_login import current_user
|
from flask_login import current_user
|
||||||
|
@ -589,8 +590,34 @@ def json_serial(obj):
|
||||||
|
|
||||||
if isinstance(obj, (datetime)):
|
if isinstance(obj, (datetime)):
|
||||||
return obj.isoformat()
|
return obj.isoformat()
|
||||||
|
if isinstance(obj, (timedelta)):
|
||||||
|
return {
|
||||||
|
'__type__': 'timedelta',
|
||||||
|
'days': obj.days,
|
||||||
|
'seconds': obj.seconds,
|
||||||
|
'microseconds': obj.microseconds,
|
||||||
|
}
|
||||||
|
# return obj.isoformat()
|
||||||
raise TypeError ("Type %s not serializable" % type(obj))
|
raise TypeError ("Type %s not serializable" % type(obj))
|
||||||
|
|
||||||
|
|
||||||
|
# helper function for displaying the runtime of tasks
|
||||||
|
def format_runtime(runtime):
|
||||||
|
retVal = ""
|
||||||
|
if runtime.days:
|
||||||
|
retVal = format_unit(runtime.days, 'duration-day', length="long", locale=web.get_locale()) + ', '
|
||||||
|
mins, seconds = divmod(runtime.seconds, 60)
|
||||||
|
hours, minutes = divmod(mins, 60)
|
||||||
|
# ToDo: locale.number_symbols._data['timeSeparator'] -> localize time separator ?
|
||||||
|
if hours:
|
||||||
|
retVal += '{:d}:{:02d}:{:02d}s'.format(hours, minutes, seconds)
|
||||||
|
elif minutes:
|
||||||
|
retVal += '{:2d}:{:02d}s'.format(minutes, seconds)
|
||||||
|
else:
|
||||||
|
retVal += '{:2d}s'.format(seconds)
|
||||||
|
return retVal
|
||||||
|
|
||||||
|
|
||||||
# helper function to apply localize status information in tasklist entries
|
# helper function to apply localize status information in tasklist entries
|
||||||
def render_task_status(tasklist):
|
def render_task_status(tasklist):
|
||||||
renderedtasklist=list()
|
renderedtasklist=list()
|
||||||
|
@ -603,6 +630,8 @@ def render_task_status(tasklist):
|
||||||
if 'starttime' not in task:
|
if 'starttime' not in task:
|
||||||
task['starttime'] = ""
|
task['starttime'] = ""
|
||||||
|
|
||||||
|
task['runtime'] = format_runtime(task['formRuntime'])
|
||||||
|
|
||||||
# localize the task status
|
# localize the task status
|
||||||
if isinstance( task['stat'], int ):
|
if isinstance( task['stat'], int ):
|
||||||
if task['stat'] == STAT_WAITING:
|
if task['stat'] == STAT_WAITING:
|
||||||
|
|
|
@ -107,7 +107,7 @@ def setup(log_file, log_level=None):
|
||||||
return
|
return
|
||||||
r.debug("logging to %s level %s", log_file, r.level)
|
r.debug("logging to %s level %s", log_file, r.level)
|
||||||
|
|
||||||
if 1 == 1: # log_file == LOG_TO_STDERR:
|
if log_file == LOG_TO_STDERR:
|
||||||
file_handler = StreamHandler()
|
file_handler = StreamHandler()
|
||||||
file_handler.baseFilename = LOG_TO_STDERR
|
file_handler.baseFilename = LOG_TO_STDERR
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -46,14 +46,13 @@ ldap_support = ldap1.ldap_supported()
|
||||||
def requires_basic_auth_if_no_ano(f):
|
def requires_basic_auth_if_no_ano(f):
|
||||||
@wraps(f)
|
@wraps(f)
|
||||||
def decorated(*args, **kwargs):
|
def decorated(*args, **kwargs):
|
||||||
if config.config_login_type == 1 and ldap_support:
|
|
||||||
return ldap1.ldap.basic_auth_required(*args, **kwargs)
|
|
||||||
auth = request.authorization
|
auth = request.authorization
|
||||||
if config.config_anonbrowse != 1:
|
if config.config_anonbrowse != 1:
|
||||||
if not auth or not check_auth(auth.username, auth.password):
|
if not auth or not check_auth(auth.username, auth.password):
|
||||||
return authenticate()
|
return authenticate()
|
||||||
return f(*args, **kwargs)
|
return f(*args, **kwargs)
|
||||||
|
if config.config_login_type == 1 and ldap_support:
|
||||||
|
return ldap1.ldap.basic_auth_required(f)
|
||||||
return decorated
|
return decorated
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,67 @@
|
||||||
|
/* alphanum.js (C) Brian Huisman
|
||||||
|
* Based on the Alphanum Algorithm by David Koelle
|
||||||
|
* The Alphanum Algorithm is discussed at http://www.DaveKoelle.com
|
||||||
|
*
|
||||||
|
* Distributed under same license as original
|
||||||
|
*
|
||||||
|
* Released under the MIT License - https://opensource.org/licenses/MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
|
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
/* ********************************************************************
|
||||||
|
* Alphanum sort() function version - case insensitive
|
||||||
|
* - Slower, but easier to modify for arrays of objects which contain
|
||||||
|
* string properties
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
function alphanumCase(a, b) {
|
||||||
|
function chunkify(t) {
|
||||||
|
var tz = new Array();
|
||||||
|
var x = 0, y = -1, n = 0, i, j;
|
||||||
|
|
||||||
|
while (i = (j = t.charAt(x++)).charCodeAt(0)) {
|
||||||
|
var m = (i == 46 || (i >=48 && i <= 57));
|
||||||
|
if (m !== n) {
|
||||||
|
tz[++y] = "";
|
||||||
|
n = m;
|
||||||
|
}
|
||||||
|
tz[y] += j;
|
||||||
|
}
|
||||||
|
return tz;
|
||||||
|
}
|
||||||
|
|
||||||
|
var aa = chunkify(a.filename.toLowerCase());
|
||||||
|
var bb = chunkify(b.filename.toLowerCase());
|
||||||
|
|
||||||
|
for (x = 0; aa[x] && bb[x]; x++) {
|
||||||
|
if (aa[x] !== bb[x]) {
|
||||||
|
var c = Number(aa[x]), d = Number(bb[x]);
|
||||||
|
if (c == aa[x] && d == bb[x]) {
|
||||||
|
return c - d;
|
||||||
|
} else return (aa[x] > bb[x]) ? 1 : -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return aa.length - bb.length;
|
||||||
|
}
|
||||||
|
// ===========================================================================
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* archive.js
|
* archive.js
|
||||||
*
|
*
|
||||||
|
@ -13,22 +77,6 @@
|
||||||
var bitjs = bitjs || {};
|
var bitjs = bitjs || {};
|
||||||
bitjs.archive = bitjs.archive || {};
|
bitjs.archive = bitjs.archive || {};
|
||||||
|
|
||||||
function naturalCompare(a, b) {
|
|
||||||
var ax = [], bx = [];
|
|
||||||
|
|
||||||
a.filename.toLowerCase().replace(/(\d+)|(\D+)/g, function(_, $1, $2) { ax.push([$1 || Infinity, $2 || ""]) });
|
|
||||||
b.filename.toLowerCase().replace(/(\d+)|(\D+)/g, function(_, $1, $2) { bx.push([$1 || Infinity, $2 || ""]) });
|
|
||||||
|
|
||||||
while(ax.length && bx.length) {
|
|
||||||
var an = ax.shift();
|
|
||||||
var bn = bx.shift();
|
|
||||||
var nn = (an[0] - bn[0]) || an[1].localeCompare(bn[1]);
|
|
||||||
if(nn) return nn;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ax.length - bx.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
// ===========================================================================
|
// ===========================================================================
|
||||||
|
|
|
@ -1332,13 +1332,7 @@ var unrar = function(arrayBuffer) {
|
||||||
totalFilesInArchive = localFiles.length;
|
totalFilesInArchive = localFiles.length;
|
||||||
|
|
||||||
// now we have all information but things are unpacked
|
// now we have all information but things are unpacked
|
||||||
// TODO: unpack
|
localFiles.sort(alphanumCase);
|
||||||
localFiles.sort(naturalCompare);
|
|
||||||
/*localFiles = localFiles.sort(function(a, b) {
|
|
||||||
var aname = a.filename.toLowerCase();
|
|
||||||
var bname = b.filename.toLowerCase();
|
|
||||||
return aname > bname ? 1 : -1;
|
|
||||||
});*/
|
|
||||||
|
|
||||||
info(localFiles.map(function(a) {
|
info(localFiles.map(function(a) {
|
||||||
return a.filename;
|
return a.filename;
|
||||||
|
|
|
@ -136,7 +136,8 @@ var untar = function(arrayBuffer) {
|
||||||
allLocalFiles.push(localFile);
|
allLocalFiles.push(localFile);
|
||||||
postProgress();
|
postProgress();
|
||||||
}
|
}
|
||||||
allLocalFiles.sort(naturalCompare);
|
// got all local files, now sort them
|
||||||
|
allLocalFiles.sort(alphanumCase);
|
||||||
|
|
||||||
allLocalFiles.forEach(function(oneLocalFile) {
|
allLocalFiles.forEach(function(oneLocalFile) {
|
||||||
// While we don't encounter an empty block, keep making TarLocalFiles.
|
// While we don't encounter an empty block, keep making TarLocalFiles.
|
||||||
|
|
|
@ -162,12 +162,7 @@ var unzip = function(arrayBuffer) {
|
||||||
totalFilesInArchive = localFiles.length;
|
totalFilesInArchive = localFiles.length;
|
||||||
|
|
||||||
// got all local files, now sort them
|
// got all local files, now sort them
|
||||||
localFiles.sort(naturalCompare);
|
localFiles.sort(alphanumCase);
|
||||||
/*localFiles.sort(function(a, b) {
|
|
||||||
var aname = a.filename.toLowerCase();
|
|
||||||
var bname = b.filename.toLowerCase();
|
|
||||||
return aname > bname ? 1 : -1;
|
|
||||||
});*/
|
|
||||||
|
|
||||||
// archive extra data record
|
// archive extra data record
|
||||||
if (bstream.peekNumber(4) === zArchiveExtraDataSignature) {
|
if (bstream.peekNumber(4) === zArchiveExtraDataSignature) {
|
||||||
|
@ -663,51 +658,3 @@ function inflate(compressedData, numDecompressedBytes) {
|
||||||
onmessage = function(event) {
|
onmessage = function(event) {
|
||||||
unzip(event.data.file, true);
|
unzip(event.data.file, true);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
function naturalCompare(a, b) {
|
|
||||||
var ax = [], bx = [];
|
|
||||||
|
|
||||||
a.filename.toLowerCase().replace(/(\d+)|(\D+)/g, function(_, $1, $2) { ax.push([$1 || Infinity, $2 || ""]) });
|
|
||||||
b.filename.toLowerCase().replace(/(\d+)|(\D+)/g, function(_, $1, $2) { bx.push([$1 || Infinity, $2 || ""]) });
|
|
||||||
|
|
||||||
while(ax.length && bx.length) {
|
|
||||||
var an = ax.shift();
|
|
||||||
var bn = bx.shift();
|
|
||||||
var nn = (an[0] - bn[0]) || an[1].localeCompare(bn[1]);
|
|
||||||
if(nn) return nn;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ax.length - bx.length;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
|
|
||||||
/*var re = /([a-z]+)(\d+)(.+)/i;
|
|
||||||
function naturalCompare(a, b) {
|
|
||||||
var ma = a.match(re),
|
|
||||||
mb = b.match(re),
|
|
||||||
a_str = ma[1],
|
|
||||||
b_str = mb[1],
|
|
||||||
a_num = parseInt(ma[2],10),
|
|
||||||
b_num = parseInt(mb[2],10),
|
|
||||||
a_rem = ma[3],
|
|
||||||
b_rem = mb[3];
|
|
||||||
return a_str > b_str ? 1 : a_str < b_str ? -1 : a_num > b_num ? 1 : a_num < b_num ? -1 : a_rem > b_rem;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/*function naturalCompare(a, b) {
|
|
||||||
var ax = [], bx = [];
|
|
||||||
|
|
||||||
a.replace(/(\d+)|(\D+)/g, function(_, $1, $2) { ax.push([$1 || Infinity, $2 || ""]) });
|
|
||||||
b.replace(/(\d+)|(\D+)/g, function(_, $1, $2) { bx.push([$1 || Infinity, $2 || ""]) });
|
|
||||||
|
|
||||||
while(ax.length && bx.length) {
|
|
||||||
var an = ax.shift();
|
|
||||||
var bn = bx.shift();
|
|
||||||
var nn = (an[0] - bn[0]) || an[1].localeCompare(bn[1]);
|
|
||||||
if(nn) return nn;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ax.length - bx.length;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ import os
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
|
|
||||||
def process_open(command, quotes=(), env=None, sout=subprocess.PIPE):
|
def process_open(command, quotes=(), env=None, sout=subprocess.PIPE, serr=subprocess.PIPE):
|
||||||
# Linux py2.7 encode as list without quotes no empty element for parameters
|
# Linux py2.7 encode as list without quotes no empty element for parameters
|
||||||
# linux py3.x no encode and as list without quotes no empty element for parameters
|
# linux py3.x no encode and as list without quotes no empty element for parameters
|
||||||
# windows py2.7 encode as string with quotes empty element for parameters is okay
|
# windows py2.7 encode as string with quotes empty element for parameters is okay
|
||||||
|
@ -42,4 +42,4 @@ def process_open(command, quotes=(), env=None, sout=subprocess.PIPE):
|
||||||
else:
|
else:
|
||||||
exc_command = [x for x in command]
|
exc_command = [x for x in command]
|
||||||
|
|
||||||
return subprocess.Popen(exc_command, shell=False, stdout=sout, universal_newlines=True, env=env)
|
return subprocess.Popen(exc_command, shell=False, stdout=sout, stderr=serr, universal_newlines=True, env=env)
|
||||||
|
|
|
@ -64,6 +64,11 @@
|
||||||
<a class="author-name" href="{{url_for('web.books_list', data='author', sort='new', book_id=author.id) }}">{{author.name.replace('|',',')|shortentitle(30)}}</a>
|
<a class="author-name" href="{{url_for('web.books_list', data='author', sort='new', book_id=author.id) }}">{{author.name.replace('|',',')|shortentitle(30)}}</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
{% for format in entry.data %}
|
||||||
|
{% if format.format|lower == 'mp3' %}
|
||||||
|
<span class="glyphicon glyphicon-music"></span>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
</p>
|
</p>
|
||||||
{% if entry.ratings.__len__() > 0 %}
|
{% if entry.ratings.__len__() > 0 %}
|
||||||
<div class="rating">
|
<div class="rating">
|
||||||
|
|
|
@ -61,7 +61,7 @@
|
||||||
{% if loop.index > g.config_authors_max and g.config_authors_max != 0 %}
|
{% if loop.index > g.config_authors_max and g.config_authors_max != 0 %}
|
||||||
{% if not loop.first %}
|
{% if not loop.first %}
|
||||||
<span class="author-hidden-divider">&</span>
|
<span class="author-hidden-divider">&</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<a class="author-name author-hidden" href="{{url_for('web.books_list', data='author', sort='new', book_id=author.id) }}">{{author.name.replace('|',',')|shortentitle(30)}}</a>
|
<a class="author-name author-hidden" href="{{url_for('web.books_list', data='author', sort='new', book_id=author.id) }}">{{author.name.replace('|',',')|shortentitle(30)}}</a>
|
||||||
{% if loop.last %}
|
{% if loop.last %}
|
||||||
<a href="#" class="author-expand" data-authors-max="{{g.config_authors_max}}" data-collapse-caption="({{_('reduce')}})">(...)</a>
|
<a href="#" class="author-expand" data-authors-max="{{g.config_authors_max}}" data-collapse-caption="({{_('reduce')}})">(...)</a>
|
||||||
|
@ -73,6 +73,11 @@
|
||||||
<a class="author-name" href="{{url_for('web.books_list', data='author', sort='new', book_id=author.id) }}">{{author.name.replace('|',',')|shortentitle(30)}}</a>
|
<a class="author-name" href="{{url_for('web.books_list', data='author', sort='new', book_id=author.id) }}">{{author.name.replace('|',',')|shortentitle(30)}}</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
{% for format in entry.data %}
|
||||||
|
{% if format.format|lower == 'mp3' %}
|
||||||
|
<span class="glyphicon glyphicon-music"></span>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
</p>
|
</p>
|
||||||
{% if entry.ratings.__len__() > 0 %}
|
{% if entry.ratings.__len__() > 0 %}
|
||||||
<div class="rating">
|
<div class="rating">
|
||||||
|
|
|
@ -25,7 +25,7 @@ import smtplib
|
||||||
import socket
|
import socket
|
||||||
import time
|
import time
|
||||||
import threading
|
import threading
|
||||||
from datetime import datetime
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from StringIO import StringIO
|
from StringIO import StringIO
|
||||||
|
@ -226,8 +226,10 @@ class WorkerThread(threading.Thread):
|
||||||
if self.UIqueue[self.current]['stat'] == STAT_STARTED:
|
if self.UIqueue[self.current]['stat'] == STAT_STARTED:
|
||||||
if self.queue[self.current]['taskType'] == TASK_EMAIL:
|
if self.queue[self.current]['taskType'] == TASK_EMAIL:
|
||||||
self.UIqueue[self.current]['progress'] = self.get_send_status()
|
self.UIqueue[self.current]['progress'] = self.get_send_status()
|
||||||
self.UIqueue[self.current]['runtime'] = self._formatRuntime(
|
self.UIqueue[self.current]['formRuntime'] = datetime.now() - self.queue[self.current]['starttime']
|
||||||
datetime.now() - self.queue[self.current]['starttime'])
|
self.UIqueue[self.current]['rt'] = self.UIqueue[self.current]['formRuntime'].days*24*60 \
|
||||||
|
+ self.UIqueue[self.current]['formRuntime'].seconds \
|
||||||
|
+ self.UIqueue[self.current]['formRuntime'].microseconds
|
||||||
return self.UIqueue
|
return self.UIqueue
|
||||||
|
|
||||||
def _convert_any_format(self):
|
def _convert_any_format(self):
|
||||||
|
@ -336,6 +338,11 @@ class WorkerThread(threading.Thread):
|
||||||
|
|
||||||
# process returncode
|
# process returncode
|
||||||
check = p.returncode
|
check = p.returncode
|
||||||
|
calibre_traceback = p.stderr.readlines()
|
||||||
|
for ele in calibre_traceback:
|
||||||
|
log.debug(ele.strip('\n'))
|
||||||
|
if not ele.startswith('Traceback') and not ele.startswith(' File'):
|
||||||
|
error_message = "Calibre failed with error: %s" % ele.strip('\n')
|
||||||
|
|
||||||
# kindlegen returncodes
|
# kindlegen returncodes
|
||||||
# 0 = Info(prcgen):I1036: Mobi file built successfully
|
# 0 = Info(prcgen):I1036: Mobi file built successfully
|
||||||
|
@ -491,28 +498,14 @@ class WorkerThread(threading.Thread):
|
||||||
self._handleError(u'Error sending email: ' + e.strerror)
|
self._handleError(u'Error sending email: ' + e.strerror)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def _formatRuntime(self, runtime):
|
|
||||||
self.UIqueue[self.current]['rt'] = runtime.total_seconds()
|
|
||||||
val = re.split('\:|\.', str(runtime))[0:3]
|
|
||||||
erg = list()
|
|
||||||
for v in val:
|
|
||||||
if int(v) > 0:
|
|
||||||
erg.append(v)
|
|
||||||
retVal = (':'.join(erg)).lstrip('0') + ' s'
|
|
||||||
if retVal == ' s':
|
|
||||||
retVal = '0 s'
|
|
||||||
return retVal
|
|
||||||
|
|
||||||
def _handleError(self, error_message):
|
def _handleError(self, error_message):
|
||||||
log.error(error_message)
|
log.error(error_message)
|
||||||
self.UIqueue[self.current]['stat'] = STAT_FAIL
|
self.UIqueue[self.current]['stat'] = STAT_FAIL
|
||||||
self.UIqueue[self.current]['progress'] = "100 %"
|
self.UIqueue[self.current]['progress'] = "100 %"
|
||||||
self.UIqueue[self.current]['runtime'] = self._formatRuntime(
|
self.UIqueue[self.current]['formRuntime'] = datetime.now() - self.queue[self.current]['starttime']
|
||||||
datetime.now() - self.queue[self.current]['starttime'])
|
|
||||||
self.UIqueue[self.current]['message'] = error_message
|
self.UIqueue[self.current]['message'] = error_message
|
||||||
|
|
||||||
def _handleSuccess(self):
|
def _handleSuccess(self):
|
||||||
self.UIqueue[self.current]['stat'] = STAT_FINISH_SUCCESS
|
self.UIqueue[self.current]['stat'] = STAT_FINISH_SUCCESS
|
||||||
self.UIqueue[self.current]['progress'] = "100 %"
|
self.UIqueue[self.current]['progress'] = "100 %"
|
||||||
self.UIqueue[self.current]['runtime'] = self._formatRuntime(
|
self.UIqueue[self.current]['formRuntime'] = datetime.now() - self.queue[self.current]['starttime']
|
||||||
datetime.now() - self.queue[self.current]['starttime'])
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user