From 7a8d054b28fad35499e1c7ea89397149e3395e34 Mon Sep 17 00:00:00 2001 From: Ozzie Isaacs Date: Sat, 10 Aug 2024 21:05:29 +0200 Subject: [PATCH] Make datetime utcnow compatible to older python versions --- cps/cw_login/login_manager.py | 5 +++-- cps/db.py | 6 +++--- cps/editbooks.py | 12 ++++++------ cps/helper.py | 6 +++--- cps/kobo.py | 8 ++++---- cps/kobo_sync_status.py | 4 ++-- cps/shelf.py | 10 +++++----- cps/tasks/thumbnail.py | 10 +++++----- cps/ub.py | 28 ++++++++++++++-------------- 9 files changed, 45 insertions(+), 44 deletions(-) diff --git a/cps/cw_login/login_manager.py b/cps/cw_login/login_manager.py index 23ba52e73..a3714af60 100644 --- a/cps/cw_login/login_manager.py +++ b/cps/cw_login/login_manager.py @@ -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," diff --git a/cps/db.py b/cps/db.py index 758714ed1..d0edb871f 100644 --- a/cps/db.py +++ b/cps/db.py @@ -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) diff --git a/cps/editbooks.py b/cps/editbooks.py index a143919c0..33a95fb19 100644 --- a/cps/editbooks.py +++ b/cps/editbooks.py @@ -21,7 +21,7 @@ # along with this program. If not, see . 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') diff --git a/cps/helper.py b/cps/helper.py index a5931019a..bc95762c6 100644 --- a/cps/helper.py +++ b/cps/helper.py @@ -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()) diff --git a/cps/kobo.py b/cps/kobo.py index 8e5eed559..bd4deea50 100644 --- a/cps/kobo.py +++ b/cps/kobo.py @@ -18,7 +18,7 @@ # along with this program. If not, see . 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): diff --git a/cps/kobo_sync_status.py b/cps/kobo_sync_status.py index 46e35e9be..357b84efe 100644 --- a/cps/kobo_sync_status.py +++ b/cps/kobo_sync_status.py @@ -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) diff --git a/cps/shelf.py b/cps/shelf.py index 1cf4bdb94..6558e8d59 100644 --- a/cps/shelf.py +++ b/cps/shelf.py @@ -21,7 +21,7 @@ # along with this program. If not, see . 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: diff --git a/cps/tasks/thumbnail.py b/cps/tasks/thumbnail.py index 769309531..2142b018b 100644 --- a/cps/tasks/thumbnail.py +++ b/cps/tasks/thumbnail.py @@ -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() diff --git a/cps/ub.py b/cps/ub.py index 86184c729..e548cc12f 100644 --- a/cps/ub.py +++ b/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 '' % (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 '' % 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)