cubicweb/utils.py
author Simon Chabot <simon.chabot@logilab.fr>
Thu, 05 Mar 2020 17:49:34 +0100
branch3.26
changeset 12908 5c6d242069b6
parent 12874 cc71a801b846
permissions -rw-r--r--
[pkg] version 3.26.17
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
10118
78ab2b14048a [utils] provide a function to return an admin connection from an appid
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10090
diff changeset
     1
# copyright 2003-2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
5421
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5389
diff changeset
     2
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5389
diff changeset
     3
#
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5389
diff changeset
     4
# This file is part of CubicWeb.
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5389
diff changeset
     5
#
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5389
diff changeset
     6
# CubicWeb is free software: you can redistribute it and/or modify it under the
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5389
diff changeset
     7
# terms of the GNU Lesser General Public License as published by the Free
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5389
diff changeset
     8
# Software Foundation, either version 2.1 of the License, or (at your option)
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5389
diff changeset
     9
# any later version.
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5389
diff changeset
    10
#
5424
8ecbcbff9777 replace logilab-common by CubicWeb in disclaimer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5421
diff changeset
    11
# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
5421
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5389
diff changeset
    12
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5389
diff changeset
    13
# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5389
diff changeset
    14
# details.
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5389
diff changeset
    15
#
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5389
diff changeset
    16
# You should have received a copy of the GNU Lesser General Public License along
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5389
diff changeset
    17
# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
6044
9e48ebd5400c [view] use the new magic js object to generate javascript func call for auto reload user callbacks
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5940
diff changeset
    18
"""Some utilities for CubicWeb server/clients."""
7956
db49658b2812 add missing imports
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7954
diff changeset
    19
10067
16c554c76eb4 Remove obsolete __future__ imports
Rémi Cardona <remi.cardona@free.fr>
parents: 10004
diff changeset
    20
from __future__ import division
7956
db49658b2812 add missing imports
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7954
diff changeset
    21
11715
760d5c0ae08f [utils] Encode Binary value in base64 for JSON export
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11057
diff changeset
    22
import base64
3316
c4c07aab1c39 backport old head
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3231 3155
diff changeset
    23
import decimal
4466
8b0ca7904820 moved generic datetime manipulation function to lgc
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4335
diff changeset
    24
import datetime
4653
ca11228a5268 import cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4652
diff changeset
    25
import random
7998
9ef285eb20f4 [utils] add a ``js_href`` function to generated proper javascript href
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7990
diff changeset
    26
import re
9579
d5b0e1f4c5c5 [utils] the json module is always available
Julien Cristau <julien.cristau@logilab.fr>
parents: 9523
diff changeset
    27
import json
7998
9ef285eb20f4 [utils] add a ``js_href`` function to generated proper javascript href
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7990
diff changeset
    28
12319
3ee1db91fb00 [python3] use inspect.getfullargspec instead of inspect.getargspec
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 12046
diff changeset
    29
from six import PY3
3ee1db91fb00 [python3] use inspect.getfullargspec instead of inspect.getargspec
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 12046
diff changeset
    30
7954
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
    31
from operator import itemgetter
12319
3ee1db91fb00 [python3] use inspect.getfullargspec instead of inspect.getargspec
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 12046
diff changeset
    32
if PY3:
3ee1db91fb00 [python3] use inspect.getfullargspec instead of inspect.getargspec
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 12046
diff changeset
    33
    from inspect import getfullargspec as getargspec
3ee1db91fb00 [python3] use inspect.getfullargspec instead of inspect.getargspec
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 12046
diff changeset
    34
else:
3ee1db91fb00 [python3] use inspect.getfullargspec instead of inspect.getargspec
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 12046
diff changeset
    35
    from inspect import getargspec
12874
cc71a801b846 [utils] Add the possibility to add elements in the head of an UStringIO list
Guillaume Vandevelde <gvandevelde@logilab.fr>
parents: 12319
diff changeset
    36
from functools import wraps
5069
135c5d7b89d0 [querier] introduce RepeatList class, used to optimize size of data returned for result set description
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4961
diff changeset
    37
from itertools import repeat
4833
41a78fb4107c 3.7 depends on python >= 2.5
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4693
diff changeset
    38
from uuid import uuid4
4830
10e8bc190695 [javascript] fix #736185: add_onload / jQuery.bind() vs. jQuery.one()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4693
diff changeset
    39
from warnings import warn
7954
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
    40
from threading import Lock
10603
65ad6980976e [py3k] import URL mangling functions using six.moves
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10510
diff changeset
    41
from logging import getLogger
7954
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
    42
10687
d394bfcd8c25 [py3k] unicode → six.text_type
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10662
diff changeset
    43
from six import text_type
4653
ca11228a5268 import cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4652
diff changeset
    44
ca11228a5268 import cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4652
diff changeset
    45
from logilab.mtconverter import xml_escape
ca11228a5268 import cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4652
diff changeset
    46
from logilab.common.deprecation import deprecated
9579
d5b0e1f4c5c5 [utils] the json module is always available
Julien Cristau <julien.cristau@logilab.fr>
parents: 9523
diff changeset
    47
from logilab.common.date import ustrftime
1549
f87561822e27 some basic calendar manipulation functions, delete-trailing-whitespace
sylvain.thenault@logilab.fr
parents: 1397
diff changeset
    48
11715
760d5c0ae08f [utils] Encode Binary value in base64 for JSON export
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11057
diff changeset
    49
from cubicweb import Binary
760d5c0ae08f [utils] Encode Binary value in base64 for JSON export
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11057
diff changeset
    50
760d5c0ae08f [utils] Encode Binary value in base64 for JSON export
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11057
diff changeset
    51
4830
10e8bc190695 [javascript] fix #736185: add_onload / jQuery.bind() vs. jQuery.one()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4693
diff changeset
    52
_MARKER = object()
10e8bc190695 [javascript] fix #736185: add_onload / jQuery.bind() vs. jQuery.one()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4693
diff changeset
    53
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
    54
# initialize random seed from current time
4653
ca11228a5268 import cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4652
diff changeset
    55
random.seed()
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
    56
12046
9056a41d91ba Fix flake8 some errors
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 12044
diff changeset
    57
10118
78ab2b14048a [utils] provide a function to return an admin connection from an appid
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10090
diff changeset
    58
def admincnx(appid):
12044
70bb46dfa87b [repo] Drop repo.new_session method
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 12032
diff changeset
    59
    from cubicweb import repoapi
10118
78ab2b14048a [utils] provide a function to return an admin connection from an appid
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10090
diff changeset
    60
    from cubicweb.cwconfig import CubicWebConfiguration
78ab2b14048a [utils] provide a function to return an admin connection from an appid
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10090
diff changeset
    61
    from cubicweb.server.repository import Repository
78ab2b14048a [utils] provide a function to return an admin connection from an appid
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10090
diff changeset
    62
    config = CubicWebConfiguration.config_for(appid)
78ab2b14048a [utils] provide a function to return an admin connection from an appid
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10090
diff changeset
    63
78ab2b14048a [utils] provide a function to return an admin connection from an appid
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10090
diff changeset
    64
    login = config.default_admin_config['login']
78ab2b14048a [utils] provide a function to return an admin connection from an appid
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10090
diff changeset
    65
    password = config.default_admin_config['password']
78ab2b14048a [utils] provide a function to return an admin connection from an appid
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10090
diff changeset
    66
11984
55f57038e553 [utils] Do not pass a tasks manager to Repository in admincnx()
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11983
diff changeset
    67
    repo = Repository(config)
11983
5de78b6fff2e [server] Separate repository bootstrap from initialization
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11909
diff changeset
    68
    repo.bootstrap()
12044
70bb46dfa87b [repo] Drop repo.new_session method
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 12032
diff changeset
    69
    return repoapi.connect(repo, login, password=password)
10118
78ab2b14048a [utils] provide a function to return an admin connection from an appid
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10090
diff changeset
    70
78ab2b14048a [utils] provide a function to return an admin connection from an appid
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10090
diff changeset
    71
4880
fa6671e83639 [utils] make_uid imrovment: using .hex already remove '-', make key argument optional, document it
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4879
diff changeset
    72
def make_uid(key=None):
fa6671e83639 [utils] make_uid imrovment: using .hex already remove '-', make key argument optional, document it
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4879
diff changeset
    73
    """Return a unique identifier string.
4653
ca11228a5268 import cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4652
diff changeset
    74
4880
fa6671e83639 [utils] make_uid imrovment: using .hex already remove '-', make key argument optional, document it
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4879
diff changeset
    75
    if specified, `key` is used to prefix the generated uid so it can be used
9232
430a7dc5e2cf [utils] fix typos in make_uid docstring
Julien Cristau <julien.cristau@logilab.fr>
parents: 8941
diff changeset
    76
    for instance as a DOM id or as sql table name.
4653
ca11228a5268 import cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4652
diff changeset
    77
4880
fa6671e83639 [utils] make_uid imrovment: using .hex already remove '-', make key argument optional, document it
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4879
diff changeset
    78
    See uuid.uuid4 documentation for the shape of the generated identifier, but
9232
430a7dc5e2cf [utils] fix typos in make_uid docstring
Julien Cristau <julien.cristau@logilab.fr>
parents: 8941
diff changeset
    79
    this is basically a 32 bits hexadecimal string.
4880
fa6671e83639 [utils] make_uid imrovment: using .hex already remove '-', make key argument optional, document it
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4879
diff changeset
    80
    """
fa6671e83639 [utils] make_uid imrovment: using .hex already remove '-', make key argument optional, document it
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4879
diff changeset
    81
    if key is None:
fa6671e83639 [utils] make_uid imrovment: using .hex already remove '-', make key argument optional, document it
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4879
diff changeset
    82
        return uuid4().hex
fa6671e83639 [utils] make_uid imrovment: using .hex already remove '-', make key argument optional, document it
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4879
diff changeset
    83
    return str(key) + uuid4().hex
3364
039d1694f36d fix uid generation for py >= 2.5
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3316
diff changeset
    84
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    85
6067
efca814587e2 [primary] refactor primary view handling of relation's label
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6044
diff changeset
    86
def support_args(callable, *argnames):
efca814587e2 [primary] refactor primary view handling of relation's label
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6044
diff changeset
    87
    """return true if the callable support given argument names"""
6913
ab85124dc0eb [utils] support_args now support classes, searching if __init__ supports the arguments
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6684
diff changeset
    88
    if isinstance(callable, type):
ab85124dc0eb [utils] support_args now support classes, searching if __init__ supports the arguments
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6684
diff changeset
    89
        callable = callable.__init__
6067
efca814587e2 [primary] refactor primary view handling of relation's label
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6044
diff changeset
    90
    argspec = getargspec(callable)
efca814587e2 [primary] refactor primary view handling of relation's label
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6044
diff changeset
    91
    if argspec[2]:
efca814587e2 [primary] refactor primary view handling of relation's label
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6044
diff changeset
    92
        return True
efca814587e2 [primary] refactor primary view handling of relation's label
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6044
diff changeset
    93
    for argname in argnames:
efca814587e2 [primary] refactor primary view handling of relation's label
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6044
diff changeset
    94
        if argname not in argspec[0]:
efca814587e2 [primary] refactor primary view handling of relation's label
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6044
diff changeset
    95
            return False
efca814587e2 [primary] refactor primary view handling of relation's label
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6044
diff changeset
    96
    return True
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    97
6141
b8287e54b528 [web api] unify 'contentnav' (VComponent) and 'boxes' registries as 'ctxcomponents' (CtxComponent)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6067
diff changeset
    98
b8287e54b528 [web api] unify 'contentnav' (VComponent) and 'boxes' registries as 'ctxcomponents' (CtxComponent)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6067
diff changeset
    99
class wrap_on_write(object):
6580
798200432f50 some docstrings
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 6492
diff changeset
   100
    """ Sometimes it is convenient to NOT write some container element
798200432f50 some docstrings
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 6492
diff changeset
   101
    if it happens that there is nothing to be written within,
798200432f50 some docstrings
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 6492
diff changeset
   102
    but this cannot be known beforehand.
798200432f50 some docstrings
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 6492
diff changeset
   103
    Hence one can do this:
798200432f50 some docstrings
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 6492
diff changeset
   104
798200432f50 some docstrings
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 6492
diff changeset
   105
    .. sourcecode:: python
798200432f50 some docstrings
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 6492
diff changeset
   106
798200432f50 some docstrings
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 6492
diff changeset
   107
       with wrap_on_write(w, '<div class="foo">', '</div>') as wow:
798200432f50 some docstrings
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 6492
diff changeset
   108
           component.render_stuff(wow)
798200432f50 some docstrings
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 6492
diff changeset
   109
    """
6141
b8287e54b528 [web api] unify 'contentnav' (VComponent) and 'boxes' registries as 'ctxcomponents' (CtxComponent)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6067
diff changeset
   110
    def __init__(self, w, tag, closetag=None):
b8287e54b528 [web api] unify 'contentnav' (VComponent) and 'boxes' registries as 'ctxcomponents' (CtxComponent)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6067
diff changeset
   111
        self.written = False
10689
49a62b8f6d43 [py3k] unicode vs str vs bytes vs the world
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10687
diff changeset
   112
        self.tag = text_type(tag)
6141
b8287e54b528 [web api] unify 'contentnav' (VComponent) and 'boxes' registries as 'ctxcomponents' (CtxComponent)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6067
diff changeset
   113
        self.closetag = closetag
b8287e54b528 [web api] unify 'contentnav' (VComponent) and 'boxes' registries as 'ctxcomponents' (CtxComponent)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6067
diff changeset
   114
        self.w = w
b8287e54b528 [web api] unify 'contentnav' (VComponent) and 'boxes' registries as 'ctxcomponents' (CtxComponent)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6067
diff changeset
   115
b8287e54b528 [web api] unify 'contentnav' (VComponent) and 'boxes' registries as 'ctxcomponents' (CtxComponent)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6067
diff changeset
   116
    def __enter__(self):
b8287e54b528 [web api] unify 'contentnav' (VComponent) and 'boxes' registries as 'ctxcomponents' (CtxComponent)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6067
diff changeset
   117
        return self
b8287e54b528 [web api] unify 'contentnav' (VComponent) and 'boxes' registries as 'ctxcomponents' (CtxComponent)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6067
diff changeset
   118
b8287e54b528 [web api] unify 'contentnav' (VComponent) and 'boxes' registries as 'ctxcomponents' (CtxComponent)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6067
diff changeset
   119
    def __call__(self, data):
b8287e54b528 [web api] unify 'contentnav' (VComponent) and 'boxes' registries as 'ctxcomponents' (CtxComponent)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6067
diff changeset
   120
        if self.written is False:
b8287e54b528 [web api] unify 'contentnav' (VComponent) and 'boxes' registries as 'ctxcomponents' (CtxComponent)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6067
diff changeset
   121
            self.w(self.tag)
b8287e54b528 [web api] unify 'contentnav' (VComponent) and 'boxes' registries as 'ctxcomponents' (CtxComponent)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6067
diff changeset
   122
            self.written = True
b8287e54b528 [web api] unify 'contentnav' (VComponent) and 'boxes' registries as 'ctxcomponents' (CtxComponent)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6067
diff changeset
   123
        self.w(data)
b8287e54b528 [web api] unify 'contentnav' (VComponent) and 'boxes' registries as 'ctxcomponents' (CtxComponent)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6067
diff changeset
   124
b8287e54b528 [web api] unify 'contentnav' (VComponent) and 'boxes' registries as 'ctxcomponents' (CtxComponent)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6067
diff changeset
   125
    def __exit__(self, exctype, value, traceback):
b8287e54b528 [web api] unify 'contentnav' (VComponent) and 'boxes' registries as 'ctxcomponents' (CtxComponent)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6067
diff changeset
   126
        if self.written is True:
b8287e54b528 [web api] unify 'contentnav' (VComponent) and 'boxes' registries as 'ctxcomponents' (CtxComponent)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6067
diff changeset
   127
            if self.closetag:
10689
49a62b8f6d43 [py3k] unicode vs str vs bytes vs the world
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10687
diff changeset
   128
                self.w(text_type(self.closetag))
6141
b8287e54b528 [web api] unify 'contentnav' (VComponent) and 'boxes' registries as 'ctxcomponents' (CtxComponent)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6067
diff changeset
   129
            else:
b8287e54b528 [web api] unify 'contentnav' (VComponent) and 'boxes' registries as 'ctxcomponents' (CtxComponent)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6067
diff changeset
   130
                self.w(self.tag.replace('<', '</', 1))
b8287e54b528 [web api] unify 'contentnav' (VComponent) and 'boxes' registries as 'ctxcomponents' (CtxComponent)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6067
diff changeset
   131
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   132
3882
addc715f4fcd backported from confman
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3851
diff changeset
   133
# use networkX instead ?
addc715f4fcd backported from confman
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3851
diff changeset
   134
# http://networkx.lanl.gov/reference/algorithms.traversal.html#module-networkx.algorithms.traversal.astar
6854
ffc982faa264 [views] delete ``permission`` tab in ``SchemaView``
cheb
parents: 6684
diff changeset
   135
def transitive_closure_of(entity, rtype, _seen=None):
4317
b2093f8f0493 some docstring
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4212
diff changeset
   136
    """return transitive closure *for the subgraph starting from the given
b2093f8f0493 some docstring
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4212
diff changeset
   137
    entity* (eg 'parent' entities are not included in the results)
b2093f8f0493 some docstring
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4212
diff changeset
   138
    """
3882
addc715f4fcd backported from confman
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3851
diff changeset
   139
    if _seen is None:
addc715f4fcd backported from confman
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3851
diff changeset
   140
        _seen = set()
addc715f4fcd backported from confman
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3851
diff changeset
   141
    _seen.add(entity.eid)
addc715f4fcd backported from confman
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3851
diff changeset
   142
    yield entity
6854
ffc982faa264 [views] delete ``permission`` tab in ``SchemaView``
cheb
parents: 6684
diff changeset
   143
    for child in getattr(entity, rtype):
3882
addc715f4fcd backported from confman
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3851
diff changeset
   144
        if child.eid in _seen:
addc715f4fcd backported from confman
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3851
diff changeset
   145
            continue
6854
ffc982faa264 [views] delete ``permission`` tab in ``SchemaView``
cheb
parents: 6684
diff changeset
   146
        for subchild in transitive_closure_of(child, rtype, _seen):
3882
addc715f4fcd backported from confman
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3851
diff changeset
   147
            yield subchild
addc715f4fcd backported from confman
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3851
diff changeset
   148
addc715f4fcd backported from confman
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3851
diff changeset
   149
5069
135c5d7b89d0 [querier] introduce RepeatList class, used to optimize size of data returned for result set description
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4961
diff changeset
   150
class RepeatList(object):
135c5d7b89d0 [querier] introduce RepeatList class, used to optimize size of data returned for result set description
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4961
diff changeset
   151
    """fake a list with the same element in each row"""
135c5d7b89d0 [querier] introduce RepeatList class, used to optimize size of data returned for result set description
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4961
diff changeset
   152
    __slots__ = ('_size', '_item')
135c5d7b89d0 [querier] introduce RepeatList class, used to optimize size of data returned for result set description
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4961
diff changeset
   153
    def __init__(self, size, item):
135c5d7b89d0 [querier] introduce RepeatList class, used to optimize size of data returned for result set description
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4961
diff changeset
   154
        self._size = size
135c5d7b89d0 [querier] introduce RepeatList class, used to optimize size of data returned for result set description
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4961
diff changeset
   155
        self._item = item
5883
7a5f370c5be1 [utils] improve repr() of RepeatList
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 5726
diff changeset
   156
    def __repr__(self):
7a5f370c5be1 [utils] improve repr() of RepeatList
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 5726
diff changeset
   157
        return '<cubicweb.utils.RepeatList at %s item=%s size=%s>' % (
7a5f370c5be1 [utils] improve repr() of RepeatList
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 5726
diff changeset
   158
            id(self), self._item, self._size)
5069
135c5d7b89d0 [querier] introduce RepeatList class, used to optimize size of data returned for result set description
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4961
diff changeset
   159
    def __len__(self):
135c5d7b89d0 [querier] introduce RepeatList class, used to optimize size of data returned for result set description
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4961
diff changeset
   160
        return self._size
135c5d7b89d0 [querier] introduce RepeatList class, used to optimize size of data returned for result set description
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4961
diff changeset
   161
    def __iter__(self):
135c5d7b89d0 [querier] introduce RepeatList class, used to optimize size of data returned for result set description
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4961
diff changeset
   162
        return repeat(self._item, self._size)
135c5d7b89d0 [querier] introduce RepeatList class, used to optimize size of data returned for result set description
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4961
diff changeset
   163
    def __getitem__(self, index):
10691
af266f27c4d5 [py3k] __getslice__ → __getitem__ with slice support
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10690
diff changeset
   164
        if isinstance(index, slice):
af266f27c4d5 [py3k] __getslice__ → __getitem__ with slice support
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10690
diff changeset
   165
            # XXX could be more efficient, but do we bother?
af266f27c4d5 [py3k] __getslice__ → __getitem__ with slice support
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10690
diff changeset
   166
            return ([self._item] * self._size)[index]
5069
135c5d7b89d0 [querier] introduce RepeatList class, used to optimize size of data returned for result set description
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4961
diff changeset
   167
        return self._item
6374
5adf53edfe12 [rset] support for delitem on repeat list (may be necessary in pyro source)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6176
diff changeset
   168
    def __delitem__(self, idc):
5adf53edfe12 [rset] support for delitem on repeat list (may be necessary in pyro source)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6176
diff changeset
   169
        assert self._size > 0
5adf53edfe12 [rset] support for delitem on repeat list (may be necessary in pyro source)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6176
diff changeset
   170
        self._size -= 1
5069
135c5d7b89d0 [querier] introduce RepeatList class, used to optimize size of data returned for result set description
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4961
diff changeset
   171
    def __add__(self, other):
135c5d7b89d0 [querier] introduce RepeatList class, used to optimize size of data returned for result set description
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4961
diff changeset
   172
        if isinstance(other, RepeatList):
135c5d7b89d0 [querier] introduce RepeatList class, used to optimize size of data returned for result set description
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4961
diff changeset
   173
            if other._item == self._item:
135c5d7b89d0 [querier] introduce RepeatList class, used to optimize size of data returned for result set description
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4961
diff changeset
   174
                return RepeatList(self._size + other._size, self._item)
135c5d7b89d0 [querier] introduce RepeatList class, used to optimize size of data returned for result set description
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4961
diff changeset
   175
            return ([self._item] * self._size) + other[:]
135c5d7b89d0 [querier] introduce RepeatList class, used to optimize size of data returned for result set description
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4961
diff changeset
   176
        return ([self._item] * self._size) + other
135c5d7b89d0 [querier] introduce RepeatList class, used to optimize size of data returned for result set description
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4961
diff changeset
   177
    def __radd__(self, other):
135c5d7b89d0 [querier] introduce RepeatList class, used to optimize size of data returned for result set description
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4961
diff changeset
   178
        if isinstance(other, RepeatList):
135c5d7b89d0 [querier] introduce RepeatList class, used to optimize size of data returned for result set description
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4961
diff changeset
   179
            if other._item == self._item:
135c5d7b89d0 [querier] introduce RepeatList class, used to optimize size of data returned for result set description
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4961
diff changeset
   180
                return RepeatList(self._size + other._size, self._item)
135c5d7b89d0 [querier] introduce RepeatList class, used to optimize size of data returned for result set description
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4961
diff changeset
   181
            return other[:] + ([self._item] * self._size)
135c5d7b89d0 [querier] introduce RepeatList class, used to optimize size of data returned for result set description
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4961
diff changeset
   182
        return other[:] + ([self._item] * self._size)
135c5d7b89d0 [querier] introduce RepeatList class, used to optimize size of data returned for result set description
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4961
diff changeset
   183
    def __eq__(self, other):
135c5d7b89d0 [querier] introduce RepeatList class, used to optimize size of data returned for result set description
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4961
diff changeset
   184
        if isinstance(other, RepeatList):
6492
47a284c0d012 fix some pylint detected errors
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6448
diff changeset
   185
            return other._size == self._size and other._item == self._item
5069
135c5d7b89d0 [querier] introduce RepeatList class, used to optimize size of data returned for result set description
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4961
diff changeset
   186
        return self[:] == other
10661
e6eb0c7c2e98 implement __ne__ whenever we implement __eq__
Julien Cristau <julien.cristau@logilab.fr>
parents: 10603
diff changeset
   187
    def __ne__(self, other):
e6eb0c7c2e98 implement __ne__ whenever we implement __eq__
Julien Cristau <julien.cristau@logilab.fr>
parents: 10603
diff changeset
   188
        return not (self == other)
e6eb0c7c2e98 implement __ne__ whenever we implement __eq__
Julien Cristau <julien.cristau@logilab.fr>
parents: 10603
diff changeset
   189
    def __hash__(self):
e6eb0c7c2e98 implement __ne__ whenever we implement __eq__
Julien Cristau <julien.cristau@logilab.fr>
parents: 10603
diff changeset
   190
        raise NotImplementedError
5077
dc448c9ad9dd [rset] cubes such as iliane hi-jack rset description by poping some lines from it. Handle this on RepeatList
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5069
diff changeset
   191
    def pop(self, i):
dc448c9ad9dd [rset] cubes such as iliane hi-jack rset description by poping some lines from it. Handle this on RepeatList
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5069
diff changeset
   192
        self._size -= 1
5069
135c5d7b89d0 [querier] introduce RepeatList class, used to optimize size of data returned for result set description
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4961
diff changeset
   193
6684
b8bd0ecced2e minor cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6580
diff changeset
   194
12874
cc71a801b846 [utils] Add the possibility to add elements in the head of an UStringIO list
Guillaume Vandevelde <gvandevelde@logilab.fr>
parents: 12319
diff changeset
   195
def handle_writing_constraints(method):
cc71a801b846 [utils] Add the possibility to add elements in the head of an UStringIO list
Guillaume Vandevelde <gvandevelde@logilab.fr>
parents: 12319
diff changeset
   196
    @wraps(method)
cc71a801b846 [utils] Add the possibility to add elements in the head of an UStringIO list
Guillaume Vandevelde <gvandevelde@logilab.fr>
parents: 12319
diff changeset
   197
    def wrapper(self, value):
cc71a801b846 [utils] Add the possibility to add elements in the head of an UStringIO list
Guillaume Vandevelde <gvandevelde@logilab.fr>
parents: 12319
diff changeset
   198
        assert isinstance(value, text_type), u"unicode required not %s : %s"\
cc71a801b846 [utils] Add the possibility to add elements in the head of an UStringIO list
Guillaume Vandevelde <gvandevelde@logilab.fr>
parents: 12319
diff changeset
   199
            % (type(value).__name__, repr(value))
cc71a801b846 [utils] Add the possibility to add elements in the head of an UStringIO list
Guillaume Vandevelde <gvandevelde@logilab.fr>
parents: 12319
diff changeset
   200
        if self.tracewrites:
cc71a801b846 [utils] Add the possibility to add elements in the head of an UStringIO list
Guillaume Vandevelde <gvandevelde@logilab.fr>
parents: 12319
diff changeset
   201
            from traceback import format_stack
cc71a801b846 [utils] Add the possibility to add elements in the head of an UStringIO list
Guillaume Vandevelde <gvandevelde@logilab.fr>
parents: 12319
diff changeset
   202
            stack = format_stack(None)[:-1]
cc71a801b846 [utils] Add the possibility to add elements in the head of an UStringIO list
Guillaume Vandevelde <gvandevelde@logilab.fr>
parents: 12319
diff changeset
   203
            escaped_stack = xml_escape(json_dumps(u'\n'.join(stack)))
cc71a801b846 [utils] Add the possibility to add elements in the head of an UStringIO list
Guillaume Vandevelde <gvandevelde@logilab.fr>
parents: 12319
diff changeset
   204
            escaped_html = xml_escape(value).replace('\n', '<br/>\n')
cc71a801b846 [utils] Add the possibility to add elements in the head of an UStringIO list
Guillaume Vandevelde <gvandevelde@logilab.fr>
parents: 12319
diff changeset
   205
            tpl = u'<span onclick="alert(%s)">%s</span>'
cc71a801b846 [utils] Add the possibility to add elements in the head of an UStringIO list
Guillaume Vandevelde <gvandevelde@logilab.fr>
parents: 12319
diff changeset
   206
            value = tpl % (escaped_stack, escaped_html)
cc71a801b846 [utils] Add the possibility to add elements in the head of an UStringIO list
Guillaume Vandevelde <gvandevelde@logilab.fr>
parents: 12319
diff changeset
   207
        return method(self, value)
cc71a801b846 [utils] Add the possibility to add elements in the head of an UStringIO list
Guillaume Vandevelde <gvandevelde@logilab.fr>
parents: 12319
diff changeset
   208
    return wrapper
cc71a801b846 [utils] Add the possibility to add elements in the head of an UStringIO list
Guillaume Vandevelde <gvandevelde@logilab.fr>
parents: 12319
diff changeset
   209
cc71a801b846 [utils] Add the possibility to add elements in the head of an UStringIO list
Guillaume Vandevelde <gvandevelde@logilab.fr>
parents: 12319
diff changeset
   210
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   211
class UStringIO(list):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   212
    """a file wrapper which automatically encode unicode string to an encoding
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   213
    specifed in the constructor
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   214
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   215
10090
0aebb1c0f849 [utils] Add a '_cwtracehtml' GET parameter to trace self._cw.w() calls (closes #4601327)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10067
diff changeset
   216
    def __init__(self, tracewrites=False, *args, **kwargs):
0aebb1c0f849 [utils] Add a '_cwtracehtml' GET parameter to trace self._cw.w() calls (closes #4601327)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10067
diff changeset
   217
        self.tracewrites = tracewrites
0aebb1c0f849 [utils] Add a '_cwtracehtml' GET parameter to trace self._cw.w() calls (closes #4601327)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10067
diff changeset
   218
        super(UStringIO, self).__init__(*args, **kwargs)
0aebb1c0f849 [utils] Add a '_cwtracehtml' GET parameter to trace self._cw.w() calls (closes #4601327)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10067
diff changeset
   219
10690
c6290d727c0c [py3k] __nonzero__ → __bool__
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10689
diff changeset
   220
    def __bool__(self):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   221
        return True
1549
f87561822e27 some basic calendar manipulation functions, delete-trailing-whitespace
sylvain.thenault@logilab.fr
parents: 1397
diff changeset
   222
10690
c6290d727c0c [py3k] __nonzero__ → __bool__
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10689
diff changeset
   223
    __nonzero__ = __bool__
c6290d727c0c [py3k] __nonzero__ → __bool__
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10689
diff changeset
   224
12874
cc71a801b846 [utils] Add the possibility to add elements in the head of an UStringIO list
Guillaume Vandevelde <gvandevelde@logilab.fr>
parents: 12319
diff changeset
   225
    @handle_writing_constraints
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   226
    def write(self, value):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   227
        self.append(value)
1549
f87561822e27 some basic calendar manipulation functions, delete-trailing-whitespace
sylvain.thenault@logilab.fr
parents: 1397
diff changeset
   228
12874
cc71a801b846 [utils] Add the possibility to add elements in the head of an UStringIO list
Guillaume Vandevelde <gvandevelde@logilab.fr>
parents: 12319
diff changeset
   229
    @handle_writing_constraints
cc71a801b846 [utils] Add the possibility to add elements in the head of an UStringIO list
Guillaume Vandevelde <gvandevelde@logilab.fr>
parents: 12319
diff changeset
   230
    def write_front(self, value):
cc71a801b846 [utils] Add the possibility to add elements in the head of an UStringIO list
Guillaume Vandevelde <gvandevelde@logilab.fr>
parents: 12319
diff changeset
   231
        self.insert(0, value)
cc71a801b846 [utils] Add the possibility to add elements in the head of an UStringIO list
Guillaume Vandevelde <gvandevelde@logilab.fr>
parents: 12319
diff changeset
   232
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   233
    def getvalue(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   234
        return u''.join(self)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   235
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   236
    def __repr__(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   237
        return '<%s at %#x>' % (self.__class__.__name__, id(self))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   238
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
class HTMLHead(UStringIO):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   241
    """wraps HTML header's stream
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
    Request objects use a HTMLHead instance to ease adding of
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   244
    javascripts and stylesheets
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   245
    """
7267
2fe2ed459e4d [page data] don't call unload_page_data too many time (closes #1518398)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7140
diff changeset
   246
    js_unload_code = u'''if (typeof(pageDataUnloaded) == 'undefined') {
2fe2ed459e4d [page data] don't call unload_page_data too many time (closes #1518398)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7140
diff changeset
   247
    jQuery(window).unload(unloadPageData);
2fe2ed459e4d [page data] don't call unload_page_data too many time (closes #1518398)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7140
diff changeset
   248
    pageDataUnloaded = true;
2fe2ed459e4d [page data] don't call unload_page_data too many time (closes #1518398)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7140
diff changeset
   249
}'''
8941
7b26fe71404f drop xhtml content-type support (closes #2065651)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8795
diff changeset
   250
    script_opening = u'<script type="text/javascript">\n'
7b26fe71404f drop xhtml content-type support (closes #2065651)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8795
diff changeset
   251
    script_closing = u'\n</script>'
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   252
10090
0aebb1c0f849 [utils] Add a '_cwtracehtml' GET parameter to trace self._cw.w() calls (closes #4601327)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10067
diff changeset
   253
    def __init__(self, req, *args, **kwargs):
0aebb1c0f849 [utils] Add a '_cwtracehtml' GET parameter to trace self._cw.w() calls (closes #4601327)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10067
diff changeset
   254
        super(HTMLHead, self).__init__(*args, **kwargs)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   255
        self.jsvars = []
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   256
        self.jsfiles = []
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   257
        self.cssfiles = []
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   258
        self.ie_cssfiles = []
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   259
        self.post_inlined_scripts = []
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   260
        self.pagedata_unload = False
7762
a3f9ba4d44eb [web] add option to make resources-concat optional (implements #1910615)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7660
diff changeset
   261
        self._cw = req
a3f9ba4d44eb [web] add option to make resources-concat optional (implements #1910615)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7660
diff changeset
   262
        self.datadir_url = req.datadir_url
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   263
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   264
    def add_raw(self, rawheader):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   265
        self.write(rawheader)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   266
3838
9cc134372bf8 [web] safety belt to avoid overriding pageid with loadxhtml()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3789
diff changeset
   267
    def define_var(self, var, value, override=True):
9cc134372bf8 [web] safety belt to avoid overriding pageid with loadxhtml()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3789
diff changeset
   268
        """adds a javascript var declaration / assginment in the header
9cc134372bf8 [web] safety belt to avoid overriding pageid with loadxhtml()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3789
diff changeset
   269
9cc134372bf8 [web] safety belt to avoid overriding pageid with loadxhtml()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3789
diff changeset
   270
        :param var: the variable name
9cc134372bf8 [web] safety belt to avoid overriding pageid with loadxhtml()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3789
diff changeset
   271
        :param value: the variable value (as a raw python value,
9cc134372bf8 [web] safety belt to avoid overriding pageid with loadxhtml()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3789
diff changeset
   272
                      it will be jsonized later)
9cc134372bf8 [web] safety belt to avoid overriding pageid with loadxhtml()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3789
diff changeset
   273
        :param override: if False, don't set the variable value if the variable
9cc134372bf8 [web] safety belt to avoid overriding pageid with loadxhtml()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3789
diff changeset
   274
                         is already defined. Default is True.
9cc134372bf8 [web] safety belt to avoid overriding pageid with loadxhtml()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3789
diff changeset
   275
        """
9cc134372bf8 [web] safety belt to avoid overriding pageid with loadxhtml()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3789
diff changeset
   276
        self.jsvars.append( (var, value, override) )
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   277
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   278
    def add_post_inline_script(self, content):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   279
        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
   280
8795
772cd62e1295 [utils] drop pre-3.7 compat in util
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8682
diff changeset
   281
    def add_onload(self, jscode):
6448
8590d82e9b1b [javascript] update to jQuery 1.4.2 and jQuery-ui 1.8.5
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6409
diff changeset
   282
        self.add_post_inline_script(u"""$(cw).one('server-response', function(event) {
4903
627fcd90e08f fix bad conflict resolution
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4899
diff changeset
   283
%s});""" % jscode)
1549
f87561822e27 some basic calendar manipulation functions, delete-trailing-whitespace
sylvain.thenault@logilab.fr
parents: 1397
diff changeset
   284
f87561822e27 some basic calendar manipulation functions, delete-trailing-whitespace
sylvain.thenault@logilab.fr
parents: 1397
diff changeset
   285
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   286
    def add_js(self, jsfile):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   287
        """adds `jsfile` to the list of javascripts used in the webpage
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   288
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   289
        This function checks if the file has already been added
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   290
        :param jsfile: the script's URL
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   291
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   292
        if jsfile not in self.jsfiles:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   293
            self.jsfiles.append(jsfile)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   294
7277
acd7f0e9f276 [etwist] Generates apache's mod_concat-like urls for js and css
Quentin Roquefort <roquefort.quentin@gmail.com>
parents: 7187
diff changeset
   295
    def add_css(self, cssfile, media='all'):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   296
        """adds `cssfile` to the list of javascripts used in the webpage
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   297
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   298
        This function checks if the file has already been added
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   299
        :param cssfile: the stylesheet's URL
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
        if (cssfile, media) not in self.cssfiles:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   302
            self.cssfiles.append( (cssfile, media) )
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   303
4860
cedb6afdb7da [web] fix #736332: iespec functionality for add_css
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4859
diff changeset
   304
    def add_ie_css(self, cssfile, media='all', iespec=u'[if lt IE 8]'):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   305
        """registers some IE specific CSS"""
4860
cedb6afdb7da [web] fix #736332: iespec functionality for add_css
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4859
diff changeset
   306
        if (cssfile, media, iespec) not in self.ie_cssfiles:
cedb6afdb7da [web] fix #736332: iespec functionality for add_css
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4859
diff changeset
   307
            self.ie_cssfiles.append( (cssfile, media, iespec) )
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   308
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   309
    def add_unload_pagedata(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   310
        """registers onunload callback to clean page data on server"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   311
        if not self.pagedata_unload:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   312
            self.post_inlined_scripts.append(self.js_unload_code)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   313
            self.pagedata_unload = True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   314
7277
acd7f0e9f276 [etwist] Generates apache's mod_concat-like urls for js and css
Quentin Roquefort <roquefort.quentin@gmail.com>
parents: 7187
diff changeset
   315
    def concat_urls(self, urls):
acd7f0e9f276 [etwist] Generates apache's mod_concat-like urls for js and css
Quentin Roquefort <roquefort.quentin@gmail.com>
parents: 7187
diff changeset
   316
        """concatenates urls into one url usable by Apache mod_concat
acd7f0e9f276 [etwist] Generates apache's mod_concat-like urls for js and css
Quentin Roquefort <roquefort.quentin@gmail.com>
parents: 7187
diff changeset
   317
acd7f0e9f276 [etwist] Generates apache's mod_concat-like urls for js and css
Quentin Roquefort <roquefort.quentin@gmail.com>
parents: 7187
diff changeset
   318
        This method returns the url without modifying it if there is only
acd7f0e9f276 [etwist] Generates apache's mod_concat-like urls for js and css
Quentin Roquefort <roquefort.quentin@gmail.com>
parents: 7187
diff changeset
   319
        one element in the list
acd7f0e9f276 [etwist] Generates apache's mod_concat-like urls for js and css
Quentin Roquefort <roquefort.quentin@gmail.com>
parents: 7187
diff changeset
   320
        :param urls: list of local urls/filenames to concatenate
acd7f0e9f276 [etwist] Generates apache's mod_concat-like urls for js and css
Quentin Roquefort <roquefort.quentin@gmail.com>
parents: 7187
diff changeset
   321
        """
acd7f0e9f276 [etwist] Generates apache's mod_concat-like urls for js and css
Quentin Roquefort <roquefort.quentin@gmail.com>
parents: 7187
diff changeset
   322
        if len(urls) == 1:
acd7f0e9f276 [etwist] Generates apache's mod_concat-like urls for js and css
Quentin Roquefort <roquefort.quentin@gmail.com>
parents: 7187
diff changeset
   323
            return urls[0]
acd7f0e9f276 [etwist] Generates apache's mod_concat-like urls for js and css
Quentin Roquefort <roquefort.quentin@gmail.com>
parents: 7187
diff changeset
   324
        len_prefix = len(self.datadir_url)
acd7f0e9f276 [etwist] Generates apache's mod_concat-like urls for js and css
Quentin Roquefort <roquefort.quentin@gmail.com>
parents: 7187
diff changeset
   325
        concated = u','.join(url[len_prefix:] for url in urls)
acd7f0e9f276 [etwist] Generates apache's mod_concat-like urls for js and css
Quentin Roquefort <roquefort.quentin@gmail.com>
parents: 7187
diff changeset
   326
        return (u'%s??%s' % (self.datadir_url, concated))
acd7f0e9f276 [etwist] Generates apache's mod_concat-like urls for js and css
Quentin Roquefort <roquefort.quentin@gmail.com>
parents: 7187
diff changeset
   327
acd7f0e9f276 [etwist] Generates apache's mod_concat-like urls for js and css
Quentin Roquefort <roquefort.quentin@gmail.com>
parents: 7187
diff changeset
   328
    def group_urls(self, urls_spec):
acd7f0e9f276 [etwist] Generates apache's mod_concat-like urls for js and css
Quentin Roquefort <roquefort.quentin@gmail.com>
parents: 7187
diff changeset
   329
        """parses urls_spec in order to generate concatenated urls
acd7f0e9f276 [etwist] Generates apache's mod_concat-like urls for js and css
Quentin Roquefort <roquefort.quentin@gmail.com>
parents: 7187
diff changeset
   330
        for js and css includes
acd7f0e9f276 [etwist] Generates apache's mod_concat-like urls for js and css
Quentin Roquefort <roquefort.quentin@gmail.com>
parents: 7187
diff changeset
   331
acd7f0e9f276 [etwist] Generates apache's mod_concat-like urls for js and css
Quentin Roquefort <roquefort.quentin@gmail.com>
parents: 7187
diff changeset
   332
        This method checks if the file is local and if it shares options
acd7f0e9f276 [etwist] Generates apache's mod_concat-like urls for js and css
Quentin Roquefort <roquefort.quentin@gmail.com>
parents: 7187
diff changeset
   333
        with direct neighbors
acd7f0e9f276 [etwist] Generates apache's mod_concat-like urls for js and css
Quentin Roquefort <roquefort.quentin@gmail.com>
parents: 7187
diff changeset
   334
        :param urls_spec: entire list of urls/filenames to inspect
acd7f0e9f276 [etwist] Generates apache's mod_concat-like urls for js and css
Quentin Roquefort <roquefort.quentin@gmail.com>
parents: 7187
diff changeset
   335
        """
acd7f0e9f276 [etwist] Generates apache's mod_concat-like urls for js and css
Quentin Roquefort <roquefort.quentin@gmail.com>
parents: 7187
diff changeset
   336
        concatable = []
acd7f0e9f276 [etwist] Generates apache's mod_concat-like urls for js and css
Quentin Roquefort <roquefort.quentin@gmail.com>
parents: 7187
diff changeset
   337
        prev_islocal = False
acd7f0e9f276 [etwist] Generates apache's mod_concat-like urls for js and css
Quentin Roquefort <roquefort.quentin@gmail.com>
parents: 7187
diff changeset
   338
        prev_key = None
acd7f0e9f276 [etwist] Generates apache's mod_concat-like urls for js and css
Quentin Roquefort <roquefort.quentin@gmail.com>
parents: 7187
diff changeset
   339
        for url, key in urls_spec:
acd7f0e9f276 [etwist] Generates apache's mod_concat-like urls for js and css
Quentin Roquefort <roquefort.quentin@gmail.com>
parents: 7187
diff changeset
   340
            islocal = url.startswith(self.datadir_url)
acd7f0e9f276 [etwist] Generates apache's mod_concat-like urls for js and css
Quentin Roquefort <roquefort.quentin@gmail.com>
parents: 7187
diff changeset
   341
            if concatable and (islocal != prev_islocal or key != prev_key):
acd7f0e9f276 [etwist] Generates apache's mod_concat-like urls for js and css
Quentin Roquefort <roquefort.quentin@gmail.com>
parents: 7187
diff changeset
   342
                yield (self.concat_urls(concatable), prev_key)
acd7f0e9f276 [etwist] Generates apache's mod_concat-like urls for js and css
Quentin Roquefort <roquefort.quentin@gmail.com>
parents: 7187
diff changeset
   343
                del concatable[:]
acd7f0e9f276 [etwist] Generates apache's mod_concat-like urls for js and css
Quentin Roquefort <roquefort.quentin@gmail.com>
parents: 7187
diff changeset
   344
            if not islocal:
acd7f0e9f276 [etwist] Generates apache's mod_concat-like urls for js and css
Quentin Roquefort <roquefort.quentin@gmail.com>
parents: 7187
diff changeset
   345
                yield (url, key)
acd7f0e9f276 [etwist] Generates apache's mod_concat-like urls for js and css
Quentin Roquefort <roquefort.quentin@gmail.com>
parents: 7187
diff changeset
   346
            else:
acd7f0e9f276 [etwist] Generates apache's mod_concat-like urls for js and css
Quentin Roquefort <roquefort.quentin@gmail.com>
parents: 7187
diff changeset
   347
                concatable.append(url)
acd7f0e9f276 [etwist] Generates apache's mod_concat-like urls for js and css
Quentin Roquefort <roquefort.quentin@gmail.com>
parents: 7187
diff changeset
   348
            prev_islocal = islocal
acd7f0e9f276 [etwist] Generates apache's mod_concat-like urls for js and css
Quentin Roquefort <roquefort.quentin@gmail.com>
parents: 7187
diff changeset
   349
            prev_key = key
acd7f0e9f276 [etwist] Generates apache's mod_concat-like urls for js and css
Quentin Roquefort <roquefort.quentin@gmail.com>
parents: 7187
diff changeset
   350
        if concatable:
acd7f0e9f276 [etwist] Generates apache's mod_concat-like urls for js and css
Quentin Roquefort <roquefort.quentin@gmail.com>
parents: 7187
diff changeset
   351
            yield (self.concat_urls(concatable), prev_key)
acd7f0e9f276 [etwist] Generates apache's mod_concat-like urls for js and css
Quentin Roquefort <roquefort.quentin@gmail.com>
parents: 7187
diff changeset
   352
acd7f0e9f276 [etwist] Generates apache's mod_concat-like urls for js and css
Quentin Roquefort <roquefort.quentin@gmail.com>
parents: 7187
diff changeset
   353
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
   354
    def getvalue(self, skiphead=False):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   355
        """reimplement getvalue to provide a consistent (and somewhat browser
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   356
        optimzed cf. http://stevesouders.com/cuzillion) order in external
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   357
        resources declaration
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   358
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   359
        w = self.write
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   360
        # 1/ variable declaration if any
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   361
        if self.jsvars:
10166
0095961df66c [utils] Fix define_var in ajax context (closes #4881301)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10118
diff changeset
   362
            if skiphead:
0095961df66c [utils] Fix define_var in ajax context (closes #4881301)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10118
diff changeset
   363
                w(u'<cubicweb:script>')
0095961df66c [utils] Fix define_var in ajax context (closes #4881301)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10118
diff changeset
   364
            else:
0095961df66c [utils] Fix define_var in ajax context (closes #4881301)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10118
diff changeset
   365
                w(self.script_opening)
3838
9cc134372bf8 [web] safety belt to avoid overriding pageid with loadxhtml()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3789
diff changeset
   366
            for var, value, override in self.jsvars:
5389
809d3b5b3d31 [python2.6] careful: json-py provides a json package. We don't want that.
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 5377
diff changeset
   367
                vardecl = u'%s = %s;' % (var, json.dumps(value))
3838
9cc134372bf8 [web] safety belt to avoid overriding pageid with loadxhtml()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3789
diff changeset
   368
                if not override:
9cc134372bf8 [web] safety belt to avoid overriding pageid with loadxhtml()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3789
diff changeset
   369
                    vardecl = (u'if (typeof %s == "undefined") {%s}' %
9cc134372bf8 [web] safety belt to avoid overriding pageid with loadxhtml()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3789
diff changeset
   370
                               (var, vardecl))
9cc134372bf8 [web] safety belt to avoid overriding pageid with loadxhtml()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3789
diff changeset
   371
                w(vardecl + u'\n')
10166
0095961df66c [utils] Fix define_var in ajax context (closes #4881301)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10118
diff changeset
   372
            if skiphead:
0095961df66c [utils] Fix define_var in ajax context (closes #4881301)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10118
diff changeset
   373
                w(u'</cubicweb:script>')
0095961df66c [utils] Fix define_var in ajax context (closes #4881301)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10118
diff changeset
   374
            else:
0095961df66c [utils] Fix define_var in ajax context (closes #4881301)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10118
diff changeset
   375
                w(self.script_closing)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   376
        # 2/ css files
7762
a3f9ba4d44eb [web] add option to make resources-concat optional (implements #1910615)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7660
diff changeset
   377
        ie_cssfiles = ((x, (y, z)) for x, y, z in self.ie_cssfiles)
a3f9ba4d44eb [web] add option to make resources-concat optional (implements #1910615)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7660
diff changeset
   378
        if self.datadir_url and self._cw.vreg.config['concat-resources']:
a3f9ba4d44eb [web] add option to make resources-concat optional (implements #1910615)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7660
diff changeset
   379
            cssfiles = self.group_urls(self.cssfiles)
a3f9ba4d44eb [web] add option to make resources-concat optional (implements #1910615)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7660
diff changeset
   380
            ie_cssfiles = self.group_urls(ie_cssfiles)
a3f9ba4d44eb [web] add option to make resources-concat optional (implements #1910615)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7660
diff changeset
   381
            jsfiles = (x for x, _ in self.group_urls((x, None) for x in self.jsfiles))
a3f9ba4d44eb [web] add option to make resources-concat optional (implements #1910615)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7660
diff changeset
   382
        else:
a3f9ba4d44eb [web] add option to make resources-concat optional (implements #1910615)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7660
diff changeset
   383
            cssfiles = self.cssfiles
a3f9ba4d44eb [web] add option to make resources-concat optional (implements #1910615)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7660
diff changeset
   384
            jsfiles = self.jsfiles
a3f9ba4d44eb [web] add option to make resources-concat optional (implements #1910615)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7660
diff changeset
   385
        for cssfile, media in cssfiles:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   386
            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
   387
              (media, xml_escape(cssfile)))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   388
        # 3/ ie css if necessary
7762
a3f9ba4d44eb [web] add option to make resources-concat optional (implements #1910615)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7660
diff changeset
   389
        if self.ie_cssfiles: # use self.ie_cssfiles because `ie_cssfiles` is a genexp
a3f9ba4d44eb [web] add option to make resources-concat optional (implements #1910615)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7660
diff changeset
   390
            for cssfile, (media, iespec) in ie_cssfiles:
4860
cedb6afdb7da [web] fix #736332: iespec functionality for add_css
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4859
diff changeset
   391
                w(u'<!--%s>\n' % iespec)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   392
                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
   393
                  (media, xml_escape(cssfile)))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   394
            w(u'<![endif]--> \n')
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   395
        # 4/ js files
7762
a3f9ba4d44eb [web] add option to make resources-concat optional (implements #1910615)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7660
diff changeset
   396
        for jsfile in jsfiles:
7649
ede740bd7077 [ajax, IE] rewrite some code to avoid duplicated evaluation with IE
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7575
diff changeset
   397
            if skiphead:
ede740bd7077 [ajax, IE] rewrite some code to avoid duplicated evaluation with IE
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7575
diff changeset
   398
                # Don't insert <script> tags directly as they would be
ede740bd7077 [ajax, IE] rewrite some code to avoid duplicated evaluation with IE
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7575
diff changeset
   399
                # interpreted directly by some browsers (e.g. IE).
9523
cd5738fc440f [ajax] use a custom tag to handle dynamically loaded js
Julien Cristau <julien.cristau@logilab.fr>
parents: 9279
diff changeset
   400
                # Use <cubicweb:script> tags instead and let
7649
ede740bd7077 [ajax, IE] rewrite some code to avoid duplicated evaluation with IE
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7575
diff changeset
   401
                # `loadAjaxHtmlHead` handle the script insertion / execution.
9523
cd5738fc440f [ajax] use a custom tag to handle dynamically loaded js
Julien Cristau <julien.cristau@logilab.fr>
parents: 9279
diff changeset
   402
                w(u'<cubicweb:script src="%s"></cubicweb:script>\n' %
7649
ede740bd7077 [ajax, IE] rewrite some code to avoid duplicated evaluation with IE
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7575
diff changeset
   403
                  xml_escape(jsfile))
ede740bd7077 [ajax, IE] rewrite some code to avoid duplicated evaluation with IE
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7575
diff changeset
   404
                # FIXME: a probably better implementation might be to add
ede740bd7077 [ajax, IE] rewrite some code to avoid duplicated evaluation with IE
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7575
diff changeset
   405
                #        JS or CSS urls in a JS list that loadAjaxHtmlHead
ede740bd7077 [ajax, IE] rewrite some code to avoid duplicated evaluation with IE
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7575
diff changeset
   406
                #        would iterate on and postprocess:
ede740bd7077 [ajax, IE] rewrite some code to avoid duplicated evaluation with IE
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7575
diff changeset
   407
                #            cw._ajax_js_scripts.push('myscript.js')
ede740bd7077 [ajax, IE] rewrite some code to avoid duplicated evaluation with IE
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7575
diff changeset
   408
                #        Then, in loadAjaxHtmlHead, do something like:
ede740bd7077 [ajax, IE] rewrite some code to avoid duplicated evaluation with IE
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7575
diff changeset
   409
                #            jQuery.each(cw._ajax_js_script, jQuery.getScript)
ede740bd7077 [ajax, IE] rewrite some code to avoid duplicated evaluation with IE
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7575
diff changeset
   410
            else:
ede740bd7077 [ajax, IE] rewrite some code to avoid duplicated evaluation with IE
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7575
diff changeset
   411
                w(u'<script type="text/javascript" src="%s"></script>\n' %
ede740bd7077 [ajax, IE] rewrite some code to avoid duplicated evaluation with IE
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7575
diff changeset
   412
                  xml_escape(jsfile))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   413
        # 5/ post inlined scripts (i.e. scripts depending on other JS files)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   414
        if self.post_inlined_scripts:
7649
ede740bd7077 [ajax, IE] rewrite some code to avoid duplicated evaluation with IE
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7575
diff changeset
   415
            if skiphead:
ede740bd7077 [ajax, IE] rewrite some code to avoid duplicated evaluation with IE
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7575
diff changeset
   416
                for script in self.post_inlined_scripts:
9523
cd5738fc440f [ajax] use a custom tag to handle dynamically loaded js
Julien Cristau <julien.cristau@logilab.fr>
parents: 9279
diff changeset
   417
                    w(u'<cubicweb:script>')
7660
a1506b5306cc closes #1826543: error on some ajax_replace_url call
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7649
diff changeset
   418
                    w(xml_escape(script))
9523
cd5738fc440f [ajax] use a custom tag to handle dynamically loaded js
Julien Cristau <julien.cristau@logilab.fr>
parents: 9279
diff changeset
   419
                    w(u'</cubicweb:script>')
7649
ede740bd7077 [ajax, IE] rewrite some code to avoid duplicated evaluation with IE
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7575
diff changeset
   420
            else:
8941
7b26fe71404f drop xhtml content-type support (closes #2065651)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8795
diff changeset
   421
                w(self.script_opening)
7649
ede740bd7077 [ajax, IE] rewrite some code to avoid duplicated evaluation with IE
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7575
diff changeset
   422
                w(u'\n\n'.join(self.post_inlined_scripts))
8941
7b26fe71404f drop xhtml content-type support (closes #2065651)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8795
diff changeset
   423
                w(self.script_closing)
10090
0aebb1c0f849 [utils] Add a '_cwtracehtml' GET parameter to trace self._cw.w() calls (closes #4601327)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10067
diff changeset
   424
        # at the start of this function, the parent UStringIO may already have
0aebb1c0f849 [utils] Add a '_cwtracehtml' GET parameter to trace self._cw.w() calls (closes #4601327)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10067
diff changeset
   425
        # data in it, so we can't w(u'<head>\n') at the top. Instead, we create
0aebb1c0f849 [utils] Add a '_cwtracehtml' GET parameter to trace self._cw.w() calls (closes #4601327)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10067
diff changeset
   426
        # a temporary UStringIO to get the same debugging output formatting
0aebb1c0f849 [utils] Add a '_cwtracehtml' GET parameter to trace self._cw.w() calls (closes #4601327)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10067
diff changeset
   427
        # if debugging is enabled.
0aebb1c0f849 [utils] Add a '_cwtracehtml' GET parameter to trace self._cw.w() calls (closes #4601327)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10067
diff changeset
   428
        headtag = UStringIO(tracewrites=self.tracewrites)
0aebb1c0f849 [utils] Add a '_cwtracehtml' GET parameter to trace self._cw.w() calls (closes #4601327)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10067
diff changeset
   429
        if not skiphead:
0aebb1c0f849 [utils] Add a '_cwtracehtml' GET parameter to trace self._cw.w() calls (closes #4601327)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10067
diff changeset
   430
            headtag.write(u'<head>\n')
0aebb1c0f849 [utils] Add a '_cwtracehtml' GET parameter to trace self._cw.w() calls (closes #4601327)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10067
diff changeset
   431
            w(u'</head>\n')
0aebb1c0f849 [utils] Add a '_cwtracehtml' GET parameter to trace self._cw.w() calls (closes #4601327)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10067
diff changeset
   432
        return headtag.getvalue() + super(HTMLHead, self).getvalue()
1549
f87561822e27 some basic calendar manipulation functions, delete-trailing-whitespace
sylvain.thenault@logilab.fr
parents: 1397
diff changeset
   433
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   434
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   435
class HTMLStream(object):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   436
    """represents a HTML page.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   437
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   438
    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
   439
    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
   440
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   441
    HTMLStream uses the (U)StringIO interface to be compliant with
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   442
    existing code.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   443
    """
1549
f87561822e27 some basic calendar manipulation functions, delete-trailing-whitespace
sylvain.thenault@logilab.fr
parents: 1397
diff changeset
   444
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   445
    def __init__(self, req):
10090
0aebb1c0f849 [utils] Add a '_cwtracehtml' GET parameter to trace self._cw.w() calls (closes #4601327)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10067
diff changeset
   446
        self.tracehtml = req.tracehtml
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   447
        # stream for <head>
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   448
        self.head = req.html_headers
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   449
        # main stream
10090
0aebb1c0f849 [utils] Add a '_cwtracehtml' GET parameter to trace self._cw.w() calls (closes #4601327)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10067
diff changeset
   450
        self.body = UStringIO(tracewrites=req.tracehtml)
10004
acad42456767 [utils] Remove function-in-the-middle call
Rémi Cardona <remi.cardona@logilab.fr>
parents: 9780
diff changeset
   451
        # this method will be assigned to self.w in views
acad42456767 [utils] Remove function-in-the-middle call
Rémi Cardona <remi.cardona@logilab.fr>
parents: 9780
diff changeset
   452
        self.write = self.body.write
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   453
        self.doctype = u''
8941
7b26fe71404f drop xhtml content-type support (closes #2065651)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8795
diff changeset
   454
        self._htmlattrs = [('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
   455
        # 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
   456
        req.main_stream = self
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   457
8941
7b26fe71404f drop xhtml content-type support (closes #2065651)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8795
diff changeset
   458
    @deprecated('[3.17] there are no namespaces in html, xhtml is not served any longer')
7187
496f51b92154 [views] extend HTMLStream API to be able to change doctype / xmldecl
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7140
diff changeset
   459
    def add_namespace(self, prefix, uri):
8941
7b26fe71404f drop xhtml content-type support (closes #2065651)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8795
diff changeset
   460
        pass
7187
496f51b92154 [views] extend HTMLStream API to be able to change doctype / xmldecl
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7140
diff changeset
   461
8941
7b26fe71404f drop xhtml content-type support (closes #2065651)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8795
diff changeset
   462
    @deprecated('[3.17] there are no namespaces in html, xhtml is not served any longer')
7187
496f51b92154 [views] extend HTMLStream API to be able to change doctype / xmldecl
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7140
diff changeset
   463
    def set_namespaces(self, namespaces):
8941
7b26fe71404f drop xhtml content-type support (closes #2065651)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8795
diff changeset
   464
        pass
7187
496f51b92154 [views] extend HTMLStream API to be able to change doctype / xmldecl
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7140
diff changeset
   465
496f51b92154 [views] extend HTMLStream API to be able to change doctype / xmldecl
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7140
diff changeset
   466
    def add_htmlattr(self, attrname, attrvalue):
496f51b92154 [views] extend HTMLStream API to be able to change doctype / xmldecl
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7140
diff changeset
   467
        self._htmlattrs.append( (attrname, attrvalue) )
496f51b92154 [views] extend HTMLStream API to be able to change doctype / xmldecl
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7140
diff changeset
   468
496f51b92154 [views] extend HTMLStream API to be able to change doctype / xmldecl
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7140
diff changeset
   469
    def set_htmlattrs(self, attrs):
496f51b92154 [views] extend HTMLStream API to be able to change doctype / xmldecl
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7140
diff changeset
   470
        self._htmlattrs = attrs
496f51b92154 [views] extend HTMLStream API to be able to change doctype / xmldecl
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7140
diff changeset
   471
8941
7b26fe71404f drop xhtml content-type support (closes #2065651)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8795
diff changeset
   472
    def set_doctype(self, doctype, reset_xmldecl=None):
7187
496f51b92154 [views] extend HTMLStream API to be able to change doctype / xmldecl
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7140
diff changeset
   473
        self.doctype = doctype
8941
7b26fe71404f drop xhtml content-type support (closes #2065651)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8795
diff changeset
   474
        if reset_xmldecl is not None:
7b26fe71404f drop xhtml content-type support (closes #2065651)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8795
diff changeset
   475
            warn('[3.17] xhtml is no more supported',
7b26fe71404f drop xhtml content-type support (closes #2065651)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8795
diff changeset
   476
                 DeprecationWarning, stacklevel=2)
7187
496f51b92154 [views] extend HTMLStream API to be able to change doctype / xmldecl
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7140
diff changeset
   477
496f51b92154 [views] extend HTMLStream API to be able to change doctype / xmldecl
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7140
diff changeset
   478
    @property
496f51b92154 [views] extend HTMLStream API to be able to change doctype / xmldecl
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7140
diff changeset
   479
    def htmltag(self):
496f51b92154 [views] extend HTMLStream API to be able to change doctype / xmldecl
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7140
diff changeset
   480
        attrs = ' '.join('%s="%s"' % (attr, xml_escape(value))
8941
7b26fe71404f drop xhtml content-type support (closes #2065651)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8795
diff changeset
   481
                         for attr, value in self._htmlattrs)
7187
496f51b92154 [views] extend HTMLStream API to be able to change doctype / xmldecl
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7140
diff changeset
   482
        if attrs:
9523
cd5738fc440f [ajax] use a custom tag to handle dynamically loaded js
Julien Cristau <julien.cristau@logilab.fr>
parents: 9279
diff changeset
   483
            return '<html xmlns:cubicweb="http://www.cubicweb.org" %s>' % attrs
cd5738fc440f [ajax] use a custom tag to handle dynamically loaded js
Julien Cristau <julien.cristau@logilab.fr>
parents: 9279
diff changeset
   484
        return '<html xmlns:cubicweb="http://www.cubicweb.org">'
7187
496f51b92154 [views] extend HTMLStream API to be able to change doctype / xmldecl
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7140
diff changeset
   485
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   486
    def getvalue(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   487
        """writes HTML headers, closes </head> tag and writes HTML body"""
10090
0aebb1c0f849 [utils] Add a '_cwtracehtml' GET parameter to trace self._cw.w() calls (closes #4601327)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10067
diff changeset
   488
        if self.tracehtml:
0aebb1c0f849 [utils] Add a '_cwtracehtml' GET parameter to trace self._cw.w() calls (closes #4601327)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10067
diff changeset
   489
            css = u'\n'.join((u'span {',
0aebb1c0f849 [utils] Add a '_cwtracehtml' GET parameter to trace self._cw.w() calls (closes #4601327)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10067
diff changeset
   490
                              u'  font-family: monospace;',
0aebb1c0f849 [utils] Add a '_cwtracehtml' GET parameter to trace self._cw.w() calls (closes #4601327)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10067
diff changeset
   491
                              u'  word-break: break-all;',
0aebb1c0f849 [utils] Add a '_cwtracehtml' GET parameter to trace self._cw.w() calls (closes #4601327)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10067
diff changeset
   492
                              u'  word-wrap: break-word;',
0aebb1c0f849 [utils] Add a '_cwtracehtml' GET parameter to trace self._cw.w() calls (closes #4601327)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10067
diff changeset
   493
                              u'}',
0aebb1c0f849 [utils] Add a '_cwtracehtml' GET parameter to trace self._cw.w() calls (closes #4601327)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10067
diff changeset
   494
                              u'span:hover {',
0aebb1c0f849 [utils] Add a '_cwtracehtml' GET parameter to trace self._cw.w() calls (closes #4601327)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10067
diff changeset
   495
                              u'  color: red;',
0aebb1c0f849 [utils] Add a '_cwtracehtml' GET parameter to trace self._cw.w() calls (closes #4601327)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10067
diff changeset
   496
                              u'  text-decoration: underline;',
0aebb1c0f849 [utils] Add a '_cwtracehtml' GET parameter to trace self._cw.w() calls (closes #4601327)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10067
diff changeset
   497
                              u'}'))
0aebb1c0f849 [utils] Add a '_cwtracehtml' GET parameter to trace self._cw.w() calls (closes #4601327)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10067
diff changeset
   498
            style = u'<style type="text/css">\n%s\n</style>\n' % css
0aebb1c0f849 [utils] Add a '_cwtracehtml' GET parameter to trace self._cw.w() calls (closes #4601327)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10067
diff changeset
   499
            return (u'<!DOCTYPE html>\n'
0aebb1c0f849 [utils] Add a '_cwtracehtml' GET parameter to trace self._cw.w() calls (closes #4601327)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10067
diff changeset
   500
                    + u'<html>\n<head>\n%s\n</head>\n' % style
0aebb1c0f849 [utils] Add a '_cwtracehtml' GET parameter to trace self._cw.w() calls (closes #4601327)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10067
diff changeset
   501
                    + u'<body>\n'
0aebb1c0f849 [utils] Add a '_cwtracehtml' GET parameter to trace self._cw.w() calls (closes #4601327)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10067
diff changeset
   502
                    + u'<span>' + xml_escape(self.doctype) + u'</span><br/>'
0aebb1c0f849 [utils] Add a '_cwtracehtml' GET parameter to trace self._cw.w() calls (closes #4601327)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10067
diff changeset
   503
                    + u'<span>' + xml_escape(self.htmltag) + u'</span><br/>'
0aebb1c0f849 [utils] Add a '_cwtracehtml' GET parameter to trace self._cw.w() calls (closes #4601327)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10067
diff changeset
   504
                    + self.head.getvalue()
0aebb1c0f849 [utils] Add a '_cwtracehtml' GET parameter to trace self._cw.w() calls (closes #4601327)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10067
diff changeset
   505
                    + self.body.getvalue()
0aebb1c0f849 [utils] Add a '_cwtracehtml' GET parameter to trace self._cw.w() calls (closes #4601327)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10067
diff changeset
   506
                    + u'<span>' + xml_escape(u'</html>') + u'</span>'
0aebb1c0f849 [utils] Add a '_cwtracehtml' GET parameter to trace self._cw.w() calls (closes #4601327)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10067
diff changeset
   507
                    + u'</body>\n</html>')
8941
7b26fe71404f drop xhtml content-type support (closes #2065651)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8795
diff changeset
   508
        return u'%s\n%s\n%s\n%s\n</html>' % (self.doctype,
7b26fe71404f drop xhtml content-type support (closes #2065651)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8795
diff changeset
   509
                                             self.htmltag,
7b26fe71404f drop xhtml content-type support (closes #2065651)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8795
diff changeset
   510
                                             self.head.getvalue(),
7b26fe71404f drop xhtml content-type support (closes #2065651)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8795
diff changeset
   511
                                             self.body.getvalue())
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   512
5940
0e3ae19b181a [uilib] refactor json_dumps code organization
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5883
diff changeset
   513
9579
d5b0e1f4c5c5 [utils] the json module is always available
Julien Cristau <julien.cristau@logilab.fr>
parents: 9523
diff changeset
   514
class CubicWebJsonEncoder(json.JSONEncoder):
d5b0e1f4c5c5 [utils] the json module is always available
Julien Cristau <julien.cristau@logilab.fr>
parents: 9523
diff changeset
   515
    """define a json encoder to be able to encode yams std types"""
5320
848e92bb81cc [json] provide a custom json encoder for entities that includes eid in the json object
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 5077
diff changeset
   516
9579
d5b0e1f4c5c5 [utils] the json module is always available
Julien Cristau <julien.cristau@logilab.fr>
parents: 9523
diff changeset
   517
    def default(self, obj):
d5b0e1f4c5c5 [utils] the json module is always available
Julien Cristau <julien.cristau@logilab.fr>
parents: 9523
diff changeset
   518
        if hasattr(obj, '__json_encode__'):
d5b0e1f4c5c5 [utils] the json module is always available
Julien Cristau <julien.cristau@logilab.fr>
parents: 9523
diff changeset
   519
            return obj.__json_encode__()
d5b0e1f4c5c5 [utils] the json module is always available
Julien Cristau <julien.cristau@logilab.fr>
parents: 9523
diff changeset
   520
        if isinstance(obj, datetime.datetime):
d5b0e1f4c5c5 [utils] the json module is always available
Julien Cristau <julien.cristau@logilab.fr>
parents: 9523
diff changeset
   521
            return ustrftime(obj, '%Y/%m/%d %H:%M:%S')
d5b0e1f4c5c5 [utils] the json module is always available
Julien Cristau <julien.cristau@logilab.fr>
parents: 9523
diff changeset
   522
        elif isinstance(obj, datetime.date):
d5b0e1f4c5c5 [utils] the json module is always available
Julien Cristau <julien.cristau@logilab.fr>
parents: 9523
diff changeset
   523
            return ustrftime(obj, '%Y/%m/%d')
d5b0e1f4c5c5 [utils] the json module is always available
Julien Cristau <julien.cristau@logilab.fr>
parents: 9523
diff changeset
   524
        elif isinstance(obj, datetime.time):
d5b0e1f4c5c5 [utils] the json module is always available
Julien Cristau <julien.cristau@logilab.fr>
parents: 9523
diff changeset
   525
            return obj.strftime('%H:%M:%S')
d5b0e1f4c5c5 [utils] the json module is always available
Julien Cristau <julien.cristau@logilab.fr>
parents: 9523
diff changeset
   526
        elif isinstance(obj, datetime.timedelta):
d5b0e1f4c5c5 [utils] the json module is always available
Julien Cristau <julien.cristau@logilab.fr>
parents: 9523
diff changeset
   527
            return (obj.days * 24 * 60 * 60) + obj.seconds
d5b0e1f4c5c5 [utils] the json module is always available
Julien Cristau <julien.cristau@logilab.fr>
parents: 9523
diff changeset
   528
        elif isinstance(obj, decimal.Decimal):
d5b0e1f4c5c5 [utils] the json module is always available
Julien Cristau <julien.cristau@logilab.fr>
parents: 9523
diff changeset
   529
            return float(obj)
11715
760d5c0ae08f [utils] Encode Binary value in base64 for JSON export
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11057
diff changeset
   530
        elif isinstance(obj, Binary):
760d5c0ae08f [utils] Encode Binary value in base64 for JSON export
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11057
diff changeset
   531
            return base64.b64encode(obj.getvalue()).decode('ascii')
9579
d5b0e1f4c5c5 [utils] the json module is always available
Julien Cristau <julien.cristau@logilab.fr>
parents: 9523
diff changeset
   532
        try:
d5b0e1f4c5c5 [utils] the json module is always available
Julien Cristau <julien.cristau@logilab.fr>
parents: 9523
diff changeset
   533
            return json.JSONEncoder.default(self, obj)
d5b0e1f4c5c5 [utils] the json module is always available
Julien Cristau <julien.cristau@logilab.fr>
parents: 9523
diff changeset
   534
        except TypeError:
d5b0e1f4c5c5 [utils] the json module is always available
Julien Cristau <julien.cristau@logilab.fr>
parents: 9523
diff changeset
   535
            # we never ever want to fail because of an unknown type,
d5b0e1f4c5c5 [utils] the json module is always available
Julien Cristau <julien.cristau@logilab.fr>
parents: 9523
diff changeset
   536
            # just return None in those cases.
d5b0e1f4c5c5 [utils] the json module is always available
Julien Cristau <julien.cristau@logilab.fr>
parents: 9523
diff changeset
   537
            return None
4652
7c41eea7fc30 restore 3.5 compat for date functions moved to lgc.date in 3.6 (closes #716055)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4511
diff changeset
   538
9579
d5b0e1f4c5c5 [utils] the json module is always available
Julien Cristau <julien.cristau@logilab.fr>
parents: 9523
diff changeset
   539
def json_dumps(value, **kwargs):
d5b0e1f4c5c5 [utils] the json module is always available
Julien Cristau <julien.cristau@logilab.fr>
parents: 9523
diff changeset
   540
    return json.dumps(value, cls=CubicWebJsonEncoder, **kwargs)
5940
0e3ae19b181a [uilib] refactor json_dumps code organization
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5883
diff changeset
   541
4879
56c16efedc51 deprecates merge_dicts
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4844
diff changeset
   542
9579
d5b0e1f4c5c5 [utils] the json module is always available
Julien Cristau <julien.cristau@logilab.fr>
parents: 9523
diff changeset
   543
class JSString(str):
d5b0e1f4c5c5 [utils] the json module is always available
Julien Cristau <julien.cristau@logilab.fr>
parents: 9523
diff changeset
   544
    """use this string sub class in values given to :func:`js_dumps` to
d5b0e1f4c5c5 [utils] the json module is always available
Julien Cristau <julien.cristau@logilab.fr>
parents: 9523
diff changeset
   545
    insert raw javascript chain in some JSON string
d5b0e1f4c5c5 [utils] the json module is always available
Julien Cristau <julien.cristau@logilab.fr>
parents: 9523
diff changeset
   546
    """
7575
335f14e8e5a7 [uilib] new js_dumps function allowing usage of bare js string (wrapped into JSString)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7569
diff changeset
   547
9579
d5b0e1f4c5c5 [utils] the json module is always available
Julien Cristau <julien.cristau@logilab.fr>
parents: 9523
diff changeset
   548
def _dict2js(d, predictable=False):
10258
61dfc689830a [utils] use the "predictable" argument to js_dumps
Julien Cristau <julien.cristau@logilab.fr>
parents: 10236
diff changeset
   549
    if predictable:
10662
10942ed172de [py3k] dict.iteritems → dict.items
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10661
diff changeset
   550
        it = sorted(d.items())
10258
61dfc689830a [utils] use the "predictable" argument to js_dumps
Julien Cristau <julien.cristau@logilab.fr>
parents: 10236
diff changeset
   551
    else:
10662
10942ed172de [py3k] dict.iteritems → dict.items
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10661
diff changeset
   552
        it = d.items()
11909
244cd7f407b8 [uilib] Fix incorrect serialization of python dicts into javascript objects
Florent Cayré <florent.cayre@gmail.com>
parents: 11767
diff changeset
   553
    res = [js_dumps(key, predictable) + ': ' + js_dumps(val, predictable)
10258
61dfc689830a [utils] use the "predictable" argument to js_dumps
Julien Cristau <julien.cristau@logilab.fr>
parents: 10236
diff changeset
   554
           for key, val in it]
9579
d5b0e1f4c5c5 [utils] the json module is always available
Julien Cristau <julien.cristau@logilab.fr>
parents: 9523
diff changeset
   555
    return '{%s}' % ', '.join(res)
7575
335f14e8e5a7 [uilib] new js_dumps function allowing usage of bare js string (wrapped into JSString)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7569
diff changeset
   556
9579
d5b0e1f4c5c5 [utils] the json module is always available
Julien Cristau <julien.cristau@logilab.fr>
parents: 9523
diff changeset
   557
def _list2js(l, predictable=False):
d5b0e1f4c5c5 [utils] the json module is always available
Julien Cristau <julien.cristau@logilab.fr>
parents: 9523
diff changeset
   558
    return '[%s]' % ', '.join([js_dumps(val, predictable) for val in l])
7575
335f14e8e5a7 [uilib] new js_dumps function allowing usage of bare js string (wrapped into JSString)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7569
diff changeset
   559
9579
d5b0e1f4c5c5 [utils] the json module is always available
Julien Cristau <julien.cristau@logilab.fr>
parents: 9523
diff changeset
   560
def js_dumps(something, predictable=False):
d5b0e1f4c5c5 [utils] the json module is always available
Julien Cristau <julien.cristau@logilab.fr>
parents: 9523
diff changeset
   561
    """similar as :func:`json_dumps`, except values which are instances of
d5b0e1f4c5c5 [utils] the json module is always available
Julien Cristau <julien.cristau@logilab.fr>
parents: 9523
diff changeset
   562
    :class:`JSString` are expected to be valid javascript and will be output
d5b0e1f4c5c5 [utils] the json module is always available
Julien Cristau <julien.cristau@logilab.fr>
parents: 9523
diff changeset
   563
    as is
7575
335f14e8e5a7 [uilib] new js_dumps function allowing usage of bare js string (wrapped into JSString)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7569
diff changeset
   564
9579
d5b0e1f4c5c5 [utils] the json module is always available
Julien Cristau <julien.cristau@logilab.fr>
parents: 9523
diff changeset
   565
    >>> js_dumps({'hop': JSString('$.hop'), 'bar': None}, predictable=True)
d5b0e1f4c5c5 [utils] the json module is always available
Julien Cristau <julien.cristau@logilab.fr>
parents: 9523
diff changeset
   566
    '{bar: null, hop: $.hop}'
d5b0e1f4c5c5 [utils] the json module is always available
Julien Cristau <julien.cristau@logilab.fr>
parents: 9523
diff changeset
   567
    >>> js_dumps({'hop': '$.hop'})
d5b0e1f4c5c5 [utils] the json module is always available
Julien Cristau <julien.cristau@logilab.fr>
parents: 9523
diff changeset
   568
    '{hop: "$.hop"}'
d5b0e1f4c5c5 [utils] the json module is always available
Julien Cristau <julien.cristau@logilab.fr>
parents: 9523
diff changeset
   569
    >>> js_dumps({'hip': {'hop': JSString('momo')}})
d5b0e1f4c5c5 [utils] the json module is always available
Julien Cristau <julien.cristau@logilab.fr>
parents: 9523
diff changeset
   570
    '{hip: {hop: momo}}'
d5b0e1f4c5c5 [utils] the json module is always available
Julien Cristau <julien.cristau@logilab.fr>
parents: 9523
diff changeset
   571
    """
d5b0e1f4c5c5 [utils] the json module is always available
Julien Cristau <julien.cristau@logilab.fr>
parents: 9523
diff changeset
   572
    if isinstance(something, dict):
d5b0e1f4c5c5 [utils] the json module is always available
Julien Cristau <julien.cristau@logilab.fr>
parents: 9523
diff changeset
   573
        return _dict2js(something, predictable)
d5b0e1f4c5c5 [utils] the json module is always available
Julien Cristau <julien.cristau@logilab.fr>
parents: 9523
diff changeset
   574
    if isinstance(something, list):
d5b0e1f4c5c5 [utils] the json module is always available
Julien Cristau <julien.cristau@logilab.fr>
parents: 9523
diff changeset
   575
        return _list2js(something, predictable)
d5b0e1f4c5c5 [utils] the json module is always available
Julien Cristau <julien.cristau@logilab.fr>
parents: 9523
diff changeset
   576
    if isinstance(something, JSString):
d5b0e1f4c5c5 [utils] the json module is always available
Julien Cristau <julien.cristau@logilab.fr>
parents: 9523
diff changeset
   577
        return something
10258
61dfc689830a [utils] use the "predictable" argument to js_dumps
Julien Cristau <julien.cristau@logilab.fr>
parents: 10236
diff changeset
   578
    return json_dumps(something, sort_keys=predictable)
7575
335f14e8e5a7 [uilib] new js_dumps function allowing usage of bare js string (wrapped into JSString)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7569
diff changeset
   579
7998
9ef285eb20f4 [utils] add a ``js_href`` function to generated proper javascript href
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7990
diff changeset
   580
PERCENT_IN_URLQUOTE_RE = re.compile(r'%(?=[0-9a-fA-F]{2})')
9ef285eb20f4 [utils] add a ``js_href`` function to generated proper javascript href
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7990
diff changeset
   581
def js_href(javascript_code):
9ef285eb20f4 [utils] add a ``js_href`` function to generated proper javascript href
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7990
diff changeset
   582
    """Generate a "javascript: ..." string for an href attribute.
9ef285eb20f4 [utils] add a ``js_href`` function to generated proper javascript href
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7990
diff changeset
   583
9ef285eb20f4 [utils] add a ``js_href`` function to generated proper javascript href
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7990
diff changeset
   584
    Some % which may be interpreted in a href context will be escaped.
9ef285eb20f4 [utils] add a ``js_href`` function to generated proper javascript href
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7990
diff changeset
   585
9ef285eb20f4 [utils] add a ``js_href`` function to generated proper javascript href
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7990
diff changeset
   586
    In an href attribute, url-quotes-looking fragments are interpreted before
9ef285eb20f4 [utils] add a ``js_href`` function to generated proper javascript href
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7990
diff changeset
   587
    being given to the javascript engine. Valid url quotes are in the form
9ef285eb20f4 [utils] add a ``js_href`` function to generated proper javascript href
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7990
diff changeset
   588
    ``%xx`` with xx being a byte in hexadecimal form. This means that ``%toto``
9ef285eb20f4 [utils] add a ``js_href`` function to generated proper javascript href
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7990
diff changeset
   589
    will be unaltered but ``%babar`` will be mangled because ``ba`` is the
9ef285eb20f4 [utils] add a ``js_href`` function to generated proper javascript href
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7990
diff changeset
   590
    hexadecimal representation of 186.
9ef285eb20f4 [utils] add a ``js_href`` function to generated proper javascript href
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7990
diff changeset
   591
9ef285eb20f4 [utils] add a ``js_href`` function to generated proper javascript href
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7990
diff changeset
   592
    >>> js_href('alert("babar");')
9ef285eb20f4 [utils] add a ``js_href`` function to generated proper javascript href
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7990
diff changeset
   593
    'javascript: alert("babar");'
9ef285eb20f4 [utils] add a ``js_href`` function to generated proper javascript href
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7990
diff changeset
   594
    >>> js_href('alert("%babar");')
9ef285eb20f4 [utils] add a ``js_href`` function to generated proper javascript href
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7990
diff changeset
   595
    'javascript: alert("%25babar");'
9ef285eb20f4 [utils] add a ``js_href`` function to generated proper javascript href
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7990
diff changeset
   596
    >>> js_href('alert("%toto %babar");')
9ef285eb20f4 [utils] add a ``js_href`` function to generated proper javascript href
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7990
diff changeset
   597
    'javascript: alert("%toto %25babar");'
9ef285eb20f4 [utils] add a ``js_href`` function to generated proper javascript href
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7990
diff changeset
   598
    >>> js_href('alert("%1337%");')
9ef285eb20f4 [utils] add a ``js_href`` function to generated proper javascript href
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7990
diff changeset
   599
    'javascript: alert("%251337%");'
9ef285eb20f4 [utils] add a ``js_href`` function to generated proper javascript href
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7990
diff changeset
   600
    """
9ef285eb20f4 [utils] add a ``js_href`` function to generated proper javascript href
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7990
diff changeset
   601
    return 'javascript: ' + PERCENT_IN_URLQUOTE_RE.sub(r'%25', javascript_code)
9ef285eb20f4 [utils] add a ``js_href`` function to generated proper javascript href
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7990
diff changeset
   602
7575
335f14e8e5a7 [uilib] new js_dumps function allowing usage of bare js string (wrapped into JSString)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7569
diff changeset
   603
7954
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   604
logger = getLogger('cubicweb.utils')
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   605
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   606
class QueryCache(object):
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   607
    """ a minimalist dict-like object to be used by the querier
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   608
    and native source (replaces lgc.cache for this very usage)
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   609
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   610
    To be efficient it must be properly used. The usage patterns are
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   611
    quite specific to its current clients.
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   612
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   613
    The ceiling value should be sufficiently high, else it will be
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   614
    ruthlessly inefficient (there will be warnings when this happens).
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   615
    A good (high enough) value can only be set on a per-application
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   616
    value. A default, reasonnably high value is provided but tuning
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   617
    e.g `rql-cache-size` can certainly help.
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   618
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   619
    There are two kinds of elements to put in this cache:
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   620
    * frequently used elements
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   621
    * occasional elements
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   622
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   623
    The former should finish in the _permanent structure after some
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   624
    warmup.
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   625
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   626
    Occasional elements can be buggy requests (server-side) or
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   627
    end-user (web-ui provided) requests. These have to be cleaned up
10510
51321946da37 Spelling fixes in comments and docstrings
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10258
diff changeset
   628
    when they fill the cache, without evicting the useful, frequently
7954
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   629
    used entries.
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   630
    """
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   631
    # quite arbitrary, but we want to never
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   632
    # immortalize some use-a-little query
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   633
    _maxlevel = 15
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   634
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   635
    def __init__(self, ceiling=3000):
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   636
        self._max = ceiling
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   637
        # keys belonging forever to this cache
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   638
        self._permanent = set()
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   639
        # mapping of key (that can get wiped) to getitem count
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   640
        self._transient = {}
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   641
        self._data = {}
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   642
        self._lock = Lock()
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   643
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   644
    def __len__(self):
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   645
        with self._lock:
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   646
            return len(self._data)
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   647
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   648
    def __getitem__(self, k):
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   649
        with self._lock:
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   650
            if k in self._permanent:
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   651
                return self._data[k]
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   652
            v = self._transient.get(k, _MARKER)
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   653
            if v is _MARKER:
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   654
                self._transient[k] = 1
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   655
                return self._data[k]
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   656
            if v > self._maxlevel:
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   657
                self._permanent.add(k)
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   658
                self._transient.pop(k, None)
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   659
            else:
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   660
                self._transient[k] += 1
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   661
            return self._data[k]
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   662
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   663
    def __setitem__(self, k, v):
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   664
        with self._lock:
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   665
            if len(self._data) >= self._max:
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   666
                self._try_to_make_room()
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   667
            self._data[k] = v
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   668
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   669
    def pop(self, key, default=_MARKER):
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   670
        with self._lock:
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   671
            try:
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   672
                if default is _MARKER:
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   673
                    return self._data.pop(key)
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   674
                return self._data.pop(key, default)
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   675
            finally:
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   676
                if key in self._permanent:
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   677
                    self._permanent.remove(key)
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   678
                else:
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   679
                    self._transient.pop(key, None)
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   680
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   681
    def clear(self):
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   682
        with self._lock:
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   683
            self._clear()
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   684
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   685
    def _clear(self):
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   686
        self._permanent = set()
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   687
        self._transient = {}
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   688
        self._data = {}
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   689
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   690
    def _try_to_make_room(self):
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   691
        current_size = len(self._data)
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   692
        items = sorted(self._transient.items(), key=itemgetter(1))
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   693
        level = 0
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   694
        for k, v in items:
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   695
            self._data.pop(k, None)
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   696
            self._transient.pop(k, None)
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   697
            if v > level:
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   698
                datalen = len(self._data)
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   699
                if datalen == 0:
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   700
                    return
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   701
                if (current_size - datalen) / datalen > .1:
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   702
                    break
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   703
                level = v
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   704
        else:
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   705
            # we removed cruft but everything is permanent
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   706
            if len(self._data) >= self._max:
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   707
                logger.warning('Cache %s is full.' % id(self))
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   708
                self._clear()
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   709
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   710
    def _usage_report(self):
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   711
        with self._lock:
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   712
            return {'itemcount': len(self._data),
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   713
                    'transientcount': len(self._transient),
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   714
                    'permanentcount': len(self._permanent)}
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   715
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   716
    def popitem(self):
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   717
        raise NotImplementedError()
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   718
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   719
    def setdefault(self, key, default=None):
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   720
        raise NotImplementedError()
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   721
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   722
    def update(self, other):
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7876
diff changeset
   723
        raise NotImplementedError()