# HG changeset patch # User Rémi Cardona # Date 1429690094 -7200 # Node ID 729f36a1bcfa49ee4343d1e83027f619f8d6dd2c # Parent ffb269e603484994cf79843734379cdfdee91c43# Parent e52efb73f9ee5746cf85f498891633be464e267a merge 3.20.6 into 3.21 diff -r ffb269e60348 -r 729f36a1bcfa .hgtags --- a/.hgtags Wed Mar 25 10:10:24 2015 +0100 +++ b/.hgtags Wed Apr 22 10:08:14 2015 +0200 @@ -398,6 +398,13 @@ b7c373d74754f5ba9344575cb179b47282c413b6 cubicweb-version-3.19.9 b7c373d74754f5ba9344575cb179b47282c413b6 cubicweb-debian-version-3.19.9-1 b7c373d74754f5ba9344575cb179b47282c413b6 cubicweb-centos-version-3.19.9-1 +3bab0b9b0ee7355a6fea45c2adca88bffe130e5d cubicweb-version-3.19.10 +3bab0b9b0ee7355a6fea45c2adca88bffe130e5d cubicweb-debian-version-3.19.10-1 +3bab0b9b0ee7355a6fea45c2adca88bffe130e5d cubicweb-centos-version-3.19.10-1 +1ae64186af9448dffbeebdef910c8c7391c04313 cubicweb-version-3.19.11 +1ae64186af9448dffbeebdef910c8c7391c04313 cubicweb-debian-version-3.19.11-1 +1ae64186af9448dffbeebdef910c8c7391c04313 cubicweb-centos-version-3.19.11-1 +6d265ea7d56fe49e9dff261d3b2caf3c2b6f9409 cubicweb-debian-version-3.19.11-2 7e6b7739afe6128589ad51b0318decb767cbae36 cubicweb-version-3.20.0 7e6b7739afe6128589ad51b0318decb767cbae36 cubicweb-debian-version-3.20.0-1 7e6b7739afe6128589ad51b0318decb767cbae36 cubicweb-centos-version-3.20.0-1 @@ -413,3 +420,9 @@ 49831fdc84dc7e7bed01d5e8110a46242b5ccda6 cubicweb-version-3.20.4 49831fdc84dc7e7bed01d5e8110a46242b5ccda6 cubicweb-debian-version-3.20.4-1 49831fdc84dc7e7bed01d5e8110a46242b5ccda6 cubicweb-centos-version-3.20.4-1 +51aa56e7d507958b3326abbb6a31d0e6dde6b47b cubicweb-version-3.20.5 +51aa56e7d507958b3326abbb6a31d0e6dde6b47b cubicweb-debian-version-3.20.5-1 +51aa56e7d507958b3326abbb6a31d0e6dde6b47b cubicweb-centos-version-3.20.5-1 +7f64859dcbcdc6394421b8a5175896ba2e5caeb5 cubicweb-version-3.20.6 +7f64859dcbcdc6394421b8a5175896ba2e5caeb5 cubicweb-debian-version-3.20.6-1 +7f64859dcbcdc6394421b8a5175896ba2e5caeb5 cubicweb-centos-version-3.20.6-1 diff -r ffb269e60348 -r 729f36a1bcfa __init__.py --- a/__init__.py Wed Mar 25 10:10:24 2015 +0100 +++ b/__init__.py Wed Apr 22 10:08:14 2015 +0200 @@ -69,12 +69,12 @@ class Binary(StringIO): """customize StringIO to make sure we don't use unicode""" def __init__(self, buf=''): - assert isinstance(buf, (str, buffer)), \ + assert isinstance(buf, (str, buffer, bytearray)), \ "Binary objects must use raw strings, not %s" % buf.__class__ StringIO.__init__(self, buf) def write(self, data): - assert isinstance(data, (str, buffer)), \ + assert isinstance(data, (str, buffer, bytearray)), \ "Binary objects must use raw strings, not %s" % data.__class__ StringIO.write(self, data) diff -r ffb269e60348 -r 729f36a1bcfa __pkginfo__.py --- a/__pkginfo__.py Wed Mar 25 10:10:24 2015 +0100 +++ b/__pkginfo__.py Wed Apr 22 10:08:14 2015 +0200 @@ -22,7 +22,7 @@ modname = distname = "cubicweb" -numversion = (3, 20, 4) +numversion = (3, 20, 6) version = '.'.join(str(num) for num in numversion) description = "a repository of entities / relations for knowledge management" diff -r ffb269e60348 -r 729f36a1bcfa _exceptions.py --- a/_exceptions.py Wed Mar 25 10:10:24 2015 +0100 +++ b/_exceptions.py Wed Apr 22 10:08:14 2015 +0200 @@ -23,7 +23,7 @@ from logilab.common.decorators import cachedproperty -from yams import ValidationError as ValidationError +from yams import ValidationError # abstract exceptions ######################################################### diff -r ffb269e60348 -r 729f36a1bcfa cubicweb.spec --- a/cubicweb.spec Wed Mar 25 10:10:24 2015 +0100 +++ b/cubicweb.spec Wed Apr 22 10:08:14 2015 +0200 @@ -7,7 +7,7 @@ %endif Name: cubicweb -Version: 3.20.4 +Version: 3.20.6 Release: logilab.1%{?dist} Summary: CubicWeb is a semantic web application framework Source0: http://download.logilab.org/pub/cubicweb/cubicweb-%{version}.tar.gz diff -r ffb269e60348 -r 729f36a1bcfa dataimport.py --- a/dataimport.py Wed Mar 25 10:10:24 2015 +0100 +++ b/dataimport.py Wed Apr 22 10:08:14 2015 +0200 @@ -69,6 +69,7 @@ import cPickle import os.path as osp import inspect +from base64 import b64encode from collections import defaultdict from copy import copy from datetime import date, datetime, time @@ -788,11 +789,11 @@ entity = copy(entity) entity.cw_edited = copy(entity.cw_edited) entity.cw_clear_relation_cache() - self.metagen.init_entity(entity) entity.cw_edited.update(kwargs, skipsec=False) + entity_source, extid = self.metagen.init_entity(entity) cnx = self._cnx self.source.add_entity(cnx, entity) - self.source.add_info(cnx, entity, self.source, None) + self.source.add_info(cnx, entity, entity_source, extid) kwargs = dict() if inspect.getargspec(self.add_relation).keywords: kwargs['subjtype'] = entity.cw_etype @@ -835,16 +836,19 @@ - set(('eid', 'cwuri', 'is', 'is_instance_of', 'cw_source'))) - def __init__(self, cnx, baseurl=None): + def __init__(self, cnx, baseurl=None, source=None): self._cnx = cnx - self.source = cnx.repo.system_source - self.time = datetime.now() if baseurl is None: config = cnx.vreg.config baseurl = config['base-url'] or config.default_base_url() if not baseurl[-1] == '/': baseurl += '/' - self.baseurl = baseurl + self.baseurl = baseurl + if source is None: + source = cnx.repo.system_source + self.source = source + self.create_eid = cnx.repo.system_source.create_eid + self.time = datetime.now() # attributes/relations shared by all entities of the same type self.etype_attrs = [] self.etype_rels = [] @@ -854,6 +858,9 @@ schema = cnx.vreg.schema rschema = schema.rschema for rtype in self.META_RELATIONS: + # skip owned_by / created_by if user is the internal manager + if cnx.user.eid == -1 and rtype in ('owned_by', 'created_by'): + continue if rschema(rtype).final: self.etype_attrs.append(rtype) else: @@ -877,16 +884,24 @@ return entity, rels def init_entity(self, entity): - entity.eid = self.source.create_eid(self._cnx) + entity.eid = self.create_eid(self._cnx) + extid = entity.cw_edited.get('cwuri') for attr in self.entity_attrs: + if attr in entity.cw_edited: + # already set, skip this attribute + continue genfunc = self.generate(attr) if genfunc: entity.cw_edited.edited_attribute(attr, genfunc(entity)) + if isinstance(extid, unicode): + extid = extid.encode('utf-8') + return self.source, extid def generate(self, rtype): return getattr(self, 'gen_%s' % rtype, None) def gen_cwuri(self, entity): + assert self.baseurl, 'baseurl is None while generating cwuri' return u'%s%s' % (self.baseurl, entity.eid) def gen_creation_date(self, entity): diff -r ffb269e60348 -r 729f36a1bcfa debian/changelog --- a/debian/changelog Wed Mar 25 10:10:24 2015 +0100 +++ b/debian/changelog Wed Apr 22 10:08:14 2015 +0200 @@ -1,3 +1,21 @@ +cubicweb (3.20.6-1) unstable; urgency=low + + * new upstream release + + -- Julien Cristau Thu, 02 Apr 2015 10:58:16 +0200 + +cubicweb (3.20.5-2) unstable; urgency=low + + * Fix cubicweb-dev dependencies. + + -- Julien Cristau Fri, 27 Mar 2015 17:22:53 +0100 + +cubicweb (3.20.5-1) unstable; urgency=low + + * new upstream release + + -- Julien Cristau Fri, 27 Mar 2015 14:56:16 +0100 + cubicweb (3.20.4-1) unstable; urgency=low * new upstream release @@ -28,6 +46,24 @@ -- Julien Cristau Tue, 06 Jan 2015 18:11:03 +0100 +cubicweb (3.19.11-2) UNRELEASED; urgency=low + + * Fix cubicweb-dev dependencies. + + -- Julien Cristau Fri, 27 Mar 2015 16:53:20 +0100 + +cubicweb (3.19.11-1) unstable; urgency=low + + * new upstream release + + -- Julien Cristau Wed, 18 Mar 2015 11:55:52 +0100 + +cubicweb (3.19.10-1) unstable; urgency=low + + * New upstream release. + + -- Rémi Cardona Thu, 12 Mar 2015 11:52:01 +0100 + cubicweb (3.19.9-1) unstable; urgency=low * new upstream release diff -r ffb269e60348 -r 729f36a1bcfa debian/control --- a/debian/control Wed Mar 25 10:10:24 2015 +0100 +++ b/debian/control Wed Apr 22 10:08:14 2015 +0200 @@ -202,6 +202,7 @@ ${python:Depends}, cubicweb-server (= ${source:Version}), cubicweb-web (= ${source:Version}), + cubicweb-twisted (= ${source:Version}), python-pysqlite2 Suggests: w3c-dtd-xhtml, diff -r ffb269e60348 -r 729f36a1bcfa debian/watch --- a/debian/watch Wed Mar 25 10:10:24 2015 +0100 +++ b/debian/watch Wed Apr 22 10:08:14 2015 +0200 @@ -1,2 +1,3 @@ version=3 -http://download.logilab.org/pub/cubicweb cubicweb-(.*)\.tar\.gz +opts=uversionmangle=s/(rc|a|b|c)/~$1/ \ +http://pypi.debian.net/cubicweb/cubicweb-(.+)\.(?:zip|tgz|tbz|txz|(?:tar\.(?:gz|bz2|xz))) diff -r ffb269e60348 -r 729f36a1bcfa devtools/devctl.py --- a/devtools/devctl.py Wed Mar 25 10:10:24 2015 +0100 +++ b/devtools/devctl.py Wed Apr 22 10:08:14 2015 +0200 @@ -167,6 +167,7 @@ if not eschema.final: add_msg(w, 'This %s:' % etype) add_msg(w, 'New %s' % etype) + add_msg(w, 'add a %s' % etype) # AddNewAction if libconfig is not None: # processing a cube # As of 3.20.3 we no longer use it, but keeping this string # allows developers to run i18ncube with new cubicweb and still diff -r ffb269e60348 -r 729f36a1bcfa devtools/test/data/cubes/i18ntestcube/i18n/en.po.ref --- a/devtools/test/data/cubes/i18ntestcube/i18n/en.po.ref Wed Mar 25 10:10:24 2015 +0100 +++ b/devtools/test/data/cubes/i18ntestcube/i18n/en.po.ref Wed Apr 22 10:08:14 2015 +0200 @@ -41,6 +41,12 @@ msgid "add ForumThread in_forum Forum object" msgstr "" +msgid "add a Forum" +msgstr "" + +msgid "add a ForumThread" +msgstr "" + msgid "creating ForumThread (ForumThread in_forum Forum %(linkto)s)" msgstr "" diff -r ffb269e60348 -r 729f36a1bcfa devtools/test/unittest_testlib.py --- a/devtools/test/unittest_testlib.py Wed Mar 25 10:10:24 2015 +0100 +++ b/devtools/test/unittest_testlib.py Wed Apr 22 10:08:14 2015 +0200 @@ -28,6 +28,25 @@ from cubicweb.devtools.testlib import CubicWebTC from cubicweb.pytestconf import clean_repo_test_cls +class FakeFormTC(TestCase): + def test_fake_form(self): + class entity: + cw_etype = 'Entity' + eid = 0 + sio = StringIO('hop\n') + form = CubicWebTC.fake_form('import', + {'file': ('filename.txt', sio), + 'encoding': u'utf-8', + }, [(entity, {'field': 'value'})]) + self.assertEqual(form, {'__form_id': 'import', + '__maineid': 0, + '__type:0': 'Entity', + '_cw_entity_fields:0': '__type,field', + '_cw_fields': 'file,encoding', + 'eid': [0], + 'encoding': u'utf-8', + 'field:0': 'value', + 'file': ('filename.txt', sio)}) class WebTestTC(TestCase): diff -r ffb269e60348 -r 729f36a1bcfa devtools/testlib.py --- a/devtools/testlib.py Wed Mar 25 10:10:24 2015 +0100 +++ b/devtools/testlib.py Wed Apr 22 10:08:14 2015 +0200 @@ -44,7 +44,7 @@ from cubicweb import cwconfig, devtools, web, server, repoapi from cubicweb.utils import json from cubicweb.sobjects import notification -from cubicweb.web import Redirect, application +from cubicweb.web import Redirect, application, eid_param from cubicweb.server.hook import SendMailOp from cubicweb.server.session import Session from cubicweb.devtools import SYSTEM_ENTITIES, SYSTEM_RELATIONS, VIEW_VALIDATORS @@ -886,6 +886,43 @@ raise return result + @staticmethod + def fake_form(formid, field_dict=None, entity_field_dicts=()): + """Build _cw.form dictionnary to fake posting of some standard cubicweb form + + * `formid`, the form id, usually form's __regid__ + + * `field_dict`, dictionary of name:value for fields that are not tied to an entity + + * `entity_field_dicts`, list of (entity, dictionary) where dictionary contains name:value + for fields that are not tied to the given entity + """ + assert field_dict or entity_field_dicts, \ + 'field_dict and entity_field_dicts arguments must not be both unspecified' + if field_dict is None: + field_dict = {} + form = {'__form_id': formid} + fields = [] + for field, value in field_dict.items(): + fields.append(field) + form[field] = value + def _add_entity_field(entity, field, value): + entity_fields.append(field) + form[eid_param(field, entity.eid)] = value + for entity, field_dict in entity_field_dicts: + if '__maineid' not in form: + form['__maineid'] = entity.eid + entity_fields = [] + form.setdefault('eid', []).append(entity.eid) + _add_entity_field(entity, '__type', entity.cw_etype) + for field, value in field_dict.items(): + _add_entity_field(entity, field, value) + if entity_fields: + form[eid_param('_cw_entity_fields', entity.eid)] = ','.join(entity_fields) + if fields: + form['_cw_fields'] = ','.join(fields) + return form + @deprecated('[3.19] use .admin_request_from_url instead') def req_from_url(self, url): """parses `url` and builds the corresponding CW-web request diff -r ffb269e60348 -r 729f36a1bcfa doc/book/en/devrepo/datamodel/definition.rst --- a/doc/book/en/devrepo/datamodel/definition.rst Wed Mar 25 10:10:24 2015 +0100 +++ b/doc/book/en/devrepo/datamodel/definition.rst Wed Apr 22 10:08:14 2015 +0200 @@ -244,8 +244,14 @@ .. sourcecode:: python - from yams.constraints import BoundaryConstraint, TODAY - BoundaryConstraint('<=', TODAY()) + from yams.constraints import BoundaryConstraint, TODAY, NOW, Attribute + + class DatedEntity(EntityType): + start = Date(constraints=[BoundaryConstraint('>=', TODAY())]) + end = Date(constraints=[BoundaryConstraint('>=', Attribute('start'))]) + + class Before(EntityType); + last_time = DateTime(constraints=[BoundaryConstraint('<=', NOW())]) * `IntervalBoundConstraint`: allows to specify an interval with included values @@ -259,7 +265,12 @@ * `StaticVocabularyConstraint`: identical to "vocabulary=(...)" -.. XXX Attribute, NOW +Constraints can be dependent on a fixed value (90, Date(2015,3,23)) or a variable. +In this second case, yams can handle : + +* `Attribute`: compare to the value of another attribute. +* `TODAY`: compare to the current Date. +* `NOW`: compare to the current Datetime. RQL Based Constraints ...................... diff -r ffb269e60348 -r 729f36a1bcfa entities/adapters.py --- a/entities/adapters.py Wed Mar 25 10:10:24 2015 +0100 +++ b/entities/adapters.py Wed Apr 22 10:08:14 2015 +0200 @@ -20,6 +20,7 @@ """ __docformat__ = "restructuredtext en" +_ = unicode from itertools import chain from warnings import warn @@ -361,11 +362,13 @@ __select__ = match_exception(UniqueTogetherError) def raise_user_exception(self): - _ = self._cw._ rtypes = self.exc.rtypes - rtypes_msg = {} + errors = {} + msgargs = {} + i18nvalues = [] for rtype in rtypes: - rtypes_msg[rtype] = _('%s is part of violated unicity constraint') % rtype - globalmsg = _('some relations violate a unicity constraint') - rtypes_msg['unicity constraint'] = globalmsg - raise ValidationError(self.entity.eid, rtypes_msg) + errors[rtype] = _('%(KEY-rtype)s is part of violated unicity constraint') + msgargs[rtype + '-rtype'] = rtype + i18nvalues.append(rtype + '-rtype') + errors[''] = _('some relations violate a unicity constraint') + raise ValidationError(self.entity.eid, errors, msgargs=msgargs, i18nvalues=i18nvalues) diff -r ffb269e60348 -r 729f36a1bcfa entities/test/unittest_wfobjs.py --- a/entities/test/unittest_wfobjs.py Wed Mar 25 10:10:24 2015 +0100 +++ b/entities/test/unittest_wfobjs.py Wed Apr 22 10:08:14 2015 +0200 @@ -52,9 +52,9 @@ shell.commit() with self.assertRaises(ValidationError) as cm: wf.add_state(u'foo') - self.assertEqual({'name': u'name is part of violated unicity constraint', - 'state_of': u'state_of is part of violated unicity constraint', - 'unicity constraint': u'some relations violate a unicity constraint'}, + self.assertEqual({'name': u'%(KEY-rtype)s is part of violated unicity constraint', + 'state_of': u'%(KEY-rtype)s is part of violated unicity constraint', + '': u'some relations violate a unicity constraint'}, cm.exception.errors) shell.rollback() # no pb if not in the same workflow @@ -67,9 +67,9 @@ with self.assertRaises(ValidationError) as cm: bar.cw_set(name=u'foo') shell.rollback() - self.assertEqual({'name': u'name is part of violated unicity constraint', - 'state_of': u'state_of is part of violated unicity constraint', - 'unicity constraint': u'some relations violate a unicity constraint'}, + self.assertEqual({'name': u'%(KEY-rtype)s is part of violated unicity constraint', + 'state_of': u'%(KEY-rtype)s is part of violated unicity constraint', + '': u'some relations violate a unicity constraint'}, cm.exception.errors) def test_duplicated_transition(self): @@ -80,9 +80,9 @@ wf.add_transition(u'baz', (foo,), bar, ('managers',)) with self.assertRaises(ValidationError) as cm: wf.add_transition(u'baz', (bar,), foo) - self.assertEqual({'name': u'name is part of violated unicity constraint', - 'transition_of': u'transition_of is part of violated unicity constraint', - 'unicity constraint': u'some relations violate a unicity constraint'}, + self.assertEqual({'name': u'%(KEY-rtype)s is part of violated unicity constraint', + 'transition_of': u'%(KEY-rtype)s is part of violated unicity constraint', + '': u'some relations violate a unicity constraint'}, cm.exception.errors) shell.rollback() # no pb if not in the same workflow @@ -97,9 +97,9 @@ with self.assertRaises(ValidationError) as cm: biz.cw_set(name=u'baz') shell.rollback() - self.assertEqual({'name': u'name is part of violated unicity constraint', - 'transition_of': u'transition_of is part of violated unicity constraint', - 'unicity constraint': u'some relations violate a unicity constraint'}, + self.assertEqual({'name': u'%(KEY-rtype)s is part of violated unicity constraint', + 'transition_of': u'%(KEY-rtype)s is part of violated unicity constraint', + '': u'some relations violate a unicity constraint'}, cm.exception.errors) diff -r ffb269e60348 -r 729f36a1bcfa etwist/twconfig.py --- a/etwist/twconfig.py Wed Mar 25 10:10:24 2015 +0100 +++ b/etwist/twconfig.py Wed Apr 22 10:08:14 2015 +0200 @@ -93,7 +93,7 @@ def default_base_url(self): from socket import getfqdn - return 'http://%s:%s/' % (self['host'] or getfqdn(), self['port'] or 8080) + return 'http://%s:%s/' % (self['host'] or getfqdn().lower(), self['port'] or 8080) try: diff -r ffb269e60348 -r 729f36a1bcfa i18n/de.po --- a/i18n/de.po Wed Mar 25 10:10:24 2015 +0100 +++ b/i18n/de.po Wed Apr 22 10:08:14 2015 +0200 @@ -54,6 +54,10 @@ msgstr "" #, python-format +msgid "%(KEY-rtype)s is part of violated unicity constraint" +msgstr "" + +#, python-format msgid "%(KEY-value)r doesn't match the %(KEY-regexp)r regular expression" msgstr "" @@ -114,10 +118,6 @@ msgstr "%s Fehlerbericht" #, python-format -msgid "%s is part of violated unicity constraint" -msgstr "" - -#, python-format msgid "%s software version of the database" msgstr "Software-Version der Datenbank %s" @@ -1120,6 +1120,30 @@ msgid "add WorkflowTransition transition_of Workflow object" msgstr "Workflow-Übergang" +msgid "add a BaseTransition" +msgstr "" + +msgid "add a Bookmark" +msgstr "" + +msgid "add a CWAttribute" +msgstr "" + +msgid "add a CWCache" +msgstr "" + +msgid "add a CWConstraint" +msgstr "" + +msgid "add a CWConstraintType" +msgstr "" + +msgid "add a CWDataImport" +msgstr "" + +msgid "add a CWEType" +msgstr "" + msgctxt "inlined:CWRelation.from_entity.subject" msgid "add a CWEType" msgstr "einen Entitätstyp hinzufügen" @@ -1128,14 +1152,68 @@ msgid "add a CWEType" msgstr "einen Entitätstyp hinzufügen" +msgid "add a CWGroup" +msgstr "" + +msgid "add a CWProperty" +msgstr "" + +msgid "add a CWRType" +msgstr "" + msgctxt "inlined:CWRelation.relation_type.subject" msgid "add a CWRType" msgstr "einen Relationstyp hinzufügen" +msgid "add a CWRelation" +msgstr "" + +msgid "add a CWSource" +msgstr "" + +msgid "add a CWSourceHostConfig" +msgstr "" + +msgid "add a CWSourceSchemaConfig" +msgstr "" + +msgid "add a CWUniqueTogetherConstraint" +msgstr "" + +msgid "add a CWUser" +msgstr "" + +msgid "add a EmailAddress" +msgstr "" + msgctxt "inlined:CWUser.use_email.subject" msgid "add a EmailAddress" msgstr "Email-Adresse hinzufügen" +msgid "add a ExternalUri" +msgstr "" + +msgid "add a RQLExpression" +msgstr "" + +msgid "add a State" +msgstr "" + +msgid "add a SubWorkflowExitPoint" +msgstr "" + +msgid "add a TrInfo" +msgstr "" + +msgid "add a Transition" +msgstr "" + +msgid "add a Workflow" +msgstr "" + +msgid "add a WorkflowTransition" +msgstr "" + # subject and object forms for each relation type # (no object form for final relation types) msgid "add_permission" diff -r ffb269e60348 -r 729f36a1bcfa i18n/en.po --- a/i18n/en.po Wed Mar 25 10:10:24 2015 +0100 +++ b/i18n/en.po Wed Apr 22 10:08:14 2015 +0200 @@ -46,6 +46,10 @@ msgstr "" #, python-format +msgid "%(KEY-rtype)s is part of violated unicity constraint" +msgstr "" + +#, python-format msgid "%(KEY-value)r doesn't match the %(KEY-regexp)r regular expression" msgstr "" @@ -106,10 +110,6 @@ msgstr "" #, python-format -msgid "%s is part of violated unicity constraint" -msgstr "" - -#, python-format msgid "%s software version of the database" msgstr "" @@ -1082,6 +1082,30 @@ msgid "add WorkflowTransition transition_of Workflow object" msgstr "workflow-transition" +msgid "add a BaseTransition" +msgstr "" + +msgid "add a Bookmark" +msgstr "" + +msgid "add a CWAttribute" +msgstr "" + +msgid "add a CWCache" +msgstr "" + +msgid "add a CWConstraint" +msgstr "" + +msgid "add a CWConstraintType" +msgstr "" + +msgid "add a CWDataImport" +msgstr "" + +msgid "add a CWEType" +msgstr "" + msgctxt "inlined:CWRelation.from_entity.subject" msgid "add a CWEType" msgstr "add an entity type" @@ -1090,14 +1114,68 @@ msgid "add a CWEType" msgstr "add an entity type" +msgid "add a CWGroup" +msgstr "" + +msgid "add a CWProperty" +msgstr "" + +msgid "add a CWRType" +msgstr "" + msgctxt "inlined:CWRelation.relation_type.subject" msgid "add a CWRType" msgstr "add a relation type" +msgid "add a CWRelation" +msgstr "" + +msgid "add a CWSource" +msgstr "" + +msgid "add a CWSourceHostConfig" +msgstr "" + +msgid "add a CWSourceSchemaConfig" +msgstr "" + +msgid "add a CWUniqueTogetherConstraint" +msgstr "" + +msgid "add a CWUser" +msgstr "" + +msgid "add a EmailAddress" +msgstr "" + msgctxt "inlined:CWUser.use_email.subject" msgid "add a EmailAddress" msgstr "add an email address" +msgid "add a ExternalUri" +msgstr "" + +msgid "add a RQLExpression" +msgstr "" + +msgid "add a State" +msgstr "" + +msgid "add a SubWorkflowExitPoint" +msgstr "" + +msgid "add a TrInfo" +msgstr "" + +msgid "add a Transition" +msgstr "" + +msgid "add a Workflow" +msgstr "" + +msgid "add a WorkflowTransition" +msgstr "" + # subject and object forms for each relation type # (no object form for final relation types) msgid "add_permission" diff -r ffb269e60348 -r 729f36a1bcfa i18n/es.po --- a/i18n/es.po Wed Mar 25 10:10:24 2015 +0100 +++ b/i18n/es.po Wed Apr 22 10:08:14 2015 +0200 @@ -60,6 +60,10 @@ msgstr "%(KEY-cstr)s restricción errónea para el valor %(KEY-value)r" #, python-format +msgid "%(KEY-rtype)s is part of violated unicity constraint" +msgstr "%(KEY-rtype)s pertenece a una restricción de unidad no respectada" + +#, python-format msgid "%(KEY-value)r doesn't match the %(KEY-regexp)r regular expression" msgstr "%(KEY-value)r no corresponde a la expresión regular %(KEY-regexp)r" @@ -120,10 +124,6 @@ msgstr "%s reporte de errores" #, python-format -msgid "%s is part of violated unicity constraint" -msgstr "%s pertenece a una restricción de unidad no respectada" - -#, python-format msgid "%s software version of the database" msgstr "versión sistema de la base para %s" @@ -1139,6 +1139,30 @@ msgid "add WorkflowTransition transition_of Workflow object" msgstr "Transición Workflow" +msgid "add a BaseTransition" +msgstr "" + +msgid "add a Bookmark" +msgstr "" + +msgid "add a CWAttribute" +msgstr "" + +msgid "add a CWCache" +msgstr "" + +msgid "add a CWConstraint" +msgstr "" + +msgid "add a CWConstraintType" +msgstr "" + +msgid "add a CWDataImport" +msgstr "" + +msgid "add a CWEType" +msgstr "" + msgctxt "inlined:CWRelation.from_entity.subject" msgid "add a CWEType" msgstr "Agregar un tipo de entidad" @@ -1147,14 +1171,68 @@ msgid "add a CWEType" msgstr "Agregar un tipo de entidad" +msgid "add a CWGroup" +msgstr "" + +msgid "add a CWProperty" +msgstr "" + +msgid "add a CWRType" +msgstr "" + msgctxt "inlined:CWRelation.relation_type.subject" msgid "add a CWRType" msgstr "Agregar un tipo de relación" +msgid "add a CWRelation" +msgstr "" + +msgid "add a CWSource" +msgstr "" + +msgid "add a CWSourceHostConfig" +msgstr "" + +msgid "add a CWSourceSchemaConfig" +msgstr "" + +msgid "add a CWUniqueTogetherConstraint" +msgstr "" + +msgid "add a CWUser" +msgstr "" + +msgid "add a EmailAddress" +msgstr "" + msgctxt "inlined:CWUser.use_email.subject" msgid "add a EmailAddress" msgstr "Agregar correo electrónico" +msgid "add a ExternalUri" +msgstr "" + +msgid "add a RQLExpression" +msgstr "" + +msgid "add a State" +msgstr "" + +msgid "add a SubWorkflowExitPoint" +msgstr "" + +msgid "add a TrInfo" +msgstr "" + +msgid "add a Transition" +msgstr "" + +msgid "add a Workflow" +msgstr "" + +msgid "add a WorkflowTransition" +msgstr "" + # subject and object forms for each relation type # (no object form for final relation types) msgid "add_permission" diff -r ffb269e60348 -r 729f36a1bcfa i18n/fr.po --- a/i18n/fr.po Wed Mar 25 10:10:24 2015 +0100 +++ b/i18n/fr.po Wed Apr 22 10:08:14 2015 +0200 @@ -54,6 +54,10 @@ msgstr "la valeur %(KEY-value)r ne satisfait pas la contrainte %(KEY-cstr)s" #, python-format +msgid "%(KEY-rtype)s is part of violated unicity constraint" +msgstr "%(KEY-rtype)s appartient à une contrainte d'unicité transgressée" + +#, python-format msgid "%(KEY-value)r doesn't match the %(KEY-regexp)r regular expression" msgstr "" "%(KEY-value)r ne correspond pas à l'expression régulière %(KEY-regexp)r" @@ -115,10 +119,6 @@ msgstr "%s rapport d'erreur" #, python-format -msgid "%s is part of violated unicity constraint" -msgstr "%s appartient à une contrainte d'unicité transgressée" - -#, python-format msgid "%s software version of the database" msgstr "version logicielle de la base pour %s" @@ -1135,6 +1135,30 @@ msgid "add WorkflowTransition transition_of Workflow object" msgstr "transition workflow" +msgid "add a BaseTransition" +msgstr "" + +msgid "add a Bookmark" +msgstr "" + +msgid "add a CWAttribute" +msgstr "" + +msgid "add a CWCache" +msgstr "" + +msgid "add a CWConstraint" +msgstr "" + +msgid "add a CWConstraintType" +msgstr "" + +msgid "add a CWDataImport" +msgstr "" + +msgid "add a CWEType" +msgstr "" + msgctxt "inlined:CWRelation.from_entity.subject" msgid "add a CWEType" msgstr "ajouter un type d'entité sujet" @@ -1143,14 +1167,68 @@ msgid "add a CWEType" msgstr "ajouter un type d'entité objet" +msgid "add a CWGroup" +msgstr "" + +msgid "add a CWProperty" +msgstr "" + +msgid "add a CWRType" +msgstr "" + msgctxt "inlined:CWRelation.relation_type.subject" msgid "add a CWRType" msgstr "ajouter un type de relation" +msgid "add a CWRelation" +msgstr "" + +msgid "add a CWSource" +msgstr "" + +msgid "add a CWSourceHostConfig" +msgstr "" + +msgid "add a CWSourceSchemaConfig" +msgstr "" + +msgid "add a CWUniqueTogetherConstraint" +msgstr "" + +msgid "add a CWUser" +msgstr "" + +msgid "add a EmailAddress" +msgstr "" + msgctxt "inlined:CWUser.use_email.subject" msgid "add a EmailAddress" msgstr "ajouter une adresse électronique" +msgid "add a ExternalUri" +msgstr "" + +msgid "add a RQLExpression" +msgstr "" + +msgid "add a State" +msgstr "" + +msgid "add a SubWorkflowExitPoint" +msgstr "" + +msgid "add a TrInfo" +msgstr "" + +msgid "add a Transition" +msgstr "" + +msgid "add a Workflow" +msgstr "" + +msgid "add a WorkflowTransition" +msgstr "" + # subject and object forms for each relation type # (no object form for final relation types) msgid "add_permission" diff -r ffb269e60348 -r 729f36a1bcfa misc/migration/3.14.4_Any.py --- a/misc/migration/3.14.4_Any.py Wed Mar 25 10:10:24 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,10 +0,0 @@ -from cubicweb.server import schema2sql as y2sql - -dbhelper = repo.system_source.dbhelper -rdefdef = schema['CWSource'].rdef('name') -attrtype = y2sql.type_from_constraints(dbhelper, rdefdef.object, rdefdef.constraints).split()[0] - -cursor = session.cnxset.cu -sql('UPDATE entities SET asource = source WHERE asource is NULL') -dbhelper.change_col_type(cursor, 'entities', 'asource', attrtype, False) -dbhelper.change_col_type(cursor, 'entities', 'source', attrtype, False) diff -r ffb269e60348 -r 729f36a1bcfa misc/migration/3.18.0_Any.py --- a/misc/migration/3.18.0_Any.py Wed Mar 25 10:10:24 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,151 +0,0 @@ -driver = config.system_source_config['db-driver'] -if not (driver == 'postgres' or driver.startswith('sqlserver')): - import sys - print >>sys.stderr, 'This migration is not supported for backends other than sqlserver or postgres (yet).' - sys.exit(1) - -add_relation_definition('CWAttribute', 'add_permission', 'CWGroup') -add_relation_definition('CWAttribute', 'add_permission', 'RQLExpression') - -# a bad defaultval in 3.13.8 schema was fixed in 3.13.9, but the migration was missed -rql('SET ATTR defaultval NULL WHERE ATTR from_entity E, E name "CWSource", ATTR relation_type T, T name "in_synchronization"') - -# the migration gets confused when we change rdefs out from under it. So -# explicitly remove this size constraint so it doesn't stick around and break -# things later. -rdefeid = schema['defaultval'].rdefs.values()[0].eid -rql('DELETE CWConstraint C WHERE C cstrtype T, T name "SizeConstraint", R constrained_by C, R eid %(eid)s', {'eid': rdefeid}) - -sync_schema_props_perms('defaultval') - -def convert_defaultval(cwattr, default): - from decimal import Decimal - import yams - from cubicweb import Binary - if default is None: - return - if isinstance(default, Binary): - # partially migrated instance, try to be idempotent - return default - atype = cwattr.to_entity[0].name - if atype == 'Boolean': - # boolean attributes with default=False were stored as '' - assert default in ('True', 'False', ''), repr(default) - default = default == 'True' - elif atype in ('Int', 'BigInt'): - default = int(default) - elif atype == 'Float': - default = float(default) - elif atype == 'Decimal': - default = Decimal(default) - elif atype in ('Date', 'Datetime', 'TZDatetime', 'Time'): - try: - # handle NOW and TODAY, keep them stored as strings - yams.KEYWORD_MAP[atype][default.upper()] - default = default.upper() - except KeyError: - # otherwise get an actual date or datetime - default = yams.DATE_FACTORY_MAP[atype](default) - else: - assert atype == 'String', atype - default = unicode(default) - return Binary.zpickle(default) - -dbh = repo.system_source.dbhelper - - -sql('ALTER TABLE cw_cwattribute ADD new_defaultval %s' % dbh.TYPE_MAPPING['Bytes']) - -for cwattr in rql('CWAttribute X').entities(): - olddefault = cwattr.defaultval - if olddefault is not None: - req = "UPDATE cw_cwattribute SET new_defaultval = %(val)s WHERE cw_eid = %(eid)s" - args = {'val': dbh.binary_value(convert_defaultval(cwattr, olddefault).getvalue()), 'eid': cwattr.eid} - sql(req, args, ask_confirm=False) - -sql('ALTER TABLE cw_cwattribute DROP COLUMN cw_defaultval') -if driver == 'postgres': - sql('ALTER TABLE cw_cwattribute RENAME COLUMN new_defaultval TO cw_defaultval') -else: # sqlserver - sql("sp_rename 'cw_cwattribute.new_defaultval', 'cw_defaultval', 'COLUMN'") - - -# Set object type to "Bytes" for CWAttribute's "defaultval" attribute -rql('SET X to_entity B WHERE X is CWAttribute, X from_entity Y, Y name "CWAttribute", ' - 'X relation_type Z, Z name "defaultval", B name "Bytes", NOT X to_entity B') - -oldrdef = schema['CWAttribute'].rdef('defaultval') -import yams.buildobjs as ybo -newrdef = ybo.RelationDefinition('CWAttribute', 'defaultval', 'Bytes') -newrdef.eid = oldrdef.eid -schema.add_relation_def(newrdef) -schema.del_relation_def('CWAttribute', 'defaultval', 'String') - -commit() - -sync_schema_props_perms('defaultval') - -for rschema in schema.relations(): - if rschema.symmetric: - subjects = set(repr(e.type) for e in rschema.subjects()) - objects = set(repr(e.type) for e in rschema.objects()) - assert subjects == objects - martians = set(str(eid) for eid, in sql('SELECT eid_to FROM %s_relation, entities WHERE eid_to = eid AND type NOT IN (%s)' % - (rschema.type, ','.join(subjects)))) - martians |= set(str(eid) for eid, in sql('SELECT eid_from FROM %s_relation, entities WHERE eid_from = eid AND type NOT IN (%s)' % - (rschema.type, ','.join(subjects)))) - if martians: - martians = ','.join(martians) - print 'deleting broken relations %s for eids %s' % (rschema.type, martians) - sql('DELETE FROM %s_relation WHERE eid_from IN (%s) OR eid_to IN (%s)' % (rschema.type, martians, martians)) - with session.deny_all_hooks_but(): - rql('SET X %(r)s Y WHERE Y %(r)s X, NOT X %(r)s Y' % {'r': rschema.type}) - commit() - - -# multi columns unique constraints regeneration -from cubicweb.server import schemaserial - -# syncschema hooks would try to remove indices but -# 1) we already do that below -# 2) the hook expects the CWUniqueTogetherConstraint.name attribute that hasn't -# yet been added -with session.allow_all_hooks_but('syncschema'): - rql('DELETE CWUniqueTogetherConstraint C') -commit() - -add_attribute('CWUniqueTogetherConstraint', 'name') - -# low-level wipe code for postgres & sqlserver, plain sql ... -if driver == 'postgres': - for indexname, in sql('select indexname from pg_indexes'): - if indexname.startswith('unique_'): - print 'dropping index', indexname - sql('DROP INDEX %s' % indexname) - commit() -elif driver.startswith('sqlserver'): - for viewname, in sql('select name from sys.views'): - if viewname.startswith('utv_'): - print 'dropping view (index should be cascade-deleted)', viewname - sql('DROP VIEW %s' % viewname) - commit() - -# recreate the constraints, hook will lead to low-level recreation -for eschema in sorted(schema.entities()): - if eschema._unique_together: - print 'recreate unique indexes for', eschema - rql_args = schemaserial.uniquetogether2rqls(eschema) - for rql, args in rql_args: - args['x'] = eschema.eid - session.execute(rql, args) -commit() - -# all attributes perms have to be refreshed ... -for rschema in sorted(schema.relations()): - if rschema.final: - if rschema.type in fsschema: - print 'sync perms for', rschema.type - sync_schema_props_perms(rschema.type, syncprops=False, ask_confirm=False, commit=False) - else: - print 'WARNING: attribute %s missing from fs schema' % rschema.type -commit() diff -r ffb269e60348 -r 729f36a1bcfa misc/migration/bootstrapmigration_repository.py --- a/misc/migration/bootstrapmigration_repository.py Wed Mar 25 10:10:24 2015 +0100 +++ b/misc/migration/bootstrapmigration_repository.py Wed Apr 22 10:08:14 2015 +0200 @@ -49,6 +49,27 @@ cursor.execute(dbh.sql_restart_numrange('entities_id_seq', initial_value=lasteid)) session.commit() +if applcubicwebversion <= (3, 13, 0) and cubicwebversion >= (3, 13, 1): + 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') + commit() + +if applcubicwebversion <= (3, 14, 4) and cubicwebversion >= (3, 14, 4): + from cubicweb.server import schema2sql as y2sql + dbhelper = repo.system_source.dbhelper + rdefdef = schema['CWSource'].rdef('name') + attrtype = y2sql.type_from_constraints(dbhelper, rdefdef.object, rdefdef.constraints).split()[0] + cursor = session.cnxset.cu + sql('UPDATE entities SET asource = source WHERE asource is NULL') + dbhelper.change_col_type(cursor, 'entities', 'asource', attrtype, False) + dbhelper.change_col_type(cursor, 'entities', 'source', attrtype, False) + + # we now have a functional asource column, start using the normal eid_type_source method + if repo.system_source.eid_type_source == repo.system_source.eid_type_source_pre_131: + del repo.system_source.eid_type_source + if applcubicwebversion < (3, 19, 0) and cubicwebversion >= (3, 19, 0): try: # need explicit drop of the indexes on some database systems (sqlserver) @@ -71,6 +92,163 @@ add_entity_type('CWComputedRType') commit() +if schema['TZDatetime'].eid is None: + add_entity_type('TZDatetime', auto=False) +if schema['TZTime'].eid is None: + add_entity_type('TZTime', auto=False) + +if applcubicwebversion < (3, 18, 0) and cubicwebversion >= (3, 18, 0): + driver = config.system_source_config['db-driver'] + if not (driver == 'postgres' or driver.startswith('sqlserver')): + import sys + print >>sys.stderr, 'This migration is not supported for backends other than sqlserver or postgres (yet).' + sys.exit(1) + + add_relation_definition('CWAttribute', 'add_permission', 'CWGroup') + add_relation_definition('CWAttribute', 'add_permission', 'RQLExpression') + + # a bad defaultval in 3.13.8 schema was fixed in 3.13.9, but the migration was missed + rql('SET ATTR defaultval NULL WHERE ATTR from_entity E, E name "CWSource", ATTR relation_type T, T name "in_synchronization"') + + # the migration gets confused when we change rdefs out from under it. So + # explicitly remove this size constraint so it doesn't stick around and break + # things later. + rdefeid = schema['defaultval'].rdefs.values()[0].eid + rql('DELETE CWConstraint C WHERE C cstrtype T, T name "SizeConstraint", R constrained_by C, R eid %(eid)s', {'eid': rdefeid}) + + sync_schema_props_perms('defaultval') + + def convert_defaultval(cwattr, default): + from decimal import Decimal + import yams + from cubicweb import Binary + if default is None: + return + if isinstance(default, Binary): + # partially migrated instance, try to be idempotent + return default + atype = cwattr.to_entity[0].name + if atype == 'Boolean': + # boolean attributes with default=False were stored as '' + assert default in ('True', 'False', ''), repr(default) + default = default == 'True' + elif atype in ('Int', 'BigInt'): + default = int(default) + elif atype == 'Float': + default = float(default) + elif atype == 'Decimal': + default = Decimal(default) + elif atype in ('Date', 'Datetime', 'TZDatetime', 'Time'): + try: + # handle NOW and TODAY, keep them stored as strings + yams.KEYWORD_MAP[atype][default.upper()] + default = default.upper() + except KeyError: + # otherwise get an actual date or datetime + default = yams.DATE_FACTORY_MAP[atype](default) + else: + assert atype == 'String', atype + default = unicode(default) + return Binary.zpickle(default) + + dbh = repo.system_source.dbhelper + + + sql('ALTER TABLE cw_cwattribute ADD new_defaultval %s' % dbh.TYPE_MAPPING['Bytes']) + + for cwattr in rql('CWAttribute X').entities(): + olddefault = cwattr.defaultval + if olddefault is not None: + req = "UPDATE cw_cwattribute SET new_defaultval = %(val)s WHERE cw_eid = %(eid)s" + args = {'val': dbh.binary_value(convert_defaultval(cwattr, olddefault).getvalue()), 'eid': cwattr.eid} + sql(req, args, ask_confirm=False) + + sql('ALTER TABLE cw_cwattribute DROP COLUMN cw_defaultval') + if driver == 'postgres': + sql('ALTER TABLE cw_cwattribute RENAME COLUMN new_defaultval TO cw_defaultval') + else: # sqlserver + sql("sp_rename 'cw_cwattribute.new_defaultval', 'cw_defaultval', 'COLUMN'") + + + # Set object type to "Bytes" for CWAttribute's "defaultval" attribute + rql('SET X to_entity B WHERE X is CWAttribute, X from_entity Y, Y name "CWAttribute", ' + 'X relation_type Z, Z name "defaultval", B name "Bytes", NOT X to_entity B') + + oldrdef = schema['CWAttribute'].rdef('defaultval') + import yams.buildobjs as ybo + newrdef = ybo.RelationDefinition('CWAttribute', 'defaultval', 'Bytes') + newrdef.eid = oldrdef.eid + schema.add_relation_def(newrdef) + schema.del_relation_def('CWAttribute', 'defaultval', 'String') + + commit() + + sync_schema_props_perms('defaultval') + + for rschema in schema.relations(): + if rschema.symmetric: + subjects = set(repr(e.type) for e in rschema.subjects()) + objects = set(repr(e.type) for e in rschema.objects()) + assert subjects == objects + martians = set(str(eid) for eid, in sql('SELECT eid_to FROM %s_relation, entities WHERE eid_to = eid AND type NOT IN (%s)' % + (rschema.type, ','.join(subjects)))) + martians |= set(str(eid) for eid, in sql('SELECT eid_from FROM %s_relation, entities WHERE eid_from = eid AND type NOT IN (%s)' % + (rschema.type, ','.join(subjects)))) + if martians: + martians = ','.join(martians) + print 'deleting broken relations %s for eids %s' % (rschema.type, martians) + sql('DELETE FROM %s_relation WHERE eid_from IN (%s) OR eid_to IN (%s)' % (rschema.type, martians, martians)) + with session.deny_all_hooks_but(): + rql('SET X %(r)s Y WHERE Y %(r)s X, NOT X %(r)s Y' % {'r': rschema.type}) + commit() + + + # multi columns unique constraints regeneration + from cubicweb.server import schemaserial + + # syncschema hooks would try to remove indices but + # 1) we already do that below + # 2) the hook expects the CWUniqueTogetherConstraint.name attribute that hasn't + # yet been added + with session.allow_all_hooks_but('syncschema'): + rql('DELETE CWUniqueTogetherConstraint C') + commit() + add_attribute('CWUniqueTogetherConstraint', 'name') + + # low-level wipe code for postgres & sqlserver, plain sql ... + if driver == 'postgres': + for indexname, in sql('select indexname from pg_indexes'): + if indexname.startswith('unique_'): + print 'dropping index', indexname + sql('DROP INDEX %s' % indexname) + commit() + elif driver.startswith('sqlserver'): + for viewname, in sql('select name from sys.views'): + if viewname.startswith('utv_'): + print 'dropping view (index should be cascade-deleted)', viewname + sql('DROP VIEW %s' % viewname) + commit() + + # recreate the constraints, hook will lead to low-level recreation + for eschema in sorted(schema.entities()): + if eschema._unique_together: + print 'recreate unique indexes for', eschema + rql_args = schemaserial.uniquetogether2rqls(eschema) + for rql, args in rql_args: + args['x'] = eschema.eid + session.execute(rql, args) + commit() + + # all attributes perms have to be refreshed ... + for rschema in sorted(schema.relations()): + if rschema.final: + if rschema.type in fsschema: + print 'sync perms for', rschema.type + sync_schema_props_perms(rschema.type, syncprops=False, ask_confirm=False, commit=False) + else: + print 'WARNING: attribute %s missing from fs schema' % rschema.type + commit() + if applcubicwebversion < (3, 17, 0) and cubicwebversion >= (3, 17, 0): try: add_cube('sioc', update_database=False) @@ -91,18 +269,6 @@ 'cube, which is not installed. Continue anyway?'): raise -if applcubicwebversion <= (3, 13, 0) and cubicwebversion >= (3, 13, 1): - 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') - commit() - -if schema['TZDatetime'].eid is None: - add_entity_type('TZDatetime', auto=False) -if schema['TZTime'].eid is None: - add_entity_type('TZTime', auto=False) - if applcubicwebversion <= (3, 14, 0) and cubicwebversion >= (3, 14, 0): if 'require_permission' in schema and not 'localperms'in repo.config.cubes(): @@ -113,14 +279,13 @@ raise ExecutionError('In cubicweb 3.14, CWPermission and related stuff ' 'has been moved to cube localperms. Install it first.') + if applcubicwebversion == (3, 6, 0) and cubicwebversion >= (3, 6, 0): CSTRMAP = dict(rql('Any T, X WHERE X is CWConstraintType, X name T', ask_confirm=False)) _add_relation_definition_no_perms('CWAttribute', 'update_permission', 'CWGroup') _add_relation_definition_no_perms('CWAttribute', 'update_permission', 'RQLExpression') rql('SET X update_permission Y WHERE X is CWAttribute, X add_permission Y') - drop_relation_definition('CWAttribute', 'add_permission', 'CWGroup') - drop_relation_definition('CWAttribute', 'add_permission', 'RQLExpression') drop_relation_definition('CWAttribute', 'delete_permission', 'CWGroup') drop_relation_definition('CWAttribute', 'delete_permission', 'RQLExpression') diff -r ffb269e60348 -r 729f36a1bcfa schema.py --- a/schema.py Wed Mar 25 10:10:24 2015 +0100 +++ b/schema.py Wed Apr 22 10:08:14 2015 +0200 @@ -891,7 +891,7 @@ return False def has_perm(self, _cw, action, **kwargs): - """return true if the action is granted globaly or localy""" + """return true if the action is granted globally or locally""" if self.final: assert not ('fromeid' in kwargs or 'toeid' in kwargs), kwargs assert action in ('read', 'update') diff -r ffb269e60348 -r 729f36a1bcfa server/migractions.py --- a/server/migractions.py Wed Mar 25 10:10:24 2015 +0100 +++ b/server/migractions.py Wed Apr 22 10:08:14 2015 +0200 @@ -524,6 +524,9 @@ subjtypes, objtypes = targettypes, [etype] self._synchronize_rschema(rschema, syncrdefs=False, syncprops=syncprops, syncperms=syncperms) + if rschema.rule: # rdef for computed rtype are infered hence should not be + # synchronized + continue reporschema = self.repo.schema.rschema(rschema) for subj in subjtypes: for obj in objtypes: diff -r ffb269e60348 -r 729f36a1bcfa server/repository.py --- a/server/repository.py Wed Mar 25 10:10:24 2015 +0100 +++ b/server/repository.py Wed Apr 22 10:08:14 2015 +0200 @@ -1059,6 +1059,8 @@ with session.security_enabled(read=False, write=False): in_eids = ','.join([str(_e.eid) for _e in entities]) for rschema, _, role in entities[0].e_schema.relation_definitions(): + if rschema.rule: + continue # computed relation rtype = rschema.type if rtype in schema.VIRTUAL_RTYPES or rtype in pendingrtypes: continue diff -r ffb269e60348 -r 729f36a1bcfa server/serverconfig.py --- a/server/serverconfig.py Wed Mar 25 10:10:24 2015 +0100 +++ b/server/serverconfig.py Wed Apr 22 10:08:14 2015 +0200 @@ -199,7 +199,7 @@ }), ('zmq-address-sub', {'type' : 'csv', - 'default' : None, + 'default' : (), 'help': ('List of ZMQ addresses to subscribe to (requires pyzmq) ' '(of the form `tcp://:`)'), 'group': 'zmq', 'level': 1, diff -r ffb269e60348 -r 729f36a1bcfa server/session.py --- a/server/session.py Wed Mar 25 10:10:24 2015 +0100 +++ b/server/session.py Wed Apr 22 10:08:14 2015 +0200 @@ -995,8 +995,8 @@ etype, extid, source = self.repo.type_and_source_from_eid(eid, self) metas = {'type': etype, 'source': source, 'extid': extid} if asdict: - metas['asource'] = meta['source'] # XXX pre 3.19 client compat - return meta + metas['asource'] = metas['source'] # XXX pre 3.19 client compat + return metas return etype, source, extid @_with_cnx_set diff -r ffb269e60348 -r 729f36a1bcfa server/sources/native.py --- a/server/sources/native.py Wed Mar 25 10:10:24 2015 +0100 +++ b/server/sources/native.py Wed Apr 22 10:08:14 2015 +0200 @@ -862,7 +862,7 @@ res = list(res) if res[-1] is not None: res[-1] = b64decode(res[-1]) - res.append(res[1]) + res.append("system") return res def extid2eid(self, cnx, extid): @@ -1570,14 +1570,15 @@ system database in a database independent format. The file is a Zip archive containing the following files: - * format.txt: the format of the archive. Currently '1.0' + * format.txt: the format of the archive. Currently '1.1' * tables.txt: list of filenames in the archive tables/ directory * sequences.txt: list of filenames in the archive sequences/ directory + * numranges.txt: list of filenames in the archive numrange/ directory * versions.txt: the list of cube versions from CWProperty * tables/.: pickled data * sequences/: pickled data - The pickled data format for tables and sequences is a tuple of 3 elements: + The pickled data format for tables, numranges and sequences is a tuple of 3 elements: * the table name * a tuple of column names * a list of rows (as tuples with one element per column) @@ -1615,6 +1616,9 @@ for seq in self.get_sequences(): self.logger.info('processing sequence %s', seq) self.write_sequence(archive, seq) + for numrange in self.get_numranges(): + self.logger.info('processing numrange %s', numrange) + self.write_numrange(archive, numrange) for table in self.get_tables(): self.logger.info('processing table %s', table) self.write_table(archive, table) @@ -1645,12 +1649,16 @@ return non_entity_tables + etype_tables + relation_tables def get_sequences(self): + return [] + + def get_numranges(self): return ['entities_id_seq'] def write_metadata(self, archive): - archive.writestr('format.txt', '1.0') + archive.writestr('format.txt', '1.1') archive.writestr('tables.txt', '\n'.join(self.get_tables())) archive.writestr('sequences.txt', '\n'.join(self.get_sequences())) + archive.writestr('numranges.txt', '\n'.join(self.get_numranges())) versions = self._get_versions() versions_str = '\n'.join('%s %s' % (k, v) for k, v in versions) @@ -1663,6 +1671,13 @@ serialized = self._serialize(seq, columns, rows) archive.writestr('sequences/%s' % seq, serialized) + def write_numrange(self, archive, numrange): + sql = self.dbhelper.sql_numrange_current_state(numrange) + columns, rows_iterator = self._get_cols_and_rows(sql) + rows = list(rows_iterator) + serialized = self._serialize(numrange, columns, rows) + archive.writestr('numrange/%s' % numrange, serialized) + def write_table(self, archive, table): nb_lines_sql = 'SELECT COUNT(*) FROM %s' % table self.cursor.execute(nb_lines_sql) @@ -1699,10 +1714,13 @@ archive = zipfile.ZipFile(backupfile, 'r', allowZip64=True) self.cnx = self.get_connection() self.cursor = self.cnx.cursor() - sequences, tables, table_chunks = self.read_metadata(archive, backupfile) + sequences, numranges, tables, table_chunks = self.read_metadata(archive, backupfile) for seq in sequences: self.logger.info('restoring sequence %s', seq) self.read_sequence(archive, seq) + for numrange in numranges: + self.logger.info('restoring numrange %s', seq) + self.read_numrange(archive, numrange) for table in tables: self.logger.info('restoring table %s', table) self.read_table(archive, table, sorted(table_chunks[table])) @@ -1713,11 +1731,12 @@ def read_metadata(self, archive, backupfile): formatinfo = archive.read('format.txt') self.logger.info('checking metadata') - if formatinfo.strip() != "1.0": + if formatinfo.strip() != "1.1": self.logger.critical('Unsupported format in archive: %s', formatinfo) raise ValueError('Unknown format in %s: %s' % (backupfile, formatinfo)) tables = archive.read('tables.txt').splitlines() sequences = archive.read('sequences.txt').splitlines() + numranges = archive.read('numranges.txt').splitlines() file_versions = self._parse_versions(archive.read('versions.txt')) versions = set(self._get_versions()) if file_versions != versions: @@ -1734,7 +1753,7 @@ filename = basename(name) tablename, _ext = filename.rsplit('.', 1) table_chunks.setdefault(tablename, []).append(name) - return sequences, tables, table_chunks + return sequences, numranges, tables, table_chunks def read_sequence(self, archive, seq): seqname, columns, rows = loads(archive.read('sequences/%s' % seq)) @@ -1746,6 +1765,16 @@ self.cursor.execute(sql) self.cnx.commit() + def read_numrange(self, archive, numrange): + rangename, columns, rows = loads(archive.read('numrange/%s' % numrange)) + assert rangename == numrange + assert len(rows) == 1 + assert len(rows[0]) == 1 + value = rows[0][0] + sql = self.dbhelper.sql_restart_numrange(numrange, value) + self.cursor.execute(sql) + self.cnx.commit() + def read_table(self, archive, table, filenames): merge_args = self._source.merge_args self.cursor.execute('DELETE FROM %s' % table) diff -r ffb269e60348 -r 729f36a1bcfa server/test/data/schema.py --- a/server/test/data/schema.py Wed Mar 25 10:10:24 2015 +0100 +++ b/server/test/data/schema.py Wed Apr 22 10:08:14 2015 +0200 @@ -16,7 +16,7 @@ # You should have received a copy of the GNU Lesser General Public License along # with CubicWeb. If not, see . -from yams.buildobjs import (EntityType, RelationType, RelationDefinition, +from yams.buildobjs import (EntityType, RelationType, RelationDefinition, ComputedRelation, SubjectRelation, RichString, String, Int, Float, Boolean, Datetime, TZDatetime, Bytes) from yams.constraints import SizeConstraint @@ -274,3 +274,7 @@ object = 'CWUser' inlined = True cardinality = '?*' + + +class user_login(ComputedRelation): + rule = 'O login_user S' diff -r ffb269e60348 -r 729f36a1bcfa server/test/unittest_repository.py --- a/server/test/unittest_repository.py Wed Mar 25 10:10:24 2015 +0100 +++ b/server/test/unittest_repository.py Wed Apr 22 10:08:14 2015 +0200 @@ -51,10 +51,10 @@ with self.assertRaises(ValidationError) as wraperr: cnx.execute('INSERT Societe S: S nom "Logilab", S type "SSLL", S cp "75013"') self.assertEqual( - {'cp': u'cp is part of violated unicity constraint', - 'nom': u'nom is part of violated unicity constraint', - 'type': u'type is part of violated unicity constraint', - 'unicity constraint': u'some relations violate a unicity constraint'}, + {'cp': u'%(KEY-rtype)s is part of violated unicity constraint', + 'nom': u'%(KEY-rtype)s is part of violated unicity constraint', + 'type': u'%(KEY-rtype)s is part of violated unicity constraint', + '': u'some relations violate a unicity constraint'}, wraperr.exception.args[1]) def test_unique_together_schema(self): @@ -393,6 +393,13 @@ cnx.commit() self.assertEqual(len(c.reverse_fiche), 1) + def test_delete_computed_relation_nonregr(self): + with self.admin_access.repo_cnx() as cnx: + c = cnx.create_entity('Personne', nom=u'Adam', login_user=cnx.user.eid) + cnx.commit() + c.cw_delete() + cnx.commit() + def test_cw_set_in_before_update(self): # local hook class DummyBeforeHook(Hook): diff -r ffb269e60348 -r 729f36a1bcfa sobjects/notification.py --- a/sobjects/notification.py Wed Mar 25 10:10:24 2015 +0100 +++ b/sobjects/notification.py Wed Apr 22 10:08:14 2015 +0200 @@ -81,7 +81,11 @@ # this is usually the method to call def render_and_send(self, **kwargs): """generate and send email messages for this view""" - self._cw.vreg.config.sendmails(self.render_emails(**kwargs)) + # render_emails changes self._cw so cache it here so all mails are sent + # after we commit our transaction. + cnx = self._cw + for msg, recipients in self.render_emails(**kwargs): + SendMailOp(cnx, recipients=recipients, msg=msg) def cell_call(self, row, col=0, **kwargs): self.w(self._cw._(self.content) % self.context(**kwargs)) diff -r ffb269e60348 -r 729f36a1bcfa test/unittest_dataimport.py --- a/test/unittest_dataimport.py Wed Mar 25 10:10:24 2015 +0100 +++ b/test/unittest_dataimport.py Wed Apr 22 10:08:14 2015 +0200 @@ -1,7 +1,10 @@ # -*- coding: utf-8 -*- + import datetime as DT from StringIO import StringIO + from logilab.common.testlib import TestCase, unittest_main + from cubicweb import dataimport from cubicweb.devtools.testlib import CubicWebTC @@ -24,6 +27,7 @@ self.assertEqual(1, len(users)) self.assertEqual(group_eid, groups.one().eid) + class CreateCopyFromBufferTC(TestCase): # test converters @@ -134,5 +138,30 @@ [u'1', u'2', u'3', u'4', u'']]) +class MetaGeneratorTC(CubicWebTC): + + def test_dont_generate_relation_to_internal_manager(self): + with self.admin_access.repo_cnx() as cnx: + metagen = dataimport.MetaGenerator(cnx) + self.assertIn('created_by', metagen.etype_rels) + self.assertIn('owned_by', metagen.etype_rels) + with self.repo.internal_cnx() as cnx: + metagen = dataimport.MetaGenerator(cnx) + self.assertNotIn('created_by', metagen.etype_rels) + self.assertNotIn('owned_by', metagen.etype_rels) + + def test_dont_generate_specified_values(self): + with self.admin_access.repo_cnx() as cnx: + metagen = dataimport.MetaGenerator(cnx) + # hijack gen_modification_date to ensure we don't go through it + metagen.gen_modification_date = None + md = DT.datetime.now() - DT.timedelta(days=1) + entity, rels = metagen.base_etype_dicts('CWUser') + entity.cw_edited.update(dict(modification_date=md)) + with cnx.ensure_cnx_set: + metagen.init_entity(entity) + self.assertEqual(entity.cw_edited['modification_date'], md) + + if __name__ == '__main__': unittest_main() diff -r ffb269e60348 -r 729f36a1bcfa web/data/cubicweb.ajax.box.js --- a/web/data/cubicweb.ajax.box.js Wed Mar 25 10:10:24 2015 +0100 +++ b/web/data/cubicweb.ajax.box.js Wed Apr 22 10:08:14 2015 +0200 @@ -17,7 +17,7 @@ d.addCallback(function() { $('#' + holderid).empty(); var formparams = ajaxFuncArgs('render', null, 'ctxcomponents', boxid, eid); - $('#' + cw.utils.domid(boxid) + eid).loadxhtml(AJAX_BASE_URL, formparams); + $('#' + cw.utils.domid(boxid) + eid).loadxhtml(AJAX_BASE_URL, formparams, null, 'swap'); if (msg) { document.location.hash = '#header'; updateMessage(msg); @@ -29,7 +29,7 @@ var d = loadRemote(AJAX_BASE_URL, ajaxFuncArgs(delfname, null, eid, relatedeid)); d.addCallback(function() { var formparams = ajaxFuncArgs('render', null, 'ctxcomponents', boxid, eid); - $('#' + cw.utils.domid(boxid) + eid).loadxhtml(AJAX_BASE_URL, formparams); + $('#' + cw.utils.domid(boxid) + eid).loadxhtml(AJAX_BASE_URL, formparams, null, 'swap'); if (msg) { document.location.hash = '#header'; updateMessage(msg); diff -r ffb269e60348 -r 729f36a1bcfa web/data/cubicweb.ajax.js --- a/web/data/cubicweb.ajax.js Wed Mar 25 10:10:24 2015 +0100 +++ b/web/data/cubicweb.ajax.js Wed Apr 22 10:08:14 2015 +0200 @@ -511,7 +511,8 @@ d.addCallback(function(boxcontent) { $('#bookmarks_box').loadxhtml(AJAX_BASE_URL, ajaxFuncArgs('render', null, 'ctxcomponents', - 'bookmarks_box')); + 'bookmarks_box'), + null, 'swap'); document.location.hash = '#header'; updateMessage(_("bookmark has been removed")); }); diff -r ffb269e60348 -r 729f36a1bcfa web/data/cubicweb.edition.js --- a/web/data/cubicweb.edition.js Wed Mar 25 10:10:24 2015 +0100 +++ b/web/data/cubicweb.edition.js Wed Apr 22 10:08:14 2015 +0200 @@ -21,14 +21,14 @@ */ function setPropValueWidget(varname, tabindex) { - var key = firstSelected(document.getElementById('pkey:' + varname)); + var key = firstSelected(document.getElementById('pkey-subject:' + varname)); if (key) { var args = { fname: 'prop_widget', pageid: pageid, - arg: $.map([key, varname, tabindex], JSON.stringify) + arg: $.map([key.value, varname, tabindex], JSON.stringify) }; - cw.jqNode('div:value:' + varname).loadxhtml(AJAX_BASE_URL, args, 'post'); + cw.jqNode('div:value-subject:' + varname).loadxhtml(AJAX_BASE_URL, args, 'post'); } } diff -r ffb269e60348 -r 729f36a1bcfa web/data/cubicweb.facets.js --- a/web/data/cubicweb.facets.js Wed Mar 25 10:10:24 2015 +0100 +++ b/web/data/cubicweb.facets.js Wed Apr 22 10:08:14 2015 +0200 @@ -116,7 +116,7 @@ $node.loadxhtml(AJAX_BASE_URL, ajaxFuncArgs('render', { 'rql': rql }, - 'ctxcomponents', 'breadcrumbs')); + 'ctxcomponents', 'breadcrumbs'), null, 'swap'); } } var mainvar = null; diff -r ffb269e60348 -r 729f36a1bcfa web/data/cubicweb.reledit.js --- a/web/data/cubicweb.reledit.js Wed Mar 25 10:10:24 2015 +0100 +++ b/web/data/cubicweb.reledit.js Wed Apr 22 10:08:14 2015 +0200 @@ -53,7 +53,7 @@ return; } } - jQuery('#'+params.divid+'-reledit').loadxhtml(AJAX_BASE_URL, params, 'post'); + jQuery('#'+params.divid+'-reledit').loadxhtml(AJAX_BASE_URL, params, 'post', 'swap'); jQuery(cw).trigger('reledit-reloaded', params); }, @@ -69,7 +69,7 @@ pageid: pageid, action: action, eid: eid, divid: divid, formid: formid, reload: reload, vid: vid}; - var d = jQuery('#'+divid+'-reledit').loadxhtml(AJAX_BASE_URL, args, 'post'); + var d = jQuery('#'+divid+'-reledit').loadxhtml(AJAX_BASE_URL, args, 'post', 'swap'); d.addCallback(function () {cw.reledit.showInlineEditionForm(divid);}); } }); diff -r ffb269e60348 -r 729f36a1bcfa web/test/test_views.py --- a/web/test/test_views.py Wed Mar 25 10:10:24 2015 +0100 +++ b/web/test/test_views.py Wed Apr 22 10:08:14 2015 +0200 @@ -55,9 +55,11 @@ def test_sortable_js_added(self): with self.admin_access.web_request() as req: + # sortable.js should not be included by default rset = req.execute('CWUser X') - # sortable.js should not be included by default - self.assertFalse('jquery.tablesorter.js' in self.view('oneline', rset, req=req)) + self.assertNotIn('jquery.tablesorter.js', self.view('oneline', rset, req=req).source) + + with self.admin_access.web_request() as req: # but should be included by the tableview rset = req.execute('Any P,F,S LIMIT 1 WHERE P is CWUser, P firstname F, P surname S') self.assertIn('jquery.tablesorter.js', self.view('table', rset, req=req).source) diff -r ffb269e60348 -r 729f36a1bcfa web/test/unittest_views_editforms.py --- a/web/test/unittest_views_editforms.py Wed Mar 25 10:10:24 2015 +0100 +++ b/web/test/unittest_views_editforms.py Wed Apr 22 10:08:14 2015 +0200 @@ -148,6 +148,13 @@ self.vreg['forms'].select('edition', req, entity=rset.get_entity(0, 0)) self.assertFalse(any(f for f in form.fields if f is None)) + def test_edition_form_with_action(self): + with self.admin_access.web_request() as req: + rset = req.execute('CWUser X LIMIT 1') + form = self.vreg['forms'].select('edition', req, rset=rset, row=0, + col=0, action='my_custom_action') + self.assertEqual(form.form_action(), 'my_custom_action') + def test_attribute_add_permissions(self): # https://www.cubicweb.org/ticket/4342844 with self.admin_access.repo_cnx() as cnx: diff -r ffb269e60348 -r 729f36a1bcfa web/views/autoform.py --- a/web/views/autoform.py Wed Mar 25 10:10:24 2015 +0100 +++ b/web/views/autoform.py Wed Apr 22 10:08:14 2015 +0200 @@ -732,10 +732,7 @@ @deprecated('[3.18] use form_action()') def get_action(self): - try: - return self._action - except AttributeError: - return self._cw.build_url(self._default_form_action_path) + return self._action @iclassmethod diff -r ffb269e60348 -r 729f36a1bcfa web/views/cwproperties.py --- a/web/views/cwproperties.py Wed Mar 25 10:10:24 2015 +0100 +++ b/web/views/cwproperties.py Wed Apr 22 10:08:14 2015 +0200 @@ -302,7 +302,7 @@ domid = field.dom_id(form) value = '%s' % (domid, self.value) if self.msg: - value + '
%s
' % self.msg + value += '
%s
' % self.msg return value @@ -355,6 +355,7 @@ msg = form._cw._('you should probably delete that property') self.widget = NotEditableWidget(entity.printable_value('value'), '%s (%s)' % (msg, ex)) + return if entity.pkey.startswith('system.'): msg = form._cw._('value associated to this key is not editable ' 'manually') @@ -425,10 +426,10 @@ """specific method for CWProperty handling""" entity = self._cw.vreg['etypes'].etype_class('CWProperty')(self._cw) entity.eid = varname - entity['pkey'] = propkey + entity.pkey = propkey form = self._cw.vreg['forms'].select('edition', self._cw, entity=entity) form.build_context() - vfield = form.field_by_name('value') + vfield = form.field_by_name('value', 'subject') renderer = formrenderers.FormRenderer(self._cw) return vfield.render(form, renderer, tabindex=tabindex) \ + renderer.render_help(form, vfield) diff -r ffb269e60348 -r 729f36a1bcfa web/views/rdf.py --- a/web/views/rdf.py Wed Mar 25 10:10:24 2015 +0100 +++ b/web/views/rdf.py Wed Apr 22 10:08:14 2015 +0200 @@ -94,7 +94,7 @@ add( (cwuri, CW[rtype], URIRef(related.cwuri)) ) try: for item in xy.xeq('%s %s' % (entity.e_schema.type, rtype)): - add( (cwuri, urijoin(item), URIRef(related.cwuri)) ) + add( (cwuri, urijoin(item[1]), URIRef(related.cwuri)) ) except xy.UnsupportedVocabulary: pass else: diff -r ffb269e60348 -r 729f36a1bcfa web/wdoc/about_en.rst --- a/web/wdoc/about_en.rst Wed Mar 25 10:10:24 2015 +0100 +++ b/web/wdoc/about_en.rst Wed Apr 22 10:08:14 2015 +0200 @@ -22,4 +22,4 @@ .. _dublincore: http://dublincore.org .. _Logilab: http://www.logilab.fr/ -.. _schema: schema +.. _schema: ../schema diff -r ffb269e60348 -r 729f36a1bcfa web/wdoc/about_fr.rst --- a/web/wdoc/about_fr.rst Wed Mar 25 10:10:24 2015 +0100 +++ b/web/wdoc/about_fr.rst Wed Apr 22 10:08:14 2015 +0200 @@ -25,4 +25,4 @@ .. _dublincore: http://dublincore.org .. _Logilab: http://www.logilab.fr/ -.. _schéma: schema +.. _schéma: ../schema diff -r ffb269e60348 -r 729f36a1bcfa web/wdoc/add_content_en.rst --- a/web/wdoc/add_content_en.rst Wed Mar 25 10:10:24 2015 +0100 +++ b/web/wdoc/add_content_en.rst Wed Apr 22 10:08:14 2015 +0200 @@ -2,7 +2,7 @@ ----------------- As manager, you can access to entity creation forms by using the `site management`_ page. -.. _`site management`: manage +.. _`site management`: ../manage As regular user, the index page or the action box may propose some links to create entities according to the context. diff -r ffb269e60348 -r 729f36a1bcfa web/wdoc/add_content_fr.rst --- a/web/wdoc/add_content_fr.rst Wed Mar 25 10:10:24 2015 +0100 +++ b/web/wdoc/add_content_fr.rst Wed Apr 22 10:08:14 2015 +0200 @@ -2,7 +2,7 @@ ------------------- Pour un administrateur, la création des objets est toujours possible directement dans la `page de gestion de site`_. -.. _`page de gestion de site`: manage +.. _`page de gestion de site`: ../manage Pour les utilisateurs, la page principale ou la boîte d'action des entités vous permettra la création de nouveaux contenus. L'intérêt de la dernière méthode est de faciliter l'édition de la relation entre les objets. diff -r ffb269e60348 -r 729f36a1bcfa web/wdoc/advanced_usage_schema_en.rst --- a/web/wdoc/advanced_usage_schema_en.rst Wed Mar 25 10:10:24 2015 +0100 +++ b/web/wdoc/advanced_usage_schema_en.rst Wed Apr 22 10:08:14 2015 +0200 @@ -6,4 +6,4 @@ site is not a content management system with items placed in folders. It is an interface to a database which applies a view to retreived data. -.. _schema: schema +.. _schema: ../schema diff -r ffb269e60348 -r 729f36a1bcfa web/wdoc/advanced_usage_schema_fr.rst --- a/web/wdoc/advanced_usage_schema_fr.rst Wed Mar 25 10:10:24 2015 +0100 +++ b/web/wdoc/advanced_usage_schema_fr.rst Wed Apr 22 10:08:14 2015 +0200 @@ -5,7 +5,7 @@ Commencez d'abord par jeter un œil au schéma_ de l'application, puis essayez de vous rappeler que vous naviguez dans un ensemble de données en appliquant des vues aux résultats de requête. Ce site n'est pas un système de gestion de contenu avec des objets dans des répertoires. C'est une interface vers une base de données qui vous permet d'appliquer une vue aux données récupérées. -.. _schéma: schema +.. _schéma: ../schema Relation entre les objets diff -r ffb269e60348 -r 729f36a1bcfa web/wdoc/bookmarks_fr.rst --- a/web/wdoc/bookmarks_fr.rst Wed Mar 25 10:10:24 2015 +0100 +++ b/web/wdoc/bookmarks_fr.rst Wed Apr 22 10:08:14 2015 +0200 @@ -27,4 +27,4 @@ ayez le droit de les modifier. -.. _`préférences utilisateurs`: myprefs +.. _`préférences utilisateurs`: ../myprefs diff -r ffb269e60348 -r 729f36a1bcfa web/wdoc/custom_view_en.rst --- a/web/wdoc/custom_view_en.rst Wed Mar 25 10:10:24 2015 +0100 +++ b/web/wdoc/custom_view_en.rst Wed Apr 22 10:08:14 2015 +0200 @@ -6,10 +6,10 @@ preferences`_). Once you're satified, add a `bookmark`_ if you want to reuse this view later. -.. _`RQL tutorial`: doc/tut_rql -.. _`schema`: schema -.. _`user preferences`: myprefs -.. _`bookmark`: doc/bookmarks +.. _`RQL tutorial`: tut_rql +.. _`schema`: ../schema +.. _`user preferences`: ../myprefs +.. _`bookmark`: bookmarks Below are some example of what can be acheived... diff -r ffb269e60348 -r 729f36a1bcfa web/wdoc/custom_view_fr.rst --- a/web/wdoc/custom_view_fr.rst Wed Mar 25 10:10:24 2015 +0100 +++ b/web/wdoc/custom_view_fr.rst Wed Apr 22 10:08:14 2015 +0200 @@ -9,10 +9,10 @@ utilisateur`_). Une fois que vous êtes satisfait, ajoutez un `signet`_ si vous voulez réutiliser votre vue plus tard. -.. _`tutoriel RQL`: doc/tut_rql -.. _`schéma`: schema -.. _`préférences utilisateur`: myprefs -.. _`signet`: doc/bookmarks +.. _`tutoriel RQL`: tut_rql +.. _`schéma`: ../schema +.. _`préférences utilisateur`: ../myprefs +.. _`signet`: bookmarks Ci-dessous quelques exemples de ce que l'on peut faire... diff -r ffb269e60348 -r 729f36a1bcfa web/wdoc/custom_view_last_update_en.rst --- a/web/wdoc/custom_view_last_update_en.rst Wed Mar 25 10:10:24 2015 +0100 +++ b/web/wdoc/custom_view_last_update_en.rst Wed Apr 22 10:08:14 2015 +0200 @@ -5,4 +5,4 @@ Links below is providing useful RQL query example. -.. _all latest changes: view?rql=Any+M%2CX+WHERE+X+modification_date+M+ORDERBY+M+DESC+LIMIT+30 +.. _all latest changes: ../view?rql=Any+M%2CX+WHERE+X+modification_date+M+ORDERBY+M+DESC+LIMIT+30 diff -r ffb269e60348 -r 729f36a1bcfa web/wdoc/custom_view_last_update_fr.rst --- a/web/wdoc/custom_view_last_update_fr.rst Wed Mar 25 10:10:24 2015 +0100 +++ b/web/wdoc/custom_view_last_update_fr.rst Wed Apr 22 10:08:14 2015 +0200 @@ -6,5 +6,5 @@ * la table des `derniers changements`_ fournit un exemple d'utilisation de RQL pour récupérer les derniers changements ayant eu lieu sur ce site. -.. _`derniers changements`: view?rql=Any+M%2CX+WHERE+X+modification_date+M+ORDERBY+M+DESC+LIMIT+30 +.. _`derniers changements`: ../view?rql=Any+M%2CX+WHERE+X+modification_date+M+ORDERBY+M+DESC+LIMIT+30 diff -r ffb269e60348 -r 729f36a1bcfa web/wdoc/custom_view_rss_en.rst --- a/web/wdoc/custom_view_rss_en.rst Wed Mar 25 10:10:24 2015 +0100 +++ b/web/wdoc/custom_view_rss_en.rst Wed Apr 22 10:08:14 2015 +0200 @@ -10,5 +10,5 @@ an RSS reader into that and follow the site activity. For example : :raw-html:`

latest changes

` +href="../view?vid=rss&rql=Any+X%2CM+WHERE+X+modification_date+M+ORDERBY+M+DESC+LIMIT+30"> latest changes

` diff -r ffb269e60348 -r 729f36a1bcfa web/wdoc/custom_view_rss_fr.rst --- a/web/wdoc/custom_view_rss_fr.rst Wed Mar 25 10:10:24 2015 +0100 +++ b/web/wdoc/custom_view_rss_fr.rst Wed Apr 22 10:08:14 2015 +0200 @@ -13,6 +13,6 @@ derniers changements sous forme de flux RSS: :raw-html:`

latest changes

` +href="../view?vid=rss&rql=Any+X%2CM+WHERE+X+modification_date+M+ORDERBY+M+DESC+LIMIT+30"> latest changes

` diff -r ffb269e60348 -r 729f36a1bcfa web/wdoc/search_en.rst --- a/web/wdoc/search_en.rst Wed Mar 25 10:10:24 2015 +0100 +++ b/web/wdoc/search_en.rst Wed Apr 22 10:08:14 2015 +0200 @@ -10,4 +10,4 @@ * `rql` : RQL query * `text` : full text search -.. _RQL: doc/tut_rql +.. _RQL: tut_rql diff -r ffb269e60348 -r 729f36a1bcfa web/wdoc/search_fr.rst --- a/web/wdoc/search_fr.rst Wed Mar 25 10:10:24 2015 +0100 +++ b/web/wdoc/search_fr.rst Wed Apr 22 10:08:14 2015 +0200 @@ -11,5 +11,5 @@ * `rql` : requête RQL * `text` : recherche plein texte -.. _RQL: doc/tut_rql +.. _RQL: tut_rql diff -r ffb269e60348 -r 729f36a1bcfa web/wdoc/tut_rql_en.rst --- a/web/wdoc/tut_rql_en.rst Wed Mar 25 10:10:24 2015 +0100 +++ b/web/wdoc/tut_rql_en.rst Wed Apr 22 10:08:14 2015 +0200 @@ -20,7 +20,7 @@ knowledge of the application'schema. You can always view it using the "schema" link in user's dropdown menu (on the top-right of the screen) or by clicking here_. -.. _here: schema +.. _here: ../schema Some bits of theory diff -r ffb269e60348 -r 729f36a1bcfa web/wdoc/tut_rql_fr.rst --- a/web/wdoc/tut_rql_fr.rst Wed Mar 25 10:10:24 2015 +0100 +++ b/web/wdoc/tut_rql_fr.rst Wed Apr 22 10:08:14 2015 +0200 @@ -24,7 +24,7 @@ boîte affichée en cliquant sur le lien de l'utilisateur connectée (en haut à droite). Vous pouvez également le voir en cliquant ici_. -.. _ici: schema +.. _ici: ../schema Un peu de théorie diff -r ffb269e60348 -r 729f36a1bcfa web/wdoc/userprefs_en.rst --- a/web/wdoc/userprefs_en.rst Wed Mar 25 10:10:24 2015 +0100 +++ b/web/wdoc/userprefs_en.rst Wed Apr 22 10:08:14 2015 +0200 @@ -7,4 +7,4 @@ preferences" link in this menu. This will show you a form to configure which boxes are displayed, in which order, etc... -.. image:: doc/images/userprefs +.. image:: images/userprefs diff -r ffb269e60348 -r 729f36a1bcfa web/wdoc/userprefs_fr.rst --- a/web/wdoc/userprefs_fr.rst Wed Mar 25 10:10:24 2015 +0100 +++ b/web/wdoc/userprefs_fr.rst Wed Apr 22 10:08:14 2015 +0200 @@ -6,7 +6,7 @@ personnelles (y compris le mot de passe d'accès à l'application). Chaque utilisateur peut également personaliser l'apparence du site via le lien -"préférences utilisateur"_. Ce formulaire permet notamment de configurer les +`préférences utilisateur`_. Ce formulaire permet notamment de configurer les boîtes qui seront affichées, leur ordre, etc... L'administrateur possède quant à lui un menu "configuration du site" qui reprend l'ensemble des préférences utilisateurs mais les applique par défaut au site. @@ -42,6 +42,6 @@ Il est alors possible d'éditer et de relancer toute requête -.. _"préférences utilisateur: myprefs -.. _RQL: doc/tut_rql -.. image:: doc/images/userprefs +.. _`préférences utilisateur`: ../myprefs +.. _RQL: tut_rql +.. image:: images/userprefs