Skip to content

Instantly share code, notes, and snippets.

@danhammer
Created May 16, 2019 16:08
Show Gist options
  • Select an option

  • Save danhammer/1055e918822b8261a7987750ddd02259 to your computer and use it in GitHub Desktop.

Select an option

Save danhammer/1055e918822b8261a7987750ddd02259 to your computer and use it in GitHub Desktop.
Basic and simple code for a web service (Heroku and Flask) to serve out data on film scripts, after processing by USC
"""A Flask web app to serve locally stored data on film scripts."""
import glob
import json
import os
from flask import Flask, jsonify, request
app = Flask(__name__)
app.config['JSON_SORT_KEYS'] = False
SCRIPT_DATA_DIR = os.path.join(os.path.dirname(__file__), 'character_files')
DEMO_APIKEY = '0123456789'
@app.route('/')
def welcome():
invitation = ('This web app provides functionality from the endpoints '
'listed below. Click a link for relevant instructions.')
msg = {
'Invitation': invitation,
'Retrieve data on character gender and prominence in film scripts':
''.join((request.url, 'network?'))
}
return jsonify(msg)
@app.route('/network')
def network():
"""Retrieve locally stored data on film scripts."""
msg = _help_msg(
request.base_url, 'script=star_trek&apikey=MY_SECRET_KEY',
_format_network_args())
try:
_validate_apikey(request.args)
script_data = _load_script_data(request.args)
except (ValueError, FileNotFoundError) as e:
msg['Exception'] = repr(e)
return jsonify(msg)
return jsonify(script_data)
def _validate_apikey(args):
"""Validate key from url args against a static DEMO_KEY.
Raises: ValueError for an invalid key.
Returns: None
"""
key = args.get('apikey', default='')
if key != DEMO_APIKEY:
raise ValueError('A valid API key is required.')
def _load_script_data(args):
"""Parse url args for script name and load available data.
Returns: JSON-formatted dict
"""
known_scripts = _gather_script_names(SCRIPT_DATA_DIR)
script = args.get('script', default='')
script = script.lower().strip()
if script not in known_scripts:
raise ValueError('A valid script name is required.')
with open(os.path.join(SCRIPT_DATA_DIR, script + '.json')) as f:
script_data = json.load(f)
return script_data
def _gather_script_names(data_dir):
"""Collect names of JSON data files in data_dir.
Returns: List of filenames with suffix stripped.
"""
paths = glob.glob(os.path.join(data_dir, '*.json'))
names = [os.path.basename(p) for p in paths]
names = [n.split('.json')[0] for n in names]
return names
# Help messaging
def _help_msg(base_url, url_args, notes):
msg = {
'Usage': '{}?{}'.format(base_url, url_args),
'Notes': notes
}
return msg
def _format_network_args():
"""Produce a dict explaining args for help messaging."""
known_scripts = _gather_script_names(SCRIPT_DATA_DIR)
network_args = {
'Required arguments': {
'script': 'One of {}'.format(
known_scripts),
'apikey': 'A secret alpha-numeric key.'
}
}
return network_args
if __name__ == '__main__':
app.run(debug=False, host='0.0.0.0')
version: '2'
services:
web:
build: .
ports:
- "5000:5000"
volumes:
- ./webapp:/opt/webapp
tty: true
FROM ubuntu:latest
RUN apt-get update && apt-get install -y software-properties-common
RUN apt-get install -y python3-pip python3-dev build-essential
RUN pip3 install --upgrade pip
ENV DEBIAN_FRONTEND noninteractive
ADD ./requirements.txt /tmp/requirements.txt
# Install dependencies
RUN pip install -r /tmp/requirements.txt
# Add our code
ADD ./webapp /opt/webapp/
WORKDIR /opt/webapp
# To deploy locally
CMD python3 app.py
{"nodes": [{"count": 8, "name": "LIEUTENANT MITAKA", "sno": 1, "bechdel": 0, "race": "caucasian", "gender": "male"}, {"count": 141, "name": "REY", "sno": 2, "bechdel": 1, "race": "caucasian", "gender": "female"}, {"count": 10, "name": "CAPTAIN PHASMA", "sno": 3, "bechdel": 0, "race": "caucasian", "gender": "female"}, {"count": 136, "name": "HAN", "sno": 4, "bechdel": 0, "race": "caucasian", "gender": "male"}, {"count": 11, "name": "BALATIK", "sno": 5, "bechdel": 0, "race": "unknown", "gender": "male"}, {"count": 19, "name": "MAZ", "sno": 6, "bechdel": 1, "race": "african", "gender": "female"}, {"count": 23, "name": "GENERAL HUX", "sno": 7, "bechdel": 0, "race": "caucasian", "gender": "male"}, {"count": 7, "name": "SNAP", "sno": 8, "bechdel": 0, "race": "caucasian", "gender": "male"}, {"count": 27, "name": "LEIA", "sno": 9, "bechdel": 0, "race": "caucasian", "gender": "female"}, {"count": 151, "name": "FINN", "sno": 10, "bechdel": 0, "race": "african", "gender": "male"}, {"count": 11, "name": "STORMTROOPER", "sno": 11, "bechdel": 0, "race": "unknown", "gender": "male"}, {"count": 63, "name": "POE", "sno": 12, "bechdel": 0, "race": "mixed", "gender": "male"}, {"count": 58, "name": "KYLO REN", "sno": 13, "bechdel": 0, "race": "caucasian", "gender": "male"}, {"count": 19, "name": "CONTINUED", "sno": 14, "bechdel": 0, "race": "unknown", "gender": "unknown"}, {"count": 14, "name": "SNOKE", "sno": 15, "bechdel": 0, "race": "mixed", "gender": "male"}], "edges": [{"source": 0, "strength": 3.0, "target": 6}, {"source": 0, "strength": 1.0, "target": 9}, {"source": 0, "strength": 1.0, "target": 11}, {"source": 0, "strength": 7.0, "target": 12}, {"source": 1, "strength": 60.0, "target": 3}, {"source": 1, "strength": 2.0, "target": 4}, {"source": 1, "strength": 9.0, "target": 5}, {"source": 1, "strength": 3.0, "target": 6}, {"source": 1, "strength": 3.0, "target": 8}, {"source": 1, "strength": 115.0, "target": 9}, {"source": 1, "strength": 4.0, "target": 10}, {"source": 1, "strength": 1.0, "target": 11}, {"source": 1, "strength": 15.0, "target": 12}, {"source": 1, "strength": 7.0, "target": 13}, {"source": 1, "strength": 3.0, "target": 14}, {"source": 2, "strength": 1.0, "target": 3}, {"source": 2, "strength": 3.0, "target": 6}, {"source": 2, "strength": 4.0, "target": 9}, {"source": 2, "strength": 2.0, "target": 11}, {"source": 2, "strength": 3.0, "target": 12}, {"source": 2, "strength": 1.0, "target": 13}, {"source": 3, "strength": 60.0, "target": 1}, {"source": 3, "strength": 1.0, "target": 2}, {"source": 3, "strength": 13.0, "target": 4}, {"source": 3, "strength": 14.0, "target": 5}, {"source": 3, "strength": 1.0, "target": 6}, {"source": 3, "strength": 3.0, "target": 7}, {"source": 3, "strength": 27.0, "target": 8}, {"source": 3, "strength": 60.0, "target": 9}, {"source": 3, "strength": 3.0, "target": 10}, {"source": 3, "strength": 5.0, "target": 11}, {"source": 3, "strength": 16.0, "target": 12}, {"source": 3, "strength": 6.0, "target": 13}, {"source": 3, "strength": 1.0, "target": 14}, {"source": 4, "strength": 2.0, "target": 1}, {"source": 4, "strength": 13.0, "target": 3}, {"source": 4, "strength": 4.0, "target": 9}, {"source": 4, "strength": 1.0, "target": 14}, {"source": 5, "strength": 9.0, "target": 1}, {"source": 5, "strength": 14.0, "target": 3}, {"source": 5, "strength": 6.0, "target": 9}, {"source": 5, "strength": 1.0, "target": 10}, {"source": 5, "strength": 1.0, "target": 12}, {"source": 5, "strength": 1.0, "target": 13}, {"source": 6, "strength": 3.0, "target": 0}, {"source": 6, "strength": 3.0, "target": 1}, {"source": 6, "strength": 3.0, "target": 2}, {"source": 6, "strength": 1.0, "target": 3}, {"source": 6, "strength": 1.0, "target": 7}, {"source": 6, "strength": 4.0, "target": 9}, {"source": 6, "strength": 4.0, "target": 11}, {"source": 6, "strength": 8.0, "target": 12}, {"source": 6, "strength": 1.0, "target": 13}, {"source": 6, "strength": 10.0, "target": 14}, {"source": 7, "strength": 3.0, "target": 3}, {"source": 7, "strength": 1.0, "target": 6}, {"source": 7, "strength": 6.0, "target": 11}, {"source": 7, "strength": 2.0, "target": 13}, {"source": 8, "strength": 3.0, "target": 1}, {"source": 8, "strength": 27.0, "target": 3}, {"source": 8, "strength": 8.0, "target": 9}, {"source": 8, "strength": 1.0, "target": 10}, {"source": 8, "strength": 7.0, "target": 11}, {"source": 8, "strength": 1.0, "target": 13}, {"source": 9, "strength": 1.0, "target": 0}, {"source": 9, "strength": 115.0, "target": 1}, {"source": 9, "strength": 4.0, "target": 2}, {"source": 9, "strength": 60.0, "target": 3}, {"source": 9, "strength": 4.0, "target": 4}, {"source": 9, "strength": 6.0, "target": 5}, {"source": 9, "strength": 4.0, "target": 6}, {"source": 9, "strength": 8.0, "target": 8}, {"source": 9, "strength": 2.0, "target": 10}, {"source": 9, "strength": 28.0, "target": 11}, {"source": 9, "strength": 8.0, "target": 12}, {"source": 9, "strength": 8.0, "target": 13}, {"source": 10, "strength": 4.0, "target": 1}, {"source": 10, "strength": 3.0, "target": 3}, {"source": 10, "strength": 1.0, "target": 5}, {"source": 10, "strength": 1.0, "target": 8}, {"source": 10, "strength": 2.0, "target": 9}, {"source": 10, "strength": 1.0, "target": 11}, {"source": 10, "strength": 4.0, "target": 12}, {"source": 10, "strength": 2.0, "target": 13}, {"source": 11, "strength": 1.0, "target": 0}, {"source": 11, "strength": 1.0, "target": 1}, {"source": 11, "strength": 2.0, "target": 2}, {"source": 11, "strength": 5.0, "target": 3}, {"source": 11, "strength": 4.0, "target": 6}, {"source": 11, "strength": 6.0, "target": 7}, {"source": 11, "strength": 7.0, "target": 8}, {"source": 11, "strength": 28.0, "target": 9}, {"source": 11, "strength": 1.0, "target": 10}, {"source": 11, "strength": 11.0, "target": 12}, {"source": 11, "strength": 1.0, "target": 13}, {"source": 12, "strength": 7.0, "target": 0}, {"source": 12, "strength": 15.0, "target": 1}, {"source": 12, "strength": 3.0, "target": 2}, {"source": 12, "strength": 16.0, "target": 3}, {"source": 12, "strength": 1.0, "target": 5}, {"source": 12, "strength": 8.0, "target": 6}, {"source": 12, "strength": 8.0, "target": 9}, {"source": 12, "strength": 4.0, "target": 10}, {"source": 12, "strength": 11.0, "target": 11}, {"source": 12, "strength": 5.0, "target": 13}, {"source": 12, "strength": 8.0, "target": 14}, {"source": 13, "strength": 7.0, "target": 1}, {"source": 13, "strength": 1.0, "target": 2}, {"source": 13, "strength": 6.0, "target": 3}, {"source": 13, "strength": 1.0, "target": 5}, {"source": 13, "strength": 1.0, "target": 6}, {"source": 13, "strength": 2.0, "target": 7}, {"source": 13, "strength": 1.0, "target": 8}, {"source": 13, "strength": 8.0, "target": 9}, {"source": 13, "strength": 2.0, "target": 10}, {"source": 13, "strength": 1.0, "target": 11}, {"source": 13, "strength": 5.0, "target": 12}, {"source": 13, "strength": 1.0, "target": 14}, {"source": 14, "strength": 3.0, "target": 1}, {"source": 14, "strength": 1.0, "target": 3}, {"source": 14, "strength": 1.0, "target": 4}, {"source": 14, "strength": 10.0, "target": 6}, {"source": 14, "strength": 8.0, "target": 12}, {"source": 14, "strength": 1.0, "target": 13}]}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment