##// END OF EJS Templates
transaction: support multiple, separate transactions...
transaction: support multiple, separate transactions Solves that committed (closed) transactions may linger and be returned on subsequent transaction calls, even though a new transaction should be made, rather than a new nested transaction. This also fixes a race condition with the use of weakref.

File last commit:

r8014:6a77ba18 default
r8072:ecf77954 default
Show More
templatefilters.py
190 lines | 5.5 KiB | text/x-python | PythonLexer
Matt Mackall
templates: move filters to their own module...
r5976 # template-filters.py - common template expansion filters
#
# Copyright 2005-2008 Matt Mackall <mpm@selenic.com>
#
# This software may be used and distributed according to the terms
# of the GNU General Public License, incorporated herein by reference.
import cgi, re, os, time, urllib, textwrap
Matt Mackall
move encoding bits from util to encoding...
r7948 import util, templater, encoding
Matt Mackall
templates: move filters to their own module...
r5976
agescales = [("second", 1),
("minute", 60),
("hour", 3600),
("day", 3600 * 24),
("week", 3600 * 24 * 7),
("month", 3600 * 24 * 30),
("year", 3600 * 24 * 365)]
agescales.reverse()
def age(date):
'''turn a (timestamp, tzoff) tuple into an age string.'''
def plural(t, c):
if c == 1:
return t
return t + "s"
def fmt(t, c):
return "%d %s" % (c, plural(t, c))
now = time.time()
then = date[0]
Dirkjan Ochtman
templater: fix age filter to state the obvious on future timestamps
r7682 if then > now:
return 'in the future'
Matt Mackall
templates: move filters to their own module...
r5976 delta = max(1, int(now - then))
for t, s in agescales:
n = delta / s
if n >= 2 or s == 1:
return fmt(t, n)
para_re = None
space_re = None
def fill(text, width):
'''fill many paragraphs.'''
global para_re, space_re
if para_re is None:
para_re = re.compile('(\n\n|\n\\s*[-*]\\s*)', re.M)
space_re = re.compile(r' +')
def findparas():
start = 0
while True:
m = para_re.search(text, start)
if not m:
w = len(text)
while w > start and text[w-1].isspace(): w -= 1
yield text[start:w], text[w:]
break
yield text[start:m.start(0)], m.group(1)
start = m.end(1)
return "".join([space_re.sub(' ', textwrap.fill(para, width)) + rest
for para, rest in findparas()])
def firstline(text):
'''return the first line of text'''
try:
return text.splitlines(1)[0].rstrip('\r\n')
except IndexError:
return ''
def nl2br(text):
'''replace raw newlines with xhtml line breaks.'''
return text.replace('\n', '<br/>\n')
def obfuscate(text):
Matt Mackall
move encoding bits from util to encoding...
r7948 text = unicode(text, encoding.encoding, 'replace')
Matt Mackall
templates: move filters to their own module...
r5976 return ''.join(['&#%d;' % ord(c) for c in text])
def domain(author):
'''get domain of author, or empty string if none.'''
f = author.find('@')
if f == -1: return ''
author = author[f+1:]
f = author.find('>')
if f >= 0: author = author[:f]
return author
def person(author):
'''get name of author, or else username.'''
f = author.find('<')
if f == -1: return util.shortuser(author)
return author[:f].rstrip()
def indent(text, prefix):
'''indent each non-empty line of text after first with prefix.'''
lines = text.splitlines()
num_lines = len(lines)
def indenter():
for i in xrange(num_lines):
l = lines[i]
if i and l.strip():
yield prefix
yield l
if i < num_lines - 1 or text.endswith('\n'):
yield '\n'
return "".join(indenter())
def permissions(flags):
if "l" in flags:
return "lrwxrwxrwx"
if "x" in flags:
return "-rwxr-xr-x"
return "-rw-r--r--"
Jesse Glick
Permit XML entities to be escaped in template output....
r6174 def xmlescape(text):
text = (text
.replace('&', '&amp;')
.replace('<', '&lt;')
.replace('>', '&gt;')
.replace('"', '&quot;')
.replace("'", '&#39;')) # &apos; invalid in HTML
return re.sub('[\x00-\x08\x0B\x0C\x0E-\x1F]', ' ', text)
Dirkjan Ochtman
add graph page to hgweb
r6691 _escapes = [
('\\', '\\\\'), ('"', '\\"'), ('\t', '\\t'), ('\n', '\\n'),
('\r', '\\r'), ('\f', '\\f'), ('\b', '\\b'),
]
Dirkjan Ochtman
templatefilters: split out jsonescape() function
r8014 def jsonescape(s):
for k, v in _escapes:
s = s.replace(k, v)
return s
Dirkjan Ochtman
add graph page to hgweb
r6691 def json(obj):
if obj is None or obj is False or obj is True:
return {None: 'null', False: 'false', True: 'true'}[obj]
elif isinstance(obj, int) or isinstance(obj, float):
return str(obj)
elif isinstance(obj, str):
Dirkjan Ochtman
templatefilters: split out jsonescape() function
r8014 return '"%s"' % jsonescape(obj)
Dirkjan Ochtman
add graph page to hgweb
r6691 elif isinstance(obj, unicode):
return json(obj.encode('utf-8'))
elif hasattr(obj, 'keys'):
out = []
for k, v in obj.iteritems():
s = '%s: %s' % (json(k), json(v))
out.append(s)
return '{' + ', '.join(out) + '}'
elif hasattr(obj, '__iter__'):
out = []
for i in obj:
out.append(json(i))
return '[' + ', '.join(out) + ']'
else:
raise TypeError('cannot encode type %s' % obj.__class__.__name__)
Matt Mackall
templates: move filters to their own module...
r5976 filters = {
"addbreaks": nl2br,
"basename": os.path.basename,
"age": age,
"date": lambda x: util.datestr(x),
"domain": domain,
"email": util.email,
"escape": lambda x: cgi.escape(x, True),
"fill68": lambda x: fill(x, width=68),
"fill76": lambda x: fill(x, width=76),
"firstline": firstline,
"tabindent": lambda x: indent(x, '\t'),
Matt Mackall
dates: improve timezone handling...
r6229 "hgdate": lambda x: "%d %d" % x,
"isodate": lambda x: util.datestr(x, '%Y-%m-%d %H:%M %1%2'),
Giorgos Keramidas
Add an {isodatesec} template, to show seconds too.
r6319 "isodatesec": lambda x: util.datestr(x, '%Y-%m-%d %H:%M:%S %1%2'),
Dirkjan Ochtman
templatefilters: split out jsonescape() function
r8014 "json": json,
"jsonescape": jsonescape,
Matt Mackall
templates: move filters to their own module...
r5976 "obfuscate": obfuscate,
"permissions": permissions,
"person": person,
Matt Mackall
dates: improve timezone handling...
r6229 "rfc822date": lambda x: util.datestr(x, "%a, %d %b %Y %H:%M:%S %1%2"),
"rfc3339date": lambda x: util.datestr(x, "%Y-%m-%dT%H:%M:%S%1:%2"),
Matt Mackall
templates: move filters to their own module...
r5976 "short": lambda x: x[:12],
Thomas Arendsen Hein
Make annotae/grep print short dates with -q/--quiet....
r6134 "shortdate": util.shortdate,
Matt Mackall
templates: move filters to their own module...
r5976 "stringify": templater.stringify,
"strip": lambda x: x.strip(),
"urlescape": lambda x: urllib.quote(x),
"user": lambda x: util.shortuser(x),
"stringescape": lambda x: x.encode('string_escape'),
Jesse Glick
Permit XML entities to be escaped in template output....
r6174 "xmlescape": xmlescape,
Dirkjan Ochtman
add graph page to hgweb
r6691 }