mirror of
				https://github.com/janeczku/calibre-web
				synced 2025-10-31 15:23:02 +00:00 
			
		
		
		
	Merge branch 'Develop':
- Fix for new tornado version - bookmark for comic viewer - Bugfix for showing series containing only one book in list view containing having this book no series_index value set - updated requirements
This commit is contained in:
		| @@ -33,7 +33,7 @@ from functools import wraps | |||||||
| from urllib.parse import urlparse | from urllib.parse import urlparse | ||||||
|  |  | ||||||
| from flask import Blueprint, flash, redirect, url_for, abort, request, make_response, send_from_directory, g, Response | from flask import Blueprint, flash, redirect, url_for, abort, request, make_response, send_from_directory, g, Response | ||||||
| from flask import Markup | from markupsafe import Markup | ||||||
| from flask_login import login_required, current_user, logout_user | from flask_login import login_required, current_user, logout_user | ||||||
| from flask_babel import gettext as _ | from flask_babel import gettext as _ | ||||||
| from flask_babel import get_locale, format_time, format_datetime, format_timedelta | from flask_babel import get_locale, format_time, format_datetime, format_timedelta | ||||||
|   | |||||||
| @@ -663,7 +663,7 @@ class CalibreDB: | |||||||
|  |  | ||||||
|         cls.session_factory = scoped_session(sessionmaker(autocommit=False, |         cls.session_factory = scoped_session(sessionmaker(autocommit=False, | ||||||
|                                                           autoflush=True, |                                                           autoflush=True, | ||||||
|                                                           bind=cls.engine)) |                                                           bind=cls.engine, future=True)) | ||||||
|         for inst in cls.instances: |         for inst in cls.instances: | ||||||
|             inst.init_session() |             inst.init_session() | ||||||
|  |  | ||||||
|   | |||||||
| @@ -25,16 +25,15 @@ from datetime import datetime | |||||||
| import json | import json | ||||||
| from shutil import copyfile | from shutil import copyfile | ||||||
| from uuid import uuid4 | from uuid import uuid4 | ||||||
| from markupsafe import escape  # dependency of flask | from markupsafe import escape, Markup  # dependency of flask | ||||||
| from functools import wraps | from functools import wraps | ||||||
| import re |  | ||||||
|  |  | ||||||
| try: | try: | ||||||
|     from lxml.html.clean import clean_html, Cleaner |     from lxml.html.clean import clean_html, Cleaner | ||||||
| except ImportError: | except ImportError: | ||||||
|     clean_html = None |     clean_html = None | ||||||
|  |  | ||||||
| from flask import Blueprint, request, flash, redirect, url_for, abort, Markup, Response | from flask import Blueprint, request, flash, redirect, url_for, abort, Response | ||||||
| from flask_babel import gettext as _ | from flask_babel import gettext as _ | ||||||
| from flask_babel import lazy_gettext as N_ | from flask_babel import lazy_gettext as N_ | ||||||
| from flask_babel import get_locale | from flask_babel import get_locale | ||||||
|   | |||||||
							
								
								
									
										33
									
								
								cps/kobo.py
									
									
									
									
									
								
							
							
						
						
									
										33
									
								
								cps/kobo.py
									
									
									
									
									
								
							| @@ -166,12 +166,6 @@ def HandleSyncRequest(): | |||||||
|     only_kobo_shelves = current_user.kobo_only_shelves_sync |     only_kobo_shelves = current_user.kobo_only_shelves_sync | ||||||
|  |  | ||||||
|     if only_kobo_shelves: |     if only_kobo_shelves: | ||||||
|         #if sqlalchemy_version2: |  | ||||||
|         #    changed_entries = select(db.Books, |  | ||||||
|         #                             ub.ArchivedBook.last_modified, |  | ||||||
|         #                             ub.BookShelf.date_added, |  | ||||||
|         #                             ub.ArchivedBook.is_archived) |  | ||||||
|         #else: |  | ||||||
|         changed_entries = calibre_db.session.query(db.Books, |         changed_entries = calibre_db.session.query(db.Books, | ||||||
|                                                    ub.ArchivedBook.last_modified, |                                                    ub.ArchivedBook.last_modified, | ||||||
|                                                    ub.BookShelf.date_added, |                                                    ub.BookShelf.date_added, | ||||||
| @@ -192,9 +186,6 @@ def HandleSyncRequest(): | |||||||
|                            .filter(ub.Shelf.kobo_sync) |                            .filter(ub.Shelf.kobo_sync) | ||||||
|                            .distinct()) |                            .distinct()) | ||||||
|     else: |     else: | ||||||
|         #if sqlalchemy_version2: |  | ||||||
|         #    changed_entries = select(db.Books, ub.ArchivedBook.last_modified, ub.ArchivedBook.is_archived) |  | ||||||
|         #else: |  | ||||||
|         changed_entries = calibre_db.session.query(db.Books, |         changed_entries = calibre_db.session.query(db.Books, | ||||||
|                                                    ub.ArchivedBook.last_modified, |                                                    ub.ArchivedBook.last_modified, | ||||||
|                                                    ub.ArchivedBook.is_archived) |                                                    ub.ArchivedBook.is_archived) | ||||||
| @@ -209,9 +200,6 @@ def HandleSyncRequest(): | |||||||
|                            .order_by(db.Books.id)) |                            .order_by(db.Books.id)) | ||||||
|  |  | ||||||
|     reading_states_in_new_entitlements = [] |     reading_states_in_new_entitlements = [] | ||||||
|     #if sqlalchemy_version2: |  | ||||||
|     #    books = calibre_db.session.execute(changed_entries.limit(SYNC_ITEM_LIMIT)) |  | ||||||
|     #else: |  | ||||||
|     books = changed_entries.limit(SYNC_ITEM_LIMIT) |     books = changed_entries.limit(SYNC_ITEM_LIMIT) | ||||||
|     log.debug("Books to Sync: {}".format(len(books.all()))) |     log.debug("Books to Sync: {}".format(len(books.all()))) | ||||||
|     for book in books: |     for book in books: | ||||||
| @@ -255,13 +243,6 @@ def HandleSyncRequest(): | |||||||
|         new_books_last_created = max(ts_created, new_books_last_created) |         new_books_last_created = max(ts_created, new_books_last_created) | ||||||
|         kobo_sync_status.add_synced_books(book.Books.id) |         kobo_sync_status.add_synced_books(book.Books.id) | ||||||
|  |  | ||||||
|     '''if sqlalchemy_version2: |  | ||||||
|         max_change = calibre_db.session.execute(changed_entries |  | ||||||
|                                                 .filter(ub.ArchivedBook.is_archived) |  | ||||||
|                                                 .filter(ub.ArchivedBook.user_id == current_user.id) |  | ||||||
|                                                 .order_by(func.datetime(ub.ArchivedBook.last_modified).desc()))\ |  | ||||||
|             .columns(db.Books).first() |  | ||||||
|     else:''' |  | ||||||
|     max_change = changed_entries.filter(ub.ArchivedBook.is_archived)\ |     max_change = changed_entries.filter(ub.ArchivedBook.is_archived)\ | ||||||
|         .filter(ub.ArchivedBook.user_id == current_user.id) \ |         .filter(ub.ArchivedBook.user_id == current_user.id) \ | ||||||
|         .order_by(func.datetime(ub.ArchivedBook.last_modified).desc()).first() |         .order_by(func.datetime(ub.ArchivedBook.last_modified).desc()).first() | ||||||
| @@ -271,10 +252,6 @@ def HandleSyncRequest(): | |||||||
|     new_archived_last_modified = max(new_archived_last_modified, max_change) |     new_archived_last_modified = max(new_archived_last_modified, max_change) | ||||||
|  |  | ||||||
|     # no. of books returned |     # no. of books returned | ||||||
|     '''if sqlalchemy_version2: |  | ||||||
|         entries = calibre_db.session.execute(changed_entries).all() |  | ||||||
|         book_count = len(entries) |  | ||||||
|     else:''' |  | ||||||
|     book_count = changed_entries.count() |     book_count = changed_entries.count() | ||||||
|     # last entry: |     # last entry: | ||||||
|     cont_sync = bool(book_count) |     cont_sync = bool(book_count) | ||||||
| @@ -523,7 +500,7 @@ def get_metadata(book): | |||||||
| @requires_kobo_auth | @requires_kobo_auth | ||||||
| # Creates a Shelf with the given items, and returns the shelf's uuid. | # Creates a Shelf with the given items, and returns the shelf's uuid. | ||||||
| def HandleTagCreate(): | def HandleTagCreate(): | ||||||
|     # catch delete requests, otherwise the are handled in the book delete handler |     # catch delete requests, otherwise they are handled in the book delete handler | ||||||
|     if request.method == "DELETE": |     if request.method == "DELETE": | ||||||
|         abort(405) |         abort(405) | ||||||
|     name, items = None, None |     name, items = None, None | ||||||
| @@ -717,14 +694,6 @@ def sync_shelves(sync_token, sync_results, only_kobo_shelves=False): | |||||||
|             }) |             }) | ||||||
|         extra_filters.append(ub.Shelf.kobo_sync) |         extra_filters.append(ub.Shelf.kobo_sync) | ||||||
|  |  | ||||||
|     '''if sqlalchemy_version2: |  | ||||||
|         shelflist = ub.session.execute(select(ub.Shelf).outerjoin(ub.BookShelf).filter( |  | ||||||
|             or_(func.datetime(ub.Shelf.last_modified) > sync_token.tags_last_modified, |  | ||||||
|                 func.datetime(ub.BookShelf.date_added) > sync_token.tags_last_modified), |  | ||||||
|             ub.Shelf.user_id == current_user.id, |  | ||||||
|             *extra_filters |  | ||||||
|         ).distinct().order_by(func.datetime(ub.Shelf.last_modified).asc())).columns(ub.Shelf) |  | ||||||
|     else:''' |  | ||||||
|     shelflist = ub.session.query(ub.Shelf).outerjoin(ub.BookShelf).filter( |     shelflist = ub.session.query(ub.Shelf).outerjoin(ub.BookShelf).filter( | ||||||
|         or_(func.datetime(ub.Shelf.last_modified) > sync_token.tags_last_modified, |         or_(func.datetime(ub.Shelf.last_modified) > sync_token.tags_last_modified, | ||||||
|             func.datetime(ub.BookShelf.date_added) > sync_token.tags_last_modified), |             func.datetime(ub.BookShelf.date_added) > sync_token.tags_last_modified), | ||||||
|   | |||||||
| @@ -287,5 +287,8 @@ class WebServer(object): | |||||||
|         if self.wsgiserver: |         if self.wsgiserver: | ||||||
|             if _GEVENT: |             if _GEVENT: | ||||||
|                 self.wsgiserver.close() |                 self.wsgiserver.close() | ||||||
|  |             else: | ||||||
|  |                 if restart: | ||||||
|  |                     self.wsgiserver.call_later(1.0, self.wsgiserver.stop) | ||||||
|                 else: |                 else: | ||||||
|                     self.wsgiserver.add_callback_from_signal(self.wsgiserver.stop) |                     self.wsgiserver.add_callback_from_signal(self.wsgiserver.stop) | ||||||
|   | |||||||
| @@ -19,10 +19,8 @@ | |||||||
|  |  | ||||||
| import sys | import sys | ||||||
| from base64 import b64decode, b64encode | from base64 import b64decode, b64encode | ||||||
| from jsonschema import validate, exceptions, __version__ | from jsonschema import validate, exceptions | ||||||
| from datetime import datetime, timezone | from datetime import datetime | ||||||
|  |  | ||||||
| from urllib.parse import unquote |  | ||||||
|  |  | ||||||
| from flask import json | from flask import json | ||||||
| from .. import logger | from .. import logger | ||||||
|   | |||||||
| @@ -71,6 +71,7 @@ var settings = { | |||||||
|     fitMode: kthoom.Key.B, |     fitMode: kthoom.Key.B, | ||||||
|     theme: "light", |     theme: "light", | ||||||
|     direction: 0, // 0 = Left to Right, 1 = Right to Left |     direction: 0, // 0 = Left to Right, 1 = Right to Left | ||||||
|  |     nextPage: 0, // 0 = Reset to Top, 1 = Remember Position | ||||||
| 	scrollbar: 1, // 0 = Hide Scrollbar, 1 = Show Scrollbar	 | 	scrollbar: 1, // 0 = Hide Scrollbar, 1 = Show Scrollbar	 | ||||||
|     pageDisplay: 0 // 0 = Single Page, 1 = Long Strip |     pageDisplay: 0 // 0 = Single Page, 1 = Long Strip | ||||||
| }; | }; | ||||||
| @@ -177,12 +178,36 @@ kthoom.ImageFile = function(file) { | |||||||
|     } |     } | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | function updateDirectionButtons(){ | ||||||
|  |     $("#right").show(); | ||||||
|  |     $("#left").show(); | ||||||
|  |     if (currentImage == 0 ) { | ||||||
|  |         if (settings.direction === 0) { | ||||||
|  |             $("#right").show(); | ||||||
|  |             $("#left").hide(); | ||||||
|  |         } else { | ||||||
|  |             $("#left").show(); | ||||||
|  |             $("#right").hide(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     if ((currentImage + 1) >= Math.max(totalImages, imageFiles.length)) { | ||||||
|  |         if (settings.direction === 0) { | ||||||
|  |             $("#left").show(); | ||||||
|  |             $("#right").hide(); | ||||||
|  |         } else { | ||||||
|  |             $("#right").show(); | ||||||
|  |             $("#left").hide(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| function initProgressClick() { | function initProgressClick() { | ||||||
|     $("#progress").click(function(e) { |     $("#progress").click(function(e) { | ||||||
|         var offset = $(this).offset(); |         var offset = $(this).offset(); | ||||||
|         var x = e.pageX - offset.left; |         var x = e.pageX - offset.left; | ||||||
|         var rate = settings.direction === 0 ? x / $(this).width() : 1 - x / $(this).width(); |         var rate = settings.direction === 0 ? x / $(this).width() : 1 - x / $(this).width(); | ||||||
|         currentImage = Math.max(1, Math.ceil(rate * totalImages)) - 1; |         currentImage = Math.max(1, Math.ceil(rate * totalImages)) - 1; | ||||||
|  |         updateDirectionButtons(); | ||||||
|  |         setBookmark(); | ||||||
|         updatePage(); |         updatePage(); | ||||||
|     }); |     }); | ||||||
| } | } | ||||||
| @@ -222,6 +247,7 @@ function loadFromArrayBuffer(ab) { | |||||||
|                                      |                                      | ||||||
|                                     // display first page if we haven't yet |                                     // display first page if we haven't yet | ||||||
|                                     if (imageFiles.length === currentImage + 1) { |                                     if (imageFiles.length === currentImage + 1) { | ||||||
|  |                                         updateDirectionButtons(); | ||||||
|                                         updatePage(); |                                         updatePage(); | ||||||
|                                     } |                                     } | ||||||
|                                 } else { |                                 } else { | ||||||
| @@ -409,6 +435,7 @@ function showLeftPage() { | |||||||
|     } else { |     } else { | ||||||
|         showNextPage(); |         showNextPage(); | ||||||
|     } |     } | ||||||
|  |     setBookmark(); | ||||||
| } | } | ||||||
|  |  | ||||||
| function showRightPage() { | function showRightPage() { | ||||||
| @@ -417,6 +444,7 @@ function showRightPage() { | |||||||
|     } else { |     } else { | ||||||
|         showPrevPage(); |         showPrevPage(); | ||||||
|     } |     } | ||||||
|  |     setBookmark(); | ||||||
| } | } | ||||||
|  |  | ||||||
| function showPrevPage() { | function showPrevPage() { | ||||||
| @@ -427,6 +455,7 @@ function showPrevPage() { | |||||||
|     } else { |     } else { | ||||||
|         updatePage(); |         updatePage(); | ||||||
|     } |     } | ||||||
|  |     updateDirectionButtons(); | ||||||
| } | } | ||||||
|  |  | ||||||
| function showNextPage() { | function showNextPage() { | ||||||
| @@ -437,6 +466,7 @@ function showNextPage() { | |||||||
|     } else { |     } else { | ||||||
|         updatePage(); |         updatePage(); | ||||||
|     } |     } | ||||||
|  |     updateDirectionButtons(); | ||||||
| } | } | ||||||
|  |  | ||||||
| function scrollCurrentImageIntoView() { | function scrollCurrentImageIntoView() { | ||||||
| @@ -621,6 +651,16 @@ function drawCanvas() { | |||||||
|     $("#mainContent").append(canvasElement); |     $("#mainContent").append(canvasElement); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | function updateArrows() { | ||||||
|  |     if ($('input[name="direction"]:checked').val() === "0") { | ||||||
|  |         $("#prev_page_key").html("←"); | ||||||
|  |         $("#next_page_key").html("→"); | ||||||
|  |     } else { | ||||||
|  |         $("#prev_page_key").html("→"); | ||||||
|  |         $("#next_page_key").html("←"); | ||||||
|  |     } | ||||||
|  | }; | ||||||
|  |  | ||||||
| function init(filename) { | function init(filename) { | ||||||
|     var request = new XMLHttpRequest(); |     var request = new XMLHttpRequest(); | ||||||
|     request.open("GET", filename); |     request.open("GET", filename); | ||||||
| @@ -677,6 +717,7 @@ function init(filename) { | |||||||
|         if (["hflip", "vflip", "rotateTimes"].includes(this.name)) { |         if (["hflip", "vflip", "rotateTimes"].includes(this.name)) { | ||||||
|             reloadImages(); |             reloadImages(); | ||||||
|         } else if (this.name === "direction") { |         } else if (this.name === "direction") { | ||||||
|  |             updateDirectionButtons(); | ||||||
|             return updateProgress(); |             return updateProgress(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -726,7 +767,7 @@ function init(filename) { | |||||||
|         }, |         }, | ||||||
|     }); |     }); | ||||||
|     $(".mainImage").click(function (evt) { |     $(".mainImage").click(function (evt) { | ||||||
|         // Firefox does not support offsetX/Y so we have to manually calculate |         // Firefox does not support offsetX/Y, so we have to manually calculate | ||||||
|         // where the user clicked in the image. |         // where the user clicked in the image. | ||||||
|         var mainContentWidth = $("#mainContent").width(); |         var mainContentWidth = $("#mainContent").width(); | ||||||
|         var mainContentHeight = $("#mainContent").height(); |         var mainContentHeight = $("#mainContent").height(); | ||||||
| @@ -764,13 +805,21 @@ function init(filename) { | |||||||
|     // Scrolling up/down will update current image if a new image is into view (for Long Strip Display) |     // Scrolling up/down will update current image if a new image is into view (for Long Strip Display) | ||||||
|     $("#mainContent").scroll(function (){ |     $("#mainContent").scroll(function (){ | ||||||
|         var scroll = $("#mainContent").scrollTop(); |         var scroll = $("#mainContent").scrollTop(); | ||||||
|  |         var viewLength = 0; | ||||||
|  |         $(".mainImage").each(function(){ | ||||||
|  |             viewLength += $(this).height(); | ||||||
|  |         }); | ||||||
|         if (settings.pageDisplay === 0) { |         if (settings.pageDisplay === 0) { | ||||||
|             // Don't trigger the scroll for Single Page |             // Don't trigger the scroll for Single Page | ||||||
|         } else if (scroll > prevScrollPosition) { |         } else if (scroll > prevScrollPosition) { | ||||||
|             //Scroll Down |             //Scroll Down | ||||||
|             if (currentImage + 1 < imageFiles.length) { |             if (currentImage + 1 < imageFiles.length) { | ||||||
|                 if (currentImageOffset(currentImage + 1) <= 1) { |                 if (currentImageOffset(currentImage + 1) <= 1) { | ||||||
|                     currentImage++; |                     currentImage = Math.floor((imageFiles.length) / (viewLength-viewLength/(imageFiles.length)) * scroll, 0); | ||||||
|  |                     if ( currentImage >= imageFiles.length) { | ||||||
|  |                         currentImage = imageFiles.length - 1; | ||||||
|  |                     } | ||||||
|  |                     console.log(currentImage); | ||||||
|                     scrollTocToActive(); |                     scrollTocToActive(); | ||||||
|                     updateProgress(); |                     updateProgress(); | ||||||
|                 } |                 } | ||||||
| @@ -779,13 +828,13 @@ function init(filename) { | |||||||
|             //Scroll Up |             //Scroll Up | ||||||
|             if (currentImage - 1 > -1) { |             if (currentImage - 1 > -1) { | ||||||
|                 if (currentImageOffset(currentImage - 1) >= 0) { |                 if (currentImageOffset(currentImage - 1) >= 0) { | ||||||
|                     currentImage--; |                     currentImage = Math.floor((imageFiles.length) / (viewLength-viewLength/(imageFiles.length)) * scroll, 0); | ||||||
|  |                     console.log(currentImage); | ||||||
|                     scrollTocToActive(); |                     scrollTocToActive(); | ||||||
|                     updateProgress(); |                     updateProgress(); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         // Update scroll position |         // Update scroll position | ||||||
|         prevScrollPosition = scroll; |         prevScrollPosition = scroll; | ||||||
|     }); |     }); | ||||||
| @@ -794,3 +843,31 @@ function init(filename) { | |||||||
| function currentImageOffset(imageIndex) { | function currentImageOffset(imageIndex) { | ||||||
|     return $(".mainImage").eq(imageIndex).offset().top - $("#mainContent").position().top |     return $(".mainImage").eq(imageIndex).offset().top - $("#mainContent").position().top | ||||||
| } | } | ||||||
|  |  | ||||||
|  | function setBookmark() { | ||||||
|  |   // get csrf_token | ||||||
|  |     let csrf_token = $("input[name='csrf_token']").val(); | ||||||
|  |     //This sends a bookmark update to calibreweb. | ||||||
|  |     $.ajax(calibre.bookmarkUrl, { | ||||||
|  |         method: "post", | ||||||
|  |         data: { | ||||||
|  |             csrf_token: csrf_token, | ||||||
|  |             bookmark: currentImage | ||||||
|  |         } | ||||||
|  |     }).fail(function (xhr, status, error) { | ||||||
|  |         console.error(error); | ||||||
|  |     }); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | $(function() { | ||||||
|  |     $('input[name="direction"]').change(function () { | ||||||
|  |         updateArrows(); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     $('#left').click(function () { | ||||||
|  |         showLeftPage(); | ||||||
|  |     }); | ||||||
|  |     $('#right').click(function () { | ||||||
|  |         showRightPage(); | ||||||
|  |     }); | ||||||
|  | }); | ||||||
|   | |||||||
| @@ -333,7 +333,6 @@ $(function() { | |||||||
|                 } else { |                 } else { | ||||||
|                     $("#parent").addClass('hidden') |                     $("#parent").addClass('hidden') | ||||||
|                 } |                 } | ||||||
|                 // console.log(data); |  | ||||||
|                 data.files.forEach(function(entry) { |                 data.files.forEach(function(entry) { | ||||||
|                     if(entry.type === "dir") { |                     if(entry.type === "dir") { | ||||||
|                         var type = "<span class=\"glyphicon glyphicon-folder-close\"></span>"; |                         var type = "<span class=\"glyphicon glyphicon-folder-close\"></span>"; | ||||||
|   | |||||||
| @@ -1,5 +1,6 @@ | |||||||
| <!DOCTYPE html> | <!DOCTYPE html> | ||||||
| <html> | <html> | ||||||
|  |  | ||||||
| <head> | <head> | ||||||
|   <meta charset="utf-8"> |   <meta charset="utf-8"> | ||||||
|   <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> |   <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> | ||||||
| @@ -20,23 +21,6 @@ | |||||||
|   <script src="{{ url_for('static', filename='js/libs/screenfull.min.js') }}"></script> |   <script src="{{ url_for('static', filename='js/libs/screenfull.min.js') }}"></script> | ||||||
|   <script src="{{ url_for('static', filename='js/compress/uncompress.js') }}"></script> |   <script src="{{ url_for('static', filename='js/compress/uncompress.js') }}"></script> | ||||||
|   <script src="{{ url_for('static', filename='js/kthoom.js') }}"></script> |   <script src="{{ url_for('static', filename='js/kthoom.js') }}"></script> | ||||||
|   <script> |  | ||||||
|     var updateArrows = function() { |  | ||||||
|       if ($('input[name="direction"]:checked').val() === "0") { |  | ||||||
|         $("#prev_page_key").html("←"); |  | ||||||
|         $("#next_page_key").html("→"); |  | ||||||
|       } else { |  | ||||||
|         $("#prev_page_key").html("→"); |  | ||||||
|         $("#next_page_key").html("←"); |  | ||||||
|       } |  | ||||||
|     }; |  | ||||||
|     document.onreadystatechange = function () { |  | ||||||
|       if (document.readyState == "complete") { |  | ||||||
|       	init("{{ url_for('web.serve_book', book_id=comicfile, book_format=extension) }}"); |  | ||||||
|       	updateArrows(); |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   </script> |  | ||||||
| </head> | </head> | ||||||
| <body> | <body> | ||||||
| <div id="sidebar"> | <div id="sidebar"> | ||||||
| @@ -77,8 +61,8 @@ | |||||||
|   <div id="mainContent" tabindex="-1"> |   <div id="mainContent" tabindex="-1"> | ||||||
|     <div id="mainText" style="display:none"></div> |     <div id="mainText" style="display:none"></div> | ||||||
|   </div> |   </div> | ||||||
|   <div id="left" class="arrow" onclick="showLeftPage()">‹</div> |   <div id="left" class="arrow" style="display:none">‹</div> | ||||||
|   <div id="right" class="arrow" onclick="showRightPage()">›</div> |   <div id="right" class="arrow" style="display:none">›</div> | ||||||
| </div> | </div> | ||||||
|  |  | ||||||
| <div class="modal md-effect-1" id="settings-modal"> | <div class="modal md-effect-1" id="settings-modal"> | ||||||
| @@ -171,6 +155,15 @@ | |||||||
|               </div> |               </div> | ||||||
|             </td> |             </td> | ||||||
|           </tr> |           </tr> | ||||||
|  |           <tr> | ||||||
|  |             <th>{{_('Next Page')}}:</th> | ||||||
|  |             <td> | ||||||
|  |               <div class="inputs"> | ||||||
|  |                 <label for="resetToTop"><input type="radio" id="resetToTop" name="nextPage" value="0" /> {{_('Reset to Top')}}</label> | ||||||
|  |                 <label for="rememberPosition"><input type="radio" id="rememberPosition" name="nextPage" value="1" /> {{_('Remember Position')}}</label> | ||||||
|  |                   </div> | ||||||
|  |                 </td> | ||||||
|  |               </tr> | ||||||
|               <tr>                 |               <tr>                 | ||||||
|             <th>{{_('Scrollbar')}}:</th> |             <th>{{_('Scrollbar')}}:</th> | ||||||
|             <td> |             <td> | ||||||
| @@ -188,10 +181,25 @@ | |||||||
|     </div> |     </div> | ||||||
|   </div> |   </div> | ||||||
|   <div class="overlay"></div> |   <div class="overlay"></div> | ||||||
|  |   <input type="hidden" name="csrf_token" value="{{ csrf_token() }}"> | ||||||
|   <script> |   <script> | ||||||
|   $('input[name="direction"]').change(function() { |     window.calibre = { | ||||||
|     updateArrows(); |         bookmarkUrl: "{{ url_for('web.set_bookmark', book_id=comicfile, book_format=extension.upper()) }}", | ||||||
|   }); |         bookmark: "{{ bookmark.bookmark_key if bookmark != None }}", | ||||||
|  |         useBookmarks: "{{ current_user.is_authenticated | tojson }}" | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     document.onreadystatechange = function () { | ||||||
|  |       if (document.readyState == "complete") { | ||||||
|  |           if (calibre.useBookmarks) { | ||||||
|  |               currentImage = eval(calibre.bookmark); | ||||||
|  |               if (typeof currentImage !== 'number') { | ||||||
|  |                   currentImage = 0; | ||||||
|  |               } | ||||||
|  |           } | ||||||
|  |           init("{{ url_for('web.serve_book', book_id=comicfile, book_format=extension) }}"); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|   </script> |   </script> | ||||||
| </body> | </body> | ||||||
| </html> | </html> | ||||||
|   | |||||||
| @@ -16,12 +16,12 @@ | |||||||
| #  You should have received a copy of the GNU General Public License | #  You should have received a copy of the GNU General Public License | ||||||
| #  along with this program. If not, see <http://www.gnu.org/licenses/>. | #  along with this program. If not, see <http://www.gnu.org/licenses/>. | ||||||
|  |  | ||||||
|  |  | ||||||
| from tornado.wsgi import WSGIContainer | from tornado.wsgi import WSGIContainer | ||||||
| import tornado | import tornado | ||||||
|  |  | ||||||
| from tornado import escape | from tornado import escape | ||||||
| from tornado import httputil | from tornado import httputil | ||||||
|  | from tornado.ioloop import IOLoop | ||||||
|  |  | ||||||
| from typing import List, Tuple, Optional, Callable, Any, Dict, Text | from typing import List, Tuple, Optional, Callable, Any, Dict, Text | ||||||
| from types import TracebackType | from types import TracebackType | ||||||
| @@ -34,6 +34,7 @@ if typing.TYPE_CHECKING: | |||||||
| class MyWSGIContainer(WSGIContainer): | class MyWSGIContainer(WSGIContainer): | ||||||
|  |  | ||||||
|     def __call__(self, request: httputil.HTTPServerRequest) -> None: |     def __call__(self, request: httputil.HTTPServerRequest) -> None: | ||||||
|  |         if tornado.version_info < (6, 3, 0, -99): | ||||||
|             data = {}  # type: Dict[str, Any] |             data = {}  # type: Dict[str, Any] | ||||||
|             response = []  # type: List[bytes] |             response = []  # type: List[bytes] | ||||||
|  |  | ||||||
| @@ -53,7 +54,7 @@ class MyWSGIContainer(WSGIContainer): | |||||||
|                 return response.append |                 return response.append | ||||||
|  |  | ||||||
|             app_response = self.wsgi_application( |             app_response = self.wsgi_application( | ||||||
|             MyWSGIContainer.environ(request), start_response |                 MyWSGIContainer.environ(self, request), start_response | ||||||
|             ) |             ) | ||||||
|             try: |             try: | ||||||
|                 response.extend(app_response) |                 response.extend(app_response) | ||||||
| @@ -85,9 +86,14 @@ class MyWSGIContainer(WSGIContainer): | |||||||
|             request.connection.write_headers(start_line, header_obj, chunk=body) |             request.connection.write_headers(start_line, header_obj, chunk=body) | ||||||
|             request.connection.finish() |             request.connection.finish() | ||||||
|             self._log(status_code, request) |             self._log(status_code, request) | ||||||
|  |         else: | ||||||
|  |             IOLoop.current().spawn_callback(self.handle_request, request) | ||||||
|  |  | ||||||
|     @staticmethod |  | ||||||
|     def environ(request: httputil.HTTPServerRequest) -> Dict[Text, Any]: |     def environ(self, request: httputil.HTTPServerRequest) -> Dict[Text, Any]: | ||||||
|  |         try: | ||||||
|  |             environ = WSGIContainer.environ(self, request) | ||||||
|  |         except TypeError as e: | ||||||
|             environ = WSGIContainer.environ(request) |             environ = WSGIContainer.environ(request) | ||||||
|         environ['RAW_URI'] = request.path |         environ['RAW_URI'] = request.path | ||||||
|         return environ |         return environ | ||||||
|   | |||||||
| @@ -1014,7 +1014,7 @@ def series_list(): | |||||||
|                                                 func.max(db.Books.series_index), db.Books.id) |                                                 func.max(db.Books.series_index), db.Books.id) | ||||||
|                        .join(db.books_series_link).join(db.Series).filter(calibre_db.common_filters()) |                        .join(db.books_series_link).join(db.Series).filter(calibre_db.common_filters()) | ||||||
|                        .group_by(text('books_series_link.series')) |                        .group_by(text('books_series_link.series')) | ||||||
|                        .having(func.max(db.Books.series_index)) |                        .having(or_(func.max(db.Books.series_index), db.Books.series_index=="")) | ||||||
|                        .order_by(order) |                        .order_by(order) | ||||||
|                        .all()) |                        .all()) | ||||||
|             return render_title_template('grid.html', entries=entries, folder='web.books_list', charlist=char_list, |             return render_title_template('grid.html', entries=entries, folder='web.books_list', charlist=char_list, | ||||||
| @@ -1569,7 +1569,7 @@ def read_book(book_id, book_format): | |||||||
|                         title = title + " #" + '{0:.2f}'.format(book.series_index).rstrip('0').rstrip('.') |                         title = title + " #" + '{0:.2f}'.format(book.series_index).rstrip('0').rstrip('.') | ||||||
|                 log.debug("Start comic reader for %d", book_id) |                 log.debug("Start comic reader for %d", book_id) | ||||||
|                 return render_title_template('readcbr.html', comicfile=all_name, title=title, |                 return render_title_template('readcbr.html', comicfile=all_name, title=title, | ||||||
|                                              extension=fileExt) |                                              extension=fileExt, bookmark=bookmark) | ||||||
|         log.debug("Selected book is unavailable. File does not exist or is not accessible") |         log.debug("Selected book is unavailable. File does not exist or is not accessible") | ||||||
|         flash(_("Oops! Selected book is unavailable. File does not exist or is not accessible"), |         flash(_("Oops! Selected book is unavailable. File does not exist or is not accessible"), | ||||||
|               category="error") |               category="error") | ||||||
|   | |||||||
| @@ -1,31 +1,31 @@ | |||||||
| # GDrive Integration | # GDrive Integration | ||||||
| google-api-python-client>=1.7.11,<2.90.0 | google-api-python-client>=1.7.11,<2.98.0 | ||||||
| gevent>20.6.0,<23.0.0 | gevent>20.6.0,<24.0.0 | ||||||
| greenlet>=0.4.17,<2.1.0 | greenlet>=0.4.17,<2.1.0 | ||||||
| httplib2>=0.9.2,<0.23.0 | httplib2>=0.9.2,<0.23.0 | ||||||
| oauth2client>=4.0.0,<4.1.4 | oauth2client>=4.0.0,<4.1.4 | ||||||
| uritemplate>=3.0.0,<4.2.0 | uritemplate>=3.0.0,<4.2.0 | ||||||
| pyasn1-modules>=0.0.8,<0.4.0 | pyasn1-modules>=0.0.8,<0.4.0 | ||||||
| pyasn1>=0.1.9,<0.6.0 | pyasn1>=0.1.9,<0.6.0 | ||||||
| PyDrive2>=1.3.1,<1.16.0 | PyDrive2>=1.3.1,<1.18.0 | ||||||
| PyYAML>=3.12 | PyYAML>=3.12,<6.1 | ||||||
| rsa>=3.4.2,<4.10.0 | rsa>=3.4.2,<4.10.0 | ||||||
|  |  | ||||||
| # Gmail | # Gmail | ||||||
| google-auth-oauthlib>=0.4.3,<0.9.0 | google-auth-oauthlib>=0.4.3,<1.1.0 | ||||||
| google-api-python-client>=1.7.11,<2.90.0 | google-api-python-client>=1.7.11,<2.98.0 | ||||||
|  |  | ||||||
| # goodreads | # goodreads | ||||||
| goodreads>=0.3.2,<0.4.0 | goodreads>=0.3.2,<0.4.0 | ||||||
| python-Levenshtein>=0.12.0,<0.21.0 | python-Levenshtein>=0.12.0,<0.22.0 | ||||||
|  |  | ||||||
| # ldap login | # ldap login | ||||||
| python-ldap>=3.0.0,<3.5.0 | python-ldap>=3.0.0,<3.5.0 | ||||||
| Flask-SimpleLDAP>=1.4.0,<1.5.0 | Flask-SimpleLDAP>=1.4.0,<1.5.0 | ||||||
|  |  | ||||||
| # oauth | # oauth | ||||||
| Flask-Dance>=2.0.0,<6.3.0 | Flask-Dance>=2.0.0,<7.1.0 | ||||||
| SQLAlchemy-Utils>=0.33.5,<0.40.0 | SQLAlchemy-Utils>=0.33.5,<0.42.0 | ||||||
|  |  | ||||||
| # metadata extraction | # metadata extraction | ||||||
| rarfile>=3.2 | rarfile>=3.2 | ||||||
| @@ -33,8 +33,8 @@ scholarly>=1.2.0,<1.8 | |||||||
| markdown2>=2.0.0,<2.5.0 | markdown2>=2.0.0,<2.5.0 | ||||||
| html2text>=2020.1.16,<2022.1.1 | html2text>=2020.1.16,<2022.1.1 | ||||||
| python-dateutil>=2.1,<2.9.0 | python-dateutil>=2.1,<2.9.0 | ||||||
| beautifulsoup4>=4.0.1,<4.12.0 | beautifulsoup4>=4.0.1,<4.13.0 | ||||||
| faust-cchardet>=2.1.18 | faust-cchardet>=2.1.18,<2.1.20 | ||||||
| py7zr>=0.15.0,<0.21.0 | py7zr>=0.15.0,<0.21.0 | ||||||
|  |  | ||||||
| # Comics | # Comics | ||||||
| @@ -42,4 +42,4 @@ natsort>=2.2.0,<8.4.0 | |||||||
| comicapi>=2.2.0,<3.3.0 | comicapi>=2.2.0,<3.3.0 | ||||||
|  |  | ||||||
| # Kobo integration | # Kobo integration | ||||||
| jsonschema>=3.2.0,<4.18.0 | jsonschema>=3.2.0,<4.20.0 | ||||||
|   | |||||||
| @@ -1,20 +1,20 @@ | |||||||
| Werkzeug<3.0.0 | Werkzeug<3.0.0 | ||||||
| APScheduler>=3.6.3,<3.11.0 | APScheduler>=3.6.3,<3.11.0 | ||||||
| Babel>=1.3,<3.0 | Babel>=1.3,<3.0 | ||||||
| Flask-Babel>=0.11.1,<3.1.0 | Flask-Babel>=0.11.1,<3.2.0 | ||||||
| Flask-Login>=0.3.2,<0.6.3 | Flask-Login>=0.3.2,<0.6.3 | ||||||
| Flask-Principal>=0.3.2,<0.5.1 | Flask-Principal>=0.3.2,<0.5.1 | ||||||
| Flask>=1.0.2,<2.4.0 | Flask>=1.0.2,<2.4.0 | ||||||
| iso-639>=0.4.5,<0.5.0 | iso-639>=0.4.5,<0.5.0 | ||||||
| PyPDF>=3.0.0,<3.8.0 | PyPDF>=3.0.0,<3.16.0 | ||||||
| pytz>=2016.10 | pytz>=2016.10 | ||||||
| requests>=2.11.1,<2.29.0 | requests>=2.28.0,<2.32.0 | ||||||
| SQLAlchemy>=1.3.0,<2.0.0 | SQLAlchemy>=1.3.0,<2.0.0 | ||||||
| tornado>=4.1,<6.3 | tornado>=6.3,<6.4 | ||||||
| Wand>=0.4.4,<0.7.0 | Wand>=0.4.4,<0.7.0 | ||||||
| unidecode>=0.04.19,<1.4.0 | unidecode>=0.04.19,<1.4.0 | ||||||
| lxml>=3.8.0,<5.0.0 | lxml>=3.8.0,<5.0.0 | ||||||
| flask-wtf>=0.14.2,<1.2.0 | flask-wtf>=0.14.2,<1.2.0 | ||||||
| chardet>=3.0.0,<4.1.0 | chardet>=3.0.0,<4.1.0 | ||||||
| advocate>=1.0.0,<1.1.0 | advocate>=1.0.0,<1.1.0 | ||||||
| Flask-Limiter>=2.3.0,<3.4.0 | Flask-Limiter>=2.3.0,<3.5.0 | ||||||
|   | |||||||
							
								
								
									
										35
									
								
								setup.cfg
									
									
									
									
									
								
							
							
						
						
									
										35
									
								
								setup.cfg
									
									
									
									
									
								
							| @@ -38,64 +38,65 @@ console_scripts = | |||||||
| [options] | [options] | ||||||
| include_package_data = True | include_package_data = True | ||||||
| install_requires =  | install_requires =  | ||||||
|  | 	Werkzeug<3.0.0 | ||||||
| 	APScheduler>=3.6.3,<3.11.0 | 	APScheduler>=3.6.3,<3.11.0 | ||||||
| 	Babel>=1.3,<3.0 | 	Babel>=1.3,<3.0 | ||||||
| 	Flask-Babel>=0.11.1,<3.1.0 | 	Flask-Babel>=0.11.1,<3.2.0 | ||||||
| 	Flask-Login>=0.3.2,<0.6.3 | 	Flask-Login>=0.3.2,<0.6.3 | ||||||
| 	Flask-Principal>=0.3.2,<0.5.1 | 	Flask-Principal>=0.3.2,<0.5.1 | ||||||
| 	Flask>=1.0.2,<2.4.0 | 	Flask>=1.0.2,<2.4.0 | ||||||
| 	iso-639>=0.4.5,<0.5.0 | 	iso-639>=0.4.5,<0.5.0 | ||||||
| 	PyPDF>=3.0.0,<3.8.0 | 	PyPDF>=3.0.0,<3.16.0 | ||||||
| 	pytz>=2016.10 | 	pytz>=2016.10 | ||||||
| 	requests>=2.11.1,<2.29.0 | 	requests>=2.28.0,<2.32.0 | ||||||
| 	SQLAlchemy>=1.3.0,<2.0.0 | 	SQLAlchemy>=1.3.0,<2.0.0 | ||||||
| 	tornado>=4.1,<6.3 | 	tornado>=6.3,<6.4 | ||||||
| 	Wand>=0.4.4,<0.7.0 | 	Wand>=0.4.4,<0.7.0 | ||||||
| 	unidecode>=0.04.19,<1.4.0 | 	unidecode>=0.04.19,<1.4.0 | ||||||
| 	lxml>=3.8.0,<5.0.0 | 	lxml>=3.8.0,<5.0.0 | ||||||
| 	flask-wtf>=0.14.2,<1.2.0 | 	flask-wtf>=0.14.2,<1.2.0 | ||||||
| 	chardet>=3.0.0,<4.1.0 | 	chardet>=3.0.0,<4.1.0 | ||||||
| 	advocate>=1.0.0,<1.1.0 | 	advocate>=1.0.0,<1.1.0 | ||||||
| 	Flask-Limiter>=2.3.0,<3.4.0 | 	Flask-Limiter>=2.3.0,<3.5.0 | ||||||
| 	 | 	 | ||||||
|  |  | ||||||
| [options.extras_require] | [options.extras_require] | ||||||
| gdrive =  | gdrive =  | ||||||
| 	google-api-python-client>=1.7.11,<2.90.0 | 	google-api-python-client>=1.7.11,<2.98.0 | ||||||
| 	gevent>20.6.0,<23.0.0 | 	gevent>20.6.0,<24.0.0 | ||||||
| 	greenlet>=0.4.17,<2.1.0 | 	greenlet>=0.4.17,<2.1.0 | ||||||
| 	httplib2>=0.9.2,<0.23.0 | 	httplib2>=0.9.2,<0.23.0 | ||||||
| 	oauth2client>=4.0.0,<4.1.4 | 	oauth2client>=4.0.0,<4.1.4 | ||||||
| 	uritemplate>=3.0.0,<4.2.0 | 	uritemplate>=3.0.0,<4.2.0 | ||||||
| 	pyasn1-modules>=0.0.8,<0.4.0 | 	pyasn1-modules>=0.0.8,<0.4.0 | ||||||
| 	pyasn1>=0.1.9,<0.6.0 | 	pyasn1>=0.1.9,<0.6.0 | ||||||
| 	PyDrive2>=1.3.1,<1.16.0 | 	PyDrive2>=1.3.1,<1.18.0 | ||||||
| 	PyYAML>=3.12 | 	PyYAML>=3.12,<6.1 | ||||||
| 	rsa>=3.4.2,<4.10.0 | 	rsa>=3.4.2,<4.10.0 | ||||||
| gmail =  | gmail =  | ||||||
| 	google-auth-oauthlib>=0.4.3,<0.9.0 | 	google-auth-oauthlib>=0.4.3,<1.1.0 | ||||||
| 	google-api-python-client>=1.7.11,<2.90.0 | 	google-api-python-client>=1.7.11,<2.98.0 | ||||||
| goodreads =  | goodreads =  | ||||||
| 	goodreads>=0.3.2,<0.4.0 | 	goodreads>=0.3.2,<0.4.0 | ||||||
| 	python-Levenshtein>=0.12.0,<0.21.0 | 	python-Levenshtein>=0.12.0,<0.22.0 | ||||||
| ldap =  | ldap =  | ||||||
| 	python-ldap>=3.0.0,<3.5.0 | 	python-ldap>=3.0.0,<3.5.0 | ||||||
| 	Flask-SimpleLDAP>=1.4.0,<1.5.0 | 	Flask-SimpleLDAP>=1.4.0,<1.5.0 | ||||||
| oauth =  | oauth =  | ||||||
| 	Flask-Dance>=2.0.0,<6.3.0 | 	Flask-Dance>=2.0.0,<7.1.0 | ||||||
| 	SQLAlchemy-Utils>=0.33.5,<0.40.0 | 	SQLAlchemy-Utils>=0.33.5,<0.42.0 | ||||||
| metadata =  | metadata =  | ||||||
| 	rarfile>=3.2 | 	rarfile>=3.2 | ||||||
| 	scholarly>=1.2.0,<1.8 | 	scholarly>=1.2.0,<1.8 | ||||||
| 	markdown2>=2.0.0,<2.5.0 | 	markdown2>=2.0.0,<2.5.0 | ||||||
| 	html2text>=2020.1.16,<2022.1.1 | 	html2text>=2020.1.16,<2022.1.1 | ||||||
| 	python-dateutil>=2.1,<2.9.0 | 	python-dateutil>=2.1,<2.9.0 | ||||||
| 	beautifulsoup4>=4.0.1,<4.12.0 | 	beautifulsoup4>=4.0.1,<4.13.0 | ||||||
| 	faust-cchardet>=2.1.18 | 	faust-cchardet>=2.1.18,<2.1.20 | ||||||
| 	py7zr>=0.15.0,<0.21.0 | 	py7zr>=0.15.0,<0.21.0 | ||||||
| comics =  | comics =  | ||||||
| 	natsort>=2.2.0,<8.4.0 | 	natsort>=2.2.0,<8.4.0 | ||||||
| 	comicapi>=2.2.0,<3.3.0 | 	comicapi>=2.2.0,<3.3.0 | ||||||
| kobo =  | kobo =  | ||||||
| 	jsonschema>=3.2.0,<4.18.0 | 	jsonschema>=3.2.0,<4.20.0 | ||||||
|  |  | ||||||
|   | |||||||
| @@ -37,20 +37,20 @@ | |||||||
|       <div class="row"> |       <div class="row"> | ||||||
|         <div class="col-xs-6 col-md-6 col-sm-offset-3" style="margin-top:50px;"> |         <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>2023-08-23 21:16:31</p> |             <p class='text-justify attribute'><strong>Start Time: </strong>2023-10-11 19:32:23</p> | ||||||
|              |              | ||||||
|         </div> |         </div> | ||||||
|       </div> |       </div> | ||||||
|       <div class="row"> |       <div class="row"> | ||||||
|         <div class="col-xs-6 col-md-6 col-sm-offset-3"> |         <div class="col-xs-6 col-md-6 col-sm-offset-3"> | ||||||
|              |              | ||||||
|             <p class='text-justify attribute'><strong>Stop Time: </strong>2023-08-24 03:51:45</p> |             <p class='text-justify attribute'><strong>Stop Time: </strong>2023-10-12 01:29:49</p> | ||||||
|              |              | ||||||
|         </div> |         </div> | ||||||
|       </div> |       </div> | ||||||
|       <div class="row"> |       <div class="row"> | ||||||
|         <div class="col-xs-6 col-md-6 col-sm-offset-3"> |         <div class="col-xs-6 col-md-6 col-sm-offset-3"> | ||||||
|            <p class='text-justify attribute'><strong>Duration: </strong>5h 34 min</p> |            <p class='text-justify attribute'><strong>Duration: </strong>4h 56 min</p> | ||||||
|         </div> |         </div> | ||||||
|       </div> |       </div> | ||||||
|       </div> |       </div> | ||||||
| @@ -234,11 +234,11 @@ | |||||||
|      |      | ||||||
|  |  | ||||||
|  |  | ||||||
|     <tr id="su" class="passClass"> |     <tr id="su" class="failClass"> | ||||||
|         <td>TestBackupMetadata</td> |         <td>TestBackupMetadata</td> | ||||||
|         <td class="text-center">22</td> |         <td class="text-center">22</td> | ||||||
|         <td class="text-center">22</td> |         <td class="text-center">21</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">0</td> |         <td class="text-center">0</td> | ||||||
|         <td class="text-center"> |         <td class="text-center"> | ||||||
| @@ -248,11 +248,31 @@ | |||||||
|  |  | ||||||
|      |      | ||||||
|      |      | ||||||
|         <tr id='pt2.1' class='hiddenRow bg-success'> |         <tr id="ft2.1" class="none bg-danger"> | ||||||
|             <td> |             <td> | ||||||
|                 <div class='testcase'>TestBackupMetadata - test_backup_all</div> |                 <div class='testcase'>TestBackupMetadata - test_backup_all</div> | ||||||
|             </td> |             </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_ft2.1')">FAIL</a> | ||||||
|  |                 </div> | ||||||
|  |                 <!--css div popup start--> | ||||||
|  |                 <div id="div_ft2.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_ft2.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_backup_metadata.py", line 49, in test_backup_all | ||||||
|  |     self.assertEqual(1, len(res)) | ||||||
|  | AssertionError: 1 != 0</pre> | ||||||
|  |                     </div> | ||||||
|  |                     <div class="clearfix"></div> | ||||||
|  |                 </div> | ||||||
|  |                 <!--css div popup end--> | ||||||
|  |             </td> | ||||||
|         </tr> |         </tr> | ||||||
|      |      | ||||||
|      |      | ||||||
| @@ -322,7 +342,7 @@ | |||||||
|      |      | ||||||
|         <tr id='pt2.9' class='hiddenRow bg-success'> |         <tr id='pt2.9' class='hiddenRow bg-success'> | ||||||
|             <td> |             <td> | ||||||
|                 <div class='testcase'>TestBackupMetadata - test_backup_change_book_seriesindex</div> |                 <div class='testcase'>TestBackupMetadata - test_backup_change_book_series_index</div> | ||||||
|             </td> |             </td> | ||||||
|             <td colspan='6' align='center'>PASS</td> |             <td colspan='6' align='center'>PASS</td> | ||||||
|         </tr> |         </tr> | ||||||
| @@ -1014,12 +1034,12 @@ | |||||||
|      |      | ||||||
|  |  | ||||||
|  |  | ||||||
|     <tr id="su" class="errorClass"> |     <tr id="su" class="skipClass"> | ||||||
|         <td>TestEditAdditionalBooks</td> |         <td>TestEditAdditionalBooks</td> | ||||||
|         <td class="text-center">20</td> |         <td class="text-center">20</td> | ||||||
|         <td class="text-center">17</td> |         <td class="text-center">18</td> | ||||||
|  |         <td class="text-center">0</td> | ||||||
|         <td class="text-center">0</td> |         <td class="text-center">0</td> | ||||||
|         <td class="text-center">1</td> |  | ||||||
|         <td class="text-center">2</td> |         <td class="text-center">2</td> | ||||||
|         <td class="text-center"> |         <td class="text-center"> | ||||||
|             <a onclick="showClassDetail('c12', 20)">Detail</a> |             <a onclick="showClassDetail('c12', 20)">Detail</a> | ||||||
| @@ -1136,31 +1156,11 @@ | |||||||
|      |      | ||||||
|      |      | ||||||
|      |      | ||||||
|         <tr id="et12.13" class="none bg-info"> |         <tr id='pt12.13' class='hiddenRow bg-success'> | ||||||
|             <td> |             <td> | ||||||
|                 <div class='testcase'>TestEditAdditionalBooks - test_upload_metadata_cb7</div> |                 <div class='testcase'>TestEditAdditionalBooks - test_upload_metadata_cb7</div> | ||||||
|             </td> |             </td> | ||||||
|             <td colspan='6'> |             <td colspan='6' align='center'>PASS</td> | ||||||
|                 <div class="text-center"> |  | ||||||
|                     <a class="popup_link text-center" onfocus='blur()' onclick="showTestDetail('div_et12.13')">ERROR</a> |  | ||||||
|                 </div> |  | ||||||
|                 <!--css div popup start--> |  | ||||||
|                 <div id="div_et12.13" 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_et12.13').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_edit_additional_books.py", line 225, in test_upload_metadata_cb7 |  | ||||||
|     self.check_element_on_page((By.ID, 'edit_cancel')).click() |  | ||||||
| AttributeError: 'bool' object has no attribute 'click'</pre> |  | ||||||
|                     </div> |  | ||||||
|                     <div class="clearfix"></div> |  | ||||||
|                 </div> |  | ||||||
|                 <!--css div popup end--> |  | ||||||
|             </td> |  | ||||||
|         </tr> |         </tr> | ||||||
|      |      | ||||||
|      |      | ||||||
| @@ -1246,12 +1246,12 @@ AttributeError: 'bool' object has no attribute 'click'</pre> | |||||||
|      |      | ||||||
|  |  | ||||||
|  |  | ||||||
|     <tr id="su" class="errorClass"> |     <tr id="su" class="skipClass"> | ||||||
|         <td>TestEditBooks</td> |         <td>TestEditBooks</td> | ||||||
|         <td class="text-center">38</td> |         <td class="text-center">38</td> | ||||||
|         <td class="text-center">34</td> |         <td class="text-center">36</td> | ||||||
|  |         <td class="text-center">0</td> | ||||||
|         <td class="text-center">0</td> |         <td class="text-center">0</td> | ||||||
|         <td class="text-center">2</td> |  | ||||||
|         <td class="text-center">2</td> |         <td class="text-center">2</td> | ||||||
|         <td class="text-center"> |         <td class="text-center"> | ||||||
|             <a onclick="showClassDetail('c13', 38)">Detail</a> |             <a onclick="showClassDetail('c13', 38)">Detail</a> | ||||||
| @@ -1537,31 +1537,11 @@ AttributeError: 'bool' object has no attribute 'click'</pre> | |||||||
|      |      | ||||||
|      |      | ||||||
|      |      | ||||||
|         <tr id="et13.28" class="none bg-info"> |         <tr id='pt13.28' class='hiddenRow bg-success'> | ||||||
|             <td> |             <td> | ||||||
|                 <div class='testcase'>TestEditBooks - test_upload_book_cb7</div> |                 <div class='testcase'>TestEditBooks - test_upload_book_cb7</div> | ||||||
|             </td> |             </td> | ||||||
|             <td colspan='6'> |             <td colspan='6' align='center'>PASS</td> | ||||||
|                 <div class="text-center"> |  | ||||||
|                     <a class="popup_link text-center" onfocus='blur()' onclick="showTestDetail('div_et13.28')">ERROR</a> |  | ||||||
|                 </div> |  | ||||||
|                 <!--css div popup start--> |  | ||||||
|                 <div id="div_et13.28" 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_et13.28').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_edit_books.py", line 1159, in test_upload_book_cb7 |  | ||||||
|     self.check_element_on_page((By.ID, 'edit_cancel')).click() |  | ||||||
| AttributeError: 'bool' object has no attribute 'click'</pre> |  | ||||||
|                     </div> |  | ||||||
|                     <div class="clearfix"></div> |  | ||||||
|                 </div> |  | ||||||
|                 <!--css div popup end--> |  | ||||||
|             </td> |  | ||||||
|         </tr> |         </tr> | ||||||
|      |      | ||||||
|      |      | ||||||
| @@ -1647,31 +1627,11 @@ AttributeError: 'bool' object has no attribute 'click'</pre> | |||||||
|      |      | ||||||
|      |      | ||||||
|      |      | ||||||
|         <tr id="et13.38" class="none bg-info"> |         <tr id='pt13.38' class='hiddenRow bg-success'> | ||||||
|             <td> |             <td> | ||||||
|                 <div class='testcase'>TestEditBooks - test_upload_cover_hdd</div> |                 <div class='testcase'>TestEditBooks - test_upload_cover_hdd</div> | ||||||
|             </td> |             </td> | ||||||
|             <td colspan='6'> |             <td colspan='6' align='center'>PASS</td> | ||||||
|                 <div class="text-center"> |  | ||||||
|                     <a class="popup_link text-center" onfocus='blur()' onclick="showTestDetail('div_et13.38')">ERROR</a> |  | ||||||
|                 </div> |  | ||||||
|                 <!--css div popup start--> |  | ||||||
|                 <div id="div_et13.38" 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_et13.38').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_edit_books.py", line 866, in test_upload_cover_hdd |  | ||||||
|     self.delete_book(details['id']) |  | ||||||
| NameError: name 'details' is not defined</pre> |  | ||||||
|                     </div> |  | ||||||
|                     <div class="clearfix"></div> |  | ||||||
|                 </div> |  | ||||||
|                 <!--css div popup end--> |  | ||||||
|             </td> |  | ||||||
|         </tr> |         </tr> | ||||||
|      |      | ||||||
|      |      | ||||||
| @@ -1992,12 +1952,12 @@ NameError: name 'details' is not defined</pre> | |||||||
|      |      | ||||||
|  |  | ||||||
|  |  | ||||||
|     <tr id="su" class="failClass"> |     <tr id="su" class="errorClass"> | ||||||
|         <td>TestLoadMetadata</td> |         <td>TestLoadMetadata</td> | ||||||
|         <td class="text-center">1</td> |         <td class="text-center">1</td> | ||||||
|         <td class="text-center">0</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">1</td> | ||||||
|         <td class="text-center">0</td> |         <td class="text-center">0</td> | ||||||
|         <td class="text-center"> |         <td class="text-center"> | ||||||
|             <a onclick="showClassDetail('c17', 1)">Detail</a> |             <a onclick="showClassDetail('c17', 1)">Detail</a> | ||||||
| @@ -2006,32 +1966,26 @@ NameError: name 'details' is not defined</pre> | |||||||
|  |  | ||||||
|      |      | ||||||
|      |      | ||||||
|         <tr id="ft17.1" class="none bg-danger"> |         <tr id="et17.1" class="none bg-info"> | ||||||
|             <td> |             <td> | ||||||
|                 <div class='testcase'>TestLoadMetadata - test_load_metadata</div> |                 <div class='testcase'>TestLoadMetadata - test_load_metadata</div> | ||||||
|             </td> |             </td> | ||||||
|             <td colspan='6'> |             <td colspan='6'> | ||||||
|                 <div class="text-center"> |                 <div class="text-center"> | ||||||
|                     <a class="popup_link text-center" onfocus='blur()' onclick="showTestDetail('div_ft17.1')">FAIL</a> |                     <a class="popup_link text-center" onfocus='blur()' onclick="showTestDetail('div_et17.1')">ERROR</a> | ||||||
|                 </div> |                 </div> | ||||||
|                 <!--css div popup start--> |                 <!--css div popup start--> | ||||||
|                 <div id="div_ft17.1" class="popup_window test_output" style="display:block;"> |                 <div id="div_et17.1" class="popup_window test_output" style="display:block;"> | ||||||
|                     <div class='close_button pull-right'> |                     <div class='close_button pull-right'> | ||||||
|                         <button type="button" class="close" aria-label="Close" onfocus="this.blur();" |                         <button type="button" class="close" aria-label="Close" onfocus="this.blur();" | ||||||
|                                 onclick="document.getElementById('div_ft17.1').style.display='none'"><span |                                 onclick="document.getElementById('div_et17.1').style.display='none'"><span | ||||||
|                                 aria-hidden="true">×</span></button> |                                 aria-hidden="true">×</span></button> | ||||||
|                     </div> |                     </div> | ||||||
|                     <div class="text-left pull-left"> |                     <div class="text-left pull-left"> | ||||||
|                         <pre class="text-left">Traceback (most recent call last): |                         <pre class="text-left">Traceback (most recent call last): | ||||||
|   File "/home/ozzie/Development/calibre-web-test/test/test_edit_books_metadata.py", line 209, in test_load_metadata |   File "/home/ozzie/Development/calibre-web-test/test/test_edit_books_metadata.py", line 84, in test_load_metadata | ||||||
|     self.assertEqual(old_results, results) |     elif 'https://amazon.com/' == results[20]['source']: | ||||||
| AssertionError: Lists differ: [] != [{'cover_element': <selenium.webdriver.rem[10121 chars]4/'}] | IndexError: list index out of range</pre> | ||||||
|  |  | ||||||
| Second list contains 20 additional elements. |  | ||||||
| First extra element 0: |  | ||||||
| {'cover_element': <selenium.webdriver.remote.webelement.WebElement (session="34034d2d-f804-47c1-b9ad-fcf09f75f812", element="6dfe81e2-4752-4f1f-bd33-9388d0d529c1")>, 'cover': 'https://books.google.com/books/content?id=Ub8TAQAAIAAJ&printsec=frontcover&img=1&zoom=1&source=gbs_api&fife=w800-h900', 'source': 'https://books.google.com/', 'author': 'Martin Vogt', 'publisher': '', 'title': 'Der Buchtitel in der römischen Poesie', 'title_link': 'https://books.google.com/books?id=Ub8TAQAAIAAJ'} |  | ||||||
|  |  | ||||||
| Diff is 10795 characters long. Set self.maxDiff to None to see it.</pre> |  | ||||||
|                     </div> |                     </div> | ||||||
|                     <div class="clearfix"></div> |                     <div class="clearfix"></div> | ||||||
|                 </div> |                 </div> | ||||||
| @@ -3374,13 +3328,13 @@ Diff is 10795 characters long. Set self.maxDiff to None to see it.</pre> | |||||||
|  |  | ||||||
|     <tr id="su" class="passClass"> |     <tr id="su" class="passClass"> | ||||||
|         <td>TestOPDSFeed</td> |         <td>TestOPDSFeed</td> | ||||||
|         <td class="text-center">23</td> |         <td class="text-center">24</td> | ||||||
|         <td class="text-center">23</td> |         <td class="text-center">24</td> | ||||||
|         <td class="text-center">0</td> |         <td class="text-center">0</td> | ||||||
|         <td class="text-center">0</td> |         <td class="text-center">0</td> | ||||||
|         <td class="text-center">0</td> |         <td class="text-center">0</td> | ||||||
|         <td class="text-center"> |         <td class="text-center"> | ||||||
|             <a onclick="showClassDetail('c36', 23)">Detail</a> |             <a onclick="showClassDetail('c36', 24)">Detail</a> | ||||||
|         </td> |         </td> | ||||||
|     </tr> |     </tr> | ||||||
|  |  | ||||||
| @@ -3559,7 +3513,7 @@ Diff is 10795 characters long. Set self.maxDiff to None to see it.</pre> | |||||||
|      |      | ||||||
|         <tr id='pt36.20' class='hiddenRow bg-success'> |         <tr id='pt36.20' class='hiddenRow bg-success'> | ||||||
|             <td> |             <td> | ||||||
|                 <div class='testcase'>TestOPDSFeed - test_opds_tags</div> |                 <div class='testcase'>TestOPDSFeed - test_opds_stats</div> | ||||||
|             </td> |             </td> | ||||||
|             <td colspan='6' align='center'>PASS</td> |             <td colspan='6' align='center'>PASS</td> | ||||||
|         </tr> |         </tr> | ||||||
| @@ -3568,7 +3522,7 @@ Diff is 10795 characters long. Set self.maxDiff to None to see it.</pre> | |||||||
|      |      | ||||||
|         <tr id='pt36.21' class='hiddenRow bg-success'> |         <tr id='pt36.21' class='hiddenRow bg-success'> | ||||||
|             <td> |             <td> | ||||||
|                 <div class='testcase'>TestOPDSFeed - test_opds_top_rated</div> |                 <div class='testcase'>TestOPDSFeed - test_opds_tags</div> | ||||||
|             </td> |             </td> | ||||||
|             <td colspan='6' align='center'>PASS</td> |             <td colspan='6' align='center'>PASS</td> | ||||||
|         </tr> |         </tr> | ||||||
| @@ -3577,7 +3531,7 @@ Diff is 10795 characters long. Set self.maxDiff to None to see it.</pre> | |||||||
|      |      | ||||||
|         <tr id='pt36.22' class='hiddenRow bg-success'> |         <tr id='pt36.22' class='hiddenRow bg-success'> | ||||||
|             <td> |             <td> | ||||||
|                 <div class='testcase'>TestOPDSFeed - test_opds_unicode_user</div> |                 <div class='testcase'>TestOPDSFeed - test_opds_top_rated</div> | ||||||
|             </td> |             </td> | ||||||
|             <td colspan='6' align='center'>PASS</td> |             <td colspan='6' align='center'>PASS</td> | ||||||
|         </tr> |         </tr> | ||||||
| @@ -3585,6 +3539,15 @@ Diff is 10795 characters long. Set self.maxDiff to None to see it.</pre> | |||||||
|      |      | ||||||
|      |      | ||||||
|         <tr id='pt36.23' class='hiddenRow bg-success'> |         <tr id='pt36.23' class='hiddenRow bg-success'> | ||||||
|  |             <td> | ||||||
|  |                 <div class='testcase'>TestOPDSFeed - test_opds_unicode_user</div> | ||||||
|  |             </td> | ||||||
|  |             <td colspan='6' align='center'>PASS</td> | ||||||
|  |         </tr> | ||||||
|  |      | ||||||
|  |      | ||||||
|  |      | ||||||
|  |         <tr id='pt36.24' class='hiddenRow bg-success'> | ||||||
|             <td> |             <td> | ||||||
|                 <div class='testcase'>TestOPDSFeed - test_recently_added</div> |                 <div class='testcase'>TestOPDSFeed - test_recently_added</div> | ||||||
|             </td> |             </td> | ||||||
| @@ -4082,11 +4045,11 @@ Diff is 10795 characters long. Set self.maxDiff to None to see it.</pre> | |||||||
|      |      | ||||||
|  |  | ||||||
|  |  | ||||||
|     <tr id="su" class="skipClass"> |     <tr id="su" class="failClass"> | ||||||
|         <td>TestThumbnails</td> |         <td>TestThumbnails</td> | ||||||
|         <td class="text-center">8</td> |         <td class="text-center">8</td> | ||||||
|         <td class="text-center">7</td> |         <td class="text-center">6</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">1</td> |         <td class="text-center">1</td> | ||||||
|         <td class="text-center"> |         <td class="text-center"> | ||||||
| @@ -4159,11 +4122,31 @@ Diff is 10795 characters long. Set self.maxDiff to None to see it.</pre> | |||||||
|      |      | ||||||
|      |      | ||||||
|      |      | ||||||
|         <tr id='pt45.8' class='hiddenRow bg-success'> |         <tr id="ft45.8" class="none bg-danger"> | ||||||
|             <td> |             <td> | ||||||
|                 <div class='testcase'>TestThumbnails - test_sideloaded_book</div> |                 <div class='testcase'>TestThumbnails - test_sideloaded_book</div> | ||||||
|             </td> |             </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_ft45.8')">FAIL</a> | ||||||
|  |                 </div> | ||||||
|  |                 <!--css div popup start--> | ||||||
|  |                 <div id="div_ft45.8" 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_ft45.8').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 311, in test_sideloaded_book | ||||||
|  |     self.assertAlmostEqual(diff(BytesIO(list_cover), BytesIO(old_list_cover), delete_diff_file=True), 0.0, | ||||||
|  | AssertionError: 0.004399004046062869 != 0.0 within 0.0001 delta (0.004399004046062869 difference)</pre> | ||||||
|  |                     </div> | ||||||
|  |                     <div class="clearfix"></div> | ||||||
|  |                 </div> | ||||||
|  |                 <!--css div popup end--> | ||||||
|  |             </td> | ||||||
|         </tr> |         </tr> | ||||||
|      |      | ||||||
|      |      | ||||||
| @@ -5237,10 +5220,10 @@ Diff is 10795 characters long. Set self.maxDiff to None to see it.</pre> | |||||||
|  |  | ||||||
|     <tr id='total_row' class="text-center bg-grey"> |     <tr id='total_row' class="text-center bg-grey"> | ||||||
|         <td>Total</td> |         <td>Total</td> | ||||||
|         <td>461</td> |         <td>462</td> | ||||||
|         <td>448</td> |         <td>450</td> | ||||||
|  |         <td>2</td> | ||||||
|         <td>1</td> |         <td>1</td> | ||||||
|         <td>3</td> |  | ||||||
|         <td>9</td> |         <td>9</td> | ||||||
|         <td> </td> |         <td> </td> | ||||||
|     </tr> |     </tr> | ||||||
| @@ -5269,7 +5252,7 @@ Diff is 10795 characters long. Set self.maxDiff to None to see it.</pre> | |||||||
|            |            | ||||||
|             <tr> |             <tr> | ||||||
|               <th>Platform</th> |               <th>Platform</th> | ||||||
|               <td>Linux 6.2.0-26-generic #26~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Thu Jul 13 16:27:29 UTC 2 x86_64 x86_64</td> |               <td>Linux 6.2.0-34-generic #34~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Thu Sep  7 13:12:03 UTC 2 x86_64 x86_64</td> | ||||||
|               <td>Basic</td> |               <td>Basic</td> | ||||||
|             </tr> |             </tr> | ||||||
|            |            | ||||||
| @@ -5293,7 +5276,7 @@ Diff is 10795 characters long. Set self.maxDiff to None to see it.</pre> | |||||||
|            |            | ||||||
|             <tr> |             <tr> | ||||||
|               <th>Babel</th> |               <th>Babel</th> | ||||||
|               <td>2.12.1</td> |               <td>2.13.0</td> | ||||||
|               <td>Basic</td> |               <td>Basic</td> | ||||||
|             </tr> |             </tr> | ||||||
|            |            | ||||||
| @@ -5311,13 +5294,13 @@ Diff is 10795 characters long. Set self.maxDiff to None to see it.</pre> | |||||||
|            |            | ||||||
|             <tr> |             <tr> | ||||||
|               <th>flask-babel</th> |               <th>flask-babel</th> | ||||||
|               <td>3.0.1</td> |               <td>3.1.0</td> | ||||||
|               <td>Basic</td> |               <td>Basic</td> | ||||||
|             </tr> |             </tr> | ||||||
|            |            | ||||||
|             <tr> |             <tr> | ||||||
|               <th>Flask-Limiter</th> |               <th>Flask-Limiter</th> | ||||||
|               <td>3.3.1</td> |               <td>3.4.1</td> | ||||||
|               <td>Basic</td> |               <td>Basic</td> | ||||||
|             </tr> |             </tr> | ||||||
|            |            | ||||||
| @@ -5335,13 +5318,13 @@ Diff is 10795 characters long. Set self.maxDiff to None to see it.</pre> | |||||||
|            |            | ||||||
|             <tr> |             <tr> | ||||||
|               <th>Flask-WTF</th> |               <th>Flask-WTF</th> | ||||||
|               <td>1.1.1</td> |               <td>1.1.2</td> | ||||||
|               <td>Basic</td> |               <td>Basic</td> | ||||||
|             </tr> |             </tr> | ||||||
|            |            | ||||||
|             <tr> |             <tr> | ||||||
|               <th>greenlet</th> |               <th>greenlet</th> | ||||||
|               <td>2.0.2</td> |               <td>3.0.0</td> | ||||||
|               <td>Basic</td> |               <td>Basic</td> | ||||||
|             </tr> |             </tr> | ||||||
|            |            | ||||||
| @@ -5371,19 +5354,19 @@ Diff is 10795 characters long. Set self.maxDiff to None to see it.</pre> | |||||||
|            |            | ||||||
|             <tr> |             <tr> | ||||||
|               <th>pypdf</th> |               <th>pypdf</th> | ||||||
|               <td>3.7.1</td> |               <td>3.15.5</td> | ||||||
|               <td>Basic</td> |               <td>Basic</td> | ||||||
|             </tr> |             </tr> | ||||||
|            |            | ||||||
|             <tr> |             <tr> | ||||||
|               <th>pytz</th> |               <th>pytz</th> | ||||||
|               <td>2022.7.1</td> |               <td>2023.3.post1</td> | ||||||
|               <td>Basic</td> |               <td>Basic</td> | ||||||
|             </tr> |             </tr> | ||||||
|            |            | ||||||
|             <tr> |             <tr> | ||||||
|               <th>requests</th> |               <th>requests</th> | ||||||
|               <td>2.28.2</td> |               <td>2.31.0</td> | ||||||
|               <td>Basic</td> |               <td>Basic</td> | ||||||
|             </tr> |             </tr> | ||||||
|            |            | ||||||
| @@ -5395,13 +5378,13 @@ Diff is 10795 characters long. Set self.maxDiff to None to see it.</pre> | |||||||
|            |            | ||||||
|             <tr> |             <tr> | ||||||
|               <th>tornado</th> |               <th>tornado</th> | ||||||
|               <td>6.2</td> |               <td>6.3.3</td> | ||||||
|               <td>Basic</td> |               <td>Basic</td> | ||||||
|             </tr> |             </tr> | ||||||
|            |            | ||||||
|             <tr> |             <tr> | ||||||
|               <th>Unidecode</th> |               <th>Unidecode</th> | ||||||
|               <td>1.3.6</td> |               <td>1.3.7</td> | ||||||
|               <td>Basic</td> |               <td>Basic</td> | ||||||
|             </tr> |             </tr> | ||||||
|            |            | ||||||
| @@ -5419,7 +5402,7 @@ Diff is 10795 characters long. Set self.maxDiff to None to see it.</pre> | |||||||
|            |            | ||||||
|             <tr> |             <tr> | ||||||
|               <th>google-api-python-client</th> |               <th>google-api-python-client</th> | ||||||
|               <td>2.97.0</td> |               <td>2.103.0</td> | ||||||
|               <td>TestBackupMetadataGdrive</td> |               <td>TestBackupMetadataGdrive</td> | ||||||
|             </tr> |             </tr> | ||||||
|            |            | ||||||
| @@ -5449,7 +5432,7 @@ Diff is 10795 characters long. Set self.maxDiff to None to see it.</pre> | |||||||
|            |            | ||||||
|             <tr> |             <tr> | ||||||
|               <th>google-api-python-client</th> |               <th>google-api-python-client</th> | ||||||
|               <td>2.97.0</td> |               <td>2.103.0</td> | ||||||
|               <td>TestCliGdrivedb</td> |               <td>TestCliGdrivedb</td> | ||||||
|             </tr> |             </tr> | ||||||
|            |            | ||||||
| @@ -5479,7 +5462,7 @@ Diff is 10795 characters long. Set self.maxDiff to None to see it.</pre> | |||||||
|            |            | ||||||
|             <tr> |             <tr> | ||||||
|               <th>google-api-python-client</th> |               <th>google-api-python-client</th> | ||||||
|               <td>2.97.0</td> |               <td>2.103.0</td> | ||||||
|               <td>TestEbookConvertCalibreGDrive</td> |               <td>TestEbookConvertCalibreGDrive</td> | ||||||
|             </tr> |             </tr> | ||||||
|            |            | ||||||
| @@ -5509,7 +5492,7 @@ Diff is 10795 characters long. Set self.maxDiff to None to see it.</pre> | |||||||
|            |            | ||||||
|             <tr> |             <tr> | ||||||
|               <th>google-api-python-client</th> |               <th>google-api-python-client</th> | ||||||
|               <td>2.97.0</td> |               <td>2.103.0</td> | ||||||
|               <td>TestEbookConvertGDriveKepubify</td> |               <td>TestEbookConvertGDriveKepubify</td> | ||||||
|             </tr> |             </tr> | ||||||
|            |            | ||||||
| @@ -5551,7 +5534,7 @@ Diff is 10795 characters long. Set self.maxDiff to None to see it.</pre> | |||||||
|            |            | ||||||
|             <tr> |             <tr> | ||||||
|               <th>rarfile</th> |               <th>rarfile</th> | ||||||
|               <td>4.0</td> |               <td>4.1</td> | ||||||
|               <td>TestEditAdditionalBooks</td> |               <td>TestEditAdditionalBooks</td> | ||||||
|             </tr> |             </tr> | ||||||
|            |            | ||||||
| @@ -5563,7 +5546,7 @@ Diff is 10795 characters long. Set self.maxDiff to None to see it.</pre> | |||||||
|            |            | ||||||
|             <tr> |             <tr> | ||||||
|               <th>google-api-python-client</th> |               <th>google-api-python-client</th> | ||||||
|               <td>2.97.0</td> |               <td>2.103.0</td> | ||||||
|               <td>TestEditAuthorsGdrive</td> |               <td>TestEditAuthorsGdrive</td> | ||||||
|             </tr> |             </tr> | ||||||
|            |            | ||||||
| @@ -5599,7 +5582,7 @@ Diff is 10795 characters long. Set self.maxDiff to None to see it.</pre> | |||||||
|            |            | ||||||
|             <tr> |             <tr> | ||||||
|               <th>google-api-python-client</th> |               <th>google-api-python-client</th> | ||||||
|               <td>2.97.0</td> |               <td>2.103.0</td> | ||||||
|               <td>TestEditBooksOnGdrive</td> |               <td>TestEditBooksOnGdrive</td> | ||||||
|             </tr> |             </tr> | ||||||
|            |            | ||||||
| @@ -5641,7 +5624,7 @@ Diff is 10795 characters long. Set self.maxDiff to None to see it.</pre> | |||||||
|            |            | ||||||
|             <tr> |             <tr> | ||||||
|               <th>google-api-python-client</th> |               <th>google-api-python-client</th> | ||||||
|               <td>2.97.0</td> |               <td>2.103.0</td> | ||||||
|               <td>TestSetupGdrive</td> |               <td>TestSetupGdrive</td> | ||||||
|             </tr> |             </tr> | ||||||
|            |            | ||||||
| @@ -5677,19 +5660,19 @@ Diff is 10795 characters long. Set self.maxDiff to None to see it.</pre> | |||||||
|            |            | ||||||
|             <tr> |             <tr> | ||||||
|               <th>python-Levenshtein</th> |               <th>python-Levenshtein</th> | ||||||
|               <td>0.21.1</td> |               <td>0.23.0</td> | ||||||
|               <td>TestGoodreads</td> |               <td>TestGoodreads</td> | ||||||
|             </tr> |             </tr> | ||||||
|            |            | ||||||
|             <tr> |             <tr> | ||||||
|               <th>jsonschema</th> |               <th>jsonschema</th> | ||||||
|               <td>4.19.0</td> |               <td>4.19.1</td> | ||||||
|               <td>TestKoboSync</td> |               <td>TestKoboSync</td> | ||||||
|             </tr> |             </tr> | ||||||
|            |            | ||||||
|             <tr> |             <tr> | ||||||
|               <th>jsonschema</th> |               <th>jsonschema</th> | ||||||
|               <td>4.19.0</td> |               <td>4.19.1</td> | ||||||
|               <td>TestKoboSyncBig</td> |               <td>TestKoboSyncBig</td> | ||||||
|             </tr> |             </tr> | ||||||
|            |            | ||||||
| @@ -5701,7 +5684,7 @@ Diff is 10795 characters long. Set self.maxDiff to None to see it.</pre> | |||||||
|            |            | ||||||
|             <tr> |             <tr> | ||||||
|               <th>jsonschema</th> |               <th>jsonschema</th> | ||||||
|               <td>4.19.0</td> |               <td>4.19.1</td> | ||||||
|               <td>TestLdapLogin</td> |               <td>TestLdapLogin</td> | ||||||
|             </tr> |             </tr> | ||||||
|            |            | ||||||
| @@ -5731,7 +5714,7 @@ Diff is 10795 characters long. Set self.maxDiff to None to see it.</pre> | |||||||
| </div> | </div> | ||||||
|  |  | ||||||
| <script> | <script> | ||||||
|     drawCircle(448, 1, 3, 9); |     drawCircle(450, 2, 1, 9); | ||||||
|     showCase(5); |     showCase(5); | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Ozzie Isaacs
					Ozzie Isaacs