mirror of
https://github.com/janeczku/calibre-web
synced 2024-11-10 20:10:00 +00:00
Merge branch 'master' into Develop
This commit is contained in:
commit
8f2f6f5c91
@ -1,10 +1,3 @@
|
||||
# Short Notice from the maintainer
|
||||
|
||||
After 6 years of more or less intensive programming on Calibre-Web, I need a break.
|
||||
The last few months, maintaining Calibre-Web has felt more like work than a hobby. I felt pressured and teased by people to solve "their" problems and merge PRs for "their" Calibre-Web.
|
||||
I have turned off all notifications from Github/Discord and will now concentrate undisturbed on the development of “my” Calibre-Web over the next few weeks/months.
|
||||
I will look into the issues and maybe also the PRs from time to time, but don't expect a quick response from me.
|
||||
|
||||
# Calibre-Web
|
||||
|
||||
Calibre-Web is a web app that offers a clean and intuitive interface for browsing, reading, and downloading eBooks using a valid [Calibre](https://calibre-ebook.com) database.
|
||||
|
22
cps/admin.py
22
cps/admin.py
@ -54,6 +54,7 @@ from .services.worker import WorkerThread
|
||||
from .usermanagement import user_login_required
|
||||
from .babel import get_available_translations, get_available_locale, get_user_locale_language
|
||||
from . import debug_info
|
||||
from .string_helper import strip_whitespaces
|
||||
|
||||
log = logger.create()
|
||||
|
||||
@ -463,9 +464,9 @@ def edit_list_user(param):
|
||||
if 'value[]' in vals:
|
||||
setattr(user, param, prepare_tags(user, vals['action'][0], param, vals['value[]']))
|
||||
else:
|
||||
setattr(user, param, vals['value'].strip())
|
||||
setattr(user, param, strip_whitespaces(vals['value']))
|
||||
else:
|
||||
vals['value'] = vals['value'].strip()
|
||||
vals['value'] = strip_whitespaces(vals['value'])
|
||||
if param == 'name':
|
||||
if user.name == "Guest":
|
||||
raise Exception(_("Guest Name can't be changed"))
|
||||
@ -690,7 +691,7 @@ def delete_domain():
|
||||
def list_domain(allow):
|
||||
answer = ub.session.query(ub.Registration).filter(ub.Registration.allow == allow).all()
|
||||
json_dumps = json.dumps([{"domain": r.domain.replace('%', '*').replace('_', '?'), "id": r.id} for r in answer])
|
||||
js = json.dumps(json_dumps.replace('"', "'")).lstrip('"').strip('"')
|
||||
js = json.dumps(json_dumps.replace('"', "'")).strip('"')
|
||||
response = make_response(js.replace("'", '"'))
|
||||
response.headers["Content-Type"] = "application/json; charset=utf-8"
|
||||
return response
|
||||
@ -1100,7 +1101,7 @@ def _config_checkbox_int(to_save, x):
|
||||
|
||||
|
||||
def _config_string(to_save, x):
|
||||
return config.set_from_dictionary(to_save, x, lambda y: y.strip().strip(u'\u200B\u200C\u200D\ufeff') if y else y)
|
||||
return config.set_from_dictionary(to_save, x, lambda y: strip_whitespaces(y) if y else y)
|
||||
|
||||
|
||||
def _configuration_gdrive_helper(to_save):
|
||||
@ -1311,9 +1312,9 @@ def update_mailsettings():
|
||||
if to_save.get("mail_password_e", ""):
|
||||
_config_string(to_save, "mail_password_e")
|
||||
_config_int(to_save, "mail_size", lambda y: int(y) * 1024 * 1024)
|
||||
config.mail_server = to_save.get('mail_server', "").strip()
|
||||
config.mail_from = to_save.get('mail_from', "").strip()
|
||||
config.mail_login = to_save.get('mail_login', "").strip()
|
||||
config.mail_server = strip_whitespaces(to_save.get('mail_server', ""))
|
||||
config.mail_from = strip_whitespaces(to_save.get('mail_from', ""))
|
||||
config.mail_login = strip_whitespaces(to_save.get('mail_login', ""))
|
||||
try:
|
||||
config.save()
|
||||
except (OperationalError, InvalidRequestError) as e:
|
||||
@ -1678,10 +1679,10 @@ def cancel_task():
|
||||
def _db_simulate_change():
|
||||
param = request.form.to_dict()
|
||||
to_save = dict()
|
||||
to_save['config_calibre_dir'] = re.sub(r'[\\/]metadata\.db$',
|
||||
to_save['config_calibre_dir'] = strip_whitespaces(re.sub(r'[\\/]metadata\.db$',
|
||||
'',
|
||||
param['config_calibre_dir'],
|
||||
flags=re.IGNORECASE).strip()
|
||||
flags=re.IGNORECASE))
|
||||
db_valid, db_change = calibre_db.check_valid_db(to_save["config_calibre_dir"],
|
||||
ub.app_DB_path,
|
||||
config.config_calibre_uuid)
|
||||
@ -1775,9 +1776,8 @@ def _configuration_update_helper():
|
||||
|
||||
if "config_upload_formats" in to_save:
|
||||
to_save["config_upload_formats"] = ','.join(
|
||||
helper.uniq([x.lstrip().rstrip().lower() for x in to_save["config_upload_formats"].split(',')]))
|
||||
helper.uniq([x.strip().lower() for x in to_save["config_upload_formats"].split(',')]))
|
||||
_config_string(to_save, "config_upload_formats")
|
||||
# constants.EXTENSIONS_UPLOAD = config.config_upload_formats.split(',')
|
||||
|
||||
_config_string(to_save, "config_calibre")
|
||||
_config_string(to_save, "config_binariesdir")
|
||||
|
@ -35,7 +35,7 @@ except ImportError:
|
||||
|
||||
from . import constants, logger
|
||||
from .subproc_wrapper import process_wait
|
||||
|
||||
from .string_helper import strip_whitespaces
|
||||
|
||||
log = logger.create()
|
||||
_Base = declarative_base()
|
||||
@ -288,19 +288,19 @@ class ConfigSQL(object):
|
||||
|
||||
def list_denied_tags(self):
|
||||
mct = self.config_denied_tags or ""
|
||||
return [t.strip() for t in mct.split(",")]
|
||||
return [strip_whitespaces(t) for t in mct.split(",")]
|
||||
|
||||
def list_allowed_tags(self):
|
||||
mct = self.config_allowed_tags or ""
|
||||
return [t.strip() for t in mct.split(",")]
|
||||
return [strip_whitespaces(t) for t in mct.split(",")]
|
||||
|
||||
def list_denied_column_values(self):
|
||||
mct = self.config_denied_column_value or ""
|
||||
return [t.strip() for t in mct.split(",")]
|
||||
return [strip_whitespaces(t) for t in mct.split(",")]
|
||||
|
||||
def list_allowed_column_values(self):
|
||||
mct = self.config_allowed_column_value or ""
|
||||
return [t.strip() for t in mct.split(",")]
|
||||
return [strip_whitespaces(t) for t in mct.split(",")]
|
||||
|
||||
def get_log_level(self):
|
||||
return logger.get_level_name(self.config_log_level)
|
||||
@ -372,7 +372,7 @@ class ConfigSQL(object):
|
||||
db_file = os.path.join(self.config_calibre_dir, 'metadata.db')
|
||||
have_metadata_db = os.path.isfile(db_file)
|
||||
self.db_configured = have_metadata_db
|
||||
# constants.EXTENSIONS_UPLOAD = [x.lstrip().rstrip().lower() for x in self.config_upload_formats.split(',')]
|
||||
|
||||
from . import cli_param
|
||||
if os.environ.get('FLASK_DEBUG'):
|
||||
logfile = logger.setup(logger.LOG_TO_STDOUT, logger.logging.DEBUG)
|
||||
|
@ -193,7 +193,7 @@ THUMBNAIL_TYPE_AUTHOR = 3
|
||||
COVER_THUMBNAIL_ORIGINAL = 0
|
||||
COVER_THUMBNAIL_SMALL = 1
|
||||
COVER_THUMBNAIL_MEDIUM = 2
|
||||
COVER_THUMBNAIL_LARGE = 3
|
||||
COVER_THUMBNAIL_LARGE = 4
|
||||
|
||||
# clean-up the module namespace
|
||||
del sys, os, namedtuple
|
||||
|
11
cps/db.py
11
cps/db.py
@ -48,7 +48,7 @@ from flask import flash
|
||||
|
||||
from . import logger, ub, isoLanguages
|
||||
from .pagination import Pagination
|
||||
|
||||
from .string_helper import strip_whitespaces
|
||||
|
||||
log = logger.create()
|
||||
|
||||
@ -875,10 +875,11 @@ class CalibreDB:
|
||||
authors_ordered = list()
|
||||
# error = False
|
||||
for auth in sort_authors:
|
||||
results = self.session.query(Authors).filter(Authors.sort == auth.lstrip().strip()).all()
|
||||
auth = strip_whitespaces(auth)
|
||||
results = self.session.query(Authors).filter(Authors.sort == auth).all()
|
||||
# ToDo: How to handle not found author name
|
||||
if not len(results):
|
||||
log.error("Author {} not found to display name in right order".format(auth.strip()))
|
||||
log.error("Author {} not found to display name in right order".format(auth))
|
||||
# error = True
|
||||
break
|
||||
for r in results:
|
||||
@ -918,7 +919,7 @@ class CalibreDB:
|
||||
.filter(and_(Books.authors.any(and_(*q)), func.lower(Books.title).ilike("%" + title + "%"))).first()
|
||||
|
||||
def search_query(self, term, config, *join):
|
||||
term.strip().lower()
|
||||
strip_whitespaces(term).lower()
|
||||
self.session.connection().connection.connection.create_function("lower", 1, lcase)
|
||||
q = list()
|
||||
author_terms = re.split("[, ]+", term)
|
||||
@ -1026,7 +1027,7 @@ class CalibreDB:
|
||||
if match:
|
||||
prep = match.group(1)
|
||||
title = title[len(prep):] + ', ' + prep
|
||||
return title.strip()
|
||||
return strip_whitespaces(title)
|
||||
|
||||
try:
|
||||
# sqlalchemy <1.4.24 and sqlalchemy 2.0
|
||||
|
@ -47,7 +47,7 @@ from .kobo_sync_status import change_archived_books
|
||||
from .redirect import get_redirect_location
|
||||
from .file_helper import validate_mime_type
|
||||
from .usermanagement import user_login_required, login_required_if_no_ano
|
||||
|
||||
from .string_helper import strip_whitespaces
|
||||
|
||||
editbook = Blueprint('edit-book', __name__)
|
||||
log = logger.create()
|
||||
@ -979,7 +979,7 @@ def render_edit_book(book_id):
|
||||
|
||||
def edit_book_ratings(to_save, book):
|
||||
changed = False
|
||||
if to_save.get("rating", "").strip():
|
||||
if strip_whitespaces(to_save.get("rating", "")):
|
||||
old_rating = False
|
||||
if len(book.ratings) > 0:
|
||||
old_rating = book.ratings[0].rating
|
||||
@ -1003,14 +1003,14 @@ def edit_book_ratings(to_save, book):
|
||||
|
||||
def edit_book_tags(tags, book):
|
||||
input_tags = tags.split(',')
|
||||
input_tags = list(map(lambda it: it.strip(), input_tags))
|
||||
input_tags = list(map(lambda it: strip_whitespaces(it), input_tags))
|
||||
# Remove duplicates
|
||||
input_tags = helper.uniq(input_tags)
|
||||
return modify_database_object(input_tags, book.tags, db.Tags, calibre_db.session, 'tags')
|
||||
|
||||
|
||||
def edit_book_series(series, book):
|
||||
input_series = [series.strip()]
|
||||
input_series = [strip_whitespaces(series)]
|
||||
input_series = [x for x in input_series if x != '']
|
||||
return modify_database_object(input_series, book.series, db.Series, calibre_db.session, 'series')
|
||||
|
||||
@ -1072,7 +1072,7 @@ def edit_book_languages(languages, book, upload_mode=False, invalid=None):
|
||||
def edit_book_publisher(publishers, book):
|
||||
changed = False
|
||||
if publishers:
|
||||
publisher = publishers.rstrip().strip()
|
||||
publisher = strip_whitespaces(publishers)
|
||||
if len(book.publishers) == 0 or (len(book.publishers) > 0 and publisher != book.publishers[0].name):
|
||||
changed |= modify_database_object([publisher], book.publishers, db.Publishers, calibre_db.session,
|
||||
'publisher')
|
||||
@ -1119,7 +1119,7 @@ def edit_cc_data_string(book, c, to_save, cc_db_value, cc_string):
|
||||
changed = False
|
||||
if c.datatype == 'rating':
|
||||
to_save[cc_string] = str(int(float(to_save[cc_string]) * 2))
|
||||
if to_save[cc_string].strip() != cc_db_value:
|
||||
if strip_whitespaces(to_save[cc_string]) != cc_db_value:
|
||||
if cc_db_value is not None:
|
||||
# remove old cc_val
|
||||
del_cc = getattr(book, cc_string)[0]
|
||||
@ -1129,15 +1129,15 @@ def edit_cc_data_string(book, c, to_save, cc_db_value, cc_string):
|
||||
changed = True
|
||||
cc_class = db.cc_classes[c.id]
|
||||
new_cc = calibre_db.session.query(cc_class).filter(
|
||||
cc_class.value == to_save[cc_string].strip()).first()
|
||||
cc_class.value == strip_whitespaces(to_save[cc_string])).first()
|
||||
# if no cc val is found add it
|
||||
if new_cc is None:
|
||||
new_cc = cc_class(value=to_save[cc_string].strip())
|
||||
new_cc = cc_class(value=strip_whitespaces(to_save[cc_string]))
|
||||
calibre_db.session.add(new_cc)
|
||||
changed = True
|
||||
calibre_db.session.flush()
|
||||
new_cc = calibre_db.session.query(cc_class).filter(
|
||||
cc_class.value == to_save[cc_string].strip()).first()
|
||||
cc_class.value == strip_whitespaces(to_save[cc_string])).first()
|
||||
# add cc value to book
|
||||
getattr(book, cc_string).append(new_cc)
|
||||
return changed, to_save
|
||||
@ -1165,7 +1165,7 @@ def edit_cc_data(book_id, book, to_save, cc):
|
||||
cc_db_value = getattr(book, cc_string)[0].value
|
||||
else:
|
||||
cc_db_value = None
|
||||
if to_save[cc_string].strip():
|
||||
if strip_whitespaces(to_save[cc_string]):
|
||||
if c.datatype in ['int', 'bool', 'float', "datetime", "comments"]:
|
||||
change, to_save = edit_cc_data_value(book_id, book, c, to_save, cc_db_value, cc_string)
|
||||
else:
|
||||
@ -1181,7 +1181,7 @@ def edit_cc_data(book_id, book, to_save, cc):
|
||||
changed = True
|
||||
else:
|
||||
input_tags = to_save[cc_string].split(',')
|
||||
input_tags = list(map(lambda it: it.strip(), input_tags))
|
||||
input_tags = list(map(lambda it: strip_whitespaces(it), input_tags))
|
||||
changed |= modify_database_object(input_tags,
|
||||
getattr(book, cc_string),
|
||||
db.cc_classes[c.id],
|
||||
@ -1284,7 +1284,7 @@ def upload_cover(cover_request, book):
|
||||
|
||||
def handle_title_on_edit(book, book_title):
|
||||
# handle book title
|
||||
book_title = book_title.rstrip().strip()
|
||||
book_title = strip_whitespaces(book_title)
|
||||
if book.title != book_title:
|
||||
if book_title == '':
|
||||
book_title = _(u'Unknown')
|
||||
|
@ -25,6 +25,7 @@ from . import config, logger
|
||||
from .helper import split_authors
|
||||
from .epub_helper import get_content_opf, default_ns
|
||||
from .constants import BookMeta
|
||||
from .string_helper import strip_whitespaces
|
||||
|
||||
log = logger.create()
|
||||
|
||||
@ -90,7 +91,7 @@ def get_epub_info(tmp_file_path, original_file_name, original_file_extension):
|
||||
elif s == 'date':
|
||||
epub_metadata[s] = tmp[0][:10]
|
||||
else:
|
||||
epub_metadata[s] = tmp[0].strip()
|
||||
epub_metadata[s] = strip_whitespaces(tmp[0])
|
||||
else:
|
||||
epub_metadata[s] = 'Unknown'
|
||||
|
||||
|
@ -52,6 +52,7 @@ except ImportError:
|
||||
UnacceptableAddressException = MissingSchema = BaseException
|
||||
|
||||
from . import calibre_db, cli_param
|
||||
from .string_helper import strip_whitespaces
|
||||
from .tasks.convert import TaskConvert
|
||||
from . import logger, config, db, ub, fs
|
||||
from . import gdriveutils as gd
|
||||
@ -118,7 +119,7 @@ def convert_book_format(book_id, calibre_path, old_book_format, new_book_format,
|
||||
# Texts are not lazy translated as they are supposed to get send out as is
|
||||
def send_test_mail(ereader_mail, user_name):
|
||||
for email in ereader_mail.split(','):
|
||||
email = email.strip()
|
||||
email = strip_whitespaces(email)
|
||||
WorkerThread.add(user_name, TaskEmail(_('Calibre-Web Test Email'), None, None,
|
||||
config.get_mail_settings(), email, N_("Test Email"),
|
||||
_('This Email has been sent via Calibre-Web.')))
|
||||
@ -228,7 +229,7 @@ def send_mail(book_id, book_format, convert, ereader_mail, calibrepath, user_id)
|
||||
link = '<a href="{}">{}</a>'.format(url_for('web.show_book', book_id=book_id), escape(book.title))
|
||||
email_text = N_("%(book)s send to eReader", book=link)
|
||||
for email in ereader_mail.split(','):
|
||||
email = email.strip()
|
||||
email = strip_whitespaces(email)
|
||||
WorkerThread.add(user_id, TaskEmail(_("Send to eReader"), book.path, converted_file_name,
|
||||
config.get_mail_settings(), email,
|
||||
email_text, _('This Email has been sent via Calibre-Web.'), book.id))
|
||||
@ -252,7 +253,7 @@ def get_valid_filename(value, replace_whitespace=True, chars=128):
|
||||
# pipe has to be replaced with comma
|
||||
value = re.sub(r'[|]+', ',', value, flags=re.U)
|
||||
|
||||
value = value.encode('utf-8')[:chars].decode('utf-8', errors='ignore').strip()
|
||||
value = strip_whitespaces(value.encode('utf-8')[:chars].decode('utf-8', errors='ignore'))
|
||||
|
||||
if not value:
|
||||
raise ValueError("Filename cannot be empty")
|
||||
@ -267,11 +268,11 @@ def split_authors(values):
|
||||
commas = author.count(',')
|
||||
if commas == 1:
|
||||
author_split = author.split(',')
|
||||
authors_list.append(author_split[1].strip() + ' ' + author_split[0].strip())
|
||||
authors_list.append(strip_whitespaces(author_split[1]) + ' ' + strip_whitespaces(author_split[0]))
|
||||
elif commas > 1:
|
||||
authors_list.extend([x.strip() for x in author.split(',')])
|
||||
authors_list.extend([strip_whitespaces(x) for x in author.split(',')])
|
||||
else:
|
||||
authors_list.append(author.strip())
|
||||
authors_list.append(strip_whitespaces(author))
|
||||
return authors_list
|
||||
|
||||
|
||||
@ -661,7 +662,7 @@ def check_email(email):
|
||||
|
||||
|
||||
def check_username(username):
|
||||
username = username.strip()
|
||||
username = strip_whitespaces(username)
|
||||
if ub.session.query(ub.User).filter(func.lower(ub.User.name) == username.lower()).scalar():
|
||||
log.error("This username is already taken")
|
||||
raise Exception(_("This username is already taken"))
|
||||
@ -670,14 +671,14 @@ def check_username(username):
|
||||
|
||||
def valid_email(emails):
|
||||
for email in emails.split(','):
|
||||
email = email.strip()
|
||||
# if email is not deleted
|
||||
if email:
|
||||
# Regex according to https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/email#validation
|
||||
if not re.search(r"^[\w.!#$%&'*+\\/=?^_`{|}~-]+@[\w](?:[\w-]{0,61}[\w])?(?:\.[\w](?:[\w-]{0,61}[\w])?)*$",
|
||||
email):
|
||||
log.error("Invalid Email address format")
|
||||
raise Exception(_("Invalid Email address format"))
|
||||
email = strip_whitespaces(email)
|
||||
# if email is not deleted
|
||||
if email:
|
||||
# Regex according to https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/email#validation
|
||||
if not re.search(r"^[\w.!#$%&'*+\\/=?^_`{|}~-]+@[\w](?:[\w-]{0,61}[\w])?(?:\.[\w](?:[\w-]{0,61}[\w])?)*$",
|
||||
email):
|
||||
log.error("Invalid Email address format")
|
||||
raise Exception(_("Invalid Email address format"))
|
||||
return email
|
||||
|
||||
|
||||
|
@ -47,7 +47,7 @@ import requests
|
||||
from . import config, logger, kobo_auth, db, calibre_db, helper, shelf as shelf_lib, ub, csrf, kobo_sync_status
|
||||
from . import isoLanguages
|
||||
from .epub import get_epub_layout
|
||||
from .constants import COVER_THUMBNAIL_SMALL, COVER_THUMBNAIL_MEDIUM
|
||||
from .constants import COVER_THUMBNAIL_SMALL, COVER_THUMBNAIL_MEDIUM, COVER_THUMBNAIL_LARGE
|
||||
from .helper import get_download_link
|
||||
from .services import SyncToken as SyncToken
|
||||
from .web import download_required
|
||||
@ -904,7 +904,7 @@ def get_current_bookmark_response(current_bookmark):
|
||||
def HandleCoverImageRequest(book_uuid, width, height, Quality, isGreyscale):
|
||||
try:
|
||||
if int(height) > 1000:
|
||||
resolution = None
|
||||
resolution = COVER_THUMBNAIL_LARGE
|
||||
elif int(height) > 500:
|
||||
resolution = COVER_THUMBNAIL_MEDIUM
|
||||
else:
|
||||
|
@ -53,7 +53,6 @@ class Amazon(Metadata):
|
||||
def search(
|
||||
self, query: str, generic_cover: str = "", locale: str = "en"
|
||||
) -> Optional[List[MetaRecord]]:
|
||||
#timer=time()
|
||||
def inner(link, index) -> [dict, int]:
|
||||
with self.session as session:
|
||||
try:
|
||||
@ -61,11 +60,11 @@ class Amazon(Metadata):
|
||||
r.raise_for_status()
|
||||
except Exception as ex:
|
||||
log.warning(ex)
|
||||
return None
|
||||
return []
|
||||
long_soup = BS(r.text, "lxml") #~4sec :/
|
||||
soup2 = long_soup.find("div", attrs={"cel_widget_id": "dpx-books-ppd_csm_instrumentation_wrapper"})
|
||||
if soup2 is None:
|
||||
return None
|
||||
return []
|
||||
try:
|
||||
match = MetaRecord(
|
||||
title = "",
|
||||
@ -88,7 +87,7 @@ class Amazon(Metadata):
|
||||
soup2.find("div", attrs={"data-feature-name": "bookDescription"}).stripped_strings)\
|
||||
.replace("\xa0"," ")[:-9].strip().strip("\n")
|
||||
except (AttributeError, TypeError):
|
||||
return None # if there is no description it is not a book and therefore should be ignored
|
||||
return [] # if there is no description it is not a book and therefore should be ignored
|
||||
try:
|
||||
match.title = soup2.find("span", attrs={"id": "productTitle"}).text
|
||||
except (AttributeError, TypeError):
|
||||
@ -113,7 +112,7 @@ class Amazon(Metadata):
|
||||
return match, index
|
||||
except Exception as e:
|
||||
log.error_or_exception(e)
|
||||
return None
|
||||
return []
|
||||
|
||||
val = list()
|
||||
if self.active:
|
||||
@ -134,6 +133,6 @@ class Amazon(Metadata):
|
||||
soup.findAll("div", attrs={"data-component-type": "s-search-result"})]
|
||||
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
|
||||
fut = {executor.submit(inner, link, index) for index, link in enumerate(links_list[:5])}
|
||||
val = list(map(lambda x : x.result() ,concurrent.futures.as_completed(fut)))
|
||||
val = list(map(lambda x : x.result(), concurrent.futures.as_completed(fut)))
|
||||
result = list(filter(lambda x: x, val))
|
||||
return [x[0] for x in sorted(result, key=itemgetter(1))] #sort by amazons listing order for best relevance
|
||||
|
@ -54,7 +54,7 @@ class Google(Metadata):
|
||||
results.raise_for_status()
|
||||
except Exception as e:
|
||||
log.warning(e)
|
||||
return None
|
||||
return []
|
||||
for result in results.json().get("items", []):
|
||||
val.append(
|
||||
self._parse_search_result(
|
||||
|
@ -24,9 +24,9 @@ from flask_babel import format_date
|
||||
from flask_babel import gettext as _
|
||||
from sqlalchemy.sql.expression import func, not_, and_, or_, text, true
|
||||
from sqlalchemy.sql.functions import coalesce
|
||||
from sqlalchemy import exists
|
||||
|
||||
from . import logger, db, calibre_db, config, ub
|
||||
from .string_helper import strip_whitespaces
|
||||
from .usermanagement import login_required_if_no_ano
|
||||
from .render_template import render_title_template
|
||||
from .pagination import Pagination
|
||||
@ -267,11 +267,11 @@ def render_adv_search_results(term, offset=None, order=None, limit=None):
|
||||
description = term.get("comment")
|
||||
read_status = term.get("read_status")
|
||||
if author_name:
|
||||
author_name = author_name.strip().lower().replace(',', '|')
|
||||
author_name = strip_whitespaces(author_name).lower().replace(',', '|')
|
||||
if book_title:
|
||||
book_title = book_title.strip().lower()
|
||||
book_title = strip_whitespaces(book_title).lower()
|
||||
if publisher:
|
||||
publisher = publisher.strip().lower()
|
||||
publisher = strip_whitespaces(publisher).lower()
|
||||
|
||||
search_term = []
|
||||
cc_present = False
|
||||
|
23
cps/string_helper.py
Normal file
23
cps/string_helper.py
Normal file
@ -0,0 +1,23 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This file is part of the Calibre-Web (https://github.com/janeczku/calibre-web)
|
||||
# Copyright (C) 2024 OzzieIsaacs
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
import re
|
||||
|
||||
|
||||
def strip_whitespaces(text):
|
||||
return re.sub("(^[\s\u200B-\u200D\ufeff]+)|([\s\u200B-\u200D\ufeff]+$)","", text)
|
||||
|
@ -39,6 +39,7 @@ from cps.file_helper import get_temp_dir
|
||||
from cps.tasks.mail import TaskEmail
|
||||
from cps import gdriveutils, helper
|
||||
from cps.constants import SUPPORTED_CALIBRE_BINARIES
|
||||
from cps.string_helper import strip_whitespaces
|
||||
|
||||
log = logger.create()
|
||||
|
||||
@ -107,7 +108,7 @@ class TaskConvert(CalibreTask):
|
||||
try:
|
||||
EmailText = N_(u"%(book)s send to E-Reader", book=escape(self.title))
|
||||
for email in self.ereader_mail.split(','):
|
||||
email = email.strip()
|
||||
email = strip_whitespaces(email)
|
||||
worker_thread.add(self.user, TaskEmail(self.settings['subject'],
|
||||
self.results["path"],
|
||||
filename,
|
||||
|
@ -34,6 +34,7 @@ from cps.services import gmail
|
||||
from cps.embed_helper import do_calibre_export
|
||||
from cps import logger, config
|
||||
from cps import gdriveutils
|
||||
from cps.string_helper import strip_whitespaces
|
||||
import uuid
|
||||
|
||||
log = logger.create()
|
||||
@ -127,9 +128,9 @@ class TaskEmail(CalibreTask):
|
||||
try:
|
||||
# Parse out the address from the From line, and then the domain from that
|
||||
from_email = parseaddr(self.settings["mail_from"])[1]
|
||||
msgid_domain = from_email.partition('@')[2].strip()
|
||||
msgid_domain = strip_whitespaces(from_email.partition('@')[2])
|
||||
# This can sometimes sneak through parseaddr if the input is malformed
|
||||
msgid_domain = msgid_domain.rstrip('>').strip()
|
||||
msgid_domain = strip_whitespaces(msgid_domain.rstrip('>'))
|
||||
except Exception:
|
||||
msgid_domain = ''
|
||||
return msgid_domain or 'calibre-web.com'
|
||||
|
@ -35,7 +35,7 @@ except (ImportError, RuntimeError) as e:
|
||||
|
||||
|
||||
def get_resize_height(resolution):
|
||||
return int(225 * resolution)
|
||||
return int(255 * resolution)
|
||||
|
||||
|
||||
def get_resize_width(resolution, original_width, original_height):
|
||||
@ -72,7 +72,8 @@ class TaskGenerateCoverThumbnails(CalibreTask):
|
||||
self.cache = fs.FileSystem()
|
||||
self.resolutions = [
|
||||
constants.COVER_THUMBNAIL_SMALL,
|
||||
constants.COVER_THUMBNAIL_MEDIUM
|
||||
constants.COVER_THUMBNAIL_MEDIUM,
|
||||
constants.COVER_THUMBNAIL_LARGE
|
||||
]
|
||||
|
||||
def run(self, worker_thread):
|
||||
|
@ -20,7 +20,7 @@
|
||||
{{ _('Download') }} :
|
||||
</button>
|
||||
{% for format in entry.data %}
|
||||
<a href="{{ url_for('web.download_link', book_id=entry.id, book_format=format.format|lower, anyname=entry.id|string+'.'+format.format|lower) }}"
|
||||
<a href="{{ url_for('web.download_link', book_id=entry.id, book_format=format.format|lower, anyname=entry.id|string+'.'+format.format|lower|replace('kepub', 'kepub.epub')) }}"
|
||||
id="btnGroupDrop1{{ format.format|lower }}" class="btn btn-primary"
|
||||
role="button">
|
||||
<span class="glyphicon glyphicon-download"></span>{{ format.format }}
|
||||
@ -36,7 +36,7 @@
|
||||
<ul class="dropdown-menu" aria-labelledby="btnGroupDrop1">
|
||||
{% for format in entry.data %}
|
||||
<li>
|
||||
<a href="{{ url_for('web.download_link', book_id=entry.id, book_format=format.format|lower, anyname=entry.id|string+'.'+format.format|lower) }}">{{ format.format }}
|
||||
<a href="{{ url_for('web.download_link', book_id=entry.id, book_format=format.format|lower, anyname=entry.id|string+'.'+format.format|lower|replace('kepub', 'kepub.epub')) }}">{{ format.format }}
|
||||
({{ format.uncompressed_size|filesizeformat }})</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
@ -55,7 +55,7 @@
|
||||
{% if entry.Books.data|length %}
|
||||
<div class="btn-group" role="group">
|
||||
{% for format in entry.Books.data %}
|
||||
<a href="{{ url_for('web.download_link', book_id=entry.Books.id, book_format=format.format|lower, anyname=entry.Books.id|string+'.'+format.format|lower) }}" id="btnGroupDrop{{entry.Books.id}}{{format.format|lower}}" class="btn btn-primary" role="button">
|
||||
<a href="{{ url_for('web.download_link', book_id=entry.Books.id, book_format=format.format|lower, anyname=entry.Books.id|string+'.'+format.format|lower|replace('kepub', 'kepub.epub')) }}" id="btnGroupDrop{{entry.Books.id}}{{format.format|lower}}" class="btn btn-primary" role="button">
|
||||
<span class="glyphicon glyphicon-download"></span>{{format.format}} ({{ format.uncompressed_size|filesizeformat }})
|
||||
</a>
|
||||
{% endfor %}
|
||||
|
@ -25,7 +25,7 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="form-group">
|
||||
<label for="kindle_mail">{{_('Send to eReader Email Address. Use comma to seperate emails for multiple eReaders')}}</label>
|
||||
<label for="kindle_mail">{{_('Send to eReader Email Address. Use comma to separate emails for multiple eReaders')}}</label>
|
||||
<input type="email" class="form-control" name="kindle_mail" id="kindle_mail" value="{{ content.kindle_mail if content.kindle_mail != None }}">
|
||||
</div>
|
||||
{% if not content.role_anonymous() %}
|
||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
10
cps/ub.py
10
cps/ub.py
@ -54,7 +54,7 @@ from sqlalchemy.orm import backref, relationship, sessionmaker, Session, scoped_
|
||||
from werkzeug.security import generate_password_hash
|
||||
|
||||
from . import constants, logger
|
||||
|
||||
from .string_helper import strip_whitespaces
|
||||
|
||||
log = logger.create()
|
||||
|
||||
@ -196,19 +196,19 @@ class UserBase:
|
||||
|
||||
def list_denied_tags(self):
|
||||
mct = self.denied_tags or ""
|
||||
return [t.strip() for t in mct.split(",")]
|
||||
return [strip_whitespaces(t) for t in mct.split(",")]
|
||||
|
||||
def list_allowed_tags(self):
|
||||
mct = self.allowed_tags or ""
|
||||
return [t.strip() for t in mct.split(",")]
|
||||
return [strip_whitespaces(t) for t in mct.split(",")]
|
||||
|
||||
def list_denied_column_values(self):
|
||||
mct = self.denied_column_value or ""
|
||||
return [t.strip() for t in mct.split(",")]
|
||||
return [strip_whitespaces(t) for t in mct.split(",")]
|
||||
|
||||
def list_allowed_column_values(self):
|
||||
mct = self.allowed_column_value or ""
|
||||
return [t.strip() for t in mct.split(",")]
|
||||
return [strip_whitespaces(t) for t in mct.split(",")]
|
||||
|
||||
def get_view_property(self, page, prop):
|
||||
if not self.view_settings.get(page):
|
||||
|
@ -24,6 +24,7 @@ from . import logger, comic, isoLanguages
|
||||
from .constants import BookMeta
|
||||
from .helper import split_authors
|
||||
from .file_helper import get_temp_dir
|
||||
from .string_helper import strip_whitespaces
|
||||
|
||||
log = logger.create()
|
||||
|
||||
@ -97,9 +98,9 @@ def process(tmp_file_path, original_file_name, original_file_extension, rar_exec
|
||||
except Exception as ex:
|
||||
log.warning('cannot parse metadata, using default: %s', ex)
|
||||
|
||||
if not meta.title.strip():
|
||||
if not strip_whitespaces(meta.title):
|
||||
meta = meta._replace(title=original_file_name)
|
||||
if not meta.author.strip() or meta.author.lower() == 'unknown':
|
||||
if not strip_whitespaces(meta.author) or meta.author.lower() == 'unknown':
|
||||
meta = meta._replace(author=_('Unknown'))
|
||||
return meta
|
||||
|
||||
|
11
cps/web.py
11
cps/web.py
@ -60,6 +60,7 @@ from . import limiter
|
||||
from .services.worker import WorkerThread
|
||||
from .tasks_status import render_task_status
|
||||
from .usermanagement import user_login_required
|
||||
from .string_helper import strip_whitespaces
|
||||
|
||||
|
||||
feature_support = {
|
||||
@ -1286,7 +1287,7 @@ def register_post():
|
||||
if not config.get_mail_server_configured():
|
||||
flash(_("Oops! Email server is not configured, please contact your administrator."), category="error")
|
||||
return render_title_template('register.html', title=_("Register"), page="register")
|
||||
nickname = to_save.get("email", "").strip() if config.config_register_email else to_save.get('name')
|
||||
nickname = strip_whitespaces(to_save.get("email", "")) if config.config_register_email else to_save.get('name')
|
||||
if not nickname or not to_save.get("email"):
|
||||
flash(_("Oops! Please complete all fields."), category="error")
|
||||
return render_title_template('register.html', title=_("Register"), page="register")
|
||||
@ -1311,7 +1312,7 @@ def register_post():
|
||||
ub.session.commit()
|
||||
if feature_support['oauth']:
|
||||
register_user_with_oauth(content)
|
||||
send_registration_mail(to_save.get("email", "").strip(), nickname, password)
|
||||
send_registration_mail(strip_whitespaces(to_save.get("email", "")), nickname, password)
|
||||
except Exception:
|
||||
ub.session.rollback()
|
||||
flash(_("Oops! An unknown error occurred. Please try again later."), category="error")
|
||||
@ -1370,11 +1371,11 @@ def login():
|
||||
|
||||
|
||||
@web.route('/login', methods=['POST'])
|
||||
@limiter.limit("40/day", key_func=lambda: request.form.get('username', "").strip().lower())
|
||||
@limiter.limit("3/minute", key_func=lambda: request.form.get('username', "").strip().lower())
|
||||
@limiter.limit("40/day", key_func=lambda: strip_whitespaces(request.form.get('username', "")).lower())
|
||||
@limiter.limit("3/minute", key_func=lambda: strip_whitespaces(request.form.get('username', "")).lower())
|
||||
def login_post():
|
||||
form = request.form.to_dict()
|
||||
username = form.get('username', "").strip().lower().replace("\n","").replace("\r","")
|
||||
username = strip_whitespaces(form.get('username', "")).lower().replace("\n","").replace("\r","")
|
||||
try:
|
||||
limiter.check()
|
||||
except RateLimitExceeded:
|
||||
|
442
messages.pot
442
messages.pot
File diff suppressed because it is too large
Load Diff
@ -37,20 +37,20 @@
|
||||
<div class="row">
|
||||
<div class="col-xs-6 col-md-6 col-sm-offset-3" style="margin-top:50px;">
|
||||
|
||||
<p class='text-justify attribute'><strong>Start Time: </strong>2024-08-14 19:34:04</p>
|
||||
<p class='text-justify attribute'><strong>Start Time: </strong>2024-08-15 19:27:26</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-6 col-md-6 col-sm-offset-3">
|
||||
|
||||
<p class='text-justify attribute'><strong>Stop Time: </strong>2024-08-15 02:42:49</p>
|
||||
<p class='text-justify attribute'><strong>Stop Time: </strong>2024-08-16 02:42:05</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-6 col-md-6 col-sm-offset-3">
|
||||
<p class='text-justify attribute'><strong>Duration: </strong>6h 0 min</p>
|
||||
<p class='text-justify attribute'><strong>Duration: </strong>6h 5 min</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -852,11 +852,11 @@
|
||||
|
||||
|
||||
|
||||
<tr id="su" class="passClass">
|
||||
<tr id="su" class="failClass">
|
||||
<td>TestEbookConvertCalibreGDrive</td>
|
||||
<td class="text-center">7</td>
|
||||
<td class="text-center">7</td>
|
||||
<td class="text-center">0</td>
|
||||
<td class="text-center">6</td>
|
||||
<td class="text-center">1</td>
|
||||
<td class="text-center">0</td>
|
||||
<td class="text-center">0</td>
|
||||
<td class="text-center">
|
||||
@ -920,11 +920,31 @@
|
||||
|
||||
|
||||
|
||||
<tr id='pt9.7' class='hiddenRow bg-success'>
|
||||
<tr id="ft9.7" class="none bg-danger">
|
||||
<td>
|
||||
<div class='testcase'>TestEbookConvertCalibreGDrive - test_thumbnail_cache</div>
|
||||
</td>
|
||||
<td colspan='6' align='center'>PASS</td>
|
||||
<td colspan='6'>
|
||||
<div class="text-center">
|
||||
<a class="popup_link text-center" onfocus='blur()' onclick="showTestDetail('div_ft9.7')">FAIL</a>
|
||||
</div>
|
||||
<!--css div popup start-->
|
||||
<div id="div_ft9.7" class="popup_window test_output" style="display:block;">
|
||||
<div class='close_button pull-right'>
|
||||
<button type="button" class="close" aria-label="Close" onfocus="this.blur();"
|
||||
onclick="document.getElementById('div_ft9.7').style.display='none'"><span
|
||||
aria-hidden="true">×</span></button>
|
||||
</div>
|
||||
<div class="text-left pull-left">
|
||||
<pre class="text-left">Traceback (most recent call last):
|
||||
File "/home/ozzie/Development/calibre-web-test/test/test_ebook_convert_gdrive.py", line 495, in test_thumbnail_cache
|
||||
self.assertEqual(count_files(thumbnail_cache_path), 20)
|
||||
AssertionError: 25 != 20</pre>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
<!--css div popup end-->
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
@ -2878,11 +2898,11 @@ IndexError: list index out of range</pre>
|
||||
|
||||
|
||||
|
||||
<tr id="su" class="passClass">
|
||||
<tr id="su" class="failClass">
|
||||
<td>TestKoboSyncBig</td>
|
||||
<td class="text-center">6</td>
|
||||
<td class="text-center">6</td>
|
||||
<td class="text-center">0</td>
|
||||
<td class="text-center">5</td>
|
||||
<td class="text-center">1</td>
|
||||
<td class="text-center">0</td>
|
||||
<td class="text-center">0</td>
|
||||
<td class="text-center">
|
||||
@ -2892,11 +2912,31 @@ IndexError: list index out of range</pre>
|
||||
|
||||
|
||||
|
||||
<tr id='pt31.1' class='hiddenRow bg-success'>
|
||||
<tr id="ft31.1" class="none bg-danger">
|
||||
<td>
|
||||
<div class='testcase'>TestKoboSyncBig - test_download_cover</div>
|
||||
</td>
|
||||
<td colspan='6' align='center'>PASS</td>
|
||||
<td colspan='6'>
|
||||
<div class="text-center">
|
||||
<a class="popup_link text-center" onfocus='blur()' onclick="showTestDetail('div_ft31.1')">FAIL</a>
|
||||
</div>
|
||||
<!--css div popup start-->
|
||||
<div id="div_ft31.1" class="popup_window test_output" style="display:block;">
|
||||
<div class='close_button pull-right'>
|
||||
<button type="button" class="close" aria-label="Close" onfocus="this.blur();"
|
||||
onclick="document.getElementById('div_ft31.1').style.display='none'"><span
|
||||
aria-hidden="true">×</span></button>
|
||||
</div>
|
||||
<div class="text-left pull-left">
|
||||
<pre class="text-left">Traceback (most recent call last):
|
||||
File "/home/ozzie/Development/calibre-web-test/test/test_kobo_sync_big.py", line 482, in test_download_cover
|
||||
self.assertEqual(count_files(thumbnail_cache_path), (BOOK_COUNT+10)*2)
|
||||
AssertionError: 4590 != 3060</pre>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
<!--css div popup end-->
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
@ -4487,11 +4527,11 @@ IndexError: list index out of range</pre>
|
||||
|
||||
|
||||
|
||||
<tr id="su" class="passClass">
|
||||
<tr id="su" class="failClass">
|
||||
<td>TestThumbnailsEnv</td>
|
||||
<td class="text-center">1</td>
|
||||
<td class="text-center">1</td>
|
||||
<td class="text-center">0</td>
|
||||
<td class="text-center">1</td>
|
||||
<td class="text-center">0</td>
|
||||
<td class="text-center">0</td>
|
||||
<td class="text-center">
|
||||
@ -4501,11 +4541,31 @@ IndexError: list index out of range</pre>
|
||||
|
||||
|
||||
|
||||
<tr id='pt49.1' class='hiddenRow bg-success'>
|
||||
<tr id="ft49.1" class="none bg-danger">
|
||||
<td>
|
||||
<div class='testcase'>TestThumbnailsEnv - test_cover_cache_env_on_database_change</div>
|
||||
</td>
|
||||
<td colspan='6' align='center'>PASS</td>
|
||||
<td colspan='6'>
|
||||
<div class="text-center">
|
||||
<a class="popup_link text-center" onfocus='blur()' onclick="showTestDetail('div_ft49.1')">FAIL</a>
|
||||
</div>
|
||||
<!--css div popup start-->
|
||||
<div id="div_ft49.1" class="popup_window test_output" style="display:block;">
|
||||
<div class='close_button pull-right'>
|
||||
<button type="button" class="close" aria-label="Close" onfocus="this.blur();"
|
||||
onclick="document.getElementById('div_ft49.1').style.display='none'"><span
|
||||
aria-hidden="true">×</span></button>
|
||||
</div>
|
||||
<div class="text-left pull-left">
|
||||
<pre class="text-left">Traceback (most recent call last):
|
||||
File "/home/ozzie/Development/calibre-web-test/test/test_thumbnail_env.py", line 72, in test_cover_cache_env_on_database_change
|
||||
self.assertEqual(count_files(thumbnail_cache_path), 110*2)
|
||||
AssertionError: 330 != 220</pre>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
<!--css div popup end-->
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
@ -4514,8 +4574,8 @@ IndexError: list index out of range</pre>
|
||||
<tr id="su" class="failClass">
|
||||
<td>TestThumbnails</td>
|
||||
<td class="text-center">8</td>
|
||||
<td class="text-center">6</td>
|
||||
<td class="text-center">1</td>
|
||||
<td class="text-center">6</td>
|
||||
<td class="text-center">0</td>
|
||||
<td class="text-center">1</td>
|
||||
<td class="text-center">
|
||||
@ -4534,29 +4594,89 @@ IndexError: list index out of range</pre>
|
||||
|
||||
|
||||
|
||||
<tr id='pt50.2' class='hiddenRow bg-success'>
|
||||
<tr id="ft50.2" class="none bg-danger">
|
||||
<td>
|
||||
<div class='testcase'>TestThumbnails - test_cache_of_deleted_book</div>
|
||||
</td>
|
||||
<td colspan='6' align='center'>PASS</td>
|
||||
<td colspan='6'>
|
||||
<div class="text-center">
|
||||
<a class="popup_link text-center" onfocus='blur()' onclick="showTestDetail('div_ft50.2')">FAIL</a>
|
||||
</div>
|
||||
<!--css div popup start-->
|
||||
<div id="div_ft50.2" class="popup_window test_output" style="display:block;">
|
||||
<div class='close_button pull-right'>
|
||||
<button type="button" class="close" aria-label="Close" onfocus="this.blur();"
|
||||
onclick="document.getElementById('div_ft50.2').style.display='none'"><span
|
||||
aria-hidden="true">×</span></button>
|
||||
</div>
|
||||
<div class="text-left pull-left">
|
||||
<pre class="text-left">Traceback (most recent call last):
|
||||
File "/home/ozzie/Development/calibre-web-test/test/test_thumbnails.py", line 192, in test_cache_of_deleted_book
|
||||
self.assertEqual(book_thumbnail_reference, 2)
|
||||
AssertionError: 3 != 2</pre>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
<!--css div popup end-->
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<tr id='pt50.3' class='hiddenRow bg-success'>
|
||||
<tr id="ft50.3" class="none bg-danger">
|
||||
<td>
|
||||
<div class='testcase'>TestThumbnails - test_cover_cache_on_database_change</div>
|
||||
</td>
|
||||
<td colspan='6' align='center'>PASS</td>
|
||||
<td colspan='6'>
|
||||
<div class="text-center">
|
||||
<a class="popup_link text-center" onfocus='blur()' onclick="showTestDetail('div_ft50.3')">FAIL</a>
|
||||
</div>
|
||||
<!--css div popup start-->
|
||||
<div id="div_ft50.3" class="popup_window test_output" style="display:block;">
|
||||
<div class='close_button pull-right'>
|
||||
<button type="button" class="close" aria-label="Close" onfocus="this.blur();"
|
||||
onclick="document.getElementById('div_ft50.3').style.display='none'"><span
|
||||
aria-hidden="true">×</span></button>
|
||||
</div>
|
||||
<div class="text-left pull-left">
|
||||
<pre class="text-left">Traceback (most recent call last):
|
||||
File "/home/ozzie/Development/calibre-web-test/test/test_thumbnails.py", line 89, in test_cover_cache_on_database_change
|
||||
self.assertEqual(count_files(thumbnail_cache_path), 110*2)
|
||||
AssertionError: 333 != 220</pre>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
<!--css div popup end-->
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<tr id='pt50.4' class='hiddenRow bg-success'>
|
||||
<tr id="ft50.4" class="none bg-danger">
|
||||
<td>
|
||||
<div class='testcase'>TestThumbnails - test_cover_change_on_upload_new_cover</div>
|
||||
</td>
|
||||
<td colspan='6' align='center'>PASS</td>
|
||||
<td colspan='6'>
|
||||
<div class="text-center">
|
||||
<a class="popup_link text-center" onfocus='blur()' onclick="showTestDetail('div_ft50.4')">FAIL</a>
|
||||
</div>
|
||||
<!--css div popup start-->
|
||||
<div id="div_ft50.4" class="popup_window test_output" style="display:block;">
|
||||
<div class='close_button pull-right'>
|
||||
<button type="button" class="close" aria-label="Close" onfocus="this.blur();"
|
||||
onclick="document.getElementById('div_ft50.4').style.display='none'"><span
|
||||
aria-hidden="true">×</span></button>
|
||||
</div>
|
||||
<div class="text-left pull-left">
|
||||
<pre class="text-left">Traceback (most recent call last):
|
||||
File "/home/ozzie/Development/calibre-web-test/test/test_thumbnails.py", line 131, in test_cover_change_on_upload_new_cover
|
||||
self.assertEqual(110*2, count_files(thumbnail_cache_path))
|
||||
AssertionError: 220 != 333</pre>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
<!--css div popup end-->
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
@ -4570,20 +4690,60 @@ IndexError: list index out of range</pre>
|
||||
|
||||
|
||||
|
||||
<tr id='pt50.6' class='hiddenRow bg-success'>
|
||||
<tr id="ft50.6" class="none bg-danger">
|
||||
<td>
|
||||
<div class='testcase'>TestThumbnails - test_cover_on_upload_book</div>
|
||||
</td>
|
||||
<td colspan='6' align='center'>PASS</td>
|
||||
<td colspan='6'>
|
||||
<div class="text-center">
|
||||
<a class="popup_link text-center" onfocus='blur()' onclick="showTestDetail('div_ft50.6')">FAIL</a>
|
||||
</div>
|
||||
<!--css div popup start-->
|
||||
<div id="div_ft50.6" class="popup_window test_output" style="display:block;">
|
||||
<div class='close_button pull-right'>
|
||||
<button type="button" class="close" aria-label="Close" onfocus="this.blur();"
|
||||
onclick="document.getElementById('div_ft50.6').style.display='none'"><span
|
||||
aria-hidden="true">×</span></button>
|
||||
</div>
|
||||
<div class="text-left pull-left">
|
||||
<pre class="text-left">Traceback (most recent call last):
|
||||
File "/home/ozzie/Development/calibre-web-test/test/test_thumbnails.py", line 253, in test_cover_on_upload_book
|
||||
self.assertEqual(book_thumbnail_reference+2, count_files(thumbnail_cache_path))
|
||||
AssertionError: 335 != 336</pre>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
<!--css div popup end-->
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<tr id='pt50.7' class='hiddenRow bg-success'>
|
||||
<tr id="ft50.7" class="none bg-danger">
|
||||
<td>
|
||||
<div class='testcase'>TestThumbnails - test_remove_cover_from_cache</div>
|
||||
</td>
|
||||
<td colspan='6' align='center'>PASS</td>
|
||||
<td colspan='6'>
|
||||
<div class="text-center">
|
||||
<a class="popup_link text-center" onfocus='blur()' onclick="showTestDetail('div_ft50.7')">FAIL</a>
|
||||
</div>
|
||||
<!--css div popup start-->
|
||||
<div id="div_ft50.7" class="popup_window test_output" style="display:block;">
|
||||
<div class='close_button pull-right'>
|
||||
<button type="button" class="close" aria-label="Close" onfocus="this.blur();"
|
||||
onclick="document.getElementById('div_ft50.7').style.display='none'"><span
|
||||
aria-hidden="true">×</span></button>
|
||||
</div>
|
||||
<div class="text-left pull-left">
|
||||
<pre class="text-left">Traceback (most recent call last):
|
||||
File "/home/ozzie/Development/calibre-web-test/test/test_thumbnails.py", line 169, in test_remove_cover_from_cache
|
||||
self.assertEqual(book_thumbnail_reference - 2, count_files(thumbnail_cache_path))
|
||||
AssertionError: 334 != 333</pre>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
<!--css div popup end-->
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
@ -4605,9 +4765,9 @@ IndexError: list index out of range</pre>
|
||||
</div>
|
||||
<div class="text-left pull-left">
|
||||
<pre class="text-left">Traceback (most recent call last):
|
||||
File "/home/ozzie/Development/calibre-web-test/test/test_thumbnails.py", line 316, in test_sideloaded_book
|
||||
self.assertAlmostEqual(diff(BytesIO(list_cover), BytesIO(old_list_cover), delete_diff_file=True), 0.0,
|
||||
AssertionError: 0.006716588857765329 != 0.0 within 0.0001 delta (0.006716588857765329 difference)</pre>
|
||||
File "/home/ozzie/Development/calibre-web-test/test/test_thumbnails.py", line 281, in test_sideloaded_book
|
||||
self.assertEqual(book_thumbnail_reference, count_files(thumbnail_cache_path))
|
||||
AssertionError: 300 != 336</pre>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
@ -4618,11 +4778,11 @@ AssertionError: 0.006716588857765329 != 0.0 within 0.0001 delta (0.0067165888577
|
||||
|
||||
|
||||
|
||||
<tr id="su" class="skipClass">
|
||||
<tr id="su" class="failClass">
|
||||
<td>TestUpdater</td>
|
||||
<td class="text-center">9</td>
|
||||
<td class="text-center">8</td>
|
||||
<td class="text-center">0</td>
|
||||
<td class="text-center">7</td>
|
||||
<td class="text-center">1</td>
|
||||
<td class="text-center">0</td>
|
||||
<td class="text-center">1</td>
|
||||
<td class="text-center">
|
||||
@ -4668,11 +4828,31 @@ AssertionError: 0.006716588857765329 != 0.0 within 0.0001 delta (0.0067165888577
|
||||
|
||||
|
||||
|
||||
<tr id='pt51.5' class='hiddenRow bg-success'>
|
||||
<tr id="ft51.5" class="none bg-danger">
|
||||
<td>
|
||||
<div class='testcase'>TestUpdater - test_perform_update</div>
|
||||
</td>
|
||||
<td colspan='6' align='center'>PASS</td>
|
||||
<td colspan='6'>
|
||||
<div class="text-center">
|
||||
<a class="popup_link text-center" onfocus='blur()' onclick="showTestDetail('div_ft51.5')">FAIL</a>
|
||||
</div>
|
||||
<!--css div popup start-->
|
||||
<div id="div_ft51.5" class="popup_window test_output" style="display:block;">
|
||||
<div class='close_button pull-right'>
|
||||
<button type="button" class="close" aria-label="Close" onfocus="this.blur();"
|
||||
onclick="document.getElementById('div_ft51.5').style.display='none'"><span
|
||||
aria-hidden="true">×</span></button>
|
||||
</div>
|
||||
<div class="text-left pull-left">
|
||||
<pre class="text-left">Traceback (most recent call last):
|
||||
File "/home/ozzie/Development/calibre-web-test/test/test_updater.py", line 375, in test_perform_update
|
||||
self.assertEqual(20, count_files(thumbnail_cache_path))
|
||||
AssertionError: 20 != 30</pre>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
<!--css div popup end-->
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
@ -5959,8 +6139,8 @@ AssertionError: 0.006623550004797241 != 0.0058 within 0.0001 delta (0.0008235500
|
||||
<tr id='total_row' class="text-center bg-grey">
|
||||
<td>Total</td>
|
||||
<td>517</td>
|
||||
<td>497</td>
|
||||
<td>8</td>
|
||||
<td>488</td>
|
||||
<td>17</td>
|
||||
<td>3</td>
|
||||
<td>9</td>
|
||||
<td> </td>
|
||||
@ -5990,7 +6170,7 @@ AssertionError: 0.006623550004797241 != 0.0058 within 0.0001 delta (0.0008235500
|
||||
|
||||
<tr>
|
||||
<th>Platform</th>
|
||||
<td>Linux 6.5.0-45-generic #45~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Mon Jul 15 16:40:02 UTC 2 x86_64 x86_64</td>
|
||||
<td>Linux 6.8.0-40-generic #40~22.04.3-Ubuntu SMP PREEMPT_DYNAMIC Tue Jul 30 17:30:19 UTC 2 x86_64 x86_64</td>
|
||||
<td>Basic</td>
|
||||
</tr>
|
||||
|
||||
@ -6158,7 +6338,7 @@ AssertionError: 0.006623550004797241 != 0.0058 within 0.0001 delta (0.0008235500
|
||||
|
||||
<tr>
|
||||
<th>google-api-python-client</th>
|
||||
<td>2.140.0</td>
|
||||
<td>2.141.0</td>
|
||||
<td>TestBackupMetadataGdrive</td>
|
||||
</tr>
|
||||
|
||||
@ -6500,7 +6680,7 @@ AssertionError: 0.006623550004797241 != 0.0058 within 0.0001 delta (0.0008235500
|
||||
</div>
|
||||
|
||||
<script>
|
||||
drawCircle(497, 8, 3, 9);
|
||||
drawCircle(488, 17, 3, 9);
|
||||
showCase(5);
|
||||
</script>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user