--- a/.hgtags Mon Sep 26 18:03:38 2011 +0200
+++ b/.hgtags Mon Sep 26 19:24:08 2011 +0200
@@ -223,3 +223,7 @@
a62f24e1497e953fbaed5894f6064a64f7ac0be3 cubicweb-version-3.10.x
20d9c550c57eb6f9adcb0cfab1c11b6b8793afb6 cubicweb-version-3.13.5
2e9dd7d945557c210d3b79153c65f6885e755315 cubicweb-debian-version-3.13.5-1
+074c848a3712a77737d9a1bfbb618c75f5c0cbfa cubicweb-version-3.12.10
+9dfd21fa0a8b9f121a08866ad3e2ebd1dd06790d cubicweb-debian-version-3.12.10-1
+17c007ad845abbac82e12146abab32a634657574 cubicweb-version-3.13.6
+8a8949ca5351d48c5cf795ccdff06c1d4aab2ce0 cubicweb-debian-version-3.13.6-1
--- a/__pkginfo__.py Mon Sep 26 18:03:38 2011 +0200
+++ b/__pkginfo__.py Mon Sep 26 19:24:08 2011 +0200
@@ -22,7 +22,11 @@
modname = distname = "cubicweb"
+<<<<<<< /home/syt/src/cubicweb/__pkginfo__.py
numversion = (3, 14, 0)
+=======
+numversion = (3, 13, 6)
+>>>>>>> /tmp/__pkginfo__.py~other.Prvgd6
version = '.'.join(str(num) for num in numversion)
description = "a repository of entities / relations for knowledge management"
--- a/debian/changelog Mon Sep 26 18:03:38 2011 +0200
+++ b/debian/changelog Mon Sep 26 19:24:08 2011 +0200
@@ -1,3 +1,9 @@
+cubicweb (3.13.6-1) unstable; urgency=low
+
+ * new upstream release
+
+ -- Sylvain Thénault <sylvain.thenault@logilab.fr> Mon, 26 Sep 2011 18:36:00 +0200
+
cubicweb (3.13.5-1) unstable; urgency=low
* new upstream release
@@ -28,6 +34,12 @@
-- Sylvain Thénault <sylvain.thenault@logilab.fr> Tue, 12 Jul 2011 12:23:54 +0200
+cubicweb (3.12.10-1) unstable; urgency=low
+
+ * new upstream release
+
+ -- Sylvain Thénault <sylvain.thenault@logilab.fr> Mon, 26 Sep 2011 17:22:29 +0200
+
cubicweb (3.12.9-1) unstable; urgency=low
* new upstream release
--- a/devtools/__init__.py Mon Sep 26 18:03:38 2011 +0200
+++ b/devtools/__init__.py Mon Sep 26 19:24:08 2011 +0200
@@ -260,8 +260,9 @@
Example usage::
class MyTests(CubicWebTC):
- _config = RealDatabseConfiguration('myapp',
- sourcefile='/path/to/sources')
+ _config = RealDatabaseConfiguration('myapp',
+ sourcefile='/path/to/sources')
+
def test_something(self):
rset = self.execute('Any X WHERE X is CWUser')
self.view('foaf', rset)
--- a/devtools/fake.py Mon Sep 26 18:03:38 2011 +0200
+++ b/devtools/fake.py Mon Sep 26 19:24:08 2011 +0200
@@ -63,8 +63,8 @@
self._session_data = {}
self._headers_in = Headers()
- def set_cookie(self, cookie, key, maxage=300, expires=None):
- super(FakeRequest, self).set_cookie(cookie, key, maxage=300, expires=None)
+ def set_cookie(self, name, value, maxage=300, expires=None, secure=False):
+ super(FakeRequest, self).set_cookie(name, value, maxage, expires, secure)
cookie = self.get_response_header('Set-Cookie')
self._headers_in.setHeader('Cookie', cookie)
--- a/devtools/repotest.py Mon Sep 26 18:03:38 2011 +0200
+++ b/devtools/repotest.py Mon Sep 26 19:24:08 2011 +0200
@@ -329,9 +329,10 @@
# monkey patch some methods to get predicatable results #######################
-from cubicweb.rqlrewrite import RQLRewriter
-_orig_insert_snippets = RQLRewriter.insert_snippets
-_orig_build_variantes = RQLRewriter.build_variantes
+from cubicweb import rqlrewrite
+_orig_iter_relations = rqlrewrite.iter_relations
+_orig_insert_snippets = rqlrewrite.RQLRewriter.insert_snippets
+_orig_build_variantes = rqlrewrite.RQLRewriter.build_variantes
def _insert_snippets(self, snippets, varexistsmap=None):
_orig_insert_snippets(self, sorted(snippets, snippet_cmp), varexistsmap)
@@ -415,9 +416,13 @@
def _syntax_tree_search(*args, **kwargs):
return deepcopy(_orig_syntax_tree_search(*args, **kwargs))
+def _ordered_iter_relations(stinfo):
+ return sorted(_orig_iter_relations(stinfo), key=lambda x:x.r_type)
+
def do_monkey_patch():
- RQLRewriter.insert_snippets = _insert_snippets
- RQLRewriter.build_variantes = _build_variantes
+ rqlrewrite.iter_relations = _ordered_iter_relations
+ rqlrewrite.RQLRewriter.insert_snippets = _insert_snippets
+ rqlrewrite.RQLRewriter.build_variantes = _build_variantes
ExecutionPlan._check_permissions = _check_permissions
ExecutionPlan.tablesinorder = None
ExecutionPlan.init_temp_table = _init_temp_table
@@ -426,8 +431,9 @@
PyroRQLSource.syntax_tree_search = _syntax_tree_search
def undo_monkey_patch():
- RQLRewriter.insert_snippets = _orig_insert_snippets
- RQLRewriter.build_variantes = _orig_build_variantes
+ rqlrewrite.iter_relations = _orig_iter_relations
+ rqlrewrite.RQLRewriter.insert_snippets = _orig_insert_snippets
+ rqlrewrite.RQLRewriter.build_variantes = _orig_build_variantes
ExecutionPlan._check_permissions = _orig_check_permissions
ExecutionPlan.init_temp_table = _orig_init_temp_table
PartPlanInformation.merge_input_maps = _orig_merge_input_maps
--- a/doc/book/en/devrepo/testing.rst Mon Sep 26 18:03:38 2011 +0200
+++ b/doc/book/en/devrepo/testing.rst Mon Sep 26 19:24:08 2011 +0200
@@ -337,13 +337,12 @@
sourcefile='/path/to/realdb_sources')
def test_blog_rss(self):
- req = self.request()
- rset = req.execute('Any B ORDERBY D DESC WHERE B is BlogEntry, '
- 'B created_by U, U login "logilab", B creation_date D')
+ req = self.request()
+ rset = req.execute('Any B ORDERBY D DESC WHERE B is BlogEntry, '
+ 'B created_by U, U login "logilab", B creation_date D')
self.view('rss', rset)
-
Testing with other cubes
------------------------
--- a/etwist/http.py Mon Sep 26 18:03:38 2011 +0200
+++ b/etwist/http.py Mon Sep 26 19:24:08 2011 +0200
@@ -1,7 +1,7 @@
"""twisted server for CubicWeb web instances
:organization: Logilab
-:copyright: 2001-2010 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2.
+:copyright: 2001-2011 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2.
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
"""
@@ -25,25 +25,14 @@
def _init_headers(self):
if self._headers_out is None:
return
-
- # initialize cookies
- cookies = self._headers_out.getHeader('set-cookie') or []
- for cookie in cookies:
- self._twreq.addCookie(cookie.name, cookie.value, cookie.expires,
- cookie.domain, cookie.path, #TODO max-age
- comment = cookie.comment, secure=cookie.secure)
- self._headers_out.removeHeader('set-cookie')
-
- # initialize other headers
- for k, v in self._headers_out.getAllRawHeaders():
- self._twreq.setHeader(k, v[0])
-
+ # initialize headers
+ for k, values in self._headers_out.getAllRawHeaders():
+ self._twreq.responseHeaders.setRawHeaders(k, values)
# add content-length if not present
if (self._headers_out.getHeader('content-length') is None
and self._stream is not None):
self._twreq.setHeader('content-length', len(self._stream))
-
def _finalize(self):
# we must set code before writing anything, else it's too late
if self._code is not None:
--- a/i18n/de.po Mon Sep 26 18:03:38 2011 +0200
+++ b/i18n/de.po Mon Sep 26 19:24:08 2011 +0200
@@ -225,6 +225,9 @@
"können ein <a href=\"%s\">vollständiges Schema</a> mit Meta-Daten anzeigen.</"
"div>"
+msgid "<no relation>"
+msgstr ""
+
msgid "<not specified>"
msgstr "<nicht spezifiziert>"
@@ -3595,9 +3598,6 @@
msgid "searching for"
msgstr "Suche nach"
-msgid "secondary"
-msgstr "sekundär"
-
msgid "security"
msgstr "Sicherheit"
@@ -4461,9 +4461,12 @@
#, python-format
msgid "you should un-inline relation %s which is supported and may be crossed "
msgstr ""
+<<<<<<< /home/syt/src/cubicweb/i18n/de.po
#~ msgid "Schema of the data model"
#~ msgstr "Schema des Datenmodells"
#~ msgid "instance schema"
#~ msgstr "Schema der Instanz"
+=======
+>>>>>>> /tmp/de.po~other.fn7YK0
--- a/i18n/en.po Mon Sep 26 18:03:38 2011 +0200
+++ b/i18n/en.po Mon Sep 26 19:24:08 2011 +0200
@@ -214,6 +214,9 @@
"can also display a <a href=\"%s\">complete schema with meta-data</a>.</div>"
msgstr ""
+msgid "<no relation>"
+msgstr ""
+
msgid "<not specified>"
msgstr ""
@@ -1041,9 +1044,6 @@
msgid "add a CWRType"
msgstr "add a relation type"
-msgid "add a CWSource"
-msgstr "add a source"
-
msgctxt "inlined:CWUser.use_email.subject"
msgid "add a EmailAddress"
msgstr "add an email address"
@@ -3508,9 +3508,6 @@
msgid "searching for"
msgstr ""
-msgid "secondary"
-msgstr ""
-
msgid "security"
msgstr ""
@@ -4349,9 +4346,12 @@
#, python-format
msgid "you should un-inline relation %s which is supported and may be crossed "
msgstr ""
+<<<<<<< /home/syt/src/cubicweb/i18n/en.po
#~ msgid "add a CWSourceSchemaConfig"
#~ msgstr "add an item to mapping "
#~ msgid "siteinfo"
#~ msgstr "site information"
+=======
+>>>>>>> /tmp/en.po~other.NvgtGM
--- a/i18n/es.po Mon Sep 26 18:03:38 2011 +0200
+++ b/i18n/es.po Mon Sep 26 19:24:08 2011 +0200
@@ -226,6 +226,9 @@
"pero se puede ver a un <a href=\"%s\">modelo completo con meta-datos</a>.</"
"div>"
+msgid "<no relation>"
+msgstr ""
+
msgid "<not specified>"
msgstr "<no especificado>"
@@ -1091,9 +1094,12 @@
msgid "add a CWRType"
msgstr "Agregar un tipo de relación"
+<<<<<<< /home/syt/src/cubicweb/i18n/es.po
msgid "add a CWSource"
msgstr "agregar una fuente"
+=======
+>>>>>>> /tmp/es.po~other.Yb6Y5q
msgctxt "inlined:CWUser.use_email.subject"
msgid "add a EmailAddress"
msgstr "Agregar correo electrónico"
@@ -3645,9 +3651,6 @@
msgid "searching for"
msgstr "Buscando"
-msgid "secondary"
-msgstr "Secundaria"
-
msgid "security"
msgstr "Seguridad"
@@ -4512,6 +4515,7 @@
msgstr ""
"usted debe quitar la puesta en línea de la relación %s que es aceptada y "
"puede ser cruzada"
+<<<<<<< /home/syt/src/cubicweb/i18n/es.po
#~ msgid "Schema of the data model"
#~ msgstr "Esquema del modelo de datos"
@@ -4524,3 +4528,5 @@
#~ msgid "siteinfo"
#~ msgstr "información"
+=======
+>>>>>>> /tmp/es.po~other.Yb6Y5q
--- a/i18n/fr.po Mon Sep 26 18:03:38 2011 +0200
+++ b/i18n/fr.po Mon Sep 26 19:24:08 2011 +0200
@@ -226,6 +226,9 @@
"<div>Ce schéma du modèle de données <em>exclue</em> les méta-données, mais "
"vous pouvez afficher un <a href=\"%s\">schéma complet</a>.</div>"
+msgid "<no relation>"
+msgstr "<pas de relation>"
+
msgid "<not specified>"
msgstr "<non spécifié>"
@@ -1091,9 +1094,12 @@
msgid "add a CWRType"
msgstr "ajouter un type de relation"
+<<<<<<< /home/syt/src/cubicweb/i18n/fr.po
msgid "add a CWSource"
msgstr "ajouter une source"
+=======
+>>>>>>> /tmp/fr.po~other.KbuYNx
msgctxt "inlined:CWUser.use_email.subject"
msgid "add a EmailAddress"
msgstr "ajouter une adresse électronique"
@@ -3651,9 +3657,6 @@
msgid "searching for"
msgstr "Recherche de"
-msgid "secondary"
-msgstr "secondaire"
-
msgid "security"
msgstr "sécurité"
--- a/rqlrewrite.py Mon Sep 26 18:03:38 2011 +0200
+++ b/rqlrewrite.py Mon Sep 26 19:24:08 2011 +0200
@@ -119,6 +119,10 @@
return newsolutions
+def iter_relations(stinfo):
+ # this is a function so that test may return relation in a predictable order
+ return stinfo['relations'] - stinfo['rhsrelations']
+
class Unsupported(Exception):
"""raised when an rql expression can't be inserted in some rql query
because it create an unresolvable query (eg no solutions found)
@@ -349,7 +353,7 @@
while todo:
varname, stinfo = todo.pop()
done.add(varname)
- for rel in stinfo['relations'] - stinfo['rhsrelations']:
+ for rel in iter_relations(stinfo):
if rel in done:
continue
done.add(rel)
@@ -380,7 +384,7 @@
if vref.name not in done and rschema.inlined:
# we can use vref here define in above for loop
ostinfo = vref.variable.stinfo
- for orel in ostinfo['relations'] - ostinfo['rhsrelations']:
+ for orel in iter_relations(ostinfo):
orschema = get_rschema(orel.r_type)
if orschema.final or orschema.inlined:
todo.append( (vref.name, ostinfo) )
--- a/skeleton/test/realdb_test_CUBENAME.py Mon Sep 26 18:03:38 2011 +0200
+++ b/skeleton/test/realdb_test_CUBENAME.py Mon Sep 26 19:24:08 2011 +0200
@@ -18,8 +18,8 @@
"""
"""
-from cubicweb.devtools import buildconfig, loadconfig
-from cubicweb.devtools.testlib import RealDBTest
+from cubicweb.devtools.testlib import CubicWebTC
+from cubicweb.devtools.realdbtest import buildconfig, loadconfig
def setUpModule(options):
if options.source:
@@ -32,7 +32,8 @@
options.epassword)
RealDatabaseTC.configcls = configcls
-class RealDatabaseTC(RealDBTest):
+
+class RealDatabaseTC(CubicWebTC):
configcls = None # set by setUpModule()
def test_all_primaries(self):
--- a/test/unittest_rqlrewrite.py Mon Sep 26 18:03:38 2011 +0200
+++ b/test/unittest_rqlrewrite.py Mon Sep 26 19:24:08 2011 +0200
@@ -21,9 +21,8 @@
from yams import BadSchemaDefinition
from rql import parse, nodes, RQLHelper
-from cubicweb import Unauthorized
+from cubicweb import Unauthorized, rqlrewrite
from cubicweb.schema import RRQLExpression, ERQLExpression
-from cubicweb.rqlrewrite import RQLRewriter
from cubicweb.devtools import repotest, TestServerConfiguration
@@ -62,9 +61,10 @@
@staticmethod
def simplify(mainrqlst, needcopy=False):
rqlhelper.simplify(rqlst, needcopy)
- rewriter = RQLRewriter(mock_object(vreg=FakeVReg, user=(mock_object(eid=1))))
+ rewriter = rqlrewrite.RQLRewriter(
+ mock_object(vreg=FakeVReg, user=(mock_object(eid=1))))
snippets = []
- for v, exprs in snippets_map.items():
+ for v, exprs in sorted(snippets_map.items()):
rqlexprs = [isinstance(snippet, basestring)
and mock_object(snippet_rqlst=parse('Any X WHERE '+snippet).children[0],
expression='Any X WHERE '+snippet)
@@ -210,11 +210,11 @@
}, {})
# XXX suboptimal
self.assertEqual(rqlst.as_string(),
- "Any C,A,R WITH A,R,C BEING "
- "(Any A,R,C WHERE A ref R, A? inlined_card C, "
- "(A is NULL) OR (EXISTS(A inlined_card B, B require_permission D, "
- "B is Card, D is CWPermission)), "
- "A is Affaire, C is Card, EXISTS(C require_permission E, E is CWPermission))")
+ "Any C,A,R WITH A,C,R BEING "
+ "(Any A,C,R WHERE A? inlined_card C, A ref R, "
+ "(A is NULL) OR (EXISTS(A inlined_card B, B require_permission D, "
+ "B is Card, D is CWPermission)), "
+ "A is Affaire, C is Card, EXISTS(C require_permission E, E is CWPermission))")
# def test_optional_var_inlined_has_perm(self):
# c1 = ('X require_permission P')
--- a/web/application.py Mon Sep 26 18:03:38 2011 +0200
+++ b/web/application.py Mon Sep 26 19:24:08 2011 +0200
@@ -236,12 +236,10 @@
def open_session(self, req, allow_no_cnx=True):
session = self.session_manager.open_session(req, allow_no_cnx=allow_no_cnx)
- cookie = req.get_cookie()
sessioncookie = self.session_cookie(req)
- cookie[sessioncookie] = session.sessionid
- if req.https and req.base_url().startswith('https://'):
- cookie[sessioncookie]['secure'] = True
- req.set_cookie(cookie, sessioncookie, maxage=None)
+ secure = req.https and req.base_url().startswith('https://')
+ req.set_cookie(sessioncookie, session.sessionid,
+ maxage=None, secure=secure)
if not session.anonymous_session:
self.session_manager.postlogin(req)
return session
@@ -251,8 +249,7 @@
`AuthenticationError`
"""
self.session_manager.close_session(req.session)
- sessioncookie = self.session_cookie(req)
- req.remove_cookie(req.get_cookie(), sessioncookie)
+ req.remove_cookie(self.session_cookie(req))
raise LogOut(url=goto_url)
# these are overridden by set_log_methods below
--- a/web/data/cubicweb.facets.css Mon Sep 26 18:03:38 2011 +0200
+++ b/web/data/cubicweb.facets.css Mon Sep 26 19:24:08 2011 +0200
@@ -15,7 +15,7 @@
color: #000;
margin-bottom: 2px;
cursor: pointer;
- font: bold 100% Georgia;
+ font: %(facet_titleFont)s;
}
div.facetTitle a {
@@ -30,8 +30,8 @@
color: #000 !important;
}
-div.overflowed{
- height: 12em;
+div.overflowed {
+ height: %(facet_overflowedHeight)s;
overflow-y: auto;
}
--- a/web/data/uiprops.py Mon Sep 26 18:03:38 2011 +0200
+++ b/web/data/uiprops.py Mon Sep 26 19:24:08 2011 +0200
@@ -165,3 +165,9 @@
infoMsgBgImg = 'url("information.png") 5px center no-repeat'
errorMsgBgImg = 'url("error.png") 100% 50% no-repeat'
errorMsgColor = '#ed0d0d'
+
+# facets
+facet_titleFont = 'bold 100% Georgia'
+facet_overflowedHeight = '12em'
+
+
--- a/web/facet.py Mon Sep 26 18:03:38 2011 +0200
+++ b/web/facet.py Mon Sep 26 19:24:08 2011 +0200
@@ -587,7 +587,7 @@
_select_target_entity = True
title = property(rtype_facet_title)
- no_relation_label = '<no relation>'
+ no_relation_label = _('<no relation>')
def __repr__(self):
return '<%s on (%s-%s)>' % (self.__class__.__name__, self.rtype, self.role)
@@ -991,7 +991,7 @@
class AgencyFacet(RQLPathFacet):
__regid__ = 'agency'
# this facet should only be selected when visualizing offices
- __select__ = RelationFacet.__select__ & is_instance('Office')
+ __select__ = is_instance('Office')
# this facet is a filter on the 'Agency' entities linked to the office
# through the 'proposed_by' relation, where the office is the subject
# of the relation
@@ -1002,7 +1002,7 @@
class PostalCodeFacet(RQLPathFacet):
__regid__ = 'postalcode'
# this facet should only be selected when visualizing offices
- __select__ = RelationAttributeFacet.__select__ & is_instance('Office')
+ __select__ = is_instance('Office')
# this facet is a filter on the PostalAddress entities linked to the
# office through the 'has_address' relation, where the office is the
# subject of the relation
@@ -1336,6 +1336,24 @@
## html widets ################################################################
+_DEFAULT_CONSTANT_VOCAB_WIDGET_HEIGHT = 9
+
+@cached
+def _css_height_to_line_count(vreg):
+ cssprop = vreg.config.uiprops['facet_overflowedHeight'].lower().strip()
+ # let's talk a bit ...
+ # we try to deduce a number of displayed lines from a css property
+ # there is a linear (rough empiric coefficient == 0.73) relation between
+ # css _em_ value and line qty
+ # if we get another unit we're out of luck and resort to one constant
+ # hence, it is strongly advised not to specify but ems for this css prop
+ if cssprop.endswith('em'):
+ try:
+ return int(cssprop[:-2]) * .73
+ except Exception:
+ vreg.warning('css property facet_overflowedHeight looks malformed (%r)',
+ cssprop)
+ return _DEFAULT_CONSTANT_VOCAB_WIDGET_HEIGHT
class FacetVocabularyWidget(htmlwidgets.HTMLWidget):
@@ -1343,8 +1361,10 @@
self.facet = facet
self.items = []
+ @cached
def height(self):
- return len(self.items) + 1
+ maxheight = _css_height_to_line_count(self.facet._cw.vreg)
+ return 1 + min(len(self.items), maxheight) + int(self.facet._support_and_compat())
def append(self, item):
self.items.append(item)
--- a/web/http_headers.py Mon Sep 26 18:03:38 2011 +0200
+++ b/web/http_headers.py Mon Sep 26 19:24:08 2011 +0200
@@ -1354,9 +1354,25 @@
raw_header.append(value)
self._headers[name] = _RecalcNeeded
+ def addHeader(self, name, value):
+ """
+ Add a parsed representatoin to a header that may or may not already exist.
+ If it exists, add it as a separate header to output; do not
+ replace anything.
+ """
+ name=name.lower()
+ header = self._headers.get(name)
+ if header is None:
+ # No header yet
+ header = []
+ self._headers[name] = header
+ elif header is _RecalcNeeded:
+ header = self._toParsed(name)
+ header.append(value)
+ self._raw_headers[name] = _RecalcNeeded
+
def removeHeader(self, name):
"""Removes the header named."""
-
name=name.lower()
if self._raw_headers.has_key(name):
del self._raw_headers[name]
--- a/web/request.py Mon Sep 26 18:03:38 2011 +0200
+++ b/web/request.py Mon Sep 26 19:24:08 2011 +0200
@@ -19,11 +19,12 @@
__docformat__ = "restructuredtext en"
-import Cookie
import hashlib
import time
import random
import base64
+from Cookie import SimpleCookie
+from calendar import timegm
from datetime import date
from urlparse import urlsplit
from itertools import count
@@ -42,7 +43,8 @@
from cubicweb.view import STRICT_DOCTYPE, TRANSITIONAL_DOCTYPE_NOEXT
from cubicweb.web import (INTERNAL_FIELD_VALUE, LOGGER, NothingToEdit,
RequestError, StatusResponse)
-from cubicweb.web.http_headers import Headers
+from cubicweb.web.httpcache import GMTOFFSET
+from cubicweb.web.http_headers import Headers, Cookie
_MARKER = object()
@@ -518,30 +520,44 @@
def get_cookie(self):
"""retrieve request cookies, returns an empty cookie if not found"""
+ # XXX use http_headers implementation
try:
- return Cookie.SimpleCookie(self.get_header('Cookie'))
+ return SimpleCookie(self.get_header('Cookie'))
except KeyError:
- return Cookie.SimpleCookie()
+ return SimpleCookie()
- def set_cookie(self, cookie, key, maxage=300, expires=None):
- """set / update a cookie key
+ def set_cookie(self, name, value, maxage=300, expires=None, secure=False):
+ """set / update a cookie
by default, cookie will be available for the next 5 minutes.
Give maxage = None to have a "session" cookie expiring when the
client close its browser
"""
- morsel = cookie[key]
- if maxage is not None:
- morsel['Max-Age'] = maxage
- if expires:
- morsel['expires'] = expires.strftime('%a, %d %b %Y %H:%M:%S %z')
+ if isinstance(name, SimpleCookie):
+ warn('[3.13] set_cookie now takes name and value as two first '
+ 'argument, not anymore cookie object and name',
+ DeprecationWarning, stacklevel=2)
+ secure = name[value]['secure']
+ name, value = value, name[value].value
+ if maxage: # don't check is None, 0 may be specified
+ assert expires is None, 'both max age and expires cant be specified'
+ expires = maxage + time.time()
+ elif expires:
+ expires = timegm((expires + GMTOFFSET).timetuple())
+ else:
+ expires = None
# make sure cookie is set on the correct path
- morsel['path'] = self.base_url_path()
- self.add_header('Set-Cookie', morsel.OutputString())
+ cookie = Cookie(name, value, self.base_url_path(), expires=expires,
+ secure=secure)
+ self.headers_out.addHeader('Set-cookie', cookie)
- def remove_cookie(self, cookie, key):
+ def remove_cookie(self, name, bwcompat=None):
"""remove a cookie by expiring it"""
- self.set_cookie(cookie, key, maxage=0, expires=date(1970, 1, 1))
+ if bwcompat is not None:
+ warn('[3.13] remove_cookie now take only a name as argument',
+ DeprecationWarning, stacklevel=2)
+ name = bwcompat
+ self.set_cookie(key, '', maxage=0, expires=date(1970, 1, 1))
def set_content_type(self, content_type, filename=None, encoding=None):
"""set output content type for this request. An optional filename
--- a/web/views/basecontrollers.py Mon Sep 26 18:03:38 2011 +0200
+++ b/web/views/basecontrollers.py Mon Sep 26 19:24:08 2011 +0200
@@ -535,24 +535,20 @@
statename = treecookiename(treeid)
treestate = cookies.get(statename)
if treestate is None:
- cookies[statename] = nodeeid
- self._cw.set_cookie(cookies, statename)
+ self._cw.set_cookie(statename, nodeeid)
else:
marked = set(filter(None, treestate.value.split(':')))
if nodeeid in marked:
marked.remove(nodeeid)
else:
marked.add(nodeeid)
- cookies[statename] = ':'.join(marked)
- self._cw.set_cookie(cookies, statename)
+ self._cw.set_cookie(statename, ':'.join(marked))
@jsonize
@deprecated("[3.13] use jQuery.cookie(cookiename, cookievalue, {path: '/'}) in js land instead")
def js_set_cookie(self, cookiename, cookievalue):
cookiename, cookievalue = str(cookiename), str(cookievalue)
- cookies = self._cw.get_cookie()
- cookies[cookiename] = cookievalue
- self._cw.set_cookie(cookies, cookiename)
+ self._cw.set_cookie(cookiename, cookievalue)
# relations edition stuff ##################################################
--- a/web/views/cwproperties.py Mon Sep 26 18:03:38 2011 +0200
+++ b/web/views/cwproperties.py Mon Sep 26 19:24:08 2011 +0200
@@ -102,8 +102,7 @@
cookiename = self._cookie_name(group)
cookie = cookies.get(cookiename)
if cookie is None:
- cookies[cookiename] = default
- self._cw.set_cookie(cookies, cookiename, maxage=None)
+ self._cw.set_cookie(cookiename, default, maxage=None)
status = default
else:
status = cookie.value
--- a/web/views/cwsources.py Mon Sep 26 18:03:38 2011 +0200
+++ b/web/views/cwsources.py Mon Sep 26 19:24:08 2011 +0200
@@ -263,12 +263,8 @@
def call(self, **kwargs):
self.w('<h1>%s</h1>' % self._cw._(self.title))
- eschema = self._cw.vreg.schema.eschema('CWSource')
- if eschema.has_perm(self._cw, 'add'):
- self.w(u'<a href="%s" class="addButton right">%s</a>' % (
- self._cw.build_url('add/%s' % eschema),
- self._cw._('add a CWSource')))
- self.w(u'<div class="clear"></div>')
+ self.w(add_etype_button(self._cw, 'CWSource'))
+ self.w(u'<div class="clear"></div>')
self.wview('table', self._cw.execute(self.rql), displaycols=range(4))
--- a/web/views/facets.py Mon Sep 26 18:03:38 2011 +0200
+++ b/web/views/facets.py Mon Sep 26 19:24:08 2011 +0200
@@ -206,7 +206,6 @@
class FilterTable(FacetFilterMixIn, AnyRsetView):
__regid__ = 'facet.filtertable'
__select__ = has_facets()
- wdg_stack_size = 8
compact_layout_threshold = 5
def call(self, vid, divid, vidargs, cssclass=''):
@@ -235,10 +234,11 @@
w(u'<table class="filter">\n')
widget_queue = []
queue_height = 0
+ wdg_stack_size = max(wdgs, key=lambda wdg:wdg.height()).height()
w(u'<tr>\n')
for wdg in wdgs:
height = wdg.height()
- if queue_height + height <= self.wdg_stack_size:
+ if queue_height + height <= wdg_stack_size:
widget_queue.append(wdg)
queue_height += height
continue
--- a/web/views/sessions.py Mon Sep 26 18:03:38 2011 +0200
+++ b/web/views/sessions.py Mon Sep 26 19:24:08 2011 +0200
@@ -99,10 +99,10 @@
for forminternal_key in ('__form_id', '__domid', '__errorurl'):
args.pop(forminternal_key, None)
path = req.relative_path(False)
- if path == 'login':
+ if path in ('login', 'logout') or req.form.get('vid') == 'loggedout':
path = 'view'
args['__message'] = req._('welcome %s !') % req.user.login
- if 'vid' in req.form:
+ if 'vid' in req.form and req.form['vid'] != 'loggedout':
args['vid'] = req.form['vid']
if 'rql' in req.form:
args['rql'] = req.form['rql']
--- a/web/views/tabs.py Mon Sep 26 18:03:38 2011 +0200
+++ b/web/views/tabs.py Mon Sep 26 19:24:08 2011 +0200
@@ -93,8 +93,7 @@
activetab = cookies.get(cookiename)
if activetab is None:
domid = uilib.domid(default)
- cookies[cookiename] = domid
- self._cw.set_cookie(cookies, cookiename)
+ self._cw.set_cookie(cookiename, domid)
return domid
return activetab.value