Style
This commit is contained in:
parent
98ac364dc7
commit
73dd14d9dd
@ -38,7 +38,7 @@ tests_path = 'test/'
|
|||||||
|
|
||||||
def readfile(fname):
|
def readfile(fname):
|
||||||
'''Reads a file as string and returns its content'''
|
'''Reads a file as string and returns its content'''
|
||||||
fd = open(fname,encoding='utf-8')
|
fd = open(fname, encoding='utf-8')
|
||||||
expr = fd.read()
|
expr = fd.read()
|
||||||
fd.close()
|
fd.close()
|
||||||
return expr
|
return expr
|
||||||
|
@ -151,6 +151,3 @@ class user_interface (object):
|
|||||||
str(e)
|
str(e)
|
||||||
))
|
))
|
||||||
return r
|
return r
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -77,7 +77,9 @@ class TokenizerException (Exception):
|
|||||||
class ParserException (Exception):
|
class ParserException (Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class CallableString(str):
|
class CallableString(str):
|
||||||
|
|
||||||
'''
|
'''
|
||||||
This is a string. However it is also callable.
|
This is a string. However it is also callable.
|
||||||
|
|
||||||
@ -94,7 +96,8 @@ class CallableString(str):
|
|||||||
context is a dictionary where to
|
context is a dictionary where to
|
||||||
each name is associated the relative relation
|
each name is associated the relative relation
|
||||||
'''
|
'''
|
||||||
return eval(self,context)
|
return eval(self, context)
|
||||||
|
|
||||||
|
|
||||||
class node (object):
|
class node (object):
|
||||||
|
|
||||||
@ -136,16 +139,16 @@ class node (object):
|
|||||||
u"'%s' is not a valid relation name" % self.name)
|
u"'%s' is not a valid relation name" % self.name)
|
||||||
return
|
return
|
||||||
|
|
||||||
#Expression from right to left, searching for binary operators
|
# Expression from right to left, searching for binary operators
|
||||||
#this means that binary operators have lesser priority than
|
# this means that binary operators have lesser priority than
|
||||||
#unary operators.
|
# unary operators.
|
||||||
#It finds the operator with lesser priority, uses it as root of this
|
# It finds the operator with lesser priority, uses it as root of this
|
||||||
#(sub)tree using everything on its left as left parameter (so building
|
# (sub)tree using everything on its left as left parameter (so building
|
||||||
#a left subtree with the part of the list located on left) and doing
|
# a left subtree with the part of the list located on left) and doing
|
||||||
#the same on right.
|
# the same on right.
|
||||||
#Since it searches for strings, and expressions into parenthesis are
|
# Since it searches for strings, and expressions into parenthesis are
|
||||||
#within sub-lists, they won't be found here, ensuring that they will
|
# within sub-lists, they won't be found here, ensuring that they will
|
||||||
#have highest priority.
|
# have highest priority.
|
||||||
for i in range(len(expression) - 1, -1, -1):
|
for i in range(len(expression) - 1, -1, -1):
|
||||||
if expression[i] in b_operators: # Binary operator
|
if expression[i] in b_operators: # Binary operator
|
||||||
self.kind = BINARY
|
self.kind = BINARY
|
||||||
@ -318,7 +321,7 @@ def tokenize(expression):
|
|||||||
|
|
||||||
items = [] # List for the tokens
|
items = [] # List for the tokens
|
||||||
|
|
||||||
#This is a state machine. Initial status is determined by the starting of the
|
# This is a state machine. Initial status is determined by the starting of the
|
||||||
# expression. There are the following statuses:
|
# expression. There are the following statuses:
|
||||||
#
|
#
|
||||||
# relation: this is the status if the expressions begins with something else than an
|
# relation: this is the status if the expressions begins with something else than an
|
||||||
@ -327,7 +330,8 @@ def tokenize(expression):
|
|||||||
# unary operator: this status is more complex, since it will be followed by a parameter AND a
|
# unary operator: this status is more complex, since it will be followed by a parameter AND a
|
||||||
# sub-expression.
|
# sub-expression.
|
||||||
# sub-expression: this status is entered when finding a '(' and will be exited when finding a ')'.
|
# sub-expression: this status is entered when finding a '(' and will be exited when finding a ')'.
|
||||||
# means that the others open must be counted to determine which close is the right one.'''
|
# means that the others open must be counted to determine which close is
|
||||||
|
# the right one.
|
||||||
|
|
||||||
expression = expression.strip() # Removes initial and endind spaces
|
expression = expression.strip() # Removes initial and endind spaces
|
||||||
state = 0
|
state = 0
|
||||||
|
@ -101,7 +101,7 @@ class relation (object):
|
|||||||
elif self.header.sharedAttributes(other.header) == len(self.header):
|
elif self.header.sharedAttributes(other.header) == len(self.header):
|
||||||
return other.projection(self.header)
|
return other.projection(self.header)
|
||||||
raise Exception('Relations differ: [%s] [%s]' % (
|
raise Exception('Relations differ: [%s] [%s]' % (
|
||||||
','.join(self.header) , ','.join(other.header)
|
','.join(self.header), ','.join(other.header)
|
||||||
))
|
))
|
||||||
|
|
||||||
def selection(self, expr):
|
def selection(self, expr):
|
||||||
@ -111,7 +111,9 @@ class relation (object):
|
|||||||
newt.header = header(self.header)
|
newt.header = header(self.header)
|
||||||
for i in self.content:
|
for i in self.content:
|
||||||
# Fills the attributes dictionary with the values of the tuple
|
# Fills the attributes dictionary with the values of the tuple
|
||||||
attributes = {attr:i[j].autocast() for j, attr in enumerate(self.header)}
|
attributes = {attr: i[j].autocast()
|
||||||
|
for j, attr in enumerate(self.header)
|
||||||
|
}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if eval(expr, attributes):
|
if eval(expr, attributes):
|
||||||
@ -129,7 +131,8 @@ class relation (object):
|
|||||||
|
|
||||||
if (self.__class__ != other.__class__)or(self.header.sharedAttributes(other.header) != 0):
|
if (self.__class__ != other.__class__)or(self.header.sharedAttributes(other.header) != 0):
|
||||||
raise Exception(
|
raise Exception(
|
||||||
'Unable to perform product on relations with colliding attributes')
|
'Unable to perform product on relations with colliding attributes'
|
||||||
|
)
|
||||||
newt = relation()
|
newt = relation()
|
||||||
newt.header = header(self.header + other.header)
|
newt.header = header(self.header + other.header)
|
||||||
|
|
||||||
@ -277,7 +280,7 @@ class relation (object):
|
|||||||
# Creating the header with all the fields, done like that because order is
|
# Creating the header with all the fields, done like that because order is
|
||||||
# needed
|
# needed
|
||||||
h = (i for i in other.header if i not in shared)
|
h = (i for i in other.header if i not in shared)
|
||||||
newt.header = header(chain(self.header,h))
|
newt.header = header(chain(self.header, h))
|
||||||
|
|
||||||
# Shared ids of self
|
# Shared ids of self
|
||||||
sid = self.header.getAttributesId(shared)
|
sid = self.header.getAttributesId(shared)
|
||||||
@ -296,13 +299,13 @@ class relation (object):
|
|||||||
match = match and (i[sid[k]] == j[oid[k]])
|
match = match and (i[sid[k]] == j[oid[k]])
|
||||||
|
|
||||||
if match:
|
if match:
|
||||||
item = chain(i,(j[l] for l in noid))
|
item = chain(i, (j[l] for l in noid))
|
||||||
|
|
||||||
newt.content.add(tuple(item))
|
newt.content.add(tuple(item))
|
||||||
added = True
|
added = True
|
||||||
# If it didn't partecipate, adds it
|
# If it didn't partecipate, adds it
|
||||||
if not added:
|
if not added:
|
||||||
item = chain(i,repeat('---',len(noid)))
|
item = chain(i, repeat('---', len(noid)))
|
||||||
newt.content.add(tuple(item))
|
newt.content.add(tuple(item))
|
||||||
|
|
||||||
return newt
|
return newt
|
||||||
@ -319,7 +322,7 @@ class relation (object):
|
|||||||
# Creating the header with all the fields, done like that because order is
|
# Creating the header with all the fields, done like that because order is
|
||||||
# needed
|
# needed
|
||||||
h = (i for i in other.header if i not in shared)
|
h = (i for i in other.header if i not in shared)
|
||||||
newt.header = header(chain(self.header,h))
|
newt.header = header(chain(self.header, h))
|
||||||
|
|
||||||
# Shared ids of self
|
# Shared ids of self
|
||||||
sid = self.header.getAttributesId(shared)
|
sid = self.header.getAttributesId(shared)
|
||||||
@ -374,7 +377,7 @@ class relation (object):
|
|||||||
col += 1
|
col += 1
|
||||||
|
|
||||||
res = ""
|
res = ""
|
||||||
for f,attr in enumerate(self.header):
|
for f, attr in enumerate(self.header):
|
||||||
res += "%s" % (attr.ljust(2 + m_len[f]))
|
res += "%s" % (attr.ljust(2 + m_len[f]))
|
||||||
|
|
||||||
for r in self.content:
|
for r in self.content:
|
||||||
@ -398,12 +401,11 @@ class relation (object):
|
|||||||
affected = 0
|
affected = 0
|
||||||
attributes = {}
|
attributes = {}
|
||||||
keys = dic.keys() # List of headers to modify
|
keys = dic.keys() # List of headers to modify
|
||||||
f_ids = self.header.getAttributesId(
|
f_ids = self.header.getAttributesId(keys)
|
||||||
keys) # List of indexes corresponding to keys
|
|
||||||
|
|
||||||
# new_content=[] #New content of the relation
|
# new_content=[] #New content of the relation
|
||||||
for i in self.content:
|
for i in self.content:
|
||||||
for j,attr in enumerate(self.header):
|
for j, attr in enumerate(self.header):
|
||||||
attributes[attr] = i[j].autocast()
|
attributes[attr] = i[j].autocast()
|
||||||
|
|
||||||
if eval(expr, attributes): # If expr is true, changing the tuple
|
if eval(expr, attributes): # If expr is true, changing the tuple
|
||||||
@ -445,7 +447,7 @@ class relation (object):
|
|||||||
deleting all the tuples that make expr true.
|
deleting all the tuples that make expr true.
|
||||||
Returns the number of affected rows.'''
|
Returns the number of affected rows.'''
|
||||||
|
|
||||||
#Not necessary self._make_writable()
|
# Not necessary self._make_writable()
|
||||||
|
|
||||||
l = len(self.content)
|
l = len(self.content)
|
||||||
self._readonly = False
|
self._readonly = False
|
||||||
@ -459,7 +461,7 @@ class header(tuple):
|
|||||||
It is used within relations to know if requested operations are accepted'''
|
It is used within relations to know if requested operations are accepted'''
|
||||||
|
|
||||||
# Since relations are mutalbe we explicitly block hashing them
|
# Since relations are mutalbe we explicitly block hashing them
|
||||||
def __new__ (cls, fields):
|
def __new__(cls, fields):
|
||||||
return super(header, cls).__new__(cls, tuple(fields))
|
return super(header, cls).__new__(cls, tuple(fields))
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
@ -481,7 +483,7 @@ class header(tuple):
|
|||||||
params is a dictionary of {old:new} names
|
params is a dictionary of {old:new} names
|
||||||
'''
|
'''
|
||||||
attrs = list(self)
|
attrs = list(self)
|
||||||
for old,new in params.items():
|
for old, new in params.items():
|
||||||
if not is_valid_relation_name(new):
|
if not is_valid_relation_name(new):
|
||||||
raise Exception('%s is not a valid attribute name' % new)
|
raise Exception('%s is not a valid attribute name' % new)
|
||||||
try:
|
try:
|
||||||
|
@ -25,9 +25,11 @@ import re
|
|||||||
|
|
||||||
RELATION_NAME_REGEXP = r'^[_a-zA-Z]+[_a-zA-Z0-9]*$'
|
RELATION_NAME_REGEXP = r'^[_a-zA-Z]+[_a-zA-Z0-9]*$'
|
||||||
|
|
||||||
|
|
||||||
class rstring (str):
|
class rstring (str):
|
||||||
|
|
||||||
'''String subclass with some custom methods'''
|
'''String subclass with some custom methods'''
|
||||||
|
|
||||||
def autocast(self):
|
def autocast(self):
|
||||||
'''
|
'''
|
||||||
Returns the automatic cast for this
|
Returns the automatic cast for this
|
||||||
|
@ -87,7 +87,10 @@ if __name__ == "__main__":
|
|||||||
try:
|
try:
|
||||||
from relational_gui import maingui, guihandler, about, surveyForm
|
from relational_gui import maingui, guihandler, about, surveyForm
|
||||||
except:
|
except:
|
||||||
print ("Module relational_gui is missing.\nPlease install relational package.",file=sys.stderr)
|
print (
|
||||||
|
"Module relational_gui is missing.\nPlease install relational package.",
|
||||||
|
file=sys.stderr
|
||||||
|
)
|
||||||
sys.exit(3)
|
sys.exit(3)
|
||||||
|
|
||||||
about.version = version
|
about.version = version
|
||||||
@ -103,7 +106,7 @@ if __name__ == "__main__":
|
|||||||
form = guihandler.relForm(ui)
|
form = guihandler.relForm(ui)
|
||||||
ui.setupUi(form)
|
ui.setupUi(form)
|
||||||
f = QtGui.QFont()
|
f = QtGui.QFont()
|
||||||
size = f.pointSize();
|
size = f.pointSize()
|
||||||
if sys.platform.startswith('win'):
|
if sys.platform.startswith('win'):
|
||||||
winFont = 'Cambria'
|
winFont = 'Cambria'
|
||||||
symbolFont = 'Segoe UI Symbol'
|
symbolFont = 'Segoe UI Symbol'
|
||||||
@ -113,19 +116,21 @@ if __name__ == "__main__":
|
|||||||
symbolFont = f.family()
|
symbolFont = f.family()
|
||||||
increment = 2
|
increment = 2
|
||||||
|
|
||||||
ui.lstHistory.setFont(QtGui.QFont(winFont,size+increment))
|
ui.lstHistory.setFont(QtGui.QFont(winFont, size + increment))
|
||||||
ui.txtMultiQuery.setFont(QtGui.QFont(winFont,size+increment))
|
ui.txtMultiQuery.setFont(QtGui.QFont(winFont, size + increment))
|
||||||
ui.txtQuery.setFont(QtGui.QFont(winFont,size+increment))
|
ui.txtQuery.setFont(QtGui.QFont(winFont, size + increment))
|
||||||
ui.groupOperators.setFont(QtGui.QFont(winFont,size+increment))
|
ui.groupOperators.setFont(QtGui.QFont(winFont, size + increment))
|
||||||
ui.cmdClearMultilineQuery.setFont(QtGui.QFont(symbolFont))
|
ui.cmdClearMultilineQuery.setFont(QtGui.QFont(symbolFont))
|
||||||
ui.cmdClearQuery.setFont(QtGui.QFont(symbolFont))
|
ui.cmdClearQuery.setFont(QtGui.QFont(symbolFont))
|
||||||
|
|
||||||
form.restore_settings()
|
form.restore_settings()
|
||||||
|
|
||||||
m = enumerate(map(os.path.isfile, files))
|
m = enumerate(map(os.path.isfile, files))
|
||||||
invalid = ' '.join((files[i[0]] for i in (filter(lambda x: not x[1], m))))
|
invalid = ' '.join(
|
||||||
|
(files[i[0]] for i in (filter(lambda x: not x[1], m)))
|
||||||
|
)
|
||||||
if invalid:
|
if invalid:
|
||||||
print ("%s: not a file" % invalid,file=sys.stderr)
|
print ("%s: not a file" % invalid, file=sys.stderr)
|
||||||
printhelp(12)
|
printhelp(12)
|
||||||
if len(files):
|
if len(files):
|
||||||
form.loadRelation(files)
|
form.loadRelation(files)
|
||||||
@ -137,7 +142,10 @@ if __name__ == "__main__":
|
|||||||
try:
|
try:
|
||||||
import relational_readline.linegui
|
import relational_readline.linegui
|
||||||
except:
|
except:
|
||||||
print ("Module relational_readline is missing.\nPlease install relational-cli package.",file=sys.stderr)
|
print (
|
||||||
|
"Module relational_readline is missing.\nPlease install relational-cli package.",
|
||||||
|
file=sys.stderr
|
||||||
|
)
|
||||||
sys.exit(3)
|
sys.exit(3)
|
||||||
relational_readline.linegui.version = version
|
relational_readline.linegui.version = version
|
||||||
relational_readline.linegui.main(files)
|
relational_readline.linegui.main(files)
|
||||||
|
@ -80,7 +80,8 @@ class creatorForm(QtWidgets.QDialog):
|
|||||||
self.table.setItem(1, 1, i11)
|
self.table.setItem(1, 1, i11)
|
||||||
|
|
||||||
def create_relation(self):
|
def create_relation(self):
|
||||||
h = (self.table.item(0, i).text() for i in range(self.table.columnCount()))
|
h = (self.table.item(0, i).text()
|
||||||
|
for i in range(self.table.columnCount()))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
header = relation.header(h)
|
header = relation.header(h)
|
||||||
|
@ -79,7 +79,8 @@ class relForm(QtWidgets.QMainWindow):
|
|||||||
|
|
||||||
query = self.ui.txtQuery.text()
|
query = self.ui.txtQuery.text()
|
||||||
try:
|
try:
|
||||||
result = optimizer.optimize_all(query, self.user_interface.relations)
|
result = optimizer.optimize_all(
|
||||||
|
query, self.user_interface.relations)
|
||||||
self.ui.txtQuery.setText(result)
|
self.ui.txtQuery.setText(result)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.error(e)
|
self.error(e)
|
||||||
@ -106,7 +107,7 @@ class relForm(QtWidgets.QMainWindow):
|
|||||||
if self.multiline:
|
if self.multiline:
|
||||||
return self._run_multiline()
|
return self._run_multiline()
|
||||||
|
|
||||||
#Single line query
|
# Single line query
|
||||||
query = self.ui.txtQuery.text()
|
query = self.ui.txtQuery.text()
|
||||||
res_rel = self.ui.txtResult.text() # result relation's name
|
res_rel = self.ui.txtResult.text() # result relation's name
|
||||||
|
|
||||||
@ -149,7 +150,7 @@ class relForm(QtWidgets.QMainWindow):
|
|||||||
self.ui.table.addTopLevelItem(item)
|
self.ui.table.addTopLevelItem(item)
|
||||||
|
|
||||||
# Sets columns
|
# Sets columns
|
||||||
for i,attr in enumerate(rel.header):
|
for i, attr in enumerate(rel.header):
|
||||||
self.ui.table.headerItem().setText(i, attr)
|
self.ui.table.headerItem().setText(i, attr)
|
||||||
self.ui.table.resizeColumnToContents(
|
self.ui.table.resizeColumnToContents(
|
||||||
i) # Must be done in order to avoid too small columns
|
i) # Must be done in order to avoid too small columns
|
||||||
@ -201,7 +202,7 @@ class relForm(QtWidgets.QMainWindow):
|
|||||||
self.user_interface.set_relation(i.text(), result)
|
self.user_interface.set_relation(i.text(), result)
|
||||||
self.updateRelations()
|
self.updateRelations()
|
||||||
|
|
||||||
def error(self,exception):
|
def error(self, exception):
|
||||||
print (exception)
|
print (exception)
|
||||||
QtWidgets.QMessageBox.information(
|
QtWidgets.QMessageBox.information(
|
||||||
None, QtWidgets.QApplication.translate("Form", "Error"),
|
None, QtWidgets.QApplication.translate("Form", "Error"),
|
||||||
@ -217,12 +218,13 @@ class relForm(QtWidgets.QMainWindow):
|
|||||||
"Form", "Insert the name for the new relation"),
|
"Form", "Insert the name for the new relation"),
|
||||||
QtWidgets.QLineEdit.Normal, ''
|
QtWidgets.QLineEdit.Normal, ''
|
||||||
)
|
)
|
||||||
if res[1] == False:# or len(res[0]) == 0:
|
if res[1] == False: # or len(res[0]) == 0:
|
||||||
return None
|
return None
|
||||||
name = res[0]
|
name = res[0]
|
||||||
if not rtypes.is_valid_relation_name(name):
|
if not rtypes.is_valid_relation_name(name):
|
||||||
r = QtWidgets.QApplication.translate(
|
r = QtWidgets.QApplication.translate(
|
||||||
"Form", str("Wrong name for destination relation: %s." % name)
|
"Form", str(
|
||||||
|
"Wrong name for destination relation: %s." % name)
|
||||||
)
|
)
|
||||||
QtWidgets.QMessageBox.information(
|
QtWidgets.QMessageBox.information(
|
||||||
self, QtWidgets.QApplication.translate("Form", "Error"), r
|
self, QtWidgets.QApplication.translate("Form", "Error"), r
|
||||||
@ -256,8 +258,9 @@ class relForm(QtWidgets.QMainWindow):
|
|||||||
|
|
||||||
def restore_settings(self):
|
def restore_settings(self):
|
||||||
# self.settings.value('session_name','default').toString()
|
# self.settings.value('session_name','default').toString()
|
||||||
self.setMultiline(self.settings.value('multiline','false')=='true')
|
self.setMultiline(self.settings.value('multiline', 'false') == 'true')
|
||||||
self.ui.txtMultiQuery.setPlainText(self.settings.value('multiline/query',''))
|
self.ui.txtMultiQuery.setPlainText(
|
||||||
|
self.settings.value('multiline/query', ''))
|
||||||
try:
|
try:
|
||||||
self.restoreGeometry(self.settings.value('maingui/geometry'))
|
self.restoreGeometry(self.settings.value('maingui/geometry'))
|
||||||
self.restoreState(self.settings.value('maingui/windowState'))
|
self.restoreState(self.settings.value('maingui/windowState'))
|
||||||
@ -299,7 +302,7 @@ class relForm(QtWidgets.QMainWindow):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.user_interface.load(f,name)
|
self.user_interface.load(f, name)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.error(e)
|
self.error(e)
|
||||||
continue
|
continue
|
||||||
|
@ -24,7 +24,6 @@ from PyQt5 import QtCore, QtGui, QtWidgets
|
|||||||
from relational import maintenance
|
from relational import maintenance
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class surveyForm (QtWidgets.QWidget):
|
class surveyForm (QtWidgets.QWidget):
|
||||||
|
|
||||||
'''This class is the form used for the survey, needed to intercept the events.
|
'''This class is the form used for the survey, needed to intercept the events.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user