utils.py
author Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
Wed, 07 Oct 2009 19:59:46 +0200
branchstable
changeset 3608 5a46e68c3d3c
parent 3372 26b89dfe4170
child 3375 ebb11fa58ab9
child 3789 fb22b55f80f8
permissions -rw-r--r--
[editcontroller] backout (sort of) removal of entity.complete() in validate_form entity is passed to js callbacks when there's one. In that case, we want as much information as we can. The removal was there to avoid complete to fail when all constraints (required relations / attributes) aren't satisfied. This fix only does the complete() after the commit is done, any ValidationError should have been raised at this point.
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
3316
c4c07aab1c39 backport old head
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3231 3155
diff changeset
    13
import sys
c4c07aab1c39 backport old head
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3231 3155
diff changeset
    14
import decimal
c4c07aab1c39 backport old head
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3231 3155
diff changeset
    15
import datetime as pydatetime
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    16
from md5 import md5
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
    17
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
    18
from time import time, mktime
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    19
from random import randint, seed
1625
744f0cc8758f restore monthrange import
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 1616
diff changeset
    20
from calendar import monthrange
1549
f87561822e27 some basic calendar manipulation functions, delete-trailing-whitespace
sylvain.thenault@logilab.fr
parents: 1397
diff changeset
    21
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
    22
# 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
    23
seed()
1016
26387b836099 use datetime instead of mx.DateTime
sylvain.thenault@logilab.fr
parents: 709
diff changeset
    24
try:
26387b836099 use datetime instead of mx.DateTime
sylvain.thenault@logilab.fr
parents: 709
diff changeset
    25
    strptime = datetime.strptime
26387b836099 use datetime instead of mx.DateTime
sylvain.thenault@logilab.fr
parents: 709
diff changeset
    26
except AttributeError: # py < 2.5
26387b836099 use datetime instead of mx.DateTime
sylvain.thenault@logilab.fr
parents: 709
diff changeset
    27
    from time import strptime as time_strptime
26387b836099 use datetime instead of mx.DateTime
sylvain.thenault@logilab.fr
parents: 709
diff changeset
    28
    def strptime(value, format):
26387b836099 use datetime instead of mx.DateTime
sylvain.thenault@logilab.fr
parents: 709
diff changeset
    29
        return datetime(*time_strptime(value, format)[:6])
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    30
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
    31
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
    32
    """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
    33
    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
    34
        return date(somedate.year, somedate.month, somedate.day)
1603
56217e741939 more info if assertion fails
sylvain.thenault@logilab.fr
parents: 1549
diff changeset
    35
    assert isinstance(somedate, date), repr(somedate)
1621
6260508f7d71 todatetime impl., fix todate impl.
sylvain.thenault@logilab.fr
parents: 1616
diff changeset
    36
    return somedate
6260508f7d71 todatetime impl., fix todate impl.
sylvain.thenault@logilab.fr
parents: 1616
diff changeset
    37
6260508f7d71 todatetime impl., fix todate impl.
sylvain.thenault@logilab.fr
parents: 1616
diff changeset
    38
def todatetime(somedate):
6260508f7d71 todatetime impl., fix todate impl.
sylvain.thenault@logilab.fr
parents: 1616
diff changeset
    39
    """return a date from a date (leaving unchanged) or a datetime"""
1751
59e9a4f5bfea fix todatetime implementation
sylvain.thenault@logilab.fr
parents: 1711
diff changeset
    40
    # take care, datetime is a subclass of date
59e9a4f5bfea fix todatetime implementation
sylvain.thenault@logilab.fr
parents: 1711
diff changeset
    41
    if isinstance(somedate, datetime):
59e9a4f5bfea fix todatetime implementation
sylvain.thenault@logilab.fr
parents: 1711
diff changeset
    42
        return somedate
59e9a4f5bfea fix todatetime implementation
sylvain.thenault@logilab.fr
parents: 1711
diff changeset
    43
    assert isinstance(somedate, date), repr(somedate)
59e9a4f5bfea fix todatetime implementation
sylvain.thenault@logilab.fr
parents: 1711
diff changeset
    44
    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
    45
2009
b1e2b9e4c809 [utils] move datetime2ticks from cw.web.views.plots to cw.utils
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1977
diff changeset
    46
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
    47
    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
    48
1549
f87561822e27 some basic calendar manipulation functions, delete-trailing-whitespace
sylvain.thenault@logilab.fr
parents: 1397
diff changeset
    49
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
    50
ONEWEEK = timedelta(days=7)
1549
f87561822e27 some basic calendar manipulation functions, delete-trailing-whitespace
sylvain.thenault@logilab.fr
parents: 1397
diff changeset
    51
f87561822e27 some basic calendar manipulation functions, delete-trailing-whitespace
sylvain.thenault@logilab.fr
parents: 1397
diff changeset
    52
def days_in_month(date_):
f87561822e27 some basic calendar manipulation functions, delete-trailing-whitespace
sylvain.thenault@logilab.fr
parents: 1397
diff changeset
    53
    return monthrange(date_.year, date_.month)[1]
f87561822e27 some basic calendar manipulation functions, delete-trailing-whitespace
sylvain.thenault@logilab.fr
parents: 1397
diff changeset
    54
1697
5dae28906769 next_month / previous_month now support a new arg to give number of month
sylvain.thenault@logilab.fr
parents: 1626
diff changeset
    55
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
    56
    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
    57
        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
    58
        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
    59
    return date_
1549
f87561822e27 some basic calendar manipulation functions, delete-trailing-whitespace
sylvain.thenault@logilab.fr
parents: 1397
diff changeset
    60
1697
5dae28906769 next_month / previous_month now support a new arg to give number of month
sylvain.thenault@logilab.fr
parents: 1626
diff changeset
    61
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
    62
    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
    63
        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
    64
        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
    65
    return date_
1549
f87561822e27 some basic calendar manipulation functions, delete-trailing-whitespace
sylvain.thenault@logilab.fr
parents: 1397
diff changeset
    66
f87561822e27 some basic calendar manipulation functions, delete-trailing-whitespace
sylvain.thenault@logilab.fr
parents: 1397
diff changeset
    67
def first_day(date_):
f87561822e27 some basic calendar manipulation functions, delete-trailing-whitespace
sylvain.thenault@logilab.fr
parents: 1397
diff changeset
    68
    return date(date_.year, date_.month, 1)
f87561822e27 some basic calendar manipulation functions, delete-trailing-whitespace
sylvain.thenault@logilab.fr
parents: 1397
diff changeset
    69
f87561822e27 some basic calendar manipulation functions, delete-trailing-whitespace
sylvain.thenault@logilab.fr
parents: 1397
diff changeset
    70
def last_day(date_):
f87561822e27 some basic calendar manipulation functions, delete-trailing-whitespace
sylvain.thenault@logilab.fr
parents: 1397
diff changeset
    71
    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
    72
1705
d5e02874ae77 Fix date_range increments argument.
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 1697
diff changeset
    73
def date_range(begin, end, incday=None, incmonth=None):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    74
    """yields each date between begin and end
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    75
    :param begin: the start date
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    76
    :param end: the end date
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    77
    :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
    78
                 one day.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    79
    :param include: None (means no exclusion) or a function taking a
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    80
                    date as parameter, and returning True if the date
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    81
                    should be included.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    82
    """
1705
d5e02874ae77 Fix date_range increments argument.
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 1697
diff changeset
    83
    assert not (incday and incmonth)
d5e02874ae77 Fix date_range increments argument.
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 1697
diff changeset
    84
    begin = todate(begin)
1711
182536159750 Make sure end is datetime.date.
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 1705
diff changeset
    85
    end = todate(end)
1705
d5e02874ae77 Fix date_range increments argument.
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 1697
diff changeset
    86
    if incmonth:
d5e02874ae77 Fix date_range increments argument.
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 1697
diff changeset
    87
        while begin < end:
d5e02874ae77 Fix date_range increments argument.
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 1697
diff changeset
    88
            begin = next_month(begin, incmonth)
1132
96752791c2b6 pylint cleanup
sylvain.thenault@logilab.fr
parents: 1024
diff changeset
    89
            yield begin
1705
d5e02874ae77 Fix date_range increments argument.
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 1697
diff changeset
    90
    else:
d5e02874ae77 Fix date_range increments argument.
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 1697
diff changeset
    91
        if not incday:
d5e02874ae77 Fix date_range increments argument.
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 1697
diff changeset
    92
            incr = ONEDAY
d5e02874ae77 Fix date_range increments argument.
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 1697
diff changeset
    93
        else:
d5e02874ae77 Fix date_range increments argument.
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 1697
diff changeset
    94
            incr = timedelta(incday)
d5e02874ae77 Fix date_range increments argument.
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 1697
diff changeset
    95
        while begin <= end:
d5e02874ae77 Fix date_range increments argument.
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 1697
diff changeset
    96
           yield begin
d5e02874ae77 Fix date_range increments argument.
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 1697
diff changeset
    97
           begin += incr
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    98
709
b21ee900c732 avoid dependency to common
sylvain.thenault@logilab.fr
parents: 708
diff changeset
    99
def ustrftime(date, fmt='%Y-%m-%d'):
b21ee900c732 avoid dependency to common
sylvain.thenault@logilab.fr
parents: 708
diff changeset
   100
    """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
   101
    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
   102
709
b21ee900c732 avoid dependency to common
sylvain.thenault@logilab.fr
parents: 708
diff changeset
   103
    encoding is guessed by locale.getpreferredencoding()
b21ee900c732 avoid dependency to common
sylvain.thenault@logilab.fr
parents: 708
diff changeset
   104
    """
b21ee900c732 avoid dependency to common
sylvain.thenault@logilab.fr
parents: 708
diff changeset
   105
    # date format may depend on the locale
b21ee900c732 avoid dependency to common
sylvain.thenault@logilab.fr
parents: 708
diff changeset
   106
    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
   107
    return unicode(date.strftime(str(fmt)), encoding)
709
b21ee900c732 avoid dependency to common
sylvain.thenault@logilab.fr
parents: 708
diff changeset
   108
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
   109
3146
cfc4344023f2 have a better make_uid function, esp. useful for win32 as collisions are frequents with the old one
Aurelien Campeas
parents: 3101
diff changeset
   110
if sys.version_info[:2] < (2, 5):
cfc4344023f2 have a better make_uid function, esp. useful for win32 as collisions are frequents with the old one
Aurelien Campeas
parents: 3101
diff changeset
   111
    def make_uid(key):
cfc4344023f2 have a better make_uid function, esp. useful for win32 as collisions are frequents with the old one
Aurelien Campeas
parents: 3101
diff changeset
   112
        """forge a unique identifier
cfc4344023f2 have a better make_uid function, esp. useful for win32 as collisions are frequents with the old one
Aurelien Campeas
parents: 3101
diff changeset
   113
        not that unique on win32"""
cfc4344023f2 have a better make_uid function, esp. useful for win32 as collisions are frequents with the old one
Aurelien Campeas
parents: 3101
diff changeset
   114
        msg = str(key) + "%.10f" % time() + str(randint(0, 1000000))
cfc4344023f2 have a better make_uid function, esp. useful for win32 as collisions are frequents with the old one
Aurelien Campeas
parents: 3101
diff changeset
   115
        return md5(msg).hexdigest()
cfc4344023f2 have a better make_uid function, esp. useful for win32 as collisions are frequents with the old one
Aurelien Campeas
parents: 3101
diff changeset
   116
else:
cfc4344023f2 have a better make_uid function, esp. useful for win32 as collisions are frequents with the old one
Aurelien Campeas
parents: 3101
diff changeset
   117
    from uuid import uuid4
cfc4344023f2 have a better make_uid function, esp. useful for win32 as collisions are frequents with the old one
Aurelien Campeas
parents: 3101
diff changeset
   118
    def make_uid(key):
3364
039d1694f36d fix uid generation for py >= 2.5
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3316
diff changeset
   119
        # remove dash, generated uid are used as identifier sometimes (sql table
039d1694f36d fix uid generation for py >= 2.5
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3316
diff changeset
   120
        # names at least)
039d1694f36d fix uid generation for py >= 2.5
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3316
diff changeset
   121
        return str(key) + str(uuid4()).replace('-', '')
039d1694f36d fix uid generation for py >= 2.5
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3316
diff changeset
   122
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   123
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   124
def dump_class(cls, clsname):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   125
    """create copy of a class by creating an empty class inheriting
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   126
    from the given cls.
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
    Those class will be used as place holder for attribute and relation
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   129
    description
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   130
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   131
    # type doesn't accept unicode name
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   132
    # return type.__new__(type, str(clsname), (cls,), {})
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   133
    # __autogenerated__ attribute is just a marker
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   134
    return type(str(clsname), (cls,), {'__autogenerated__': True})
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
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   137
def merge_dicts(dict1, dict2):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   138
    """update a copy of `dict1` with `dict2`"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   139
    dict1 = dict(dict1)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   140
    dict1.update(dict2)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   141
    return dict1
1549
f87561822e27 some basic calendar manipulation functions, delete-trailing-whitespace
sylvain.thenault@logilab.fr
parents: 1397
diff changeset
   142
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   143
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   144
class SizeConstrainedList(list):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   145
    """simple list that makes sure the list does not get bigger
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   146
    than a given size.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   147
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   148
    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
   149
    element of the list is removed before appending the new one
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
    >>> l = SizeConstrainedList(2)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   152
    >>> l.append(1)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   153
    >>> l.append(2)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   154
    >>> l
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   155
    [1, 2]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   156
    >>> l.append(3)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   157
    [2, 3]
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 __init__(self, maxsize):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   160
        self.maxsize = maxsize
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   161
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   162
    def append(self, element):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   163
        if len(self) == self.maxsize:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   164
            del self[0]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   165
        super(SizeConstrainedList, self).append(element)
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
    def extend(self, sequence):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   168
        super(SizeConstrainedList, self).extend(sequence)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   169
        keepafter = len(self) - self.maxsize
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   170
        if keepafter > 0:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   171
            del self[:keepafter]
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
    __iadd__ = extend
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   174
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   175
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   176
class UStringIO(list):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   177
    """a file wrapper which automatically encode unicode string to an encoding
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   178
    specifed in the constructor
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   179
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   180
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   181
    def __nonzero__(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   182
        return True
1549
f87561822e27 some basic calendar manipulation functions, delete-trailing-whitespace
sylvain.thenault@logilab.fr
parents: 1397
diff changeset
   183
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   184
    def write(self, value):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   185
        assert isinstance(value, unicode), u"unicode required not %s : %s"\
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   186
                                     % (type(value).__name__, repr(value))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   187
        self.append(value)
1549
f87561822e27 some basic calendar manipulation functions, delete-trailing-whitespace
sylvain.thenault@logilab.fr
parents: 1397
diff changeset
   188
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   189
    def getvalue(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   190
        return u''.join(self)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   191
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   192
    def __repr__(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   193
        return '<%s at %#x>' % (self.__class__.__name__, id(self))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   194
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
class HTMLHead(UStringIO):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   197
    """wraps HTML header's stream
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   198
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   199
    Request objects use a HTMLHead instance to ease adding of
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   200
    javascripts and stylesheets
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   201
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   202
    js_unload_code = u'jQuery(window).unload(unloadPageData);'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   203
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   204
    def __init__(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   205
        super(HTMLHead, self).__init__()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   206
        self.jsvars = []
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   207
        self.jsfiles = []
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   208
        self.cssfiles = []
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   209
        self.ie_cssfiles = []
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   210
        self.post_inlined_scripts = []
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   211
        self.pagedata_unload = False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   212
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   213
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   214
    def add_raw(self, rawheader):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   215
        self.write(rawheader)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   216
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   217
    def define_var(self, var, value):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   218
        self.jsvars.append( (var, value) )
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   219
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   220
    def add_post_inline_script(self, content):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   221
        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
   222
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
   223
    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
   224
        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
   225
            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
   226
%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
   227
});""" % 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
   228
        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
   229
            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
   230
 %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
   231
 });""" % jscode)
1549
f87561822e27 some basic calendar manipulation functions, delete-trailing-whitespace
sylvain.thenault@logilab.fr
parents: 1397
diff changeset
   232
f87561822e27 some basic calendar manipulation functions, delete-trailing-whitespace
sylvain.thenault@logilab.fr
parents: 1397
diff changeset
   233
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   234
    def add_js(self, jsfile):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   235
        """adds `jsfile` to the list of javascripts used in the webpage
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   236
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   237
        This function checks if the file has already been added
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   238
        :param jsfile: the script's URL
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   239
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   240
        if jsfile not in self.jsfiles:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   241
            self.jsfiles.append(jsfile)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   242
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   243
    def add_css(self, cssfile, media):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   244
        """adds `cssfile` to the list of javascripts used in the webpage
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   245
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   246
        This function checks if the file has already been added
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   247
        :param cssfile: the stylesheet's URL
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
        if (cssfile, media) not in self.cssfiles:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   250
            self.cssfiles.append( (cssfile, media) )
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   251
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   252
    def add_ie_css(self, cssfile, media='all'):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   253
        """registers some IE specific CSS"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   254
        if (cssfile, media) not in self.ie_cssfiles:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   255
            self.ie_cssfiles.append( (cssfile, media) )
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   256
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   257
    def add_unload_pagedata(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   258
        """registers onunload callback to clean page data on server"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   259
        if not self.pagedata_unload:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   260
            self.post_inlined_scripts.append(self.js_unload_code)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   261
            self.pagedata_unload = True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   262
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
   263
    def getvalue(self, skiphead=False):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   264
        """reimplement getvalue to provide a consistent (and somewhat browser
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   265
        optimzed cf. http://stevesouders.com/cuzillion) order in external
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   266
        resources declaration
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   267
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   268
        w = self.write
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   269
        # 1/ variable declaration if any
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   270
        if self.jsvars:
2554
3b6a6d2f9d7e make jsvars declaration xhtml and html compatible
Fabrice <fabrice@secondweb.fr>
parents: 2361
diff changeset
   271
            w(u'<script type="text/javascript"><!--//--><![CDATA[//><!--\n')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   272
            for var, value in self.jsvars:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   273
                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
   274
            w(u'//--><!]]></script>\n')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   275
        # 2/ css files
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   276
        for cssfile, media in self.cssfiles:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   277
            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
   278
              (media, xml_escape(cssfile)))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   279
        # 3/ ie css if necessary
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   280
        if self.ie_cssfiles:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   281
            w(u'<!--[if lt IE 8]>\n')
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   282
            for cssfile, media in self.ie_cssfiles:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   283
                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
   284
                  (media, xml_escape(cssfile)))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   285
            w(u'<![endif]--> \n')
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   286
        # 4/ js files
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   287
        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
   288
            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
   289
              xml_escape(jsfile))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   290
        # 5/ post inlined scripts (i.e. scripts depending on other JS files)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   291
        if self.post_inlined_scripts:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   292
            w(u'<script type="text/javascript">\n')
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   293
            w(u'\n\n'.join(self.post_inlined_scripts))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   294
            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
   295
        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
   296
        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
   297
            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
   298
        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
   299
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   300
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   301
class HTMLStream(object):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   302
    """represents a HTML page.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   303
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   304
    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
   305
    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
   306
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   307
    HTMLStream uses the (U)StringIO interface to be compliant with
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   308
    existing code.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   309
    """
1549
f87561822e27 some basic calendar manipulation functions, delete-trailing-whitespace
sylvain.thenault@logilab.fr
parents: 1397
diff changeset
   310
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   311
    def __init__(self, req):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   312
        # stream for <head>
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   313
        self.head = req.html_headers
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   314
        # main stream
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   315
        self.body = UStringIO()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   316
        self.doctype = u''
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   317
        # xmldecl and html opening tag
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   318
        self.xmldecl = u'<?xml version="1.0" encoding="%s"?>\n' % req.encoding
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   319
        self.htmltag = u'<html xmlns="http://www.w3.org/1999/xhtml" ' \
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   320
                       'xmlns:cubicweb="http://www.logilab.org/2008/cubicweb" ' \
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   321
                       '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
   322
        # 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
   323
        req.main_stream = self
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   324
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   325
    def write(self, data):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   326
        """StringIO interface: this method will be assigned to self.w
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   327
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   328
        self.body.write(data)
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
    def getvalue(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   331
        """writes HTML headers, closes </head> tag and writes HTML body"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   332
        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
   333
                                                 self.htmltag,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   334
                                                 self.head.getvalue(),
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   335
                                                 self.body.getvalue())
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   336
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   337
2935
e06b3eadef31 [views,pdf] minimal support for xhtml->pdf conversion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2932
diff changeset
   338
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
   339
    """pdf conversion depends on
e06b3eadef31 [views,pdf] minimal support for xhtml->pdf conversion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2932
diff changeset
   340
    * pyxmltrf (python package)
e06b3eadef31 [views,pdf] minimal support for xhtml->pdf conversion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2932
diff changeset
   341
    * fop 0.9x
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   342
    """
2935
e06b3eadef31 [views,pdf] minimal support for xhtml->pdf conversion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2932
diff changeset
   343
    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
   344
        return __answer[0]
e06b3eadef31 [views,pdf] minimal support for xhtml->pdf conversion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2932
diff changeset
   345
    try:
2936
f35b64718d02 follow name change, fix pdf template registration, add debian package tracking
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2935
diff changeset
   346
        import pysixt
2935
e06b3eadef31 [views,pdf] minimal support for xhtml->pdf conversion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2932
diff changeset
   347
    except ImportError:
e06b3eadef31 [views,pdf] minimal support for xhtml->pdf conversion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2932
diff changeset
   348
        __answer[0] = False
e06b3eadef31 [views,pdf] minimal support for xhtml->pdf conversion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2932
diff changeset
   349
        return False
e06b3eadef31 [views,pdf] minimal support for xhtml->pdf conversion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2932
diff changeset
   350
    from subprocess import Popen, STDOUT
e06b3eadef31 [views,pdf] minimal support for xhtml->pdf conversion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2932
diff changeset
   351
    import os
e06b3eadef31 [views,pdf] minimal support for xhtml->pdf conversion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2932
diff changeset
   352
    try:
e06b3eadef31 [views,pdf] minimal support for xhtml->pdf conversion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2932
diff changeset
   353
        Popen(['/usr/bin/fop', '-q'],
e06b3eadef31 [views,pdf] minimal support for xhtml->pdf conversion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2932
diff changeset
   354
              stdout=open(os.devnull, 'w'),
e06b3eadef31 [views,pdf] minimal support for xhtml->pdf conversion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2932
diff changeset
   355
              stderr=STDOUT)
e06b3eadef31 [views,pdf] minimal support for xhtml->pdf conversion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2932
diff changeset
   356
    except OSError, e:
e06b3eadef31 [views,pdf] minimal support for xhtml->pdf conversion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2932
diff changeset
   357
        print e
e06b3eadef31 [views,pdf] minimal support for xhtml->pdf conversion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2932
diff changeset
   358
        __answer[0] = False
e06b3eadef31 [views,pdf] minimal support for xhtml->pdf conversion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2932
diff changeset
   359
        return False
e06b3eadef31 [views,pdf] minimal support for xhtml->pdf conversion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2932
diff changeset
   360
    __answer[0] = True
e06b3eadef31 [views,pdf] minimal support for xhtml->pdf conversion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2932
diff changeset
   361
    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
   362
3371
762a7bc3b73d this has probably be killed by a bad merge...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3364
diff changeset
   363
try:
3372
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3371
diff changeset
   364
    # may not be there if cubicweb-web not installed
3371
762a7bc3b73d this has probably be killed by a bad merge...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3364
diff changeset
   365
    from simplejson import dumps, JSONEncoder
762a7bc3b73d this has probably be killed by a bad merge...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3364
diff changeset
   366
except ImportError:
762a7bc3b73d this has probably be killed by a bad merge...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3364
diff changeset
   367
    pass
762a7bc3b73d this has probably be killed by a bad merge...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3364
diff changeset
   368
else:
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
   369
3371
762a7bc3b73d this has probably be killed by a bad merge...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3364
diff changeset
   370
    class CubicWebJsonEncoder(JSONEncoder):
762a7bc3b73d this has probably be killed by a bad merge...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3364
diff changeset
   371
        """define a simplejson encoder to be able to encode yams std types"""
762a7bc3b73d this has probably be killed by a bad merge...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3364
diff changeset
   372
        def default(self, obj):
762a7bc3b73d this has probably be killed by a bad merge...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3364
diff changeset
   373
            if isinstance(obj, pydatetime.datetime):
762a7bc3b73d this has probably be killed by a bad merge...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3364
diff changeset
   374
                return obj.strftime('%Y/%m/%d %H:%M:%S')
762a7bc3b73d this has probably be killed by a bad merge...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3364
diff changeset
   375
            elif isinstance(obj, pydatetime.date):
762a7bc3b73d this has probably be killed by a bad merge...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3364
diff changeset
   376
                return obj.strftime('%Y/%m/%d')
762a7bc3b73d this has probably be killed by a bad merge...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3364
diff changeset
   377
            elif isinstance(obj, pydatetime.time):
762a7bc3b73d this has probably be killed by a bad merge...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3364
diff changeset
   378
                return obj.strftime('%H:%M:%S')
762a7bc3b73d this has probably be killed by a bad merge...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3364
diff changeset
   379
            elif isinstance(obj, decimal.Decimal):
762a7bc3b73d this has probably be killed by a bad merge...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3364
diff changeset
   380
                return float(obj)
762a7bc3b73d this has probably be killed by a bad merge...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3364
diff changeset
   381
            try:
762a7bc3b73d this has probably be killed by a bad merge...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3364
diff changeset
   382
                return JSONEncoder.default(self, obj)
762a7bc3b73d this has probably be killed by a bad merge...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3364
diff changeset
   383
            except TypeError:
762a7bc3b73d this has probably be killed by a bad merge...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3364
diff changeset
   384
                # we never ever want to fail because of an unknown type,
762a7bc3b73d this has probably be killed by a bad merge...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3364
diff changeset
   385
                # just return None in those cases.
762a7bc3b73d this has probably be killed by a bad merge...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3364
diff changeset
   386
                return None