diff --git a/MANIFEST.in b/MANIFEST.in index d5f7c071..b667159c 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1 +1 @@ -graft src/cps +graft src/calibreweb diff --git a/README.md b/README.md index d3f112d6..f7577d4b 100644 --- a/README.md +++ b/README.md @@ -73,4 +73,4 @@ Pre-built Docker images based on Alpine Linux are available in these Docker Hub # Wiki -For further informations, How To's and FAQ please check the ![Wiki](https://github.com/janeczku/calibre-web/wiki) +For further informations, How To's and FAQ please check the [Wiki](https://github.com/janeczku/calibre-web/wiki) diff --git a/__init__.py b/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/cps/__init__.py b/cps/__init__.py index 87a9026f..dfe72e5c 100755 --- a/cps/__init__.py +++ b/cps/__init__.py @@ -20,6 +20,7 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +__all__ =['app'] import mimetypes from flask import Flask, request, g @@ -71,7 +72,7 @@ lm.anonymous_user = ub.Anonymous ub.init_db() config = Config() -import db +from . import db try: with open(os.path.join(config.get_main_dir, 'cps/translations/iso639.pickle'), 'rb') as f: @@ -83,10 +84,10 @@ except cPickle.UnpicklingError as error: searched_ids = {} -from worker import WorkerThread +from .worker import WorkerThread global_WorkerThread = WorkerThread() -from server import server +from .server import server Server = server() babel = Babel() @@ -142,5 +143,5 @@ def get_timezone(): if user is not None: return user.timezone -from updater import Updater +from .updater import Updater updater_thread = Updater() diff --git a/cps/about.py b/cps/about.py index 69deb7db..59623f16 100644 --- a/cps/about.py +++ b/cps/about.py @@ -23,9 +23,9 @@ from flask import Blueprint from flask_login import login_required -from cps import db +from . import db import sys -import uploader +from .uploader import get_versions from babel import __version__ as babelVersion from sqlalchemy import __version__ as sqlalchemyVersion from flask_principal import __version__ as flask_principalVersion @@ -34,11 +34,11 @@ from pytz import __version__ as pytzVersion from flask import __version__ as flaskVersion from werkzeug import __version__ as werkzeugVersion from jinja2 import __version__ as jinja2Version -import converter +from .converter import versioncheck from flask_babel import gettext as _ from cps import Server import requests -from web import render_title_template +from .web import render_title_template try: from flask_login import __version__ as flask_loginVersion @@ -55,7 +55,7 @@ def stats(): authors = db.session.query(db.Authors).count() categorys = db.session.query(db.Tags).count() series = db.session.query(db.Series).count() - versions = uploader.get_versions() + versions = get_versions() versions['Babel'] = 'v' + babelVersion versions['Sqlalchemy'] = 'v' + sqlalchemyVersion versions['Werkzeug'] = 'v' + werkzeugVersion @@ -69,7 +69,7 @@ def stats(): versions['Requests'] = 'v' + requests.__version__ versions['pySqlite'] = 'v' + db.engine.dialect.dbapi.version versions['Sqlite'] = 'v' + db.engine.dialect.dbapi.sqlite_version - versions.update(converter.versioncheck()) + versions.update(versioncheck()) versions.update(Server.getNameVersion()) versions['Python'] = sys.version return render_title_template('stats.html', bookcounter=counter, authorcounter=authors, versions=versions, diff --git a/cps/admin.py b/cps/admin.py index 6aca350a..305dd9e3 100644 --- a/cps/admin.py +++ b/cps/admin.py @@ -25,9 +25,9 @@ import os from flask import Blueprint, flash, redirect, url_for from flask import abort, request, make_response from flask_login import login_required, current_user, logout_user -from web import admin_required, render_title_template, before_request, unconfigured, \ +from .web import admin_required, render_title_template, before_request, unconfigured, \ login_required_if_no_ano -from cps import db, ub, Server, get_locale, config, app, updater_thread, babel +from . import db, ub, Server, get_locale, config, app, updater_thread, babel import json from datetime import datetime, timedelta import time @@ -35,9 +35,9 @@ from babel.dates import format_datetime from flask_babel import gettext as _ from babel import Locale as LC from sqlalchemy.exc import IntegrityError -from gdriveutils import is_gdrive_ready, gdrive_support, downloadFile, deleteDatabaseOnChange, listRootFolders -import helper -from helper import speaking_language, check_valid_domain +from .gdriveutils import is_gdrive_ready, gdrive_support, downloadFile, deleteDatabaseOnChange, listRootFolders +from .helper import speaking_language, check_valid_domain, check_unrar, send_test_mail, generate_random_password, \ + send_registration_mail from werkzeug.security import generate_password_hash try: from imp import reload @@ -467,7 +467,7 @@ def configuration_helper(origin): # Rarfile Content configuration if "config_rarfile_location" in to_save and to_save['config_rarfile_location'] is not u"": - check = helper.check_unrar(to_save["config_rarfile_location"].strip()) + check = check_unrar(to_save["config_rarfile_location"].strip()) if not check[0] : content.config_rarfile_location = to_save["config_rarfile_location"].strip() else: @@ -486,7 +486,6 @@ def configuration_helper(origin): flash(_(u"Calibre-Web configuration updated"), category="success") config.loadSettings() app.logger.setLevel(config.config_log_level) - # logging.getLogger("uploader").setLevel(config.config_log_level) except Exception as e: flash(e, category="error") return render_title_template("config_edit.html", config=config, origin=origin, @@ -602,7 +601,7 @@ def edit_mailsettings(): flash(e, category="error") if "test" in to_save and to_save["test"]: if current_user.kindle_mail: - result = helper.send_test_mail(current_user.kindle_mail, current_user.nickname) + result = send_test_mail(current_user.kindle_mail, current_user.nickname) if result is None: flash(_(u"Test e-mail successfully send to %(kindlemail)s", kindlemail=current_user.kindle_mail), category="success") @@ -725,11 +724,11 @@ def reset_password(user_id): abort(404) if current_user is not None and current_user.is_authenticated: existing_user = ub.session.query(ub.User).filter(ub.User.id == user_id).first() - password = helper.generate_random_password() + password = generate_random_password() existing_user.password = generate_password_hash(password) try: ub.session.commit() - helper.send_registration_mail(existing_user.email, existing_user.nickname, password, True) + send_registration_mail(existing_user.email, existing_user.nickname, password, True) flash(_(u"Password for user %(user)s reset", user=existing_user.nickname), category="success") except Exception: ub.session.rollback() diff --git a/cps/cli.py b/cps/cli.py index bb404bde..0495b313 100644 --- a/cps/cli.py +++ b/cps/cli.py @@ -26,8 +26,10 @@ parser = argparse.ArgumentParser(description='Calibre Web is a web app' ' providing a interface for browsing, reading and downloading eBooks\n', prog='cps.py') parser.add_argument('-p', metavar='path', help='path and name to settings db, e.g. /opt/cw.db') parser.add_argument('-g', metavar='path', help='path and name to gdrive db, e.g. /opt/gd.db') -parser.add_argument('-c', metavar='path', help='path and name to SSL certfile, e.g. /opt/test.cert, works only in combination with keyfile') -parser.add_argument('-k', metavar='path', help='path and name to SSL keyfile, e.g. /opt/test.key, works only in combination with certfile') +parser.add_argument('-c', metavar='path', + help='path and name to SSL certfile, e.g. /opt/test.cert, works only in combination with keyfile') +parser.add_argument('-k', metavar='path', + help='path and name to SSL keyfile, e.g. /opt/test.key, works only in combination with certfile') parser.add_argument('-v', action='store_true', help='shows version number and exits Calibre-web') args = parser.parse_args() diff --git a/cps/comic.py b/cps/comic.py index 1ddb7194..b68e638d 100755 --- a/cps/comic.py +++ b/cps/comic.py @@ -18,7 +18,7 @@ # along with this program. If not, see . import os -from cps import uploader +from constants import BookMeta from cps import app from iso639 import languages as isoLanguages @@ -94,7 +94,7 @@ def get_comic_info(tmp_file_path, original_file_name, original_file_extension): else: loadedMetadata.language = "" - return uploader.BookMeta( + return BookMeta( file_path=tmp_file_path, extension=original_file_extension, title=loadedMetadata.title or original_file_name, @@ -107,7 +107,7 @@ def get_comic_info(tmp_file_path, original_file_name, original_file_extension): languages=loadedMetadata.language) else: - return uploader.BookMeta( + return BookMeta( file_path=tmp_file_path, extension=original_file_extension, title=original_file_name, diff --git a/cps/constants.py b/cps/constants.py new file mode 100644 index 00000000..9e89f70f --- /dev/null +++ b/cps/constants.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# This file is part of the Calibre-Web (https://github.com/janeczku/calibre-web) +# Copyright (C) 2019 OzzieIsaacs +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from collections import namedtuple + +""" + :rtype: BookMeta +""" +BookMeta = namedtuple('BookMeta', 'file_path, extension, title, author, cover, description, tags, series, ' + 'series_id, languages') diff --git a/cps/converter.py b/cps/converter.py index e1012448..d538619d 100644 --- a/cps/converter.py +++ b/cps/converter.py @@ -24,7 +24,7 @@ import ub import re from flask_babel import gettext as _ from subproc_wrapper import process_open -from cps import config +from . import config def versionKindle(): diff --git a/cps/db.py b/cps/db.py index b220dcf2..07ff54f7 100755 --- a/cps/db.py +++ b/cps/db.py @@ -24,7 +24,7 @@ from sqlalchemy.orm import * import os import re import ast -from cps import config +from . import config import ub import sys import unidecode diff --git a/cps/editbooks.py b/cps/editbooks.py index 249e706c..0cab9e23 100644 --- a/cps/editbooks.py +++ b/cps/editbooks.py @@ -22,7 +22,7 @@ # along with this program. If not, see . # opds routing functions -from cps import config, language_table, get_locale, app, ub, global_WorkerThread, db +from . import config, language_table, get_locale, app, ub, global_WorkerThread, db from flask import request, flash, redirect, url_for, abort, Markup, Response from flask import Blueprint import datetime @@ -30,14 +30,14 @@ import os import json from flask_babel import gettext as _ from uuid import uuid4 -import helper -from helper import order_authors, common_filters +from . import helper +from .helper import order_authors, common_filters from flask_login import current_user -from web import login_required_if_no_ano, render_title_template, edit_required, \ +from .web import login_required_if_no_ano, render_title_template, edit_required, \ upload_required, login_required, EXTENSIONS_UPLOAD -import gdriveutils +from . import gdriveutils from shutil import move, copyfile -import uploader +from . import uploader from iso639 import languages as isoLanguages editbook = Blueprint('editbook', __name__) diff --git a/cps/epub.py b/cps/epub.py index 913feaca..68325089 100644 --- a/cps/epub.py +++ b/cps/epub.py @@ -20,7 +20,7 @@ import zipfile from lxml import etree import os -import uploader +from .constants import BookMeta import isoLanguages diff --git a/cps/fb2.py b/cps/fb2.py index adcac758..4f113383 100644 --- a/cps/fb2.py +++ b/cps/fb2.py @@ -18,7 +18,7 @@ # along with this program. If not, see . from lxml import etree -import uploader +from .constants import BookMeta def get_fb2_info(tmp_file_path, original_file_extension): @@ -66,7 +66,7 @@ def get_fb2_info(tmp_file_path, original_file_extension): else: description = u'' - return uploader.BookMeta( + return BookMeta( file_path=tmp_file_path, extension=original_file_extension, title=title.decode('utf-8'), diff --git a/cps/gdrive.py b/cps/gdrive.py index 025c2d65..b4749aa1 100644 --- a/cps/gdrive.py +++ b/cps/gdrive.py @@ -22,17 +22,17 @@ # along with this program. If not, see . import os from flask import Blueprint -import gdriveutils +from . import gdriveutils from flask import flash, request, redirect, url_for, abort from flask_babel import gettext as _ -from cps import app, config, ub, db +from . import app, config, ub, db from flask_login import login_required import json from uuid import uuid4 from time import time import tempfile from shutil import move, copyfile -from web import admin_required +from .web import admin_required try: from googleapiclient.errors import HttpError diff --git a/cps/gdriveutils.py b/cps/gdriveutils.py index ca974b82..c4b32e95 100644 --- a/cps/gdriveutils.py +++ b/cps/gdriveutils.py @@ -27,7 +27,7 @@ except ImportError: gdrive_support = False import os -from cps import config, app +from . import config, app import cli import shutil from flask import Response, stream_with_context diff --git a/cps/helper.py b/cps/helper.py index 4fb6077a..2ff6515d 100644 --- a/cps/helper.py +++ b/cps/helper.py @@ -19,7 +19,7 @@ # along with this program. If not, see . -from cps import config, global_WorkerThread, get_locale, db, mimetypes +from . import config, global_WorkerThread, get_locale, db, mimetypes from flask import current_app as app from tempfile import gettempdir import sys @@ -27,7 +27,8 @@ import io import os import re import unicodedata -import worker +from .worker import STAT_WAITING, STAT_FAIL, STAT_STARTED, STAT_FINISH_SUCCESS, TASK_EMAIL, TASK_CONVERT, TASK_UPLOAD, \ + TASK_CONVERT_ANY import time from flask import send_from_directory, make_response, redirect, abort from flask_babel import gettext as _ @@ -610,26 +611,26 @@ def render_task_status(tasklist): # localize the task status if isinstance( task['stat'], int ): - if task['stat'] == worker.STAT_WAITING: + if task['stat'] == STAT_WAITING: task['status'] = _(u'Waiting') - elif task['stat'] == worker.STAT_FAIL: + elif task['stat'] == STAT_FAIL: task['status'] = _(u'Failed') - elif task['stat'] == worker.STAT_STARTED: + elif task['stat'] == STAT_STARTED: task['status'] = _(u'Started') - elif task['stat'] == worker.STAT_FINISH_SUCCESS: + elif task['stat'] == STAT_FINISH_SUCCESS: task['status'] = _(u'Finished') else: task['status'] = _(u'Unknown Status') # localize the task type if isinstance( task['taskType'], int ): - if task['taskType'] == worker.TASK_EMAIL: + if task['taskType'] == TASK_EMAIL: task['taskMessage'] = _(u'E-mail: ') + task['taskMess'] - elif task['taskType'] == worker.TASK_CONVERT: + elif task['taskType'] == TASK_CONVERT: task['taskMessage'] = _(u'Convert: ') + task['taskMess'] - elif task['taskType'] == worker.TASK_UPLOAD: + elif task['taskType'] == TASK_UPLOAD: task['taskMessage'] = _(u'Upload: ') + task['taskMess'] - elif task['taskType'] == worker.TASK_CONVERT_ANY: + elif task['taskType'] == TASK_CONVERT_ANY: task['taskMessage'] = _(u'Convert: ') + task['taskMess'] else: task['taskMessage'] = _(u'Unknown Task: ') + task['taskMess'] diff --git a/cps/jinjia.py b/cps/jinjia.py index 5aaa9a61..480ae274 100644 --- a/cps/jinjia.py +++ b/cps/jinjia.py @@ -26,9 +26,10 @@ from flask import Blueprint, request, url_for import datetime import re -from cps import mimetypes +from . import mimetypes, app from babel.dates import format_date from flask_babel import get_locale +from flask_login import current_user jinjia = Blueprint('jinjia', __name__) @@ -78,7 +79,8 @@ def formatdate_filter(val): formatdate = datetime.datetime.strptime(conformed_timestamp[:15], "%Y%m%d %H%M%S") return format_date(formatdate, format='medium', locale=get_locale()) except AttributeError as e: - app.logger.error('Babel error: %s, Current user locale: %s, Current User: %s' % (e, current_user.locale, current_user.nickname)) + app.logger.error('Babel error: %s, Current user locale: %s, Current User: %s' % + (e, current_user.locale, current_user.nickname)) return formatdate @jinjia.app_template_filter('formatdateinput') diff --git a/cps/opds.py b/cps/opds.py index a7a75de9..86b24ab6 100644 --- a/cps/opds.py +++ b/cps/opds.py @@ -22,7 +22,7 @@ # along with this program. If not, see . # opds routing functions -from cps import config, db +from . import config, db from flask import request, render_template, Response, g, make_response from pagination import Pagination from flask import Blueprint @@ -30,11 +30,10 @@ import datetime import ub from flask_login import current_user from functools import wraps -from web import login_required_if_no_ano, common_filters, get_search_results, render_read_books, download_required +from .web import login_required_if_no_ano, common_filters, get_search_results, render_read_books, download_required from sqlalchemy.sql.expression import func, text -import helper from werkzeug.security import check_password_hash -from helper import fill_indexpage +from .helper import fill_indexpage, get_download_link, get_book_cover import sys opds = Blueprint('opds', __name__) @@ -253,7 +252,7 @@ def feed_shelf(book_id): @requires_basic_auth_if_no_ano @download_required def opds_download_link(book_id, book_format): - return helper.get_download_link(book_id,book_format) + return get_download_link(book_id,book_format) @opds.route("/ajax/book/") @@ -308,7 +307,7 @@ def render_xml_template(*args, **kwargs): @opds.route("/opds/cover/") @requires_basic_auth_if_no_ano def feed_get_cover(book_id): - return helper.get_book_cover(book_id) + return get_book_cover(book_id) @opds.route("/opds/readbooks/") @requires_basic_auth_if_no_ano diff --git a/cps/server.py b/cps/server.py index 016689cc..f104203a 100644 --- a/cps/server.py +++ b/cps/server.py @@ -22,7 +22,7 @@ from socket import error as SocketError import sys import os import signal -from cps import config, global_WorkerThread +from . import config, global_WorkerThread try: from gevent.pywsgi import WSGIServer diff --git a/cps/shelf.py b/cps/shelf.py index f7f27755..1a926b0e 100644 --- a/cps/shelf.py +++ b/cps/shelf.py @@ -22,11 +22,11 @@ # along with this program. If not, see . from flask import Blueprint, request, flash, redirect, url_for -from cps import ub, searched_ids, app, db +from . import ub, searched_ids, app, db from flask_babel import gettext as _ from sqlalchemy.sql.expression import func, or_ from flask_login import login_required, current_user -from web import render_title_template +from .web import render_title_template shelf = Blueprint('shelf', __name__) diff --git a/cps/updater.py b/cps/updater.py index 12693623..107c7da7 100644 --- a/cps/updater.py +++ b/cps/updater.py @@ -18,7 +18,7 @@ # along with this program. If not, see . -from cps import config, get_locale, Server, app +from . import config, get_locale, Server, app import threading import zipfile import requests diff --git a/cps/uploader.py b/cps/uploader.py index 8886bba1..235c215c 100644 --- a/cps/uploader.py +++ b/cps/uploader.py @@ -17,14 +17,13 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -# import os + from tempfile import gettempdir import hashlib -from collections import namedtuple import os from flask_babel import gettext as _ -from cps import comic -from cps import app +import comic +from . import app try: from lxml.etree import LXML_VERSION as lxmlversion @@ -72,13 +71,8 @@ except ImportError: use_PIL = False -__author__ = 'lemmsh' - -BookMeta = namedtuple('BookMeta', 'file_path, extension, title, author, cover, description, tags, series, series_id, languages') -""" - :rtype: BookMeta -""" +__author__ = 'lemmsh' def process(tmp_file_path, original_file_name, original_file_extension): diff --git a/cps/web.py b/cps/web.py index 503229e9..f02c6006 100644 --- a/cps/web.py +++ b/cps/web.py @@ -21,8 +21,8 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -from cps import mimetypes, global_WorkerThread, searched_ids, lm, babel, ub, config, get_locale, language_table, app, db -from helper import common_filters, get_search_results, fill_indexpage, speaking_language, check_valid_domain, \ +from . import mimetypes, global_WorkerThread, searched_ids, lm, babel, ub, config, get_locale, language_table, app, db +from .helper import common_filters, get_search_results, fill_indexpage, speaking_language, check_valid_domain, \ order_authors, get_typeahead, render_task_status, json_serial, get_unique_other_books, get_cc_columns, \ get_book_cover, get_download_link, send_mail, generate_random_password, send_registration_mail, \ check_send_to_kindle, check_read_formats, lcase @@ -44,7 +44,7 @@ import os.path import json import datetime import isoLanguages -import gdriveutils +from .gdriveutils import getFileFromEbooksFolder, do_gdrive_download feature_support = dict() @@ -995,8 +995,8 @@ def serve_book(book_id, book_format): headers["Content-Type"] = mimetypes.types_map['.' + book_format] except KeyError: headers["Content-Type"] = "application/octet-stream" - df = gdriveutils.getFileFromEbooksFolder(book.path, data.name + "." + book_format) - return gdriveutils.do_gdrive_download(df, headers) + df = getFileFromEbooksFolder(book.path, data.name + "." + book_format) + return do_gdrive_download(df, headers) else: return send_from_directory(os.path.join(config.config_calibre_dir, book.path), data.name + "." + book_format) diff --git a/cps/worker.py b/cps/worker.py index f00baa2e..8da30885 100644 --- a/cps/worker.py +++ b/cps/worker.py @@ -27,11 +27,11 @@ import socket import sys import os from email.generator import Generator -from cps import config, db, app +from . import config, db, app from flask_babel import gettext as _ import re -import gdriveutils as gd -from subproc_wrapper import process_open +from .gdriveutils import getFileFromEbooksFolder, updateGdriveCalibreFromLocal +from .subproc_wrapper import process_open try: from StringIO import StringIO @@ -70,7 +70,7 @@ def get_attachment(bookpath, filename): """Get file as MIMEBase message""" calibrepath = config.config_calibre_dir if config.config_use_google_drive: - df = gd.getFileFromEbooksFolder(bookpath, filename) + df = getFileFromEbooksFolder(bookpath, filename) if df: datafile = os.path.join(calibrepath, bookpath, filename) if not os.path.exists(os.path.join(calibrepath, bookpath)): @@ -236,7 +236,7 @@ class WorkerThread(threading.Thread): filename = self._convert_ebook_format() if filename: if config.config_use_google_drive: - gd.updateGdriveCalibreFromLocal() + updateGdriveCalibreFromLocal() if curr_task == TASK_CONVERT: self.add_email(self.queue[self.current]['settings']['subject'], self.queue[self.current]['path'], filename, self.queue[self.current]['settings'], self.queue[self.current]['kindle'], diff --git a/setup.cfg b/setup.cfg index 7975d6ed..12008482 100644 --- a/setup.cfg +++ b/setup.cfg @@ -2,8 +2,8 @@ universal = 1 [metadata] -name = calibre-web -version= 0.6.4 Beta +name = calibro-web +version= 0.6.6 Beta url = https://github.com/janeczku/calibre-web project_urls = Bug Tracker = https://github.com/janeczku/calibre-web/issues @@ -33,15 +33,13 @@ keywords = calibre-web library -[entry_points] +[options.entry_points] console_scripts = - calibre-web=src.cps:main - + cps = calibreweb:main [options] python_requires = >=2.6 package_dir= =src -packages = cps include_package_data = True zip_safe = False install_requires = diff --git a/setup.py b/setup.py index 1b0138a4..4fc653b0 100644 --- a/setup.py +++ b/setup.py @@ -21,4 +21,5 @@ from setuptools import setup -setup() +setup( + package_dir = {'': 'src'})