--- a/__pkginfo__.py Wed Feb 13 17:06:44 2019 +0100
+++ b/__pkginfo__.py Wed Feb 13 17:07:13 2019 +0100
@@ -51,6 +51,7 @@
include_dirs = []
+
def gecode_version():
version = [3,3,1]
if osp.exists('data/gecode_version.cc'):
@@ -63,6 +64,7 @@
pass
return version
+
def encode_version(a,b,c):
return ((a<<16)+(b<<8)+c)
--- a/rql/__init__.py Wed Feb 13 17:06:44 2019 +0100
+++ b/rql/__init__.py Wed Feb 13 17:07:13 2019 +0100
@@ -41,6 +41,7 @@
- variables type resolving
- comparison of two queries
"""
+
def __init__(self, schema, uid_func_mapping=None, special_relations=None,
resolver_class=None, backend=None):
# chech schema
@@ -82,6 +83,7 @@
def get_backend(self):
return self._checker.backend
+
def set_backend(self, backend):
self._checker.backend = backend
backend = property(get_backend, set_backend)
--- a/rql/_exceptions.py Wed Feb 13 17:06:44 2019 +0100
+++ b/rql/_exceptions.py Wed Feb 13 17:07:13 2019 +0100
@@ -19,23 +19,30 @@
__docformat__ = "restructuredtext en"
+
class RQLException(Exception):
"""Base exception for exceptions of the rql module."""
+
class MissingType(RQLException):
"""Raised when there is some expected type missing from a schema."""
+
class UsesReservedWord(RQLException):
"""Raised when the schema uses a reserved word as type or relation."""
+
class RQLSyntaxError(RQLException):
"""Raised when there is a syntax error in the rql string."""
+
class TypeResolverException(RQLException):
"""Raised when we are unable to guess variables' type."""
+
class BadRQLQuery(RQLException):
"""Raised when there is a no sense in the rql query."""
+
class CoercionError(RQLException):
"""Failed to infer type of a math expression."""
--- a/rql/analyze.py Wed Feb 13 17:06:44 2019 +0100
+++ b/rql/analyze.py Wed Feb 13 17:07:13 2019 +0100
@@ -44,6 +44,7 @@
# Gecode solver not available
#rql_solve = None # uncomment to force using logilab-constraint
+
class ConstraintCSPProblem(object):
def __init__(self):
self.constraints = []
@@ -139,6 +140,7 @@
_EQV:"eqv"
}
+
class GecodeCSPProblem(object):
"""Builds an internal representation of the constraint
that will be passed to the rql_solve module which implements
@@ -157,6 +159,7 @@
but it should be fixed anyways.
When fixing that we should also replace string nodes by integers
"""
+
def __init__(self):
self.constraints = []
self.op = [_AND]
@@ -552,22 +555,31 @@
def visit_and(self, et, constraints):
pass
+
def visit_or(self, ou, constraints):
pass
+
def visit_not(self, et, constraints):
pass
+
def visit_comparison(self, comparison, constraints):
pass
+
def visit_mathexpression(self, mathexpression, constraints):
pass
+
def visit_function(self, function, constraints):
pass
+
def visit_variableref(self, variableref, constraints):
pass
+
def visit_constant(self, constant, constraints):
pass
+
def visit_keyword(self, keyword, constraints):
pass
+
def visit_exists(self, exists, constraints):
pass
--- a/rql/base.py Wed Feb 13 17:06:44 2019 +0100
+++ b/rql/base.py Wed Feb 13 17:07:13 2019 +0100
@@ -169,6 +169,7 @@
new_child.parent = self
return old_child, self, i
+
class BinaryNode(Node):
__slots__ = ()
--- a/rql/compare.py Wed Feb 13 17:06:44 2019 +0100
+++ b/rql/compare.py Wed Feb 13 17:07:13 2019 +0100
@@ -27,6 +27,7 @@
from rql.nodes import VariableRef, Variable, Function, Relation, Comparison
+
def compare_tree(request1, request2):
"""Compares 2 RQL requests.
@@ -35,6 +36,7 @@
"""
return make_canon_dict(request1) == make_canon_dict(request2)
+
def make_canon_dict(rql_tree, verbose=0):
"""Return a canonical representation of the request as a dictionnary."""
allvars = {}
@@ -57,6 +59,7 @@
pprint(canon)
return canon
+
def sort(canon_dict):
"""Remove the all_variables entry and sort other entries in place."""
del canon_dict['all_variables']
@@ -64,9 +67,11 @@
for values in canon_dict['restriction'].values():
values.sort()
+
class SkipChildren(Exception):
"""Signal indicating to ignore the current child."""
+
class RQLCanonizer(object):
"""Build a dictionnary which represents a RQL syntax tree."""
@@ -204,6 +209,7 @@
pass
return ('=', lhs)
+
def make_rhs_reminder(rhs, canon):
"""Return a reminder for a relation's right hand side
(i.e a Comparison object).
--- a/rql/editextensions.py Wed Feb 13 17:06:44 2019 +0100
+++ b/rql/editextensions.py Wed Feb 13 17:07:13 2019 +0100
@@ -21,6 +21,7 @@
from rql.nodes import Constant, Variable, VariableRef, Relation, make_relation
+
def switch_selection(rqlst, new_var, old_var):
"""Switch the select variable from old_var (VariableRef instance) to
new_var (Variable instance).
@@ -28,6 +29,7 @@
rqlst.remove_selected(old_var)
rqlst.add_selected(new_var, 0)
+
def add_main_restriction(rqlst, new_type, r_type, direction):
"""The result_tree must represent the same restriction as 'rqlst' and :
- 'new_varname' IS <new_type>
@@ -48,6 +50,7 @@
rqlst.add_restriction(rel_rest)
return new_var
+
def remove_has_text_relation(node):
"""Remove has_text relation."""
for rel in node.iget_nodes(Relation):
@@ -55,6 +58,7 @@
node.remove_node(rel)
return
+
def get_vars_relations(node):
"""Return a dict with 'var_names' as keys, and the list of relations which
concern them.
--- a/rql/interfaces.py Wed Feb 13 17:06:44 2019 +0100
+++ b/rql/interfaces.py Wed Feb 13 17:07:13 2019 +0100
@@ -22,6 +22,7 @@
from logilab.common.interface import Interface
+
class ISchema(Interface):
"""RQL expects some base types to exists: String, Float, Int, Boolean, Date
and a base relation : is
@@ -71,6 +72,7 @@
"""Return a list of types which can be object of this relation.
"""
+
class IEntitySchema(Interface):
"""Interface for Entity schema."""
--- a/rql/nodes.py Wed Feb 13 17:06:44 2019 +0100
+++ b/rql/nodes.py Wed Feb 13 17:07:13 2019 +0100
@@ -57,6 +57,7 @@
KEYWORD_MAP = {'NOW' : datetime.now,
'TODAY': date.today}
+
def etype_from_pyobj(value):
"""guess yams type from python value"""
# note:
@@ -65,6 +66,7 @@
# __class__ attribute
return ETYPE_PYOBJ_MAP[type(value)]
+
def variable_ref(var):
"""get a VariableRef"""
if isinstance(var, Variable):
@@ -72,6 +74,7 @@
assert isinstance(var, VariableRef)
return var
+
def variable_refs(node):
for vref in node.iget_nodes(VariableRef):
if isinstance(vref.variable, Variable):
@@ -134,6 +137,7 @@
relation.append(cmpop)
return relation
+
def make_constant_restriction(var, rtype, value, ctype, operator='='):
if ctype is None:
ctype = etype_from_pyobj(value)
@@ -252,6 +256,7 @@
class SubQuery(BaseNode):
"""WITH clause"""
__slots__ = ('aliases', 'query')
+
def __init__(self, aliases=None, query=None):
if aliases is not None:
self.set_aliases(aliases)
@@ -277,10 +282,12 @@
def as_string(self, kwargs=None):
return '%s BEING (%s)' % (','.join(v.name for v in self.aliases),
self.query.as_string(kwargs=kwargs))
+
def __repr__(self):
return '%s BEING (%s)' % (','.join(repr(v) for v in self.aliases),
repr(self.query))
+
class And(BinaryNode):
"""a logical AND node (binary)"""
__slots__ = ()
@@ -289,6 +296,7 @@
"""return the tree as an encoded rql string"""
return '%s, %s' % (self.children[0].as_string(kwargs=kwargs),
self.children[1].as_string(kwargs=kwargs))
+
def __repr__(self):
return '%s AND %s' % (repr(self.children[0]), repr(self.children[1]))
@@ -320,6 +328,7 @@
class Not(Node):
"""a logical NOT node (unary)"""
__slots__ = ()
+
def __init__(self, expr=None):
Node.__init__(self)
if expr is not None:
@@ -538,6 +547,7 @@
CMP_OPERATORS = frozenset(('=', '!=', '<', '<=', '>=', '>', 'ILIKE', 'LIKE', 'REGEXP'))
+
class Comparison(HSMixin, Node):
"""handle comparisons:
@@ -969,6 +979,7 @@
def set_scope(self, scopenode):
self._set_scope('scope', scopenode)
+
def get_scope(self):
return self.stinfo['scope']
scope = property(get_scope, set_scope)
@@ -1082,6 +1093,7 @@
class ColumnAlias(Referenceable):
__slots__ = ('colnum', 'query',
'_q_sql', '_q_sqltable') # XXX cubicweb specific
+
def __init__(self, alias, colnum, query=None):
super(ColumnAlias, self).__init__(alias)
self.colnum = int(colnum)
--- a/rql/parser.py Wed Feb 13 17:06:44 2019 +0100
+++ b/rql/parser.py Wed Feb 13 17:07:13 2019 +0100
@@ -51,6 +51,7 @@
import re
from yapps import runtime
+
class HerculeScanner(runtime.Scanner):
patterns = [
("'IN'", re.compile('IN')),
@@ -101,11 +102,14 @@
('INT', re.compile('-?\\d+')),
('SUBSTITUTE', re.compile('%\\([A-Za-z_0-9]+\\)s')),
]
+
def __init__(self, str,*args,**kw):
runtime.Scanner.__init__(self,None,{'\\s+':None,'/\\*(?:[^*]|\\*(?!/))*\\*/':None,},str,*args,**kw)
+
class Hercule(runtime.Parser):
Context = runtime.Context
+
def goal(self, _parent=None):
_context = self.Context(_parent, self._scanner, 'goal', [])
_token = self._peek('DELETE', 'INSERT', 'SET', 'r"\\("', 'DISTINCT', 'E_TYPE', context=_context)
--- a/rql/pygments_ext.py Wed Feb 13 17:06:44 2019 +0100
+++ b/rql/pygments_ext.py Wed Feb 13 17:07:13 2019 +0100
@@ -16,6 +16,7 @@
__all__ = ['RqlLexer']
+
class RqlLexer(RegexLexer):
"""
Lexer for Relation Query Language.
--- a/rql/rqlgen.py Wed Feb 13 17:06:44 2019 +0100
+++ b/rql/rqlgen.py Wed Feb 13 17:07:13 2019 +0100
@@ -24,6 +24,7 @@
NOT = 1
+
class RQLGenerator(object):
"""
Helper class to generate RQL strings.
@@ -198,6 +199,7 @@
RQLGENERATOR = RQLGenerator()
+
def _test():
"""
Launch doctest
--- a/rql/stcheck.py Wed Feb 13 17:06:44 2019 +0100
+++ b/rql/stcheck.py Wed Feb 13 17:07:13 2019 +0100
@@ -36,6 +36,7 @@
except KeyError:
return subvarname + str(id(select))
+
def bloc_simplification(variable, term):
try:
variable.stinfo['blocsimplification'].add(term)
@@ -45,6 +46,7 @@
class GoTo(Exception):
"""Exception used to control the visit of the tree."""
+
def __init__(self, node):
self.node = node
@@ -54,6 +56,7 @@
VAR_HAS_UID_REL = 4
VAR_HAS_REL = 8
+
class STCheckState(object):
def __init__(self):
self.errors = []
@@ -69,6 +72,7 @@
except KeyError:
self.var_info[var] = vi
+
class RQLSTChecker(object):
"""Check a RQL syntax tree for errors not detected on parsing.
@@ -132,6 +136,7 @@
if not len(select.selection) == nbselected:
state.error('when using union, all subqueries should have '
'the same number of selected terms')
+
def leave_union(self, node, state):
pass
@@ -206,16 +211,19 @@
def visit_insert(self, insert, state):
self._visit_selectedterm(insert, state)
+
def leave_insert(self, node, state):
pass
def visit_delete(self, delete, state):
self._visit_selectedterm(delete, state)
+
def leave_delete(self, node, state):
pass
def visit_set(self, update, state):
self._visit_selectedterm(update, state)
+
def leave_set(self, node, state):
pass
@@ -223,6 +231,7 @@
def visit_exists(self, node, state):
pass
+
def leave_exists(self, node, state):
pass
@@ -280,6 +289,7 @@
def visit_and(self, et, state):
pass #assert len(et.children) == 2, len(et.children)
+
def leave_and(self, node, state):
pass
@@ -304,11 +314,13 @@
raise GoTo(r1)
except AttributeError:
pass
+
def leave_or(self, node, state):
pass
def visit_not(self, not_, state):
state.under_not.append(True)
+
def leave_not(self, not_, state):
state.under_not.pop()
# NOT normalization
@@ -400,15 +412,19 @@
def visit_comparison(self, comparison, state):
pass #assert len(comparison.children) in (1,2), len(comparison.children)
+
def leave_comparison(self, node, state):
pass
def visit_mathexpression(self, mathexpr, state):
pass #assert len(mathexpr.children) == 2, len(mathexpr.children)
+
def leave_mathexpression(self, node, state):
pass
+
def visit_unaryexpression(self, unaryexpr, state):
pass #assert len(unaryexpr.children) == 2, len(unaryexpr.children)
+
def leave_unaryexpression(self, node, state):
pass
@@ -692,6 +708,7 @@
if vref is rhs.children[0] and rschema.final:
update_attrvars(var, relation, lhs)
+
def update_attrvars(var, relation, lhs):
if var.stinfo['relations'] - var.stinfo['rhsrelations']:
raise BadRQLQuery('variable %s should not be used as rhs of attribute relation %s'
--- a/rql/stmts.py Wed Feb 13 17:06:44 2019 +0100
+++ b/rql/stmts.py Wed Feb 13 17:07:13 2019 +0100
@@ -40,6 +40,7 @@
_MARKER = object()
+
def _check_references(defined, varrefs):
refs = {}
for var in defined.values():
@@ -53,14 +54,18 @@
raise AssertionError('vref %r is not referenced (%r)' % (vref, vref.stmt))
return True
+
class undo_modification(object):
def __init__(self, select):
self.select = select
+
def __enter__(self):
self.select.save_state()
+
def __exit__(self):
self.select.recover()
+
class ScopeNode(BaseNode):
solutions = () # list of possibles solutions for used variables
_varmaker = None # variable names generator, built when necessary
@@ -226,6 +231,7 @@
warn('offset is now a Select node attribute', DeprecationWarning,
stacklevel=2)
return self.children[-1].offset
+
def set_offset(self, offset):
if len(self.children) == 1:
self.children[-1].set_offset(offset)
@@ -240,6 +246,7 @@
warn('limit is now a Select node attribute', DeprecationWarning,
stacklevel=2)
return self.children[-1].limit
+
def set_limit(self, limit):
if len(self.children) == 1:
self.children[-1].set_limit(limit)
--- a/rql/undo.py Wed Feb 13 17:06:44 2019 +0100
+++ b/rql/undo.py Wed Feb 13 17:07:13 2019 +0100
@@ -22,6 +22,7 @@
from rql.nodes import Exists, VariableRef, Variable, BinaryNode
from rql.stmts import Select
+
class SelectionManager(object):
"""Manage the operation stacks."""
@@ -58,8 +59,10 @@
"""flush the current operations"""
self.op_list = []
+
class NodeOperation(object):
"""Abstract class for node manipulation operations."""
+
def __init__(self, node, stmt=None):
self.node = node
if stmt is None:
@@ -72,14 +75,18 @@
# Undo for variable manipulation operations ##################################
+
class MakeVarOperation(NodeOperation):
"""Defines how to undo make_variable()."""
+
def undo(self, selection):
"""undo the operation on the selection"""
self.stmt.undefine_variable(self.node)
+
class UndefineVarOperation(NodeOperation):
"""Defines how to undo undefine_variable()."""
+
def __init__(self, node, stmt, solutions):
NodeOperation.__init__(self, node, stmt)
self.solutions = solutions
@@ -90,6 +97,7 @@
self.stmt.defined_vars[var.name] = var
self.stmt.solutions = self.solutions
+
class SelectVarOperation(NodeOperation):
"""Defines how to undo add_selected()."""
@@ -97,8 +105,10 @@
"""undo the operation on the selection"""
self.stmt.remove_selected(self.node)
+
class UnselectVarOperation(NodeOperation):
"""Defines how to undo unselect_var()."""
+
def __init__(self, var, pos):
NodeOperation.__init__(self, var)
self.index = pos
@@ -117,8 +127,10 @@
"""undo the operation on the selection"""
self.stmt.remove_node(self.node)
+
class ReplaceNodeOperation(object):
"""Defines how to undo 'replace node'."""
+
def __init__(self, old_node, new_node):
self.old_node = old_node
self.new_node = new_node
@@ -136,6 +148,7 @@
def __str__(self):
return "ReplaceNodeOperation %s by %s" % (self.old_node, self.new_node)
+
class RemoveNodeOperation(NodeOperation):
"""Defines how to undo remove_node()."""
@@ -174,6 +187,7 @@
for varref in self.node.iget_nodes(VariableRef):
varref.register_reference()
+
class AddSortOperation(NodeOperation):
"""Defines how to undo 'add sort'."""
@@ -181,8 +195,10 @@
"""undo the operation on the selection"""
self.stmt.remove_sort_term(self.node)
+
class RemoveSortOperation(NodeOperation):
"""Defines how to undo 'remove sort'."""
+
def __init__(self, node):
NodeOperation.__init__(self, node)
self.index = self.stmt.orderby.index(self.node)
@@ -191,6 +207,7 @@
"""undo the operation on the selection"""
self.stmt.add_sort_term(self.node, self.index)
+
class AddGroupOperation(NodeOperation):
"""Defines how to undo 'add group'."""
@@ -198,6 +215,7 @@
"""undo the operation on the selection"""
self.stmt.remove_group_term(self.node)
+
class RemoveGroupOperation(NodeOperation):
"""Defines how to undo 'remove group'."""
@@ -211,11 +229,13 @@
# misc operations #############################################################
+
class ChangeValueOperation(object):
def __init__(self, previous_value, node=None):
self.value = previous_value
self.node = node
+
class SetDistinctOperation(ChangeValueOperation):
"""Defines how to undo 'set_distinct'."""
@@ -223,6 +243,7 @@
"""undo the operation on the selection"""
self.node.distinct = self.value
+
class SetOffsetOperation(ChangeValueOperation):
"""Defines how to undo 'set_offset'."""
@@ -230,6 +251,7 @@
"""undo the operation on the selection"""
self.node.offset = self.value
+
class SetLimitOperation(ChangeValueOperation):
"""Defines how to undo 'set_limit'."""
@@ -237,8 +259,10 @@
"""undo the operation on the selection"""
self.node.limit = self.value
+
class SetOptionalOperation(ChangeValueOperation):
"""Defines how to undo 'set_limit'."""
+
def __init__(self, rel, previous_value):
self.rel = rel
self.value = previous_value
@@ -247,8 +271,10 @@
"""undo the operation on the selection"""
self.rel.optional = self.value
+
class SetHavingOperation(object):
"""Defines how to undo 'set_having'."""
+
def __init__(self, select, previous_value):
self.select = select
self.value = previous_value
@@ -265,8 +291,10 @@
# Union operations ############################################################
+
class AppendSelectOperation(object):
"""Defines how to undo append_select()."""
+
def __init__(self, union, select):
self.union = union
self.select = select
@@ -276,8 +304,10 @@
self.select.parent = self.union
self.union.children.remove(self.select)
+
class RemoveSelectOperation(AppendSelectOperation):
"""Defines how to undo append_select()."""
+
def __init__(self, union, select, origindex):
AppendSelectOperation.__init__(self, union, select)
self.origindex = origindex
--- a/rql/utils.py Wed Feb 13 17:06:44 2019 +0100
+++ b/rql/utils.py Wed Feb 13 17:07:13 2019 +0100
@@ -22,6 +22,8 @@
from rql._exceptions import BadRQLQuery
UPPERCASE = u'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+
+
def decompose_b26(index, table=UPPERCASE):
"""Return a letter (base-26) decomposition of index."""
div, mod = divmod(index, 26)
@@ -29,6 +31,7 @@
return table[mod]
return decompose_b26(div-1) + table[mod]
+
class rqlvar_maker(object):
"""Yields consistent RQL variable names.
@@ -38,6 +41,7 @@
"""
# NOTE: written a an iterator class instead of a simple generator to be
# picklable
+
def __init__(self, stop=None, index=0, defined=None, aliases=None):
self.index = index
self.stop = stop
@@ -75,6 +79,7 @@
RQL_FUNCTIONS_REGISTRY = SQL_FUNCTIONS_REGISTRY.copy()
+
@monkeypatch(FunctionDescr)
def st_description(self, funcnode, mainindex, tr):
return '%s(%s)' % (
@@ -82,6 +87,7 @@
', '.join(sorted(child.get_description(mainindex, tr)
for child in iter_funcnode_variables(funcnode))))
+
@monkeypatch(FunctionDescr)
def st_check_backend(self, backend, funcnode):
if not self.supports(backend):
@@ -92,10 +98,12 @@
def rql_return_type(self, funcnode):
return self.rtype
+
@monkeypatch(CAST)
def st_description(self, funcnode, mainindex, tr):
return self.rql_return_type(funcnode)
+
@monkeypatch(CAST)
def rql_return_type(self, funcnode):
return funcnode.children[0].value
@@ -108,10 +116,12 @@
except AttributeError as ex:
yield term
+
def is_keyword(word):
"""Return true if the given word is a RQL keyword."""
return word.upper() in KEYWORDS
+
def common_parent(node1, node2):
"""return the first common parent between node1 and node2
@@ -131,14 +141,17 @@
node2 = node2.parent
raise Exception('DUH!')
+
def register_function(funcdef):
RQL_FUNCTIONS_REGISTRY.register_function(funcdef)
SQL_FUNCTIONS_REGISTRY.register_function(funcdef)
+
def function_description(funcname):
"""Return the description (:class:`FunctionDescr`) for a RQL function."""
return RQL_FUNCTIONS_REGISTRY.get_function(funcname)
+
def quote(value):
"""Quote a string value."""
res = ['"']
@@ -149,6 +162,7 @@
res.append('"')
return ''.join(res)
+
def uquote(value):
"""Quote a unicode string value."""
res = ['"']
@@ -172,6 +186,7 @@
visit_method = getattr(visitor, 'leave_%s' % visit_id)
return visit_method(self, *args, **kwargs)
+
class RQLVisitorHandler(object):
"""Handler providing a dummy implementation of all callbacks necessary
to visit a RQL syntax tree.
@@ -179,33 +194,45 @@
def visit_union(self, union):
pass
+
def visit_insert(self, insert):
pass
+
def visit_delete(self, delete):
pass
+
def visit_set(self, update):
pass
def visit_select(self, selection):
pass
+
def visit_sortterm(self, sortterm):
pass
def visit_and(self, et):
pass
+
def visit_or(self, ou):
pass
+
def visit_not(self, not_):
pass
+
def visit_relation(self, relation):
pass
+
def visit_comparison(self, comparison):
pass
+
def visit_mathexpression(self, mathexpression):
pass
+
def visit_function(self, function):
pass
+
def visit_variableref(self, variable):
pass
+
def visit_constant(self, constant):
pass
--- a/setup.py Wed Feb 13 17:06:44 2019 +0100
+++ b/setup.py Wed Feb 13 17:07:13 2019 +0100
@@ -48,6 +48,7 @@
"""Extend build_ext command to pass through compilation error.
In fact, if gecode extension fail, rql will use logilab.constraint
"""
+
def run(self):
try:
build_ext.build_ext.run(self)
--- a/test/unittest_analyze.py Wed Feb 13 17:06:44 2019 +0100
+++ b/test/unittest_analyze.py Wed Feb 13 17:07:13 2019 +0100
@@ -23,6 +23,7 @@
FINAL_ETYPES = ('String', 'Boolean', 'Int', 'Float', 'Date', 'Datetime')
+
class ERSchema(object):
def __cmp__(self, other):
@@ -81,6 +82,7 @@
def specialized_by(self):
return self._specialized_by
+
class DummySchema(object):
def __init__(self):
@@ -181,6 +183,7 @@
def rschema(self, r_type):
return self._relations[r_type]
+
def eschema(self, e_type):
return self._types[e_type]
@@ -200,6 +203,7 @@
"""check wrong queries arre correctly detected
"""
eids = {10: 'Eetype'}
+
def _type_from_eid(self, eid):
return self.eids.get(eid, 'Person')
--- a/test/unittest_compare.py Wed Feb 13 17:06:44 2019 +0100
+++ b/test/unittest_compare.py Wed Feb 13 17:07:13 2019 +0100
@@ -20,6 +20,7 @@
from rql import RQLHelper
from unittest_analyze import RelationSchema, EntitySchema, DummySchema as BaseSchema
+
class DummySchema(BaseSchema):
def __init__(self):
@@ -34,6 +35,7 @@
self._relations['nom'] = self._relations['name']
self._relations['prenom'] = self._relations['firstname']
+
class RQLCompareClassTest(TestCase):
""" Compare RQL strings """
@classmethod
--- a/test/unittest_editextensions.py Wed Feb 13 17:06:44 2019 +0100
+++ b/test/unittest_editextensions.py Wed Feb 13 17:07:13 2019 +0100
@@ -22,6 +22,7 @@
from rql.nodes import Exists
from rql.editextensions import *
+
class RQLUndoTestCase(TestCase):
def test_selected(self):
--- a/test/unittest_nodes.py Wed Feb 13 17:06:44 2019 +0100
+++ b/test/unittest_nodes.py Wed Feb 13 17:07:13 2019 +0100
@@ -31,11 +31,13 @@
annotator = RQLSTAnnotator(schema, {})
helper = RQLHelper(schema, None, {'eid': 'uid'})
+
def sparse(rql):
tree = helper.parse(rql)
helper.compute_solutions(tree)
return tree
+
class EtypeFromPyobjTC(TestCase):
def test_bool(self):
self.assertEqual(nodes.etype_from_pyobj(True), 'Boolean')
--- a/test/unittest_parser.py Wed Feb 13 17:06:44 2019 +0100
+++ b/test/unittest_parser.py Wed Feb 13 17:07:13 2019 +0100
@@ -172,6 +172,7 @@
'Any U,G WHERE U login UL, G name GL, G is CWGroup HAVING UPPER(UL)?=UPPER(GL);',
)
+
class ParserHercule(unittest.TestCase):
_syntaxerr = SyntaxError
--- a/test/unittest_utils.py Wed Feb 13 17:06:44 2019 +0100
+++ b/test/unittest_utils.py Wed Feb 13 17:07:13 2019 +0100
@@ -22,6 +22,7 @@
from rql import utils, nodes, parse
+
class Visitor(utils.RQLVisitorHandler):
def visit(self, node):
node.accept(self)
--- a/tools/rql_analyze.py Wed Feb 13 17:06:44 2019 +0100
+++ b/tools/rql_analyze.py Wed Feb 13 17:07:13 2019 +0100
@@ -31,6 +31,7 @@
#print(schema)
+
def cmp_sol(sol1, sol2):
ret = True
for l in sol1:
@@ -43,6 +44,7 @@
print("Sol2", l)
return ret
+
def analyze_rq(rq):
print("RQL:", rq)
helper1 = RQLHelper(schema, Resolver=ETypeResolver)