merge stable
authorNicolas Chauvat <nicolas.chauvat@logilab.fr>
Mon, 28 Mar 2011 19:31:45 +0200
branchstable
changeset 7127 a055a1649727
parent 7126 9ebc24d85bb5 (current diff)
parent 7123 bb303290a6cb (diff)
child 7128 f1fe05d5224e
merge
--- a/dataimport.py	Mon Mar 28 19:31:26 2011 +0200
+++ b/dataimport.py	Mon Mar 28 19:31:45 2011 +0200
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
@@ -81,7 +81,7 @@
 from logilab.common.deprecation import deprecated
 
 from cubicweb.server.utils import eschema_eid
-from cubicweb.server.ssplanner import EditedEntity
+from cubicweb.server.edition import EditedEntity
 
 def count_lines(stream_or_filename):
     if isinstance(stream_or_filename, basestring):
--- a/entities/authobjs.py	Mon Mar 28 19:31:26 2011 +0200
+++ b/entities/authobjs.py	Mon Mar 28 19:31:45 2011 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
@@ -87,8 +87,10 @@
                 'CWProperty X WHERE X pkey %(k)s, X for_user U, U eid %(u)s',
                 {'k': pkey, 'u': self.eid}).get_entity(0, 0)
         except:
-            self._cw.create_entity('CWProperty', pkey=unicode(pkey),
-                                   value=value, for_user=self)
+            kwargs = dict(pkey=unicode(pkey), value=value)
+            if self.is_in_group('managers'):
+                kwargs['for_user'] = self
+            self._cw.create_entity('CWProperty', **kwargs)
         else:
             prop.set_attributes(value=value)
 
--- a/hooks/syncsession.py	Mon Mar 28 19:31:26 2011 +0200
+++ b/hooks/syncsession.py	Mon Mar 28 19:31:45 2011 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
--- a/req.py	Mon Mar 28 19:31:26 2011 +0200
+++ b/req.py	Mon Mar 28 19:31:45 2011 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
@@ -154,7 +154,7 @@
 
     def find_one_entity(self, etype, **kwargs):
         """find one entity of the given type and attribute values.
-        raise FindEntityError if can not return one and only one entity.
+        raise :exc:`FindEntityError` if can not return one and only one entity.
 
         >>> users = find_one_entity('CWGroup', name=u'users')
         >>> groups = find_one_entity('CWGroup')
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/edition.py	Mon Mar 28 19:31:45 2011 +0200
@@ -0,0 +1,128 @@
+from copy import copy
+
+_MARKER = object()
+
+class dict_protocol_catcher(object):
+    def __init__(self, entity):
+        self.__entity = entity
+    def __getitem__(self, attr):
+        return self.__entity.cw_edited[attr]
+    def __setitem__(self, attr, value):
+        self.__entity.cw_edited[attr] = value
+    def __getattr__(self, attr):
+        return getattr(self.__entity, attr)
+
+
+class EditedEntity(dict):
+    """encapsulate entities attributes being written by an RQL query"""
+    def __init__(self, entity, **kwargs):
+        dict.__init__(self, **kwargs)
+        self.entity = entity
+        self.skip_security = set()
+        self.querier_pending_relations = {}
+        self.saved = False
+
+    def __hash__(self):
+        # dict|set keyable
+        return hash(id(self))
+
+    def __cmp__(self, other):
+        # we don't want comparison by value inherited from dict
+        return cmp(id(self), id(other))
+
+    def __setitem__(self, attr, value):
+        assert attr != 'eid'
+        # don't add attribute into skip_security if already in edited
+        # attributes, else we may accidentaly skip a desired security check
+        if attr not in self:
+            self.skip_security.add(attr)
+        self.edited_attribute(attr, value)
+
+    def __delitem__(self, attr):
+        assert not self.saved, 'too late to modify edited attributes'
+        super(EditedEntity, self).__delitem__(attr)
+        self.entity.cw_attr_cache.pop(attr, None)
+
+    def pop(self, attr, *args):
+        # don't update skip_security by design (think to storage api)
+        assert not self.saved, 'too late to modify edited attributes'
+        value = super(EditedEntity, self).pop(attr, *args)
+        self.entity.cw_attr_cache.pop(attr, *args)
+        return value
+
+    def setdefault(self, attr, default):
+        assert attr != 'eid'
+        # don't add attribute into skip_security if already in edited
+        # attributes, else we may accidentaly skip a desired security check
+        if attr not in self:
+            self[attr] = default
+        return self[attr]
+
+    def update(self, values, skipsec=True):
+        if skipsec:
+            setitem = self.__setitem__
+        else:
+            setitem = self.edited_attribute
+        for attr, value in values.iteritems():
+            setitem(attr, value)
+
+    def edited_attribute(self, attr, value):
+        """attribute being edited by a rql query: should'nt be added to
+        skip_security
+        """
+        assert not self.saved, 'too late to modify edited attributes'
+        super(EditedEntity, self).__setitem__(attr, value)
+        self.entity.cw_attr_cache[attr] = value
+
+    def oldnewvalue(self, attr):
+        """returns the couple (old attr value, new attr value)
+
+        NOTE: will only work in a before_update_entity hook
+        """
+        assert not self.saved, 'too late to get the old value'
+        # get new value and remove from local dict to force a db query to
+        # fetch old value
+        newvalue = self.entity.cw_attr_cache.pop(attr, _MARKER)
+        oldvalue = getattr(self.entity, attr)
+        if newvalue is not _MARKER:
+            self.entity.cw_attr_cache[attr] = newvalue
+        else:
+            newvalue = oldvalue
+        return oldvalue, newvalue
+
+    def set_defaults(self):
+        """set default values according to the schema"""
+        for attr, value in self.entity.e_schema.defaults():
+            if not attr in self:
+                self[str(attr)] = value
+
+    def check(self, creation=False):
+        """check the entity edition against its schema. Only final relation
+        are checked here, constraint on actual relations are checked in hooks
+        """
+        entity = self.entity
+        if creation:
+            # on creations, we want to check all relations, especially
+            # required attributes
+            relations = [rschema for rschema in entity.e_schema.subject_relations()
+                         if rschema.final and rschema.type != 'eid']
+        else:
+            relations = [entity._cw.vreg.schema.rschema(rtype)
+                         for rtype in self]
+        from yams import ValidationError
+        try:
+            entity.e_schema.check(dict_protocol_catcher(entity),
+                                  creation=creation, _=entity._cw._,
+                                  relations=relations)
+        except ValidationError, ex:
+            ex.entity = self.entity
+            raise
+
+    def clone(self):
+        thecopy = EditedEntity(copy(self.entity))
+        thecopy.entity.cw_attr_cache = copy(self.entity.cw_attr_cache)
+        thecopy.entity._cw_related_cache = {}
+        thecopy.update(self, skipsec=False)
+        return thecopy
+
+
--- a/server/querier.py	Mon Mar 28 19:31:26 2011 +0200
+++ b/server/querier.py	Mon Mar 28 19:31:45 2011 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
@@ -38,7 +38,8 @@
 
 from cubicweb.server.utils import cleanup_solutions
 from cubicweb.server.rqlannotation import SQLGenAnnotator, set_qdata
-from cubicweb.server.ssplanner import READ_ONLY_RTYPES, add_types_restriction, EditedEntity
+from cubicweb.server.ssplanner import READ_ONLY_RTYPES, add_types_restriction
+from cubicweb.server.edition import EditedEntity
 from cubicweb.server.session import security_enabled
 
 def empty_rset(rql, args, rqlst=None):
--- a/server/serverctl.py	Mon Mar 28 19:31:26 2011 +0200
+++ b/server/serverctl.py	Mon Mar 28 19:31:45 2011 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
--- a/server/session.py	Mon Mar 28 19:31:26 2011 +0200
+++ b/server/session.py	Mon Mar 28 19:31:45 2011 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
@@ -37,6 +37,7 @@
 from cubicweb.dbapi import ConnectionProperties
 from cubicweb.utils import make_uid, RepeatList
 from cubicweb.rqlrewrite import RQLRewriter
+from cubicweb.server.edition import EditedEntity
 
 ETYPE_PYOBJ_MAP[Binary] = 'Bytes'
 
@@ -215,8 +216,9 @@
         with security_enabled(self, False, False):
             if self.vreg.schema[rtype].inlined:
                 entity = self.entity_from_eid(fromeid)
-                entity[rtype] = toeid
-                self.repo.glob_update_entity(self, entity, set((rtype,)))
+                edited = EditedEntity(entity)
+                edited.edited_attribute(rtype, toeid)
+                self.repo.glob_update_entity(self, edited)
             else:
                 self.repo.glob_add_relation(self, fromeid, rtype, toeid)
 
@@ -234,7 +236,7 @@
         with security_enabled(self, False, False):
             if self.vreg.schema[rtype].inlined:
                 entity = self.entity_from_eid(fromeid)
-                entity[rtype] = None
+                entity.cw_attr_cache[rtype] = None
                 self.repo.glob_update_entity(self, entity, set((rtype,)))
             else:
                 self.repo.glob_delete_relation(self, fromeid, rtype, toeid)
--- a/server/sources/__init__.py	Mon Mar 28 19:31:26 2011 +0200
+++ b/server/sources/__init__.py	Mon Mar 28 19:31:45 2011 +0200
@@ -31,7 +31,7 @@
 from cubicweb import ValidationError, set_log_methods, server
 from cubicweb.schema import VIRTUAL_RTYPES
 from cubicweb.server.sqlutils import SQL_PREFIX
-from cubicweb.server.ssplanner import EditedEntity
+from cubicweb.server.edition import EditedEntity
 
 
 def dbg_st_search(uri, union, varmap, args, cachekey=None, prefix='rql for'):
--- a/server/sources/ldapuser.py	Mon Mar 28 19:31:26 2011 +0200
+++ b/server/sources/ldapuser.py	Mon Mar 28 19:31:45 2011 +0200
@@ -522,7 +522,8 @@
     def _search(self, session, base, scope,
                 searchstr='(objectClass=*)', attrs=()):
         """make an ldap query"""
-        self.debug('ldap search %s %s %s %s %s', self.uri, base, scope, searchstr, list(attrs))
+        self.debug('ldap search %s %s %s %s %s', self.uri, base, scope,
+                   searchstr, list(attrs))
         # XXX for now, we do not have connection pool support for LDAP, so
         # this is always self._conn
         cnx = session.pool.connection(self.uri).cnx
--- a/server/sources/native.py	Mon Mar 28 19:31:26 2011 +0200
+++ b/server/sources/native.py	Mon Mar 28 19:31:45 2011 +0200
@@ -58,7 +58,7 @@
 from cubicweb.server.rqlannotation import set_qdata
 from cubicweb.server.hook import CleanupDeletedEidsCacheOp
 from cubicweb.server.session import hooks_control, security_enabled
-from cubicweb.server.ssplanner import EditedEntity
+from cubicweb.server.edition import EditedEntity
 from cubicweb.server.sources import AbstractSource, dbg_st_search, dbg_results
 from cubicweb.server.sources.rql2sql import SQLGenerator
 
--- a/server/sources/storages.py	Mon Mar 28 19:31:26 2011 +0200
+++ b/server/sources/storages.py	Mon Mar 28 19:31:45 2011 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
@@ -24,7 +24,7 @@
 
 from cubicweb import Binary, ValidationError
 from cubicweb.server import hook
-from cubicweb.server.ssplanner import EditedEntity
+from cubicweb.server.edition import EditedEntity
 
 
 def set_attribute_storage(repo, etype, attr, storage):
--- a/server/ssplanner.py	Mon Mar 28 19:31:26 2011 +0200
+++ b/server/ssplanner.py	Mon Mar 28 19:31:45 2011 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
@@ -21,8 +21,6 @@
 
 __docformat__ = "restructuredtext en"
 
-from copy import copy
-
 from rql.stmts import Union, Select
 from rql.nodes import Constant, Relation
 
@@ -31,6 +29,7 @@
 from cubicweb.rqlrewrite import add_types_restriction
 from cubicweb.server.session import security_enabled
 from cubicweb.server.hook import CleanupDeletedEidsCacheOp
+from cubicweb.server.edition import EditedEntity
 
 READ_ONLY_RTYPES = set(('eid', 'has_text', 'is', 'is_instance_of', 'identity'))
 
@@ -128,132 +127,6 @@
     return select
 
 
-_MARKER = object()
-
-class dict_protocol_catcher(object):
-    def __init__(self, entity):
-        self.__entity = entity
-    def __getitem__(self, attr):
-        return self.__entity.cw_edited[attr]
-    def __setitem__(self, attr, value):
-        self.__entity.cw_edited[attr] = value
-    def __getattr__(self, attr):
-        return getattr(self.__entity, attr)
-
-
-class EditedEntity(dict):
-    """encapsulate entities attributes being written by an RQL query"""
-    def __init__(self, entity, **kwargs):
-        dict.__init__(self, **kwargs)
-        self.entity = entity
-        self.skip_security = set()
-        self.querier_pending_relations = {}
-        self.saved = False
-
-    def __hash__(self):
-        # dict|set keyable
-        return hash(id(self))
-
-    def __cmp__(self, other):
-        # we don't want comparison by value inherited from dict
-        return cmp(id(self), id(other))
-
-    def __setitem__(self, attr, value):
-        assert attr != 'eid'
-        # don't add attribute into skip_security if already in edited
-        # attributes, else we may accidentaly skip a desired security check
-        if attr not in self:
-            self.skip_security.add(attr)
-        self.edited_attribute(attr, value)
-
-    def __delitem__(self, attr):
-        assert not self.saved, 'too late to modify edited attributes'
-        super(EditedEntity, self).__delitem__(attr)
-        self.entity.cw_attr_cache.pop(attr, None)
-
-    def pop(self, attr, *args):
-        # don't update skip_security by design (think to storage api)
-        assert not self.saved, 'too late to modify edited attributes'
-        value = super(EditedEntity, self).pop(attr, *args)
-        self.entity.cw_attr_cache.pop(attr, *args)
-        return value
-
-    def setdefault(self, attr, default):
-        assert attr != 'eid'
-        # don't add attribute into skip_security if already in edited
-        # attributes, else we may accidentaly skip a desired security check
-        if attr not in self:
-            self[attr] = default
-        return self[attr]
-
-    def update(self, values, skipsec=True):
-        if skipsec:
-            setitem = self.__setitem__
-        else:
-            setitem = self.edited_attribute
-        for attr, value in values.iteritems():
-            setitem(attr, value)
-
-    def edited_attribute(self, attr, value):
-        """attribute being edited by a rql query: should'nt be added to
-        skip_security
-        """
-        assert not self.saved, 'too late to modify edited attributes'
-        super(EditedEntity, self).__setitem__(attr, value)
-        self.entity.cw_attr_cache[attr] = value
-
-    def oldnewvalue(self, attr):
-        """returns the couple (old attr value, new attr value)
-
-        NOTE: will only work in a before_update_entity hook
-        """
-        assert not self.saved, 'too late to get the old value'
-        # get new value and remove from local dict to force a db query to
-        # fetch old value
-        newvalue = self.entity.cw_attr_cache.pop(attr, _MARKER)
-        oldvalue = getattr(self.entity, attr)
-        if newvalue is not _MARKER:
-            self.entity.cw_attr_cache[attr] = newvalue
-        else:
-            newvalue = oldvalue
-        return oldvalue, newvalue
-
-    def set_defaults(self):
-        """set default values according to the schema"""
-        for attr, value in self.entity.e_schema.defaults():
-            if not attr in self:
-                self[str(attr)] = value
-
-    def check(self, creation=False):
-        """check the entity edition against its schema. Only final relation
-        are checked here, constraint on actual relations are checked in hooks
-        """
-        entity = self.entity
-        if creation:
-            # on creations, we want to check all relations, especially
-            # required attributes
-            relations = [rschema for rschema in entity.e_schema.subject_relations()
-                         if rschema.final and rschema.type != 'eid']
-        else:
-            relations = [entity._cw.vreg.schema.rschema(rtype)
-                         for rtype in self]
-        from yams import ValidationError
-        try:
-            entity.e_schema.check(dict_protocol_catcher(entity),
-                                  creation=creation, _=entity._cw._,
-                                  relations=relations)
-        except ValidationError, ex:
-            ex.entity = self.entity
-            raise
-
-    def clone(self):
-        thecopy = EditedEntity(copy(self.entity))
-        thecopy.entity.cw_attr_cache = copy(self.entity.cw_attr_cache)
-        thecopy.entity._cw_related_cache = {}
-        thecopy.update(self, skipsec=False)
-        return thecopy
-
-
 class SSPlanner(object):
     """SingleSourcePlanner: build execution plan for rql queries
 
--- a/server/test/unittest_ldapuser.py	Mon Mar 28 19:31:26 2011 +0200
+++ b/server/test/unittest_ldapuser.py	Mon Mar 28 19:31:45 2011 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
--- a/web/data/cubicweb.ajax.js	Mon Mar 28 19:31:26 2011 +0200
+++ b/web/data/cubicweb.ajax.js	Mon Mar 28 19:31:45 2011 +0200
@@ -283,7 +283,7 @@
  * dictionary, `reqtype` the HTTP request type (get 'GET' or 'POST').
  */
 function loadRemote(url, form, reqtype, sync) {
-    if (!url.toLowerCase().startswith(baseuri())) {
+    if (!url.toLowerCase().startswith(baseuri().toLowerCase())) {
         url = baseuri() + url;
     }
     if (!sync) {