Permalink
Browse files

First commit of catchphrase project

  • Loading branch information...
1 parent 15b6ec7 commit 7f7824fac78b97c785ad1a4c8072680e909ef44a @zachwill committed Sep 28, 2011
Showing with 535 additions and 175 deletions.
  1. +8 −145 README.md
  2. +444 −0 app/catchphrases.js
  3. +10 −0 app/utils.py
  4. +40 −10 app/views.py
  5. +2 −4 requirements.txt
  6. +1 −0 static/css/main.css
  7. +5 −0 static/css/main.less
  8. +1 −1 templates/404.html
  9. +3 −5 templates/base.html
  10. +10 −0 templates/home.html
  11. +11 −10 test.py
View
153 README.md
@@ -1,151 +1,14 @@
-Flask Heroku
-============
+Holy Catchphrase!
+=================
-<pre><code>
+**Holy Flask app on heroku, Batman!**
+All the catchphrases and action words I could find from the original
+Adam West Batman TV show, now in a conveniently named web app.
- ##
- ######### ###
- ## # ## :GG DG
- ## ## :EE EE ;E
- ## ## :EE KK ;E
- ## ## :EE ;E
- ## # ## #### #### :EEEEEEG KEEEE WE WEEE; ;E EE EE EE
- ###### ## ## #f # # :EE EE GEf;tEK EEKK EEfiEE, ;E fE EE EE
- ## # ## #l ## EE KE tE EK E; EE ;E E, EE EE
- ## ## ##a ### EK EEEEEEE EK E KE ;EEEE EE EE
- ## ## ## #s ### EK EE EK E KE ;E EE EE EE
- ## ## ## #k ## E EE EE EK E, EK ;E KE EE EE
- ## ## ## ##W # #: E EK ;EK.,EK EK EE,:EE, ;E ED KE.,EEE
- ##### ##### ### W# ####, EK ,KEEE K# DEEK. iK WK KEEE.
+### Sources ###
- github.com/zachwill/flask_heroku
+The catchphrases were [taken from this website](http://adamwest.tripod.com/robin.htm).
-</code></pre>
-
-
-What is this?
--------------
-
-A template to get your [Flask](http://flask.pocoo.org/) app running on
-[heroku](https://www.heroku.com/) as fast as possible. For added
-convenience, the templates use [Twitter's Bootstrap
-project](http://twitter.github.com/bootstrap/) to help reduce the amount
-of time it's takes you as a developer to go from an idea to a working
-site.
-
-All of the CSS stylesheets are written using the [Less
-CSS](http://lesscss.org/) syntax (even Bootstrap's CSS). If you're using
-Mac OS X for development, make sure to check out [incident57's
-Less.app](http://incident57.com/less/).
-
-Lastly, in heroku's production environment, your Flask application will
-be served through the [gevent Python module](http://www.gevent.org/)
-WSGI server.
-
-
-Why should I use this?
-----------------------
-
-Everything I've learned from writing and maintaining the [Flask
-Engine](https://github.com/zachwill/flask-engine) template for Google
-App Engine has made its way into this repo, too. The goal is to make a
-simple repo that can be cloned and added to for the majority of projects
-going forward, while also staying minimal in size and complexity.
-
-
-Instructions
-------------
-
-First, you'll need to clone the repo.
-
- $ git clone git@github.com:zachwill/flask_heroku.git
- $ cd flask_heroku
-
-Second, let's download `pip`, `virtualenv`, and the [`heroku` Ruby
-gem](http://devcenter.heroku.com/articles/using-the-cli).
-
- $ sudo easy_install pip
- $ sudo pip install virtualenv
- $ gem install heroku
-
-Next, we'll need to install `libevent` for the `gevent` production
-server. If you're operating on a Linux OS, you can `apt-get install
-libevent-dev`. If you're using Mac OS X, consider installing the
-[homebrew](http://mxcl.github.com/homebrew/) package manager, and run
-the following command:
-
- $ brew install libevent
-
-Now, you can setup an isolated environment with `virtualenv`.
-
- $ virtualenv --no-site-packages env
- $ source env/bin/activate
-
-Then, let's get the requirements installed in your isolated test
-environment.
-
- $ pip install -r requirements.txt
-
-Now, you can run the application locally.
-
- $ python bootstrap.py
-
-Or, to test the production configuration, simply run:
-
- $ python bootstrap.py --gevent
-
-You can also specify what port you'd prefer to use.
-
- $ python bootstrap.py --port 5555
-
-If you haven't [signed up for heroku](https://api.heroku.com/signup), go
-ahead and do that. You should then be able to [add your SSH key to
-heroku](http://devcenter.heroku.com/articles/quickstart), and also
-`heroku login` from the commandline.
-
-Now, to upload your application, you'll first need to do the
-following:
-
- $ heroku create --stack cedar
- $ git push heroku master
-
-Finally, we can scale the web process and make sure the application is
-up and running.
-
- $ heroku scale web=1
- $ heroku ps
-
-To get the name of your application -- and view it in your web browser
-(at `my-app-name.herokuapps.com`) -- run the following:
-
- $ heroku apps
-
-And, to deactivate `virtualenv` (once you've finished coding), you
-simply run the following command:
-
- $ deactivate
-
-
-Reactivating the Virtual Environment
-------------------------------------
-
-If you haven't worked with `virtualenv` before, you'll need to
-reactivate the environment everytime you close or reload your terminal.
-
- $ source env/bin/activate
-
-If you don't reactivate the environment, then you'll probably receive a
-screen full of errors when trying to run the application locally.
-
-
-Adding Requirements
--------------------
-
-In the course of creating your application, you may find yourself
-installing various Python modules with `pip` -- in which case you'll
-need to update the `requirements.txt` file. One way that this can be
-done is with `pip freeze`.
-
- $ pip freeze > requirements.txt
+And action words were [taken from this website](http://www.usfamily.net/web/wpattinson/otr/batman/batfgtwd.htm).
View
444 app/catchphrases.js
@@ -0,0 +1,444 @@
+{
+ "catchphrases": [
+ "Hamlet",
+ "flight plan",
+ "alter ego",
+ "rat trap",
+ "fireworks",
+ "hood-wink",
+ "masked potatoes",
+ "red snapper",
+ "human pearls",
+ "jelly moulds",
+ "nick of time",
+ "movie moguls",
+ "mechanical marvel",
+ "stomach ache",
+ "remote control robot",
+ "wedding cake",
+ "Frankenstein",
+ "Hollywood",
+ "crystal ball",
+ "human collector's item",
+ "uncanny photographic mental processes",
+ "nerve center",
+ "oil factory",
+ "reverse polarity",
+ "ice skates",
+ "complications",
+ "hieroglyphics",
+ "missing relatives",
+ "sudden incapacitation",
+ "one track batcomputer mind",
+ "Fourth Amendment",
+ "heart failure",
+ "purple cannibals",
+ "understatements",
+ "pin cushions",
+ "human surfboards",
+ "rising headlights",
+ "incantation",
+ "Robert Louis Stevenson",
+ "priceless collection of Etruscan snoods",
+ "cold creeps",
+ "here we go again",
+ "special delivery",
+ "return from oblivion",
+ "crucial moment",
+ "finishing touches",
+ "bargain basements",
+ "Rip Van Winkle",
+ "interplanetary yard stick",
+ "rock garden",
+ "Jack-in-the-Box",
+ "Fourth of July",
+ "interruptions",
+ "toreador",
+ "matador",
+ "guacamole",
+ "bat-logic",
+ "deposit slip",
+ "stratosphere",
+ "ghost writer",
+ "autobon",
+ "crack-up",
+ "miracle",
+ "astronomy",
+ "terminology",
+ "mashed potatoes",
+ "naivete",
+ "cliffhangers",
+ "sub-orbit",
+ "history",
+ "catastrophe",
+ "cryptology",
+ "trampoline",
+ "fork in the road",
+ "Titanic",
+ "hypotheses",
+ "bijou",
+ "split seconds",
+ "olfactory",
+ "jetset",
+ "tipoff",
+ "hamburger",
+ "Luthor Burbank",
+ "anagrams",
+ "haziness",
+ "contributing to the delinquency of minors",
+ "roadblocks",
+ "show-ups",
+ "Alps",
+ "hamstrings",
+ "underwritten metropolis",
+ "karats",
+ "known/unknown flying objects",
+ "unrefillable prescriptions",
+ "giveaways",
+ "astringent plum-like fruit",
+ "skull tap",
+ "ashtray",
+ "smoke",
+ "haberdashery",
+ "lodestone",
+ "rainbow",
+ "hallelujah",
+ "fishbowl",
+ "crossfire",
+ "red herring",
+ "serpentine",
+ "bouncing boiler-plated fits",
+ "transistors",
+ "rats in a trap",
+ "alphabet",
+ "ball and chain",
+ "fruit salad",
+ "New Year's Eve",
+ "homicide",
+ "reincarnation",
+ "explosion",
+ "helmets",
+ "happenstance",
+ "switcheroo",
+ "ricochet",
+ "jackpot",
+ "bat-trap",
+ "nightmare",
+ "Taj Mahal",
+ "tee shot",
+ "shrinkage",
+ "smokestack",
+ "camouflage",
+ "masquerade",
+ "asp",
+ "taxadermy",
+ "triple feat",
+ "kindergarten",
+ "Wayne Manor",
+ "puzzlers",
+ "oxygen",
+ "jitterbug",
+ "firing squad",
+ "Davey Jones",
+ "epicure",
+ "love birds",
+ "bunyons",
+ "olee-o",
+ "taxation",
+ "rocking chair",
+ "gunpowder",
+ "hairdo",
+ "forecast",
+ "Motor Von Bon",
+ "jawbreaker",
+ "sun dial",
+ "squirrel cage",
+ "hijackers",
+ "horseshoes",
+ "trasitor's bill",
+ "rainbow",
+ "fly trap",
+ "semantics",
+ "recompense",
+ "polar front",
+ "hijack",
+ "tuxedo",
+ "shamrocks",
+ "distortion",
+ "chicken coop",
+ "epigrams",
+ "travel agent",
+ "impossibility",
+ "metronome",
+ "apparition",
+ "perfect pitch",
+ "relief",
+ "piano",
+ "fugitives",
+ "fratricide",
+ "Caruso",
+ "greed",
+ "Sherlock Holmes",
+ "bank deposits",
+ "graft zepplin",
+ "voltage",
+ "seditives",
+ "memory bank",
+ "multitudes",
+ "sonic booms",
+ "holocaust",
+ "gambles",
+ "cinemascope",
+ "miscast",
+ "armadilloes",
+ "precision",
+ "dead end",
+ "bankruptcy",
+ "madness",
+ "stewpot",
+ "caffeine",
+ "flypaper",
+ "unlikelihood",
+ "jet set",
+ "hoaxes",
+ "hostage",
+ "agility",
+ "blackout",
+ "mucelage",
+ "timebomb",
+ "gemini",
+ "eggshells",
+ "ten toes",
+ "hyperdermics",
+ "detonation",
+ "gullibility",
+ "homework",
+ "dilemna",
+ "homecoming",
+ "tartars",
+ "gall",
+ "karate",
+ "hoofbeats",
+ "stuffing",
+ "grammar",
+ "Koufax",
+ "safari",
+ "headlines",
+ "iceberg",
+ "blizzard",
+ "snowball",
+ "backfire",
+ "felony",
+ "geography",
+ "sewer pipe",
+ "Venuzuela",
+ "stalactites",
+ "trolls and goblins",
+ "ordeuvres",
+ "jigsaw puzzle",
+ "stampede",
+ "human pearls",
+ "hidal burn",
+ "resourcefulness",
+ "mush",
+ "handiwork",
+ "self-service",
+ "mermaid",
+ "bulls-eye",
+ "stereo",
+ "shucks",
+ "diversionary tactics",
+ "Houdini",
+ "funny bone",
+ "hutzpah",
+ "clockwork",
+ "hunting horn",
+ "Zorro",
+ "living end",
+ "oversight",
+ "floor covering",
+ "escape hatch",
+ "chillblaines",
+ "polar ice sheet",
+ "standstills",
+ "riot ball",
+ "surprise parties",
+ "tintanabulation",
+ "rising hemlines",
+ "levitation",
+ "molars",
+ "knit one pearl two",
+ "slipped disc",
+ "mechanical armies",
+ "disappearing act",
+ "helplessness",
+ "human pressure cookers",
+ "non-sequiturs",
+ "barracuda",
+ "showcase",
+ "popcorn",
+ "hole in a donut",
+ "birthday cake",
+ "graveyard",
+ "schizophrenia",
+ "ravioli",
+ "conflagration",
+ "armour plate",
+ "wigs",
+ "magician",
+ "vacuum",
+ "Las Vegas",
+ "Benedict Arnold",
+ "hailstorms",
+ "murder",
+ "detonator",
+ "Cinderella",
+ "tome",
+ "trickery",
+ "cats",
+ "icepicks",
+ "knockout drops",
+ "hot foot",
+ "Romeo and Juliet",
+ "iodine",
+ "paraffin",
+ "spiderwebs",
+ "looking glass",
+ "impregnability",
+ "encore",
+ "Golden Gate",
+ "hurricane",
+ "whiskers",
+ "false front",
+ "skyrocket",
+ "headache",
+ "chocolate eclair",
+ "fog",
+ "rudder",
+ "straightjacket",
+ "blank cartridge",
+ "flip-flop",
+ "cliche",
+ "weaponry",
+ "dart",
+ "inquisition",
+ "deviltry",
+ "Blackbeard",
+ "green card",
+ "jail break",
+ "rheostat",
+ "Einstein",
+ "high wire",
+ "mainframe",
+ "corpusles",
+ "sarcophagus",
+ "cosmos",
+ "kilowatts",
+ "Bill of Rights",
+ "hot spot",
+ "IT&T",
+ "banks",
+ "hypnotism",
+ "harem",
+ "fate worse than death",
+ "hardest metal in the world",
+ "journey to the center of the earth",
+ "waste of energy",
+ "razor's edge",
+ "taxidermy",
+ "bluebeard",
+ "Parefski",
+ "heartbreak",
+ "vertebra",
+ "keyring",
+ "keyhole",
+ "mesmerism",
+ "pseudonym",
+ "hydraulics",
+ "floodgate"
+ ],
+ "actions": [
+ "aieee",
+ "aiieee",
+ "awk",
+ "awkkkkkk",
+ "bam",
+ "bang",
+ "bang-eth",
+ "bap",
+ "biff",
+ "bloop",
+ "blurp",
+ "boff",
+ "bonk",
+ "clange",
+ "clank",
+ "clank-est",
+ "clash",
+ "clunk",
+ "clunk-eth",
+ "cr-r-a-a-ck",
+ "crash",
+ "crr-aaack",
+ "crraack",
+ "crunch",
+ "crunch-eth",
+ "eee-yow",
+ "flrbbbbb",
+ "glipp",
+ "glurpp",
+ "kapow",
+ "kayo",
+ "ker-plop",
+ "ker-sploosh",
+ "klonk",
+ "krunch",
+ "ooooff",
+ "ouch",
+ "ouch-eth",
+ "owww",
+ "pam",
+ "plop",
+ "pow",
+ "powie",
+ "qunckkk",
+ "rakkk",
+ "rip",
+ "slosh",
+ "sock",
+ "spla-a-t",
+ "splatt",
+ "sploosh",
+ "swa-a-p",
+ "swish",
+ "swoosh",
+ "thunk",
+ "thwack",
+ "thwacke",
+ "thwape",
+ "thwapp",
+ "touche",
+ "uggh",
+ "urkk",
+ "urkkk",
+ "vronk",
+ "whack",
+ "whack-eth",
+ "wham-eth",
+ "whamm",
+ "whap",
+ "z-zwap",
+ "zam",
+ "zamm",
+ "zap",
+ "zapeth",
+ "zgruppp",
+ "zlonk",
+ "zlopp",
+ "zlott",
+ "zok",
+ "zowie",
+ "zwapp",
+ "zzzzzwap"
+ ]
+}
View
10 app/utils.py
@@ -0,0 +1,10 @@
+"""Helpful utility functions that do not deal with requests."""
+
+import simplejson as json
+
+
+def batman_words():
+ """Return available Batman words."""
+ with open('app/catchphrases.js') as f:
+ words = json.loads(f.read())
+ return words
View
50 app/views.py
@@ -5,22 +5,52 @@
application.
"""
-from flask import Blueprint, render_template, request, redirect, url_for
+import random
+from flask import Blueprint, render_template, request, jsonify, url_for
+from app.utils import batman_words
views = Blueprint('views', __name__, static_folder='../static',
template_folder='../templates')
-@views.route('/')
-def index():
- """Render website's index page."""
- return render_template('home.html')
+BATMAN_WORDS = batman_words()
+CATCHPHRASES = BATMAN_WORDS['catchphrases']
+ACTION_WORDS = BATMAN_WORDS['actions']
-@views.route('/about/')
-def about():
- """Render the website's about page."""
- return render_template('about.html')
+@views.route('/')
+def home():
+ """Render the website's home page."""
+ catchphrase = random_choice()
+ action = random_choice('action')
+ return render_template('home.html', action=action, catchphrase=catchphrase)
+
+
+@views.route('/api/<endpoint>')
+@views.route('/api')
+def interface(endpoint=None):
+ """API for available catchphrases and action words."""
+ catchphrases, action_words = CATCHPHRASES, ACTION_WORDS
+ if 'catchphrase' in endpoint:
+ data = {'catchphrases': catchphrases}
+ elif 'action' in endpoint:
+ data = {'actions': action_words}
+ else:
+ data = BATMAN_WORDS
+ return jsonify(data)
+
+
+@views.route('/random/<endpoint>')
+@views.route('/random')
+def random_choice(endpoint='catchphrase'):
+ """Return a random catchphrase or action word."""
+ # Local variables are faster.
+ catchphrases, action_words = CATCHPHRASES, ACTION_WORDS
+ if 'action' in endpoint:
+ choice = random.choice(action_words)
+ else:
+ choice = random.choice(catchphrases)
+ return choice
# The functions below should be applicable to all Flask apps.
@@ -45,7 +75,7 @@ def add_header(response):
and also to cache the rendered page for 10 minutes.
"""
response.headers['X-UA-Compatible'] = 'IE=Edge,chrome=1'
- response.headers['Cache-Control'] = 'public, max-age=600'
+ response.headers['Cache-Control'] = 'public, max-age=300'
return response
View
6 requirements.txt
@@ -2,7 +2,6 @@
# Flask
# ----------------------
flask
-flask-wtf
# ----------------------
@@ -12,10 +11,9 @@ mock
# ----------------------
-# Database
+# Utilities
# ----------------------
-sqlalchemy
-flask-sqlalchemy
+simplejson
# ----------------------
View
1 static/css/main.css
@@ -1,2 +1,3 @@
::-moz-selection{background:#8fc829;color:#fff;text-shadow:none;}
::selection{background:#8fc829;color:#fff;text-shadow:none;}
+body{margin-top:75px;}
View
5 static/css/main.less
@@ -8,3 +8,8 @@
/* Custom highlight */
::-moz-selection{ background:@green; color:#fff; text-shadow: none; }
::selection { background:@green; color:#fff; text-shadow: none; }
+
+
+body{
+ margin-top: 75px;
+}
View
2 templates/404.html
@@ -24,5 +24,5 @@
{% block main %}
<h1>404</h1>
<p>That page doesn't even exist.</p>
-<p>Why don't you just <a href="{{ url_for('views.index') }}">go back home</a>?</p>
+<p>Why don't you just <a href="{{ url_for('views.home') }}">go back home</a>?</p>
{% endblock %}
View
8 templates/base.html
@@ -7,7 +7,7 @@
<head>
<meta charset="utf-8">
- <title>{% block title %}yoursite.com{% endblock %}</title>
+ <title>{% block title %}Holy catchphrase, Batman!{% endblock %}</title>
<meta name="description" content="">
<meta name="author" content="">
@@ -33,9 +33,7 @@
<body>
- <header>
- {% include "header.html" %}
- </header>
+ <header></header>
<div id="main" role="main">
{% block main %}{% endblock %}
@@ -49,7 +47,7 @@
<!-- JavaScript at the bottom for fast page loading -->
<!-- Grab Google CDN's jQuery, with a protocol relative URL; fall back to local if necessary -->
- <script src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
+ <script src="//ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="/static/js/libs/jquery-1.6.2.min.js">\x3C/script>')</script>
View
10 templates/home.html
@@ -6,4 +6,14 @@
{% block main %}
+<div class="container">
+ <div class="row">
+ <div class="span8">
+ <h1>Holy {{ catchphrase }}, Batman!</h1>
+ </div>
+ <div class="span8">
+ <a href="#" class="btn primary">{{ action }}</a>
+ </div>
+ </div>
+</div>
{% endblock %}
View
21 test.py
@@ -17,14 +17,20 @@ def test_index_page_works(self):
self.assertTrue(rv.data)
self.assertEquals(rv.status_code, 200)
- def test_about_page_works(self):
- rv = self.app.get('/about/')
+ def test_api_works(self):
+ rv = self.app.get('/api')
self.assertTrue(rv.data)
self.assertEquals(rv.status_code, 200)
- def test_default_redirecting(self):
- rv = self.app.get('/about')
- self.assertEquals(rv.status_code, 301)
+ def test_api_for_catchphrases_works(self):
+ rv = self.app.get('/api/catchphrases')
+ self.assertTrue(rv.data)
+ self.assertEquals(rv.status_code, 200)
+
+ def test_api_for_actions_works(self):
+ rv = self.app.get('/api/actions')
+ self.assertTrue(rv.data)
+ self.assertEquals(rv.status_code, 200)
def test_404_page(self):
rv = self.app.get('/i-am-not-found/')
@@ -35,11 +41,6 @@ def test_static_text_file_request(self):
self.assertTrue(rv.data)
self.assertEquals(rv.status_code, 200)
- def test_qunit_javascript_tests(self):
- rv = self.app.get('/qunit/')
- assert 'QUnit Tests' in rv.data
- self.assertEquals(rv.status_code, 200)
-
if __name__ == '__main__':
unittest.main()

0 comments on commit 7f7824f

Please sign in to comment.