utils.py
author Sylvain Thénault <sylvain.thenault@logilab.fr>
Wed, 16 Sep 2009 16:34:34 +0200
branch3.5
changeset 3247 a6243d9585ba
parent 3231 3ee43e2f8560
child 3293 69c0ba095536
child 3316 c4c07aab1c39
permissions -rw-r--r--
hide bookmarked_by relation from addrelated menu, we've a specific box for bookmarks
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     1
"""Some utilities for CubicWeb server/clients.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     2
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     3
:organization: Logilab
1977
606923dff11b big bunch of copyright / docstring update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1751
diff changeset
     4
:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     5
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
1977
606923dff11b big bunch of copyright / docstring update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1751
diff changeset
     6
:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     7
"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     8
__docformat__ = "restructuredtext en"
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     9
3091
c3d73cecb29e [html-head] escape js and css urls
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2678
diff changeset
    10
from logilab.mtconverter import xml_escape
c3d73cecb29e [html-head] escape js and css urls
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2678
diff changeset
    11
709
b21ee900c732 avoid dependency to common
sylvain.thenault@logilab.fr
parents: 708
diff changeset
    12
import locale
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    13
from md5 import md5
3231
3ee43e2f8560 [utils] provide a class to extend the default simplejson encoder to be able to dump standard yams attribute types
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3101
diff changeset
    14
import datetime as pydatetime
1024
bb96289257bf remove unused working_hours function, new todate function since we can't compare date and datetime objects
sylvain.thenault@logilab.fr
parents: 1016
diff changeset
    15
from datetime import datetime, timedelta, date
2009
b1e2b9e4c809 [utils] move datetime2ticks from cw.web.views.plots to cw.utils
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1977
diff changeset
    16
from time import time, mktime
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    17
from random import randint, seed
1625
744f0cc8758f restore monthrange import
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 1616
diff changeset
    18
from calendar import monthrange
3231
3ee43e2f8560 [utils] provide a class to extend the default simplejson encoder to be able to dump standard yams attribute types
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3101
diff changeset
    19
import decimal
3ee43e2f8560 [utils] provide a class to extend the default simplejson encoder to be able to dump standard yams attribute types
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3101
diff changeset
    20
3ee43e2f8560 [utils] provide a class to extend the default simplejson encoder to be able to dump standard yams attribute types
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3101
diff changeset
    21
import simplejson
1549
f87561822e27 some basic calendar manipulation functions, delete-trailing-whitespace
sylvain.thenault@logilab.fr
parents: 1397
diff changeset
    22
1024
bb96289257bf remove unused working_hours function, new todate function since we can't compare date and datetime objects
sylvain.thenault@logilab.fr
parents: 1016
diff changeset
    23
# initialize random seed from current time
bb96289257bf remove unused working_hours function, new todate function since we can't compare date and datetime objects
sylvain.thenault@logilab.fr
parents: 1016
diff changeset
    24
seed()
1016
26387b836099 use datetime instead of mx.DateTime
sylvain.thenault@logilab.fr
parents: 709
diff changeset
    25
try:
26387b836099 use datetime instead of mx.DateTime
sylvain.thenault@logilab.fr
parents: 709
diff changeset
    26
    strptime = datetime.strptime
26387b836099 use datetime instead of mx.DateTime
sylvain.thenault@logilab.fr
parents: 709
diff changeset
    27
except AttributeError: # py < 2.5
26387b836099 use datetime instead of mx.DateTime
sylvain.thenault@logilab.fr
parents: 709
diff changeset
    28
    from time import strptime as time_strptime
26387b836099 use datetime instead of mx.DateTime
sylvain.thenault@logilab.fr
parents: 709
diff changeset
    29
    def strptime(value, format):
26387b836099 use datetime instead of mx.DateTime
sylvain.thenault@logilab.fr
parents: 709
diff changeset
    30
        return datetime(*time_strptime(value, format)[:6])
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    31
1024
bb96289257bf remove unused working_hours function, new todate function since we can't compare date and datetime objects
sylvain.thenault@logilab.fr
parents: 1016
diff changeset
    32
def todate(somedate):
bb96289257bf remove unused working_hours function, new todate function since we can't compare date and datetime objects
sylvain.thenault@logilab.fr
parents: 1016
diff changeset
    33
    """return a date from a date (leaving unchanged) or a datetime"""
bb96289257bf remove unused working_hours function, new todate function since we can't compare date and datetime objects
sylvain.thenault@logilab.fr
parents: 1016
diff changeset
    34
    if isinstance(somedate, datetime):
bb96289257bf remove unused working_hours function, new todate function since we can't compare date and datetime objects
sylvain.thenault@logilab.fr
parents: 1016
diff changeset
    35
        return date(somedate.year, somedate.month, somedate.day)
1603
56217e741939 more info if assertion fails
sylvain.thenault@logilab.fr
parents: 1549
diff changeset
    36
    assert isinstance(somedate, date), repr(somedate)
1621
6260508f7d71 todatetime impl., fix todate impl.
sylvain.thenault@logilab.fr
parents: 1616
diff changeset
    37
    return somedate
6260508f7d71 todatetime impl., fix todate impl.
sylvain.thenault@logilab.fr
parents: 1616
diff changeset
    38
6260508f7d71 todatetime impl., fix todate impl.
sylvain.thenault@logilab.fr
parents: 1616
diff changeset
    39
def todatetime(somedate):
6260508f7d71 todatetime impl., fix todate impl.
sylvain.thenault@logilab.fr
parents: 1616
diff changeset
    40
    """return a date from a date (leaving unchanged) or a datetime"""
1751
59e9a4f5bfea fix todatetime implementation
sylvain.thenault@logilab.fr
parents: 1711
diff changeset
    41
    # take care, datetime is a subclass of date
59e9a4f5bfea fix todatetime implementation
sylvain.thenault@logilab.fr
parents: 1711
diff changeset
    42
    if isinstance(somedate, datetime):
59e9a4f5bfea fix todatetime implementation
sylvain.thenault@logilab.fr
parents: 1711
diff changeset
    43
        return somedate
59e9a4f5bfea fix todatetime implementation
sylvain.thenault@logilab.fr
parents: 1711
diff changeset
    44
    assert isinstance(somedate, date), repr(somedate)
59e9a4f5bfea fix todatetime implementation
sylvain.thenault@logilab.fr
parents: 1711
diff changeset
    45
    return datetime(somedate.year, somedate.month, somedate.day)
1024
bb96289257bf remove unused working_hours function, new todate function since we can't compare date and datetime objects
sylvain.thenault@logilab.fr
parents: 1016
diff changeset
    46
2009
b1e2b9e4c809 [utils] move datetime2ticks from cw.web.views.plots to cw.utils
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1977
diff changeset
    47
def datetime2ticks(date):
b1e2b9e4c809 [utils] move datetime2ticks from cw.web.views.plots to cw.utils
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1977
diff changeset
    48
    return mktime(date.timetuple()) * 1000
b1e2b9e4c809 [utils] move datetime2ticks from cw.web.views.plots to cw.utils
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1977
diff changeset
    49
1549
f87561822e27 some basic calendar manipulation functions, delete-trailing-whitespace
sylvain.thenault@logilab.fr
parents: 1397
diff changeset
    50
ONEDAY = timedelta(days=1)
1697
5dae28906769 next_month / previous_month now support a new arg to give number of month
sylvain.thenault@logilab.fr
parents: 1626
diff changeset
    51
ONEWEEK = timedelta(days=7)
1549
f87561822e27 some basic calendar manipulation functions, delete-trailing-whitespace
sylvain.thenault@logilab.fr
parents: 1397
diff changeset
    52
f87561822e27 some basic calendar manipulation functions, delete-trailing-whitespace
sylvain.thenault@logilab.fr
parents: 1397
diff changeset
    53
def days_in_month(date_):
f87561822e27 some basic calendar manipulation functions, delete-trailing-whitespace
sylvain.thenault@logilab.fr
parents: 1397
diff changeset
    54
    return monthrange(date_.year, date_.month)[1]
f87561822e27 some basic calendar manipulation functions, delete-trailing-whitespace
sylvain.thenault@logilab.fr
parents: 1397
diff changeset
    55
1697
5dae28906769 next_month / previous_month now support a new arg to give number of month
sylvain.thenault@logilab.fr
parents: 1626
diff changeset
    56
def previous_month(date_, nbmonth=1):
5dae28906769 next_month / previous_month now support a new arg to give number of month
sylvain.thenault@logilab.fr
parents: 1626
diff changeset
    57
    while nbmonth:
5dae28906769 next_month / previous_month now support a new arg to give number of month
sylvain.thenault@logilab.fr
parents: 1626
diff changeset
    58
        date_ = first_day(date_) - ONEDAY
5dae28906769 next_month / previous_month now support a new arg to give number of month
sylvain.thenault@logilab.fr
parents: 1626
diff changeset
    59
        nbmonth -= 1
5dae28906769 next_month / previous_month now support a new arg to give number of month
sylvain.thenault@logilab.fr
parents: 1626
diff changeset
    60
    return date_
1549
f87561822e27 some basic calendar manipulation functions, delete-trailing-whitespace
sylvain.thenault@logilab.fr
parents: 1397
diff changeset
    61
1697
5dae28906769 next_month / previous_month now support a new arg to give number of month
sylvain.thenault@logilab.fr
parents: 1626
diff changeset
    62
def next_month(date_, nbmonth=1):
5dae28906769 next_month / previous_month now support a new arg to give number of month
sylvain.thenault@logilab.fr
parents: 1626
diff changeset
    63
    while nbmonth:
5dae28906769 next_month / previous_month now support a new arg to give number of month
sylvain.thenault@logilab.fr
parents: 1626
diff changeset
    64
        date_ = last_day(date_) + ONEDAY
5dae28906769 next_month / previous_month now support a new arg to give number of month
sylvain.thenault@logilab.fr
parents: 1626
diff changeset
    65
        nbmonth -= 1
5dae28906769 next_month / previous_month now support a new arg to give number of month
sylvain.thenault@logilab.fr
parents: 1626
diff changeset
    66
    return date_
1549
f87561822e27 some basic calendar manipulation functions, delete-trailing-whitespace
sylvain.thenault@logilab.fr
parents: 1397
diff changeset
    67
f87561822e27 some basic calendar manipulation functions, delete-trailing-whitespace
sylvain.thenault@logilab.fr
parents: 1397
diff changeset
    68
def first_day(date_):
f87561822e27 some basic calendar manipulation functions, delete-trailing-whitespace
sylvain.thenault@logilab.fr
parents: 1397
diff changeset
    69
    return date(date_.year, date_.month, 1)
f87561822e27 some basic calendar manipulation functions, delete-trailing-whitespace
sylvain.thenault@logilab.fr
parents: 1397
diff changeset
    70
f87561822e27 some basic calendar manipulation functions, delete-trailing-whitespace
sylvain.thenault@logilab.fr
parents: 1397
diff changeset
    71
def last_day(date_):
f87561822e27 some basic calendar manipulation functions, delete-trailing-whitespace
sylvain.thenault@logilab.fr
parents: 1397
diff changeset
    72
    return date(date_.year, date_.month, days_in_month(date_))
f87561822e27 some basic calendar manipulation functions, delete-trailing-whitespace
sylvain.thenault@logilab.fr
parents: 1397
diff changeset
    73
1705
d5e02874ae77 Fix date_range increments argument.
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 1697
diff changeset
    74
def date_range(begin, end, incday=None, incmonth=None):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    75
    """yields each date between begin and end
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    76
    :param begin: the start date
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    77
    :param end: the end date
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    78
    :param incr: the step to use to iterate over dates. Default is
1549
f87561822e27 some basic calendar manipulation functions, delete-trailing-whitespace
sylvain.thenault@logilab.fr
parents: 1397
diff changeset
    79
                 one day.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    80
    :param include: None (means no exclusion) or a function taking a
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    81
                    date as parameter, and returning True if the date
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    82
                    should be included.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    83
    """
1705
d5e02874ae77 Fix date_range increments argument.
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 1697
diff changeset
    84
    assert not (incday and incmonth)
d5e02874ae77 Fix date_range increments argument.
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 1697
diff changeset
    85
    begin = todate(begin)
1711
182536159750 Make sure end is datetime.date.
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 1705
diff changeset
    86
    end = todate(end)
1705
d5e02874ae77 Fix date_range increments argument.
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 1697
diff changeset
    87
    if incmonth:
d5e02874ae77 Fix date_range increments argument.
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 1697
diff changeset
    88
        while begin < end:
d5e02874ae77 Fix date_range increments argument.
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 1697
diff changeset
    89
            begin = next_month(begin, incmonth)
1132
96752791c2b6 pylint cleanup
sylvain.thenault@logilab.fr
parents: 1024
diff changeset
    90
            yield begin
1705
d5e02874ae77 Fix date_range increments argument.
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 1697
diff changeset
    91
    else:
d5e02874ae77 Fix date_range increments argument.
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 1697
diff changeset
    92
        if not incday:
d5e02874ae77 Fix date_range increments argument.
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 1697
diff changeset
    93
            incr = ONEDAY
d5e02874ae77 Fix date_range increments argument.
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 1697
diff changeset
    94
        else:
d5e02874ae77 Fix date_range increments argument.
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 1697
diff changeset
    95
            incr = timedelta(incday)
d5e02874ae77 Fix date_range increments argument.
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 1697
diff changeset
    96
        while begin <= end:
d5e02874ae77 Fix date_range increments argument.
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 1697
diff changeset
    97
           yield begin
d5e02874ae77 Fix date_range increments argument.
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 1697
diff changeset
    98
           begin += incr
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    99
709
b21ee900c732 avoid dependency to common
sylvain.thenault@logilab.fr
parents: 708
diff changeset
   100
def ustrftime(date, fmt='%Y-%m-%d'):
b21ee900c732 avoid dependency to common
sylvain.thenault@logilab.fr
parents: 708
diff changeset
   101
    """like strftime, but returns a unicode string instead of an encoded
1705
d5e02874ae77 Fix date_range increments argument.
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 1697
diff changeset
   102
    string which' may be problematic with localized date.
1549
f87561822e27 some basic calendar manipulation functions, delete-trailing-whitespace
sylvain.thenault@logilab.fr
parents: 1397
diff changeset
   103
709
b21ee900c732 avoid dependency to common
sylvain.thenault@logilab.fr
parents: 708
diff changeset
   104
    encoding is guessed by locale.getpreferredencoding()
b21ee900c732 avoid dependency to common
sylvain.thenault@logilab.fr
parents: 708
diff changeset
   105
    """
b21ee900c732 avoid dependency to common
sylvain.thenault@logilab.fr
parents: 708
diff changeset
   106
    # date format may depend on the locale
b21ee900c732 avoid dependency to common
sylvain.thenault@logilab.fr
parents: 708
diff changeset
   107
    encoding = locale.getpreferredencoding(do_setlocale=False) or 'UTF-8'
1397
6cbc7bc8ea6d rollback florent's not-proven-to-be-useful fix
sylvain.thenault@logilab.fr
parents: 1387
diff changeset
   108
    return unicode(date.strftime(str(fmt)), encoding)
709
b21ee900c732 avoid dependency to common
sylvain.thenault@logilab.fr
parents: 708
diff changeset
   109
1024
bb96289257bf remove unused working_hours function, new todate function since we can't compare date and datetime objects
sylvain.thenault@logilab.fr
parents: 1016
diff changeset
   110
def make_uid(key):
bb96289257bf remove unused working_hours function, new todate function since we can't compare date and datetime objects
sylvain.thenault@logilab.fr
parents: 1016
diff changeset
   111
    """forge a unique identifier"""
2009
b1e2b9e4c809 [utils] move datetime2ticks from cw.web.views.plots to cw.utils
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1977
diff changeset
   112
    msg = str(key) + "%.10f" % time() + str(randint(0, 1000000))
1024
bb96289257bf remove unused working_hours function, new todate function since we can't compare date and datetime objects
sylvain.thenault@logilab.fr
parents: 1016
diff changeset
   113
    return md5(msg).hexdigest()
bb96289257bf remove unused working_hours function, new todate function since we can't compare date and datetime objects
sylvain.thenault@logilab.fr
parents: 1016
diff changeset
   114
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   115
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   116
def dump_class(cls, clsname):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   117
    """create copy of a class by creating an empty class inheriting
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   118
    from the given cls.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   119
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   120
    Those class will be used as place holder for attribute and relation
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   121
    description
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   122
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   123
    # type doesn't accept unicode name
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   124
    # return type.__new__(type, str(clsname), (cls,), {})
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   125
    # __autogenerated__ attribute is just a marker
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   126
    return type(str(clsname), (cls,), {'__autogenerated__': True})
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   127
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   128
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   129
def merge_dicts(dict1, dict2):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   130
    """update a copy of `dict1` with `dict2`"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   131
    dict1 = dict(dict1)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   132
    dict1.update(dict2)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   133
    return dict1
1549
f87561822e27 some basic calendar manipulation functions, delete-trailing-whitespace
sylvain.thenault@logilab.fr
parents: 1397
diff changeset
   134
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   135
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   136
class SizeConstrainedList(list):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   137
    """simple list that makes sure the list does not get bigger
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   138
    than a given size.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   139
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   140
    when the list is full and a new element is added, the first
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   141
    element of the list is removed before appending the new one
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   142
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   143
    >>> l = SizeConstrainedList(2)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   144
    >>> l.append(1)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   145
    >>> l.append(2)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   146
    >>> l
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   147
    [1, 2]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   148
    >>> l.append(3)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   149
    [2, 3]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   150
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   151
    def __init__(self, maxsize):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   152
        self.maxsize = maxsize
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   153
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   154
    def append(self, element):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   155
        if len(self) == self.maxsize:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   156
            del self[0]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   157
        super(SizeConstrainedList, self).append(element)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   158
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   159
    def extend(self, sequence):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   160
        super(SizeConstrainedList, self).extend(sequence)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   161
        keepafter = len(self) - self.maxsize
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   162
        if keepafter > 0:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   163
            del self[:keepafter]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   164
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   165
    __iadd__ = extend
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   166
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   167
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   168
class UStringIO(list):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   169
    """a file wrapper which automatically encode unicode string to an encoding
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   170
    specifed in the constructor
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   171
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   172
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   173
    def __nonzero__(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   174
        return True
1549
f87561822e27 some basic calendar manipulation functions, delete-trailing-whitespace
sylvain.thenault@logilab.fr
parents: 1397
diff changeset
   175
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   176
    def write(self, value):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   177
        assert isinstance(value, unicode), u"unicode required not %s : %s"\
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   178
                                     % (type(value).__name__, repr(value))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   179
        self.append(value)
1549
f87561822e27 some basic calendar manipulation functions, delete-trailing-whitespace
sylvain.thenault@logilab.fr
parents: 1397
diff changeset
   180
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   181
    def getvalue(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   182
        return u''.join(self)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   183
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   184
    def __repr__(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   185
        return '<%s at %#x>' % (self.__class__.__name__, id(self))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   186
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   187
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   188
class HTMLHead(UStringIO):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   189
    """wraps HTML header's stream
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   190
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   191
    Request objects use a HTMLHead instance to ease adding of
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   192
    javascripts and stylesheets
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   193
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   194
    js_unload_code = u'jQuery(window).unload(unloadPageData);'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   195
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   196
    def __init__(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   197
        super(HTMLHead, self).__init__()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   198
        self.jsvars = []
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   199
        self.jsfiles = []
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   200
        self.cssfiles = []
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   201
        self.ie_cssfiles = []
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   202
        self.post_inlined_scripts = []
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   203
        self.pagedata_unload = False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   204
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   205
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   206
    def add_raw(self, rawheader):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   207
        self.write(rawheader)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   208
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   209
    def define_var(self, var, value):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   210
        self.jsvars.append( (var, value) )
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   211
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   212
    def add_post_inline_script(self, content):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   213
        self.post_inlined_scripts.append(content)
28
9b7067bfaa15 introduce html_headers.on_load() method as a shortcut for add_post_inline_script('''jQuery(document).ready(...''')
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 0
diff changeset
   214
2258
79bc598c6411 when request is a json request, bind on 'ajax-loaded' instead of document.ready()
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2009
diff changeset
   215
    def add_onload(self, jscode, jsoncall=False):
79bc598c6411 when request is a json request, bind on 'ajax-loaded' instead of document.ready()
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2009
diff changeset
   216
        if jsoncall:
79bc598c6411 when request is a json request, bind on 'ajax-loaded' instead of document.ready()
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2009
diff changeset
   217
            self.add_post_inline_script(u"""jQuery(CubicWeb).bind('ajax-loaded', function(event) {
79bc598c6411 when request is a json request, bind on 'ajax-loaded' instead of document.ready()
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2009
diff changeset
   218
%s
79bc598c6411 when request is a json request, bind on 'ajax-loaded' instead of document.ready()
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2009
diff changeset
   219
});""" % jscode)
79bc598c6411 when request is a json request, bind on 'ajax-loaded' instead of document.ready()
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2009
diff changeset
   220
        else:
79bc598c6411 when request is a json request, bind on 'ajax-loaded' instead of document.ready()
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2009
diff changeset
   221
            self.add_post_inline_script(u"""jQuery(document).ready(function () {
28
9b7067bfaa15 introduce html_headers.on_load() method as a shortcut for add_post_inline_script('''jQuery(document).ready(...''')
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 0
diff changeset
   222
 %s
9b7067bfaa15 introduce html_headers.on_load() method as a shortcut for add_post_inline_script('''jQuery(document).ready(...''')
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 0
diff changeset
   223
 });""" % jscode)
1549
f87561822e27 some basic calendar manipulation functions, delete-trailing-whitespace
sylvain.thenault@logilab.fr
parents: 1397
diff changeset
   224
f87561822e27 some basic calendar manipulation functions, delete-trailing-whitespace
sylvain.thenault@logilab.fr
parents: 1397
diff changeset
   225
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   226
    def add_js(self, jsfile):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   227
        """adds `jsfile` to the list of javascripts used in the webpage
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   228
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   229
        This function checks if the file has already been added
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   230
        :param jsfile: the script's URL
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   231
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   232
        if jsfile not in self.jsfiles:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   233
            self.jsfiles.append(jsfile)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   234
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   235
    def add_css(self, cssfile, media):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   236
        """adds `cssfile` to the list of javascripts used in the webpage
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   237
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   238
        This function checks if the file has already been added
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   239
        :param cssfile: the stylesheet's URL
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   240
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   241
        if (cssfile, media) not in self.cssfiles:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   242
            self.cssfiles.append( (cssfile, media) )
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   243
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   244
    def add_ie_css(self, cssfile, media='all'):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   245
        """registers some IE specific CSS"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   246
        if (cssfile, media) not in self.ie_cssfiles:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   247
            self.ie_cssfiles.append( (cssfile, media) )
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   248
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   249
    def add_unload_pagedata(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   250
        """registers onunload callback to clean page data on server"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   251
        if not self.pagedata_unload:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   252
            self.post_inlined_scripts.append(self.js_unload_code)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   253
            self.pagedata_unload = True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   254
643
616191014b8b [jsoncontroller] reorganize _html_exec (used by replacePageChunk) to output required css and js scripts
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 28
diff changeset
   255
    def getvalue(self, skiphead=False):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   256
        """reimplement getvalue to provide a consistent (and somewhat browser
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   257
        optimzed cf. http://stevesouders.com/cuzillion) order in external
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   258
        resources declaration
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   259
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   260
        w = self.write
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   261
        # 1/ variable declaration if any
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   262
        if self.jsvars:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   263
            from simplejson import dumps
2554
3b6a6d2f9d7e make jsvars declaration xhtml and html compatible
Fabrice <fabrice@secondweb.fr>
parents: 2361
diff changeset
   264
            w(u'<script type="text/javascript"><!--//--><![CDATA[//><!--\n')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   265
            for var, value in self.jsvars:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   266
                w(u'%s = %s;\n' % (var, dumps(value)))
2554
3b6a6d2f9d7e make jsvars declaration xhtml and html compatible
Fabrice <fabrice@secondweb.fr>
parents: 2361
diff changeset
   267
            w(u'//--><!]]></script>\n')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   268
        # 2/ css files
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   269
        for cssfile, media in self.cssfiles:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   270
            w(u'<link rel="stylesheet" type="text/css" media="%s" href="%s"/>\n' %
3091
c3d73cecb29e [html-head] escape js and css urls
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2678
diff changeset
   271
              (media, xml_escape(cssfile)))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   272
        # 3/ ie css if necessary
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   273
        if self.ie_cssfiles:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   274
            w(u'<!--[if lt IE 8]>\n')
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   275
            for cssfile, media in self.ie_cssfiles:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   276
                w(u'<link rel="stylesheet" type="text/css" media="%s" href="%s"/>\n' %
3091
c3d73cecb29e [html-head] escape js and css urls
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2678
diff changeset
   277
                  (media, xml_escape(cssfile)))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   278
            w(u'<![endif]--> \n')
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   279
        # 4/ js files
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   280
        for jsfile in self.jsfiles:
3091
c3d73cecb29e [html-head] escape js and css urls
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2678
diff changeset
   281
            w(u'<script type="text/javascript" src="%s"></script>\n' %
c3d73cecb29e [html-head] escape js and css urls
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2678
diff changeset
   282
              xml_escape(jsfile))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   283
        # 5/ post inlined scripts (i.e. scripts depending on other JS files)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   284
        if self.post_inlined_scripts:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   285
            w(u'<script type="text/javascript">\n')
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   286
            w(u'\n\n'.join(self.post_inlined_scripts))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   287
            w(u'\n</script>\n')
643
616191014b8b [jsoncontroller] reorganize _html_exec (used by replacePageChunk) to output required css and js scripts
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 28
diff changeset
   288
        header = super(HTMLHead, self).getvalue()
616191014b8b [jsoncontroller] reorganize _html_exec (used by replacePageChunk) to output required css and js scripts
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 28
diff changeset
   289
        if skiphead:
616191014b8b [jsoncontroller] reorganize _html_exec (used by replacePageChunk) to output required css and js scripts
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 28
diff changeset
   290
            return header
616191014b8b [jsoncontroller] reorganize _html_exec (used by replacePageChunk) to output required css and js scripts
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 28
diff changeset
   291
        return u'<head>\n%s</head>\n' % header
1549
f87561822e27 some basic calendar manipulation functions, delete-trailing-whitespace
sylvain.thenault@logilab.fr
parents: 1397
diff changeset
   292
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   293
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   294
class HTMLStream(object):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   295
    """represents a HTML page.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   296
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   297
    This is used my main templates so that HTML headers can be added
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   298
    at any time during the page generation.
1549
f87561822e27 some basic calendar manipulation functions, delete-trailing-whitespace
sylvain.thenault@logilab.fr
parents: 1397
diff changeset
   299
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   300
    HTMLStream uses the (U)StringIO interface to be compliant with
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   301
    existing code.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   302
    """
1549
f87561822e27 some basic calendar manipulation functions, delete-trailing-whitespace
sylvain.thenault@logilab.fr
parents: 1397
diff changeset
   303
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   304
    def __init__(self, req):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   305
        # stream for <head>
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   306
        self.head = req.html_headers
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   307
        # main stream
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   308
        self.body = UStringIO()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   309
        self.doctype = u''
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   310
        # xmldecl and html opening tag
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   311
        self.xmldecl = u'<?xml version="1.0" encoding="%s"?>\n' % req.encoding
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   312
        self.htmltag = u'<html xmlns="http://www.w3.org/1999/xhtml" ' \
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   313
                       'xmlns:cubicweb="http://www.logilab.org/2008/cubicweb" ' \
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   314
                       'xml:lang="%s" lang="%s">' % (req.lang, req.lang)
3094
978ed8c2c0e4 [googlemap] #344872 set request content-type to text/html
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3091
diff changeset
   315
        # keep main_stream's reference on req for easier text/html demoting
978ed8c2c0e4 [googlemap] #344872 set request content-type to text/html
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3091
diff changeset
   316
        req.main_stream = self
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   317
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   318
    def write(self, data):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   319
        """StringIO interface: this method will be assigned to self.w
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   320
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   321
        self.body.write(data)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   322
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   323
    def getvalue(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   324
        """writes HTML headers, closes </head> tag and writes HTML body"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   325
        return u'%s\n%s\n%s\n%s\n%s\n</html>' % (self.xmldecl, self.doctype,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   326
                                                 self.htmltag,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   327
                                                 self.head.getvalue(),
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   328
                                                 self.body.getvalue())
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   329
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   330
2935
e06b3eadef31 [views,pdf] minimal support for xhtml->pdf conversion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2932
diff changeset
   331
def can_do_pdf_conversion(__answer=[None]):
e06b3eadef31 [views,pdf] minimal support for xhtml->pdf conversion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2932
diff changeset
   332
    """pdf conversion depends on
e06b3eadef31 [views,pdf] minimal support for xhtml->pdf conversion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2932
diff changeset
   333
    * pyxmltrf (python package)
e06b3eadef31 [views,pdf] minimal support for xhtml->pdf conversion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2932
diff changeset
   334
    * fop 0.9x
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   335
    """
2935
e06b3eadef31 [views,pdf] minimal support for xhtml->pdf conversion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2932
diff changeset
   336
    if __answer[0] is not None:
e06b3eadef31 [views,pdf] minimal support for xhtml->pdf conversion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2932
diff changeset
   337
        return __answer[0]
e06b3eadef31 [views,pdf] minimal support for xhtml->pdf conversion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2932
diff changeset
   338
    try:
2936
f35b64718d02 follow name change, fix pdf template registration, add debian package tracking
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2935
diff changeset
   339
        import pysixt
2935
e06b3eadef31 [views,pdf] minimal support for xhtml->pdf conversion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2932
diff changeset
   340
    except ImportError:
e06b3eadef31 [views,pdf] minimal support for xhtml->pdf conversion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2932
diff changeset
   341
        __answer[0] = False
e06b3eadef31 [views,pdf] minimal support for xhtml->pdf conversion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2932
diff changeset
   342
        return False
e06b3eadef31 [views,pdf] minimal support for xhtml->pdf conversion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2932
diff changeset
   343
    from subprocess import Popen, STDOUT
e06b3eadef31 [views,pdf] minimal support for xhtml->pdf conversion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2932
diff changeset
   344
    import os
e06b3eadef31 [views,pdf] minimal support for xhtml->pdf conversion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2932
diff changeset
   345
    try:
e06b3eadef31 [views,pdf] minimal support for xhtml->pdf conversion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2932
diff changeset
   346
        Popen(['/usr/bin/fop', '-q'],
e06b3eadef31 [views,pdf] minimal support for xhtml->pdf conversion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2932
diff changeset
   347
              stdout=open(os.devnull, 'w'),
e06b3eadef31 [views,pdf] minimal support for xhtml->pdf conversion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2932
diff changeset
   348
              stderr=STDOUT)
e06b3eadef31 [views,pdf] minimal support for xhtml->pdf conversion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2932
diff changeset
   349
    except OSError, e:
e06b3eadef31 [views,pdf] minimal support for xhtml->pdf conversion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2932
diff changeset
   350
        print e
e06b3eadef31 [views,pdf] minimal support for xhtml->pdf conversion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2932
diff changeset
   351
        __answer[0] = False
e06b3eadef31 [views,pdf] minimal support for xhtml->pdf conversion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2932
diff changeset
   352
        return False
e06b3eadef31 [views,pdf] minimal support for xhtml->pdf conversion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2932
diff changeset
   353
    __answer[0] = True
e06b3eadef31 [views,pdf] minimal support for xhtml->pdf conversion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2932
diff changeset
   354
    return True
3231
3ee43e2f8560 [utils] provide a class to extend the default simplejson encoder to be able to dump standard yams attribute types
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3101
diff changeset
   355
3ee43e2f8560 [utils] provide a class to extend the default simplejson encoder to be able to dump standard yams attribute types
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3101
diff changeset
   356
3ee43e2f8560 [utils] provide a class to extend the default simplejson encoder to be able to dump standard yams attribute types
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3101
diff changeset
   357
class CubicWebJsonEncoder(simplejson.JSONEncoder):
3ee43e2f8560 [utils] provide a class to extend the default simplejson encoder to be able to dump standard yams attribute types
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3101
diff changeset
   358
    """define a simplejson encoder to be able to encode yams std types"""
3ee43e2f8560 [utils] provide a class to extend the default simplejson encoder to be able to dump standard yams attribute types
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3101
diff changeset
   359
    def default(self, obj):
3ee43e2f8560 [utils] provide a class to extend the default simplejson encoder to be able to dump standard yams attribute types
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3101
diff changeset
   360
        if isinstance(obj, pydatetime.datetime):
3ee43e2f8560 [utils] provide a class to extend the default simplejson encoder to be able to dump standard yams attribute types
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3101
diff changeset
   361
            return obj.strftime('%Y/%m/%d %H:%M:%S')
3ee43e2f8560 [utils] provide a class to extend the default simplejson encoder to be able to dump standard yams attribute types
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3101
diff changeset
   362
        elif isinstance(obj, pydatetime.date):
3ee43e2f8560 [utils] provide a class to extend the default simplejson encoder to be able to dump standard yams attribute types
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3101
diff changeset
   363
            return obj.strftime('%Y/%m/%d')
3ee43e2f8560 [utils] provide a class to extend the default simplejson encoder to be able to dump standard yams attribute types
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3101
diff changeset
   364
        elif isinstance(obj, pydatetime.time):
3ee43e2f8560 [utils] provide a class to extend the default simplejson encoder to be able to dump standard yams attribute types
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3101
diff changeset
   365
            return obj.strftime('%H:%M:%S')
3ee43e2f8560 [utils] provide a class to extend the default simplejson encoder to be able to dump standard yams attribute types
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3101
diff changeset
   366
        elif isinstance(obj, decimal.Decimal):
3ee43e2f8560 [utils] provide a class to extend the default simplejson encoder to be able to dump standard yams attribute types
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3101
diff changeset
   367
            return float(obj)
3ee43e2f8560 [utils] provide a class to extend the default simplejson encoder to be able to dump standard yams attribute types
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3101
diff changeset
   368
        try:
3ee43e2f8560 [utils] provide a class to extend the default simplejson encoder to be able to dump standard yams attribute types
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3101
diff changeset
   369
            return simplejson.JSONEncoder.default(self, obj)
3ee43e2f8560 [utils] provide a class to extend the default simplejson encoder to be able to dump standard yams attribute types
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3101
diff changeset
   370
        except TypeError:
3ee43e2f8560 [utils] provide a class to extend the default simplejson encoder to be able to dump standard yams attribute types
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3101
diff changeset
   371
            # we never ever want to fail because of an unknown type,
3ee43e2f8560 [utils] provide a class to extend the default simplejson encoder to be able to dump standard yams attribute types
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3101
diff changeset
   372
            # just return None in those cases.
3ee43e2f8560 [utils] provide a class to extend the default simplejson encoder to be able to dump standard yams attribute types
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3101
diff changeset
   373
            return None