flask/flask_website/utils.py
Armin Ronacher 63001a7279 More API
2010-07-23 13:03:29 +01:00

149 lines
4.2 KiB
Python

import re
import creoleparser
from datetime import datetime, timedelta
from genshi import builder
from functools import wraps
from creoleparser.elements import PreBlock
from pygments import highlight
from pygments.formatters import HtmlFormatter
from pygments.lexers import get_lexer_by_name
from pygments.util import ClassNotFound
from flask import g, url_for, flash, abort, request, redirect, Markup
from flask_website.flaskystyle import FlaskyStyle # same as docs
from flask_website.database import User
pygments_formatter = HtmlFormatter(style=FlaskyStyle)
_ws_split_re = re.compile(r'(\s+)')
TIMEDELTA_UNITS = (
('year', 3600 * 24 * 365),
('month', 3600 * 24 * 30),
('week', 3600 * 24 * 7),
('day', 3600 * 24),
('hour', 3600),
('minute', 60),
('second', 1)
)
class CodeBlock(PreBlock):
def __init__(self):
super(CodeBlock, self).__init__('pre', ['{{{', '}}}'])
def _build(self, mo, element_store, environ):
lines = self.regexp2.sub(r'\1', mo.group(1)).splitlines()
if lines and lines[0].startswith('#!'):
try:
lexer = get_lexer_by_name(lines.pop(0)[2:].strip())
except ClassNotFound:
pass
else:
return Markup(highlight(u'\n'.join(lines), lexer,
pygments_formatter))
return builder.tag.pre(u'\n'.join(lines))
custom_dialect = creoleparser.create_dialect(creoleparser.creole10_base)
# hacky way to get rid of image support
custom_dialect.img = custom_dialect.no_wiki
custom_dialect.pre = CodeBlock()
_parser = creoleparser.Parser(
dialect=custom_dialect,
method='html'
)
def format_creole(text):
return Markup(_parser.render(text, encoding=None))
def split_lines_wrapping(text, width=74, threshold=82):
lines = text.splitlines()
if all(len(line) <= threshold for line in lines):
return lines
result = []
for line in lines:
if len(line) <= threshold:
result.append(line)
continue
line_width = 0
line_buffer = []
for piece in _ws_split_re.split(line):
line_width += len(piece)
if line_width > width:
result.append(u''.join(line_buffer))
line_buffer = []
if not piece.isspace():
line_buffer.append(piece)
line_width = len(piece)
else:
line_width = 0
else:
line_buffer.append(piece)
if line_buffer:
result.append(u''.join(line_buffer))
return result
def request_wants_json():
return request.accept_mimetypes \
.best_match(['application/json', 'text/html']) == 'application/json'
def requires_login(f):
@wraps(f)
def decorated_function(*args, **kwargs):
if g.user is None:
flash(u'You need to be signed in for this page.')
return redirect(url_for('general.login', next=request.path))
return f(*args, **kwargs)
return decorated_function
def requires_admin(f):
@wraps(f)
def decorated_function(*args, **kwargs):
if not g.user.is_admin:
abort(401)
return f(*args, **kwargs)
return requires_login(decorated_function)
def format_datetime(dt):
return dt.strftime('%Y-%m-%d @ %H:%M')
def format_timedelta(delta, granularity='second', threshold=.85):
if isinstance(delta, datetime):
delta = datetime.utcnow() - delta
if isinstance(delta, timedelta):
seconds = int((delta.days * 86400) + delta.seconds)
else:
seconds = delta
for unit, secs_per_unit in TIMEDELTA_UNITS:
value = abs(seconds) / secs_per_unit
if value >= threshold or unit == granularity:
if unit == granularity and value > 0:
value = max(1, value)
value = int(round(value))
rv = u'%s %s' % (value, unit)
if value != 1:
rv += u's'
return rv
return u''
def display_openid(openid):
if not openid:
return ''
rv = openid
if rv.startswith(('http://', 'https://')):
rv = rv.split('/', 2)[-1]
return rv.rstrip('/')