Organizing

Larger projects, long-running processes, and code that manages many and various routines, benefits from some organization. Organized code prevents many murders. Disorganized code causes m

# supervisor.py

import foobaz_interface
import summary_builder
import emailer
import traceback
import schedule
import time

class Supervisor():
    """Manages timing + exc of foobaz_interface pulls, summary_builder, and emailer."""
    def __init__(self, staging=False, 
        template_refresh_minutes=60, 
        fetch_form_minutes=5, 
        email_minutes=6):
        self.template_refresh_minutes = template_refresh_minutes
        self.fetch_form_minutes = fetch_form_minutes
        self.email_minutes  = email_minutes
        self.staging = staging

    def template_test(self):
        print(foobaz_interface.read_template_record()[0])

    def clock(self, staging):
        schedule.every(self.template_refresh_minutes).minutes.do(
            foobaz_interface.write_template_record)
        schedule.every(self.fetch_form_minutes).minutes.do(
            summary_builder.summarize, self.fetch_form_minutes)
        schedule.every(self.email_minutes).minutes.do(
            emailer.run, self.staging)

    def start(self):
        self.clock(self.staging)
        while True:
            schedule.run_pending()
            time.sleep(1)

# entry point for server deployment where we allow Supervisor to manage 
# the application. Recommend using systemd to run in production.
if __name__ == "__main__":
    print("Foobaz-Summarizer: Supervisor started as application manager.")
    s = Supervisor(staging=False) # Set to false for prod deployment.
    s.start()

 

# foobaz_request_strings.py
# Just a place to put foobaz endpoints
from env import *

f_headers   = {
        "X-API-TOKEN": ENV["foobaz_API_KEY"],
        "accept": "application/json",
    }

f_api = {
    "list_templates"        : "https://www.foobaz.com/api/list_thingthings?start=0&limit=9999",
    "get_template"          : "https://www.foobaz.com/api/get_thingthings/",
    "list_submissions"      : "https://www.foobaz.com/api/donestuffs", 
    "get_submission"        : "https://www.foobaz.com/api/donestuffs/obtain/", 
    "storage_url"           : "https://www.foobaz.com/api/users/banana/storage/",
    "list_teams"            : "https://www.foobaz.com/api/cults",
    "get_team"              : "https://www.foobaz.com/api/cults/", 
    "list_roles"            : "https://www.foobaz.com/api/userroles",
    "get_role"              : "https://www.foobaz.com/api/userroles/", 
    "list_users"            : "https://www.foobaz.com/api/users",
    "get_user"              : "https://www.foobaz.com/api/users/", 
    "list_locations"        : "https://www.foobaz.com/api/altars",
    "get_location"          : "https://www.foobaz.com/api/altars/", 
    "get_form_submissions"  : "https://www.foobaz.com/api/donestuffs/",
}

 

# foobaz_interface.py

from foobaz_request_strings import *
import requests
import traceback
import pprint
import json

# Updates a JSON file with the latest list of form templates in our foobaz account.

def list_templates():
    try:
        response = requests.get(f_api['list_things'], headers=f_headers)
        rdict = response.json()
        print("Status: " + str(rdict['status']))
        return rdict['results']
    except Exception:
        traceback.print_exc()
    return None

def get_template(form_id, path=ENV['THINGS_PATH']):
    url = f_api["get_template"] + str(form_id)
    filename = str(form_id) + ".json"
    response = requests.get(url, headers=f_headers)
    try:
        with open(path + filename, 'w') as f:
            f.write(json.dumps(response.json()))
        print("Cached " + filename)
    except Exception:
        traceback.print_exc()
    return response.json()
    
def write_template_record(path=ENV['THINGS_PATH']):
    # This should be called periodically to refresh the form template record.
    t_list = list_templates()
    try:
        fdata = json.dumps(t_list)
        with open(path + 'things.json', 'w') as f:
            f.write(fdata)
        print("Write things.json file success.")
        return "Success"
    except Exception:
        traceback.print_exc()
    print("Write things.json file failed.")
    return "Fail"

def read_template_record(path=ENV['TEMPLATES_PATH']):
    try:
        with open(path, 'r') as f:
            c = json.load(f)
            return c
    except Exception:
        traceback.print_exc()
    return "Fail"

def write_summary_config(config, path=ENV['SUMMARY_CONFIG_PATH']):
    # This is used by the configurator handler to update the config file for summarizing.
    try:
        fdata = json.dumps(config)
        with open(path, 'w') as f:
            f.write(fdata)
        print("Write summary_config.json file success.")
        return "Success"
    except Exception:
        traceback.print_exc()
    return "Fail"

def read_summary_config(path=ENV['SUMMARY_CONFIG_PATH']):
    # Used by summary_builder to find out which things to summarize, and where to send them.
    try:
        with open(path, 'r') as f:
            c = json.load(f)
            return c
    except Exception:
        traceback.print_exc()
    return "Fail"

def get_storage_file(s3_key):
    url = f_api["storage_url"]
    params = {"path": s3_key}
    response = requests.get(url, headers=f_headers, params=params)
    return response.json()["data"]["altar"]