Skip to content

Instantly share code, notes, and snippets.

@coleifer
Created October 30, 2011 18:53
Show Gist options
  • Save coleifer/62c6e55e9aa6d1e745ac to your computer and use it in GitHub Desktop.
Save coleifer/62c6e55e9aa6d1e745ac to your computer and use it in GitHub Desktop.
{% extends "pastebin/base.html" %}
{% block title %}Pastebin{% endblock %}
{% block content_title %}Add paste{% endblock %}
{% block content %}
<form method="post" action="{{ url_for('pastebin.add') }}">
{% for field in form %}
<p>{{ field.label }} {{ field }}</p>
{% endfor %}
<p><button type="submit">Add</button>
<a href="{{ url_for('pastebin.list') }}">Cancel</a>
</p>
</form>
{% endblock %}
{% extends "base.html" %}
{% block extra_head %}
<link rel=stylesheet type=text/css href="{{ url_for('pastebin.static', filename='hilite.css') }}" />
{% endblock %}
import datetime
import hashlib
from flask import request, redirect, url_for, render_template, Blueprint, Response
from peewee import *
from pygments import formatters, highlight, lexers
from wtfpeewee.orm import model_form
from flaskext.rest import RestResource
from flaskext.utils import get_object_or_404, object_list
from app import app, db
from auth import auth
class Paste(db.Model):
filename = CharField()
content = TextField()
highlighted = TextField()
created_date = DateTimeField(default=datetime.datetime.now)
sha = CharField()
class Meta:
ordering = (('created_date', 'desc'),)
def __unicode__(self):
return self.filename
def save(self):
self.highlighted = self.highlight()
self.sha = hashlib.sha1(self.content).hexdigest()
super(Paste, self).save()
def highlight(self):
lexer = None
try:
lexer = lexers.get_lexer_for_filename(self.filename)
except lexers.ClassNotFound:
lexer = lexers.guess_lexer(self.content)
formatter = formatters.HtmlFormatter(linenos=True)
return highlight(self.content, lexer, formatter)
pastebin = Blueprint('pastebin', __name__, static_folder='static', template_folder='templates')
@pastebin.route('/')
@auth.login_required
def list():
qr = Paste.select()
return object_list('pastebin/index.html', qr)
@pastebin.route('/add/', methods=['GET', 'POST'])
@auth.login_required
def add():
Form = model_form(Paste, only=('filename', 'content',))
if request.method == 'POST':
form = Form(request.form)
if form.validate():
instance = Paste()
form.populate_obj(instance)
instance.save()
return redirect(url_for('pastebin.list'))
else:
form = Form()
return render_template('pastebin/add.html', form=form)
@pastebin.route('/<sha>/')
def detail(sha):
paste = get_object_or_404(Paste, sha=sha)
return render_template('pastebin/detail.html', paste=paste)
@pastebin.route('/<sha>/raw/')
def detail_raw(sha):
paste = get_object_or_404(Paste, sha=sha)
return Response(paste.content)
@pastebin.route('/<sha>/delete/', methods=['GET', 'POST'])
@auth.login_required
def delete(sha):
paste = get_object_or_404(Paste, sha=sha)
if request.method == 'POST':
paste.delete_instance()
return redirect(url_for('pastebin.list'))
return render_template('pastebin/delete.html', paste=paste)
class PasteResource(RestResource):
exclude = ('highlighted',)
{% extends "pastebin/base.html" %}
{% block title %}Pastebin | {{ paste.filename }}{% endblock %}
{% block content_title %}Delete {{ paste.filename }}?{% endblock %}
{% block content %}
<form method="post" action="{{ url_for('pastebin.delete', sha=paste.sha) }}">
<p>
<button type="submit">Delete</button>
<a href="{{ url_for('pastebin.list') }}">Cancel</a>
</p>
</form>
{% endblock %}
{% extends "pastebin/base.html" %}
{% block title %}Pastebin | {{ paste.filename }}{% endblock %}
{% block content_title %}{{ paste.filename }}{% endblock %}
{% block content %}
{% if user %}
<p style="float: left;"><a href="{{ url_for('pastebin.list') }}">&laquo; back</a></p>
<p style="text-align: right;"><a href="{{ url_for('pastebin.add') }}">Add new</a></p>
{% endif %}
<p>{{ paste.sha }}, created {{ paste.created_date.strftime('%Y-%m-%d %H:%M') }}</p>
{% autoescape off %}
{{ paste.highlighted }}
{% endautoescape %}
{% if user %}
<form method="post" action="{{ url_for('pastebin.delete', sha=paste.sha) }}">
<p><button type="submit">Delete</button></p>
</form>
{% endif %}
{% endblock %}
.hll { background-color: #ffffcc }
.c { color: #999988; font-style: italic } /* Comment */
.err { color: #a61717; background-color: #e3d2d2 } /* Error */
.k { font-weight: bold } /* Keyword */
.o { font-weight: bold } /* Operator */
.cm { color: #999988; font-style: italic } /* Comment.Multiline */
.cp { color: #444444; font-weight: bold } /* Comment.Preproc */
.c1 { color: #999988; font-style: italic } /* Comment.Single */
.cs { color: #444444; font-weight: bold; font-style: italic } /* Comment.Special */
.gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.ge { font-style: italic } /* Generic.Emph */
.gr { color: #aa0000 } /* Generic.Error */
.gh { color: #444444 } /* Generic.Heading */
.gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.go { color: #888888 } /* Generic.Output */
.gp { color: #555555 } /* Generic.Prompt */
.gs { font-weight: bold } /* Generic.Strong */
.gu { color: #aaaaaa } /* Generic.Subheading */
.gt { color: #aa0000 } /* Generic.Traceback */
.kc { font-weight: bold } /* Keyword.Constant */
.kd { font-weight: bold } /* Keyword.Declaration */
.kn { font-weight: bold } /* Keyword.Namespace */
.kp { font-weight: bold } /* Keyword.Pseudo */
.kr { font-weight: bold } /* Keyword.Reserved */
.kt { color: #445588; font-weight: bold } /* Keyword.Type */
.m { color: #009999 } /* Literal.Number */
.s { color: #bb8844 } /* Literal.String */
.na { color: #008080 } /* Name.Attribute */
.nb { color: #444444 } /* Name.Builtin */
.nc { color: #445588; font-weight: bold } /* Name.Class */
.no { color: #008080 } /* Name.Constant */
.ni { color: #800080 } /* Name.Entity */
.ne { color: #990000; font-weight: bold } /* Name.Exception */
.nf { color: #990000; font-weight: bold } /* Name.Function */
.nn { color: #555555 } /* Name.Namespace */
.nt { color: #000080 } /* Name.Tag */
.nv { color: #008080 } /* Name.Variable */
.ow { font-weight: bold } /* Operator.Word */
.w { color: #bbbbbb } /* Text.Whitespace */
.mf { color: #009999 } /* Literal.Number.Float */
.mh { color: #009999 } /* Literal.Number.Hex */
.mi { color: #009999 } /* Literal.Number.Integer */
.mo { color: #009999 } /* Literal.Number.Oct */
.sb { color: #bb8844 } /* Literal.String.Backtick */
.sc { color: #bb8844 } /* Literal.String.Char */
.sd { color: #bb8844 } /* Literal.String.Doc */
.s2 { color: #bb8844 } /* Literal.String.Double */
.se { color: #bb8844 } /* Literal.String.Escape */
.sh { color: #bb8844 } /* Literal.String.Heredoc */
.si { color: #bb8844 } /* Literal.String.Interpol */
.sx { color: #bb8844 } /* Literal.String.Other */
.sr { color: #808000 } /* Literal.String.Regex */
.s1 { color: #bb8844 } /* Literal.String.Single */
.ss { color: #bb8844 } /* Literal.String.Symbol */
.bp { color: #444444 } /* Name.Builtin.Pseudo */
.vc { color: #008080 } /* Name.Variable.Class */
.vg { color: #008080 } /* Name.Variable.Global */
.vi { color: #008080 } /* Name.Variable.Instance */
.il { color: #009999 } /* Literal.Number.Integer.Long */
{% extends "pastebin/base.html" %}
{% block title %}Pastebin{% endblock %}
{% block content_title %}Pastebin{% endblock %}
{% block content %}
{% if user %}
<p style="text-align: right;"><a href="{{ url_for('pastebin.add') }}">Add new</a></p>
{% endif %}
<ul>
{% for paste in object_list %}
<li><p><a href="{{ url_for('pastebin.detail', sha=paste.sha) }}">{{ paste.filename }}</a>, {{ paste.created_date.strftime('%Y-%m-%d %H:%M') }}</p>
<pre>{{ paste.content[:60] }}</pre>
</li>
{% endfor %}
</ul>
{% include "includes/pagination.html" %}
{% endblock %}
#!/usr/bin/env python
# gitconfig
# paste.user / paste.key
# env
# PASTE_USER PASTE_KEY
import datetime
import httplib2
import json
import optparse
import os
import subprocess
import sys
ENDPOINT = 'http://<your site>/api/paste/'
URL_TEMPLATE = 'http://<your site>/pastebin/%s/'
def get_credentials(options):
if options.user and options.key:
return [options.user, options.key]
elif 'PASTE_USER' in os.environ and 'PASTE_KEY' in os.environ:
return [os.environ['PASTE_USER'], os.environ['PASTE_KEY']]
else:
data = []
for piece in ('user', 'key'):
p = subprocess.Popen(['git', 'config', '--global', 'paste.%s' % piece], stdout=subprocess.PIPE)
data.append(p.communicate()[0].strip())
return data
def post_file(user, key, filename, content):
sock = httplib2.Http()
sock.add_credentials(user, key)
headers, resp = sock.request(ENDPOINT, 'POST', json.dumps({
'filename': filename,
'content': content,
}))
if headers['status'] == '200':
resp_data = json.loads(resp)
print URL_TEMPLATE % resp_data['sha']
else:
print 'Error: %s' % headers['status']
print resp
def main(user, key, args):
if args:
for filename in args:
fh = open(filename)
post_file(user, key, os.path.basename(filename), fh.read())
else:
now = datetime.datetime.now()
post_file(user, key, now.strftime('%Y-%m-%d %H:%M:%S'), sys.stdin.read())
if __name__ == '__main__':
parser = optparse.OptionParser()
parser.add_option('-u', '--user', dest='user')
parser.add_option('-k', '--key', dest='key')
options, args = parser.parse_args()
user, key = get_credentials(options)
if not user or not key:
print 'Error: unable to determine user or api key'
sys.exit(1)
main(user, key, args)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment