2009-06-16 03:08:55 +00:00
|
|
|
import datetime
|
2010-09-27 11:44:23 -04:00
|
|
|
import threading
|
|
|
|
import sys
|
2011-02-02 13:07:12 -05:00
|
|
|
import traceback
|
2011-02-05 20:49:52 -05:00
|
|
|
import pprint
|
2011-02-05 15:34:43 -05:00
|
|
|
from django.core.mail import mail_admins
|
2010-08-03 21:53:08 -04:00
|
|
|
from django.utils.translation import ungettext
|
2011-09-01 09:11:29 -07:00
|
|
|
from django.conf import settings
|
2011-02-02 13:07:12 -05:00
|
|
|
from utils import log as logging
|
2009-06-16 03:08:55 +00:00
|
|
|
|
2010-09-27 11:44:23 -04:00
|
|
|
class TimeoutError(Exception): pass
|
|
|
|
def timelimit(timeout):
|
|
|
|
"""borrowed from web.py"""
|
|
|
|
def _1(function):
|
|
|
|
def _2(*args, **kw):
|
|
|
|
class Dispatch(threading.Thread):
|
|
|
|
def __init__(self):
|
|
|
|
threading.Thread.__init__(self)
|
|
|
|
self.result = None
|
|
|
|
self.error = None
|
|
|
|
|
|
|
|
self.setDaemon(True)
|
|
|
|
self.start()
|
|
|
|
|
|
|
|
def run(self):
|
|
|
|
try:
|
|
|
|
self.result = function(*args, **kw)
|
|
|
|
except:
|
|
|
|
self.error = sys.exc_info()
|
2012-07-20 19:43:28 -07:00
|
|
|
c = Dispatch()
|
|
|
|
c.join(timeout)
|
|
|
|
if c.isAlive():
|
|
|
|
raise TimeoutError, 'took too long'
|
2012-11-26 11:41:31 -08:00
|
|
|
if c.error:
|
2012-07-20 19:43:28 -07:00
|
|
|
tb = ''.join(traceback.format_exception(c.error[0], c.error[1], c.error[2]))
|
|
|
|
logging.debug(tb)
|
|
|
|
mail_admins('Error in timeout: %s' % c.error[0], tb)
|
2012-11-26 11:41:31 -08:00
|
|
|
raise c.error[0], c.error[1], c.error[2]
|
2012-07-20 19:43:28 -07:00
|
|
|
return c.result
|
2010-09-27 11:44:23 -04:00
|
|
|
return _2
|
|
|
|
return _1
|
2012-09-04 11:46:41 -07:00
|
|
|
|
|
|
|
|
2011-02-06 15:04:21 -05:00
|
|
|
def utf8encode(tstr):
|
2009-06-16 03:08:55 +00:00
|
|
|
""" Encodes a unicode string in utf-8
|
|
|
|
"""
|
|
|
|
if not tstr:
|
2011-12-02 11:37:55 -08:00
|
|
|
return u''
|
2009-06-16 03:08:55 +00:00
|
|
|
# this is _not_ pretty, but it works
|
|
|
|
try:
|
2011-12-02 11:37:55 -08:00
|
|
|
return unicode(tstr.encode('utf-8', "xmlcharrefreplace"))
|
2009-06-16 03:08:55 +00:00
|
|
|
except UnicodeDecodeError:
|
|
|
|
# it's already UTF8.. sigh
|
2011-02-06 15:04:21 -05:00
|
|
|
try:
|
2011-12-02 11:37:55 -08:00
|
|
|
return unicode(tstr.decode('utf-8').encode('utf-8'))
|
2011-02-06 15:04:21 -05:00
|
|
|
except UnicodeDecodeError:
|
2011-12-02 11:37:55 -08:00
|
|
|
return u''
|
2009-06-16 03:08:55 +00:00
|
|
|
|
2009-08-01 04:26:57 +00:00
|
|
|
# From: http://www.poromenos.org/node/87
|
|
|
|
def levenshtein_distance(first, second):
|
|
|
|
"""Find the Levenshtein distance between two strings."""
|
|
|
|
if len(first) > len(second):
|
|
|
|
first, second = second, first
|
|
|
|
if len(second) == 0:
|
|
|
|
return len(first)
|
|
|
|
first_length = len(first) + 1
|
|
|
|
second_length = len(second) + 1
|
|
|
|
distance_matrix = [[0] * second_length for x in range(first_length)]
|
|
|
|
for i in range(first_length):
|
|
|
|
distance_matrix[i][0] = i
|
|
|
|
for j in range(second_length):
|
|
|
|
distance_matrix[0][j]=j
|
|
|
|
for i in xrange(1, first_length):
|
|
|
|
for j in range(1, second_length):
|
|
|
|
deletion = distance_matrix[i-1][j] + 1
|
|
|
|
insertion = distance_matrix[i][j-1] + 1
|
|
|
|
substitution = distance_matrix[i-1][j-1]
|
|
|
|
if first[i-1] != second[j-1]:
|
|
|
|
substitution += 1
|
|
|
|
distance_matrix[i][j] = min(insertion, deletion, substitution)
|
2010-07-21 11:38:33 -04:00
|
|
|
return distance_matrix[first_length-1][second_length-1]
|
|
|
|
|
2010-07-28 18:18:01 -04:00
|
|
|
def _do_timesince(d, chunks, now=None):
|
|
|
|
"""
|
|
|
|
Started as a copy of django.util.timesince.timesince, but modified to
|
|
|
|
only output one time unit, and use months as the maximum unit of measure.
|
|
|
|
|
|
|
|
Takes two datetime objects and returns the time between d and now
|
|
|
|
as a nicely formatted string, e.g. "10 minutes". If d occurs after now,
|
|
|
|
then "0 minutes" is returned.
|
|
|
|
|
|
|
|
Units used are months, weeks, days, hours, and minutes.
|
|
|
|
Seconds and microseconds are ignored.
|
|
|
|
"""
|
|
|
|
# Convert datetime.date to datetime.datetime for comparison
|
|
|
|
if d.__class__ is not datetime.datetime:
|
|
|
|
d = datetime.datetime(d.year, d.month, d.day)
|
|
|
|
|
|
|
|
if not now:
|
2010-10-10 23:55:00 -04:00
|
|
|
now = datetime.datetime.utcnow()
|
2010-07-28 18:18:01 -04:00
|
|
|
|
|
|
|
# ignore microsecond part of 'd' since we removed it from 'now'
|
|
|
|
delta = now - (d - datetime.timedelta(0, 0, d.microsecond))
|
|
|
|
since = delta.days * 24 * 60 * 60 + delta.seconds
|
2012-01-15 20:51:48 -08:00
|
|
|
if since > 10:
|
|
|
|
for i, (seconds, name) in enumerate(chunks):
|
|
|
|
count = since // seconds
|
|
|
|
if count != 0:
|
|
|
|
break
|
|
|
|
s = '%(number)d %(type)s' % {'number': count, 'type': name(count)}
|
|
|
|
else:
|
|
|
|
s = 'just a second'
|
2010-07-28 18:18:01 -04:00
|
|
|
return s
|
|
|
|
|
|
|
|
def relative_timesince(value):
|
|
|
|
if not value:
|
|
|
|
return u''
|
|
|
|
|
|
|
|
chunks = (
|
2012-01-13 09:20:37 -08:00
|
|
|
(60 * 60 * 24, lambda n: ungettext('day', 'days', n)),
|
2010-07-28 18:18:01 -04:00
|
|
|
(60 * 60, lambda n: ungettext('hour', 'hours', n)),
|
2012-01-15 20:51:48 -08:00
|
|
|
(60, lambda n: ungettext('minute', 'minutes', n)),
|
|
|
|
(1, lambda n: ungettext('second', 'seconds', n)),
|
|
|
|
(0, lambda n: 'just now'),
|
2010-07-28 18:18:01 -04:00
|
|
|
)
|
|
|
|
return _do_timesince(value, chunks)
|
|
|
|
|
|
|
|
def relative_timeuntil(value):
|
|
|
|
if not value:
|
|
|
|
return u''
|
|
|
|
|
|
|
|
chunks = (
|
|
|
|
(60 * 60, lambda n: ungettext('hour', 'hours', n)),
|
|
|
|
(60, lambda n: ungettext('minute', 'minutes', n))
|
|
|
|
)
|
|
|
|
|
2010-10-10 23:55:00 -04:00
|
|
|
now = datetime.datetime.utcnow()
|
2010-07-28 18:18:01 -04:00
|
|
|
|
|
|
|
return _do_timesince(now, chunks, value)
|
2011-08-18 09:56:52 -07:00
|
|
|
|
|
|
|
def seconds_timesince(value):
|
|
|
|
now = datetime.datetime.utcnow()
|
|
|
|
delta = now - value
|
|
|
|
|
|
|
|
return delta.days * 24 * 60 * 60 + delta.seconds
|
|
|
|
|
2010-07-28 01:14:25 -04:00
|
|
|
def format_relative_date(date, future=False):
|
2010-07-26 21:38:56 -04:00
|
|
|
if not date or date < datetime.datetime(2010, 1, 1):
|
|
|
|
return "Soon"
|
|
|
|
|
2010-10-10 23:55:00 -04:00
|
|
|
now = datetime.datetime.utcnow()
|
2010-07-28 01:14:25 -04:00
|
|
|
diff = abs(now - date)
|
2010-07-26 21:38:56 -04:00
|
|
|
if diff < datetime.timedelta(minutes=60):
|
2010-07-26 22:21:58 -04:00
|
|
|
minutes = diff.seconds / 60
|
2010-07-28 18:18:01 -04:00
|
|
|
return "%s minute%s %s" % (minutes,
|
|
|
|
'' if minutes == 1 else 's',
|
|
|
|
'' if future else 'ago')
|
2010-07-26 21:38:56 -04:00
|
|
|
elif datetime.timedelta(minutes=60) <= diff < datetime.timedelta(minutes=90):
|
2010-07-28 01:14:25 -04:00
|
|
|
return "1 hour %s" % ('' if future else 'ago')
|
2012-01-13 09:20:37 -08:00
|
|
|
elif diff < datetime.timedelta(hours=24):
|
2010-07-28 01:14:25 -04:00
|
|
|
dec = (diff.seconds / 60 + 15) % 60
|
2010-07-26 21:38:56 -04:00
|
|
|
if dec >= 30:
|
2010-07-28 18:18:01 -04:00
|
|
|
return "%s.5 hours %s" % ((((diff.seconds / 60) + 15) / 60),
|
|
|
|
'' if future else 'ago')
|
2010-07-26 21:38:56 -04:00
|
|
|
else:
|
2010-07-28 18:18:01 -04:00
|
|
|
return "%s hours %s" % ((((diff.seconds / 60) + 15) / 60),
|
2011-01-09 23:11:09 -05:00
|
|
|
'' if future else 'ago')
|
2012-01-13 09:20:37 -08:00
|
|
|
else:
|
|
|
|
days = ((diff.seconds / 60) / 60 / 24)
|
|
|
|
return "%s day%s %s" % (days, '' if days == 1 else 's', '' if future else 'ago')
|
|
|
|
|
2012-08-12 18:57:29 -07:00
|
|
|
def add_object_to_folder(obj, in_folder, folders, parent='', added=False):
|
|
|
|
obj_identifier = obj
|
|
|
|
if isinstance(obj, dict):
|
|
|
|
obj_identifier = obj.keys()[0]
|
|
|
|
print obj, obj_identifier, folders
|
|
|
|
|
|
|
|
if (not in_folder and not parent and
|
|
|
|
not isinstance(obj, dict) and
|
|
|
|
obj_identifier not in folders):
|
2011-01-23 02:13:55 -05:00
|
|
|
folders.append(obj)
|
|
|
|
return folders
|
|
|
|
|
2012-08-12 18:57:29 -07:00
|
|
|
child_folder_names = []
|
|
|
|
for item in folders:
|
|
|
|
if isinstance(item, dict):
|
|
|
|
child_folder_names.append(item.keys()[0])
|
|
|
|
if isinstance(obj, dict) and in_folder == parent:
|
|
|
|
if obj_identifier not in child_folder_names:
|
|
|
|
folders.append(obj)
|
|
|
|
return folders
|
|
|
|
|
2011-01-23 02:13:55 -05:00
|
|
|
for k, v in enumerate(folders):
|
|
|
|
if isinstance(v, dict):
|
|
|
|
for f_k, f_v in v.items():
|
2012-08-12 18:57:29 -07:00
|
|
|
if f_k == in_folder and obj_identifier not in f_v and not added:
|
2011-01-23 02:13:55 -05:00
|
|
|
f_v.append(obj)
|
2011-03-09 20:09:32 -05:00
|
|
|
added = True
|
2012-08-12 18:57:29 -07:00
|
|
|
folders[k][f_k] = add_object_to_folder(obj, in_folder, f_v, f_k, added)
|
|
|
|
|
2011-01-26 22:02:23 -05:00
|
|
|
return folders
|
2011-02-05 15:34:43 -05:00
|
|
|
|
2012-01-05 20:59:48 -08:00
|
|
|
def mail_feed_error_to_admin(feed, e, local_vars=None, subject=None):
|
2011-02-05 15:34:43 -05:00
|
|
|
# Mail the admins with the error
|
2012-01-05 20:59:48 -08:00
|
|
|
if not subject:
|
|
|
|
subject = "Feed update error"
|
2011-02-05 15:34:43 -05:00
|
|
|
exc_info = sys.exc_info()
|
2012-01-05 20:59:48 -08:00
|
|
|
subject = '%s: %s' % (subject, repr(e))
|
2011-12-20 22:30:55 -08:00
|
|
|
message = 'Traceback:\n%s\n\Feed:\n%s\nLocals:\n%s' % (
|
2011-02-05 15:34:43 -05:00
|
|
|
'\n'.join(traceback.format_exception(*exc_info)),
|
2011-12-20 22:30:55 -08:00
|
|
|
pprint.pformat(feed.__dict__),
|
|
|
|
pprint.pformat(local_vars)
|
2011-02-05 15:34:43 -05:00
|
|
|
)
|
|
|
|
# print message
|
|
|
|
mail_admins(subject, message)
|