mirror of
https://github.com/spiral-project/ihatemoney.git
synced 2025-04-28 17:32:38 +02:00
remove usage of Flask-Script
Use flask.cli instead with compatibility layer for existing commands, such as "runserver".
This commit is contained in:
parent
eff871e83c
commit
74e222f1a1
5 changed files with 77 additions and 89 deletions
2
Makefile
2
Makefile
|
@ -38,7 +38,7 @@ update: remove-install-stamp install ## Update the dependencies
|
||||||
.PHONY: serve
|
.PHONY: serve
|
||||||
serve: install ## Run the ihatemoney server
|
serve: install ## Run the ihatemoney server
|
||||||
@echo 'Running ihatemoney on http://localhost:5000'
|
@echo 'Running ihatemoney on http://localhost:5000'
|
||||||
$(PYTHON) -m ihatemoney.manage runserver
|
$(PYTHON) -m ihatemoney.manage run
|
||||||
|
|
||||||
.PHONY: test
|
.PHONY: test
|
||||||
test: install-dev ## Run the tests
|
test: install-dev ## Run the tests
|
||||||
|
|
|
@ -61,7 +61,7 @@ Test it
|
||||||
|
|
||||||
Once installed, you can start a test server::
|
Once installed, you can start a test server::
|
||||||
|
|
||||||
ihatemoney runserver
|
ihatemoney run
|
||||||
|
|
||||||
And point your browser at `http://localhost:5000 <http://localhost:5000>`_.
|
And point your browser at `http://localhost:5000 <http://localhost:5000>`_.
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,8 @@ import os
|
||||||
import random
|
import random
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from flask_migrate import Migrate, MigrateCommand
|
import click
|
||||||
from flask_script import Command, Manager, Option
|
from flask.cli import FlaskGroup
|
||||||
from werkzeug.security import generate_password_hash
|
from werkzeug.security import generate_password_hash
|
||||||
|
|
||||||
from ihatemoney.models import Project, db
|
from ihatemoney.models import Project, db
|
||||||
|
@ -14,31 +14,48 @@ from ihatemoney.run import create_app
|
||||||
from ihatemoney.utils import create_jinja_env
|
from ihatemoney.utils import create_jinja_env
|
||||||
|
|
||||||
|
|
||||||
class GeneratePasswordHash(Command):
|
@click.group(cls=FlaskGroup, create_app=create_app)
|
||||||
|
def cli():
|
||||||
|
"""IHateMoney Management script"""
|
||||||
|
|
||||||
|
|
||||||
|
@cli.command(
|
||||||
|
context_settings={"ignore_unknown_options": True, "allow_extra_args": True}
|
||||||
|
)
|
||||||
|
@click.pass_context
|
||||||
|
def runserver(ctx):
|
||||||
|
"""Deprecated, use the "run" command instead"""
|
||||||
|
click.secho(
|
||||||
|
'"runserver" is deprecated, please use the standard "run" flask command',
|
||||||
|
fg="red",
|
||||||
|
)
|
||||||
|
run = cli.get_command(ctx, "run")
|
||||||
|
ctx.forward(run)
|
||||||
|
|
||||||
|
|
||||||
|
@click.command(name="generate_password_hash")
|
||||||
|
def password_hash():
|
||||||
"""Get password from user and hash it without printing it in clear text."""
|
"""Get password from user and hash it without printing it in clear text."""
|
||||||
|
|
||||||
def run(self):
|
|
||||||
password = getpass.getpass(prompt="Password: ")
|
password = getpass.getpass(prompt="Password: ")
|
||||||
print(generate_password_hash(password))
|
print(generate_password_hash(password))
|
||||||
|
|
||||||
|
|
||||||
class GenerateConfig(Command):
|
@click.command()
|
||||||
def get_options(self):
|
@click.argument(
|
||||||
return [
|
|
||||||
Option(
|
|
||||||
"config_file",
|
"config_file",
|
||||||
choices=[
|
type=click.Choice(
|
||||||
|
[
|
||||||
"ihatemoney.cfg",
|
"ihatemoney.cfg",
|
||||||
"apache-vhost.conf",
|
"apache-vhost.conf",
|
||||||
"gunicorn.conf.py",
|
"gunicorn.conf.py",
|
||||||
"supervisord.conf",
|
"supervisord.conf",
|
||||||
"nginx.conf",
|
"nginx.conf",
|
||||||
],
|
|
||||||
)
|
|
||||||
]
|
]
|
||||||
|
),
|
||||||
|
)
|
||||||
|
def generate_config(config_file):
|
||||||
|
"""Generate front-end server configuration"""
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def gen_secret_key():
|
def gen_secret_key():
|
||||||
return "".join(
|
return "".join(
|
||||||
[
|
[
|
||||||
|
@ -49,7 +66,6 @@ class GenerateConfig(Command):
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
def run(self, config_file):
|
|
||||||
env = create_jinja_env("conf-templates", strict_rendering=True)
|
env = create_jinja_env("conf-templates", strict_rendering=True)
|
||||||
template = env.get_template(f"{config_file}.j2")
|
template = env.get_template(f"{config_file}.j2")
|
||||||
|
|
||||||
|
@ -61,47 +77,22 @@ class GenerateConfig(Command):
|
||||||
pkg_path=pkg_path,
|
pkg_path=pkg_path,
|
||||||
bin_path=bin_path,
|
bin_path=bin_path,
|
||||||
sys_prefix=sys.prefix,
|
sys_prefix=sys.prefix,
|
||||||
secret_key=self.gen_secret_key(),
|
secret_key=gen_secret_key(),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class DeleteProject(Command):
|
@cli.command()
|
||||||
def run(self, project_name):
|
@click.argument("project_name")
|
||||||
demo_project = Project.query.get(project_name)
|
def delete_project(project_name):
|
||||||
db.session.delete(demo_project)
|
"""Delete a project"""
|
||||||
|
project = Project.query.get(project_name)
|
||||||
|
if project is None:
|
||||||
|
click.secho(f'Project "{project_name}" not found', fg="red")
|
||||||
|
else:
|
||||||
|
db.session.delete(project)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
QUIET_COMMANDS = ("generate_password_hash", "generate-config")
|
|
||||||
|
|
||||||
exception = None
|
|
||||||
backup_stderr = sys.stderr
|
|
||||||
# Hack to divert stderr for commands generating content to stdout
|
|
||||||
# to avoid confusing the user
|
|
||||||
if len(sys.argv) > 1 and sys.argv[1] in QUIET_COMMANDS:
|
|
||||||
sys.stderr = open(os.devnull, "w")
|
|
||||||
|
|
||||||
try:
|
|
||||||
app = create_app()
|
|
||||||
Migrate(app, db)
|
|
||||||
except Exception as e:
|
|
||||||
exception = e
|
|
||||||
|
|
||||||
# Restore stderr
|
|
||||||
sys.stderr = backup_stderr
|
|
||||||
|
|
||||||
if exception:
|
|
||||||
raise exception
|
|
||||||
|
|
||||||
manager = Manager(app)
|
|
||||||
manager.add_command("db", MigrateCommand)
|
|
||||||
manager.add_command("generate_password_hash", GeneratePasswordHash)
|
|
||||||
manager.add_command("generate-config", GenerateConfig)
|
|
||||||
manager.add_command("delete-project", DeleteProject)
|
|
||||||
manager.run()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
cli()
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import io
|
|
||||||
import os
|
import os
|
||||||
import smtplib
|
import smtplib
|
||||||
import socket
|
import socket
|
||||||
|
@ -9,7 +8,7 @@ from sqlalchemy import orm
|
||||||
|
|
||||||
from ihatemoney import models
|
from ihatemoney import models
|
||||||
from ihatemoney.currency_convertor import CurrencyConverter
|
from ihatemoney.currency_convertor import CurrencyConverter
|
||||||
from ihatemoney.manage import DeleteProject, GenerateConfig, GeneratePasswordHash
|
from ihatemoney.manage import delete_project, generate_config, password_hash
|
||||||
from ihatemoney.run import load_configuration
|
from ihatemoney.run import load_configuration
|
||||||
from ihatemoney.tests.common.ihatemoney_testcase import BaseTestCase, IhatemoneyTestCase
|
from ihatemoney.tests.common.ihatemoney_testcase import BaseTestCase, IhatemoneyTestCase
|
||||||
|
|
||||||
|
@ -82,28 +81,23 @@ class CommandTestCase(BaseTestCase):
|
||||||
- raise no exception
|
- raise no exception
|
||||||
- produce something non-empty
|
- produce something non-empty
|
||||||
"""
|
"""
|
||||||
cmd = GenerateConfig()
|
runner = self.app.test_cli_runner()
|
||||||
for config_file in cmd.get_options()[0].kwargs["choices"]:
|
for config_file in generate_config.params[0].type.choices:
|
||||||
with patch("sys.stdout", new=io.StringIO()) as stdout:
|
result = runner.invoke(generate_config, config_file)
|
||||||
cmd.run(config_file)
|
self.assertNotEqual(len(result.output.strip()), 0)
|
||||||
print(stdout.getvalue())
|
|
||||||
self.assertNotEqual(len(stdout.getvalue().strip()), 0)
|
|
||||||
|
|
||||||
def test_generate_password_hash(self):
|
def test_generate_password_hash(self):
|
||||||
cmd = GeneratePasswordHash()
|
runner = self.app.test_cli_runner()
|
||||||
with patch("sys.stdout", new=io.StringIO()) as stdout, patch(
|
with patch("getpass.getpass", new=lambda prompt: "secret"):
|
||||||
"getpass.getpass", new=lambda prompt: "secret"
|
result = runner.invoke(password_hash)
|
||||||
): # NOQA
|
self.assertEqual(len(result.output.strip()), 94)
|
||||||
cmd.run()
|
|
||||||
print(stdout.getvalue())
|
|
||||||
self.assertEqual(len(stdout.getvalue().strip()), 189)
|
|
||||||
|
|
||||||
def test_demo_project_deletion(self):
|
def test_demo_project_deletion(self):
|
||||||
self.create_project("demo")
|
self.create_project("demo")
|
||||||
self.assertEquals(models.Project.query.get("demo").name, "demo")
|
self.assertEquals(models.Project.query.get("demo").name, "demo")
|
||||||
|
|
||||||
cmd = DeleteProject()
|
runner = self.app.test_cli_runner()
|
||||||
cmd.run("demo")
|
runner.invoke(delete_project, "demo")
|
||||||
|
|
||||||
self.assertEqual(len(models.Project.query.all()), 0)
|
self.assertEqual(len(models.Project.query.all()), 0)
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,6 @@ install_requires =
|
||||||
Flask-Mail~=0.9
|
Flask-Mail~=0.9
|
||||||
Flask-Migrate>=2.5.3,<3 # Not following semantic versioning (e.g. https://github.com/miguelgrinberg/flask-migrate/commit/1af28ba273de6c88544623b8dc02dd539340294b)
|
Flask-Migrate>=2.5.3,<3 # Not following semantic versioning (e.g. https://github.com/miguelgrinberg/flask-migrate/commit/1af28ba273de6c88544623b8dc02dd539340294b)
|
||||||
Flask-RESTful~=0.3
|
Flask-RESTful~=0.3
|
||||||
Flask-Script~=2.0
|
|
||||||
Flask-SQLAlchemy~=2.4
|
Flask-SQLAlchemy~=2.4
|
||||||
Flask-WTF~=0.14,>=0.14.3 # See b76da172652da94c1f9c4b2fdd965375da8a2c3f
|
Flask-WTF~=0.14,>=0.14.3 # See b76da172652da94c1f9c4b2fdd965375da8a2c3f
|
||||||
WTForms~=2.2.1,<2.3 # See #567
|
WTForms~=2.2.1,<2.3 # See #567
|
||||||
|
@ -58,8 +57,12 @@ doc =
|
||||||
docutils==0.17.1
|
docutils==0.17.1
|
||||||
|
|
||||||
[options.entry_points]
|
[options.entry_points]
|
||||||
|
flask.commands =
|
||||||
|
generate_password_hash = ihatemoney.manage:password_hash
|
||||||
|
generate-config = ihatemoney.manage:generate_config
|
||||||
|
|
||||||
console_scripts =
|
console_scripts =
|
||||||
ihatemoney = ihatemoney.manage:main
|
ihatemoney = ihatemoney.manage:cli
|
||||||
|
|
||||||
paste.app_factory =
|
paste.app_factory =
|
||||||
main = ihatemoney.run:main
|
main = ihatemoney.run:main
|
||||||
|
|
Loading…
Reference in a new issue