From 566f631bf611b6576bb2878d66499ea3b14db968 Mon Sep 17 00:00:00 2001 From: lza_menace Date: Sun, 12 Dec 2021 01:19:43 -0800 Subject: [PATCH] add project skeleton code --- .gitignore | 3 ++ Makefile | 20 ++++++++++++++ manage.sh | 31 +++++++++++++++++++++ requirements.txt | 14 ++++++++++ suchwowx/__init__.py | 0 suchwowx/app.py | 12 ++++++++ suchwowx/config.py | 56 ++++++++++++++++++++++++++++++++++++++ suchwowx/factory.py | 36 ++++++++++++++++++++++++ suchwowx/filters.py | 15 ++++++++++ suchwowx/models.py | 13 +++++++++ suchwowx/routes.py | 8 ++++++ suchwowx/tasks/__init__.py | 0 suchwowx/tasks/config.py | 12 ++++++++ 13 files changed, 220 insertions(+) create mode 100644 Makefile create mode 100644 manage.sh create mode 100644 requirements.txt create mode 100644 suchwowx/__init__.py create mode 100644 suchwowx/app.py create mode 100644 suchwowx/config.py create mode 100644 suchwowx/factory.py create mode 100644 suchwowx/filters.py create mode 100644 suchwowx/models.py create mode 100644 suchwowx/routes.py create mode 100644 suchwowx/tasks/__init__.py create mode 100644 suchwowx/tasks/config.py diff --git a/.gitignore b/.gitignore index b6e4761..878c163 100644 --- a/.gitignore +++ b/.gitignore @@ -127,3 +127,6 @@ dmypy.json # Pyre type checker .pyre/ + +# Data +data/ diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..bf19901 --- /dev/null +++ b/Makefile @@ -0,0 +1,20 @@ +setup: + python3 -m venv .venv + .venv/bin/pip install -r requirements.txt + +shell: + bash manage.sh shell + +dev: + bash manage.sh run + +prod: + bash manage.sh prod + +huey: + mkdir -p data/ + .venv/bin/huey_consumer suchwowx.tasks.huey -w 1 -v | tee -a data/huey.log + +kill: + pkill -e -f huey + pkill -e -f suchwowx diff --git a/manage.sh b/manage.sh new file mode 100644 index 0000000..21a93bc --- /dev/null +++ b/manage.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +source .venv/bin/activate +export FLASK_APP=suchwowx/app.py +export FLASK_SECRETS=config.py +export FLASK_DEBUG=1 +export FLASK_ENV=development + +# override +export $(cat .env) + +if [[ ${1} == "prod" ]]; +then + export BASE=./data/gunicorn + export FLASK_ENV=production + export FLASK_DEBUG=0 + mkdir -p $BASE + pgrep -F $BASE/gunicorn.pid + if [[ $? != 0 ]]; then + gunicorn \ + --bind 127.0.0.1:4000 "suchwowx.app:app" \ + --daemon \ + --log-file $BASE/gunicorn.log \ + --pid $BASE/gunicorn.pid \ + --reload + sleep 2 + echo "Started gunicorn on 127.0.0.1:4000 with pid $(cat $BASE/gunicorn.pid)" + fi +else + flask $@ +fi diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..6d7a014 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,14 @@ +arrow +Flask +Flask-WTF +Flask-SQLAlchemy +Flask-Mobility +peewee +gunicorn +huey +redis +Pillow +ipfshttpclient +python-dotenv +requests +web3 diff --git a/suchwowx/__init__.py b/suchwowx/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/suchwowx/app.py b/suchwowx/app.py new file mode 100644 index 0000000..ff7e668 --- /dev/null +++ b/suchwowx/app.py @@ -0,0 +1,12 @@ +from logging.config import dictConfig + +from suchwowx.factory import create_app +from suchwowx import config + + +app = create_app() + +dictConfig(config.LOGGING_CONFIG) + +if __name__ == '__main__': + app.run() diff --git a/suchwowx/config.py b/suchwowx/config.py new file mode 100644 index 0000000..7c93088 --- /dev/null +++ b/suchwowx/config.py @@ -0,0 +1,56 @@ +from os import getenv +from dotenv import load_dotenv + +load_dotenv() + +# App +SECRET_KEY = getenv('SECRET_KEY', 'yyyyyyyyyyyyy') # whatever you want it to be +DATA_FOLDER = getenv('DATA_FOLDER', '/path/to/uploads') # some stable storage path +SERVER_NAME = getenv('SERVER_NAME', '127.0.0.1:5000') # name of your DNS resolvable site (.com) + +# Cache +CACHE_HOST = getenv('CACHE_HOST', 'localhost') +CACHE_PORT = getenv('CACHE_PORT', 6379) + +# Uploads +SESSION_TYPE = 'filesystem' +ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif', 'svg', 'mp4', 'webp'} +MAX_CONTENT_LENGTH = 32 * 1024 * 1024 +TEMPLATES_AUTO_RELOAD = getenv('TEMPLATES_AUTO_RELOAD', True) + +# Logging +LOGGING_CONFIG = { + 'version': 1, + 'formatters': {'default': { + 'format': '[%(asctime)s] %(levelname)s in %(module)s: %(message)s', + }}, + 'handlers': { + 'console': { + 'level': 'INFO', + 'class': 'logging.StreamHandler', + 'formatter': 'default', + 'stream': 'ext://sys.stdout', + }, + 'wsgi': { + 'class': 'logging.StreamHandler', + 'stream': 'ext://flask.logging.wsgi_errors_stream', + 'formatter': 'default' + } + }, + 'loggers': { + 'gunicorn.error': { + 'handlers': ['console'], + 'level': 'INFO', + 'propagate': False, + }, + 'gunicorn.access': { + 'handlers': ['console'], + 'level': 'INFO', + 'propagate': False, + } + }, + 'root': { + 'level': 'DEBUG', + 'handlers': ['console'], + } +} diff --git a/suchwowx/factory.py b/suchwowx/factory.py new file mode 100644 index 0000000..b06270b --- /dev/null +++ b/suchwowx/factory.py @@ -0,0 +1,36 @@ +from logging.config import dictConfig + +from flask import Flask +from flask_sqlalchemy import SQLAlchemy +from flask_mobility import Mobility + +from suchwowx import config + + +db = SQLAlchemy() + + +def setup_db(app: Flask, db:SQLAlchemy=db): + app.config['SQLALCHEMY_DATABASE_URI'] = f'sqlite://{config.DATA_FOLDER}/sqlite.db' # noqa + app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False + db.init_app(app) + return db + +def create_app_huey(): + app = Flask(__name__) + db = SQLAlchemy() + dictConfig(config.LOGGING_CONFIG) + setup_db(app, db) + return app + +def create_app(): + app = Flask(__name__) + app.config.from_envvar('FLASK_SECRETS') + setup_db(app) + Mobility(app) + + with app.app_context(): + from suchwowx import filters, routes + app.register_blueprint(filters.bp) + app.register_blueprint(routes.bp) + return app diff --git a/suchwowx/filters.py b/suchwowx/filters.py new file mode 100644 index 0000000..ec20dbf --- /dev/null +++ b/suchwowx/filters.py @@ -0,0 +1,15 @@ +from flask import Blueprint +from arrow import get as arrow_get + + +bp = Blueprint('filters', 'filters') + +@bp.app_template_filter('shorten_address') +def shorten_address(a): + _p = a[0:4] + _s = a[-4:] + return f'{_p}...{_s}' + +@bp.app_template_filter('humanize') +def humanize(d): + return arrow_get(d).humanize() diff --git a/suchwowx/models.py b/suchwowx/models.py new file mode 100644 index 0000000..bab68a8 --- /dev/null +++ b/suchwowx/models.py @@ -0,0 +1,13 @@ +from uuid import uuid4 + +from suchwowx.factory import db + + +def rand_id(): + return uuid4().hex + + +class User(db.Model): + __tablename__ = 'users' + + id = db.Column(db.Integer, primary_key=True) diff --git a/suchwowx/routes.py b/suchwowx/routes.py new file mode 100644 index 0000000..9d83185 --- /dev/null +++ b/suchwowx/routes.py @@ -0,0 +1,8 @@ +from flask import Blueprint + + +bp = Blueprint('meta', 'meta') + +@bp.route('/') +def index(): + return 'interplanetary memes' diff --git a/suchwowx/tasks/__init__.py b/suchwowx/tasks/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/suchwowx/tasks/config.py b/suchwowx/tasks/config.py new file mode 100644 index 0000000..fcc845a --- /dev/null +++ b/suchwowx/tasks/config.py @@ -0,0 +1,12 @@ +from huey import RedisHuey + +from suchwowx.factory import create_app_huey +from suchwowx import config + + +huey = RedisHuey( + host=config.CACHE_HOST, + port=config.CACHE_PORT +) + +app = create_app_huey()