diff -r c25da7573ebd -r 02b52bf9f5f8 utils.py --- a/utils.py Fri Feb 12 15:18:00 2010 +0100 +++ b/utils.py Wed Mar 24 10:23:31 2010 +0100 @@ -7,121 +7,36 @@ """ __docformat__ = "restructuredtext en" -from logilab.mtconverter import xml_escape - -import locale +import os import sys import decimal -import datetime as pydatetime -from md5 import md5 -from datetime import datetime, timedelta, date -from time import time -from random import randint, seed -from calendar import monthrange, timegm +import datetime +import random + +from logilab.mtconverter import xml_escape +from logilab.common.deprecation import deprecated # initialize random seed from current time -seed() -try: - strptime = datetime.strptime -except AttributeError: # py < 2.5 - from time import strptime as time_strptime - def strptime(value, format): - return datetime(*time_strptime(value, format)[:6]) - -def todate(somedate): - """return a date from a date (leaving unchanged) or a datetime""" - if isinstance(somedate, datetime): - return date(somedate.year, somedate.month, somedate.day) - assert isinstance(somedate, date), repr(somedate) - return somedate - -def todatetime(somedate): - """return a date from a date (leaving unchanged) or a datetime""" - # take care, datetime is a subclass of date - if isinstance(somedate, datetime): - return somedate - assert isinstance(somedate, date), repr(somedate) - return datetime(somedate.year, somedate.month, somedate.day) - -def datetime2ticks(date): - return timegm(date.timetuple()) * 1000 - -ONEDAY = timedelta(days=1) -ONEWEEK = timedelta(days=7) - -def days_in_month(date_): - return monthrange(date_.year, date_.month)[1] - -def days_in_year(date_): - feb = pydatetime.date(date_.year, 2, 1) - if days_in_month(feb) == 29: - return 366 - else: - return 365 - -def previous_month(date_, nbmonth=1): - while nbmonth: - date_ = first_day(date_) - ONEDAY - nbmonth -= 1 - return date_ - -def next_month(date_, nbmonth=1): - while nbmonth: - date_ = last_day(date_) + ONEDAY - nbmonth -= 1 - return date_ - -def first_day(date_): - return date(date_.year, date_.month, 1) - -def last_day(date_): - return date(date_.year, date_.month, days_in_month(date_)) - -def date_range(begin, end, incday=None, incmonth=None): - """yields each date between begin and end - :param begin: the start date - :param end: the end date - :param incr: the step to use to iterate over dates. Default is - one day. - :param include: None (means no exclusion) or a function taking a - date as parameter, and returning True if the date - should be included. - """ - assert not (incday and incmonth) - begin = todate(begin) - end = todate(end) - if incmonth: - while begin < end: - begin = next_month(begin, incmonth) - yield begin - else: - if not incday: - incr = ONEDAY - else: - incr = timedelta(incday) - while begin <= end: - yield begin - begin += incr - -def ustrftime(date, fmt='%Y-%m-%d'): - """like strftime, but returns a unicode string instead of an encoded - string which' may be problematic with localized date. - - encoding is guessed by locale.getpreferredencoding() - """ - # date format may depend on the locale - encoding = locale.getpreferredencoding(do_setlocale=False) or 'UTF-8' - return unicode(date.strftime(str(fmt)), encoding) - +random.seed() if sys.version_info[:2] < (2, 5): + + from time import time + from md5 import md5 + from random import randint + def make_uid(key): """forge a unique identifier - not that unique on win32""" - msg = str(key) + "%.10f" % time() + str(randint(0, 1000000)) - return md5(msg).hexdigest() + XXX not that unique on win32 + """ + key = str(key) + msg = key + "%.10f" % time() + str(randint(0, 1000000)) + return key + md5(msg).hexdigest() + else: + from uuid import uuid4 + def make_uid(key): # remove dash, generated uid are used as identifier sometimes (sql table # names at least) @@ -254,7 +169,7 @@ def add_onload(self, jscode, jsoncall=False): if jsoncall: - self.add_post_inline_script(u"""jQuery(CubicWeb).bind('ajax-loaded', function(event) { + self.add_post_inline_script(u"""jQuery(CubicWeb).one('ajax-loaded', function(event) { %s });""" % jscode) else: @@ -281,10 +196,10 @@ if (cssfile, media) not in self.cssfiles: self.cssfiles.append( (cssfile, media) ) - def add_ie_css(self, cssfile, media='all'): + def add_ie_css(self, cssfile, media='all', iespec=u'[if lt IE 8]'): """registers some IE specific CSS""" - if (cssfile, media) not in self.ie_cssfiles: - self.ie_cssfiles.append( (cssfile, media) ) + if (cssfile, media, iespec) not in self.ie_cssfiles: + self.ie_cssfiles.append( (cssfile, media, iespec) ) def add_unload_pagedata(self): """registers onunload callback to clean page data on server""" @@ -314,8 +229,8 @@ (media, xml_escape(cssfile))) # 3/ ie css if necessary if self.ie_cssfiles: - w(u' \n') @@ -371,31 +286,35 @@ self.body.getvalue()) -def can_do_pdf_conversion(__answer=[None]): - """pdf conversion depends on - * pysixt (python package) - * fop 0.9x - """ - if __answer[0] is not None: - return __answer[0] +def _pdf_conversion_availability(): try: import pysixt except ImportError: - __answer[0] = False return False from subprocess import Popen, STDOUT - import os + if not os.path.isfile('/usr/bin/fop'): + return False try: Popen(['/usr/bin/fop', '-q'], stdout=open(os.devnull, 'w'), stderr=STDOUT) except OSError, e: - print e - __answer[0] = False + getLogger('cubicweb').info('fop not usable (%s)', e) return False - __answer[0] = True return True +def can_do_pdf_conversion(__answer_cache=[]): + """pdf conversion depends on + * pysixt (python package) + * fop 0.9x + + NOTE: actual check is done by _pdf_conversion_availability and + result is cached + """ + if not __answer_cache: # first time, not in cache + __answer_cache.append(_pdf_conversion_availability()) + return __answer_cache[0] + try: # may not be there if cubicweb-web not installed from simplejson import dumps, JSONEncoder @@ -406,13 +325,13 @@ class CubicWebJsonEncoder(JSONEncoder): """define a simplejson encoder to be able to encode yams std types""" def default(self, obj): - if isinstance(obj, pydatetime.datetime): + if isinstance(obj, datetime.datetime): return obj.strftime('%Y/%m/%d %H:%M:%S') - elif isinstance(obj, pydatetime.date): + elif isinstance(obj, datetime.date): return obj.strftime('%Y/%m/%d') - elif isinstance(obj, pydatetime.time): + elif isinstance(obj, datetime.time): return obj.strftime('%H:%M:%S') - elif isinstance(obj, pydatetime.timedelta): + elif isinstance(obj, datetime.timedelta): return (obj.days * 24 * 60 * 60) + obj.seconds elif isinstance(obj, decimal.Decimal): return float(obj) @@ -422,3 +341,12 @@ # we never ever want to fail because of an unknown type, # just return None in those cases. return None + +from logilab.common import date +_THIS_MOD_NS = globals() +for funcname in ('date_range', 'todate', 'todatetime', 'datetime2ticks', + 'days_in_month', 'days_in_year', 'previous_month', + 'next_month', 'first_day', 'last_day', 'ustrftime', + 'strptime'): + msg = '[3.6] %s has been moved to logilab.common.date' % funcname + _THIS_MOD_NS[funcname] = deprecated(msg)(getattr(date, funcname))