From 9f56dccdee1d801f803d3c12dab0745749374e70 Mon Sep 17 00:00:00 2001 From: Leo Hemsted Date: Mon, 6 Nov 2017 12:34:29 +0000 Subject: [PATCH] Remove flask-script, move commands to click click (http://click.pocoo.org/) is used by flask to run its cli args. In removing flask_script (it's unmaintained), we had to migrate all our commands to use click. This is a change for the better in my eyes - you don't need to define the command in several places, and it makes managing options a bit easier. View diff with whitespace turned off unless you're a masochist. --- README.md | 3 + app/__ | 0 app/__init__.py | 14 +- app/commands.py | 559 ++++++++++++++++++++++----------------------- application.py | 38 +-- requirements.txt | 1 - run_celery.py | 6 +- scripts/run_app.sh | 2 +- server_commands.py | 8 +- 9 files changed, 300 insertions(+), 331 deletions(-) create mode 100644 app/__ diff --git a/README.md b/README.md index 8252c9bbf..c5737e8d8 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,9 @@ export FIRETEXT_API_KEY='FIRETEXT_ACTUAL_KEY' export STATSD_PREFIX='YOU_OWN_PREFIX' export NOTIFICATION_QUEUE_PREFIX='YOUR_OWN_PREFIX' export REDIS_URL="redis://localhost:6379/0" +export FLASK_APP=application.py +export FLASK_DEBUG=1 +export WERKZEUG_DEBUG_PIN=off "> environment.sh ``` diff --git a/app/__ b/app/__ new file mode 100644 index 000000000..e69de29bb diff --git a/app/__init__.py b/app/__init__.py index d4e9c8136..a1172736e 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -6,6 +6,7 @@ import uuid from flask import Flask, _request_ctx_stack, request, g, jsonify from flask_sqlalchemy import SQLAlchemy from flask_marshmallow import Marshmallow +from flask_migrate import Migrate from monotonic import monotonic from notifications_utils.clients.statsd.statsd_client import StatsdClient from notifications_utils.clients.redis.redis_client import RedisClient @@ -25,6 +26,7 @@ DATETIME_FORMAT = "%Y-%m-%dT%H:%M:%S.%fZ" DATE_FORMAT = "%Y-%m-%d" db = SQLAlchemy() +migrate = Migrate() ma = Marshmallow() notify_celery = NotifyCelery() firetext_client = FiretextClient() @@ -42,21 +44,19 @@ api_user = LocalProxy(lambda: _request_ctx_stack.top.api_user) authenticated_service = LocalProxy(lambda: _request_ctx_stack.top.authenticated_service) -def create_app(app_name=None): - application = Flask(__name__) - +def create_app(application): from app.config import configs notify_environment = os.environ['NOTIFY_ENVIRONMENT'] application.config.from_object(configs[notify_environment]) - if app_name: - application.config['NOTIFY_APP_NAME'] = app_name + application.config['NOTIFY_APP_NAME'] = application.name init_app(application) request_helper.init_app(application) db.init_app(application) + migrate.init_app(application, db=db) ma.init_app(application) statsd_client.init_app(application) logging.init_app(application, statsd_client) @@ -73,6 +73,10 @@ def create_app(app_name=None): register_blueprint(application) register_v2_blueprints(application) + # avoid circular imports by importing this file later 😬 + from app.commands import setup_commands + setup_commands(application) + return application diff --git a/app/commands.py b/app/commands.py index f1e125e01..d4be9d23a 100644 --- a/app/commands.py +++ b/app/commands.py @@ -1,7 +1,9 @@ import uuid from datetime import datetime, timedelta from decimal import Decimal -from flask_script import Command, Option + +from flask import current_app +import click from app import db from app.dao.monthly_billing_dao import ( @@ -14,181 +16,152 @@ from app.dao.services_dao import ( delete_service_and_all_associated_db_objects, dao_fetch_all_services_by_user ) -from app.dao.provider_rates_dao import create_provider_rates +from app.dao.provider_rates_dao import create_provider_rates as dao_create_provider_rates from app.dao.users_dao import (delete_model_user, delete_user_verify_codes) from app.utils import get_midnight_for_day_before, get_london_midnight_in_utc from app.performance_platform.processing_time import send_processing_time_for_start_and_end -class CreateProviderRateCommand(Command): +commands = click.Group(name='commands', help='Additional commands') - option_list = ( - Option('-p', '--provider_name', dest="provider_name", help='Provider name'), - Option('-c', '--cost', dest="cost", help='Cost (pence) per message including decimals'), - Option('-d', '--valid_from', dest="valid_from", help="Date (%Y-%m-%dT%H:%M:%S) valid from") - ) - def run(self, provider_name, cost, valid_from): - if provider_name not in PROVIDERS: - raise Exception("Invalid provider name, must be one of ({})".format(', '.join(PROVIDERS))) +@commands.command() +@click.option('-p', '--provider_name', required=True, help='Provider name') +@click.option('-c', '--cost', required=True, help='Cost (pence) per message including decimals') +@click.option('-d', '--valid_from', required=True, help="Date (%Y-%m-%dT%H:%M:%S) valid from") +def create_provider_rates(provider_name, cost, valid_from): + if provider_name not in PROVIDERS: + raise Exception("Invalid provider name, must be one of ({})".format(', '.join(PROVIDERS))) + try: + cost = Decimal(cost) + except: + raise Exception("Invalid cost value.") + + try: + valid_from = datetime.strptime('%Y-%m-%dT%H:%M:%S', valid_from) + except: + raise Exception("Invalid valid_from date. Use the format %Y-%m-%dT%H:%M:%S") + + dao_create_provider_rates(provider_name, valid_from, cost) + + +@commands.command() +@click.option('-u', '--user_email_prefix', required=True, help="Functional test user email prefix.") +def purge_functional_test_data(user_email_prefix): + users = User.query.filter(User.email_address.like("{}%".format(user_email_prefix))).all() + for usr in users: + # Make sure the full email includes a uuid in it + # Just in case someone decides to use a similar email address. try: - cost = Decimal(cost) - except: - raise Exception("Invalid cost value.") - - try: - valid_from = datetime.strptime('%Y-%m-%dT%H:%M:%S', valid_from) - except: - raise Exception("Invalid valid_from date. Use the format %Y-%m-%dT%H:%M:%S") - - create_provider_rates(provider_name, valid_from, cost) - - -class PurgeFunctionalTestDataCommand(Command): - - option_list = ( - Option('-u', '-user-email-prefix', dest='user_email_prefix', help="Functional test user email prefix."), - ) - - def run(self, user_email_prefix=None): - if user_email_prefix: - users = User.query.filter(User.email_address.like("{}%".format(user_email_prefix))).all() - for usr in users: - # Make sure the full email includes a uuid in it - # Just in case someone decides to use a similar email address. - try: - uuid.UUID(usr.email_address.split("@")[0].split('+')[1]) - except ValueError: - print("Skipping {} as the user email doesn't contain a UUID.".format(usr.email_address)) - else: - services = dao_fetch_all_services_by_user(usr.id) - if services: - for service in services: - delete_service_and_all_associated_db_objects(service) - else: - delete_user_verify_codes(usr) - delete_model_user(usr) - - -class CustomDbScript(Command): - - option_list = ( - Option('-n', '-name-of-db-function', dest='name_of_db_function', help="Function name of the DB script to run"), - ) - - def run(self, name_of_db_function): - db_function = getattr(self, name_of_db_function, None) - if callable(db_function): - db_function() + uuid.UUID(usr.email_address.split("@")[0].split('+')[1]) + except ValueError: + print("Skipping {} as the user email doesn't contain a UUID.".format(usr.email_address)) else: - print('The specified function does not exist.') + services = dao_fetch_all_services_by_user(usr.id) + if services: + for service in services: + delete_service_and_all_associated_db_objects(service) + else: + delete_user_verify_codes(usr) + delete_model_user(usr) - def backfill_notification_statuses(self): - """ - This will be used to populate the new `Notification._status_fkey` with the old - `Notification._status_enum` - """ - LIMIT = 250000 - subq = "SELECT id FROM notification_history WHERE notification_status is NULL LIMIT {}".format(LIMIT) - update = "UPDATE notification_history SET notification_status = status WHERE id in ({})".format(subq) + +@commands.command() +def backfill_notification_statuses(): + """ + This will be used to populate the new `Notification._status_fkey` with the old + `Notification._status_enum` + """ + LIMIT = 250000 + subq = "SELECT id FROM notification_history WHERE notification_status is NULL LIMIT {}".format(LIMIT) + update = "UPDATE notification_history SET notification_status = status WHERE id in ({})".format(subq) + result = db.session.execute(subq).fetchall() + + while len(result) > 0: + db.session.execute(update) + print('commit {} updates at {}'.format(LIMIT, datetime.utcnow())) + db.session.commit() result = db.session.execute(subq).fetchall() - while len(result) > 0: - db.session.execute(update) - print('commit {} updates at {}'.format(LIMIT, datetime.utcnow())) - db.session.commit() - result = db.session.execute(subq).fetchall() - def update_notification_international_flag(self): - # 250,000 rows takes 30 seconds to update. - subq = "select id from notifications where international is null limit 250000" - update = "update notifications set international = False where id in ({})".format(subq) +@commands.command() +def update_notification_international_flag(): + # 250,000 rows takes 30 seconds to update. + subq = "select id from notifications where international is null limit 250000" + update = "update notifications set international = False where id in ({})".format(subq) + result = db.session.execute(subq).fetchall() + + while len(result) > 0: + db.session.execute(update) + print('commit 250000 updates at {}'.format(datetime.utcnow())) + db.session.commit() result = db.session.execute(subq).fetchall() - while len(result) > 0: - db.session.execute(update) - print('commit 250000 updates at {}'.format(datetime.utcnow())) - db.session.commit() - result = db.session.execute(subq).fetchall() - - # Now update notification_history - subq_history = "select id from notification_history where international is null limit 250000" - update_history = "update notification_history set international = False where id in ({})".format(subq_history) + # Now update notification_history + subq_history = "select id from notification_history where international is null limit 250000" + update_history = "update notification_history set international = False where id in ({})".format(subq_history) + result_history = db.session.execute(subq_history).fetchall() + while len(result_history) > 0: + db.session.execute(update_history) + print('commit 250000 updates at {}'.format(datetime.utcnow())) + db.session.commit() result_history = db.session.execute(subq_history).fetchall() - while len(result_history) > 0: - db.session.execute(update_history) - print('commit 250000 updates at {}'.format(datetime.utcnow())) - db.session.commit() - result_history = db.session.execute(subq_history).fetchall() - def fix_notification_statuses_not_in_sync(self): - """ - This will be used to correct an issue where Notification._status_enum and NotificationHistory._status_fkey - became out of sync. See 979e90a. - Notification._status_enum is the source of truth so NotificationHistory._status_fkey will be updated with - these values. - """ - MAX = 10000 +@commands.command() +def fix_notification_statuses_not_in_sync(): + """ + This will be used to correct an issue where Notification._status_enum and NotificationHistory._status_fkey + became out of sync. See 979e90a. - subq = "SELECT id FROM notifications WHERE cast (status as text) != notification_status LIMIT {}".format(MAX) - update = "UPDATE notifications SET notification_status = status WHERE id in ({})".format(subq) + Notification._status_enum is the source of truth so NotificationHistory._status_fkey will be updated with + these values. + """ + MAX = 10000 + + subq = "SELECT id FROM notifications WHERE cast (status as text) != notification_status LIMIT {}".format(MAX) + update = "UPDATE notifications SET notification_status = status WHERE id in ({})".format(subq) + result = db.session.execute(subq).fetchall() + + while len(result) > 0: + db.session.execute(update) + print('Committed {} updates at {}'.format(len(result), datetime.utcnow())) + db.session.commit() result = db.session.execute(subq).fetchall() - while len(result) > 0: - db.session.execute(update) - print('Committed {} updates at {}'.format(len(result), datetime.utcnow())) - db.session.commit() - result = db.session.execute(subq).fetchall() + subq_hist = "SELECT id FROM notification_history WHERE cast (status as text) != notification_status LIMIT {}" \ + .format(MAX) + update = "UPDATE notification_history SET notification_status = status WHERE id in ({})".format(subq_hist) + result = db.session.execute(subq_hist).fetchall() - subq_hist = "SELECT id FROM notification_history WHERE cast (status as text) != notification_status LIMIT {}" \ - .format(MAX) - update = "UPDATE notification_history SET notification_status = status WHERE id in ({})".format(subq_hist) + while len(result) > 0: + db.session.execute(update) + print('Committed {} updates at {}'.format(len(result), datetime.utcnow())) + db.session.commit() result = db.session.execute(subq_hist).fetchall() - while len(result) > 0: - db.session.execute(update) - print('Committed {} updates at {}'.format(len(result), datetime.utcnow())) - db.session.commit() - result = db.session.execute(subq_hist).fetchall() - def link_inbound_numbers_to_service(self): - update = """ - UPDATE inbound_numbers SET - service_id = services.id, - updated_at = now() - FROM services - WHERE services.sms_sender = inbound_numbers.number AND - inbound_numbers.service_id is null - """ - result = db.session.execute(update) - db.session.commit() +@commands.command() +def link_inbound_numbers_to_service(): + update = """ + UPDATE inbound_numbers SET + service_id = services.id, + updated_at = now() + FROM services + WHERE services.sms_sender = inbound_numbers.number AND + inbound_numbers.service_id is null + """ + result = db.session.execute(update) + db.session.commit() - print("Linked {} inbound numbers to service".format(result.rowcount)) + print("Linked {} inbound numbers to service".format(result.rowcount)) -class PopulateMonthlyBilling(Command): - option_list = ( - Option('-y', '-year', dest="year", help="Use for integer value for year, e.g. 2017"), - ) - - def run(self, year): - service_ids = get_service_ids_that_need_billing_populated( - start_date=datetime(2016, 5, 1), end_date=datetime(2017, 8, 16) - ) - start, end = 1, 13 - if year == '2016': - start = 4 - - for service_id in service_ids: - print('Starting to populate data for service {}'.format(str(service_id))) - print('Starting populating monthly billing for {}'.format(year)) - for i in range(start, end): - print('Population for {}-{}'.format(i, year)) - self.populate(service_id, year, i) - - def populate(self, service_id, year, month): +@commands.command() +@click.option('-y', '--year', required=True, help="Use for integer value for year, e.g. 2017") +def populate_monthly_billing(year): + def populate(service_id, year, month): create_or_update_monthly_billing(service_id, datetime(int(year), int(month), 1)) sms_res = get_monthly_billing_by_notification_type( service_id, datetime(int(year), int(month), 1), SMS_TYPE @@ -200,165 +173,181 @@ class PopulateMonthlyBilling(Command): print('SMS: {}'.format(sms_res.monthly_totals)) print('Email: {}'.format(email_res.monthly_totals)) - -class BackfillProcessingTime(Command): - option_list = ( - Option('-s', '--start_date', dest='start_date', help="Date (%Y-%m-%d) start date inclusive"), - Option('-e', '--end_date', dest='end_date', help="Date (%Y-%m-%d) end date inclusive"), + service_ids = get_service_ids_that_need_billing_populated( + start_date=datetime(2016, 5, 1), end_date=datetime(2017, 8, 16) ) + start, end = 1, 13 - def run(self, start_date, end_date): - start_date = datetime.strptime(start_date, '%Y-%m-%d') - end_date = datetime.strptime(end_date, '%Y-%m-%d') + if year == '2016': + start = 4 - delta = end_date - start_date - - print('Sending notification processing-time data for all days between {} and {}'.format(start_date, end_date)) - - for i in range(delta.days + 1): - # because the tz conversion funcs talk about midnight, and the midnight before last, - # we want to pretend we're running this from the next morning, so add one. - process_date = start_date + timedelta(days=i + 1) - - process_start_date = get_midnight_for_day_before(process_date) - process_end_date = get_london_midnight_in_utc(process_date) - - print('Sending notification processing-time for {} - {}'.format( - process_start_date.isoformat(), - process_end_date.isoformat() - )) - send_processing_time_for_start_and_end(process_start_date, process_end_date) + for service_id in service_ids: + print('Starting to populate data for service {}'.format(str(service_id))) + print('Starting populating monthly billing for {}'.format(year)) + for i in range(start, end): + print('Population for {}-{}'.format(i, year)) + populate(service_id, year, i) -class PopulateServiceEmailReplyTo(Command): +@commands.command() +@click.option('-s', '--start_date', required=True, help="Date (%Y-%m-%d) start date inclusive") +@click.option('-e', '--end_date', required=True, help="Date (%Y-%m-%d) end date inclusive") +def backfill_processing_time(start_date, end_date): + start_date = datetime.strptime(start_date, '%Y-%m-%d') + end_date = datetime.strptime(end_date, '%Y-%m-%d') - def run(self): - services_to_update = """ - INSERT INTO service_email_reply_to(id, service_id, email_address, is_default, created_at) - SELECT uuid_in(md5(random()::text || now()::text)::cstring), id, reply_to_email_address, true, '{}' - FROM services - WHERE reply_to_email_address IS NOT NULL - AND id NOT IN( - SELECT service_id - FROM service_email_reply_to - ) - """.format(datetime.utcnow()) + delta = end_date - start_date - result = db.session.execute(services_to_update) - db.session.commit() + print('Sending notification processing-time data for all days between {} and {}'.format(start_date, end_date)) - print("Populated email reply to addresses for {}".format(result.rowcount)) + for i in range(delta.days + 1): + # because the tz conversion funcs talk about midnight, and the midnight before last, + # we want to pretend we're running this from the next morning, so add one. + process_date = start_date + timedelta(days=i + 1) + + process_start_date = get_midnight_for_day_before(process_date) + process_end_date = get_london_midnight_in_utc(process_date) + + print('Sending notification processing-time for {} - {}'.format( + process_start_date.isoformat(), + process_end_date.isoformat() + )) + send_processing_time_for_start_and_end(process_start_date, process_end_date) -class PopulateServiceSmsSender(Command): +@commands.command() +def populate_service_email_reply_to(): + services_to_update = """ + INSERT INTO service_email_reply_to(id, service_id, email_address, is_default, created_at) + SELECT uuid_in(md5(random()::text || now()::text)::cstring), id, reply_to_email_address, true, '{}' + FROM services + WHERE reply_to_email_address IS NOT NULL + AND id NOT IN( + SELECT service_id + FROM service_email_reply_to + ) + """.format(datetime.utcnow()) - def run(self): - services_to_update = """ - INSERT INTO service_sms_senders(id, service_id, sms_sender, inbound_number_id, is_default, created_at) - SELECT uuid_in(md5(random()::text || now()::text)::cstring), service_id, number, id, true, '{}' - FROM inbound_numbers - WHERE service_id NOT IN( - SELECT service_id - FROM service_sms_senders - ) - """.format(datetime.utcnow()) + result = db.session.execute(services_to_update) + db.session.commit() - services_to_update_from_services = """ - INSERT INTO service_sms_senders(id, service_id, sms_sender, inbound_number_id, is_default, created_at) - SELECT uuid_in(md5(random()::text || now()::text)::cstring), id, sms_sender, null, true, '{}' + print("Populated email reply to addresses for {}".format(result.rowcount)) + + +@commands.command() +def populate_service_sms_sender(): + services_to_update = """ + INSERT INTO service_sms_senders(id, service_id, sms_sender, inbound_number_id, is_default, created_at) + SELECT uuid_in(md5(random()::text || now()::text)::cstring), service_id, number, id, true, '{}' + FROM inbound_numbers + WHERE service_id NOT IN( + SELECT service_id + FROM service_sms_senders + ) + """.format(datetime.utcnow()) + + services_to_update_from_services = """ + INSERT INTO service_sms_senders(id, service_id, sms_sender, inbound_number_id, is_default, created_at) + SELECT uuid_in(md5(random()::text || now()::text)::cstring), id, sms_sender, null, true, '{}' + FROM services + WHERE id NOT IN( + SELECT service_id + FROM service_sms_senders + ) + """.format(datetime.utcnow()) + + result = db.session.execute(services_to_update) + second_result = db.session.execute(services_to_update_from_services) + db.session.commit() + + services_count_query = db.session.execute("Select count(*) from services").fetchall()[0][0] + + service_sms_sender_count_query = db.session.execute("Select count(*) from service_sms_senders").fetchall()[0][0] + + print("Populated sms sender {} services from inbound_numbers".format(result.rowcount)) + print("Populated sms sender {} services from services".format(second_result.rowcount)) + print("{} services in table".format(services_count_query)) + print("{} service_sms_senders".format(service_sms_sender_count_query)) + + +@commands.command() +def populate_service_letter_contact(): + services_to_update = """ + INSERT INTO service_letter_contacts(id, service_id, contact_block, is_default, created_at) + SELECT uuid_in(md5(random()::text || now()::text)::cstring), id, letter_contact_block, true, '{}' + FROM services + WHERE letter_contact_block IS NOT NULL + AND id NOT IN( + SELECT service_id + FROM service_letter_contacts + ) + """.format(datetime.utcnow()) + + result = db.session.execute(services_to_update) + db.session.commit() + + print("Populated letter contacts for {} services".format(result.rowcount)) + + +@commands.command() +def populate_service_and_service_history_free_sms_fragment_limit(): + services_to_update = """ + UPDATE services + SET free_sms_fragment_limit = 250000 + WHERE free_sms_fragment_limit IS NULL + """ + + services_history_to_update = """ + UPDATE services_history + SET free_sms_fragment_limit = 250000 + WHERE free_sms_fragment_limit IS NULL + """ + + services_result = db.session.execute(services_to_update) + services_history_result = db.session.execute(services_history_to_update) + + db.session.commit() + + print("Populated free sms fragment limits for {} services".format(services_result.rowcount)) + print("Populated free sms fragment limits for {} services history".format(services_history_result.rowcount)) + + +@commands.command() +def populate_annual_billing(): + financial_year = [2016, 2017, 2018] + + for fy in financial_year: + populate_data = """ + INSERT INTO annual_billing(id, service_id, free_sms_fragment_limit, financial_year_start, + created_at, updated_at) + SELECT uuid_in(md5(random()::text || now()::text)::cstring), id, 250000, {}, '{}', '{}' FROM services WHERE id NOT IN( SELECT service_id - FROM service_sms_senders - ) - """.format(datetime.utcnow()) + FROM annual_billing + WHERE financial_year_start={}) + """.format(fy, datetime.utcnow(), datetime.utcnow(), fy) - result = db.session.execute(services_to_update) - second_result = db.session.execute(services_to_update_from_services) + services_result1 = db.session.execute(populate_data) db.session.commit() - services_count_query = db.session.execute("Select count(*) from services").fetchall()[0][0] - - service_sms_sender_count_query = db.session.execute("Select count(*) from service_sms_senders").fetchall()[0][0] - - print("Populated sms sender {} services from inbound_numbers".format(result.rowcount)) - print("Populated sms sender {} services from services".format(second_result.rowcount)) - print("{} services in table".format(services_count_query)) - print("{} service_sms_senders".format(service_sms_sender_count_query)) + print("Populated annual billing {} for {} services".format(fy, services_result1.rowcount)) -class PopulateServiceLetterContact(Command): - - def run(self): - services_to_update = """ - INSERT INTO service_letter_contacts(id, service_id, contact_block, is_default, created_at) - SELECT uuid_in(md5(random()::text || now()::text)::cstring), id, letter_contact_block, true, '{}' - FROM services - WHERE letter_contact_block IS NOT NULL - AND id NOT IN( - SELECT service_id - FROM service_letter_contacts - ) - """.format(datetime.utcnow()) - - result = db.session.execute(services_to_update) - db.session.commit() - - print("Populated letter contacts for {} services".format(result.rowcount)) +@commands.command() +@click.option('-j', '--job_id', required=True, help="Enter the job id to rebuild the dvla file for") +def re_run_build_dvla_file_for_job(job_id): + from app.celery.tasks import build_dvla_file + from app.config import QueueNames + build_dvla_file.apply_async([job_id], queue=QueueNames.JOBS) -class PopulateServiceAndServiceHistoryFreeSmsFragmentLimit(Command): - - def run(self): - services_to_update = """ - UPDATE services - SET free_sms_fragment_limit = 250000 - WHERE free_sms_fragment_limit IS NULL - """ - - services_history_to_update = """ - UPDATE services_history - SET free_sms_fragment_limit = 250000 - WHERE free_sms_fragment_limit IS NULL - """ - - services_result = db.session.execute(services_to_update) - services_history_result = db.session.execute(services_history_to_update) - - db.session.commit() - - print("Populated free sms fragment limits for {} services".format(services_result.rowcount)) - print("Populated free sms fragment limits for {} services history".format(services_history_result.rowcount)) +@commands.command() +def list_routes(): + """List URLs of all application routes.""" + for rule in sorted(current_app.url_map.iter_rules(), key=lambda r: r.rule): + print("{:10} {}".format(", ".join(rule.methods - set(['OPTIONS', 'HEAD'])), rule.rule)) -class PopulateAnnualBilling(Command): - def run(self): - financial_year = [2016, 2017, 2018] - - for fy in financial_year: - populate_data = """ - INSERT INTO annual_billing(id, service_id, free_sms_fragment_limit, financial_year_start, - created_at, updated_at) - SELECT uuid_in(md5(random()::text || now()::text)::cstring), id, 250000, {}, '{}', '{}' - FROM services - WHERE id NOT IN( - SELECT service_id - FROM annual_billing - WHERE financial_year_start={}) - """.format(fy, datetime.utcnow(), datetime.utcnow(), fy) - - services_result1 = db.session.execute(populate_data) - db.session.commit() - - print("Populated annual billing {} for {} services".format(fy, services_result1.rowcount)) - - -class ReRunBuildDvlaFileForJob(Command): - option_list = ( - Option('-j', '--job_id', dest='job_id', help="Enter the job id to rebuild the dvla file for"), - ) - - def run(self, job_id): - from app.celery.tasks import build_dvla_file - from app.config import QueueNames - build_dvla_file.apply_async([job_id], queue=QueueNames.JOBS) +def setup_commands(application): + application.cli.add_command(commands) diff --git a/application.py b/application.py index b606aee81..6960fd08b 100644 --- a/application.py +++ b/application.py @@ -1,38 +1,10 @@ -#!/usr/bin/env python - +##!/usr/bin/env python from __future__ import print_function -import os -from flask_script import Manager, Server -from flask_migrate import Migrate, MigrateCommand -from app import (create_app, db, commands) -application = create_app() -manager = Manager(application) -port = int(os.environ.get('PORT', 6011)) -manager.add_command("runserver", Server(host='0.0.0.0', port=port)) +from flask import Flask -migrate = Migrate(application, db) -manager.add_command('db', MigrateCommand) -manager.add_command('create_provider_rate', commands.CreateProviderRateCommand) -manager.add_command('purge_functional_test_data', commands.PurgeFunctionalTestDataCommand) -manager.add_command('custom_db_script', commands.CustomDbScript) -manager.add_command('populate_monthly_billing', commands.PopulateMonthlyBilling) -manager.add_command('backfill_processing_time', commands.BackfillProcessingTime) -manager.add_command('populate_service_email_reply_to', commands.PopulateServiceEmailReplyTo) -manager.add_command('populate_service_sms_sender', commands.PopulateServiceSmsSender) -manager.add_command('populate_service_letter_contact', commands.PopulateServiceLetterContact) -manager.add_command('populate_service_and_service_history_free_sms_fragment_limit', - commands.PopulateServiceAndServiceHistoryFreeSmsFragmentLimit) -manager.add_command('populate_annual_billing', commands.PopulateAnnualBilling) -manager.add_command('rerun_build_dvla_file', commands.ReRunBuildDvlaFileForJob) +from app import create_app +app = Flask('app') -@manager.command -def list_routes(): - """List URLs of all application routes.""" - for rule in sorted(application.url_map.iter_rules(), key=lambda r: r.rule): - print("{:10} {}".format(", ".join(rule.methods - set(['OPTIONS', 'HEAD'])), rule.rule)) - - -if __name__ == '__main__': - manager.run() +create_app(app) diff --git a/requirements.txt b/requirements.txt index 8d69902c5..37351cacb 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,7 +5,6 @@ docopt==0.6.2 Flask-Bcrypt==0.7.1 Flask-Marshmallow==0.8.0 Flask-Migrate==2.1.1 -Flask-Script==2.0.5 Flask-SQLAlchemy==2.3.2 Flask==0.12.2 gunicorn==19.7.1 diff --git a/run_celery.py b/run_celery.py index 013499615..4fb28ae08 100644 --- a/run_celery.py +++ b/run_celery.py @@ -1,6 +1,10 @@ #!/usr/bin/env python # notify_celery is referenced from manifest_delivery_base.yml, and cannot be removed +from flask import Flask + from app import notify_celery, create_app -application = create_app('delivery') + +application = Flask('delivery') +create_app(application) application.app_context().push() diff --git a/scripts/run_app.sh b/scripts/run_app.sh index e8ab00bb6..9997d1072 100755 --- a/scripts/run_app.sh +++ b/scripts/run_app.sh @@ -3,4 +3,4 @@ set -e source environment.sh -python3 application.py runserver +flask run -p 6011 diff --git a/server_commands.py b/server_commands.py index 9f0ce8a60..a3c78bf78 100644 --- a/server_commands.py +++ b/server_commands.py @@ -1,4 +1,3 @@ -from flask_script import Manager, Server from flask_migrate import Migrate, MigrateCommand from app import (create_app, db, commands) import os @@ -16,11 +15,10 @@ os.environ['NOTIFY_API_ENVIRONMENT'] = configs[environment] application = create_app() -manager = Manager(application) migrate = Migrate(application, db) -manager.add_command('db', MigrateCommand) -manager.add_command('purge_functional_test_data', commands.PurgeFunctionalTestDataCommand) -manager.add_command('custom_db_script', commands.CustomDbScript) +application.add_command('db', MigrateCommand) +application.add_command('purge_functional_test_data', commands.PurgeFunctionalTestDataCommand) +application.add_command('custom_db_script', commands.CustomDbScript) if __name__ == '__main__': manager.run()