Commit 557342f0 authored by Nicolas Chauvat's avatar Nicolas Chauvat
Browse files

merge 3.27.6 into 3.28

--HG--
branch : 3.28
Pipeline #62367 failed with stages
in 35 minutes and 5 seconds
......@@ -614,6 +614,8 @@ d238badfc268ad4440b3238a24690858bad3fbdd debian/3.25.3-1
b8567725c473b701fe9352e578ad6e05c523c1f2 3.25.4
b8567725c473b701fe9352e578ad6e05c523c1f2 centos/3.25.4-1
b8567725c473b701fe9352e578ad6e05c523c1f2 debian/3.25.4-1
2b12cb5f470a14bb313830353bcffd49ac1534a8 3.25.5
2b12cb5f470a14bb313830353bcffd49ac1534a8 debian/3.25.5
199851fcddd4b45e3d7f40efcd1739134c33db2a 3.26.0
199851fcddd4b45e3d7f40efcd1739134c33db2a debian/3.26.0-1
199851fcddd4b45e3d7f40efcd1739134c33db2a centos/3.26.0-1
......@@ -655,6 +657,11 @@ fb6aecd654a34b68b81a444340d5c6c8a7c80664 debian/3.26.16-1
2d1d6c5ab3c3b8f8a348d79fe92d2e897eccc698 debian/3.26.18-1
d5fb8ecdd5c0cdc6c3df757f2bb8826ec99aa866 3.26.19
d5fb8ecdd5c0cdc6c3df757f2bb8826ec99aa866 debian/3.26.19-1
09a1f898e5eb170e4c9b5cfa6dca59f6419af5a3 3.26.20
439cb73f58abcc86b16d344686940b73a7a471d6 3.26.21
439cb73f58abcc86b16d344686940b73a7a471d6 debian/3.26.21
d40fb37abd55ea1eb2d06a3c404fbf6060bd5d64 3.26.22
d40fb37abd55ea1eb2d06a3c404fbf6060bd5d64 debian/3.26.22
e77900f19390fdf38515afdd212d21ac2592693d 3.27.0
e77900f19390fdf38515afdd212d21ac2592693d debian/3.27.0-1
917601bb5b1ba13eb92296f5bd82eaa89e99bdad 3.27.1
......@@ -665,6 +672,7 @@ e731c31eaed06ac0a781db4d9a36d8b3732a4852 debian/3.27.2-1
85284f0282667f577c1422725605565b95b5a9c7 debian/3.27.3-1
f2e07e9cc36753c9bb21030a05a6d715aa33a289 3.27.4
7e69862f2332df296950afa7d4943471dec01986 3.27.5
7b332e2e0287182c6e9283b7debf4eb7233d3bad 3.27.6
695832965852f2a8d6c767dab0f74903c962feb8 3.28.0rc1
2c0ecdfda9c46f95ef514efa0c9c06c96c98b4bd 3.28.0
4b2725c4066a0015afa66267dea3bd392235194d 3.28.1
......
# -*- coding: iso-8859-1 -*-
# -*- coding: utf-8 -*-
# copyright 2003-2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
......@@ -47,7 +47,7 @@ def decompose_b26(index, ascii=False):
"""return a letter (base-26) decomposition of index"""
if ascii:
return base_decompose_b26(index)
return base_decompose_b26(index, u'abcdefghijklmnopqrstuvwxyz')
return base_decompose_b26(index, u'éabcdefghijklmnopqrstuvwxyz')
def get_max_length(eschema, attrname):
"""returns the maximum length allowed for 'attrname'"""
......@@ -120,7 +120,7 @@ class _ValueGenerator(object):
# always use plain text when no format is specified
attrprefix = attrname[:max(attrlength-num_len-1, 0)]
if format == 'text/html':
value = u'<span>%s<b>%d</b></span>' % (attrprefix, index)
value = u'<span>é%s<b>%d</b></span>' % (attrprefix, index)
elif format == 'text/rest':
value = u"""
title
......@@ -128,10 +128,10 @@ title
* %s
* %d
* &
* é&
""" % (attrprefix, index)
else:
value = u'&%s%d' % (attrprefix, index)
value = u'é&%s%d' % (attrprefix, index)
return value[:attrlength]
def generate_password(self, entity, attrname, index):
......
......@@ -50,6 +50,8 @@ from getpass import getpass
from os.path import basename
from time import clock
from six.moves import input
from logilab.common.fileutils import lines
from logilab.common.ureports import Table, TextWriter
......@@ -162,7 +164,7 @@ def run(args):
usage(1)
queries = [query for query in lines(args[1]) if not query.startswith('#')]
if user is None:
user = raw_input('login: ')
user = input('login: ')
if password is None:
password = getpass('password: ')
from cubicweb.cwconfig import instance_configuration
......
# -*- coding: iso-8859-1 -*-
# -*- coding: utf-8 -*-
# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
......@@ -66,7 +66,7 @@ class ValueGeneratorTC(TestCase):
def test_string(self):
"""test string generation"""
surname = self.person_valgen.generate_attribute_value({}, 'surname', 12)
self.assertEqual(surname, u'&surname12')
self.assertEqual(surname, u'é&surname12')
def test_domain_value(self):
"""test value generation from a given domain value"""
......
......@@ -47,7 +47,8 @@ class DevCtlTC(TestCase):
expected_project_content = ['setup.py', 'test', 'MANIFEST.in',
'cubicweb_foo',
'cubicweb-foo.spec', 'debian', 'README',
'tox.ini', '.gitlab-ci.yaml']
'tox.ini', '.gitlab-ci.yml',
'.hgignore']
expected_package_content = ['i18n', 'hooks.py', 'views.py',
'migration', 'entities.py', 'schema.py',
'__init__.py', 'data', '__pkginfo__.py']
......
# -*- coding: iso-8859-1 -*-
# -*- coding: utf-8 -*-
# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
......
......@@ -701,11 +701,11 @@ class ServerMigrationHelper(MigrationHelper):
# remove cubes'entity and relation types
for rschema in fsschema.relations():
if rschema not in removedcubes_schema and rschema in reposchema:
self.cmd_drop_relation_type(rschema.type)
self.cmd_drop_relation_type(rschema.type, commit=False)
toremove = [eschema for eschema in fsschema.entities()
if eschema not in removedcubes_schema and eschema in reposchema]
for eschema in reversed(order_eschemas(toremove)):
self.cmd_drop_entity_type(eschema.type)
self.cmd_drop_entity_type(eschema.type, commit=False)
for rschema in fsschema.relations():
if rschema in removedcubes_schema and rschema in reposchema:
# check if attributes/relations has been added to entities from
......@@ -714,13 +714,13 @@ class ServerMigrationHelper(MigrationHelper):
if (fromtype, totype) not in removedcubes_schema[rschema.type].rdefs and \
(fromtype, totype) in reposchema[rschema.type].rdefs:
self.cmd_drop_relation_definition(
str(fromtype), rschema.type, str(totype))
str(fromtype), rschema.type, str(totype), commit=False)
# execute post-remove files
for cube in reversed(removedcubes):
self.cmd_exec_event_script('postremove', cube)
self.rqlexec('DELETE CWProperty X WHERE X pkey %(pk)s',
{'pk': u'system.version.' + cube}, ask_confirm=False)
self.commit()
self.commit()
# schema migration actions ################################################
......
......@@ -54,7 +54,7 @@ def group_mapping(cnx, interactive=True):
print('or just type enter to skip permissions granted to a group')
for group in missing:
while True:
value = raw_input('eid for group %s: ' % group).strip()
value = input('eid for group %s: ' % group).strip()
if not value:
continue
try:
......
......@@ -138,6 +138,15 @@ def repo_cnx(config):
"""return a in-memory repository and a repoapi connection to it"""
from cubicweb import repoapi
from cubicweb.server.utils import manager_userpasswd
db_driver = config.system_source_config.get('db-driver')
if db_driver == "sqlite":
if not os.path.exists(config.system_source_config.get('db-name')):
print("Your database does not exist.")
sys.exit(1)
from sqlite3 import OperationalError
else:
from psycopg2 import OperationalError
try:
login = config.default_admin_config['login']
pwd = config.default_admin_config['password']
......@@ -152,6 +161,9 @@ def repo_cnx(config):
print('-> Error: wrong user/password.')
# reset cubes else we'll have an assertion error on next retry
config._cubes = None
except OperationalError as exc: # sqlite or psycopg2 driver, depending on db_driver
print("OperationalError: %s" % exc)
sys.exit(1)
login, pwd = manager_userpasswd()
......@@ -933,10 +945,11 @@ option is set to "y" or "yes" (may be long for large database).'}
config.repairing = self.config.force
repo, _cnx = repo_cnx(config)
with repo.internal_cnx() as cnx:
checkintegrity.check(repo, cnx,
self.config.checks,
self.config.reindex,
self.config.autofix)
checkintegrity.check(
repo, cnx,
self.config.checks,
self.config.reindex,
self.config.autofix)
class DBIndexSanityCheckCommand(Command):
......
# -*- coding: iso-8859-1 -*-
# -*- coding: utf-8 -*-
# copyright 2003 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
......@@ -690,18 +690,18 @@ class QuerierTC(BaseQuerierTC):
## self.assertEqual(rset.rows[0][0], 'admin')
def test_select_searchable_text_1(self):
rset = self.qexecute(u"INSERT Personne X: X nom 'bidle'")
rset = self.qexecute(u"INSERT Societe X: X nom 'bidle'")
rset = self.qexecute(u"INSERT Personne X: X nom 'bidüle'")
rset = self.qexecute(u"INSERT Societe X: X nom 'bidüle'")
rset = self.qexecute("INSERT Societe X: X nom 'chouette'")
rset = self.qexecute('Any X where X has_text %(text)s', {'text': u'bidle'})
rset = self.qexecute('Any X where X has_text %(text)s', {'text': u'bidüle'})
self.assertEqual(len(rset.rows), 2, rset.rows)
rset = self.qexecute(u'Any N where N has_text "bidle"')
rset = self.qexecute(u'Any N where N has_text "bidüle"')
self.assertEqual(len(rset.rows), 2, rset.rows)
biduleeids = [r[0] for r in rset.rows]
rset = self.qexecute(u'Any N where NOT N has_text "bidle"')
rset = self.qexecute(u'Any N where NOT N has_text "bidüle"')
self.assertFalse([r[0] for r in rset.rows if r[0] in biduleeids])
# duh?
rset = self.qexecute('Any X WHERE X has_text %(text)s', {'text': u'a'})
rset = self.qexecute('Any X WHERE X has_text %(text)s', {'text': u'ça'})
def test_select_searchable_text_2(self):
rset = self.qexecute("INSERT Personne X: X nom 'bidule'")
......@@ -718,11 +718,11 @@ class QuerierTC(BaseQuerierTC):
self.assertEqual(len(rset.rows), 1, rset.rows)
def test_select_multiple_searchable_text(self):
self.qexecute(u"INSERT Personne X: X nom 'bidle'")
self.qexecute(u"INSERT Personne X: X nom 'bidüle'")
self.qexecute("INSERT Societe X: X nom 'chouette', S travaille X")
self.qexecute(u"INSERT Personne X: X nom 'bidle'")
self.qexecute(u"INSERT Personne X: X nom 'bidüle'")
rset = self.qexecute('Personne X WHERE X has_text %(text)s, X travaille S, S has_text %(text2)s',
{'text': u'bidle',
{'text': u'bidüle',
'text2': u'chouette',}
)
self.assertEqual(len(rset.rows), 1, rset.rows)
......@@ -1495,7 +1495,7 @@ Any P1,B,E WHERE P1 identity P2 WITH
self.qexecute("INSERT Tag X: X name %(name)s,"
"X modification_date %(modification_date)s,"
"X creation_date %(creation_date)s",
{'name': u'name0',
{'name': u'éname0',
'modification_date': '2003/03/12 11:00',
'creation_date': '2000/07/03 11:00'})
rset = self.qexecute('Any lower(N) ORDERBY LOWER(N) WHERE X is Tag, X name N,'
......
# -*- coding: iso-8859-1 -*-
# -*- coding: utf-8 -*-
# copyright 2003-2016 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
......@@ -95,10 +95,10 @@ class RepositoryTC(CubicWebTC):
with self.admin_access.repo_cnx() as cnx:
cnx.execute('INSERT CWUser X: X login %(login)s, X upassword %(passwd)s, '
'X in_group G WHERE G name "users"',
{'login': u"barnab", 'passwd': u"hhh".encode('UTF8')})
{'login': u"barnabé", 'passwd': u"héhéhé".encode('UTF8')})
cnx.commit()
repo = self.repo
self.assertTrue(repo.authenticate_user(cnx, u"barnab", password=u"hhh".encode('UTF8')))
self.assertTrue(repo.authenticate_user(cnx, u"barnabé", password=u"héhéhé".encode('UTF8')))
def test_rollback_on_execute_validation_error(self):
class ValidationErrorAfterHook(Hook):
......
......@@ -8,6 +8,7 @@ from cubicweb.server.serverctl import (
DBDumpCommand,
RepositorySchedulerCommand,
SynchronizeSourceCommand,
repo_cnx,
)
from cubicweb.server.serverconfig import ServerConfiguration
......@@ -80,6 +81,16 @@ class ServerCTLTC(testlib.CubicWebTC):
self.assertEqual(str(exc.exception), 'All sources where not synced')
self.assertEqual(len(cnx.find('Card', title=u'fail')), 0)
def test_db_check_no_db(self):
init_db_name = self.config.system_source_config["db-name"]
self.config.system_source_config["db-name"] = "not existing db"
try:
with self.assertRaises(SystemExit) as ctx:
repo_cnx(self.config)
self.assertEqual(ctx.exception.code, 1)
finally:
self.config.system_source_config["db-name"] = init_db_name
if __name__ == '__main__':
from unittest import main
......
default:
image: python
# avoid running duplicate pipelines for both topic head and MR
# see: https://docs.gitlab.com/ee/ci/yaml/#switch-between-branch-pipelines-and-merge-request-pipelines
workflow:
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
- if: '$CI_COMMIT_REF_NAME =~ /^topic\/.*/ && $CI_OPEN_MERGE_REQUESTS'
when: never
- when: always
stages:
- lint
- tests
- after-tests
before_script:
- pip install tox
flake8:
stage: lint
script: tox -e flake8
check-manifest:
stage: lint
script: tox -e check-manifest
black:
stage: lint
script: tox -e black
yamllint:
rules:
- changes:
- "**/*.yaml"
- "**/*.yml"
stage: lint
before_script:
- pip install tox
script:
- tox -e yamllint
# If you have mypy set up
# mypy:
# stage: lint
# script: tox -e mypy
py3:
stage: tests
script: tox -e py3
# If you have your project on readthedocs, you can automatically trigger its
# build by setting:
# - READTHEDOCS_TOKEN
# - READTHEDOCS_ID
# in your heptapod project Settings > CI/CD > Variables.
# You can find those secrets by creating a new integration in your readthedocs
# project here: https://readthedocs.org/dashboard/cubicweb_%(cubename)s/integrations/
#
# Related documentation:
# https://docs.readthedocs.io/en/latest/webhooks.html#using-the-generic-api-integration
#
# trigger-readthedocs:
# only:
# refs:
# - branch/default
# stage: after-tests
# script:
# # regarding the " everywhere when there is a '%%': yaml is extremly weird when %% are involved
# - curl -X POST -d "token=${READTHEDOCS_TOKEN}" https://readthedocs.org/api/v2/webhook/cubicweb_%(cubename)s/${READTHEDOCS_ID} -w "\nhttp code:"\ "%%{http_code}\n" -f
syntax: glob
*~
#*
*.bak
*.old
*.pyo
*.pyc
*.cache
*.swp
*.swo
*.mo
*.lock
*.sqlite
__pycache__
*.egg-info
.tox/
.pybuild
.cache
.coverage
.pytest-cache
build/
dist/
node_modules/
.mypy_cache/
debian/*.log
debian/*.substvars
debian/files
test/data/database/
test/data/ldapdb/
test/data/uicache/
docs/_build
# copyright 2003-2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
# contact https://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# This file is part of CubicWeb.
#
......@@ -14,7 +14,7 @@
# details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with CubicWeb. If not, see <http://www.gnu.org/licenses/>.
# with CubicWeb. If not, see <https://www.gnu.org/licenses/>.
import sys
import os
from os.path import join
......@@ -54,7 +54,8 @@ class CubicWebCtlTC(unittest.TestCase):
def test_list_configurations(self):
ListCommand(None).run(['configurations'])
configs = [line[2:].strip() for line in self.stream.getvalue().splitlines()
configs = [line[2:].strip()
for line in self.stream.getvalue().splitlines()
if line.startswith('* ')]
self.assertIn('all-in-one', configs)
self.assertIn('pyramid', configs)
......
# copyright 2003 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
# contact https://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# This file is part of CubicWeb.
#
......@@ -14,7 +14,7 @@
# details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with CubicWeb. If not, see <http://www.gnu.org/licenses/>.
# with CubicWeb. If not, see <https://www.gnu.org/licenses/>.
"""
.. autoclass:: AutomaticEntityForm
......@@ -730,10 +730,13 @@ class UnrelatedDivs(EntityView):
mode = '%s:%s:%s:%s' % (role, entity.eid, rschema.type, eschema)
url = self._cw.build_url(entity.rest_path(), vid='search-associate',
__mode=mode)
options.append((eschema.display_name(self._cw),
'<option value="%s">%s %s</option>' % (
xml_escape(url), _('Search for'), eschema.display_name(self._cw))))
return [option for _name, option in sorted(options)]
options.append(
(eschema.display_name(self._cw),
'<option value="%s">%s %s</option>' % (
xml_escape(url),
_('Search for'),
eschema.display_name(self._cw))))
return [option for name, option in sorted(options)]
# The automatic entity form ####################################################
......
# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
# copyright 2003-2021 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact https://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# This file is part of CubicWeb.
#
......@@ -14,7 +14,7 @@
# details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with CubicWeb. If not, see <http://www.gnu.org/licenses/>.
# with CubicWeb. If not, see <https://www.gnu.org/licenses/>.
"""Set of base controllers, which are directly plugged into the application
object to handle publication.
"""
......
......@@ -22,6 +22,12 @@ cubicweb (3.28.0-1) unstable; urgency=medium
-- Chabot Simon <schabot@logilab.fr> Wed, 24 Jun 2020 10:17:13 +0200
cubicweb (3.27.6-1) unstable; urgency=medium
* New upstream release
-- Nicolas Chauvat <nico@volans.logilab.fr> Wed, 16 Jun 2021 15:46:29 +0200
cubicweb (3.27.5-1) unstable; urgency=medium
* New patch release
......@@ -113,6 +119,24 @@ cubicweb (3.27.0~a0-1) unstable; urgency=medium
-- Denis Laxalde <denis.laxalde@logilab.fr> Wed, 24 Jul 2019 16:08:43 +0200
cubicweb (3.26.22-1) unstable; urgency=medium
* New upstream release
-- Nicola Spanti <nspanti@logilab.fr> Fri, 30 Apr 2021 16:48:52 +0200
cubicweb (3.26.21-1) unstable; urgency=medium
* New upstream release
-- Nicola Spanti <nspanti@logilab.fr> Tue, 27 Apr 2021 15:52:47 +0200
cubicweb (3.26.20-1) unstable; urgency=medium
* New patch release
-- Laurent Peuch <cortex@worlddomination.be> Fri, 05 Mar 2021 12:13:02 +0100
cubicweb (3.26.19-1) unstable; urgency=medium
* New upstream release
......@@ -228,6 +252,12 @@ cubicweb (3.26.0-1) unstable; urgency=medium
-- Denis Laxalde <denis.laxalde@logilab.fr> Thu, 01 Feb 2018 09:24:01 +0100
cubicweb (3.25.5-1) unstable; urgency=medium
* backport SMTP authentication from 3.28
-- Carine Dengler <carine.dengler@logilab.fr> Fri, 23 Apr 2021 15:22:48 +0200
cubicweb (3.25.4-1) unstable; urgency=medium
* New upstream release.
......
......@@ -30,7 +30,7 @@ Build-Depends:
sphinx-common,
Standards-Version: 4.3.0
Homepage: https://www.cubicweb.org
X-Python3-Version: >= 3.6
X-Python3-Version: >= 3.7
Package: python3-cubicweb
......
......@@ -465,8 +465,8 @@ simplify greatly complex security definition and upgrade.
class my_relation(RelationDefinition):
__permissions__ = {'read': ('managers', 'users'),
'add': ('managers', RRQLExpression('U has_update_permission S')),
'delete': ('managers', RRQLExpression('U has_update_permission S'))
}
'delete': ('managers', RRQLExpression('U has_update_permission S')),
}
In the above example, user will be allowed to add/delete `my_relation` if he has
the `update` permission on the subject of the relation.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment