diff --git a/MANIFEST.in b/MANIFEST.in
index b667159c..f07c4d83 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1 +1,3 @@
graft src/calibreweb
+global-exclude __pycache__
+global-exclude *.pyc
diff --git a/cps/__init__.py b/cps/__init__.py
index 7f2a6b13..31614c2a 100644
--- a/cps/__init__.py
+++ b/cps/__init__.py
@@ -31,12 +31,10 @@ from flask_principal import Principal
from . import logger
from .cli import CliParameter
-from .constants import CONFIG_DIR
from .reverseproxy import ReverseProxied
from .server import WebServer
from .dep_check import dependency_check
from .updater import Updater
-from .babel import babel, get_locale
from . import config_sql
from . import cache_buster
from . import ub, db
@@ -183,6 +181,7 @@ def create_app():
app.secret_key = os.getenv('SECRET_KEY', config_sql.get_flask_session_key(ub.session))
web_server.init_app(app, config)
+ from .cw_babel import babel, get_locale
if hasattr(babel, "localeselector"):
babel.init_app(app)
babel.localeselector(get_locale)
diff --git a/cps/about.py b/cps/about.py
index fb031343..b43c97b9 100644
--- a/cps/about.py
+++ b/cps/about.py
@@ -42,19 +42,17 @@ opt = dep_check.load_dependencies(True)
for i in (req + opt):
modules[i[1]] = i[0]
modules['Jinja2'] = importlib.metadata.version("jinja2")
-try:
+if sys.version_info < (3, 12):
modules['pySqlite'] = sqlite3.version
-except Exception:
- pass
modules['SQLite'] = sqlite3.sqlite_version
sorted_modules = OrderedDict((sorted(modules.items(), key=lambda x: x[0].casefold())))
def collect_stats():
if constants.NIGHTLY_VERSION[0] == "$Format:%H$":
- calibre_web_version = constants.STABLE_VERSION['version'].replace("b", " Beta")
+ calibre_web_version = constants.STABLE_VERSION.replace("b", " Beta")
else:
- calibre_web_version = (constants.STABLE_VERSION['version'].replace("b", " Beta") + ' - '
+ calibre_web_version = (constants.STABLE_VERSION.replace("b", " Beta") + ' - '
+ constants.NIGHTLY_VERSION[0].replace('%', '%%') + ' - '
+ constants.NIGHTLY_VERSION[1].replace('%', '%%'))
diff --git a/cps/admin.py b/cps/admin.py
index 08972292..6252b317 100644
--- a/cps/admin.py
+++ b/cps/admin.py
@@ -52,7 +52,7 @@ from .gdriveutils import is_gdrive_ready, gdrive_support
from .render_template import render_title_template, get_sidebar_config
from .services.worker import WorkerThread
from .usermanagement import user_login_required
-from .babel import get_available_translations, get_available_locale, get_user_locale_language
+from .cw_babel import get_available_translations, get_available_locale, get_user_locale_language
from . import debug_info
from .string_helper import strip_whitespaces
@@ -219,7 +219,7 @@ def admin():
form_date += timedelta(hours=int(commit[20:22]), minutes=int(commit[23:]))
commit = format_datetime(form_date - tz, format='short')
else:
- commit = version['version'].replace("b", " Beta")
+ commit = version.replace("b", " Beta")
all_user = ub.session.query(ub.User).all()
# email_settings = mail_config.get_mail_settings()
diff --git a/cps/cli.py b/cps/cli.py
index 5bf289b8..3f21a17e 100644
--- a/cps/cli.py
+++ b/cps/cli.py
@@ -29,8 +29,8 @@ from .constants import DEFAULT_SETTINGS_FILE, DEFAULT_GDRIVE_FILE
def version_info():
if _NIGHTLY_VERSION[1].startswith('$Format'):
- return "Calibre-Web version: %s - unknown git-clone" % _STABLE_VERSION['version'].replace("b", " Beta")
- return "Calibre-Web version: %s -%s" % (_STABLE_VERSION['version'].replace("b", " Beta"), _NIGHTLY_VERSION[1])
+ return "Calibre-Web version: %s - unknown git-clone" % _STABLE_VERSION.replace("b", " Beta")
+ return "Calibre-Web version: %s -%s" % (_STABLE_VERSION.replace("b", " Beta"), _NIGHTLY_VERSION[1])
class CliParameter(object):
diff --git a/cps/constants.py b/cps/constants.py
index 3d1f0dfe..0f03364a 100644
--- a/cps/constants.py
+++ b/cps/constants.py
@@ -19,9 +19,6 @@
import sys
import os
from collections import namedtuple
-from sqlalchemy import __version__ as sql_version
-
-sqlalchemy_version2 = ([int(x) for x in sql_version.split('.')] >= [2, 0, 0])
# APP_MODE - production, development, or test
APP_MODE = os.environ.get('APP_MODE', 'production')
@@ -175,7 +172,8 @@ BookMeta = namedtuple('BookMeta', 'file_path, extension, title, author, cover, d
'series_id, languages, publisher, pubdate, identifiers')
# python build process likes to have x.y.zbw -> b for beta and w a counting number
-STABLE_VERSION = {'version': '0.6.24b'}
+STABLE_VERSION = '0.6.24b'
+# _version = STABLE_VERSION['version']
NIGHTLY_VERSION = dict()
NIGHTLY_VERSION[0] = '$Format:%H$'
diff --git a/cps/babel.py b/cps/cw_babel.py
similarity index 100%
rename from cps/babel.py
rename to cps/cw_babel.py
diff --git a/cps/dep_check.py b/cps/dep_check.py
index b1917f7a..2f156913 100644
--- a/cps/dep_check.py
+++ b/cps/dep_check.py
@@ -63,7 +63,7 @@ def dependency_check(optional=False):
deps = load_dependencies(optional)
for dep in deps:
try:
- dep_version_int = [int(x) if x.isnumeric() else 0 for x in dep[0].split('.')]
+ dep_version_int = [int(x) if x.isnumeric() else 0 for x in dep[0].split('.')[:3]]
low_check = [int(x) for x in dep[3].split('.')]
high_check = [int(x) for x in dep[5].split('.')]
except AttributeError:
diff --git a/cps/isoLanguages.py b/cps/isoLanguages.py
index bbab7089..a34cd34a 100644
--- a/cps/isoLanguages.py
+++ b/cps/isoLanguages.py
@@ -25,20 +25,7 @@ log = logger.create()
try:
- from iso639 import languages
- # iso_version = importlib.metadata.version("iso639")
- get = languages.get
- try:
- if sys.version_info >= (3, 12):
- import pkg_resources
- except ImportError:
- print("Python 3.12 isn't compatible with iso-639. Please install pycountry.")
-except ImportError as ex:
from pycountry import languages as pyc_languages
- #try:
- # iso_version = importlib.metadata.version("pycountry") + ' (PyCountry)'
- #except (ImportError, Exception):
- # iso_version = "?" + ' (PyCountry)'
def _copy_fields(l):
l.part1 = getattr(l, 'alpha_2', None)
@@ -52,6 +39,11 @@ except ImportError as ex:
return _copy_fields(pyc_languages.get(alpha_2=part1))
if name is not None:
return _copy_fields(pyc_languages.get(name=name))
+except ImportError as ex:
+ if sys.version_info >= (3, 12):
+ print("Python 3.12 isn't compatible with iso-639. Please install pycountry.")
+ from iso639 import languages
+ get = languages.get
def get_language_names(locale):
@@ -109,6 +101,6 @@ def get_lang3(lang):
ret_value = lang
else:
ret_value = ""
- except KeyError:
+ except (KeyError, AttributeError):
ret_value = lang
return ret_value
diff --git a/cps/services/background_scheduler.py b/cps/services/background_scheduler.py
index 72991559..55b12df3 100644
--- a/cps/services/background_scheduler.py
+++ b/cps/services/background_scheduler.py
@@ -42,6 +42,7 @@ class BackgroundScheduler:
if cls._instance is None:
cls._instance = super(BackgroundScheduler, cls).__new__(cls)
cls.log = logger.create()
+ logger.logging.getLogger('tzlocal').setLevel(logger.logging.WARNING)
cls.scheduler = BScheduler()
cls.scheduler.start()
diff --git a/cps/updater.py b/cps/updater.py
index ab67e7a6..e55feb6b 100644
--- a/cps/updater.py
+++ b/cps/updater.py
@@ -614,7 +614,7 @@ class Updater(threading.Thread):
if version is False:
status['current_commit_hash'] = _(u'Unknown')
else:
- status['current_commit_hash'] = version['version']
+ status['current_commit_hash'] = version
try:
headers = {'Accept': 'application/vnd.github.v3+json'}
r = requests.get(repository_url, headers=headers, timeout=10)
diff --git a/cps/web.py b/cps/web.py
index 8277a763..ab2b54e3 100644
--- a/cps/web.py
+++ b/cps/web.py
@@ -23,6 +23,7 @@ import json
import mimetypes
import chardet # dependency of requests
import copy
+import importlib
from flask import Blueprint, jsonify
from flask import request, redirect, send_from_directory, make_response, flash, abort, url_for, Response
@@ -36,7 +37,6 @@ from sqlalchemy.exc import IntegrityError, InvalidRequestError, OperationalError
from sqlalchemy.sql.expression import text, func, false, not_, and_, or_
from sqlalchemy.orm.attributes import flag_modified
from sqlalchemy.sql.functions import coalesce
-
from werkzeug.datastructures import Headers
from werkzeug.security import generate_password_hash, check_password_hash
@@ -51,7 +51,7 @@ from .helper import check_valid_domain, check_email, check_username, \
edit_book_read_status, valid_password
from .pagination import Pagination
from .redirect import get_redirect_location
-from .babel import get_available_locale
+from .cw_babel import get_available_locale
from .usermanagement import login_required_if_no_ano
from .kobo_sync_status import remove_synced_book
from .render_template import render_title_template
@@ -86,6 +86,10 @@ except ImportError:
sort = sorted # Just use regular sort then, may cause issues with badly named pages in cbz/cbr files
+sql_version = importlib.metadata.version("sqlalchemy")
+sqlalchemy_version2 = ([int(x) for x in sql_version.split('.')] >= [2, 0, 0])
+
+
@app.after_request
def add_security_headers(resp):
default_src = ([host.strip() for host in config.config_trustedhosts.split(',') if host] +
@@ -532,7 +536,7 @@ def render_author_books(page, author_id, order):
flash(_("Oops! Selected book is unavailable. File does not exist or is not accessible"),
category="error")
return redirect(url_for("web.index"))
- if constants.sqlalchemy_version2:
+ if sqlalchemy_version2:
author = calibre_db.session.get(db.Authors, author_id)
else:
author = calibre_db.session.query(db.Authors).get(author_id)
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 00000000..9ff8bb1f
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,127 @@
+[build-system]
+requires = ["setuptools>=61.2"]
+build-backend = "setuptools.build_meta"
+
+[project]
+name = "calibreweb"
+description = "Web app for browsing, reading and downloading eBooks stored in a Calibre database."
+authors = [{name = "@OzzieIsaacs", email = "Ozzie.Fernandez.Isaacs@googlemail.com"}]
+maintainers = [{name = "@OzzieIsaacs"}]
+license = {text = "GPLv3+"}
+classifiers = [
+ "Development Status :: 5 - Production/Stable",
+ "License :: OSI Approved :: GNU Affero General Public License v3",
+ "Programming Language :: Python :: 3",
+ "Programming Language :: Python :: 3.6",
+ "Programming Language :: Python :: 3.7",
+ "Programming Language :: Python :: 3.8",
+ "Programming Language :: Python :: 3.9",
+ "Programming Language :: Python :: 3.10",
+ "Programming Language :: Python :: 3.11",
+ "Operating System :: OS Independent",
+]
+keywords = [
+ "calibre",
+ "calibre-web",
+ "library",
+]
+requires-python = ">=3.6"
+dependencies = [
+ "APScheduler>=3.6.3,<3.11.0",
+ "Babel>=1.3,<3.0",
+ "Flask-Babel>=0.11.1,<4.1.0",
+ "Flask-Principal>=0.3.2,<0.5.1",
+ "Flask>=1.0.2,<3.1.0",
+ "iso-639>=0.4.5,<0.5.0",
+ "PyPDF>=3.15.6,<5.1.0",
+ "pytz>=2016.10",
+ "requests>=2.32.0,<2.33.0",
+ "SQLAlchemy>=1.3.0,<2.1.0",
+ "tornado>=6.3,<6.5",
+ "Wand>=0.4.4,<0.7.0",
+ "unidecode>=0.04.19,<1.4.0",
+ "lxml>=4.9.1,<5.3.0",
+ "flask-wtf>=0.14.2,<1.3.0",
+ "chardet>=3.0.0,<5.3.0",
+ "netifaces-plus>=0.12.0,<0.13.0",
+ "urllib3>=1.22,<3.0",
+ "Flask-Limiter>=2.3.0,<3.9.0",
+ "regex>=2022.3.2,<2024.6.25",
+ "bleach>=6.0.0,<6.2.0",
+ "python-magic>=0.4.27,<0.5.0",
+ "flask-httpAuth>=4.4.0,<5.0.0",
+ "cryptography>=30.0.0,<44.0.0",
+]
+dynamic = ["version"]
+
+[project.urls]
+Homepage = "https://github.com/janeczku/calibre-web"
+"Bug Tracker" = "https://github.com/janeczku/calibre-web/issues"
+"Release Management" = "https://github.com/janeczku/calibre-web/releases"
+Documentation = "https://github.com/janeczku/calibre-web/wiki"
+"Source Code" = "https://github.com/janeczku/calibre-web"
+
+[project.readme]
+file = "README.md"
+content-type = "text/markdown"
+
+[project.optional-dependencies]
+gdrive = [
+ "google-api-python-client>=1.7.11,<2.200.0",
+ "gevent>20.6.0,<24.3.0",
+ "greenlet>=0.4.17,<3.1.0",
+ "httplib2>=0.9.2,<0.23.0",
+ "oauth2client>=4.0.0,<4.1.4",
+ "uritemplate>=3.0.0,<4.2.0",
+ "pyasn1-modules>=0.0.8,<0.5.0",
+ "pyasn1>=0.1.9,<0.7.0",
+ "PyDrive2>=1.3.1,<1.20.0",
+ "PyYAML>=3.12,<6.1",
+ "rsa>=3.4.2,<4.10.0",
+]
+gmail = [
+ "google-auth-oauthlib>=0.4.3,<1.3.0",
+ "google-api-python-client>=1.7.11,<2.200.0",
+]
+goodreads = [
+ "goodreads>=0.3.2,<0.4.0",
+ "python-Levenshtein>=0.12.0,<0.27.0",
+]
+ldap = [
+ "python-ldap>=3.0.0,<3.5.0",
+ "Flask-SimpleLDAP>=1.4.0,<2.1.0",
+]
+oauth = [
+ "Flask-Dance>=2.0.0,<7.1.0",
+ "SQLAlchemy-Utils>=0.33.5,<0.42.0",
+]
+metadata = [
+ "rarfile>=3.2,<5.0",
+ "scholarly>=1.2.0,<1.8",
+ "markdown2>=2.0.0,<2.5.0",
+ "html2text>=2020.1.16,<2024.2.26",
+ "python-dateutil>=2.1,<2.10.0",
+ "beautifulsoup4>=4.0.1,<4.13.0",
+ "faust-cchardet>=2.1.18,<2.1.20",
+ "py7zr>=0.15.0,<0.21.0",
+ "mutagen>=1.40.0,<1.50.0",
+ "pycountry>=20.0.0,<25.0.0",
+]
+comics = [
+ "natsort>=2.2.0,<8.5.0",
+ "comicapi>=2.2.0,<3.3.0",
+]
+kobo = [
+ "jsonschema>=3.2.0,<4.24.0",
+]
+
+[project.scripts]
+cps = "calibreweb:main"
+
+[tool.setuptools]
+include-package-data = true
+license-files = ["LICENSE"]
+
+[tool.setuptools.dynamic]
+version = {attr = "calibreweb.cps.constants.STABLE_VERSION"}
+
diff --git a/setup.cfg b/setup.cfg
deleted file mode 100644
index ee1c63c5..00000000
--- a/setup.cfg
+++ /dev/null
@@ -1,110 +0,0 @@
-[metadata]
-name = calibreweb
-url = https://github.com/janeczku/calibre-web
-project_urls =
- Bug Tracker = https://github.com/janeczku/calibre-web/issues
- Release Management = https://github.com/janeczku/calibre-web/releases
- Documentation = https://github.com/janeczku/calibre-web/wiki
- Source Code = https://github.com/janeczku/calibre-web
-description = Web app for browsing, reading and downloading eBooks stored in a Calibre database.
-long_description = file: README.md
-long_description_content_type = text/markdown
-author = @OzzieIsaacs
-author_email = Ozzie.Fernandez.Isaacs@googlemail.com
-maintainer = @OzzieIsaacs
-license = GPLv3+
-license_files = LICENSE
-classifiers =
- Development Status :: 5 - Production/Stable
- License :: OSI Approved :: GNU Affero General Public License v3
- Programming Language :: Python :: 3
- Programming Language :: Python :: 3.6
- Programming Language :: Python :: 3.7
- Programming Language :: Python :: 3.8
- Programming Language :: Python :: 3.9
- Programming Language :: Python :: 3.10
- Programming Language :: Python :: 3.11
- Operating System :: OS Independent
-keywords =
- calibre
- calibre-web
- library
-python_requires = >=3.5
-
-[options.entry_points]
-console_scripts =
- cps = calibreweb:main
-
-[options]
-include_package_data = True
-install_requires =
- APScheduler>=3.6.3,<3.11.0
- Babel>=1.3,<3.0
- Flask-Babel>=0.11.1,<4.1.0
- Flask-Principal>=0.3.2,<0.5.1
- Flask>=1.0.2,<3.1.0
- iso-639>=0.4.5,<0.5.0
- PyPDF>=3.15.6,<4.3.0
- pytz>=2016.10
- requests>=2.28.0,<2.32.0
- SQLAlchemy>=1.3.0,<2.1.0
- tornado>=6.3,<6.5
- Wand>=0.4.4,<0.7.0
- unidecode>=0.04.19,<1.4.0
- lxml>=4.9.1,<5.3.0
- flask-wtf>=0.14.2,<1.3.0
- chardet>=3.0.0,<5.3.0
- advocate>=1.0.0,<1.1.0
- Flask-Limiter>=2.3.0,<3.9.0
- regex>=2022.3.2,<2024.6.25
- bleach>=6.0.0,<6.2.0
- python-magic>=0.4.27,<0.5.0
- flask-httpAuth>=4.4.0,<5.0.0
-
-
-[options.packages.find]
-where = src
-include = cps/services*
-
-[options.extras_require]
-gdrive =
- google-api-python-client>=1.7.11,<2.200.0
- gevent>20.6.0,<24.3.0
- greenlet>=0.4.17,<3.1.0
- httplib2>=0.9.2,<0.23.0
- oauth2client>=4.0.0,<4.1.4
- uritemplate>=3.0.0,<4.2.0
- pyasn1-modules>=0.0.8,<0.5.0
- pyasn1>=0.1.9,<0.7.0
- PyDrive2>=1.3.1,<1.20.0
- PyYAML>=3.12,<6.1
- rsa>=3.4.2,<4.10.0
-gmail =
- google-auth-oauthlib>=0.4.3,<1.3.0
- google-api-python-client>=1.7.11,<2.200.0
-goodreads =
- goodreads>=0.3.2,<0.4.0
- python-Levenshtein>=0.12.0,<0.26.0
-ldap =
- python-ldap>=3.0.0,<3.5.0
- Flask-SimpleLDAP>=1.4.0,<2.1.0
-oauth =
- Flask-Dance>=2.0.0,<7.1.0
- SQLAlchemy-Utils>=0.33.5,<0.42.0
-metadata =
- rarfile>=3.2,<5.0
- scholarly>=1.2.0,<1.8
- markdown2>=2.0.0,<2.5.0
- html2text>=2020.1.16,<2024.2.26
- python-dateutil>=2.1,<2.10.0
- beautifulsoup4>=4.0.1,<4.13.0
- faust-cchardet>=2.1.18,<2.1.20
- py7zr>=0.15.0,<0.21.0
- mutagen>=1.40.0,<1.50.0
- pycountry>=20.0.0,<25.0.0
-comics =
- natsort>=2.2.0,<8.5.0
- comicapi>=2.2.0,<3.3.0
-kobo =
- jsonschema>=3.2.0,<4.24.0
-
diff --git a/setup.py b/setup.py
deleted file mode 100644
index 8dcbee25..00000000
--- a/setup.py
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-# This file is part of the Calibre-Web (https://github.com/janeczku/calibre-web)
-# Copyright (C) 2019 decentral1se
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see
Start Time: 2024-10-31 19:45:00
+Start Time: 2024-11-02 08:09:02
Stop Time: 2024-11-01 03:02:38
+Stop Time: 2024-11-02 15:03:00
Duration: 6h 11 min
+Duration: 5h 47 min
Traceback (most recent call last): + File "/home/ozzie/Development/calibre-web-test/test/test_kobo_sync.py", line 372, in test_sync_shelf + self.assertEqual(1, len(data), data) +AssertionError: 1 != 0 : []+
Traceback (most recent call last): - File "/home/ozzie/Development/calibre-web-test/test/test_pip_install.py", line 39, in setUpClass - make_release.main(args) - File "/home/ozzie/Development/calibre-web-test/build_release/make_release.py", line 456, in main - update_requirements() - File "/home/ozzie/Development/calibre-web-test/build_release/make_release.py", line 92, in update_requirements - with open(os.path.join(FILEPATH, "pyproject.toml"), 'r') as fp: -FileNotFoundError: [Errno 2] No such file or directory: '/home/ozzie/Development/calibre-web/pyproject.toml'-
Traceback (most recent call last): + File "/home/ozzie/Development/calibre-web-test/test/test_updater.py", line 153, in test_check_update_stable_errors + self.check_updater('Timeout', "alert", 13) + File "/home/ozzie/Development/calibre-web-test/test/test_updater.py", line 87, in check_updater + self.assertTrue(responsetext in self.check_element_on_page((By.ID, "message")).text) +AttributeError: 'bool' object has no attribute 'text'+
Traceback (most recent call last): + File "/home/ozzie/Development/calibre-web-test/test/test_updater.py", line 181, in test_check_update_stable_versions + self.check_updater('{}.{}.{}'.format(*version3), "alert-warning") + File "/home/ozzie/Development/calibre-web-test/test/test_updater.py", line 87, in check_updater + self.assertTrue(responsetext in self.check_element_on_page((By.ID, "message")).text) +AttributeError: 'bool' object has no attribute 'text'+
Traceback (most recent call last): + File "/home/ozzie/Development/calibre-web-test/test/test_updater.py", line 390, in test_perform_update + performUpdate.click() + File "/home/ozzie/Development/calibre-web-test/venv/lib/python3.10/site-packages/selenium/webdriver/remote/webelement.py", line 93, in click + self._execute(Command.CLICK_ELEMENT) + File "/home/ozzie/Development/calibre-web-test/venv/lib/python3.10/site-packages/selenium/webdriver/remote/webelement.py", line 403, in _execute + return self._parent.execute(command, params) + File "/home/ozzie/Development/calibre-web-test/venv/lib/python3.10/site-packages/selenium/webdriver/remote/webdriver.py", line 440, in execute + self.error_handler.check_response(response) + File "/home/ozzie/Development/calibre-web-test/venv/lib/python3.10/site-packages/selenium/webdriver/remote/errorhandler.py", line 245, in check_response + raise exception_class(message, screen, stacktrace) +selenium.common.exceptions.ElementNotInteractableException: Message: Element <div id="perform_update" class="btn btn-primary hidden"> could not be scrolled into view +Stacktrace: +RemoteError@chrome://remote/content/shared/RemoteError.sys.mjs:8:8 +WebDriverError@chrome://remote/content/shared/webdriver/Errors.sys.mjs:193:5 +ElementNotInteractableError@chrome://remote/content/shared/webdriver/Errors.sys.mjs:353:5 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:167:11 +interaction.clickElement@chrome://remote/content/marionette/interaction.sys.mjs:136:11 +clickElement@chrome://remote/content/marionette/actors/MarionetteCommandsChild.sys.mjs:205:29 +receiveMessage@chrome://remote/content/marionette/actors/MarionetteCommandsChild.sys.mjs:85:31+
Traceback (most recent call last): + File "/home/ozzie/Development/calibre-web-test/test/test_updater.py", line 330, in test_perform_update_stable_errors + performUpdate.click() + File "/home/ozzie/Development/calibre-web-test/venv/lib/python3.10/site-packages/selenium/webdriver/remote/webelement.py", line 93, in click + self._execute(Command.CLICK_ELEMENT) + File "/home/ozzie/Development/calibre-web-test/venv/lib/python3.10/site-packages/selenium/webdriver/remote/webelement.py", line 403, in _execute + return self._parent.execute(command, params) + File "/home/ozzie/Development/calibre-web-test/venv/lib/python3.10/site-packages/selenium/webdriver/remote/webdriver.py", line 440, in execute + self.error_handler.check_response(response) + File "/home/ozzie/Development/calibre-web-test/venv/lib/python3.10/site-packages/selenium/webdriver/remote/errorhandler.py", line 245, in check_response + raise exception_class(message, screen, stacktrace) +selenium.common.exceptions.ElementNotInteractableException: Message: Element <div id="perform_update" class="btn btn-primary hidden"> could not be scrolled into view +Stacktrace: +RemoteError@chrome://remote/content/shared/RemoteError.sys.mjs:8:8 +WebDriverError@chrome://remote/content/shared/webdriver/Errors.sys.mjs:193:5 +ElementNotInteractableError@chrome://remote/content/shared/webdriver/Errors.sys.mjs:353:5 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:167:11 +interaction.clickElement@chrome://remote/content/marionette/interaction.sys.mjs:136:11 +clickElement@chrome://remote/content/marionette/actors/MarionetteCommandsChild.sys.mjs:205:29 +receiveMessage@chrome://remote/content/marionette/actors/MarionetteCommandsChild.sys.mjs:85:31+
Traceback (most recent call last): + File "/home/ozzie/Development/calibre-web-test/test/test_updater.py", line 431, in test_update_write_protect + self.assertTrue(self.check_element_on_page((By.ID, "message"))) +AssertionError: False is not true+
Traceback (most recent call last): + File "/home/ozzie/Development/calibre-web-test/test/test_upload_epubs.py", line 88, in test_upload_epub_lang + details = self.verify_upload(epub_file, check_warning=True) + File "/home/ozzie/Development/calibre-web-test/test/test_upload_epubs.py", line 79, in verify_upload + self.assertTrue(self.check_element_on_page((By.ID, "flash_warning"))) +AssertionError: False is not true+