add entry points for fittrackee package
This commit is contained in:
parent
6c3e31bf6d
commit
8c84afe793
5
.gitignore
vendored
5
.gitignore
vendored
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
Makefile.custom.config
|
Makefile.custom.config
|
||||||
|
|
||||||
# MPWO_API
|
# API
|
||||||
###############
|
###############
|
||||||
__pycache__
|
__pycache__
|
||||||
uploads
|
uploads
|
||||||
@ -13,8 +13,9 @@ coverage.xml
|
|||||||
.pytest_cache
|
.pytest_cache
|
||||||
.venv
|
.venv
|
||||||
/fittrackee.egg-info/
|
/fittrackee.egg-info/
|
||||||
|
/dist
|
||||||
|
|
||||||
# MPWO_CLIENT
|
# CLIENT
|
||||||
###############
|
###############
|
||||||
|
|
||||||
# dependencies
|
# dependencies
|
||||||
|
@ -3,12 +3,9 @@ API_PORT = 5000
|
|||||||
CLIENT_PORT = 3000
|
CLIENT_PORT = 3000
|
||||||
|
|
||||||
export FLASK_APP = $(PWD)/fittrackee/server.py
|
export FLASK_APP = $(PWD)/fittrackee/server.py
|
||||||
export APP_SETTINGS=fittrackee.config.DevelopmentConfig
|
|
||||||
export FLASK_ENV=development
|
export FLASK_ENV=development
|
||||||
export TEST_APP_URL = http://$(HOST):$(API_PORT)
|
export TEST_APP_URL = http://$(HOST):$(API_PORT)
|
||||||
export TEST_CLIENT_URL = http://$(HOST):$(CLIENT_PORT)
|
export TEST_CLIENT_URL = http://$(HOST):$(CLIENT_PORT)
|
||||||
export DATABASE_URL = postgres://fittrackee:fittrackee@$(HOST):5432/fittrackee
|
|
||||||
export DATABASE_TEST_URL = postgres://fittrackee:fittrackee@$(HOST):5432/fittrackee_test
|
|
||||||
export MIGRATIONS = $(PWD)/fittrackee/migrations
|
export MIGRATIONS = $(PWD)/fittrackee/migrations
|
||||||
|
|
||||||
# Python env
|
# Python env
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
|
# dramatiq (task queue)
|
||||||
WORKERS_PROCESSES = 1
|
WORKERS_PROCESSES = 1
|
||||||
|
|
||||||
export REACT_APP_API_URL=
|
export DATABASE_URL = postgres://fittrackee:fittrackee@$(HOST):5432/fittrackee
|
||||||
|
export DATABASE_TEST_URL = postgres://fittrackee:fittrackee@$(HOST):5432/fittrackee_test
|
||||||
|
export APP_SETTINGS=fittrackee.config.DevelopmentConfig
|
||||||
|
export DATABASE_DISABLE_POOLING=True
|
||||||
export TILE_SERVER_URL=
|
export TILE_SERVER_URL=
|
||||||
export MAP_ATTRIBUTION=
|
export MAP_ATTRIBUTION=
|
||||||
export WEATHER_API=
|
export WEATHER_API=
|
||||||
@ -8,6 +12,7 @@ export UI_URL=
|
|||||||
export EMAIL_URL=
|
export EMAIL_URL=
|
||||||
export SENDER_EMAIL=
|
export SENDER_EMAIL=
|
||||||
export REDIS_URL=
|
export REDIS_URL=
|
||||||
|
export UPLOAD_FOLDER=
|
||||||
|
|
||||||
# for dev env
|
# for dev env
|
||||||
export CODACY_PROJECT_TOKEN=
|
export REACT_APP_API_URL=
|
||||||
|
@ -24,7 +24,9 @@ def create_app():
|
|||||||
|
|
||||||
# set config
|
# set config
|
||||||
with app.app_context():
|
with app.app_context():
|
||||||
app_settings = os.getenv('APP_SETTINGS')
|
app_settings = os.getenv(
|
||||||
|
'APP_SETTINGS', 'fittrackee.config.ProductionConfig'
|
||||||
|
)
|
||||||
if app_settings == 'fittrackee.config.TestingConfig':
|
if app_settings == 'fittrackee.config.TestingConfig':
|
||||||
# reload config on tests
|
# reload config on tests
|
||||||
config = import_module('fittrackee.config')
|
config = import_module('fittrackee.config')
|
||||||
|
53
fittrackee/__main__.py
Normal file
53
fittrackee/__main__.py
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
# source: http://docs.gunicorn.org/en/stable/custom.html
|
||||||
|
import os
|
||||||
|
|
||||||
|
import gunicorn.app.base
|
||||||
|
from fittrackee import create_app
|
||||||
|
from fittrackee.database_utils import init_database
|
||||||
|
from flask_dramatiq import worker
|
||||||
|
from flask_migrate import upgrade
|
||||||
|
|
||||||
|
HOST = os.getenv('HOST', '0.0.0.0')
|
||||||
|
PORT = os.getenv('API_PORT', '5000')
|
||||||
|
WORKERS = os.getenv('APP_WORKERS', 1)
|
||||||
|
BASEDIR = os.path.abspath(os.path.dirname(__file__))
|
||||||
|
app = create_app()
|
||||||
|
dramatiq_worker = worker
|
||||||
|
|
||||||
|
|
||||||
|
class StandaloneApplication(gunicorn.app.base.BaseApplication):
|
||||||
|
def __init__(self, current_app, options=None):
|
||||||
|
self.options = options or {}
|
||||||
|
self.application = current_app
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
def load_config(self):
|
||||||
|
config = {
|
||||||
|
key: value
|
||||||
|
for key, value in self.options.items()
|
||||||
|
if key in self.cfg.settings and value is not None
|
||||||
|
}
|
||||||
|
for key, value in config.items():
|
||||||
|
self.cfg.set(key.lower(), value)
|
||||||
|
|
||||||
|
def load(self):
|
||||||
|
return self.application
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade_db():
|
||||||
|
with app.app_context():
|
||||||
|
upgrade(directory=BASEDIR + '/migrations')
|
||||||
|
|
||||||
|
|
||||||
|
def init_data():
|
||||||
|
with app.app_context():
|
||||||
|
init_database(app)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
options = {'bind': f'{HOST}:{PORT}', 'workers': WORKERS}
|
||||||
|
StandaloneApplication(app, options).run()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
@ -3,6 +3,7 @@ import os
|
|||||||
from dramatiq.brokers.redis import RedisBroker
|
from dramatiq.brokers.redis import RedisBroker
|
||||||
from dramatiq.brokers.stub import StubBroker
|
from dramatiq.brokers.stub import StubBroker
|
||||||
from flask import current_app
|
from flask import current_app
|
||||||
|
from sqlalchemy.pool import NullPool
|
||||||
|
|
||||||
if os.getenv('APP_SETTINGS') == 'fittrackee.config.TestingConfig':
|
if os.getenv('APP_SETTINGS') == 'fittrackee.config.TestingConfig':
|
||||||
broker = StubBroker
|
broker = StubBroker
|
||||||
@ -20,7 +21,9 @@ class BaseConfig:
|
|||||||
TOKEN_EXPIRATION_DAYS = 30
|
TOKEN_EXPIRATION_DAYS = 30
|
||||||
TOKEN_EXPIRATION_SECONDS = 0
|
TOKEN_EXPIRATION_SECONDS = 0
|
||||||
PASSWORD_TOKEN_EXPIRATION_SECONDS = 3600
|
PASSWORD_TOKEN_EXPIRATION_SECONDS = 3600
|
||||||
UPLOAD_FOLDER = os.path.join(current_app.root_path, 'uploads')
|
UPLOAD_FOLDER = os.path.join(
|
||||||
|
os.getenv('UPLOAD_FOLDER', current_app.root_path), 'uploads'
|
||||||
|
)
|
||||||
PICTURE_ALLOWED_EXTENSIONS = {'jpg', 'png', 'gif'}
|
PICTURE_ALLOWED_EXTENSIONS = {'jpg', 'png', 'gif'}
|
||||||
ACTIVITY_ALLOWED_EXTENSIONS = {'gpx', 'zip'}
|
ACTIVITY_ALLOWED_EXTENSIONS = {'gpx', 'zip'}
|
||||||
TEMPLATES_FOLDER = os.path.join(current_app.root_path, 'email/templates')
|
TEMPLATES_FOLDER = os.path.join(current_app.root_path, 'email/templates')
|
||||||
@ -68,3 +71,18 @@ class TestingConfig(BaseConfig):
|
|||||||
TOKEN_EXPIRATION_SECONDS = 3
|
TOKEN_EXPIRATION_SECONDS = 3
|
||||||
PASSWORD_TOKEN_EXPIRATION_SECONDS = 3
|
PASSWORD_TOKEN_EXPIRATION_SECONDS = 3
|
||||||
UPLOAD_FOLDER = '/tmp/fitTrackee/uploads'
|
UPLOAD_FOLDER = '/tmp/fitTrackee/uploads'
|
||||||
|
|
||||||
|
|
||||||
|
class ProductionConfig(BaseConfig):
|
||||||
|
"""Production configuration"""
|
||||||
|
|
||||||
|
DEBUG = False
|
||||||
|
# https://docs.sqlalchemy.org/en/13/core/pooling.html#using-connection-pools-with-multiprocessing-or-os-fork # noqa
|
||||||
|
SQLALCHEMY_ENGINE_OPTIONS = (
|
||||||
|
{'poolclass': NullPool}
|
||||||
|
if os.getenv('DATABASE_DISABLE_POOLING', True)
|
||||||
|
else {}
|
||||||
|
)
|
||||||
|
SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL')
|
||||||
|
SECRET_KEY = os.getenv('APP_SECRET_KEY')
|
||||||
|
DRAMATIQ_BROKER_URL = os.getenv('REDIS_URL', 'redis://')
|
||||||
|
46
fittrackee/database_utils.py
Normal file
46
fittrackee/database_utils.py
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
from fittrackee import db
|
||||||
|
from fittrackee.activities.models import Sport
|
||||||
|
from fittrackee.application.utils import (
|
||||||
|
init_config,
|
||||||
|
update_app_config_from_database,
|
||||||
|
)
|
||||||
|
from fittrackee.users.models import User
|
||||||
|
|
||||||
|
|
||||||
|
def init_database(app):
|
||||||
|
"""Init the database."""
|
||||||
|
admin = User(
|
||||||
|
username='admin', email='admin@example.com', password='mpwoadmin'
|
||||||
|
)
|
||||||
|
admin.admin = True
|
||||||
|
admin.timezone = 'Europe/Paris'
|
||||||
|
db.session.add(admin)
|
||||||
|
sport = Sport(label='Cycling (Sport)')
|
||||||
|
sport.img = '/img/sports/cycling-sport.png'
|
||||||
|
sport.is_default = True
|
||||||
|
db.session.add(sport)
|
||||||
|
sport = Sport(label='Cycling (Transport)')
|
||||||
|
sport.img = '/img/sports/cycling-transport.png'
|
||||||
|
sport.is_default = True
|
||||||
|
db.session.add(sport)
|
||||||
|
sport = Sport(label='Hiking')
|
||||||
|
sport.img = '/img/sports/hiking.png'
|
||||||
|
sport.is_default = True
|
||||||
|
db.session.add(sport)
|
||||||
|
sport = Sport(label='Mountain Biking')
|
||||||
|
sport.img = '/img/sports/mountain-biking.png'
|
||||||
|
sport.is_default = True
|
||||||
|
db.session.add(sport)
|
||||||
|
sport = Sport(label='Running')
|
||||||
|
sport.img = '/img/sports/running.png'
|
||||||
|
sport.is_default = True
|
||||||
|
db.session.add(sport)
|
||||||
|
sport = Sport(label='Walking')
|
||||||
|
sport.img = '/img/sports/walking.png'
|
||||||
|
sport.is_default = True
|
||||||
|
db.session.add(sport)
|
||||||
|
db.session.commit()
|
||||||
|
_, db_app_config = init_config()
|
||||||
|
update_app_config_from_database(app, db_app_config)
|
||||||
|
|
||||||
|
print('Initial data stored in database.')
|
@ -1,15 +1,13 @@
|
|||||||
import shutil
|
import shutil
|
||||||
|
|
||||||
from fittrackee import create_app, db
|
from fittrackee import create_app, db
|
||||||
from fittrackee.activities.models import Activity, Sport
|
from fittrackee.activities.models import Activity
|
||||||
from fittrackee.activities.utils import update_activity
|
from fittrackee.activities.utils import update_activity
|
||||||
from fittrackee.application.utils import (
|
from fittrackee.application.utils import init_config
|
||||||
init_config,
|
|
||||||
update_app_config_from_database,
|
|
||||||
)
|
|
||||||
from fittrackee.users.models import User
|
|
||||||
from tqdm import tqdm
|
from tqdm import tqdm
|
||||||
|
|
||||||
|
from .database_utils import init_database
|
||||||
|
|
||||||
app = create_app()
|
app = create_app()
|
||||||
|
|
||||||
|
|
||||||
@ -26,43 +24,8 @@ def drop_db():
|
|||||||
|
|
||||||
@app.cli.command()
|
@app.cli.command()
|
||||||
def initdata():
|
def initdata():
|
||||||
"""Init the database."""
|
"""Init the database and application config."""
|
||||||
admin = User(
|
init_database(app)
|
||||||
username='admin', email='admin@example.com', password='mpwoadmin'
|
|
||||||
)
|
|
||||||
admin.admin = True
|
|
||||||
admin.timezone = 'Europe/Paris'
|
|
||||||
db.session.add(admin)
|
|
||||||
sport = Sport(label='Cycling (Sport)')
|
|
||||||
sport.img = '/img/sports/cycling-sport.png'
|
|
||||||
sport.is_default = True
|
|
||||||
db.session.add(sport)
|
|
||||||
sport = Sport(label='Cycling (Transport)')
|
|
||||||
sport.img = '/img/sports/cycling-transport.png'
|
|
||||||
sport.is_default = True
|
|
||||||
db.session.add(sport)
|
|
||||||
sport = Sport(label='Hiking')
|
|
||||||
sport.img = '/img/sports/hiking.png'
|
|
||||||
sport.is_default = True
|
|
||||||
db.session.add(sport)
|
|
||||||
sport = Sport(label='Mountain Biking')
|
|
||||||
sport.img = '/img/sports/mountain-biking.png'
|
|
||||||
sport.is_default = True
|
|
||||||
db.session.add(sport)
|
|
||||||
sport = Sport(label='Running')
|
|
||||||
sport.img = '/img/sports/running.png'
|
|
||||||
sport.is_default = True
|
|
||||||
db.session.add(sport)
|
|
||||||
sport = Sport(label='Walking')
|
|
||||||
sport.img = '/img/sports/walking.png'
|
|
||||||
sport.is_default = True
|
|
||||||
db.session.add(sport)
|
|
||||||
db.session.commit()
|
|
||||||
# update app config
|
|
||||||
_, db_app_config = init_config()
|
|
||||||
update_app_config_from_database(app, db_app_config)
|
|
||||||
|
|
||||||
print('Initial data stored in database.')
|
|
||||||
|
|
||||||
|
|
||||||
@app.cli.command()
|
@app.cli.command()
|
||||||
|
@ -1,9 +1,24 @@
|
|||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "fittrackee"
|
name = "fittrackee"
|
||||||
version = "0.3.0-beta"
|
version = "0.3.0-beta"
|
||||||
description = ""
|
description = "Self-hosted workout/activity tracker"
|
||||||
authors = ["Your Name <you@example.com>"]
|
authors = ["SamR1"]
|
||||||
license = "GPL-3.0"
|
license = "GPL-3.0"
|
||||||
|
readme = "README.md"
|
||||||
|
homepage = "https://github.com/SamR1/FitTrackee"
|
||||||
|
documentation = "https://samr1.github.io/FitTrackee"
|
||||||
|
classifiers = [
|
||||||
|
"Development Status :: 4 - Beta",
|
||||||
|
"Environment :: Web Environment",
|
||||||
|
"Framework :: Flask",
|
||||||
|
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
|
||||||
|
"Operating System :: POSIX :: Linux",
|
||||||
|
"Programming Language :: Python :: 3",
|
||||||
|
"Programming Language :: Python :: 3.7",
|
||||||
|
"Programming Language :: Python :: 3.8",
|
||||||
|
"Programming Language :: JavaScript"
|
||||||
|
]
|
||||||
|
exclude = ["fittrackee/tests"]
|
||||||
|
|
||||||
[tool.poetry.dependencies]
|
[tool.poetry.dependencies]
|
||||||
python = "^3.7"
|
python = "^3.7"
|
||||||
@ -38,8 +53,11 @@ pyopenssl = "^19.0"
|
|||||||
freezegun = "^1.0.0"
|
freezegun = "^1.0.0"
|
||||||
pytest-selenium = "^2.0.0"
|
pytest-selenium = "^2.0.0"
|
||||||
|
|
||||||
[tool.pytest]
|
[tool.poetry.scripts]
|
||||||
norecursedirs = "fittrackee/.venv"
|
fittrackee = 'fittrackee.__main__:main'
|
||||||
|
fittrackee_init_data = 'fittrackee.__main__:init_data'
|
||||||
|
fittrackee_upgrade_db = 'fittrackee.__main__:upgrade_db'
|
||||||
|
fittrackee_worker = 'fittrackee.__main__:dramatiq_worker'
|
||||||
|
|
||||||
[tool.black]
|
[tool.black]
|
||||||
line-length = 79
|
line-length = 79
|
||||||
|
Loading…
Reference in New Issue
Block a user