kopia lustrzana https://github.com/glidernet/ogn-python
Apply factory pattern WIP
rodzic
34d9c39ab6
commit
b13064cf73
|
@ -1,12 +1,10 @@
|
|||
language: python
|
||||
|
||||
env:
|
||||
- OGN_CONFIG_MODULE='config/test.py'
|
||||
|
||||
python:
|
||||
- 3.5
|
||||
- 3.6
|
||||
- 3.7-dev
|
||||
- 3.7
|
||||
- 3.8-dev
|
||||
|
||||
addons:
|
||||
postgresql: "9.6"
|
||||
|
|
|
@ -7,21 +7,32 @@ from celery import Celery
|
|||
|
||||
from app.flask_celery import make_celery
|
||||
|
||||
# Initialize Flask
|
||||
app = Flask(__name__)
|
||||
bootstrap = Bootstrap()
|
||||
db = SQLAlchemy()
|
||||
cache = Cache()
|
||||
|
||||
# Load the configuration
|
||||
app.config.from_object('app.config.default')
|
||||
app.config.from_envvar("OGN_CONFIG_MODULE", silent=True)
|
||||
def create_app(config_name='development'):
|
||||
# Initialize Flask
|
||||
app = Flask(__name__)
|
||||
|
||||
# Initialize other things
|
||||
bootstrap = Bootstrap(app)
|
||||
db = SQLAlchemy(app)
|
||||
migrate = Migrate(app, db)
|
||||
cache = Cache(app)
|
||||
celery = make_celery(app)
|
||||
# Load the configuration
|
||||
if config_name == 'testing':
|
||||
app.config.from_object('app.config.test')
|
||||
else:
|
||||
app.config.from_object('app.config.default')
|
||||
app.config.from_envvar("OGN_CONFIG_MODULE", silent=True)
|
||||
|
||||
from app.main import bp as bp_main
|
||||
app.register_blueprint(bp_main)
|
||||
# Initialize other things
|
||||
bootstrap.init_app(app)
|
||||
db.init_app(app)
|
||||
cache.init_app(app)
|
||||
|
||||
#migrate = Migrate(app, db)
|
||||
#celery = make_celery(app)
|
||||
|
||||
from app.main import bp as bp_main
|
||||
app.register_blueprint(bp_main)
|
||||
|
||||
from app import commands
|
||||
#from app import commands
|
||||
|
||||
return app
|
||||
|
|
|
@ -2,12 +2,11 @@ from sqlalchemy import distinct
|
|||
from sqlalchemy.sql import null, and_, func, not_, case
|
||||
from sqlalchemy.dialects import postgresql
|
||||
from sqlalchemy.dialects.postgresql import insert
|
||||
from flask import current_app
|
||||
|
||||
from app.model import Country, DeviceInfo, DeviceInfoOrigin, AircraftBeacon, ReceiverBeacon, Device, Receiver
|
||||
from app.utils import get_ddb, get_flarmnet
|
||||
|
||||
from app import app
|
||||
|
||||
|
||||
def upsert(session, model, rows, update_cols):
|
||||
"""Insert rows in model. On conflicting update columns if new value IS NOT NULL."""
|
||||
|
@ -46,7 +45,7 @@ def import_ddb(session, logger=None):
|
|||
"""Import registered devices from the DDB."""
|
||||
|
||||
if logger is None:
|
||||
logger = app.logger
|
||||
logger = current_app.logger
|
||||
|
||||
logger.info("Import registered devices fom the DDB...")
|
||||
counter = update_device_infos(session, DeviceInfoOrigin.OGN_DDB)
|
||||
|
@ -60,7 +59,7 @@ def update_country_code(session, logger=None):
|
|||
"""Update country code in receivers table if None."""
|
||||
|
||||
if logger is None:
|
||||
logger = app.logger
|
||||
logger = current_app.logger
|
||||
|
||||
update_receivers = (
|
||||
session.query(Receiver)
|
||||
|
|
|
@ -1,18 +1,17 @@
|
|||
from sqlalchemy import and_, or_, insert, update, exists, between
|
||||
from sqlalchemy.sql import func, null
|
||||
from sqlalchemy.sql.expression import true, false
|
||||
from flask import current_app
|
||||
|
||||
from app.model import TakeoffLanding, Logbook, AircraftBeacon
|
||||
from app.utils import date_to_timestamps
|
||||
|
||||
from app import app
|
||||
|
||||
|
||||
def update_entries(session, date, logger=None):
|
||||
"""Add/update logbook entries."""
|
||||
|
||||
if logger is None:
|
||||
logger = app.logger
|
||||
logger = current_app.logger
|
||||
|
||||
logger.info("Compute logbook.")
|
||||
|
||||
|
@ -167,7 +166,7 @@ def update_max_altitudes(session, date, logger=None):
|
|||
"""Add max altitudes in logbook when flight is complete (takeoff and landing)."""
|
||||
|
||||
if logger is None:
|
||||
logger = app.logger
|
||||
logger = current_app.logger
|
||||
|
||||
logger.info("Update logbook max altitude.")
|
||||
|
||||
|
|
|
@ -1,18 +1,17 @@
|
|||
from sqlalchemy import Date
|
||||
from sqlalchemy import and_, insert, update, exists, between
|
||||
from sqlalchemy.sql import func, null
|
||||
from flask import current_app
|
||||
|
||||
from app.model import AircraftBeacon, ReceiverCoverage
|
||||
from app.utils import date_to_timestamps
|
||||
|
||||
from app import app
|
||||
|
||||
|
||||
def update_entries(session, date, logger=None):
|
||||
"""Create receiver coverage stats for Melissas ognrange."""
|
||||
|
||||
if logger is None:
|
||||
logger = app.logger
|
||||
logger = current_app.logger
|
||||
|
||||
logger.info("Compute receiver coverages.")
|
||||
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
from flask import current_app
|
||||
from sqlalchemy import insert, distinct, between, literal
|
||||
from sqlalchemy.sql import null, and_, func, or_, update
|
||||
from sqlalchemy.sql.expression import case
|
||||
|
||||
from app.model import AircraftBeacon, DeviceStats, Country, CountryStats, ReceiverStats, ReceiverBeacon, RelationStats, Receiver, Device
|
||||
|
||||
from app.utils import date_to_timestamps
|
||||
|
||||
from app import app
|
||||
|
||||
# 40dB@10km is enough for 640km
|
||||
MAX_PLAUSIBLE_QUALITY = 40
|
||||
|
@ -16,7 +15,7 @@ def create_device_stats(session, date, logger=None):
|
|||
"""Add/update device stats."""
|
||||
|
||||
if logger is None:
|
||||
logger = app.logger
|
||||
logger = current_app.logger
|
||||
|
||||
(start, end) = date_to_timestamps(date)
|
||||
|
||||
|
@ -83,7 +82,7 @@ def create_receiver_stats(session, date, logger=None):
|
|||
"""Add/update receiver stats."""
|
||||
|
||||
if logger is None:
|
||||
logger = app.logger
|
||||
logger = current_app.logger
|
||||
|
||||
(start, end) = date_to_timestamps(date)
|
||||
|
||||
|
@ -155,7 +154,7 @@ def create_receiver_stats(session, date, logger=None):
|
|||
|
||||
def create_country_stats(session, date, logger=None):
|
||||
if logger is None:
|
||||
logger = app.logger
|
||||
logger = current_app.logger
|
||||
|
||||
(start, end) = date_to_timestamps(date)
|
||||
|
||||
|
@ -181,7 +180,7 @@ def update_device_stats_jumps(session, date, logger=None):
|
|||
"""Update device stats jumps."""
|
||||
|
||||
if logger is None:
|
||||
logger = app.logger
|
||||
logger = current_app.logger
|
||||
|
||||
(start, end) = date_to_timestamps(date)
|
||||
|
||||
|
@ -237,7 +236,7 @@ def create_relation_stats(session, date, logger=None):
|
|||
"""Add/update relation stats."""
|
||||
|
||||
if logger is None:
|
||||
logger = app.logger
|
||||
logger = current_app.logger
|
||||
|
||||
(start, end) = date_to_timestamps(date)
|
||||
|
||||
|
@ -274,7 +273,7 @@ def update_qualities(session, date, logger=None):
|
|||
"""Calculate relative qualities of receivers and devices."""
|
||||
|
||||
if logger is None:
|
||||
logger = app.logger
|
||||
logger = current_app.logger
|
||||
|
||||
# Calculate avg quality of devices
|
||||
dev_sq = session.query(RelationStats.device_id, func.avg(RelationStats.quality).label("quality")).filter(RelationStats.date == date).group_by(RelationStats.device_id).subquery()
|
||||
|
@ -339,7 +338,7 @@ def update_receivers(session, logger=None):
|
|||
"""Update receivers with stats."""
|
||||
|
||||
if logger is None:
|
||||
logger = app.logger
|
||||
logger = current_app.logger
|
||||
|
||||
receiver_stats = (
|
||||
session.query(
|
||||
|
@ -394,7 +393,7 @@ def update_devices(session, logger=None):
|
|||
"""Update devices with stats."""
|
||||
|
||||
if logger is None:
|
||||
logger = app.logger
|
||||
logger = current_app.logger
|
||||
|
||||
device_stats = (
|
||||
session.query(
|
||||
|
|
|
@ -1,19 +1,18 @@
|
|||
from datetime import timedelta
|
||||
|
||||
from flask import current_app
|
||||
from sqlalchemy import and_, or_, insert, between, exists
|
||||
from sqlalchemy.sql import func, null
|
||||
from sqlalchemy.sql.expression import case
|
||||
|
||||
from app.model import AircraftBeacon, TakeoffLanding, Airport
|
||||
|
||||
from app import app
|
||||
|
||||
|
||||
def update_entries(session, start, end, logger=None):
|
||||
"""Compute takeoffs and landings."""
|
||||
|
||||
if logger is None:
|
||||
logger = app.logger
|
||||
logger = current_app.logger
|
||||
|
||||
logger.info("Compute takeoffs and landings.")
|
||||
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
from app import app
|
||||
|
||||
from .database import user_cli as database_cli
|
||||
from .export import user_cli as export_cli
|
||||
from .flights import user_cli as flights_cli
|
||||
|
@ -7,9 +5,10 @@ from .gateway import user_cli as gateway_cli
|
|||
from .logbook import user_cli as logbook_cli
|
||||
from .stats import user_cli as stats_cli
|
||||
|
||||
app.cli.add_command(database_cli)
|
||||
app.cli.add_command(export_cli)
|
||||
app.cli.add_command(flights_cli)
|
||||
app.cli.add_command(gateway_cli)
|
||||
app.cli.add_command(logbook_cli)
|
||||
app.cli.add_command(stats_cli)
|
||||
def register(app):
|
||||
app.cli.add_command(database_cli)
|
||||
app.cli.add_command(export_cli)
|
||||
app.cli.add_command(flights_cli)
|
||||
app.cli.add_command(gateway_cli)
|
||||
app.cli.add_command(logbook_cli)
|
||||
app.cli.add_command(stats_cli)
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
from flask import current_app
|
||||
from flask.cli import AppGroup
|
||||
import click
|
||||
|
||||
|
@ -8,7 +9,6 @@ from app.collect.database import update_device_infos, update_country_code
|
|||
from app.model import *
|
||||
from app.utils import get_airports, get_days
|
||||
|
||||
from app import app
|
||||
from app import db
|
||||
|
||||
user_cli = AppGroup("database")
|
||||
|
@ -36,8 +36,8 @@ def get_database_days(start, end):
|
|||
|
||||
@user_cli.command("info")
|
||||
def info():
|
||||
print(app.config)
|
||||
print(app.config["SQLALCHEMY_DATABASE_URI"])
|
||||
print(current_app.config)
|
||||
print(current_app.config["SQLALCHEMY_DATABASE_URI"])
|
||||
|
||||
|
||||
@user_cli.command("init")
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
from flask import current_app
|
||||
from flask.cli import AppGroup
|
||||
import click
|
||||
|
||||
from ogn.client import AprsClient
|
||||
from app.gateway.bulkimport import ContinuousDbFeeder
|
||||
|
||||
from app import app
|
||||
|
||||
user_cli = AppGroup("gateway")
|
||||
user_cli.help = "Connection to APRS servers."
|
||||
|
||||
|
@ -21,14 +20,14 @@ def run(aprs_user="anon-dev"):
|
|||
print("aprs_user must be a string of 3-9 characters.")
|
||||
return
|
||||
|
||||
app.logger.warning("Start ogn gateway")
|
||||
current_app.logger.warning("Start ogn gateway")
|
||||
client = AprsClient(aprs_user)
|
||||
client.connect()
|
||||
|
||||
try:
|
||||
client.run(callback=saver.add, autoreconnect=True)
|
||||
except KeyboardInterrupt:
|
||||
app.logger.warning("\nStop ogn gateway")
|
||||
current_app.logger.warning("\nStop ogn gateway")
|
||||
|
||||
saver.flush()
|
||||
client.disconnect()
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
from datetime import datetime, timedelta
|
||||
from io import StringIO
|
||||
|
||||
from flask import current_app
|
||||
from flask.cli import AppGroup
|
||||
import click
|
||||
from tqdm import tqdm
|
||||
|
@ -13,7 +14,6 @@ from app.utils import open_file
|
|||
from app.gateway.process_tools import *
|
||||
|
||||
from app import db
|
||||
from app import app
|
||||
|
||||
user_cli = AppGroup("bulkimport")
|
||||
user_cli.help = "Tools for accelerated data import."
|
||||
|
@ -91,16 +91,16 @@ def string_to_message(raw_string, reference_date):
|
|||
try:
|
||||
message = parse(raw_string, reference_date)
|
||||
except NotImplementedError as e:
|
||||
app.logger.error("No parser implemented for message: {}".format(raw_string))
|
||||
current_app.logger.error("No parser implemented for message: {}".format(raw_string))
|
||||
return None
|
||||
except ParseError as e:
|
||||
app.logger.error("Parsing error with message: {}".format(raw_string))
|
||||
current_app.logger.error("Parsing error with message: {}".format(raw_string))
|
||||
return None
|
||||
except TypeError as e:
|
||||
app.logger.error("TypeError with message: {}".format(raw_string))
|
||||
current_app.logger.error("TypeError with message: {}".format(raw_string))
|
||||
return None
|
||||
except Exception as e:
|
||||
app.logger.error("Other Exception with string: {}".format(raw_string))
|
||||
current_app.logger.error("Other Exception with string: {}".format(raw_string))
|
||||
return None
|
||||
|
||||
# update reference receivers and distance to the receiver
|
||||
|
@ -160,7 +160,7 @@ class ContinuousDbFeeder:
|
|||
self.receiver_buffer.write(complete_message)
|
||||
self.receiver_buffer.write("\n")
|
||||
else:
|
||||
app.logger.error("Ignore beacon_type: {}".format(message["beacon_type"]))
|
||||
current_app.logger.error("Ignore beacon_type: {}".format(message["beacon_type"]))
|
||||
return
|
||||
|
||||
if datetime.utcnow() - self.last_flush >= timedelta(seconds=20):
|
||||
|
@ -243,7 +243,7 @@ class FileDbFeeder:
|
|||
self.receiver_buffer.write(complete_message)
|
||||
self.receiver_buffer.write("\n")
|
||||
else:
|
||||
app.logger.error("Ignore beacon_type: {}".format(message["beacon_type"]))
|
||||
current_app.logger.error("Ignore beacon_type: {}".format(message["beacon_type"]))
|
||||
return
|
||||
|
||||
def prepare(self):
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
[program:celerybeat]
|
||||
environment=OGN_CONFIG_MODULE='config/default.py'
|
||||
command=/home/pi/venv/bin/celery -A app.collect beat -l info
|
||||
command=/home/pi/ogn-python/venv/bin/celery -A app.collect beat -l info
|
||||
directory=/home/pi/ogn-python
|
||||
|
||||
user=pi
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
[program:celery]
|
||||
environment=OGN_CONFIG_MODULE='config/default.py'
|
||||
command=/home/pi/ogn-python/venv/bin/celery -A app.collect worker -l info
|
||||
directory=/home/pi/ogn-python
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
[program:flower]
|
||||
environment=OGN_CONFIG_MODULE='config/default.py'
|
||||
command=/home/pi/ogn-python/venv/bin/celery flower -A app.celery --port=5555 -l info
|
||||
directory=/home/pi/ogn-python
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
[program:gunicorn]
|
||||
environment=OGN_CONFIG_MODULE='config/default.py'
|
||||
command=/home/pi/ogn-python/venv/bin/gunicorn --bind :5000 ogn_python:app
|
||||
directory=/home/pi/ogn-python
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
[program:ogn-feeder]
|
||||
environment=OGN_CONFIG_MODULE='config/default.py'
|
||||
command=/home/pi/ogn-python/venv/bin/python -m flask gateway run
|
||||
directory=/home/pi/ogn_python
|
||||
directory=/home/pi/ogn-python
|
||||
|
||||
user=pi
|
||||
stderr_logfile=/var/log/supervisor/ogn-feeder.log
|
||||
|
|
|
@ -1,5 +1,13 @@
|
|||
from app import app
|
||||
import os
|
||||
|
||||
from flask_migrate import Migrate
|
||||
from app import create_app, db
|
||||
from app.commands import register
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run()
|
||||
app = create_app(os.getenv('FLASK_CONFIG') or 'default')
|
||||
migrate = Migrate(app, db)
|
||||
register(app)
|
||||
|
||||
@app.shell_context_processor
|
||||
def make_shell_context():
|
||||
return dict(app=app, db=db)
|
|
@ -1,36 +1,18 @@
|
|||
import unittest
|
||||
import os
|
||||
|
||||
os.environ["OGN_CONFIG_MODULE"] = "config/test.py"
|
||||
|
||||
from app import db # noqa: E402
|
||||
from app import create_app, db
|
||||
|
||||
|
||||
class TestBaseDB(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
db.session.execute("CREATE EXTENSION IF NOT EXISTS postgis;")
|
||||
db.session.commit()
|
||||
db.drop_all()
|
||||
def setUp(self):
|
||||
self.app = create_app('testing')
|
||||
self.app_context = self.app.app_context()
|
||||
self.app_context.push()
|
||||
db.create_all()
|
||||
|
||||
def setUp(self):
|
||||
pass
|
||||
|
||||
def tearDown(self):
|
||||
db.session.execute(
|
||||
"""
|
||||
DELETE FROM aircraft_beacons;
|
||||
DELETE FROM receiver_beacons;
|
||||
DELETE FROM takeoff_landings;
|
||||
DELETE FROM logbook;
|
||||
DELETE FROM receiver_coverages;
|
||||
DELETE FROM device_stats;
|
||||
DELETE FROM receiver_stats;
|
||||
DELETE FROM receivers;
|
||||
DELETE FROM devices;
|
||||
"""
|
||||
)
|
||||
db.session.remove()
|
||||
db.drop_all()
|
||||
self.app_context.pop()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
@ -9,6 +9,8 @@ from app.collect.logbook import update_entries
|
|||
|
||||
class TestLogbook(TestBaseDB):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
|
||||
# Create basic data and insert
|
||||
self.dd0815 = Device(address="DD0815")
|
||||
self.dd4711 = Device(address="DD4711")
|
||||
|
|
|
@ -1,17 +1,16 @@
|
|||
import unittest
|
||||
import os
|
||||
|
||||
from tests.base import TestBaseDB, db
|
||||
|
||||
from flask import current_app
|
||||
from app.model import DeviceInfo
|
||||
from app.commands.database import import_file
|
||||
|
||||
from app import app
|
||||
from tests.base import TestBaseDB, db
|
||||
|
||||
|
||||
class TestDatabase(TestBaseDB):
|
||||
def test_import_ddb_file(self):
|
||||
runner = app.test_cli_runner()
|
||||
runner = current_app.test_cli_runner()
|
||||
result = runner.invoke(import_file, [os.path.dirname(__file__) + "/../custom_ddb.txt"])
|
||||
self.assertEqual(result.exit_code, 0)
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue