Add dev bootstrapping, which i found laying around

...not sure what the status of this is, but might as well commit
This commit is contained in:
Lance Edgar 2021-06-11 17:40:42 -05:00
parent 1177ca6591
commit f9db799506
5 changed files with 482 additions and 0 deletions

59
dev/bootstrap.py Normal file
View file

@ -0,0 +1,59 @@
# -*- coding: utf-8; -*-
"""
Bootstrap development for Corporal
"""
import os
import subprocess
import sys
here = os.path.abspath(os.path.dirname(__file__))
def bootstrap():
if not inside_virtualenv():
return
# install wheel
subprocess.run(['pip', 'install', 'wheel'],
check=True)
# install invoke, sphinx
subprocess.run(['pip', 'install', 'invoke', 'Sphinx'],
check=True)
# run bootstrap task
os.chdir(here)
try:
if sys.platform == 'win32':
completed = subprocess.run(['invoke', 'bootstrap'])
else:
completed = subprocess.run(['invoke', '--echo', 'bootstrap'])
except KeyboardInterrupt:
sys.exit(130) # 128 + SIGINT
else:
sys.exit(completed.returncode)
def inside_virtualenv():
if not (hasattr(sys, 'real_prefix') or
(hasattr(sys, 'base_prefix') and sys.base_prefix != sys.prefix)):
print("")
print("Not running inside a virtual environment!")
print("")
print("Please create and activate that first, e.g. like:")
print("")
if sys.platform == 'win32':
print(" py -m venv C:\\envs\\corporal")
print(" C:\\envs\\corporal\\Scripts\\activate.bat")
else:
print(" python -m venv /srv/envs/corporal")
print(" source /srv/envs/corporal/bin/activate")
print("")
return False
return True
if __name__ == '__main__':
bootstrap()

146
dev/rattail.conf Normal file
View file

@ -0,0 +1,146 @@
############################################################
#
# Development config for Corporal
#
############################################################
[corepos]
office.url = http://localhost/fannie/
[corepos.api]
url = http://localhost/fannie/ws/
[corepos.db.office_op]
default.url = mysql+mysqlconnector://corepos:corepospass@localhost/core_op
default.pool_recycle = 3600
[corepos.db.office_trans]
default.url = mysql+mysqlconnector://corepos:corepospass@localhost/core_trans
default.pool_recycle = 3600
##############################
# rattail
##############################
[rattail]
app_title = Corporal
timezone.default = America/Chicago
datadir = <ENVDIR><SEP>app<SEP>data
batch.files = <ENVDIR><SEP>app<SEP>data<SEP>batch
workdir = <ENVDIR><SEP>app<SEP>work
[rattail.config]
# include = /etc/rattail/rattail.conf
configure_logging = true
usedb = true
preferdb = true
[rattail.db]
default.url = postgresql://<DBUSER>:<DBPASS>@<DBHOST>/<DBNAME>
versioning.enabled = true
[rattail.mail]
send_emails = false
smtp.server = localhost
templates = rattail:templates/mail
default.prefix = [Rattail]
default.from = rattail@localhost
default.to = root@localhost
# default.enabled = false
[rattail.pod]
pictures.gtin.root_url = https://rattailproject.org/pod/pictures/gtin
[rattail.upgrades]
files = <ENVDIR><SEP>app<SEP>data<SEP>upgrades
##############################
# alembic
##############################
[alembic]
script_location = rattail.db:alembic
version_locations = rattail.db:alembic/versions
##############################
# logging
##############################
[loggers]
keys = root, exc_logger, beaker, txn, sqlalchemy, django_db, flufl_bounce, requests
[handlers]
keys = file, console, email
[formatters]
keys = generic, console
[logger_root]
handlers = file, console
level = DEBUG
[logger_exc_logger]
qualname = exc_logger
handlers = email
level = ERROR
[logger_beaker]
qualname = beaker
handlers =
level = INFO
[logger_txn]
qualname = txn
handlers =
level = INFO
[logger_sqlalchemy]
qualname = sqlalchemy.engine
handlers =
# handlers = file
# level = INFO
[logger_django_db]
qualname = django.db.backends
handlers =
level = INFO
# level = DEBUG
[logger_flufl_bounce]
qualname = flufl.bounce
handlers =
level = WARNING
[logger_requests]
qualname = requests
handlers =
# level = WARNING
[handler_file]
class = handlers.RotatingFileHandler
args = (r'<ENVDIR><SEP>app<SEP>log<SEP>rattail.log', 'a', 1000000, 100, 'utf_8')
formatter = generic
[handler_console]
class = StreamHandler
args = (sys.stderr,)
formatter = console
# formatter = generic
# level = INFO
# level = WARNING
[handler_email]
class = handlers.SMTPHandler
args = ('localhost', 'rattail@localhost', ['root@localhost'], "[Rattail] Logging")
formatter = generic
level = ERROR
[formatter_generic]
format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(funcName)s: %(message)s
datefmt = %Y-%m-%d %H:%M:%S
[formatter_console]
format = %(levelname)-5.5s [%(name)s][%(threadName)s] %(funcName)s: %(message)s

7
dev/settings.ini Normal file
View file

@ -0,0 +1,7 @@
[devbootstrap]
dbhost = localhost
dbname = corporal
dbuser = rattail
dbpass = rattailpass
corporaluser = lance
corporalpass = lancepass

212
dev/tasks.py Normal file
View file

@ -0,0 +1,212 @@
# -*- coding: utf-8; -*-
"""
Development Tasks for Corporal
"""
import os
import configparser
import shutil
import sys
from invoke import task
from sphinx.util.console import bold
from sphinx.cmd.quickstart import do_prompt
from bootstrap import inside_virtualenv
here = os.path.abspath(os.path.dirname(__file__))
@task
def bootstrap(c):
"""
Bootstrap a development environment.
"""
if not inside_virtualenv():
sys.exit(1)
envdir = sys.prefix
upgrade_pip(c)
install_app_package(c)
appdir = make_appdir(c, envdir)
info = collect_info()
make_configs(c, envdir, appdir, info)
check_db(c, envdir, appdir)
install_db_schema(c, envdir, appdir)
make_admin_user(c, envdir, appdir, info)
print()
print(bold("============================================================"))
print()
print(bold(" Okay, you should be ready to go!"))
print()
print(bold("============================================================"))
print()
print("start your development web app with this command:")
print()
print(" cd {}".format(envdir))
if sys.platform == 'win32':
print(r" Scripts\pserve --reload file+ini:app\web.conf")
else:
print(" bin/pserve --reload file+ini:app/web.conf")
print()
print("then check out your development web app at:")
print()
print(" http://localhost:9080")
print()
def collect_info():
"""
Collect misc. dev info from user
"""
info = {}
print()
print(bold("Welcome to Corporal, the CORE supplement."))
config = configparser.ConfigParser()
if config.read(os.path.join(here, 'settings.ini')):
if config.has_section('devbootstrap'):
info = dict(config.items('devbootstrap'))
try:
print()
print("Please enter the details for your Corporal database.")
print()
info['dbhost'] = do_prompt('DB host',
default=info.get('dbhost', 'localhost'))
info['dbname'] = do_prompt('DB name',
default=info.get('dbname', 'corporal'))
info['dbuser'] = do_prompt('DB user',
default=info.get('dbuser', 'rattail'))
info['dbpass'] = do_prompt('DB password',
default=info.get('dbpass'))
print()
print("Please enter the details for your Corporal admin user.")
print()
info['corporaluser'] = do_prompt('Corporal username',
default=info.get('corporaluser', 'admin'))
info['corporalpass'] = do_prompt('Corporal password',
default=info.get('corporalpass'))
except (KeyboardInterrupt, EOFError):
print("\n[Interrupted.]")
sys.exit(130) # 128 + SIGINT
return info
def upgrade_pip(c):
"""
Upgrade pip and friends
"""
if sys.platform == 'win32':
c.run('python -m pip install -U pip')
else:
c.run('pip install -U pip')
c.run('pip install -U setuptools wheel')
def install_app_package(c):
"""
Install the Corporal app package
"""
project = os.path.abspath(os.path.join(here, os.pardir))
c.run('pip install -e {}'.format(project))
# c.run('pip install Corporal')
def make_appdir(c, envdir):
"""
Create the 'app' dir for virtual env
"""
appdir = os.path.join(envdir, 'app')
if not os.path.exists(appdir):
if sys.platform == 'win32':
c.run('{} make-appdir --path {}'.format(
os.path.join(envdir, 'Scripts', 'rattail'),
appdir))
else:
c.run('{}/bin/rattail make-appdir --path {}'.format(
envdir, appdir))
return appdir
def make_configs(c, envdir, appdir, info):
"""
Create app config files
"""
# rattail.conf
if not os.path.exists(os.path.join(appdir, 'rattail.conf')):
with open('rattail.conf') as f:
contents = f.read()
contents = contents.replace('<ENVDIR>', envdir)
contents = contents.replace('<SEP>', os.sep)
contents = contents.replace('<DBHOST>', info['dbhost'])
contents = contents.replace('<DBNAME>', info['dbname'])
contents = contents.replace('<DBUSER>', info['dbuser'])
contents = contents.replace('<DBPASS>', info['dbpass'])
with open(os.path.join(appdir, 'rattail.conf'), 'w') as f:
f.write(contents)
# quiet.conf
if not os.path.exists(os.path.join(appdir, 'quiet.conf')):
if sys.platform == 'win32':
c.run('{} make-config -T quiet -O {}'.format(
os.path.join(envdir, 'Scripts', 'rattail'),
appdir))
else:
c.run('{}/bin/rattail make-config -T quiet -O {}'.format(
envdir, appdir))
# web.conf
if not os.path.exists(os.path.join(appdir, 'web.conf')):
with open('web.conf') as f:
contents = f.read()
contents = contents.replace('<ENVDIR>', envdir)
contents = contents.replace('<SEP>', os.sep)
with open(os.path.join(appdir, 'web.conf'), 'w') as f:
f.write(contents)
def check_db(c, envdir, appdir):
"""
Do basic sanity checks for Corporal database
"""
if sys.platform == 'win32':
c.run('{} -c {} --no-versioning checkdb'.format(
os.path.join(envdir, 'Scripts', 'rattail'),
os.path.join(appdir, 'quiet.conf')))
else:
c.run('{}/bin/rattail -c {}/quiet.conf --no-versioning checkdb'.format(
envdir, appdir))
def install_db_schema(c, envdir, appdir):
"""
Install the schema for Corporal database
"""
if sys.platform == 'win32':
c.run('{} -c {} upgrade heads'.format(
os.path.join(envdir, 'Scripts', 'alembic'),
os.path.join(appdir, 'rattail.conf')))
else:
c.run('{}/bin/alembic -c {}/rattail.conf upgrade heads'.format(
envdir, appdir))
def make_admin_user(c, envdir, appdir, info):
"""
Make an admin user in the Corporal database
"""
if sys.platform == 'win32':
c.run('{} -c {} make-user --admin {} --password {}'.format(
os.path.join(envdir, 'Scripts', 'rattail'),
os.path.join(appdir, 'quiet.conf'),
info['corporaluser'], info['corporalpass']))
else:
c.run('{}/bin/rattail -c {}/quiet.conf make-user --admin {} --password {}'.format(
envdir, appdir, info['corporaluser'], info['corporalpass']))

58
dev/web.conf Normal file
View file

@ -0,0 +1,58 @@
############################################################
#
# Development web app config for Corporal
#
############################################################
##############################
# rattail
##############################
[rattail.config]
include = %(here)s<SEP>rattail.conf
##############################
# pyramid
##############################
[app:main]
use = egg:Corporal
pyramid.reload_templates = true
pyramid.debug_all = true
pyramid.default_locale_name = en
# you can enable this if you find it helpful
#pyramid.includes = pyramid_debugtoolbar
beaker.session.type = file
beaker.session.data_dir = %(here)s/sessions/data
beaker.session.lock_dir = %(here)s/sessions/lock
# this secret should only be used in development!
beaker.session.secret = b15zXlYNNIfzRjDjjyOL
beaker.session.key = rattail
pyramid_deform.tempdir = %(here)s/data/uploads
exclog.extra_info = true
rattail.config = %(__file__)s
[server:main]
use = egg:waitress#main
# to bind to all interfaces, set host to 0.0.0.0
host = 127.0.0.1
port = 9080
##############################
# logging
##############################
[handler_console]
level = INFO
[handler_file]
args = (r'<ENVDIR><SEP>app<SEP>log<SEP>web.log', 'a', 1000000, 100, 'utf_8')