mirror of
				https://github.com/janeczku/calibre-web
				synced 2025-10-31 15:23:02 +00:00 
			
		
		
		
	Make datetime utcnow compatible to older python versions
This commit is contained in:
		| @@ -1,4 +1,5 @@ | ||||
| from datetime import datetime, UTC | ||||
| from datetime import datetime | ||||
| from datetime import timezone | ||||
| from datetime import timedelta | ||||
| import hashlib | ||||
|  | ||||
| @@ -496,7 +497,7 @@ class LoginManager: | ||||
|             duration = timedelta(seconds=duration) | ||||
|  | ||||
|         try: | ||||
|             expires = datetime.now(UTC) + duration | ||||
|             expires = datetime.now(timezone.utc) + duration | ||||
|         except TypeError as e: | ||||
|             raise Exception( | ||||
|                 "REMEMBER_COOKIE_DURATION must be a datetime.timedelta," | ||||
|   | ||||
| @@ -20,7 +20,7 @@ | ||||
| import os | ||||
| import re | ||||
| import json | ||||
| from datetime import datetime | ||||
| from datetime import datetime, timezone | ||||
| from urllib.parse import quote | ||||
| import unidecode | ||||
| from weakref import WeakSet | ||||
| @@ -378,10 +378,10 @@ class Books(Base): | ||||
|     title = Column(String(collation='NOCASE'), nullable=False, default='Unknown') | ||||
|     sort = Column(String(collation='NOCASE')) | ||||
|     author_sort = Column(String(collation='NOCASE')) | ||||
|     timestamp = Column(TIMESTAMP, default=datetime.utcnow) | ||||
|     timestamp = Column(TIMESTAMP, default=lambda: datetime.now(timezone.utc)) | ||||
|     pubdate = Column(TIMESTAMP, default=DEFAULT_PUBDATE) | ||||
|     series_index = Column(String, nullable=False, default="1.0") | ||||
|     last_modified = Column(TIMESTAMP, default=datetime.utcnow) | ||||
|     last_modified = Column(TIMESTAMP, default=lambda: datetime.now(timezone.utc)) | ||||
|     path = Column(String, default="", nullable=False) | ||||
|     has_cover = Column(Integer, default=0) | ||||
|     uuid = Column(String) | ||||
|   | ||||
| @@ -21,7 +21,7 @@ | ||||
| #  along with this program. If not, see <http://www.gnu.org/licenses/>. | ||||
|  | ||||
| import os | ||||
| from datetime import datetime, UTC | ||||
| from datetime import datetime, timezone | ||||
| import json | ||||
| from shutil import copyfile | ||||
| from uuid import uuid4 | ||||
| @@ -200,7 +200,7 @@ def edit_book(book_id): | ||||
|             book.pubdate = db.Books.DEFAULT_PUBDATE | ||||
|  | ||||
|         if modify_date: | ||||
|             book.last_modified = datetime.now(UTC) | ||||
|             book.last_modified = datetime.now(timezone.utc) | ||||
|             kobo_sync_status.remove_synced_book(edited_books_id, all=True) | ||||
|             calibre_db.set_metadata_dirty(book.id) | ||||
|  | ||||
| @@ -444,7 +444,7 @@ def edit_list_book(param): | ||||
|                                mimetype='application/json') | ||||
|         else: | ||||
|             return _("Parameter not found"), 400 | ||||
|         book.last_modified = datetime.now(UTC) | ||||
|         book.last_modified = datetime.now(timezone.utc) | ||||
|  | ||||
|         calibre_db.session.commit() | ||||
|         # revert change for sort if automatic fields link is deactivated | ||||
| @@ -560,7 +560,7 @@ def table_xchange_author_title(): | ||||
|                 # toDo: Handle error | ||||
|                 edit_error = helper.update_dir_structure(edited_books_id, config.get_book_path(), input_authors[0]) | ||||
|             if modify_date: | ||||
|                 book.last_modified = datetime.now(UTC) | ||||
|                 book.last_modified = datetime.now(timezone.utc) | ||||
|                 calibre_db.set_metadata_dirty(book.id) | ||||
|             try: | ||||
|                 calibre_db.session.commit() | ||||
| @@ -711,8 +711,8 @@ def create_book_on_upload(modify_date, meta): | ||||
|         pubdate = datetime(101, 1, 1) | ||||
|  | ||||
|     # Calibre adds books with utc as timezone | ||||
|     db_book = db.Books(title, "", sort_authors, datetime.now(UTC), pubdate, | ||||
|                        '1', datetime.now(UTC), path, meta.cover, db_author, [], "") | ||||
|     db_book = db.Books(title, "", sort_authors, datetime.now(timezone.utc), pubdate, | ||||
|                        '1', datetime.now(timezone.utc), path, meta.cover, db_author, [], "") | ||||
|  | ||||
|     modify_date |= modify_database_object(input_authors, db_book.authors, db.Authors, calibre_db.session, | ||||
|                                           'author') | ||||
|   | ||||
| @@ -25,7 +25,7 @@ import re | ||||
| import regex | ||||
| import shutil | ||||
| import socket | ||||
| from datetime import datetime, timedelta, UTC | ||||
| from datetime import datetime, timedelta, timezone | ||||
| import requests | ||||
| import unidecode | ||||
| from uuid import uuid4 | ||||
| @@ -793,7 +793,7 @@ def get_book_cover_thumbnail(book, resolution): | ||||
|                 .filter(ub.Thumbnail.type == THUMBNAIL_TYPE_COVER) | ||||
|                 .filter(ub.Thumbnail.entity_id == book.id) | ||||
|                 .filter(ub.Thumbnail.resolution == resolution) | ||||
|                 .filter(or_(ub.Thumbnail.expiration.is_(None), ub.Thumbnail.expiration > datetime.now(UTC))) | ||||
|                 .filter(or_(ub.Thumbnail.expiration.is_(None), ub.Thumbnail.expiration > datetime.now(timezone.utc))) | ||||
|                 .first()) | ||||
|  | ||||
|  | ||||
| @@ -831,7 +831,7 @@ def get_series_thumbnail(series_id, resolution): | ||||
|         .filter(ub.Thumbnail.type == THUMBNAIL_TYPE_SERIES) | ||||
|         .filter(ub.Thumbnail.entity_id == series_id) | ||||
|         .filter(ub.Thumbnail.resolution == resolution) | ||||
|         .filter(or_(ub.Thumbnail.expiration.is_(None), ub.Thumbnail.expiration > datetime.now(UTC))) | ||||
|         .filter(or_(ub.Thumbnail.expiration.is_(None), ub.Thumbnail.expiration > datetime.now(timezone.utc))) | ||||
|         .first()) | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -18,7 +18,7 @@ | ||||
| #  along with this program. If not, see <http://www.gnu.org/licenses/>. | ||||
|  | ||||
| import base64 | ||||
| from datetime import datetime, UTC | ||||
| from datetime import datetime, timezone | ||||
| import os | ||||
| import uuid | ||||
| import zipfile | ||||
| @@ -131,7 +131,7 @@ def convert_to_kobo_timestamp_string(timestamp): | ||||
|         return timestamp.strftime("%Y-%m-%dT%H:%M:%SZ") | ||||
|     except AttributeError as exc: | ||||
|         log.debug("Timestamp not valid: {}".format(exc)) | ||||
|         return datetime.now(UTC).strftime("%Y-%m-%dT%H:%M:%SZ") | ||||
|         return datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ") | ||||
|  | ||||
|  | ||||
| @kobo.route("/v1/library/sync") | ||||
| @@ -375,7 +375,7 @@ def create_book_entitlement(book, archived): | ||||
|     book_uuid = str(book.uuid) | ||||
|     return { | ||||
|         "Accessibility": "Full", | ||||
|         "ActivePeriod": {"From": convert_to_kobo_timestamp_string(datetime.now(UTC))}, | ||||
|         "ActivePeriod": {"From": convert_to_kobo_timestamp_string(datetime.now(timezone.utc))}, | ||||
|         "Created": convert_to_kobo_timestamp_string(book.timestamp), | ||||
|         "CrossRevisionId": book_uuid, | ||||
|         "Id": book_uuid, | ||||
| @@ -795,7 +795,7 @@ def HandleStateRequest(book_uuid): | ||||
|                 if new_book_read_status == ub.ReadBook.STATUS_IN_PROGRESS \ | ||||
|                         and new_book_read_status != book_read.read_status: | ||||
|                     book_read.times_started_reading += 1 | ||||
|                     book_read.last_time_started_reading = datetime.now(UTC) | ||||
|                     book_read.last_time_started_reading = datetime.now(timezone.utc) | ||||
|                 book_read.read_status = new_book_read_status | ||||
|                 update_results_response["StatusInfoResult"] = {"Result": "Success"} | ||||
|         except (KeyError, TypeError, ValueError, StatementError): | ||||
|   | ||||
| @@ -19,7 +19,7 @@ | ||||
|  | ||||
| from .cw_login import current_user | ||||
| from . import ub | ||||
| from datetime import datetime, UTC | ||||
| from datetime import datetime, timezone | ||||
| from sqlalchemy.sql.expression import or_, and_, true | ||||
| # from sqlalchemy import exc | ||||
|  | ||||
| @@ -58,7 +58,7 @@ def change_archived_books(book_id, state=None, message=None): | ||||
|         archived_book = ub.ArchivedBook(user_id=current_user.id, book_id=book_id) | ||||
|  | ||||
|     archived_book.is_archived = state if state else not archived_book.is_archived | ||||
|     archived_book.last_modified = datetime.now(UTC)        # toDo. Check utc timestamp | ||||
|     archived_book.last_modified = datetime.now(timezone.utc)        # toDo. Check utc timestamp | ||||
|  | ||||
|     ub.session.merge(archived_book) | ||||
|     ub.session_commit(message) | ||||
|   | ||||
							
								
								
									
										10
									
								
								cps/shelf.py
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								cps/shelf.py
									
									
									
									
									
								
							| @@ -21,7 +21,7 @@ | ||||
| #  along with this program. If not, see <http://www.gnu.org/licenses/>. | ||||
|  | ||||
| import sys | ||||
| from datetime import datetime, UTC | ||||
| from datetime import datetime, timezone | ||||
|  | ||||
| from flask import Blueprint, flash, redirect, request, url_for, abort | ||||
| from flask_babel import gettext as _ | ||||
| @@ -80,7 +80,7 @@ def add_to_shelf(shelf_id, book_id): | ||||
|         return "%s is a invalid Book Id. Could not be added to Shelf" % book_id, 400 | ||||
|  | ||||
|     shelf.books.append(ub.BookShelf(shelf=shelf.id, book_id=book_id, order=maxOrder + 1)) | ||||
|     shelf.last_modified = datetime.now(UTC) | ||||
|     shelf.last_modified = datetime.now(timezone.utc) | ||||
|     try: | ||||
|         ub.session.merge(shelf) | ||||
|         ub.session.commit() | ||||
| @@ -139,7 +139,7 @@ def search_to_shelf(shelf_id): | ||||
|         for book in books_for_shelf: | ||||
|             maxOrder += 1 | ||||
|             shelf.books.append(ub.BookShelf(shelf=shelf.id, book_id=book, order=maxOrder)) | ||||
|         shelf.last_modified = datetime.now(UTC) | ||||
|         shelf.last_modified = datetime.now(timezone.utc) | ||||
|         try: | ||||
|             ub.session.merge(shelf) | ||||
|             ub.session.commit() | ||||
| @@ -185,7 +185,7 @@ def remove_from_shelf(shelf_id, book_id): | ||||
|  | ||||
|         try: | ||||
|             ub.session.delete(book_shelf) | ||||
|             shelf.last_modified = datetime.now(UTC) | ||||
|             shelf.last_modified = datetime.now(timezone.utc) | ||||
|             ub.session.commit() | ||||
|         except (OperationalError, InvalidRequestError) as e: | ||||
|             ub.session.rollback() | ||||
| @@ -271,7 +271,7 @@ def order_shelf(shelf_id): | ||||
|             for book in books_in_shelf: | ||||
|                 setattr(book, 'order', to_save[str(book.book_id)]) | ||||
|                 counter += 1 | ||||
|                 # if order different from before -> shelf.last_modified = datetime.now(UTC) | ||||
|                 # if order different from before -> shelf.last_modified = datetime.now(timezone.utc) | ||||
|             try: | ||||
|                 ub.session.commit() | ||||
|             except (OperationalError, InvalidRequestError) as e: | ||||
|   | ||||
| @@ -20,7 +20,7 @@ import os | ||||
| from shutil import copyfile, copyfileobj | ||||
| from urllib.request import urlopen | ||||
| from io import BytesIO | ||||
| from datetime import datetime, UTC | ||||
| from datetime import datetime, timezone | ||||
|  | ||||
| from .. import constants | ||||
| from cps import config, db, fs, gdriveutils, logger, ub | ||||
| @@ -122,7 +122,7 @@ class TaskGenerateCoverThumbnails(CalibreTask): | ||||
|             .query(ub.Thumbnail) \ | ||||
|             .filter(ub.Thumbnail.type == constants.THUMBNAIL_TYPE_COVER) \ | ||||
|             .filter(ub.Thumbnail.entity_id == book_id) \ | ||||
|             .filter(or_(ub.Thumbnail.expiration.is_(None), ub.Thumbnail.expiration > datetime.now(UTC))) \ | ||||
|             .filter(or_(ub.Thumbnail.expiration.is_(None), ub.Thumbnail.expiration > datetime.now(timezone.utc))) \ | ||||
|             .all() | ||||
|  | ||||
|     def create_book_cover_thumbnails(self, book): | ||||
| @@ -164,7 +164,7 @@ class TaskGenerateCoverThumbnails(CalibreTask): | ||||
|             self.app_db_session.rollback() | ||||
|  | ||||
|     def update_book_cover_thumbnail(self, book, thumbnail): | ||||
|         thumbnail.generated_at = datetime.now(UTC) | ||||
|         thumbnail.generated_at = datetime.now(timezone.utc) | ||||
|  | ||||
|         try: | ||||
|             self.app_db_session.commit() | ||||
| @@ -325,7 +325,7 @@ class TaskGenerateSeriesThumbnails(CalibreTask): | ||||
|             .query(ub.Thumbnail) | ||||
|             .filter(ub.Thumbnail.type == constants.THUMBNAIL_TYPE_SERIES) | ||||
|             .filter(ub.Thumbnail.entity_id == series_id) | ||||
|             .filter(or_(ub.Thumbnail.expiration.is_(None), ub.Thumbnail.expiration > datetime.now(UTC))) | ||||
|             .filter(or_(ub.Thumbnail.expiration.is_(None), ub.Thumbnail.expiration > datetime.now(timezone.utc))) | ||||
|             .all()) | ||||
|  | ||||
|     def create_series_thumbnail(self, series, series_books, resolution): | ||||
| @@ -345,7 +345,7 @@ class TaskGenerateSeriesThumbnails(CalibreTask): | ||||
|             self.app_db_session.rollback() | ||||
|  | ||||
|     def update_series_thumbnail(self, series_books, thumbnail): | ||||
|         thumbnail.generated_at = datetime.now(UTC) | ||||
|         thumbnail.generated_at = datetime.now(timezone.utc) | ||||
|  | ||||
|         try: | ||||
|             self.app_db_session.commit() | ||||
|   | ||||
							
								
								
									
										28
									
								
								cps/ub.py
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								cps/ub.py
									
									
									
									
									
								
							| @@ -20,7 +20,7 @@ | ||||
| import atexit | ||||
| import os | ||||
| import sys | ||||
| from datetime import datetime, UTC, timedelta | ||||
| from datetime import datetime, timezone, timedelta | ||||
| import itertools | ||||
| import uuid | ||||
| from flask import session as flask_session | ||||
| @@ -370,8 +370,8 @@ class Shelf(Base): | ||||
|     user_id = Column(Integer, ForeignKey('user.id')) | ||||
|     kobo_sync = Column(Boolean, default=False) | ||||
|     books = relationship("BookShelf", backref="ub_shelf", cascade="all, delete-orphan", lazy="dynamic") | ||||
|     created = Column(DateTime, default=lambda: datetime.now(UTC)) | ||||
|     last_modified = Column(DateTime, default=lambda: datetime.now(UTC), onupdate=lambda: datetime.now(UTC)) | ||||
|     created = Column(DateTime, default=lambda: datetime.now(timezone.utc)) | ||||
|     last_modified = Column(DateTime, default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc)) | ||||
|  | ||||
|     def __repr__(self): | ||||
|         return '<Shelf %d:%r>' % (self.id, self.name) | ||||
| @@ -385,7 +385,7 @@ class BookShelf(Base): | ||||
|     book_id = Column(Integer) | ||||
|     order = Column(Integer) | ||||
|     shelf = Column(Integer, ForeignKey('shelf.id')) | ||||
|     date_added = Column(DateTime, default=lambda: datetime.now(UTC)) | ||||
|     date_added = Column(DateTime, default=lambda: datetime.now(timezone.utc)) | ||||
|  | ||||
|     def __repr__(self): | ||||
|         return '<Book %r>' % self.id | ||||
| @@ -398,7 +398,7 @@ class ShelfArchive(Base): | ||||
|     id = Column(Integer, primary_key=True) | ||||
|     uuid = Column(String) | ||||
|     user_id = Column(Integer, ForeignKey('user.id')) | ||||
|     last_modified = Column(DateTime, default=lambda: datetime.now(UTC)) | ||||
|     last_modified = Column(DateTime, default=lambda: datetime.now(timezone.utc)) | ||||
|  | ||||
|  | ||||
| class ReadBook(Base): | ||||
| @@ -418,7 +418,7 @@ class ReadBook(Base): | ||||
|                                       cascade="all", | ||||
|                                       backref=backref("book_read_link", | ||||
|                                                       uselist=False)) | ||||
|     last_modified = Column(DateTime, default=lambda: datetime.now(UTC), onupdate=lambda: datetime.now(UTC)) | ||||
|     last_modified = Column(DateTime, default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc)) | ||||
|     last_time_started_reading = Column(DateTime, nullable=True) | ||||
|     times_started_reading = Column(Integer, default=0, nullable=False) | ||||
|  | ||||
| @@ -441,7 +441,7 @@ class ArchivedBook(Base): | ||||
|     user_id = Column(Integer, ForeignKey('user.id')) | ||||
|     book_id = Column(Integer) | ||||
|     is_archived = Column(Boolean, unique=False) | ||||
|     last_modified = Column(DateTime, default=lambda: datetime.now(UTC)) | ||||
|     last_modified = Column(DateTime, default=lambda: datetime.now(timezone.utc)) | ||||
|  | ||||
|  | ||||
| class KoboSyncedBooks(Base): | ||||
| @@ -460,8 +460,8 @@ class KoboReadingState(Base): | ||||
|     id = Column(Integer, primary_key=True, autoincrement=True) | ||||
|     user_id = Column(Integer, ForeignKey('user.id')) | ||||
|     book_id = Column(Integer) | ||||
|     last_modified = Column(DateTime, default=lambda: datetime.now(UTC), onupdate=lambda: datetime.now(UTC)) | ||||
|     priority_timestamp = Column(DateTime, default=lambda: datetime.now(UTC), onupdate=lambda: datetime.now(UTC)) | ||||
|     last_modified = Column(DateTime, default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc)) | ||||
|     priority_timestamp = Column(DateTime, default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc)) | ||||
|     current_bookmark = relationship("KoboBookmark", uselist=False, backref="kobo_reading_state", cascade="all, delete") | ||||
|     statistics = relationship("KoboStatistics", uselist=False, backref="kobo_reading_state", cascade="all, delete") | ||||
|  | ||||
| @@ -471,7 +471,7 @@ class KoboBookmark(Base): | ||||
|  | ||||
|     id = Column(Integer, primary_key=True) | ||||
|     kobo_reading_state_id = Column(Integer, ForeignKey('kobo_reading_state.id')) | ||||
|     last_modified = Column(DateTime, default=lambda: datetime.now(UTC), onupdate=lambda: datetime.now(UTC)) | ||||
|     last_modified = Column(DateTime, default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc)) | ||||
|     location_source = Column(String) | ||||
|     location_type = Column(String) | ||||
|     location_value = Column(String) | ||||
| @@ -484,7 +484,7 @@ class KoboStatistics(Base): | ||||
|  | ||||
|     id = Column(Integer, primary_key=True) | ||||
|     kobo_reading_state_id = Column(Integer, ForeignKey('kobo_reading_state.id')) | ||||
|     last_modified = Column(DateTime, default=lambda: datetime.now(UTC), onupdate=lambda: datetime.now(UTC)) | ||||
|     last_modified = Column(DateTime, default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc)) | ||||
|     remaining_time_minutes = Column(Integer) | ||||
|     spent_reading_minutes = Column(Integer) | ||||
|  | ||||
| @@ -495,11 +495,11 @@ def receive_before_flush(session, flush_context, instances): | ||||
|     for change in itertools.chain(session.new, session.dirty): | ||||
|         if isinstance(change, (ReadBook, KoboStatistics, KoboBookmark)): | ||||
|             if change.kobo_reading_state: | ||||
|                 change.kobo_reading_state.last_modified = datetime.now(UTC) | ||||
|                 change.kobo_reading_state.last_modified = datetime.now(timezone.utc) | ||||
|     # Maintain the last_modified_bit for the Shelf table. | ||||
|     for change in itertools.chain(session.new, session.deleted): | ||||
|         if isinstance(change, BookShelf): | ||||
|             change.ub_shelf.last_modified = datetime.now(UTC) | ||||
|             change.ub_shelf.last_modified = datetime.now(timezone.utc) | ||||
|  | ||||
|  | ||||
| # Baseclass representing Downloads from calibre-web in app.db | ||||
| @@ -563,7 +563,7 @@ class Thumbnail(Base): | ||||
|     type = Column(SmallInteger, default=constants.THUMBNAIL_TYPE_COVER) | ||||
|     resolution = Column(SmallInteger, default=constants.COVER_THUMBNAIL_SMALL) | ||||
|     filename = Column(String, default=filename) | ||||
|     generated_at = Column(DateTime, default=lambda: datetime.now(UTC)) | ||||
|     generated_at = Column(DateTime, default=lambda: datetime.now(timezone.utc)) | ||||
|     expiration = Column(DateTime, nullable=True) | ||||
|  | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Ozzie Isaacs
					Ozzie Isaacs