17
19
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
from xml.etree import ElementTree as ET
23
from elementtree import ElementTree as ET
52
59
# displaydate and approximatedate return an elementtree <span> Element
53
60
# with the full date in a tooltip.
55
63
def date_day(value):
56
64
return value.strftime('%Y-%m-%d')
59
67
def date_time(value):
60
return value.strftime('%Y-%m-%d %T')
69
return value.strftime('%Y-%m-%d %T')
63
74
def _displaydate(date):
118
129
return _wrap_with_date_time_title(date, _displaydate(date))
121
class Container (object):
132
class Container(object):
123
134
Convert a dict into an object with attributes.
125
137
def __init__(self, _dict=None, **kw):
126
138
if _dict is not None:
127
139
for key, value in _dict.iteritems():
132
144
def __repr__(self):
134
146
for key, value in self.__dict__.iteritems():
135
if key.startswith('_') or (getattr(self.__dict__[key], '__call__', None) is not None):
147
if key.startswith('_') or (getattr(self.__dict__[key],
148
'__call__', None) is not None):
137
150
out += '%r => %r, ' % (key, value)
167
181
return '%s at %s' % (username, domains[-2])
168
182
return '%s at %s' % (username, domains[0])
184
def hide_emails(emails):
186
try to obscure any email address in a list of bazaar committers' names.
190
result.append(hide_email(email))
171
193
# only do this if unicode turns out to be a problem
172
194
#_BADCHARS_RE = re.compile(ur'[\u007f-\uffff]')
174
196
# FIXME: get rid of this method; use fixed_width() and avoid XML().
175
199
def html_clean(s):
177
201
clean up a string for html display. expand any tabs, encode any html
187
210
NONBREAKING_SPACE = u'\N{NO-BREAK SPACE}'
215
CSS is stupid. In some cases we need to replace an empty value with
216
a non breaking space ( ). There has to be a better way of doing this.
218
return: the same value recieved if not empty, and a ' ' if it is.
222
elif isinstance(s, int):
228
s = s.decode('utf-8')
229
except UnicodeDecodeError:
230
s = s.decode('iso-8859-15')
233
HSC = HTMLStructureCleaner()
189
235
def fixed_width(s):
191
237
expand tabs and turn spaces into "non-breaking spaces", so browsers won't
201
247
s = s.decode('utf-8')
202
248
except UnicodeDecodeError:
203
249
s = s.decode('iso-8859-15')
204
return s.expandtabs().replace(' ', NONBREAKING_SPACE)
251
s = cgi.escape(s).expandtabs().replace(' ', NONBREAKING_SPACE)
253
return HSC.clean(s).replace('\n', '<br/>')
207
256
def fake_permissions(kind, executable):
285
335
navigation.position = 0
286
336
navigation.count = len(navigation.revid_list)
287
337
navigation.page_position = navigation.position // navigation.pagesize + 1
288
navigation.page_count = (len(navigation.revid_list) + (navigation.pagesize - 1)) // navigation.pagesize
338
navigation.page_count = (len(navigation.revid_list) + (navigation.pagesize\
339
- 1)) // navigation.pagesize
290
341
def get_offset(offset):
291
if (navigation.position + offset < 0) or (navigation.position + offset > navigation.count - 1):
342
if (navigation.position + offset < 0) or (
343
navigation.position + offset > navigation.count - 1):
293
345
return navigation.revid_list[navigation.position + offset]
347
navigation.last_in_page_revid = get_offset(navigation.pagesize - 1)
295
348
navigation.prev_page_revid = get_offset(-1 * navigation.pagesize)
296
349
navigation.next_page_revid = get_offset(1 * navigation.pagesize)
297
350
prev_page_revno = navigation.history.get_revno(
300
353
navigation.next_page_revid)
301
354
start_revno = navigation.history.get_revno(navigation.start_revid)
303
params = { 'filter_file_id': navigation.filter_file_id }
356
params = {'filter_file_id': navigation.filter_file_id}
304
357
if getattr(navigation, 'query', None) is not None:
305
358
params['q'] = navigation.query
315
368
[navigation.scan_url, next_page_revno], **params)
371
def directory_breadcrumbs(path, is_root, view):
373
Generate breadcrumb information from the directory path given
375
The path given should be a path up to any branch that is currently being
379
path -- The path to convert into breadcrumbs
380
is_root -- Whether or not loggerhead is serving a branch at its root
381
view -- The type of view we are showing (files, changes etc)
383
# Is our root directory itself a branch?
391
# Create breadcrumb trail for the path leading up to the branch
393
'dir_name': "(root)",
398
dir_parts = path.strip('/').split('/')
399
for index, dir_name in enumerate(dir_parts):
401
'dir_name': dir_name,
402
'path': '/'.join(dir_parts[:index + 1]),
405
# If we are not in the directory view, the last crumb is a branch,
406
# so we need to specify a view
407
if view != 'directory':
408
breadcrumbs[-1]['suffix'] = '/' + view
412
def branch_breadcrumbs(path, inv, view):
414
Generate breadcrumb information from the branch path given
416
The path given should be a path that exists within a branch
419
path -- The path to convert into breadcrumbs
420
inv -- Inventory to get file information from
421
view -- The type of view we are showing (files, changes etc)
423
dir_parts = path.strip('/').split('/')
424
inner_breadcrumbs = []
425
for index, dir_name in enumerate(dir_parts):
426
inner_breadcrumbs.append({
427
'dir_name': dir_name,
428
'file_id': inv.path2id('/'.join(dir_parts[:index + 1])),
429
'suffix': '/' + view,
431
return inner_breadcrumbs
318
434
def decorator(unbound):
319
436
def new_decorator(f):
321
438
g.__name__ = f.__name__
328
445
return new_decorator
331
# common threading-lock decorator
332
def with_lock(lockname, debug_name=None):
333
if debug_name is None:
334
debug_name = lockname
336
def _decorator(unbound):
337
def locked(self, *args, **kw):
338
getattr(self, lockname).acquire()
340
return unbound(self, *args, **kw)
342
getattr(self, lockname).release()
349
452
def _f(*a, **kw):
350
453
from loggerhead.lsprof import profile
353
456
ret, stats = profile(f, *a, **kw)
354
log.debug('Finished profiled %s in %d msec.' % (f.__name__, int((time.time() - z) * 1000)))
457
log.debug('Finished profiled %s in %d msec.' % (f.__name__,
458
int((time.time() - z) * 1000)))
357
461
now = time.time()
358
462
msec = int(now * 1000) % 1000
359
timestr = time.strftime('%Y%m%d%H%M%S', time.localtime(now)) + ('%03d' % msec)
463
timestr = time.strftime('%Y%m%d%H%M%S',
464
time.localtime(now)) + ('%03d' % (msec,))
360
465
filename = f.__name__ + '-' + timestr + '.lsprof'
361
466
cPickle.dump(stats, open(filename, 'w'), 2)
418
523
overrides = dict((k, v) for (k, v) in overrides.iteritems() if k in _valid)
419
524
map.update(overrides)
528
class Reloader(object):
530
This class wraps all paste.reloader logic. All methods are @classmethod.
533
_reloader_environ_key = 'PYTHON_RELOADER_SHOULD_RUN'
536
def _turn_sigterm_into_systemexit(cls):
538
Attempts to turn a SIGTERM exception into a SystemExit exception.
545
def handle_term(signo, frame):
547
signal.signal(signal.SIGTERM, handle_term)
550
def is_installed(cls):
551
return os.environ.get(cls._reloader_environ_key)
555
from paste import reloader
556
reloader.install(int(1))
559
def restart_with_reloader(cls):
560
"""Based on restart_with_monitor from paste.script.serve."""
561
print 'Starting subprocess with file monitor'
563
args = [sys.executable] + sys.argv
564
new_environ = os.environ.copy()
565
new_environ[cls._reloader_environ_key] = 'true'
569
cls._turn_sigterm_into_systemexit()
570
proc = subprocess.Popen(args, env=new_environ)
571
exit_code = proc.wait()
573
except KeyboardInterrupt:
574
print '^C caught in monitor process'
578
and getattr(os, 'kill', None) is not None):
581
os.kill(proc.pid, signal.SIGTERM)
582
except (OSError, IOError):
585
# Reloader always exits with code 3; but if we are
586
# a monitor, any exit code will restart
589
print '-'*20, 'Restarting', '-'*20
592
def convert_file_errors(application):
593
"""WSGI wrapper to convert some file errors to Paste exceptions"""
594
def new_application(environ, start_response):
596
return application(environ, start_response)
597
except (IOError, OSError), e:
599
from paste import httpexceptions
600
if e.errno == errno.ENOENT:
601
raise httpexceptions.HTTPNotFound()
602
elif e.errno == errno.EACCES:
603
raise httpexceptions.HTTPForbidden()
606
return new_application