~cedric/newspipe

49b199c610bb32d0581d771d856b3e3332707f17 — Cédric Bonhomme 1 year, 1 month ago e62084c
Migrate form Flask-Script to the built-in integration of the click command line interface of Flask.
9 files changed, 49 insertions(+), 55 deletions(-)

M README.md
M docker-compose.yml
M newspipe/bootstrap.py
R manager.py => newspipe/commands.py
M newspipe/lib/misc_utils.py
M poetry.lock
M pyproject.toml
M runserver.py
M wait-for-postgres.sh
M README.md => README.md +14 -6
@@ 51,13 51,21 @@ $ git clone https://git.sr.ht/~cedric/newspipe
$ cd newspipe/
$ npm install
$ poetry install
$ export Newspipe_CONFIG=sqlite.py
$ poetry shell
$ pybabel compile -d newspipe/translations
$ python manager.py db_create
$ python manager.py create_admin <nickname> <password>
$ python runserver.py
  * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
$ export NEWSPIPE_CONFIG=sqlite.py
$ export FLASK_APP=runserver.py
$ export FLASK_ENV=development
$ flask db_create
$ flask create_admin --nickname <nickname> --password <password>
$ flask run
 * Serving Flask app "runserver" (lazy loading)
 * Environment: development
 * Debug mode: on
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 221-873-938
```

If you want to use PostgreSQL you can customize


@@ 67,7 75,7 @@ the provided example configuration file (``instance/config.py``):
$ sudo apt-get install postgresql
$ cp instance/config.py instance/postgresql.py
$ vim instance/postgresql.py # customize it
$ export Newspipe_CONFIG=postgresql.py
$ export NEWSPIPE_CONFIG=postgresql.py
```

For production you can use [Gunicorn](https://gunicorn.org) or ``mod_wsgi``.

M docker-compose.yml => docker-compose.yml +1 -1
@@ 22,7 22,7 @@ services:
      dockerfile: ./Dockerfile
    tty: true
    environment:
        - Newspipe_CONFIG=/newspipe/instance/config.py
        - NEWSPIPE_CONFIG=/newspipe/instance/config.py
    ports:
        - "5000:5000"
    expose:

M newspipe/bootstrap.py => newspipe/bootstrap.py +1 -1
@@ 48,7 48,7 @@ def set_logging(

# Create Flask application
application = Flask(__name__, instance_relative_config=True)
configuration = os.environ.get("Newspipe_CONFIG", False)
configuration = os.environ.get("NEWSPIPE_CONFIG", False)
if configuration == "testing":
    application.debug = logging.DEBUG
    application.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///:memory:"

R manager.py => newspipe/commands.py +11 -24
@@ 5,48 5,37 @@ import logging
import os
from datetime import datetime

from flask_migrate import Migrate, MigrateCommand
from flask_script import Manager
import click
from flask import Flask
from werkzeug.security import generate_password_hash

import newspipe.models
from newspipe.bootstrap import application, db
from newspipe.controllers import UserController

logger = logging.getLogger("manager")
logger = logging.getLogger("commands")

Migrate(application, db)

manager = Manager(application)
manager.add_command("db", MigrateCommand)


@manager.command
@application.cli.command("db_empty")
def db_empty():
    "Will drop every datas stocked in db."
    with application.app_context():
        newspipe.models.db_empty(db)


@manager.command
@application.cli.command("db_create")
def db_create():
    "Will create the database from conf parameters."
    admin = {
        "is_admin": True,
        "is_api": True,
        "is_active": True,
        "nickname": "admin",
        "pwdhash": generate_password_hash(os.environ.get("ADMIN_PASSWORD", "password")),
    }
    with application.app_context():
        try:
            db.create_all()
            UserController(ignore_context=True).create(**admin)
        except Exception as e:
            print(e)


@manager.command
@application.cli.command("create_admin")
@click.option('--nickname', default='admin', help='Nickname')
@click.option('--password', default='password', help='Password')
def create_admin(nickname, password):
    "Will create an admin user."
    admin = {


@@ 60,7 49,9 @@ def create_admin(nickname, password):
        UserController(ignore_context=True).create(**admin)


@manager.command
@application.cli.command("fetch_asyncio")
@click.option('--user-id', default=None, help='Id of the user')
@click.option('--feed-id', default=None, help='If of the feed')
def fetch_asyncio(user_id=None, feed_id=None):
    "Crawl the feeds with asyncio."
    import asyncio


@@ 92,7 83,3 @@ def fetch_asyncio(user_id=None, feed_id=None):
        end = datetime.now()
        loop.close()
        logger.info("Crawler finished in {} seconds.".format((end - start).seconds))


if __name__ == "__main__":
    manager.run()

M newspipe/lib/misc_utils.py => newspipe/lib/misc_utils.py +4 -4
@@ 101,13 101,13 @@ def fetch(id, feed_id=None):
    The default crawler ("asyncio") is launched with the manager.
    """
    cmd = [
        sys.executable,
        "manager.py",
        "poetry", "run",
        "flask",
        "fetch_asyncio",
        "--user_id=" + str(id),
        "--user-id", str(id),
    ]
    if feed_id:
        cmd.append("--feed_id=" + str(feed_id))
        cmd.extend(["--feed-id", str(feed_id)])
    return subprocess.Popen(cmd, stdout=subprocess.PIPE)



M poetry.lock => poetry.lock +1 -15
@@ 247,17 247,6 @@ docs = ["sphinx"]

[[package]]
category = "main"
description = "Scripting support for Flask"
name = "flask-script"
optional = false
python-versions = "*"
version = "2.0.6"

[package.dependencies]
Flask = "*"

[[package]]
category = "main"
description = "Adds SQLAlchemy support to your Flask application."
name = "flask-sqlalchemy"
optional = false


@@ 583,7 572,7 @@ idna = ">=2.0"
multidict = ">=4.0"

[metadata]
content-hash = "c8407863562e0f8573d3f8b8a7b1ab4b09ea3a40271ae077af278176246e934b"
content-hash = "f5e5860ca483252734221f791fc859169287b8c691ab6ee15816f79794faabcd"
python-versions = "^3.8"

[metadata.files]


@@ 679,9 668,6 @@ flask-restful = [
    {file = "Flask-RESTful-0.3.8.tar.gz", hash = "sha256:5ea9a5991abf2cb69b4aac19793faac6c032300505b325687d7c305ffaa76915"},
    {file = "Flask_RESTful-0.3.8-py2.py3-none-any.whl", hash = "sha256:d891118b951921f1cec80cabb4db98ea6058a35e6404788f9e70d5b243813ec2"},
]
flask-script = [
    {file = "Flask-Script-2.0.6.tar.gz", hash = "sha256:6425963d91054cfcc185807141c7314a9c5ad46325911bd24dcb489bd0161c65"},
]
flask-sqlalchemy = [
    {file = "Flask-SQLAlchemy-2.4.1.tar.gz", hash = "sha256:6974785d913666587949f7c2946f7001e4fa2cb2d19f4e69ead02e4b8f50b33d"},
    {file = "Flask_SQLAlchemy-2.4.1-py2.py3-none-any.whl", hash = "sha256:0078d8663330dc05a74bc72b3b6ddc441b9a744e2f56fe60af1a5bfc81334327"},

M pyproject.toml => pyproject.toml +0 -1
@@ 26,7 26,6 @@ Flask-RESTful = "^0.3.8"
Flask-paginate = "^0.5.5"
Flask-Babel = "^1.0.0"
Flask-Migrate = "^2.5.2"
Flask-Script = "^2.0.6"
WTForms = "^2.2.1"
python-dateutil = "^2.8.1"
psycopg2-binary = "^2.8.4"

M runserver.py => runserver.py +11 -0
@@ 22,6 22,15 @@ from flask import g
from flask_restful import Api

from newspipe.bootstrap import application
from newspipe import commands


def register_commands(app):
    """Register Click commands."""
    app.cli.add_command(commands.db_empty)
    app.cli.add_command(commands.db_create)
    app.cli.add_command(commands.fetch_asyncio)
    app.cli.add_command(commands.create_admin)


with application.app_context():


@@ 42,6 51,8 @@ with application.app_context():
    application.register_blueprint(views.bookmarks_bp)
    application.register_blueprint(views.bookmark_bp)

    register_commands(application)


if __name__ == "__main__":
    application.run(

M wait-for-postgres.sh => wait-for-postgres.sh +6 -3
@@ 13,7 13,10 @@ do
done

>&2 echo "Postgres is up - executing command"
export Newspipe_CONFIG=/newspipe/instance/config.py
poetry run ./manager.py db_create >/dev/null
export NEWSPIPE_CONFIG=/newspipe/instance/config.py
export FLASK_APP=runserver.py
export FLASK_ENV=development
poetry run flask db_create >/dev/null
poetry run flask create_admin --nickname admin --password password >/dev/null
poetry run pybabel compile -d newspipe/translations
poetry run ./runserver.py
poetry run flask run