Converted app into a package

This commit is contained in:
Armin Ronacher 2010-05-02 16:52:15 +02:00
parent ef7818e10e
commit 904fe68d51
22 changed files with 49 additions and 35 deletions

14
flask_website/__init__.py Normal file
View file

@ -0,0 +1,14 @@
from flask import Flask, render_template
app = Flask(__name__)
@app.errorhandler(404)
def not_found(error):
return render_template('404.html'), 404
from flask_website.views.general import general
from flask_website.views.mailinglist import mailinglist
from flask_website.views.snippets import snippets
app.register_module(general)
app.register_module(mailinglist)
app.register_module(snippets)

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View file

@ -0,0 +1,34 @@
$(function() {
var first_mail = $('div.mail:first')[0].id;
function display(id) {
var pos = {
x: window.pageXOffset || document.body.scrollLeft,
y: window.pageYOffset || document.body.scrollTop
};
$('ul.mailtree div.link').removeClass('selected');
$('#link-' + id).addClass('selected').focus();
$('div.mail').hide();
$('h2:first').text($('h3', $('#' + id).show()).text());
if (!(document.location.hash == '' && id == first_mail))
document.location.href = '#' + id;
window.scrollTo(pos.x, pos.y);
}
$('div.mail')
.addClass('dynamic-mail')
.appendTo($('<div></div>').insertBefore('div.mail:first'))
.hide();
$('div.mail h3').hide();
$('div.link').each(function() {
var id = $('a', $(this).parent()).attr('href').substr(1);
$(this).click(function() {
display(id);
return false;
});
}).css({cursor: 'pointer'});
var href = document.location.href.split(/#/, 2)[1];
display(href != null ? href : first_mail);
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View file

@ -0,0 +1,47 @@
body { font-family: 'Georgia', serif; font-size: 17px; color: #000; }
a { color: #004B6B; }
a:hover { color: #6D4100; }
.box { width: 540px; margin: 40px auto; }
h1, h2, h3 { font-family: 'Garamond', 'Georgia', serif; font-weight: normal; }
h2 { font-size: 28px; margin: 15px 0 5px 0; }
h3 { font-size: 22px; margin: 15px 0 5px 0; }
code,
pre { font-family: 'Consolas', 'Menlo', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono',
monospace; font-size: 15px; background: #eee; }
pre { padding: 7px 30px; margin: 15px -30px; line-height: 1.3; }
.ig { color: #888; }
p { line-height: 1.4; }
ul { margin: 15px 0 15px 0; padding: 0; list-style: none; line-height: 1.4; }
ul li:before { content: "\00BB \0020"; color: #888; position: absolute; margin-left: -19px; }
blockquote { margin: 0; font-style: italic; color: #444; }
.footer { font-size: 13px; color: #888; text-align: right; margin-top: 25px; }
.nav { text-align: center; }
.nav a { font-style: italic; }
.backnav { float: right; color: #444; font-style: italic;
margin: 5px 0 0 0; font-size: 0.9em; }
/* mailinglist */
.pagination { text-align: center; font-size: 15px; margin: 20px 0 0 0; }
.disabled { color: #888; }
.archive .meta { font-size: 0.9em; display: block; margin: 0 0 0.5em 1em; }
.mailtree { border-top: 1px solid black; padding: 5px 12px 5px 12px;
border-bottom: 1px solid black; font-size: 14px;
max-height: 100px; overflow: auto; }
.mailtree ul { margin: 0 0 0 15px; line-height: 1.5; }
.mailtree li:before { display: none; }
.mailtree .selected { background: #fafafa; }
.mailtree .selected:before { content: "\00BB\0020"; color: #888;
position: relative; margin-left: -12px;
width: 12px!important; }
.mail { margin: 15px 0; }
.children .mail { margin: 15px 0 15px 20px; }
.dynamic-mail { margin-left: 0!important; }
.mail dl { margin: 0; padding-bottom: 15px;
border-bottom: 1px solid black; }
.mail dl dt { color: #888; width: 70px; float: left; height: 20px; }
.mail dl dd { height: 20px; width: 500px; }
.mail dl dd.from { text-decoration: underline; }
.mail pre { background: transparent; font-size: 13px;
line-height: 1.15; }
.mail .quote { color: #004B6B; }
.mail .sig { color: #888; }

View file

@ -0,0 +1,47 @@
<!doctype html>
<title>Chapter 404: The Lost Page</title>
<style type=text/css>
body, html {
height: 100%;
margin: 0;
padding: 0;
}
body {
background: url(/static/ship.png) no-repeat center right;
}
body:after {
content: "";
display: block;
position: absolute;
top: 0;
bottom: 0;
width: 30px;
background: url(/static/mask.png) repeat-y left;
}
a { color: #004B6B; }
a:hover { color: #6D4100; }
h1 {
font-family: 'Garamond', 'Georgia', serif;
font-weight: normal;
color: #222;
font-size: 36px;
padding: 50px 0 10px 50px;
margin: 0;
}
p {
font-family: 'Georgia', serif;
color: #000;
font-size: 17px;
padding: 10px 0 0 90px;
margin: 0;
width: 360px;
}
</style>
<h1>Chapter 404: The Lost Page</h1>
<p>A careful and diligent search has been made for the desired page, but it just cannot be found.
<p>And so they returned to <a href=/>familiar waters</a>.

View file

@ -0,0 +1,72 @@
{% extends "layout.html" %}
{% block head %}
{{ super() }}
<style type=text/css>
h1 { margin: 0 0 30px 0; background: url(/static/logo.png) no-repeat center; height: 165px; }
h1 span, p.tagline { display: none; }
</style>
{% endblock %}
{% block body_title %}
{{ super() }}
<p class=tagline>because sometimes a pocket knife is not enough
{% endblock %}
{% block body %}
<blockquote>
Flask is a microframework for Python based on Werkzeug, Jinja 2 and good intentions.
And before you ask: It's <a href=docs/license/>BSD licensed</a>!
</blockquote>
<h2>Flask is Fun</h2>
<pre><span class=ig>from flask import Flask
app = Flask(__name__)</span>
@app.route("/")
def hello():
return "Hello World!"
<span class=ig>if __name__ == "__main__":
app.run()</span></pre>
<h2>And Easy to Setup</h2>
<pre><span class=ig>$ </span>easy_install Flask
<span class=ig>$ </span>python hello.py
<span class=ig> * Running on http://localhost:5000/</span></pre>
<h2>Interested?</h2>
<ul>
<li>
<a href=docs/>Read the documentation</a> or download as
<a href=docs/flask-docs.pdf>PDF</a> and
<a href=docs/flask-docs.zip>zipped HTML</a>
<li><a href=mailinglist/>Join the mailinglist</a>
<li><a href=http://github.com/mitsuhiko/flask>Fork it on github</a>
<li><a href=http://pypi.python.org/pypi/Flask>Download it from PyPI</a>
</ul>
<h2>Whats in the Box?</h2>
<ul>
<li>built in development server and <a href=docs/quickstart/#debug-mode>debugger</a>
<li>integrated support for <a href=docs/testing/>unittesting support</a>
<li>RESTful <a href=docs/quickstart/#routing>request dispatching</a>
<li>uses <a href=http://jinja.pocoo.org/2/documentation/templates>Jinja2 templating</a>
<li>support for <a href=docs/quickstart/#sessions>secure cookies</a> (client side sessions)
<li>100% <a href=http://www.python.org/dev/peps/pep-0333/>WSGI 1.0</a> compliant
<li>Unicode based
</ul>
<h2>What do Flask Apps look like?</h2>
<p>
If you are looking for some example code of applications written with Flask,
have a look at the sources of the examples on github:
<ul>
<li><a href=http://github.com/mitsuhiko/flask/tree/master/examples/flaskr/>flaskr</a>
— a microblog
<li><a href=http://github.com/mitsuhiko/flask/tree/master/examples/minitwit/>minitwit</a>
— a twitter clone
<li><a href=http://github.com/mitsuhiko/flask/tree/website>this website</a>
— static pages + mailinglist archives
</ul>
<h2>Contribute</h2>
<p>Found a bug? Have a good idea for improving Flask? Head over to
<a href=http://github.com/mitsuhiko/flask>Flask's github</a> page and
create a new ticket or fork. If you just want to chat with fellow
developers, go to <code>#pocoo</code> on irc.freenode.net.
<a href="http://github.com/mitsuhiko/flask"><img style="position: fixed; top: 0; right: 0; border: 0;"
src="http://s3.amazonaws.com/github/ribbons/forkme_right_gray_6d6d6d.png" alt="Fork me on GitHub"></a>
{% endblock %}

View file

@ -0,0 +1,20 @@
<!doctype html>
{% block head %}
<title>{% block title %}Welcome{% endblock %} | Flask (A Python Microframework)</title>
<meta charset=utf-8>
<link rel=stylesheet type=text/css href="/static/style.css">
<script type=text/javascript
src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
{% endblock %}
<div class=box>
{% block body_title %}
<h1><span>{{ self.title() }}</span></h1>
{% endblock %}
<p class=nav>
<a href=/>overview</a> //
<a href=/docs/>documentation</a> //
<a href=/mailinglist/>mailinglist</a> //
<a href=/snippets/>snippets</a>
{% block body %}{% endblock %}
<p class=footer>&copy; Copyright 2010 by <a href=http://lucumr.pocoo.org/>Armin Ronacher</a>
</div>

View file

@ -0,0 +1,27 @@
{% extends "mailinglist/layout.html" %}
{% block title %}Mailinglist Archive{% endblock %}
{% block body %}
<h2>Mailinglist Archive</h2>
<ul class=archive>
{% for thread in threads %}
<li><a href="{{ thread.url }}">{{ thread.title }}</a>
<span class=meta>
by {{ thread.author_name or thread.author_email }}
on {{ thread.date.strftime('%Y-%m-%d @ %H:%M') }}
({{ thread.reply_count }} repl{{ thread.reply_count == 1 and 'y' or 'ies' }})</span>
{% endfor %}
</ul>
<div class=pagination>
{% if page > 1 %}
<a href="{{ url_for('mailinglist.archive', page=page - 1) }}">&laquo; Previous</a>
{% else %}
<span class=disabled>&laquo; Previous</span>
{% endif %}
| <strong>{{ page }}</strong> |
{% if page < page_count %}
<a href="{{ url_for('mailinglist.archive', page=page + 1) }}">Next &raquo;</a>
{% else %}
<span class=disabled>Next &raquo;</span>
{% endif %}
</div>
{% endblock %}

View file

@ -0,0 +1,20 @@
{% extends "mailinglist/layout.html" %}
{% block title %}Mailinglist{% endblock %}
{% block body %}
<p>
There is a mailinglist for Flask hosted on <a
href=http://librelist.com/>librelist</a> you can use for both user requests
and development discussions.
<p>
To subscribe, send a mail to <em>flask@librelist.com</em> and reply
to the confirmation mail. Make sure to check your Spam folder, just in
case. To unsubscribe again, send a mail to
<em>flask-unsubscribe@librelist.com</em> and reply to the
confirmation mail.
<p>
The <a href="{{ url_for('mailinglist.archive') }}">mailinglist archive</a>
is synched every hour. Go there to read up old discussions grouped by
thread.
{% endblock %}

View file

@ -0,0 +1,11 @@
{% extends "layout.html" %}
{% block head %}
{{ super() }}
<style type=text/css>
h1 { margin: 0 0 30px 0; background: url(/static/mailinglist.png) no-repeat center; height: 165px; }
h1 span { display: none; }
</style>
{% endblock %}
{% block body_title %}
<h1><span>Flask Mailinglist</span></h1>
{% endblock %}

View file

@ -0,0 +1,36 @@
{% extends "mailinglist/layout.html" %}
{% block title %}{{ thread.title }}{% endblock %}
{% block head %}
{{ super() }}
<script type=text/javascript src=/static/mailinglist.js></script>
{% endblock %}
{% block body %}
<p class=backnav>
<a href=/mailinglist/archive/>&laquo; back to archive</a>
<h2>{{ thread.title }}</h2>
<ul class=mailtree>
{% for mail in [thread.root] recursive %}
<li><div class=link id="link-{{ mail.id }}"><a href="#{{
mail.id }}">{{ mail.subject }}</a> by {{
mail.author_name or mail.author_email }}</div>
{% if mail.children %}<ul>{{ loop(mail.children) }}</ul>{% endif %}
{% endfor %}
</ul>
{% for mail in [thread.root] recursive %}
<div class=mail id="{{ mail.id }}">
<h3>{{ mail.subject }}</h3>
<dl>
<dt>From:
<dd class=from>{{ mail.author_name or mail.author_email }}
<dt>Date:
<dd>{{ mail.date.strftime('%Y-%m-%d @ %H:%M') }}
</dl>
<pre>{{ mail.rendered_text }}</pre>
{% if mail.children %}
<div class=children>{{ loop(mail.children) }}</div>
{% endif %}
</div>
{% endfor %}
{% endblock %}

View file

@ -0,0 +1,17 @@
{% extends "snippets/layout.html" %}
{% block title %}Snippets Archive{% endblock %}
{% block body %}
<p>
Welcome to the Flask snippet archive. This is the place where anyone
can drop helpful pieces of code for others to use.
<p>
In order to add snippets to this page or to add comments, all you need
is an <a href=http://en.wikipedia.org/wiki/OpenID>OpenID</a> account.
<form action=/snippets/search/ method=get>
<p>
Search snippets:
<input type=text name=q size=30>
<input type=submit value=Search>
</form>
<h2>Snippets by Category</h2>
{% endblock %}

View file

@ -0,0 +1,11 @@
{% extends "layout.html" %}
{% block head %}
{{ super() }}
<style type=text/css>
h1 { margin: 0 0 30px 0; background: url(/static/snippets.png) no-repeat center; height: 165px; }
h1 span { display: none; }
</style>
{% endblock %}
{% block body_title %}
<h1><span>Flask Snippets</span></h1>
{% endblock %}

View file

View file

@ -0,0 +1,8 @@
from flask import Module, render_template
general = Module(__name__)
@general.route('/')
def index():
return render_template('general/index.html')

View file

@ -0,0 +1,97 @@
from __future__ import with_statement
import os
from hashlib import md5
from werkzeug import parse_date
from jinja2.utils import urlize
from flask import Module, render_template, json, url_for, abort, Markup
mailinglist = Module(__name__)
THREADS_PER_PAGE = 15
MAILINGLIST_PATH = os.path.join(os.path.dirname(__file__), '..', '..', '_mailinglist')
class Mail(object):
def __init__(self, d):
self.msgid = d['msgid']
self.author_name, self.author_addr = d['author']
self.date = parse_date(d['date'])
self.subject = d['subject']
self.children = [Mail(x) for x in d['children']]
self.text = d['text']
@property
def rendered_text(self):
result = []
in_sig = False
for line in self.text.splitlines():
if line == u'-- ':
in_sig = True
if in_sig:
line = Markup(u'<span class=sig>%s</span>' % line)
elif line.startswith('>'):
line = Markup(u'<span class=quote>%s</span>' % line)
result.append(urlize(line))
return Markup(u'\n'.join(result))
@property
def id(self):
return md5(self.msgid.encode('utf-8')).hexdigest()
class Thread(object):
def __init__(self, d):
self.slug = d['slug'].rsplit('/', 1)[-1]
self.title = d['title']
self.reply_count = d['reply_count']
self.author_name, self.author_email = d['author']
self.date = parse_date(d['date'])
if 'root' in d:
self.root = Mail(d['root'])
@staticmethod
def get(year, month, day, slug):
try:
with open('%s/threads/%s-%02d-%02d/%s' %
(MAILINGLIST_PATH, year, month, day, slug)) as f:
return Thread(json.load(f))
except IOError:
pass
@staticmethod
def get_list():
with open('%s/threads/threadlist' % MAILINGLIST_PATH) as f:
return [Thread(x) for x in json.load(f)]
@property
def url(self):
return url_for('mailinglist.show_thread', year=self.date.year,
month=self.date.month, day=self.date.day,
slug=self.slug)
@mailinglist.route('/mailinglist/')
def index():
return render_template('mailinglist/index.html')
@mailinglist.route('/mailinglist/archive/', defaults={'page': 1})
@mailinglist.route('/mailinglist/archive/page/<int:page>/')
def archive(page):
all_threads = Thread.get_list()
offset = (page - 1) * THREADS_PER_PAGE
threads = all_threads[offset:offset + THREADS_PER_PAGE]
if page != 1 and not threads:
abort(404)
return render_template('mailinglist/archive.html',
page_count=len(threads) // THREADS_PER_PAGE + 1,
page=page, threads=threads)
@mailinglist.route('/mailinglist/archive/<int:year>/<int:month>/<int:day>/<slug>/')
def show_thread(year, month, day, slug):
thread = Thread.get(year, month, day, slug)
if thread is None:
abort(404)
return render_template('mailinglist/show_thread.html', thread=thread)

View file

@ -0,0 +1,8 @@
from flask import Module, render_template
snippets = Module(__name__, url_prefix='/snippets')
@snippets.route('/')
def index():
return render_template('snippets/index.html')