summaryrefslogtreecommitdiff
path: root/pastepy/pastepy.py
diff options
context:
space:
mode:
Diffstat (limited to 'pastepy/pastepy.py')
-rw-r--r--pastepy/pastepy.py169
1 files changed, 169 insertions, 0 deletions
diff --git a/pastepy/pastepy.py b/pastepy/pastepy.py
new file mode 100644
index 0000000..750d8fe
--- /dev/null
+++ b/pastepy/pastepy.py
@@ -0,0 +1,169 @@
+import datetime
+import random
+
+from flask import Blueprint, current_app, render_template, request, session, redirect, url_for
+try:
+ import markdown
+ has_markdown = True
+except ImportError:
+ has_markdown = False
+import pygments
+from pygments import highlight
+from pygments.lexers import get_all_lexers, get_lexer_by_name
+from pygments.formatters import HtmlFormatter
+
+from . import db
+
+app = Blueprint(__name__, 'pastepy')
+
+base62_alphabet = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
+
+class PasteError(Exception): pass
+class UnknownSyntaxError(PasteError): pass
+
+class CustomHtmlFormatter(HtmlFormatter):
+ def wrap(self, source, outfile):
+ yield 0, '<pre>'
+ line = 1
+ for i, t in source:
+ yield i, '<span id="codeline-{}">{}</span>'.format(i, t)
+ line += 1
+ yield 0, '</pre>'
+
+def init_lexers():
+ all_lexers = dict([(x[0], x[1][0]) for x in get_all_lexers()])
+ lexers = []
+ removed = []
+ for cat, ls in current_app.config['CATEGORIES']:
+ for l in ls:
+ removed.append(l)
+ lexers.append((cat, [(x, all_lexers[x]) for x in ls if x in all_lexers]))
+ for l in removed:
+ try:
+ del all_lexers[l]
+ except KeyError:
+ pass
+ rendered = []
+ if has_markdown:
+ rendered.append(('Rendered markdown', 'md-render'))
+ if len(rendered):
+ lexers.append(('Rendered', rendered))
+ lexers.append(('Others' if current_app.config['CATEGORIES'] else 'Syntax', sorted(all_lexers.items(), key = lambda l: l[0].lower())))
+
+ current_app.config['LEXERS'] = lexers
+ current_app.config['FORMATTER'] = CustomHtmlFormatter(linenos='table', lineanchors='line', anchorlinenos=True)
+
+init_lexers()
+
+@app.route('/')
+@app.route('/paste')
+def paste():
+ context = {
+ 'title': current_app.config['PASTEBIN_NAME'],
+ 'header': current_app.config['PASTEBIN_NAME'],
+ }
+ return render_template('paste.html', **context)
+
+def get_formatted(syntax, text):
+ if syntax == 'md-render' and has_markdown:
+ text = markdown.markdown(text, extensions=current_app.config['MARKDOWN_EXTENSIONS'])
+ lexername = 'Rendered markdown'
+ else:
+ try:
+ lex = get_lexer_by_name(syntax or 'text')
+ except pygments.util.ClassNotFound:
+ raise UnknownSyntaxError(syntax)
+ lexername = lex.name
+ text = highlight(text, lex, current_app.config['FORMATTER'])
+ return (lexername, text)
+
+def add_paste():
+ nick = request.form.get('nick')
+ syntax = request.form.get('syntax')
+ title = request.form.get('title')
+ text = request.form.get('text').replace('\r', '')
+
+ with db.session_scope() as db_session:
+ paste_hash = ''.join(random.choice(base62_alphabet) for x in range(5))
+ paste = db.Paste(paste_hash, nick, datetime.datetime.utcnow(), syntax, title, text, request.remote_addr)
+ db_session.add(paste)
+
+ if 'remember_me' in request.form:
+ session['nick'] = nick
+ else:
+ session.pop('nick', None)
+ if 'remember_syntax' in request.form:
+ session['syntax'] = syntax
+ else:
+ session.pop('syntax', None)
+ return redirect(url_for('.view_paste', paste_hash=paste_hash))
+
+def render_preview():
+ try:
+ lexername, text = get_formatted(request.form['syntax'], request.form['text'])
+ except UnknownSyntaxError:
+ abort(500, 'Could not find lexer "{}".'.format(request.form['syntax']))
+
+ nick = request.form['nick'] or 'Anonymous'
+ title = request.form['title'] or 'Untitled'
+ return render_template('view.html',
+ title='Preview',
+ hash=None,
+ nick=nick,
+ date='{} UTC'.format(datetime.datetime.utcnow().ctime()),
+ syntax=lexername,
+ pastetitle=title,
+ text=text,
+ rendered=(lexername or '').startswith('Rendered '),
+ )
+
+@app.route('/paste', methods=['POST'])
+def post_paste():
+ if request.form['type'] == 'Preview':
+ return render_preview()
+ if request.form['type'] == 'Paste':
+ return add_paste()
+ abort(404)
+
+@app.route('/view/<paste_hash>')
+@app.route('/full/<paste_hash>', endpoint='view_full')
+def view_paste(paste_hash):
+ with db.session_scope() as db_session:
+ try:
+ cache = db_session.query(db.Cache).filter_by(paste_hash=paste_hash).one()
+ paste = cache.paste
+ except db.NoResultFound:
+ try:
+ paste = db_session.query(db.Paste).filter_by(hash=paste_hash).one()
+ except db.NoResultFound:
+ abort(404)
+ try:
+ lexername, text = get_formatted(paste.syntax, paste.text)
+ except UnknownSyntaxError:
+ abort(500, 'Could not find the lexer "{}"'.format(paste.syntax))
+ cache = db.Cache(paste_hash, lexername, text)
+ db_session.add(cache)
+ template = 'full.html' if request.endpoint.endswith('.view_full') else 'view.html'
+ return render_template(template,
+ title='View paste \u2013 {}'.format(current_app.config['PASTEBIN_NAME'], paste.title or 'Untitled'),
+ hash=paste_hash,
+ date='{} UTC'.format(paste.date.ctime()),
+ nick=paste.nick or 'Anonymous',
+ syntax=cache.syntax_name,
+ pastetitle=paste.title or 'Untitled',
+ text=cache.text,
+ rendered=(cache.syntax_name or '').startswith('Rendered '),
+ )
+
+@app.route('/highlight_stylesheet')
+def highlight_stylesheet():
+ return current_app.config['FORMATTER'].get_style_defs(), 200, {'Content-Type': 'text/css'}
+
+@app.route('/raw/<paste_hash>')
+def raw(paste_hash):
+ with db.session_scope() as db_session:
+ try:
+ paste = db_session.query(db.Paste).filter_by(hash=paste_hash).one()
+ except db.NoResultFound:
+ abort(404)
+ return paste.text, 200, {'Content-Type': 'text/plain'}