# HG changeset patch
# User Sylvain Thénault
an error occured while interpreting this rql directive: ObjectNotFound(u'toto',)
")) + def test_rql_role_without_vid(self): context = self.context() out = rest_publish(context, ':rql:`Any X WHERE X is CWUser`') diff -r d313666c171e -r cbb0a0ce3795 hooks/syncsources.py --- a/hooks/syncsources.py Wed Jul 27 20:17:45 2011 +0200 +++ b/hooks/syncsources.py Fri Aug 05 14:23:55 2011 +0200 @@ -19,6 +19,7 @@ from socket import gethostname +from logilab.common.decorators import clear_cache from yams.schema import role_name from cubicweb import ValidationError @@ -66,7 +67,7 @@ SourceRemovedOp(self._cw, uri=self.entity.name) -class SourceUpdatedOp(hook.DataOperationMixIn, hook.Operation): +class SourceConfigUpdatedOp(hook.DataOperationMixIn, hook.Operation): def precommit_event(self): self.__processed = [] @@ -79,13 +80,45 @@ for source, conf in self.__processed: source.repo_source.update_config(source, conf) + +class SourceRenamedOp(hook.LateOperation): + + def precommit_event(self): + source = self.session.repo.sources_by_uri[self.oldname] + if source.copy_based_source: + sql = 'UPDATE entities SET asource=%(newname)s WHERE asource=%(oldname)s' + else: + sql = 'UPDATE entities SET source=%(newname)s, asource=%(newname)s WHERE source=%(oldname)s' + self.session.system_sql(sql, {'oldname': self.oldname, + 'newname': self.newname}) + + def postcommit_event(self): + repo = self.session.repo + # XXX race condition + source = repo.sources_by_uri.pop(self.oldname) + source.uri = self.newname + source.public_config['uri'] = self.newname + repo.sources_by_uri[self.newname] = source + repo._type_source_cache.clear() + clear_cache(repo, 'source_defs') + if not source.copy_based_source: + repo._extid_cache.clear() + repo._clear_planning_caches() + for cnxset in repo.cnxsets: + cnxset.source_cnxs[self.oldname] = cnxset.source_cnxs.pop(self.oldname) + + class SourceUpdatedHook(SourceHook): __regid__ = 'cw.sources.configupdate' __select__ = SourceHook.__select__ & is_instance('CWSource') - events = ('after_update_entity',) + events = ('before_update_entity',) def __call__(self): if 'config' in self.entity.cw_edited: - SourceUpdatedOp.get_instance(self._cw).add_data(self.entity) + SourceConfigUpdatedOp.get_instance(self._cw).add_data(self.entity) + if 'name' in self.entity.cw_edited: + oldname, newname = self.entity.cw_edited.oldnewvalue('name') + SourceRenamedOp(self._cw, oldname=oldname, newname=newname) + class SourceHostConfigUpdatedHook(SourceHook): __regid__ = 'cw.sources.hostconfigupdate' @@ -97,7 +130,7 @@ not 'config' in self.entity.cw_edited: return try: - SourceUpdatedOp.get_instance(self._cw).add_data(self.entity.cwsource) + SourceConfigUpdatedOp.get_instance(self._cw).add_data(self.entity.cwsource) except IndexError: # XXX no source linked to the host config yet pass diff -r d313666c171e -r cbb0a0ce3795 i18n/de.po --- a/i18n/de.po Wed Jul 27 20:17:45 2011 +0200 +++ b/i18n/de.po Fri Aug 05 14:23:55 2011 +0200 @@ -1250,6 +1250,9 @@ msgid "auto" msgstr "automatisch" +msgid "autocomputed attribute used to ensure transition coherency" +msgstr "" + msgid "automatic" msgstr "automatisch" @@ -2288,9 +2291,6 @@ msgid "eid" msgstr "" -msgid "email address to use for notification" -msgstr "E-Mail-Adresse für Mitteilungen." - msgid "emails successfully sent" msgstr "E-Mails erfolgreich versandt." @@ -2619,6 +2619,18 @@ msgid "groups" msgstr "Gruppen" +msgid "groups allowed to add entities/relations of this type" +msgstr "" + +msgid "groups allowed to delete entities/relations of this type" +msgstr "" + +msgid "groups allowed to read entities/relations of this type" +msgstr "" + +msgid "groups allowed to update entities/relations of this type" +msgstr "" + msgid "groups grant permissions to the user" msgstr "die Gruppen geben dem Nutzer Rechte" @@ -3604,6 +3616,18 @@ msgid "right" msgstr "rechts" +msgid "rql expression allowing to add entities/relations of this type" +msgstr "" + +msgid "rql expression allowing to delete entities/relations of this type" +msgstr "" + +msgid "rql expression allowing to read entities/relations of this type" +msgstr "" + +msgid "rql expression allowing to update entities/relations of this type" +msgstr "" + msgid "rql expressions" msgstr "RQL-Ausdrücke" @@ -4323,6 +4347,9 @@ msgid "user preferences" msgstr "Nutzereinstellungen" +msgid "user's email account" +msgstr "" + msgid "users" msgstr "Nutzer" @@ -4521,3 +4548,6 @@ #, python-format msgid "you should un-inline relation %s which is supported and may be crossed " msgstr "" + +#~ msgid "email address to use for notification" +#~ msgstr "E-Mail-Adresse für Mitteilungen." diff -r d313666c171e -r cbb0a0ce3795 i18n/en.po --- a/i18n/en.po Wed Jul 27 20:17:45 2011 +0200 +++ b/i18n/en.po Fri Aug 05 14:23:55 2011 +0200 @@ -1205,6 +1205,9 @@ msgid "auto" msgstr "automatic" +msgid "autocomputed attribute used to ensure transition coherency" +msgstr "" + msgid "automatic" msgstr "" @@ -2233,9 +2236,6 @@ msgid "eid" msgstr "" -msgid "email address to use for notification" -msgstr "" - msgid "emails successfully sent" msgstr "" @@ -2554,6 +2554,18 @@ msgid "groups" msgstr "" +msgid "groups allowed to add entities/relations of this type" +msgstr "" + +msgid "groups allowed to delete entities/relations of this type" +msgstr "" + +msgid "groups allowed to read entities/relations of this type" +msgstr "" + +msgid "groups allowed to update entities/relations of this type" +msgstr "" + msgid "groups grant permissions to the user" msgstr "" @@ -3511,6 +3523,18 @@ msgid "right" msgstr "" +msgid "rql expression allowing to add entities/relations of this type" +msgstr "" + +msgid "rql expression allowing to delete entities/relations of this type" +msgstr "" + +msgid "rql expression allowing to read entities/relations of this type" +msgstr "" + +msgid "rql expression allowing to update entities/relations of this type" +msgstr "" + msgid "rql expressions" msgstr "" @@ -4209,6 +4233,9 @@ msgid "user preferences" msgstr "" +msgid "user's email account" +msgstr "" + msgid "users" msgstr "" diff -r d313666c171e -r cbb0a0ce3795 i18n/es.po --- a/i18n/es.po Wed Jul 27 20:17:45 2011 +0200 +++ b/i18n/es.po Fri Aug 05 14:23:55 2011 +0200 @@ -1261,6 +1261,9 @@ msgid "auto" msgstr "Automático" +msgid "autocomputed attribute used to ensure transition coherency" +msgstr "" + msgid "automatic" msgstr "Automático" @@ -2327,9 +2330,6 @@ msgid "eid" msgstr "eid" -msgid "email address to use for notification" -msgstr "Dirección electrónica a utilizarse para notificar" - msgid "emails successfully sent" msgstr "Mensajes enviados con éxito" @@ -2661,6 +2661,18 @@ msgid "groups" msgstr "Grupos" +msgid "groups allowed to add entities/relations of this type" +msgstr "" + +msgid "groups allowed to delete entities/relations of this type" +msgstr "" + +msgid "groups allowed to read entities/relations of this type" +msgstr "" + +msgid "groups allowed to update entities/relations of this type" +msgstr "" + msgid "groups grant permissions to the user" msgstr "Los grupos otorgan los permisos al usuario" @@ -3654,6 +3666,18 @@ msgid "right" msgstr "Derecha" +msgid "rql expression allowing to add entities/relations of this type" +msgstr "" + +msgid "rql expression allowing to delete entities/relations of this type" +msgstr "" + +msgid "rql expression allowing to read entities/relations of this type" +msgstr "" + +msgid "rql expression allowing to update entities/relations of this type" +msgstr "" + msgid "rql expressions" msgstr "Expresiones RQL" @@ -4373,6 +4397,9 @@ msgid "user preferences" msgstr "Preferencias" +msgid "user's email account" +msgstr "" + msgid "users" msgstr "Usuarios" @@ -4576,3 +4603,6 @@ #~ msgctxt "CWAttribute" #~ msgid "cw_schema_object" #~ msgstr "mapeado por" + +#~ msgid "email address to use for notification" +#~ msgstr "Dirección electrónica a utilizarse para notificar" diff -r d313666c171e -r cbb0a0ce3795 i18n/fr.po --- a/i18n/fr.po Wed Jul 27 20:17:45 2011 +0200 +++ b/i18n/fr.po Fri Aug 05 14:23:55 2011 +0200 @@ -164,7 +164,7 @@ #, python-format msgid "" "'%s' action for in_state relation should at least have 'linkattr=name' option" -msgstr "" +msgstr "l'action '%s' pour la relation in_state doit au moins avoir l'option 'linkattr=name'" #, python-format msgid "'%s' action requires 'linkattr' option" @@ -1174,7 +1174,7 @@ #, python-format msgid "allowed values for \"action\" are %s" -msgstr "" +msgstr "les valeurs autorisées pour \"action\" sont %s" msgid "allowed_transition" msgstr "transitions autorisées" @@ -1259,6 +1259,9 @@ msgid "auto" msgstr "automatique" +msgid "autocomputed attribute used to ensure transition coherency" +msgstr "attribut calculé automatiquement pour assurer la cohérence de la transition" + msgid "automatic" msgstr "automatique" @@ -2326,9 +2329,6 @@ msgid "eid" msgstr "eid" -msgid "email address to use for notification" -msgstr "adresse email à utiliser pour la notification" - msgid "emails successfully sent" msgstr "courriels envoyés avec succès" @@ -2660,6 +2660,18 @@ msgid "groups" msgstr "groupes" +msgid "groups allowed to add entities/relations of this type" +msgstr "groupes autorisés à ajouter des entités/relations de ce type" + +msgid "groups allowed to delete entities/relations of this type" +msgstr "groupes autorisés à supprimer des entités/relations de ce type" + +msgid "groups allowed to read entities/relations of this type" +msgstr "groupes autorisés à lire des entités/relations de ce type" + +msgid "groups allowed to update entities/relations of this type" +msgstr "groupes autorisés à mettre à jour des entités/relations de ce type" + msgid "groups grant permissions to the user" msgstr "les groupes donnent des permissions à l'utilisateur" @@ -3239,10 +3251,10 @@ msgstr "aucune permission associée" msgid "no content next link" -msgstr "" +msgstr "pas de lien 'suivant'" msgid "no content prev link" -msgstr "" +msgstr "pas de lien 'précédent'" msgid "no edited fields specified" msgstr "aucun champ à éditer spécifié" @@ -3655,6 +3667,18 @@ msgid "right" msgstr "droite" +msgid "rql expression allowing to add entities/relations of this type" +msgstr "expression rql autorisant à ajouter des entités/relations de ce type" + +msgid "rql expression allowing to delete entities/relations of this type" +msgstr "expression rql autorisant à supprimer des entités/relations de ce type" + +msgid "rql expression allowing to read entities/relations of this type" +msgstr "expression rql autorisant à lire des entités/relations de ce type" + +msgid "rql expression allowing to update entities/relations of this type" +msgstr "expression rql autorisant à mettre à jour des entités/relations de ce type" + msgid "rql expressions" msgstr "conditions rql" @@ -4013,10 +4037,10 @@ msgstr "la valeur \"%s\" est déjà utilisée, veuillez utiliser une autre valeur" msgid "there is no next page" -msgstr "" +msgstr "il n'y a pas de page suivante" msgid "there is no previous page" -msgstr "" +msgstr "il n'y a pas de page précédente" msgid "this action is not reversible!" msgstr "" @@ -4372,6 +4396,9 @@ msgid "user preferences" msgstr "préférences utilisateur" +msgid "user's email account" +msgstr "email de l'utilisateur" + msgid "users" msgstr "utilisateurs" @@ -4572,7 +4599,3 @@ msgstr "" "vous devriez enlevé la mise en ligne de la relation %s qui est supportée et " "peut-être croisée" - -#~ msgctxt "CWAttribute" -#~ msgid "cw_schema_object" -#~ msgstr "mappé par" diff -r d313666c171e -r cbb0a0ce3795 misc/migration/bootstrapmigration_repository.py --- a/misc/migration/bootstrapmigration_repository.py Wed Jul 27 20:17:45 2011 +0200 +++ b/misc/migration/bootstrapmigration_repository.py Fri Aug 05 14:23:55 2011 +0200 @@ -36,7 +36,7 @@ commit(ask_confirm=False) if applcubicwebversion <= (3, 13, 0) and cubicwebversion >= (3, 13, 1): - sql('ALTER TABLE entities ADD COLUMN asource VARCHAR(64)') + sql('ALTER TABLE entities ADD asource VARCHAR(64)') sql('UPDATE entities SET asource=cw_name ' 'FROM cw_CWSource, cw_source_relation ' 'WHERE entities.eid=cw_source_relation.eid_from AND cw_source_relation.eid_to=cw_CWSource.cw_eid') diff -r d313666c171e -r cbb0a0ce3795 schemas/base.py --- a/schemas/base.py Wed Jul 27 20:17:45 2011 +0200 +++ b/schemas/base.py Fri Aug 05 14:23:55 2011 +0200 @@ -42,12 +42,6 @@ firstname = String(maxsize=64) surname = String(maxsize=64) last_login_time = Datetime(description=_('last connection date')) - # allowing an email to be the primary email of multiple entities is necessary for - # test at least :-/ - primary_email = SubjectRelation('EmailAddress', cardinality='??', - description=_('email address to use for notification')) - use_email = SubjectRelation('EmailAddress', cardinality='*?', composite='subject') - in_group = SubjectRelation('CWGroup', cardinality='+*', constraints=[RQLConstraint('NOT O name "owners"')], description=_('groups grant permissions to the user')) @@ -71,17 +65,35 @@ to indicate which is the preferred form.')) class use_email(RelationType): - """ """ + fulltext_container = 'subject' + + +class use_email_relation(RelationDefinition): + """user's email account""" + name = "use_email" __permissions__ = { 'read': ('managers', 'users', 'guests',), 'add': ('managers', RRQLExpression('U has_update_permission S'),), 'delete': ('managers', RRQLExpression('U has_update_permission S'),), } - fulltext_container = 'subject' + subject = "CWUser" + object = "EmailAddress" + cardinality = '*?' + composite = 'subject' + -class primary_email(RelationType): +class primary_email(RelationDefinition): """the prefered email""" - __permissions__ = use_email.__permissions__ + __permissions__ = { + 'read': ('managers', 'users', 'guests',), + 'add': ('managers', RRQLExpression('U has_update_permission S'),), + 'delete': ('managers', RRQLExpression('U has_update_permission S'),), + } + subject = "CWUser" + object = "EmailAddress" + cardinality = '??' + constraints= [RQLConstraint('S use_email O')] + class prefered_form(RelationType): __permissions__ = { diff -r d313666c171e -r cbb0a0ce3795 server/repository.py --- a/server/repository.py Wed Jul 27 20:17:45 2011 +0200 +++ b/server/repository.py Fri Aug 05 14:23:55 2011 +0200 @@ -505,12 +505,7 @@ This is a public method, not requiring a session id. """ - try: - # necessary to support pickling used by pyro - self.schema.__hashmode__ = 'pickle' - return self.schema - finally: - self.schema.__hashmode__ = None + return self.schema def get_cubes(self): """Return the list of cubes used by this instance. diff -r d313666c171e -r cbb0a0ce3795 server/rqlannotation.py --- a/server/rqlannotation.py Wed Jul 27 20:17:45 2011 +0200 +++ b/server/rqlannotation.py Fri Aug 05 14:23:55 2011 +0200 @@ -109,8 +109,9 @@ ostinfo = rhs.children[0].variable.stinfo else: ostinfo = lhs.variable.stinfo - if not any(orel for orel in ostinfo['relations'] - if orel.optional and orel is not rel): + if not (ostinfo.get('optcomparisons') or + any(orel for orel in ostinfo['relations'] + if orel.optional and orel is not rel)): break if rschema.final or (onlhs and rschema.inlined): if rschema.type != 'has_text': diff -r d313666c171e -r cbb0a0ce3795 server/session.py --- a/server/session.py Wed Jul 27 20:17:45 2011 +0200 +++ b/server/session.py Fri Aug 05 14:23:55 2011 +0200 @@ -1180,7 +1180,8 @@ def _build_descr(self, result, basedescription, todetermine): description = [] etype_from_eid = self.describe - for row in result: + todel = [] + for i, row in enumerate(result): row_descr = basedescription[:] for index, isfinal in todetermine: value = row[index] @@ -1194,10 +1195,14 @@ try: row_descr[index] = etype_from_eid(value)[0] except UnknownEid: - self.critical('wrong eid %s in repository, you should ' - 'db-check the database' % value) - row_descr[index] = row[index] = None - description.append(tuple(row_descr)) + self.error('wrong eid %s in repository, you should ' + 'db-check the database' % value) + todel.append(i) + break + else: + description.append(tuple(row_descr)) + for i in reversed(todel): + del result[i] return description # deprecated ############################################################### diff -r d313666c171e -r cbb0a0ce3795 server/sources/datafeed.py --- a/server/sources/datafeed.py Wed Jul 27 20:17:45 2011 +0200 +++ b/server/sources/datafeed.py Fri Aug 05 14:23:55 2011 +0200 @@ -218,7 +218,7 @@ """ entity = super(DataFeedSource, self).before_entity_insertion( session, lid, etype, eid, sourceparams) - entity.cw_edited['cwuri'] = unicode(lid) + entity.cw_edited['cwuri'] = lid.decode('utf-8') entity.cw_edited.set_defaults() sourceparams['parser'].before_entity_copy(entity, sourceparams) return entity @@ -275,6 +275,8 @@ else: source = self.source sourceparams['parser'] = self + if isinstance(uri, unicode): + uri = uri.encode('utf-8') try: eid = session.repo.extid2eid(source, str(uri), etype, session, complete=False, commit=False, @@ -351,10 +353,10 @@ def parse(self, url): if url.startswith('http'): - from cubicweb.sobjects.parsers import HOST_MAPPING - for mappedurl in HOST_MAPPING: + from cubicweb.sobjects.parsers import URL_MAPPING + for mappedurl in URL_MAPPING: if url.startswith(mappedurl): - url = url.replace(mappedurl, HOST_MAPPING[mappedurl], 1) + url = url.replace(mappedurl, URL_MAPPING[mappedurl], 1) break self.source.info('GET %s', url) stream = _OPENER.open(url) diff -r d313666c171e -r cbb0a0ce3795 server/sources/rql2sql.py --- a/server/sources/rql2sql.py Wed Jul 27 20:17:45 2011 +0200 +++ b/server/sources/rql2sql.py Fri Aug 05 14:23:55 2011 +0200 @@ -1238,35 +1238,47 @@ def _visit_outer_join_inlined_relation(self, relation, rschema): - leftvar, leftconst, rightvar, rightconst = relation_info(relation) - assert not (leftconst and rightconst), "doesn't make sense" - if relation.optional != 'right': - leftvar, rightvar = rightvar, leftvar - leftconst, rightconst = rightconst, leftconst - outertype = 'FULL' if relation.optional == 'both' else 'LEFT' - leftalias = self._var_table(leftvar) + lhsvar, lhsconst, rhsvar, rhsconst = relation_info(relation) + assert not (lhsconst and rhsconst), "doesn't make sense" attr = 'eid' if relation.r_type == 'identity' else relation.r_type - lhs, rhs = relation.get_variable_parts() + lhsalias = self._var_table(lhsvar) + rhsalias = rhsvar and self._var_table(rhsvar) try: - lhssql = self._varmap['%s.%s' % (lhs.name, attr)] + lhssql = self._varmap['%s.%s' % (lhsvar.name, attr)] except KeyError: - lhssql = '%s.%s%s' % (self._var_table(lhs.variable), SQL_PREFIX, attr) - if rightvar is not None: - rightalias = self._var_table(rightvar) - if rightalias is None: - if rightconst is not None: - # inlined relation with invariant as rhs - condition = '%s=%s' % (lhssql, rightconst.accept(self)) - if relation.r_type != 'identity': - condition = '(%s OR %s IS NULL)' % (condition, lhssql) - if not leftvar.stinfo.get('optrelations'): - return condition - self._state.add_outer_join_condition(leftalias, condition) - return - if leftalias is None: - leftalias = leftvar._q_sql.split('.', 1)[0] - self._state.replace_tables_by_outer_join( - leftalias, rightalias, outertype, '%s=%s' % (lhssql, rhs.accept(self))) + if lhsalias is None: + lhssql = lhsconst.accept(self) + else: + lhssql = '%s.%s%s' % (lhsalias, SQL_PREFIX, attr) + condition = '%s=%s' % (lhssql, (rhsconst or rhsvar).accept(self)) + # this is not a typo, rhs optional variable means lhs outer join and vice-versa + if relation.optional == 'left': + lhsvar, rhsvar = rhsvar, lhsvar + lhsconst, rhsconst = rhsconst, lhsconst + lhsalias, rhsalias = rhsalias, lhsalias + outertype = 'LEFT' + elif relation.optional == 'both': + outertype = 'FULL' + else: + outertype = 'LEFT' + if rhsalias is None: + if rhsconst is not None: + # inlined relation with invariant as rhs + if relation.r_type != 'identity': + condition = '(%s OR %s IS NULL)' % (condition, lhssql) + if not lhsvar.stinfo.get('optrelations'): + return condition + self._state.add_outer_join_condition(lhsalias, condition) + return + if lhsalias is None: + if lhsconst is not None and not rhsvar.stinfo.get('optrelations'): + return condition + lhsalias = lhsvar._q_sql.split('.', 1)[0] + if lhsalias == rhsalias: + self._state.add_outer_join_condition(lhsalias, condition) + else: + self._state.replace_tables_by_outer_join( + lhsalias, rhsalias, outertype, condition) return '' def _visit_var_attr_relation(self, relation, rhs_vars): @@ -1442,6 +1454,10 @@ pass return '(%s %s %s)'% (lhs.accept(self), operator, rhs.accept(self)) + def visit_unaryexpression(self, uexpr): + """generate SQL for a unary expression""" + return '%s%s'% (uexpr.operator, uexpr.children[0].accept(self)) + def visit_function(self, func): """generate SQL name for a function""" if func.name == 'FTIRANK': diff -r d313666c171e -r cbb0a0ce3795 server/test/unittest_datafeed.py --- a/server/test/unittest_datafeed.py Wed Jul 27 20:17:45 2011 +0200 +++ b/server/test/unittest_datafeed.py Fri Aug 05 14:23:55 2011 +0200 @@ -94,9 +94,26 @@ self.assertTrue(dfsource.latest_retrieval) self.assertTrue(dfsource.fresh()) + # test_rename_source + req = self.request() + req.execute('SET S name "myrenamedfeed" WHERE S is CWSource, S name "myfeed"') + self.commit() + entity = self.execute('Card X').get_entity(0, 0) + self.assertEqual(entity.cwuri, 'http://www.cubicweb.org/') + self.assertEqual(entity.cw_source[0].name, 'myrenamedfeed') + self.assertEqual(entity.cw_metainformation(), + {'type': 'Card', + 'source': {'uri': 'myrenamedfeed', 'type': 'datafeed', 'use-cwuri-as-url': True}, + 'extid': 'http://www.cubicweb.org/'} + ) + self.assertEqual(self.repo._type_source_cache[entity.eid], + ('Card', 'system', 'http://www.cubicweb.org/', 'myrenamedfeed')) + self.assertEqual(self.repo._extid_cache[('http://www.cubicweb.org/', 'system')], + entity.eid) + # test_delete_source req = self.request() - req.execute('DELETE CWSource S WHERE S name "myfeed"') + req.execute('DELETE CWSource S WHERE S name "myrenamedfeed"') self.commit() self.failIf(self.execute('Card X WHERE X title "cubicweb.org"')) self.failIf(self.execute('Any X WHERE X has_text "cubicweb.org"')) diff -r d313666c171e -r cbb0a0ce3795 server/test/unittest_repository.py --- a/server/test/unittest_repository.py Wed Jul 27 20:17:45 2011 +0200 +++ b/server/test/unittest_repository.py Fri Aug 05 14:23:55 2011 +0200 @@ -366,7 +366,6 @@ schema = cnx.get_schema() self.failUnless(cnx.vreg) self.failUnless('etypes'in cnx.vreg) - self.assertEqual(schema.__hashmode__, None) cu = cnx.cursor() rset = cu.execute('Any U,G WHERE U in_group G') user = iter(rset.entities()).next() diff -r d313666c171e -r cbb0a0ce3795 server/test/unittest_rql2sql.py --- a/server/test/unittest_rql2sql.py Wed Jul 27 20:17:45 2011 +0200 +++ b/server/test/unittest_rql2sql.py Fri Aug 05 14:23:55 2011 +0200 @@ -88,7 +88,6 @@ ] BASIC = [ - ("Any AS WHERE AS is Affaire", '''SELECT _AS.cw_eid FROM cw_Affaire AS _AS'''), @@ -201,7 +200,12 @@ ('Any X WHERE X title V, NOT X wikiid V, NOT X title "parent", X is Card', '''SELECT _X.cw_eid FROM cw_Card AS _X -WHERE NOT (_X.cw_wikiid=_X.cw_title) AND NOT (_X.cw_title=parent)''') +WHERE NOT (_X.cw_wikiid=_X.cw_title) AND NOT (_X.cw_title=parent)'''), + + ("Any -AS WHERE AS is Affaire", + '''SELECT -_AS.cw_eid +FROM cw_Affaire AS _AS'''), + ] BASIC_WITH_LIMIT = [ @@ -972,7 +976,7 @@ ('Any CASE, CALIBCFG, CFG ' 'WHERE CASE eid 1, CFG ecrit_par CASE, CALIBCFG? ecrit_par CASE', '''SELECT _CFG.cw_ecrit_par, _CALIBCFG.cw_eid, _CFG.cw_eid -FROM cw_Note AS _CFG LEFT OUTER JOIN cw_Note AS _CALIBCFG ON (_CALIBCFG.cw_ecrit_par=_CFG.cw_ecrit_par) +FROM cw_Note AS _CFG LEFT OUTER JOIN cw_Note AS _CALIBCFG ON (_CALIBCFG.cw_ecrit_par=1) WHERE _CFG.cw_ecrit_par=1'''), ('Any U,G WHERE U login UL, G name GL, G is CWGroup HAVING UPPER(UL)=UPPER(GL)?', @@ -986,6 +990,17 @@ ('Any U,G WHERE U login UL, G name GL, G is CWGroup HAVING UPPER(UL)?=UPPER(GL)?', '''SELECT _U.cw_eid, _G.cw_eid FROM cw_CWUser AS _U FULL OUTER JOIN cw_CWGroup AS _G ON (UPPER(_U.cw_login)=UPPER(_G.cw_name))'''), + + ('Any H, COUNT(X), SUM(XCE)/1000 ' + 'WHERE X type "0", X date XSCT, X para XCE, X? ecrit_par F, F eid 999999, F is Personne, ' + 'DH is Affaire, DH ref H ' + 'HAVING XSCT?=H', + '''SELECT _DH.cw_ref, COUNT(_X.cw_eid), (SUM(_X.cw_para) / 1000) +FROM cw_Affaire AS _DH LEFT OUTER JOIN cw_Note AS _X ON (_X.cw_date=_DH.cw_ref AND _X.cw_type=0 AND _X.cw_ecrit_par=999999)'''), + + ('Any C WHERE X ecrit_par C?, X? inline1 F, F eid 1, X type XT, Z is Personne, Z nom ZN HAVING ZN=XT?', + '''SELECT _X.cw_ecrit_par +FROM cw_Personne AS _Z LEFT OUTER JOIN cw_Note AS _X ON (_Z.cw_nom=_X.cw_type AND _X.cw_inline1=1)'''), ] VIRTUAL_VARS = [ @@ -1721,7 +1736,7 @@ class SqlServer2005SQLGeneratorTC(PostgresSQLGeneratorTC): backend = 'sqlserver2005' def _norm_sql(self, sql): - return sql.strip().replace(' SUBSTR', ' SUBSTRING').replace(' || ', ' + ').replace(' ILIKE ', ' LIKE ') + return sql.strip().replace(' SUBSTR', ' SUBSTRING').replace(' || ', ' + ').replace(' ILIKE ', ' LIKE ').replace('TRUE', '1').replace('FALSE', '0') def test_has_text(self): for t in self._parse(HAS_TEXT_LG_INDEXER): diff -r d313666c171e -r cbb0a0ce3795 server/test/unittest_session.py --- a/server/test/unittest_session.py Wed Jul 27 20:17:45 2011 +0200 +++ b/server/test/unittest_session.py Fri Aug 05 14:23:55 2011 +0200 @@ -78,5 +78,15 @@ self.assertEqual(session._tx_data, {}) self.assertEqual(session.cnxset, None) + def test_build_descr(self): + rset = self.execute('(Any U,L WHERE U login L) UNION (Any G,N WHERE G name N, G is CWGroup)') + orig_length = len(rset) + rset.rows[0][0] = 9999999 + description = self.session.build_description(rset.syntax_tree(), None, rset.rows) + self.assertEqual(len(description), orig_length - 1) + self.assertEqual(len(rset.rows), orig_length - 1) + self.failIf(rset.rows[0][0] == 9999999) + + if __name__ == '__main__': unittest_main() diff -r d313666c171e -r cbb0a0ce3795 sobjects/parsers.py --- a/sobjects/parsers.py Wed Jul 27 20:17:45 2011 +0200 +++ b/sobjects/parsers.py Fri Aug 05 14:23:55 2011 +0200 @@ -459,10 +459,10 @@ def registration_callback(vreg): vreg.register_all(globals().values(), __name__) - global HOST_MAPPING - HOST_MAPPING = {} + global URL_MAPPING + URL_MAPPING = {} if vreg.config.apphome: - host_mapping_file = osp.join(vreg.config.apphome, 'hostmapping.py') - if osp.exists(host_mapping_file): - HOST_MAPPING = eval(file(host_mapping_file).read()) - vreg.info('using host mapping %s from %s', HOST_MAPPING, host_mapping_file) + url_mapping_file = osp.join(vreg.config.apphome, 'urlmapping.py') + if osp.exists(url_mapping_file): + URL_MAPPING = eval(file(url_mapping_file).read()) + vreg.info('using url mapping %s from %s', URL_MAPPING, url_mapping_file) diff -r d313666c171e -r cbb0a0ce3795 web/data/cubicweb.reset.css --- a/web/data/cubicweb.reset.css Wed Jul 27 20:17:45 2011 +0200 +++ b/web/data/cubicweb.reset.css Fri Aug 05 14:23:55 2011 +0200 @@ -1,53 +1,48 @@ -/* http://meyerweb.com/eric/tools/css/reset/ */ -/* v1.0 | 20080212 */ +/* http://meyerweb.com/eric/tools/css/reset/ + v2.0 | 20110126 + License: none (public domain) +*/ html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, -del, dfn, em, font, img, ins, kbd, q, s, samp, +del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, -table, caption, tbody, tfoot, thead, tr, th, td { - margin: 0; - padding: 0; - border: 0; - outline: 0; - font-size: 100%; - vertical-align: baseline; - background: transparent; +table, caption, tbody, tfoot, thead, tr, th, td, +article, aside, canvas, details, embed, +figure, figcaption, footer, header, hgroup, +menu, nav, output, ruby, section, summary, +time, mark, audio, video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; +} +/* HTML5 display-role reset for older browsers */ +article, aside, details, figcaption, figure, +footer, header, hgroup, menu, nav, section { + display: block; } body { - line-height: 1; + line-height: 1; } ol, ul { - list-style: none; + list-style: none; } blockquote, q { - quotes: none; + quotes: none; } blockquote:before, blockquote:after, q:before, q:after { - content: ''; - content: none; -} - -/* remember to define focus styles! */ -:focus { - outline: 0; + content: ''; + content: none; } - -/* remember to highlight inserts somehow! */ -ins { - text-decoration: none; -} -del { - text-decoration: line-through; -} - -/* tables still need 'cellspacing="0"' in the markup */ table { - border-collapse: collapse; - border-spacing: 0; + border-collapse: collapse; + border-spacing: 0; } \ No newline at end of file diff -r d313666c171e -r cbb0a0ce3795 web/test/unittest_views_editforms.py --- a/web/test/unittest_views_editforms.py Wed Jul 27 20:17:45 2011 +0200 +++ b/web/test/unittest_views_editforms.py Fri Aug 05 14:23:55 2011 +0200 @@ -77,9 +77,9 @@ # (appears here while expected in hidden self.assertListEqual([x for x in rbc(e, 'main', 'relations') if x != ('tags', 'object')], - [('primary_email', 'subject'), - ('connait', 'subject'), + [('connait', 'subject'), ('custom_workflow', 'subject'), + ('primary_email', 'subject'), ('checked_by', 'object'), ]) self.assertListEqual(rbc(e, 'main', 'inlined'), diff -r d313666c171e -r cbb0a0ce3795 web/views/actions.py --- a/web/views/actions.py Wed Jul 27 20:17:45 2011 +0200 +++ b/web/views/actions.py Fri Aug 05 14:23:55 2011 +0200 @@ -135,8 +135,13 @@ params = self._cw.form.copy() for param in ('vid', '__message') + controller.NAV_FORM_PARAMETERS: params.pop(param, None) - return self._cw.build_url(self._cw.relative_path(includeparams=False), - **params) + if self._cw.json_request: + path = 'view' + if self.cw_rset is not None: + params = {'rql': self.cw_rset.printable_rql()} + else: + path = self._cw.relative_path(includeparams=False) + return self._cw.build_url(path, **params) class ModifyAction(action.Action): @@ -163,7 +168,7 @@ order = 10 def url(self): - return self._cw.build_url('view', rql=self.cw_rset.rql, vid='muledit') + return self._cw.build_url('view', rql=self.cw_rset.printable_rql(), vid='muledit') # generic "more" actions ####################################################### diff -r d313666c171e -r cbb0a0ce3795 web/views/cwuser.py --- a/web/views/cwuser.py Wed Jul 27 20:17:45 2011 +0200 +++ b/web/views/cwuser.py Fri Aug 05 14:23:55 2011 +0200 @@ -168,6 +168,10 @@ class CWUserManagementView(StartupView): __regid__ = 'cw.user-management' + # XXX one could wish to display for instance only user's firstname/surname + # for non managers but filtering out NULL cause crash with an ldapuser + # source. + __select__ = StartupView.__select__ & match_user_groups('managers') rql = ('Any U,USN,F,S,U,UAA,UDS, L,UAA,UDSN ORDERBY L WHERE U is CWUser, ' 'U login L, U firstname F, U surname S, ' 'U in_state US, US name USN, ' diff -r d313666c171e -r cbb0a0ce3795 web/views/emailaddress.py --- a/web/views/emailaddress.py Wed Jul 27 20:17:45 2011 +0200 +++ b/web/views/emailaddress.py Fri Aug 05 14:23:55 2011 +0200 @@ -15,9 +15,8 @@ # # You should have received a copy of the GNU Lesser General Public License along # with CubicWeb. If not, see