# -*- coding: utf-8; -*- """ Development Tasks for Theo """ 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 Theo, the order system.")) 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 Theo database.") print() info['dbhost'] = do_prompt('DB host', default=info.get('dbhost', 'localhost')) info['dbname'] = do_prompt('DB name', default=info.get('dbname', 'theo')) 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 Theo admin user.") print() info['theouser'] = do_prompt('Theo username', default=info.get('theouser', 'admin')) info['theopass'] = do_prompt('Theo password', default=info.get('theopass')) 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 Theo app package """ project = os.path.abspath(os.path.join(here, os.pardir)) c.run('pip install -e {}'.format(project)) c.run('pip install tailbone-theo[app]') 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) contents = contents.replace('', os.sep) contents = contents.replace('', info['dbhost']) contents = contents.replace('', info['dbname']) contents = contents.replace('', info['dbuser']) contents = contents.replace('', 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)) # nodb.conf if not os.path.exists(os.path.join(appdir, 'nodb.conf')): shutil.copyfile('nodb.conf', os.path.join(appdir, 'nodb.conf')) # 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) contents = contents.replace('', 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 Theo database """ if sys.platform == 'win32': c.run('{} -c {} -c {} --no-versioning checkdb'.format( os.path.join(envdir, 'Scripts', 'rattail'), os.path.join(appdir, 'quiet.conf'), os.path.join(appdir, 'nodb.conf'))) else: c.run('{0}/bin/rattail -c {1}/quiet.conf -c {1}/nodb.conf --no-versioning checkdb'.format( envdir, appdir)) def install_db_schema(c, envdir, appdir): """ Install the schema for Theo 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 Theo 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['theouser'], info['theopass'])) else: c.run('{}/bin/rattail -c {}/quiet.conf make-user --admin {} --password {}'.format( envdir, appdir, info['theouser'], info['theopass']))