[py3k] Unicode everywhere, drop as_string()'s 'encoding' parameter
authorRémi Cardona <remi.cardona@free.fr>
Tue, 08 Sep 2015 18:08:07 +0200
changeset 780 43e30d2417b1
parent 779 d8451fa72dcc
child 781 7d5aa315998c
[py3k] Unicode everywhere, drop as_string()'s 'encoding' parameter WARNING: This is an API break Among other things we no longer use repr() for String constants, which means they consistently get quoted with double quotes instead of a mix of single and double quotes. Closes #1190507
debian/control
rql/analyze.py
rql/base.py
rql/nodes.py
rql/stmts.py
test/unittest_nodes.py
test/unittest_parser.py
test/unittest_stcheck.py
--- a/debian/control	Wed Jul 23 09:27:39 2014 +0200
+++ b/debian/control	Tue Sep 08 18:08:07 2015 +0200
@@ -23,7 +23,8 @@
  yapps2-runtime,
  python-logilab-database (>= 1.6.0),
  python-six (>= 1.4.0),
-Conflicts: cubicweb-common (<= 3.13.9)
+Breaks:
+ cubicweb-common (<= 3.21.0),
 Suggests: python-pygments
 Description: relationship query language (RQL) utilities
  A library providing the base utilities to handle RQL queries,
--- a/rql/analyze.py	Wed Jul 23 09:27:39 2014 +0200
+++ b/rql/analyze.py	Tue Sep 08 18:08:07 2015 +0200
@@ -336,7 +336,7 @@
         sols = constraints.solve()
 
         if not sols:
-            rql = node.as_string('utf8', self.kwargs)
+            rql = node.as_string(kwargs=self.kwargs)
             ex_msg = 'Unable to resolve variables types in "%s"' % (rql,)
             if True or self.debug:
                 ex_msg += '\n%s' % (constraints.get_output(),)
--- a/rql/base.py	Wed Jul 23 09:27:39 2014 +0200
+++ b/rql/base.py	Tue Sep 08 18:08:07 2015 +0200
@@ -22,6 +22,8 @@
 
 __docformat__ = "restructuredtext en"
 
+import sys
+
 from rql.utils import VisitableMixIn
 
 
@@ -29,9 +31,11 @@
     __slots__ = ('parent',)
 
     def __str__(self):
-        return self.as_string(encoding='utf-8')
+        s = self.as_string()
+        s = s.encode('unicode_escape') if sys.version_info < (3,) else s
+        return s
 
-    def as_string(self, encoding=None, kwargs=None):
+    def as_string(self, kwargs=None):
         """Return the tree as an encoded rql string."""
         raise NotImplementedError()
 
--- a/rql/nodes.py	Wed Jul 23 09:27:39 2014 +0200
+++ b/rql/nodes.py	Tue Sep 08 18:08:07 2015 +0200
@@ -29,6 +29,8 @@
 from datetime import datetime, date, time, timedelta
 from time import localtime
 
+from six import string_types
+
 from logilab.database import DYNAMIC_RTYPE
 
 from rql import CoercionError, RQLException
@@ -269,9 +271,9 @@
     def children(self):
         return self.aliases + [self.query]
 
-    def as_string(self, encoding=None, kwargs=None):
+    def as_string(self, kwargs=None):
         return '%s BEING (%s)' % (','.join(v.name for v in self.aliases),
-                                  self.query.as_string(encoding, kwargs))
+                                  self.query.as_string(kwargs=kwargs))
     def __repr__(self):
         return '%s BEING (%s)' % (','.join(repr(v) for v in self.aliases),
                                   repr(self.query))
@@ -280,10 +282,10 @@
     """a logical AND node (binary)"""
     __slots__ = ()
 
-    def as_string(self, encoding=None, kwargs=None):
+    def as_string(self, kwargs=None):
         """return the tree as an encoded rql string"""
-        return '%s, %s' % (self.children[0].as_string(encoding, kwargs),
-                           self.children[1].as_string(encoding, kwargs))
+        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]))
 
@@ -298,9 +300,9 @@
     """a logical OR node (binary)"""
     __slots__ = ()
 
-    def as_string(self, encoding=None, kwargs=None):
-        return '(%s) OR (%s)' % (self.children[0].as_string(encoding, kwargs),
-                                 self.children[1].as_string(encoding, kwargs))
+    def as_string(self, kwargs=None):
+        return '(%s) OR (%s)' % (self.children[0].as_string(kwargs=kwargs),
+                                 self.children[1].as_string(kwargs=kwargs))
 
     def __repr__(self):
         return '%s OR %s' % (repr(self.children[0]), repr(self.children[1]))
@@ -320,10 +322,10 @@
         if expr is not None:
             self.append(expr)
 
-    def as_string(self, encoding=None, kwargs=None):
+    def as_string(self, kwargs=None):
         if isinstance(self.children[0], (Exists, Relation)):
-            return 'NOT %s' % self.children[0].as_string(encoding, kwargs)
-        return 'NOT (%s)' % self.children[0].as_string(encoding, kwargs)
+            return 'NOT %s' % self.children[0].as_string(kwargs=kwargs)
+        return 'NOT (%s)' % self.children[0].as_string(kwargs=kwargs)
 
     def __repr__(self, encoding=None, kwargs=None):
         return 'NOT (%s)' % repr(self.children[0])
@@ -376,8 +378,8 @@
             return True
         raise NotImplementedError
 
-    def as_string(self, encoding=None, kwargs=None):
-        content = self.query and self.query.as_string(encoding, kwargs)
+    def as_string(self, kwargs=None):
+        content = self.query and self.query.as_string(kwargs=kwargs)
         return 'EXISTS(%s)' % content
 
     def __repr__(self):
@@ -443,13 +445,13 @@
             return False
         return True
 
-    def as_string(self, encoding=None, kwargs=None):
+    def as_string(self, kwargs=None):
         """return the tree as an encoded rql string"""
         try:
-            lhs = self.children[0].as_string(encoding, kwargs)
+            lhs = self.children[0].as_string(kwargs=kwargs)
             if self.optional in ('left', 'both'):
                 lhs += '?'
-            rhs = self.children[1].as_string(encoding, kwargs)
+            rhs = self.children[1].as_string(kwargs=kwargs)
             if self.optional in ('right', 'both'):
                 rhs += '?'
         except IndexError:
@@ -567,7 +569,7 @@
             return False
         return self.operator == other.operator
 
-    def as_string(self, encoding=None, kwargs=None):
+    def as_string(self, kwargs=None):
         """return the tree as an encoded rql string"""
         if len(self.children) == 0:
             return self.operator
@@ -577,13 +579,13 @@
                 lhsopt = '?'
             if self.optional in ('right', 'both'):
                 rhsopt = '?'
-            return '%s%s %s %s%s' % (self.children[0].as_string(encoding, kwargs),
+            return '%s%s %s %s%s' % (self.children[0].as_string(kwargs=kwargs),
                                      lhsopt, self.operator,
-                                     self.children[1].as_string(encoding, kwargs), rhsopt)
+                                     self.children[1].as_string(kwargs=kwargs), rhsopt)
         if self.operator == '=':
-            return self.children[0].as_string(encoding, kwargs)
+            return self.children[0].as_string(kwargs=kwargs)
         return '%s %s' % (self.operator,
-                          self.children[0].as_string(encoding, kwargs))
+                          self.children[0].as_string(kwargs=kwargs))
 
     def __repr__(self):
         return '%s %s' % (self.operator, ', '.join(repr(c) for c in self.children))
@@ -597,11 +599,11 @@
         BinaryNode.__init__(self, lhs, rhs)
         self.operator = operator
 
-    def as_string(self, encoding=None, kwargs=None):
+    def as_string(self, kwargs=None):
         """return the tree as an encoded rql string"""
-        return '(%s %s %s)' % (self.children[0].as_string(encoding, kwargs),
+        return '(%s %s %s)' % (self.children[0].as_string(kwargs=kwargs),
                                self.operator,
-                               self.children[1].as_string(encoding, kwargs))
+                               self.children[1].as_string(kwargs=kwargs))
 
     def __repr__(self):
         return '(%r %s %r)' % (self.children[0], self.operator,
@@ -642,10 +644,10 @@
         if child is not None:
             self.append(child)
 
-    def as_string(self, encoding=None, kwargs=None):
+    def as_string(self, kwargs=None):
         """return the tree as an encoded rql string"""
         return '%s%s' % (self.operator,
-                         self.children[0].as_string(encoding, kwargs))
+                         self.children[0].as_string(kwargs=kwargs))
 
     def __repr__(self):
         return '%s%r' % (self.operator, self.children[0])
@@ -677,9 +679,9 @@
             return False
         return self.name == other.name
 
-    def as_string(self, encoding=None, kwargs=None):
+    def as_string(self, kwargs=None):
         """return the tree as an encoded rql string"""
-        return '%s(%s)' % (self.name, ', '.join(c.as_string(encoding, kwargs)
+        return '%s(%s)' % (self.name, ', '.join(c.as_string(kwargs=kwargs)
                                                 for c in self.children))
 
     def __repr__(self):
@@ -730,11 +732,10 @@
             return False
         return self.type == other.type and self.value == other.value
 
-    def as_string(self, encoding=None, kwargs=None):
+    def as_string(self, kwargs=None):
         """return the tree as an encoded rql string (an unicode string is
         returned if encoding is None)
         """
-        u = str if sys.version_info >= (3,) else unicode
         if self.type is None:
             return 'NULL'
         if self.type in ('etype', 'Date', 'Datetime', 'Int', 'Float'):
@@ -746,25 +747,20 @@
             #     and linked relation
             if kwargs is not None:
                 value = kwargs.get(self.value, '???')
-                if sys.version_info < (3,) and isinstance(value, u):
-                    if encoding:
-                        value = quote(value.encode(encoding))
-                    else:
-                        value = uquote(value)
-                elif isinstance(value, str):
-                    value = quote(value)
+                if isinstance(value, string_types):
+                    value = uquote(value)
                 else:
                     value = repr(value)
                 return value
             return '%%(%s)s' % self.value
-        if sys.version_info < (3,) and isinstance(self.value, u):
-            if encoding is not None:
-                return quote(self.value.encode(encoding))
+        if isinstance(self.value, string_types):
             return uquote(self.value)
         return repr(self.value)
 
     def __repr__(self):
-        return self.as_string('utf8')
+        s = self.as_string()
+        s = s.encode('unicode_escape') if sys.version_info < (3,) else s
+        return s
 
     def eval(self, kwargs):
         if self.type == 'Substitute':
@@ -809,7 +805,7 @@
             return False
         return self.name == other.name
 
-    def as_string(self, encoding=None, kwargs=None):
+    def as_string(self, kwargs=None):
         """return the tree as an encoded rql string"""
         return self.name
 
@@ -871,7 +867,7 @@
             return False
         return self.asc == other.asc
 
-    def as_string(self, encoding=None, kwargs=None):
+    def as_string(self, kwargs=None):
         if self.asc:
             return '%s' % self.term
         return '%s DESC' % self.term
@@ -911,7 +907,7 @@
         if not self.stinfo.get('possibletypes'):
             self.stinfo['possibletypes'] = old.stinfo.get('possibletypes')
 
-    def as_string(self, encoding=None, kwargs=None):
+    def as_string(self, kwargs=None):
         """return the tree as an encoded rql string"""
         return self.name
 
--- a/rql/stmts.py	Wed Jul 23 09:27:39 2014 +0200
+++ b/rql/stmts.py	Tue Sep 08 18:08:07 2015 +0200
@@ -268,9 +268,9 @@
     def __repr__(self):
         return '\nUNION\n'.join(repr(select) for select in self.children)
 
-    def as_string(self, encoding=None, kwargs=None):
+    def as_string(self, kwargs=None):
         """return the tree as an encoded rql string"""
-        strings = [select.as_string(encoding, kwargs)
+        strings = [select.as_string(kwargs=kwargs)
                    for select in self.children]
         if len(strings) == 1:
             return strings[0]
@@ -473,12 +473,12 @@
     def __repr__(self):
         return self.as_string(userepr=True)
 
-    def as_string(self, encoding=None, kwargs=None, userepr=False):
+    def as_string(self, kwargs=None, userepr=False):
         """return the tree as an encoded rql string"""
         if userepr:
             as_string = repr
         else:
-            as_string = lambda x: x.as_string(encoding, kwargs)
+            as_string = lambda x: x.as_string(kwargs=kwargs)
         s = [','.join(as_string(term) for term in self.selection)]
         if self.groupby:
             s.append('GROUPBY ' + ','.join(as_string(term)
@@ -938,7 +938,7 @@
             result.append('HAVING ' + ','.join(repr(term) for term in self.having))
         return ' '.join(result)
 
-    def as_string(self, encoding=None, kwargs=None):
+    def as_string(self, kwargs=None):
         """return the tree as an encoded rql string"""
         result = ['DELETE']
         if self.main_variables:
@@ -947,12 +947,12 @@
         if self.main_relations:
             if self.main_variables:
                 result.append(',')
-            result.append(', '.join([rel.as_string(encoding, kwargs)
+            result.append(', '.join([rel.as_string(kwargs=kwargs)
                                      for rel in self.main_relations]))
         if self.where is not None:
-            result.append('WHERE ' + self.where.as_string(encoding, kwargs))
+            result.append('WHERE ' + self.where.as_string(kwargs=kwargs))
         if self.having:
-            result.append('HAVING ' + ','.join(term.as_string(encoding, kwargs)
+            result.append('HAVING ' + ','.join(term.as_string(kwargs=kwargs)
                                           for term in self.having))
         return ' '.join(result)
 
@@ -1031,19 +1031,19 @@
             result.append('HAVING ' + ','.join(repr(term) for term in self.having))
         return ' '.join(result)
 
-    def as_string(self, encoding=None, kwargs=None):
+    def as_string(self, kwargs=None):
         """return the tree as an encoded rql string"""
         result = ['INSERT']
         result.append(', '.join(['%s %s' % (etype, var)
                                  for etype, var in self.main_variables]))
         if self.main_relations:
             result.append(':')
-            result.append(', '.join([rel.as_string(encoding, kwargs)
+            result.append(', '.join([rel.as_string(kwargs=kwargs)
                                      for rel in self.main_relations]))
         if self.where is not None:
-            result.append('WHERE ' + self.where.as_string(encoding, kwargs))
+            result.append('WHERE ' + self.where.as_string(kwargs=kwargs))
         if self.having:
-            result.append('HAVING ' + ','.join(term.as_string(encoding, kwargs)
+            result.append('HAVING ' + ','.join(term.as_string(kwargs=kwargs)
                                                for term in self.having))
         return ' '.join(result)
 
@@ -1100,15 +1100,15 @@
             result.append('HAVING ' + ','.join(repr(term) for term in self.having))
         return ' '.join(result)
 
-    def as_string(self, encoding=None, kwargs=None):
+    def as_string(self, kwargs=None):
         """return the tree as an encoded rql string"""
         result = ['SET']
-        result.append(', '.join(rel.as_string(encoding, kwargs)
+        result.append(', '.join(rel.as_string(kwargs=kwargs)
                                 for rel in self.main_relations))
         if self.where is not None:
-            result.append('WHERE ' + self.where.as_string(encoding, kwargs))
+            result.append('WHERE ' + self.where.as_string(kwargs=kwargs))
         if self.having:
-            result.append('HAVING ' + ','.join(term.as_string(encoding, kwargs)
+            result.append('HAVING ' + ','.join(term.as_string(kwargs=kwargs)
                                                for term in self.having))
         return ' '.join(result)
 
--- a/test/unittest_nodes.py	Wed Jul 23 09:27:39 2014 +0200
+++ b/test/unittest_nodes.py	Tue Sep 08 18:08:07 2015 +0200
@@ -70,7 +70,7 @@
         x = next(select.get_selected_variables())
         self.assertRaises(RQLException, select.add_type_restriction, x.variable, 'Babar')
         select.add_type_restriction(x.variable, 'Person')
-        self.assertEqual(tree.as_string(), "Any X WHERE X is Person, X name ILIKE 'A%'")
+        self.assertEqual(tree.as_string(), 'Any X WHERE X is Person, X name ILIKE "A%"')
 
     def test_add_new_is_type_restriction_in(self):
         tree = self.parse("Any X WHERE X is IN(Person, Company), X name ILIKE 'A%'")
@@ -78,7 +78,7 @@
         x = next(select.get_selected_variables())
         select.add_type_restriction(x.variable, 'Company')
         # implementation is KISS (the IN remains)
-        self.assertEqual(tree.as_string(), "Any X WHERE X is IN(Company), X name ILIKE 'A%'")
+        self.assertEqual(tree.as_string(), 'Any X WHERE X is IN(Company), X name ILIKE "A%"')
 
     def test_add_new_is_type_restriction_in_nonregr(self):
         tree = self.parse('Any X WHERE X is IN(Person, Company, Student)')
@@ -92,20 +92,20 @@
         select = tree.children[0]
         x = next(select.get_selected_variables())
         self.assertRaises(RQLException, select.add_type_restriction, x.variable, 'Babar')
-        self.assertEqual(tree.as_string(), "Any X WHERE X is IN(Person, Company), X name ILIKE 'A%'")
+        self.assertEqual(tree.as_string(), 'Any X WHERE X is IN(Person, Company), X name ILIKE "A%"')
 
     def test_add_is_type_restriction_on_is_instance_of(self):
         select = self.parse("Any X WHERE X is_instance_of Person, X name ILIKE 'A%'").children[0]
         x = next(select.get_selected_variables())
         select.add_type_restriction(x.variable, 'Person')
-        self.assertEqual(select.as_string(), "Any X WHERE X name ILIKE 'A%', X is Person")
+        self.assertEqual(select.as_string(), 'Any X WHERE X name ILIKE "A%", X is Person')
 
     def test_add_new_is_type_restriction_in_on_is_instance_of(self):
         tree = self.parse("Any X WHERE X is_instance_of IN(Person, Company), X name ILIKE 'A%'")
         select = tree.children[0]
         x = next(select.get_selected_variables())
         select.add_type_restriction(x.variable, 'Company')
-        self.assertEqual(tree.as_string(), "Any X WHERE X name ILIKE 'A%', X is Company")
+        self.assertEqual(tree.as_string(), 'Any X WHERE X name ILIKE "A%", X is Company')
 
 
 class NodesTest(TestCase):
@@ -309,28 +309,28 @@
         self.assertEqual(tree.as_string(), 'Any X,Y GROUPBY X,Y')
 
     def test_recover_add_type_restriction_is_in(self):
-        tree = self._parse("Any X WHERE X is IN(Person, Company), X name ILIKE 'A%'")
+        tree = self._parse('Any X WHERE X is IN(Person, Company), X name ILIKE "A%"')
         annotator.annotate(tree) # needed to get typerel index
         tree.save_state()
         select = tree.children[0]
         x = next(select.get_selected_variables())
         select.add_type_restriction(x.variable, 'Company')
-        self.assertEqual(tree.as_string(), "Any X WHERE X is IN(Company), X name ILIKE 'A%'")
+        self.assertEqual(tree.as_string(), 'Any X WHERE X is IN(Company), X name ILIKE "A%"')
         tree.recover()
         tree.check_references()
-        self.assertEqual(tree.as_string(), "Any X WHERE X is IN(Person, Company), X name ILIKE 'A%'")
+        self.assertEqual(tree.as_string(), 'Any X WHERE X is IN(Person, Company), X name ILIKE "A%"')
 
     def test_recover_add_type_restriction_is_instance_of(self):
-        tree = self._parse("Any X WHERE X is_instance_of IN(Person, Company), X name ILIKE 'A%'")
+        tree = self._parse('Any X WHERE X is_instance_of IN(Person, Company), X name ILIKE "A%"')
         annotator.annotate(tree) # needed to get typerel index
         tree.save_state()
         select = tree.children[0]
         x = next(select.get_selected_variables())
         select.add_type_restriction(x.variable, 'Company')
-        self.assertEqual(tree.as_string(), "Any X WHERE X name ILIKE 'A%', X is Company")
+        self.assertEqual(tree.as_string(), 'Any X WHERE X name ILIKE "A%", X is Company')
         tree.recover()
         tree.check_references()
-        self.assertEqual(tree.as_string(), "Any X WHERE X is_instance_of IN(Person, Company), X name ILIKE 'A%'")
+        self.assertEqual(tree.as_string(), 'Any X WHERE X is_instance_of IN(Person, Company), X name ILIKE "A%"')
 
     def test_select_base_1(self):
         tree = self._parse("Any X WHERE X is Person")
@@ -488,7 +488,7 @@
         self.assertEqual(tree.main_variables[0][1].name, 'X')
 
     def test_insert_base_2(self):
-        tree = self._parse("INSERT Person X : X name 'bidule'")
+        tree = self._parse('INSERT Person X : X name "bidule"')
         # test specific attributes
         self.assertEqual(len(tree.main_relations), 1)
         self.assertIsInstance(tree.main_relations[0], nodes.Relation)
@@ -498,7 +498,7 @@
         self.assertEqual(tree.main_variables[0][1].name, 'X')
 
     def test_insert_multi(self):
-        tree = self._parse("INSERT Person X, Person Y : X name 'bidule', Y name 'chouette', X friend Y")
+        tree = self._parse('INSERT Person X, Person Y : X name "bidule", Y name "chouette", X friend Y')
         # test specific attributes
         self.assertEqual(len(tree.main_relations), 3)
         for relation in tree.main_relations:
@@ -512,7 +512,7 @@
         self.assertEqual(tree.main_variables[1][1].name, 'Y')
 
     def test_insert_where(self):
-        tree = self._parse("INSERT Person X : X name 'bidule', X friend Y WHERE Y name 'chouette'")
+        tree = self._parse('INSERT Person X : X name "bidule", X friend Y WHERE Y name "chouette"')
         self.assertEqual(len(tree.children), 4)
         self.assertIsInstance(tree.where, nodes.Relation)
         # test specific attributes
@@ -527,7 +527,7 @@
     # update tests ############################################################
 
     def test_update_1(self):
-        tree = self._parse("SET X name 'toto' WHERE X is Person, X name 'bidule'")
+        tree = self._parse('SET X name "toto" WHERE X is Person, X name "bidule"')
         self.assertIsInstance(tree, stmts.Set)
         self.assertEqual(len(tree.children), 2)
         self.assertIsInstance(tree.where, nodes.And)
@@ -536,13 +536,13 @@
     # deletion tests #########################################################
 
     def test_delete_1(self):
-        tree = self._parse("DELETE Person X WHERE X name 'toto'")
+        tree = self._parse('DELETE Person X WHERE X name "toto"')
         self.assertIsInstance(tree, stmts.Delete)
         self.assertEqual(len(tree.children), 2)
         self.assertIsInstance(tree.where, nodes.Relation)
 
     def test_delete_2(self):
-        tree = self._parse("DELETE X friend Y WHERE X name 'toto'")
+        tree = self._parse('DELETE X friend Y WHERE X name "toto"')
         self.assertIsInstance(tree, stmts.Delete)
         self.assertEqual(len(tree.children), 2)
         self.assertIsInstance(tree.where, nodes.Relation)
@@ -558,17 +558,17 @@
                           'Any X WHERE X is Person')
 
         tree = parse(u"Any X WHERE X has_text 'héhé'")
-        self.assertEqual(tree.as_string('utf8'),
-                          u'Any X WHERE X has_text "héhé"'.encode('utf8'))
+        self.assertEqual(tree.as_string(),
+                          u'Any X WHERE X has_text "héhé"')
         tree = parse(u"Any X WHERE X has_text %(text)s")
-        self.assertEqual(tree.as_string('utf8', {'text': u'héhé'}),
-                          u'Any X WHERE X has_text "héhé"'.encode('utf8'))
+        self.assertEqual(tree.as_string({'text': u'héhé'}),
+                          u'Any X WHERE X has_text "héhé"')
         tree = parse(u"Any X WHERE X has_text %(text)s")
-        self.assertEqual(tree.as_string('utf8', {'text': u'hé"hé'}),
-                          u'Any X WHERE X has_text "hé\\"hé"'.encode('utf8'))
+        self.assertEqual(tree.as_string({'text': u'hé"hé'}),
+                          u'Any X WHERE X has_text "hé\\"hé"')
         tree = parse(u"Any X WHERE X has_text %(text)s")
-        self.assertEqual(tree.as_string('utf8', {'text': u'hé"\'hé'}),
-                          u'Any X WHERE X has_text "hé\\"\'hé"'.encode('utf8'))
+        self.assertEqual(tree.as_string({'text': u'hé"\'hé'}),
+                          u'Any X WHERE X has_text "hé\\"\'hé"')
 
     def test_as_string_no_encoding(self):
         tree = parse(u"Any X WHERE X has_text 'héhé'")
--- a/test/unittest_parser.py	Wed Jul 23 09:27:39 2014 +0200
+++ b/test/unittest_parser.py	Tue Sep 08 18:08:07 2015 +0200
@@ -200,7 +200,7 @@
         self.assertEqual(isinstance(base, nodes.Or), 1)
         self.assertEqual(isinstance(base.children[0], nodes.And), 1)
         self.assertEqual(isinstance(base.children[1], nodes.Relation), 1)
-        self.assertEqual(str(tree), "Any X WHERE (X firstname 'lulu', X name 'toto') OR (X name 'tutu')")
+        self.assertEqual(str(tree), 'Any X WHERE (X firstname "lulu", X name "toto") OR (X name "tutu")')
 
     def test_precedence_2(self):
         tree = self.parse("Any X WHERE X firstname 'lulu', X name 'toto' OR X name 'tutu';")
@@ -208,7 +208,7 @@
         self.assertEqual(isinstance(base, nodes.And), 1)
         self.assertEqual(isinstance(base.children[0], nodes.Relation), 1)
         self.assertEqual(isinstance(base.children[1], nodes.Or), 1)
-        self.assertEqual(str(tree), "Any X WHERE X firstname 'lulu', (X name 'toto') OR (X name 'tutu')")
+        self.assertEqual(str(tree), 'Any X WHERE X firstname "lulu", (X name "toto") OR (X name "tutu")')
 
     def test_precedence_3(self):
         tree = self.parse("Any X WHERE X firstname 'lulu' AND (X name 'toto' or X name 'tutu');")
@@ -216,7 +216,7 @@
         self.assertEqual(isinstance(base, nodes.And), 1)
         self.assertEqual(isinstance(base.children[0], nodes.Relation), 1)
         self.assertEqual(isinstance(base.children[1], nodes.Or), 1)
-        self.assertEqual(str(tree), "Any X WHERE X firstname 'lulu', (X name 'toto') OR (X name 'tutu')")
+        self.assertEqual(str(tree), 'Any X WHERE X firstname "lulu", (X name "toto") OR (X name "tutu")')
 
     def test_precedence_4(self):
         tree = self.parse("Any X WHERE X firstname 'lulu' OR X name 'toto' AND X name 'tutu';")
@@ -227,15 +227,15 @@
 
     def test_not_precedence_0(self):
         tree = self.parse("Any X WHERE NOT X firstname 'lulu', X name 'toto';")
-        self.assertEqual(str(tree), "Any X WHERE NOT X firstname 'lulu', X name 'toto'")
+        self.assertEqual(str(tree), 'Any X WHERE NOT X firstname "lulu", X name "toto"')
 
     def test_not_precedence_1(self):
         tree = self.parse("Any X WHERE NOT X firstname 'lulu' AND X name 'toto';")
-        self.assertEqual(str(tree), "Any X WHERE NOT X firstname 'lulu', X name 'toto'")
+        self.assertEqual(str(tree), 'Any X WHERE NOT X firstname "lulu", X name "toto"')
 
     def test_not_precedence_2(self):
         tree = self.parse("Any X WHERE NOT X firstname 'lulu' OR X name 'toto';")
-        self.assertEqual(str(tree), "Any X WHERE (NOT X firstname 'lulu') OR (X name 'toto')")
+        self.assertEqual(str(tree), 'Any X WHERE (NOT X firstname "lulu") OR (X name "toto")')
 
     def test_string_1(self):
         tree = self.parse(r"Any X WHERE X firstname 'lu\"lu';")
@@ -306,8 +306,8 @@
         tree = self.parse("Any X WHERE X firstname 'lulu',"
                           "EXISTS (X owned_by U, U in_group G, G name 'lulufanclub' OR G name 'managers');")
         self.assertEqual(tree.as_string(),
-                         "Any X WHERE X firstname 'lulu', "
-                         "EXISTS(X owned_by U, U in_group G, (G name 'lulufanclub') OR (G name 'managers'))")
+                         'Any X WHERE X firstname "lulu", '
+                         'EXISTS(X owned_by U, U in_group G, (G name "lulufanclub") OR (G name "managers"))')
         exists = tree.children[0].where.get_nodes(nodes.Exists)[0]
         self.assertTrue(exists.children[0].parent is exists)
         self.assertTrue(exists.parent)
--- a/test/unittest_stcheck.py	Wed Jul 23 09:27:39 2014 +0200
+++ b/test/unittest_stcheck.py	Tue Sep 08 18:08:07 2015 +0200
@@ -119,7 +119,7 @@
             ('Person X',
              'Any X WHERE X is Person'),
             ("Any X WHERE X eid IN (12), X name 'toto'",
-             "Any X WHERE X eid 12, X name 'toto'"),
+             'Any X WHERE X eid 12, X name "toto"'),
             ('Any X WHERE X work_for Y, Y eid 12',
              'Any X WHERE X work_for 12'),
             ('Any X WHERE Y work_for X, Y eid 12',
@@ -139,7 +139,7 @@
 #            ('Any X,Y WHERE NOT X work_for Y OR X work_for Y', 'Any X,Y WHERE X? work_for Y?'),
             # test symmetric OR rewrite
             ("DISTINCT Any P WHERE P connait S OR S connait P, S name 'chouette'",
-             "DISTINCT Any P WHERE P connait S, S name 'chouette'"),
+             'DISTINCT Any P WHERE P connait S, S name "chouette"'),
             # queries that should not be rewritten
             ('DELETE Person X WHERE X eid 12',
              'DELETE Person X WHERE X eid 12'),
@@ -162,11 +162,11 @@
 
             ("Any X WHERE X firstname 'lulu',"
              "EXISTS (X owned_by U, U name 'lulufanclub' OR U name 'managers');",
-             "Any X WHERE X firstname 'lulu', "
-             "EXISTS(X owned_by U, (U name 'lulufanclub') OR (U name 'managers'))"),
+             'Any X WHERE X firstname "lulu", '
+             'EXISTS(X owned_by U, (U name "lulufanclub") OR (U name "managers"))'),
 
             ('Any X WHERE X eid 12, EXISTS(X name "hop" OR X work_for Y?)',
-             "Any 12 WHERE EXISTS((A name 'hop') OR (A work_for Y?), 12 identity A)"),
+             'Any 12 WHERE EXISTS((A name "hop") OR (A work_for Y?), 12 identity A)'),
 
             ('(Any X WHERE X eid 12) UNION (Any X ORDERBY X WHERE X eid 13)',
              '(Any 12) UNION (Any 13)'),
@@ -287,19 +287,19 @@
 
     def test_not_rel_normalization_3(self):
         rqlst = self.parse('Any X WHERE C is Company, X work_for C, NOT C name "World Company"').children[0]
-        self.assertEqual(rqlst.as_string(), "Any X WHERE C is Company, X work_for C, NOT C name 'World Company'")
+        self.assertEqual(rqlst.as_string(), 'Any X WHERE C is Company, X work_for C, NOT C name "World Company"')
         C = rqlst.defined_vars['C']
         self.assertTrue(C.scope is rqlst, C.scope)
 
     def test_not_rel_normalization_4(self):
         rqlst = self.parse('Any X WHERE C is Company, NOT (X work_for C, C name "World Company")').children[0]
-        self.assertEqual(rqlst.as_string(), "Any X WHERE C is Company, NOT EXISTS(X work_for C, C name 'World Company')")
+        self.assertEqual(rqlst.as_string(), 'Any X WHERE C is Company, NOT EXISTS(X work_for C, C name "World Company")')
         C = rqlst.defined_vars['C']
         self.assertFalse(C.scope is rqlst, C.scope)
 
     def test_not_rel_normalization_5(self):
         rqlst = self.parse('Any X WHERE X work_for C, EXISTS(C identity D, NOT Y work_for D, D name "World Company")').children[0]
-        self.assertEqual(rqlst.as_string(), "Any X WHERE X work_for C, EXISTS(C identity D, NOT EXISTS(Y work_for D), D name 'World Company')")
+        self.assertEqual(rqlst.as_string(), 'Any X WHERE X work_for C, EXISTS(C identity D, NOT EXISTS(Y work_for D), D name "World Company")')
         D = rqlst.defined_vars['D']
         self.assertFalse(D.scope is rqlst, D.scope)
         self.assertTrue(D.scope.parent.scope is rqlst, D.scope.parent.scope)