# HG changeset patch # User Sylvain Thénault # Date 1505485551 -7200 # Node ID 03b94c9863de5c8b424cc7ae20093ebd576bcc6a # Parent 14fdd5888cbb81b4b9e0eaa787b79bdb8269255b [rql2sql/test] Move base class from repotest to unittest_rql2sql It's only used there, so move it closer to its usage. Along the way, stop using lgc.testlib. diff -r 14fdd5888cbb -r 03b94c9863de cubicweb/devtools/repotest.py --- a/cubicweb/devtools/repotest.py Fri Sep 15 16:59:13 2017 +0200 +++ b/cubicweb/devtools/repotest.py Fri Sep 15 16:25:51 2017 +0200 @@ -1,4 +1,4 @@ -# copyright 2003-2016 LOGILAB S.A. (Paris, FRANCE), all rights reserved. +# copyright 2003 LOGILAB S.A. (Paris, FRANCE), all rights reserved. # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr # # This file is part of CubicWeb. @@ -24,10 +24,14 @@ from contextlib import contextmanager from pprint import pprint -from logilab.common.testlib import SkipTest -from cubicweb.devtools.testlib import RepoAccess from cubicweb.entities.authobjs import user_session_cache_key +from cubicweb.server import set_debug, debugged +from cubicweb.server.sources.rql2sql import remove_unused_solutions + +from .testlib import RepoAccess, BaseTestCase +from .fake import FakeRequest + def tuplify(mylist): return [tuple(item) for item in mylist] @@ -129,67 +133,7 @@ schema._eid_index[rdef.eid] = rdef -from logilab.common.testlib import TestCase, mock_object -from logilab.database import get_db_helper - -from rql import RQLHelper - -from cubicweb.devtools.testlib import BaseTestCase -from cubicweb.devtools.fake import FakeRepo, FakeConfig, FakeRequest, FakeConnection -from cubicweb.server import set_debug, debugged -from cubicweb.server.querier import QuerierHelper -from cubicweb.server.sources.rql2sql import SQLGenerator, remove_unused_solutions - -class RQLGeneratorTC(BaseTestCase): - schema = backend = None # set this in concrete class - - @classmethod - def setUpClass(cls): - if cls.backend is not None: - try: - cls.dbhelper = get_db_helper(cls.backend) - except ImportError as ex: - raise SkipTest(str(ex)) - - def setUp(self): - self.repo = FakeRepo(self.schema, config=FakeConfig(apphome=self.datadir)) - self.repo.system_source = mock_object(dbdriver=self.backend) - self.rqlhelper = RQLHelper(self.schema, - special_relations={'eid': 'uid', - 'has_text': 'fti'}, - backend=self.backend) - self.qhelper = QuerierHelper(self.repo, self.schema) - ExecutionPlan._check_permissions = _dummy_check_permissions - rqlannotation._select_principal = _select_principal - if self.backend is not None: - self.o = SQLGenerator(self.schema, self.dbhelper) - - def tearDown(self): - ExecutionPlan._check_permissions = _orig_check_permissions - rqlannotation._select_principal = _orig_select_principal - - def set_debug(self, debug): - set_debug(debug) - def debugged(self, debug): - return debugged(debug) - - def _prepare(self, rql): - #print '******************** prepare', rql - union = self.rqlhelper.parse(rql) - #print '********* parsed', union.as_string() - self.rqlhelper.compute_solutions(union) - #print '********* solutions', solutions - self.rqlhelper.simplify(union) - #print '********* simplified', union.as_string() - plan = self.qhelper.plan_factory(union, {}, FakeConnection(self.repo)) - plan.preprocess(union) - for select in union.children: - select.solutions.sort(key=lambda x: list(x.items())) - #print '********* ppsolutions', solutions - return union - - -class BaseQuerierTC(TestCase): +class BaseQuerierTC(BaseTestCase): repo = None # set this in concrete class def setUp(self): @@ -316,8 +260,6 @@ res = DumbOrderedDict(sorted(res.items(), key=lambda x: [list(y.items()) for y in x[1]])) return res, restricted -def _dummy_check_permissions(self, rqlst): - return {(): rqlst.solutions}, set() from cubicweb.server import rqlannotation _orig_select_principal = rqlannotation._select_principal diff -r 14fdd5888cbb -r 03b94c9863de cubicweb/server/test/unittest_rql2sql.py --- a/cubicweb/server/test/unittest_rql2sql.py Fri Sep 15 16:59:13 2017 +0200 +++ b/cubicweb/server/test/unittest_rql2sql.py Fri Sep 15 16:25:51 2017 +0200 @@ -1,4 +1,4 @@ -# copyright 2003-2016 LOGILAB S.A. (Paris, FRANCE), all rights reserved. +# copyright 2003 LOGILAB S.A. (Paris, FRANCE), all rights reserved. # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr # # This file is part of CubicWeb. @@ -26,17 +26,24 @@ from logilab.common.decorators import monkeypatch from rql import BadRQLQuery +from rql import RQLHelper from rql.utils import register_function, FunctionDescr from cubicweb import devtools -from cubicweb.devtools.repotest import RQLGeneratorTC -from cubicweb.server.sources.rql2sql import SQLGenerator, remove_unused_solutions +from cubicweb.devtools.fake import FakeRepo, FakeConfig, FakeConnection +from cubicweb.devtools.testlib import BaseTestCase +from cubicweb.server import rqlannotation +from cubicweb.server.querier import QuerierHelper, ExecutionPlan +from cubicweb.server.sources import rql2sql + +_orig_select_principal = rqlannotation._select_principal +_orig_check_permissions = ExecutionPlan._check_permissions def setUpModule(): """Monkey-patch the SQL generator to ensure solutions order is predictable.""" global orig_solutions_sql - orig_solutions_sql = SQLGenerator._solutions_sql + orig_solutions_sql = rql2sql.SQLGenerator._solutions_sql @monkeypatch def _solutions_sql(self, select, solutions, distinct, needalias): @@ -45,7 +52,7 @@ def tearDownModule(): """Remove monkey-patch done in setUpModule""" - SQLGenerator._solutions_sql = orig_solutions_sql + rql2sql.SQLGenerator._solutions_sql = orig_solutions_sql # add a dumb registered procedure @@ -1226,8 +1233,67 @@ '''SELECT rel_is0.eid_from FROM is_relation AS rel_is0 WHERE rel_is0.eid_to=2'''), +] - ] + +class RQLGeneratorTC(BaseTestCase): + schema = backend = None # set this in concrete class + + @classmethod + def setUpClass(cls): + if cls.backend is not None: + try: + cls.dbhelper = db.get_db_helper(cls.backend) + except ImportError as ex: + self.skipTest(str(ex)) + + def setUp(self): + self.repo = FakeRepo(self.schema, config=FakeConfig(apphome=self.datadir)) + self.repo.system_source = mock_object(dbdriver=self.backend) + self.rqlhelper = RQLHelper(self.schema, + special_relations={'eid': 'uid', + 'has_text': 'fti'}, + backend=self.backend) + self.qhelper = QuerierHelper(self.repo, self.schema) + + def _dummy_check_permissions(self, rqlst): + return {(): rqlst.solutions}, set() + + ExecutionPlan._check_permissions = _dummy_check_permissions + + def _select_principal(scope, relations): + def sort_key(something): + try: + return something.r_type + except AttributeError: + return (something[0].r_type, something[1]) + return _orig_select_principal(scope, relations, + _sort=lambda rels: sorted(rels, key=sort_key)) + + rqlannotation._select_principal = _select_principal + if self.backend is not None: + self.o = rql2sql.SQLGenerator(self.schema, self.dbhelper) + + def tearDown(self): + ExecutionPlan._check_permissions = _orig_check_permissions + rqlannotation._select_principal = _orig_select_principal + + def _prepare(self, rql): + #print '******************** prepare', rql + union = self.rqlhelper.parse(rql) + #print '********* parsed', union.as_string() + self.rqlhelper.compute_solutions(union) + #print '********* solutions', solutions + self.rqlhelper.simplify(union) + #print '********* simplified', union.as_string() + plan = self.qhelper.plan_factory(union, {}, FakeConnection(self.repo)) + plan.preprocess(union) + for select in union.children: + select.solutions.sort(key=lambda x: list(x.items())) + #print '********* ppsolutions', solutions + return union + + class CWRQLTC(RQLGeneratorTC): backend = 'sqlite' @@ -2273,21 +2339,23 @@ rqlst = mock_object(defined_vars={}) rqlst.defined_vars['A'] = mock_object(scope=rqlst, stinfo={}, _q_invariant=True) rqlst.defined_vars['B'] = mock_object(scope=rqlst, stinfo={}, _q_invariant=False) - self.assertEqual(remove_unused_solutions(rqlst, [{'A': 'RugbyGroup', 'B': 'RugbyTeam'}, - {'A': 'FootGroup', 'B': 'FootTeam'}], None), - ([{'A': 'RugbyGroup', 'B': 'RugbyTeam'}, - {'A': 'FootGroup', 'B': 'FootTeam'}], - {}, set('B')) - ) + self.assertEqual( + rql2sql.remove_unused_solutions(rqlst, [{'A': 'RugbyGroup', 'B': 'RugbyTeam'}, + {'A': 'FootGroup', 'B': 'FootTeam'}], None), + ([{'A': 'RugbyGroup', 'B': 'RugbyTeam'}, + {'A': 'FootGroup', 'B': 'FootTeam'}], + {}, set('B')) + ) def test_invariant_varying(self): rqlst = mock_object(defined_vars={}) rqlst.defined_vars['A'] = mock_object(scope=rqlst, stinfo={}, _q_invariant=True) rqlst.defined_vars['B'] = mock_object(scope=rqlst, stinfo={}, _q_invariant=False) - self.assertEqual(remove_unused_solutions(rqlst, [{'A': 'RugbyGroup', 'B': 'RugbyTeam'}, - {'A': 'FootGroup', 'B': 'RugbyTeam'}], None), - ([{'A': 'RugbyGroup', 'B': 'RugbyTeam'}], {}, set()) - ) + self.assertEqual( + rql2sql.remove_unused_solutions(rqlst, [{'A': 'RugbyGroup', 'B': 'RugbyTeam'}, + {'A': 'FootGroup', 'B': 'RugbyTeam'}], None), + ([{'A': 'RugbyGroup', 'B': 'RugbyTeam'}], {}, set()) + ) if __name__ == '__main__':