flask/flask_website/utils.py

150 lines
4.2 KiB
Python
Raw Normal View History

2010-05-05 17:37:44 +02:00
import re
2010-05-03 11:20:52 +02:00
import creoleparser
2010-05-16 01:06:37 +02:00
from datetime import datetime, timedelta
2010-05-03 11:20:52 +02:00
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
2010-05-15 23:19:13 +02:00
from flask import g, url_for, flash, abort, request, redirect, Markup
2010-05-03 11:20:52 +02:00
from flask_website.flaskystyle import FlaskyStyle # same as docs
from flask_website.database import User
pygments_formatter = HtmlFormatter(style=FlaskyStyle)
2010-05-05 17:37:44 +02:00
_ws_split_re = re.compile(r'(\s+)')
2010-05-03 11:20:52 +02:00
2010-05-16 01:06:37 +02:00
TIMEDELTA_UNITS = (
('year', 3600 * 24 * 365),
('month', 3600 * 24 * 30),
('week', 3600 * 24 * 7),
('day', 3600 * 24),
('hour', 3600),
('minute', 60),
('second', 1)
)
2010-05-03 11:20:52 +02:00
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)
2010-05-16 02:21:43 +02:00
# hacky way to get rid of image support
custom_dialect.img = custom_dialect.no_wiki
2010-05-03 11:20:52 +02:00
custom_dialect.pre = CodeBlock()
_parser = creoleparser.Parser(
dialect=custom_dialect,
method='html'
)
def format_creole(text):
return Markup(_parser.render(text, encoding=None))
2010-05-05 17:37:44 +02:00
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
2010-07-23 13:03:29 +01:00
def request_wants_json():
return request.accept_mimetypes \
.best_match(['application/json', 'text/html']) == 'application/json'
2010-05-03 11:20:52 +02:00
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
2010-05-15 23:19:13 +02:00
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)
2010-05-16 01:06:37 +02:00
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
2010-05-16 01:06:37 +02:00
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('/')