Switch core module to Python3

The core module (the relational algebra, not the interface) is now
using Python3

Tests are passing, so it should be ok.
This commit is contained in:
Salvo 'LtWorf' Tomaselli 2015-02-19 12:42:41 +01:00
parent 4019fbadb0
commit a355762fc4
9 changed files with 115 additions and 120 deletions

123
driver.py
View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# coding=UTF-8
# Relational
@ -31,7 +31,7 @@ COLOR_GREEN = 0x00ff00
COLOR_MAGENTA = 0xff00ff
COLOR_CYAN = 0x00ffff
print relation
print(relation)
rels = {}
examples_path = 'samples/'
@ -49,17 +49,17 @@ def readfile(fname):
def load_relations():
'''Loads all the relations present in the directory indicated in the
examples_path variable and stores them in the rels dictionary'''
print "Loading relations"
print("Loading relations")
for i in os.listdir(examples_path):
if i.endswith('.csv'): # It's a relation, loading it
# Naming the relation
relname = i[:-4]
print ("Loading relation %s with name %s..." % (i, relname)),
print ("Loading relation %s with name %s..." % (i, relname))
rels[relname] = relation.relation('%s%s' % (examples_path, i))
print 'done'
print('done')
def execute_tests():
@ -93,49 +93,50 @@ def execute_tests():
ex_good += 1
else:
ex_bad += 1
print colorize("Resume of the results", COLOR_CYAN)
print (colorize("Resume of the results", COLOR_CYAN))
print colorize("Query tests", COLOR_MAGENTA)
print "Total test count: %d" % q_tot
print "Passed tests: %d" % q_good
print (colorize("Query tests", COLOR_MAGENTA))
print ("Total test count: %d" % q_tot)
print ("Passed tests: %d" % q_good)
if q_bad > 0:
print colorize("Failed tests count: %d" % q_bad, COLOR_RED)
print (colorize("Failed tests count: %d" % q_bad, COLOR_RED))
print colorize("Python tests", COLOR_MAGENTA)
print "Total test count: %d" % py_tot
print "Passed tests: %d" % py_good
print (colorize("Python tests", COLOR_MAGENTA))
print ("Total test count: %d" % py_tot)
print ("Passed tests: %d" % py_good)
if py_bad > 0:
print colorize("Failed tests count: %d" % py_bad, COLOR_RED)
print (colorize("Failed tests count: %d" % py_bad, COLOR_RED))
print colorize("Execute Python tests", COLOR_MAGENTA)
print "Total test count: %d" % ex_tot
print "Passed tests: %d" % ex_good
print (colorize("Execute Python tests", COLOR_MAGENTA))
print ("Total test count: %d" % ex_tot)
print ("Passed tests: %d" % ex_good)
if ex_bad > 0:
print colorize("Failed tests count: %d" % ex_bad, COLOR_RED)
print (colorize("Failed tests count: %d" % ex_bad, COLOR_RED))
print colorize("Total results", COLOR_CYAN)
print (colorize("Total results", COLOR_CYAN))
if q_bad + py_bad + ex_bad == 0:
print colorize("No failed tests", COLOR_GREEN)
print (colorize("No failed tests", COLOR_GREEN))
return 0
else:
print colorize("There are %d failed tests" % (py_bad + q_bad + ex_bad), COLOR_RED)
print (colorize("There are %d failed tests" %
(py_bad + q_bad + ex_bad), COLOR_RED))
return 1
def run_exec_test(testname):
'''Runs a python test, which executes code directly rather than queries'''
print "Running python test: " + colorize(testname, COLOR_MAGENTA)
print ("Running python test: " + colorize(testname, COLOR_MAGENTA))
glob = rels.copy()
exp_result = {}
try:
expr = readfile('%s%s.exec' % (tests_path, testname))
exec(expr, glob) # Evaluating the expression
expr = readfile('%s%s.exec' % (tests_path, testname))
exec(expr, glob) # Evaluating the expression
try:
exec(expr, glob) # Evaluating the expression
except Exception as e:
print (e)
raise Exception("")
expr = readfile('%s%s.result' % (tests_path, testname))
exp_result = eval(expr, rels) # Evaluating the expression
@ -147,21 +148,22 @@ def run_exec_test(testname):
fields_ok = fields_ok and glob[i] == exp_result[i]
if fields_ok:
print colorize('Test passed', COLOR_GREEN)
print (colorize('Test passed', COLOR_GREEN))
return True
except:
pass
print colorize('ERROR', COLOR_RED)
print colorize('=====================================', COLOR_RED)
print "Expected %s" % exp_result
# print "Got %s" % result
print colorize('=====================================', COLOR_RED)
print (colorize('ERROR', COLOR_RED))
print (colorize('=====================================', COLOR_RED))
print ("Expected %s" % exp_result)
# print ("Got %s" % glob)
print (colorize('=====================================', COLOR_RED))
return False
def run_py_test(testname):
'''Runs a python test, which evaluates expressions directly rather than queries'''
print "Running expression python test: " + colorize(testname, COLOR_MAGENTA)
print ("Running expression python test: " +
colorize(testname, COLOR_MAGENTA))
try:
@ -172,16 +174,16 @@ def run_py_test(testname):
exp_result = eval(expr, rels) # Evaluating the expression
if result == exp_result:
print colorize('Test passed', COLOR_GREEN)
print (colorize('Test passed', COLOR_GREEN))
return True
except:
pass
print colorize('ERROR', COLOR_RED)
print colorize('=====================================', COLOR_RED)
print "Expected %s" % exp_result
print "Got %s" % result
print colorize('=====================================', COLOR_RED)
print (colorize('ERROR', COLOR_RED))
print (colorize('=====================================', COLOR_RED))
print ("Expected %s" % exp_result)
print ("Got %s" % result)
print (colorize('=====================================', COLOR_RED))
return False
@ -192,7 +194,7 @@ def run_test(testname):
testname.result
The query will be executed both unoptimized and
optimized'''
print "Running test: " + colorize(testname, COLOR_MAGENTA)
print ("Running test: " + colorize(testname, COLOR_MAGENTA))
query = None
expr = None
@ -205,8 +207,7 @@ def run_test(testname):
try:
result_rel = relation.relation('%s%s.result' % (tests_path, testname))
query = unicode(
readfile('%s%s.query' % (tests_path, testname)).strip(), 'utf8')
query = readfile('%s%s.query' % (tests_path, testname)).strip()
o_query = optimizer.optimize_all(query, rels)
expr = parser.parse(query) # Converting expression to python string
@ -220,29 +221,31 @@ def run_test(testname):
c_result = eval(c_expr, rels)
if (o_result == result_rel) and (result == result_rel) and (c_result == result_rel):
print colorize('Test passed', COLOR_GREEN)
print (colorize('Test passed', COLOR_GREEN))
return True
except Exception as inst:
print inst
print (inst)
pass
print colorize('ERROR', COLOR_RED)
print "Query: %s -> %s" % (query, expr)
print "Optimized query: %s -> %s" % (o_query, o_expr)
print colorize('=====================================', COLOR_RED)
print colorize("Expected result", COLOR_GREEN)
print result_rel
print colorize("Result", COLOR_RED)
print result
print colorize("Optimized result", COLOR_RED)
print o_result
print colorize("optimized result match %s" % str(result_rel == o_result), COLOR_MAGENTA)
print colorize("result match %s" % str(result == result_rel), COLOR_MAGENTA)
print colorize('=====================================', COLOR_RED)
print (colorize('ERROR', COLOR_RED))
print ("Query: %s -> %s" % (query, expr))
print ("Optimized query: %s -> %s" % (o_query, o_expr))
print (colorize('=====================================', COLOR_RED))
print (colorize("Expected result", COLOR_GREEN))
print (result_rel)
print (colorize("Result", COLOR_RED))
print (result)
print (colorize("Optimized result", COLOR_RED))
print (o_result)
print (colorize("optimized result match %s" %
str(result_rel == o_result), COLOR_MAGENTA))
print (colorize("result match %s" %
str(result == result_rel), COLOR_MAGENTA))
print (colorize('=====================================', COLOR_RED))
return False
if __name__ == '__main__':
print "-> Starting testsuite for relational"
print ("-> Starting testsuite for relational")
load_relations()
print "-> Starting tests"
print ("-> Starting tests")
exit(execute_tests())

View File

@ -29,11 +29,12 @@
# The class used is defined in optimizer module.
# A function will have to return the number of changes performed on the tree.
import parser
from cStringIO import StringIO
from io import StringIO
from tokenize import generate_tokens
from relational import parser
sel_op = (
'//=', '**=', 'and', 'not', 'in', '//', '**', '<<', '>>', '==', '!=', '>=', '<=', '+=', '-=',
'*=', '/=', '%=', 'or', '+', '-', '*', '/', '&', '|', '^', '~', '<', '>', '%', '=', '(', ')', ',', '[', ']')
@ -620,4 +621,4 @@ general_optimizations = [
specific_optimizations = [selection_and_product]
if __name__ == "__main__":
print tokenize_select("skill == 'C' and id % 2 == 0")
print (tokenize_select("skill == 'C' and id % 2 == 0"))

View File

@ -25,8 +25,8 @@
# The functions will always return a string with the optimized query, but if a parse tree was provided,
# the parse tree itself will be modified accordingly.
import optimizations
import parser
from relational import optimizations
from relational import parser
# Stuff that was here before, keeping it for compatibility
@ -56,12 +56,12 @@ def optimize_all(expression, rels, specific=True, general=True, debug=None):
steps.
Return value: this will return an optimized version of the expression'''
if isinstance(expression, unicode):
if isinstance(expression, str):
n = tree(expression) # Gets the tree
elif isinstance(expression, node):
n = expression
else:
raise (TypeError("expression must be a unicode string or a node"))
raise (TypeError("expression must be a string or a node"))
if isinstance(debug, list):
dbg = True
@ -128,8 +128,8 @@ if __name__ == "__main__":
print rels'''
n = tree(u"π indice,qq,name (ρ age➡qq,id➡indice (P1-P2))")
# n=tree("σ id==3 and indice==2 and name==5 or name<2(P1 * S1)")
print n
print n.toPython()
print (n)
print (n.toPython())
# print optimizations.selection_and_product(n,rels)

View File

@ -41,7 +41,8 @@
# Language definition here:
# https://github.com/ltworf/relational/wiki/Grammar-and-language
import re
import rtypes
from relational import rtypes
RELATION = 0
UNARY = 1
@ -104,10 +105,10 @@ class node (object):
# If the list contains only a list, it will consider the lower level list.
# This will allow things like ((((((a))))) to work
while len(expression) == 1 and isinstance(expression[0], list):
expression = expression[0]
expression = expression[0]
# The list contains only 1 string. Means it is the name of a relation
if len(expression) == 1 and isinstance(expression[0], unicode):
if len(expression) == 1:
self.kind = RELATION
self.name = expression[0]
if not rtypes.is_valid_relation_name(self.name):
@ -125,7 +126,7 @@ class node (object):
Since it searches for strings, and expressions into parenthesis are
within sub-lists, they won't be found here, ensuring that they will
have highest priority.'''
for i in xrange(len(expression) - 1, -1, -1):
for i in range(len(expression) - 1, -1, -1):
if expression[i] in b_operators: # Binary operator
self.kind = BINARY
self.name = expression[i]
@ -142,7 +143,7 @@ class node (object):
self.right = node(expression[i + 1:])
return
'''Searches for unary operators, parsing from right to left'''
for i in xrange(len(expression) - 1, -1, -1):
for i in range(len(expression) - 1, -1, -1):
if expression[i] in u_operators: # Unary operator
self.kind = UNARY
self.name = expression[i]
@ -293,9 +294,6 @@ def tokenize(expression):
'''This function converts an expression into a list where
every token of the expression is an item of a list. Expressions into
parenthesis will be converted into sublists.'''
if not isinstance(expression, unicode):
raise TokenizerException('expected unicode')
items = [] # List for the tokens
'''This is a state machine. Initial status is determined by the starting of the
@ -334,7 +332,7 @@ def tokenize(expression):
elif expression.startswith((u"σ", u"π", u"ρ")): # Unary 2 bytes
items.append(expression[0:1])
#Adding operator in the top of the list
# Adding operator in the top of the list
expression = expression[
1:].strip() # Removing operator from the expression
@ -345,7 +343,7 @@ def tokenize(expression):
par = expression.find('(')
items.append(expression[:par].strip())
#Inserting parameter of the operator
# Inserting parameter of the operator
expression = expression[
par:].strip() # Removing parameter from the expression
elif expression.startswith((u"÷", u"", u"", u"*", u"-")):
@ -417,8 +415,8 @@ def parse(expr):
if __name__ == "__main__":
while True:
e = unicode(raw_input("Expression: "), 'utf-8')
print parse(e)
e = str(raw_input("Expression: "))
print (parse(e))
# b=u"σ age>1 and skill=='C' (peopleᐅᐊskills)"
# print b[0]

View File

@ -19,7 +19,7 @@
#
# This module provides a classes to represent queries
import parser
from relational import
class TypeException(Exception):
@ -29,10 +29,6 @@ class TypeException(Exception):
class Query(object):
def __init__(self, query):
if not isinstance(query, unicode):
raise TypeException('Expected unicode')
self.query = query
self.tree = parser.tree(query)
# TODO self.query_code = parser

View File

@ -20,9 +20,10 @@
# This module provides a classes to represent relations and to perform
# relational operations on them.
from rtypes import *
import csv
from relational.rtypes import *
class relation (object):
@ -46,13 +47,13 @@ class relation (object):
self.header = header([])
return
# Opening file
fp = file(filename)
fp = open(filename)
reader = csv.reader(fp) # Creating a csv reader
self.header = header(reader.next()) # read 1st line
self.header = header(next(reader)) # read 1st line
self.content = set()
for i in reader.__iter__(): # Iterating rows
for i in reader: # Iterating rows
self.content.add(tuple(i))
# Closing file
@ -123,7 +124,7 @@ class relation (object):
try:
if eval(expr, attributes):
newt.content.add(i)
except Exception, e:
except Exception as e:
raise Exception(
"Failed to evaluate %s\n%s" % (expr, e.__str__()))
return newt
@ -190,7 +191,7 @@ class relation (object):
newt = relation()
newt.header = header(list(self.header.attributes))
for old, new in params.iteritems():
for old, new in params.items():
if (newt.header.rename(old, new)) == False:
raise Exception('Unable to find attribute: %s' % old)

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# coding=UTF-8
# Relational
@ -28,35 +28,35 @@ version = "1.3"
def printver(exit=True):
print "Relational %s" % version
print "Copyright (C) 2008 Salvo 'LtWorf' Tomaselli."
print
print "This program comes with ABSOLUTELY NO WARRANTY."
print "This is free software, and you are welcome to redistribute it"
print "under certain conditions."
print "For details see the GPLv3 Licese."
print
print "Written by Salvo 'LtWorf' Tomaselli <tiposchi@tiscali.it>"
print
print "http://ltworf.github.io/relational/"
print ("Relational %s" % version)
print ("Copyright (C) 2008 Salvo 'LtWorf' Tomaselli.")
print ()
print ("This program comes with ABSOLUTELY NO WARRANTY.")
print ("This is free software, and you are welcome to redistribute it")
print ("under certain conditions.")
print ("For details see the GPLv3 Licese.")
print ()
print ("Written by Salvo 'LtWorf' Tomaselli <tiposchi@tiscali.it>")
print ()
print ("http://ltworf.github.io/relational/")
if exit:
sys.exit(0)
def printhelp(code=0):
print "Relational"
print
print "Usage: %s [options] [files]" % sys.argv[0]
print
print " -v Print version and exits"
print " -h Print this help and exits"
print ("Relational")
print ()
print ("Usage: %s [options] [files]" % sys.argv[0])
print ()
print (" -v Print version and exits")
print (" -h Print this help and exits")
if sys.argv[0].endswith('relational-cli'):
print " -q Uses QT user interface"
print " -r Uses readline user interface (default)"
print (" -q Uses QT user interface")
print (" -r Uses readline user interface (default)")
else:
print " -q Uses QT user interface (default)"
print " -r Uses readline user interface"
print (" -q Uses QT user interface (default)")
print (" -r Uses readline user interface")
sys.exit(code)
if __name__ == "__main__":
@ -116,7 +116,7 @@ if __name__ == "__main__":
defname = f[len(f) - 1].lower()
if defname.endswith(".csv"): # removes the extension
defname = defname[:-4]
print 'Loading file "%s" with name "%s"' % (files[i], defname)
print ('Loading file "%s" with name "%s"' % (files[i], defname))
Form.loadRelation(files[i], defname)
Form.show()

View File

@ -1,7 +1,5 @@
p1=people.rename({"id":"ido"})
people.insert((123,"lala",0,31))
print p1
print people
retval=people==p1
people.delete("id==123")

View File

@ -1,7 +1,5 @@
p1=people.rename({"id":"ido"})
p1.insert((123,"lala",0,31))
print p1
print people
retval=people==p1
people.delete("id==123")