# HG changeset patch # User Denis Laxalde # Date 1466689719 -7200 # Node ID 68f0678fc543083b5ce9128e64c18bc1dc1c236d # Parent 67373614e125db2d06baee376a546769281f6005# Parent 4482e94daabefe0308b02fa954f3f8e06e27d3a7 Merge with 3.21 diff -r 4482e94daabe -r 68f0678fc543 .hgtags --- a/.hgtags Tue Jun 21 07:44:35 2016 +0200 +++ b/.hgtags Thu Jun 23 15:48:39 2016 +0200 @@ -520,6 +520,9 @@ f66a4895759e0913b1203943fc2cd7be1a821e05 3.20.14 f66a4895759e0913b1203943fc2cd7be1a821e05 debian/3.20.14-1 f66a4895759e0913b1203943fc2cd7be1a821e05 centos/3.20.14-1 +636a83e65870433c2560f3c49d55ca628bc96e11 3.20.15 +636a83e65870433c2560f3c49d55ca628bc96e11 debian/3.20.15-1 +636a83e65870433c2560f3c49d55ca628bc96e11 centos/3.20.15-1 887c6eef807781560adcd4ecd2dea9011f5a6681 3.21.0 887c6eef807781560adcd4ecd2dea9011f5a6681 debian/3.21.0-1 887c6eef807781560adcd4ecd2dea9011f5a6681 centos/3.21.0-1 @@ -551,6 +554,6 @@ 1b93ff37755b0588081f6fcb93da0dde772a6adb 3.22.2 1b93ff37755b0588081f6fcb93da0dde772a6adb debian/3.22.2-1 1b93ff37755b0588081f6fcb93da0dde772a6adb centos/3.22.2-1 -636a83e65870433c2560f3c49d55ca628bc96e11 3.20.15 -636a83e65870433c2560f3c49d55ca628bc96e11 debian/3.20.15-1 -636a83e65870433c2560f3c49d55ca628bc96e11 centos/3.20.15-1 +b1e7de00053628968ea364ee9044fb4f8714fb50 3.22.3 +b1e7de00053628968ea364ee9044fb4f8714fb50 debian/3.22.3-1 +b1e7de00053628968ea364ee9044fb4f8714fb50 centos/3.22.3-1 diff -r 4482e94daabe -r 68f0678fc543 __pkginfo__.py --- a/__pkginfo__.py Tue Jun 21 07:44:35 2016 +0200 +++ b/__pkginfo__.py Thu Jun 23 15:48:39 2016 +0200 @@ -22,8 +22,8 @@ modname = distname = "cubicweb" -numversion = (3, 22, 2) -version = '.'.join(str(num) for num in numversion) + '.dev0' +numversion = (3, 22, 3) +version = '.'.join(str(num) for num in numversion) description = "a repository of entities / relations for knowledge management" author = "Logilab" @@ -43,7 +43,7 @@ 'logilab-common': '>= 0.63.1', 'logilab-mtconverter': '>= 0.8.0', 'rql': '>= 0.34.0', - 'yams': '>= 0.42.0', + 'yams': '>= 0.42.0,< 0.43', #gettext # for xgettext, msgcat, etc... # web dependencies 'lxml': '', diff -r 4482e94daabe -r 68f0678fc543 cubicweb.spec --- a/cubicweb.spec Tue Jun 21 07:44:35 2016 +0200 +++ b/cubicweb.spec Thu Jun 23 15:48:39 2016 +0200 @@ -8,7 +8,7 @@ %{!?python_sitelib: %define python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")} Name: cubicweb -Version: 3.22.2 +Version: 3.22.3 Release: logilab.1%{?dist} Summary: CubicWeb is a semantic web application framework Source0: https://pypi.python.org/packages/source/c/cubicweb/cubicweb-%{version}.tar.gz @@ -26,6 +26,7 @@ Requires: %{python}-logilab-mtconverter >= 0.8.0 Requires: %{python}-rql >= 0.34.0 Requires: %{python}-yams >= 0.42.0 +Requires: %{python}-yams < 0.43 Requires: %{python}-logilab-database >= 1.15.0 Requires: %{python}-passlib Requires: %{python}-lxml diff -r 4482e94daabe -r 68f0678fc543 debian/changelog --- a/debian/changelog Tue Jun 21 07:44:35 2016 +0200 +++ b/debian/changelog Thu Jun 23 15:48:39 2016 +0200 @@ -1,3 +1,9 @@ +cubicweb (3.22.3-1) unstable; urgency=medium + + * New upstream release. + + -- Denis Laxalde Tue, 21 Jun 2016 15:32:19 +0200 + cubicweb (3.22.2-1) unstable; urgency=medium * new upstream release diff -r 4482e94daabe -r 68f0678fc543 debian/control --- a/debian/control Tue Jun 21 07:44:35 2016 +0200 +++ b/debian/control Thu Jun 23 15:48:39 2016 +0200 @@ -17,6 +17,7 @@ python-tz, python-rql (>= 0.34.0), python-yams (>= 0.42.0), + python-yams (<< 0.43), python-lxml, Standards-Version: 3.9.1 Homepage: https://www.cubicweb.org diff -r 4482e94daabe -r 68f0678fc543 doc/announce.en.txt --- a/doc/announce.en.txt Tue Jun 21 07:44:35 2016 +0200 +++ b/doc/announce.en.txt Thu Jun 23 15:48:39 2016 +0200 @@ -33,10 +33,10 @@ The impatient will move right away to installation_ and set-up of a CubicWeb environment. -.. _cubicweb: http://www.cubicweb.org/ -.. _overview: http://www.cubicweb.org/doc/en/A020-tutorial.en.html#overview -.. _forge: http://www.cubicweb.org/project?vtitle=All%20cubicweb%20projects -.. _installation: http://www.cubicweb.org/doc/en/C010-setup.en.html#miseenplaceenv +.. _cubicweb: https://www.cubicweb.org/ +.. _overview: https://docs.cubicweb.org/tutorials/base/index.html +.. _forge: https://www.cubicweb.org/project?vtitle=All%20cubicweb%20projects +.. _installation: https://docs.cubicweb.org/book/admin/setup.html#setupenv Home page --------- diff -r 4482e94daabe -r 68f0678fc543 doc/book/admin/config.rst --- a/doc/book/admin/config.rst Tue Jun 21 07:44:35 2016 +0200 +++ b/doc/book/admin/config.rst Thu Jun 23 15:48:39 2016 +0200 @@ -8,7 +8,6 @@ You can `configure the database`_ system of your choice: - `PostgreSQL configuration`_ - - `MySql configuration`_ - `SQLServer configuration`_ - `SQLite configuration`_ @@ -18,7 +17,6 @@ .. _`configure the database`: DatabaseInstallation_ .. _`PostgreSQL configuration`: PostgresqlConfiguration_ -.. _`MySql configuration`: MySqlConfiguration_ .. _`SQLServer configuration`: SQLServerConfiguration_ .. _`SQLite configuration`: SQLiteConfiguration_ .. _`Cubicweb resources configuration`: RessourcesConfiguration_ @@ -41,7 +39,7 @@ Each instance can be configured with its own database connection information, that will be stored in the instance's :file:`sources` file. The database to use will be chosen when creating the instance. CubicWeb is known to run with -Postgresql (recommended), SQLServer and SQLite, and may run with MySQL. +Postgresql (recommended), SQLServer and SQLite. Other possible sources of data include CubicWeb, Subversion, LDAP and Mercurial, but at least one relational database is required for CubicWeb to work. You do @@ -89,6 +87,10 @@ $ initdb -E UTF8 -D /path/to/pgsql +Note: ``initdb`` might not be in the PATH, so you may have to use its +absolute path instead (usually something like +``/usr/lib/postgresql/9.4/bin/initdb``). + Notice the encoding specification. This is necessary since |cubicweb| usually want UTF8 encoded database. If you use a cluster with the wrong encoding, you'll get error like:: @@ -105,6 +107,7 @@ $ chown username /path/to/pgsql + Database authentication +++++++++++++++++++++++ @@ -116,31 +119,42 @@ $ su $ su - postgres - $ createuser -s -P username + $ createuser -s -P The option `-P` (for password prompt), will encrypt the password with the method set in the configuration file :file:`pg_hba.conf`. If you do not use this option `-P`, then the default value will be null and you will need to set it with:: - $ su postgres -c "echo ALTER USER username WITH PASSWORD 'userpasswd' | psql" + $ su postgres -c "echo ALTER USER WITH PASSWORD '' | psql" The above login/password will be requested when you will create an instance with `cubicweb-ctl create` to initialize the database of your instance. + +Database creation ++++++++++++++++++ + +If you create the database by hand (instead of using the `cubicweb-ctl +db-create` tool), you may want to make sure that the local settings are +properly set. For example, if you need to handle french accents +properly for indexing and sorting, you may need to create the database +with something like:: + + $ createdb --encoding=UTF-8 --locale=fr_FR.UTF-8 -t template0 -O + Notice that the `cubicweb-ctl db-create` does database initialization that may requires a postgres superuser. That's why a login/password is explicitly asked at this step, so you can use there a superuser without using this user when running the instance. Things that require special privileges at this step: * database creation, require the 'create database' permission -* install the plpython extension language (require superuser) -* install the tsearch extension for postgres version prior to 8.3 (require superuser) +* install the `plpython` extension language (require superuser) To avoid using a super user each time you create an install, a nice trick is to install plpython (and tsearch when needed) on the special `template1` database, so they will be installed automatically when cubicweb databases are created -without even with needs for special access rights. To do so, run :: +without needs for special access rights. To do so, run :: # Installation of plpythonu language by default :: $ createlang -U pgadmin plpythonu template1 @@ -151,29 +165,6 @@ default plpython is an 'untrusted' language and as such can't be used by non superuser. This update fix that problem by making it trusted. -To install the tsearch plain-text index extension on postgres prior to 8.3, run:: - - cat /usr/share/postgresql/8.X/contrib/tsearch2.sql | psql -U username template1 - - -.. _MySqlConfiguration: - -MySql -~~~~~ -.. warning:: - CubicWeb's MySQL support is not commonly used, so things may or may not work properly. - -You must add the following lines in ``/etc/mysql/my.cnf`` file:: - - transaction-isolation=READ-COMMITTED - default-storage-engine=INNODB - default-character-set=utf8 - max_allowed_packet = 128M - -.. Note:: - It is unclear whether mysql supports indexed string of arbitrary length or - not. - .. _SQLServerConfiguration: @@ -226,4 +217,3 @@ .. Note:: SQLite is great for testing and to play with cubicweb but is not suited for production environments. - diff -r 4482e94daabe -r 68f0678fc543 doc/book/devweb/internationalization.rst --- a/doc/book/devweb/internationalization.rst Tue Jun 21 07:44:35 2016 +0200 +++ b/doc/book/devweb/internationalization.rst Thu Jun 23 15:48:39 2016 +0200 @@ -227,3 +227,29 @@ It is also possible to explicitly use the with _cw.pgettext(context, msgid). + + +Specialize translation for an application cube +`````````````````````````````````````````````` + +Every cube has its own translation files. For a specific application cube +it can be useful to specialize translations of other cubes. You can either mark +those strings for translation using `_` in the python code, or add a +`static-messages.pot` file into the `i18n` directory. This file +looks like: :: + + msgid "" + msgstr "" + "PO-Revision-Date: YEAR-MO-DA HO:MI +ZONE\n" + "MIME-Version: 1.0\n" + "Content-Type: text/plain; charset=UTF-8\n" + "Content-Transfer-Encoding: 8bit\n" + "Generated-By: pygettext.py 1.5\n" + "Plural-Forms: nplurals=2; plural=(n > 1);\n" + + msgig "expression to be translated" + msgstr "" + +Doing this, ``expression to be translated`` will be taken into account by +the ``i18ncube`` command and additional messages will then appear in `.po` files +of the cube. diff -r 4482e94daabe -r 68f0678fc543 server/sources/rql2sql.py --- a/server/sources/rql2sql.py Tue Jun 21 07:44:35 2016 +0200 +++ b/server/sources/rql2sql.py Thu Jun 23 15:48:39 2016 +0200 @@ -187,7 +187,8 @@ try: thisexistssols, thisexistsvars = existssols[var.scope] except KeyError: - thisexistssols = [newsols[0]] + # copy to avoid shared dict in newsols and exists sols + thisexistssols = [newsols[0].copy()] thisexistsvars = set() existssols[var.scope] = thisexistssols, thisexistsvars for i in range(len(newsols)-1, 0, -1): @@ -199,6 +200,13 @@ for i in range(1, len(newsols)): if vtype != newsols[i][vname]: unstable.add(vname) + # remove unstable variables from exists solutions: the possible types of these variables are not + # properly represented in exists solutions, so we have to remove and reinject them later + # according to the outer solution (see `iter_exists_sols`) + for sols, _ in existssols.values(): + for vname in unstable: + for sol in sols: + sol.pop(vname, None) if invariants: # filter out duplicates newsols_ = [] @@ -400,24 +408,30 @@ thisexistssols, thisexistsvars = self.existssols[exists] notdone_outside_vars = set() # when iterating other solutions inner to an EXISTS subquery, we should - # reset variables which have this exists node as scope at each iteration + # reset variables which have this EXISTS node as scope at each iteration for var in exists.stmt.defined_vars.values(): if var.scope is exists: thisexistsvars.add(var.name) elif var.name not in self.done: notdone_outside_vars.add(var) - origsol = self.solution + # make a copy of the outer statement's solution for later restore + origsol = self.solution.copy() origtables = self.tables done = self.done for thisexistssol in thisexistssols: for vname in self.unstablevars: - if thisexistssol[vname] != origsol[vname] and vname in thisexistsvars: + # check first if variable belong to the EXISTS's scope, else it may be missing from + # `thisexistssol` + if vname in thisexistsvars and thisexistssol[vname] != origsol[vname]: break else: self.tables = origtables.copy() - self.solution = thisexistssol + # overwrite current outer solution by EXISTS solution (the later will be missing + # unstable outer variables) + self.solution.update(thisexistssol) yield 1 - # cleanup self.done from stuff specific to exists + # cleanup self.done from stuff specific to EXISTS, so they will be reconsidered in + # the next round for var in thisexistsvars: if var in done: done.remove(var) @@ -428,6 +442,7 @@ for rel in exists.iget_nodes(Relation): if rel in done: done.remove(rel) + # restore original solution self.solution = origsol self.tables = origtables diff -r 4482e94daabe -r 68f0678fc543 server/test/unittest_rql2sql.py --- a/server/test/unittest_rql2sql.py Tue Jun 21 07:44:35 2016 +0200 +++ b/server/test/unittest_rql2sql.py Thu Jun 23 15:48:39 2016 +0200 @@ -574,8 +574,18 @@ ''', '''SELECT _X.cw_eid FROM cw_CWSourceSchemaConfig AS _X LEFT OUTER JOIN owned_by_relation AS rel_owned_by1 ON (rel_owned_by1.eid_from=_X.cw_eid) WHERE EXISTS(SELECT 1 FROM created_by_relation AS rel_created_by0, cw_CWUser AS _U WHERE rel_created_by0.eid_from=_X.cw_eid AND rel_created_by0.eid_to=_U.cw_eid) AND _X.cw_cw_schema IS NOT NULL -''') - ] +'''), + + ('Any X WHERE EXISTS(X in_state S, S name "state name"), X is in (Affaire, Note)', + '''SELECT _X.cw_eid +FROM cw_Affaire AS _X +WHERE EXISTS(SELECT 1 FROM cw_State AS _S WHERE _X.cw_in_state=_S.cw_eid AND _S.cw_name=state name) +UNION ALL +SELECT _X.cw_eid +FROM cw_Note AS _X +WHERE EXISTS(SELECT 1 FROM cw_State AS _S WHERE _X.cw_in_state=_S.cw_eid AND _S.cw_name=state name)'''), + +] ADVANCED_WITH_GROUP_CONCAT = [ ("Any X,GROUP_CONCAT(TN) GROUPBY X ORDERBY XN WHERE T tags X, X name XN, T name TN, X is CWGroup", diff -r 4482e94daabe -r 68f0678fc543 web/request.py --- a/web/request.py Tue Jun 21 07:44:35 2016 +0200 +++ b/web/request.py Thu Jun 23 15:48:39 2016 +0200 @@ -884,9 +884,15 @@ self.session.data.pop(self.pageid, None) else: try: - del self.session.data[self.pageid][key] + page_data = self.session.data[self.pageid] + del page_data[key] except KeyError: pass + else: + # make sure we write the session data value in the + # self.session.data dict-like object so any session + # handler can "detect" and manage the persistency + self.session.data[self.pageid] = page_data # user-agent detection #################################################### diff -r 4482e94daabe -r 68f0678fc543 web/views/autoform.py --- a/web/views/autoform.py Tue Jun 21 07:44:35 2016 +0200 +++ b/web/views/autoform.py Thu Jun 23 15:48:39 2016 +0200 @@ -484,13 +484,19 @@ def _add_pending(req, eidfrom, rel, eidto, kind): key = 'pending_%s' % kind - pendings = req.session.data.setdefault(key, set()) - pendings.add( (int(eidfrom), rel, int(eidto)) ) + pendings = req.session.data.get(key, []) + value = (int(eidfrom), rel, int(eidto)) + if value not in pendings: + pendings.append(value) + req.session.data[key] = pendings def _remove_pending(req, eidfrom, rel, eidto, kind): key = 'pending_%s' % kind pendings = req.session.data[key] - pendings.remove( (int(eidfrom), rel, int(eidto)) ) + value = (int(eidfrom), rel, int(eidto)) + if value in pendings: + pendings.remove(value) + req.session.data[key] = pendings @ajaxfunc(output_type='json') def remove_pending_insert(self, args): diff -r 4482e94daabe -r 68f0678fc543 web/views/basetemplates.py --- a/web/views/basetemplates.py Tue Jun 21 07:44:35 2016 +0200 +++ b/web/views/basetemplates.py Thu Jun 23 15:48:39 2016 +0200 @@ -46,6 +46,8 @@ w(u'') def template_header(self, content_type, view=None, page_title='', additional_headers=()): + self._cw.html_headers.define_var('BASE_URL', self._cw.base_url()) + self._cw.html_headers.define_var('DATA_URL', self._cw.datadir_url) w = self.whead # explictly close the tag to avoid IE 6 bugs while browsing DOM w(u'' % xml_escape(self._cw.base_url())) diff -r 4482e94daabe -r 68f0678fc543 web/views/editforms.py --- a/web/views/editforms.py Tue Jun 21 07:44:35 2016 +0200 +++ b/web/views/editforms.py Thu Jun 23 15:48:39 2016 +0200 @@ -20,25 +20,21 @@ """ __docformat__ = "restructuredtext en" -from cubicweb import _ from copy import copy from six.moves import range -from logilab.mtconverter import xml_escape -from logilab.common.decorators import cached from logilab.common.registry import yes from logilab.common.deprecation import class_moved +from cubicweb import _ from cubicweb import tags -from cubicweb.predicates import (match_kwargs, one_line_rset, non_final_entity, - specified_etype_implements, is_instance) +from cubicweb.predicates import (one_line_rset, non_final_entity, + specified_etype_implements, is_instance) from cubicweb.view import EntityView -from cubicweb.schema import display_name -from cubicweb.web import stdmsgs, eid_param, \ - formfields as ff, formwidgets as fw -from cubicweb.web.form import FormViewMixIn, FieldNotFound +from cubicweb.web import stdmsgs, eid_param, formwidgets as fw +from cubicweb.web.form import FormViewMixIn from cubicweb.web.views import uicfg, forms, reledit _pvdc = uicfg.primaryview_display_ctrl @@ -52,7 +48,8 @@ domid = 'deleteconf' copy_nav_params = True form_buttons = [fw.Button(stdmsgs.BUTTON_DELETE, cwaction='delete'), - fw.Button(stdmsgs.BUTTON_CANCEL, cwaction='cancel')] + fw.Button(stdmsgs.BUTTON_CANCEL, + {'class': fw.Button.css_class + ' cwjs-edition-cancel'})] def __init__(self, *args, **kwargs): super(DeleteConfForm, self).__init__(*args, **kwargs)