Source

flowrate / flowrate / run.py

Full commit
import optparse
import os
thisdir = os.path.abspath(os.path.dirname(__file__))
import sys

import cherrypy
from cherrypy.process import plugins
import simplejson

import flowrate
from flowrate import dbutil
from flowrate import variables


class Postgres(plugins.SimplePlugin):

    def __init__(self, bus, config):
        self.bus = bus
        self.config = config

    def start(self):
        self.bus.log("Connecting to Postgres database...")
        flowrate.set_db(
            'postgresql://%(user)s:%(password)s@%(host)s:%(port)s/%(database)s' %
            self.config, echo=False, max_overflow=10,
            strategy='threadlocal')
        self.bus.log("Connected to Postgres database.")
    start.priority = 30

    def recreate(self):
        d = dbutil.PgDatabase(**self.config)
        self.bus.log("Dropping Postgres database %s..." %
                     self.config['database'])
        d.drop_if_exists()
        self.bus.log("Creating Postgres database %s..." %
                     self.config['database'])
        d.create('flowrate.sql')
        self.bus.log("Postgres database created.")


class FlowrateApp(plugins.SimplePlugin):

    def __init__(self, bus, config):
        self.bus = bus
        self.config = config

    def start(self):
        self.bus.log("Mounting Flowrate application...")
        
        cherrypy.config.update({
            'server.socket_port': self.config['port'],
            'server.socket_host': self.config['host'],
            })
        appconf = {
            '/': {
                'tools.cpstats.on': True,
                'request.dispatch': cherrypy.dispatch.MethodDispatcher(),
                'tools.trailing_slash.status': 307,
            },
            "/okapi": {
                "tools.staticdir.on": True,
                "tools.staticdir.dir": os.path.join(thisdir, 'okapi'),
            },
            "/cpstats": {
                'request.dispatch': cherrypy.dispatch.Dispatcher(),
            },
            "/manager": {
                'request.dispatch': cherrypy.dispatch.Dispatcher(),
            },
        }
        cpenv = self.config.get('environment', 'development')
        if cpenv != 'development':
            appconf['global']['environment'] = cpenv

        cherrypy.server.statistics = True

        self.app = cherrypy.tree.mount(flowrate.root, '/', appconf)
    start.priority = 70


class EnvLoader(plugins.SimplePlugin):

    def __init__(self, bus):
        self.bus = bus

    def start(self):
        self.bus.log("Loading Flowrate variables...")

        allvars = dict(
            (row['name'], [row['expr'], row['variables']])
            for row in flowrate.db.execute("SELECT * FROM variables;"
                                           ).fetchall())

        # Evaluate in topological order.
        # Start with all the ones which reference no others.
        Q = [(name, expr)
             for name, (expr, refs) in allvars.iteritems() if not refs]
        while Q:
            name, expr = Q.pop()

            # Eval and store result.
            variables.bind(name, expr)

            # Mark all vars which reference "name".
            for k, (e, r) in allvars.iteritems():
                if name in r:
                    r.remove(name)
                    # Add if all references have been evaluated.
                    if not r:
                        Q.append((k, e))

        # Error if there are any circular definitions.
        remaining = [(name, expr, refs)
                     for name, (expr, refs) in allvars.iteritems() if refs]
        if remaining:
            raise ValueError("Circular dependencies found.", remaining)

        print "Environment:", variables.environment

    start.priority = Postgres.start.priority + 5


def run(config):
    cherrypy.engine.timeout_monitor.unsubscribe()
    Postgres(cherrypy.engine, config['db_info']).subscribe()
    EnvLoader(cherrypy.engine).subscribe()
    FlowrateApp(cherrypy.engine, config).subscribe()
    cherrypy.engine.start()
    cherrypy.engine.block()


usage = 'flowrate/run.py <config>'


if __name__ == '__main__':
    parser = optparse.OptionParser(prog='flowrate/run.py', usage=usage)
    options, args = parser.parse_args(sys.argv[1:])

    if len(args) != 1:
        parser.error("You must supply a config file path.")

    config = simplejson.loads(open(args[0], 'rb').read())
    run(config)