Fixed "Add records" procedure (sql qwery now is correct). Added button on "Add record" form for colling relations table.

This commit is contained in:
Sergey Kalinin 2017-03-24 15:34:19 +03:00
parent 0ed5789c35
commit 2234722708
2 changed files with 163 additions and 146 deletions

66
dm.py
View File

@ -67,7 +67,7 @@ def firstInit():
def dbConnect(): def dbConnect():
global c, db_type, db_hostname, db_user, db_password, db_name global c, db_type, db_hostname, db_user, db_password, db_name, conn
if db_type == "mysql": if db_type == "mysql":
import pymysql import pymysql
conn = pymysql.connect( conn = pymysql.connect(
@ -76,6 +76,7 @@ def dbConnect():
passwd=db_password, passwd=db_password,
host=db_hostname, host=db_hostname,
charset='utf8') charset='utf8')
conn.commit()
elif db_type == "sqlite": elif db_type == "sqlite":
import sqlite3 import sqlite3
conn = sqlite3.connect(db_name) conn = sqlite3.connect(db_name)
@ -84,7 +85,6 @@ def dbConnect():
exit() exit()
#print(conn) #print(conn)
c = conn.cursor() c = conn.cursor()
return c return c
def createTables(tbl_list): def createTables(tbl_list):
@ -121,19 +121,21 @@ def createTables(tbl_list):
qwery_create = qwery_create + tbl_list[i]["fieldList"][x]["fName"] + " " + \ qwery_create = qwery_create + tbl_list[i]["fieldList"][x]["fName"] + " " + \
tbl_list[i]["fieldList"][x]["fType"] + auto_increment tbl_list[i]["fieldList"][x]["fType"] + auto_increment
if tbl_list[i]["fieldList"][x]["index"] == "PRIMARY KEY": if tbl_list[i]["fieldList"][x]["index"] == "PRIMARY KEY":
index = "PRIMARY KEY(" + tbl_list[i]["fieldList"][x]["fName"] + ")" index = ", PRIMARY KEY (" + tbl_list[i]["fieldList"][x]["fName"] + ")"
field_names_list.append( field_names_list.append(
[tbl_list[i]["fieldList"][x]["fName"], tbl_list[i]["fieldList"][x]["fDescription"]]) [tbl_list[i]["fieldList"][x]["fName"], tbl_list[i]["fieldList"][x]["fDescription"]])
# struct_fields_list.append(tbl_list[i]["fieldList"][x]["fName"]) # struct_fields_list.append(tbl_list[i]["fieldList"][x]["fName"])
struct_fields_list.append( struct_fields_list.append(
[tbl_list[i]["fieldList"][x]["fName"], fieldTypeConvert(tbl_list[i]["fieldList"][x]["fType"]), ]) [tbl_list[i]["fieldList"][x]["fName"], fieldTypeConvert(tbl_list[i]["fieldList"][x]["fType"]), auto_increment.strip(', ')])
if tbl_list[i]["fieldList"][x]["relation"]: if tbl_list[i]["fieldList"][x]["relation"]:
relation_list = [tbl_list[i]["fieldList"][x]["fName"]] relation_list = [tbl_list[i]["fieldList"][x]["fName"]]
relation_list.append(tbl_list[i]["fieldList"][x]["relation"]) relation_list.append(tbl_list[i]["fieldList"][x]["relation"])
one_Table_relation.append(relation_list) one_Table_relation.append(relation_list)
x = x + 1 x = x + 1
qwery_create = qwery_create + index + ");" qwery_create = qwery_create.strip(', ') + index + ');'
#qwery_create = qwery_create + index + ');'
#print(qwery_create)
elif db_type == 'sqlite': elif db_type == 'sqlite':
while x < len(tbl_list[i]["fieldList"]): while x < len(tbl_list[i]["fieldList"]):
if tbl_list[i]["fieldList"][x]["autoIncrement"] == "yes": if tbl_list[i]["fieldList"][x]["autoIncrement"] == "yes":
@ -150,7 +152,7 @@ def createTables(tbl_list):
field_names_list.append([tbl_list[i]["fieldList"][x]["fName"], tbl_list[i]["fieldList"][x]["fDescription"]]) field_names_list.append([tbl_list[i]["fieldList"][x]["fName"], tbl_list[i]["fieldList"][x]["fDescription"]])
# struct_fields_list.append(tbl_list[i]["fieldList"][x]["fName"]) # struct_fields_list.append(tbl_list[i]["fieldList"][x]["fName"])
struct_fields_list.append( struct_fields_list.append(
[tbl_list[i]["fieldList"][x]["fName"], fieldTypeConvert(tbl_list[i]["fieldList"][x]["fType"]), ]) [tbl_list[i]["fieldList"][x]["fName"], fieldTypeConvert(tbl_list[i]["fieldList"][x]["fType"]), auto_increment.strip(', ')])
if tbl_list[i]["fieldList"][x]["relation"]: if tbl_list[i]["fieldList"][x]["relation"]:
relation_list = [tbl_list[i]["fieldList"][x]["fName"]] relation_list = [tbl_list[i]["fieldList"][x]["fName"]]
relation_list.append(tbl_list[i]["fieldList"][x]["relation"]) relation_list.append(tbl_list[i]["fieldList"][x]["relation"])
@ -165,7 +167,7 @@ def createTables(tbl_list):
i = i + 1 i = i + 1
tbl_descr_list.append(one_Table_descr) tbl_descr_list.append(one_Table_descr)
tbl_struct_list.append(one_Table_struct) tbl_struct_list.append(one_Table_struct)
print(qwery_create) #print(qwery_create)
c.execute(qwery_create) c.execute(qwery_create)
return tbl_names_list return tbl_names_list
@ -212,7 +214,7 @@ def selectData(tbl):
subqwery = "(SELECT (" + field_replace + ") FROM " + subqwery +" WHERE "+ table1 + "." + field1 +"="+ tbl +"."+ field +") AS " + field subqwery = "(SELECT (" + field_replace + ") FROM " + subqwery +" WHERE "+ table1 + "." + field1 +"="+ tbl +"."+ field +") AS " + field
qwery = qwery.replace(field, subqwery) qwery = qwery.replace(field, subqwery)
qwery = qwery.rstrip(',') + " FROM " + tbl + " LIMIT 10000" qwery = qwery.rstrip(',') + " FROM " + tbl + " LIMIT 10000"
print(qwery) #print(qwery)
c.execute(qwery) c.execute(qwery)
return c.fetchall() return c.fetchall()
@ -273,13 +275,41 @@ def getFieldType(tbl, field):
#print(item[1]) #print(item[1])
#return item[1] #return item[1]
def getRelationsForField(tblSearch, fieldName):
global tbl_struct_list, c, db_type
#print("Ищем связи для:" +tblSearch +','+ fieldName)
#print(tbl_struct_list)
#searchField = tblSearch + '.' + fieldName
dataList = []
for item in tbl_struct_list:
#print(item)
tblName = item[0]
for field in item[1]:
field = field[0]
for rel in item[2]:
if tblName == tblSearch:
# выдергиваем из списка название и поле нужной нам таблицы
if rel[0] == fieldName:
#print('table - ' + tblName)
##print('field - ' + fieldName)
#print('relation - ' + str(rel))
l = rel[1][0].split('.')
relTable = l[0]
relField = l[1]
replaceFields = rel[1][1]
# print('reltable - ' + relTable)
#print('relfield - ' + relField)
#print('relrelation - ' + replaceFields)
return [relTable, relField, replaceFields]
return "q"
# добавление записи в БД на вход принимает список вида: # добавление записи в БД на вход принимает список вида:
# [table [['field_1', 'значение'], ['field_2', 'значение'],....., ['field_n', 'значение']]] # [table [['field_1', 'значение'], ['field_2', 'значение'],....., ['field_n', 'значение']]]
def insertDataIntoBD(dataList): def insertDataIntoBD(dataList):
global c global c, conn
dbConnect() dbConnect()
tableName = dataList[0] tableName = dataList[0]
#print(dataList)
#datetime.strptime("21/11/06 16:30", "%d/%m/%y %H:%M") #datetime.strptime("21/11/06 16:30", "%d/%m/%y %H:%M")
qwery = 'INSERT INTO ' + tableName + ' (' qwery = 'INSERT INTO ' + tableName + ' ('
@ -288,6 +318,8 @@ def insertDataIntoBD(dataList):
for item in dataList[1]: for item in dataList[1]:
fType = getFieldType(tableName, item[0]) fType = getFieldType(tableName, item[0])
#print(fType) #print(fType)
# проверяем если значение поля пустое то в запрос оно не включается
if item[1] != '':
qweryField = qweryField + item[0] + ',' qweryField = qweryField + item[0] + ','
if fType == 'integer': if fType == 'integer':
qweryData = qweryData + '' + item[1] + ',' qweryData = qweryData + '' + item[1] + ','
@ -304,10 +336,12 @@ def insertDataIntoBD(dataList):
else: else:
qweryData = qweryData + '\'' + item[1] + '\',' qweryData = qweryData + '\'' + item[1] + '\','
qwery = qwery + qweryField.rstrip(',') + ')' + ' VALUES (' + qweryData.rstrip(',') + ');' qwery = qwery + qweryField.rstrip(',') + ')' + ' VALUES (' + qweryData.rstrip(',') + ');'
#print(qwery) print(qwery)
c.execute(qwery) c.execute(qwery)
conn.commit()
#c.close() #c.close()
return return
@ -342,16 +376,16 @@ def selectDataFromDB(tblName, fieldName, fieldValue):
fieldReplace = fieldReplace.replace(",", ",' ',") fieldReplace = fieldReplace.replace(",", ",' ',")
subqwery = "(SELECT CONCAT(" + fieldReplace + ") FROM " + subqwery + " WHERE " + table1 + "." + field1 + "=" + tblName + "." + field + ") AS " + field subqwery = "(SELECT CONCAT(" + fieldReplace + ") FROM " + subqwery + " WHERE " + table1 + "." + field1 + "=" + tblName + "." + field + ") AS " + field
elif db_type == "sqlite": elif db_type == "sqlite":
print(db_type) #print(db_type)
print(fieldReplace) #print(fieldReplace)
fieldReplace = fieldReplace.replace(",", " || ' ' ||") fieldReplace = fieldReplace.replace(",", " || ' ' ||")
print(fieldReplace) #print(fieldReplace)
subqwery = "(SELECT (" + fieldReplace + ") FROM " + subqwery +" WHERE "+ table1 + "." + field1 +"="+ tblName +"."+ field +") AS " + field subqwery = "(SELECT (" + fieldReplace + ") FROM " + subqwery +" WHERE "+ table1 + "." + field1 +"="+ tblName +"."+ field +") AS " + field
print("---" + subqwery) #print("---" + subqwery)
qwery = qwery.replace(field, subqwery) qwery = qwery.replace(field, subqwery)
#qwery = qwery.rstrip(',') + " FROM " + tblName + " LIMIT 10000" #qwery = qwery.rstrip(',') + " FROM " + tblName + " LIMIT 10000"
qwery = qwery.rstrip(',') + " FROM " + tblName + " WHERE " + fieldName + '=' + fieldValue qwery = qwery.rstrip(',') + " FROM " + tblName + " WHERE " + fieldName + '=' + fieldValue
print(qwery) #print(qwery)
c.execute(qwery) c.execute(qwery)
return c.fetchall() return c.fetchall()

211
gui.py
View File

@ -49,7 +49,7 @@ class MyTable(QTableWidget):
showRelationsRecords(self.currentIndex().column(), item.text()) showRelationsRecords(self.currentIndex().column(), item.text())
def on_click(self): def on_click(self):
print(self.cursor().pos().x()) #print(self.cursor().pos().x())
#self.contextMenuEvent(self.cursor()) #self.contextMenuEvent(self.cursor())
for currentQTableWidgetItem in self.selectedItems(): for currentQTableWidgetItem in self.selectedItems():
print(currentQTableWidgetItem.row(), currentQTableWidgetItem.column(), currentQTableWidgetItem.text()) print(currentQTableWidgetItem.row(), currentQTableWidgetItem.column(), currentQTableWidgetItem.text())
@ -58,6 +58,7 @@ class MyTable(QTableWidget):
class EditForm(QMainWindow): class EditForm(QMainWindow):
lblList = [] lblList = []
editList = [] editList = []
def __init__(self, tblName, tblDescr): def __init__(self, tblName, tblDescr):
super().__init__() super().__init__()
self.tblName = tblName self.tblName = tblName
@ -83,14 +84,20 @@ class EditForm(QMainWindow):
integerValidator = QRegExpValidator(integerRegex, self) integerValidator = QRegExpValidator(integerRegex, self)
# список соответствия полей и QEdit # список соответствия полей и QEdit
self.widgetsList = [] self.widgetsList = []
self.btnRelationsList = []
# добавляем динамически поля на форму в зависимости от типов данных # добавляем динамически поля на форму в зависимости от типов данных
for item in dm.getFields(tblName): for item in dm.getFields(tblName):
#print(item) #print(item)
fName = item[0] fName = item[0]
fType = item[1] fType = item[1]
fAutoIncr = item[2]
fDescr = dm.getFieldDescription(tblName, fName) fDescr = dm.getFieldDescription(tblName, fName)
hboxEdit = QHBoxLayout() hboxEdit = QHBoxLayout()
lbl = QLabel(fDescr) lbl = QLabel(fDescr)
#listRelationTableAndField = []
btnRelations = ''
tableRelation = ''
# создаем поле ввода соответсвующее типу данных # создаем поле ввода соответсвующее типу данных
if fType == 'datetime': if fType == 'datetime':
edit = QDateTimeEdit() edit = QDateTimeEdit()
@ -112,6 +119,9 @@ class EditForm(QMainWindow):
edit.setTime(now) edit.setTime(now)
elif fType == 'integer': elif fType == 'integer':
edit = QLineEdit() edit = QLineEdit()
# отключаем поле если оно автоинкрементное
if fAutoIncr == 'AUTOINCREMENT' or fAutoIncr == 'AUTO_INCREMENT':
edit.setDisabled(True)
# проверка на ввод цифр # проверка на ввод цифр
edit.setValidator(integerValidator) edit.setValidator(integerValidator)
else: else:
@ -121,6 +131,23 @@ class EditForm(QMainWindow):
hboxEdit.addWidget(lbl) hboxEdit.addWidget(lbl)
hboxEdit.addWidget(edit) hboxEdit.addWidget(edit)
# добавляем к полю кнопку для вызова связанных
print(fName)
listRelationTableAndField = dm.getRelationsForField(tblName, fName)
print(listRelationTableAndField)
if listRelationTableAndField != 'q':
tableRelation = listRelationTableAndField[0]
fieldRelation = listRelationTableAndField[1]
replaceField = listRelationTableAndField[2]
print(tableRelation + '-' + fieldRelation +'-'+replaceField)
btnRelations = QPushButton('...')
btnRelations.setFixedWidth(30)
# добавляем название виджета в список соответсвия кнопок и таблиц БД
# пиздец извращения =(
self.btnRelationsList.append([btnRelations, tableRelation, fieldRelation, replaceField])
btnRelations.clicked.connect(lambda: self.openRelationTable())
hboxEdit.addWidget(btnRelations)
l.addLayout(hboxEdit) l.addLayout(hboxEdit)
#print(self.widgetsList) #print(self.widgetsList)
hboxBtn.addWidget(btnOk) hboxBtn.addWidget(btnOk)
@ -138,85 +165,45 @@ class EditForm(QMainWindow):
listFieldData = [] listFieldData = []
for item in self.widgetsList: for item in self.widgetsList:
#print(item[0] + ' ' + item[1].text()) #print(item[0] + ' ' + item[1].text())
if item[1].isEnabled:
listFieldData.append([item[0], item[1].text()]) listFieldData.append([item[0], item[1].text()])
listData.append(listFieldData) listData.append(listFieldData)
#print(listData) #print(listData)
dm.insertDataIntoBD(listData) dm.insertDataIntoBD(listData)
self.close() self.close()
# выбираем данные для связанной таблицы
def openRelationTable(self):
sender = self.sender()
# ищем в списке соответсвующую кнопоку и связанные с ней данные
for item in self.btnRelationsList:
if sender == item[0]:
btn = item[0]
tbl = item[1]
# выбираем данные из БД
data = dm.selectData(tbl)
print(data)
def clickTablesList(tbl_name, tblDataWidget, data='NULL'):
class EditForm_(QMainWindow): global tblList, tabRelationsData
def __init__(self, tblName, tblDescr): # удаляем все открытые табы
super().__init__()
self.setWindowTitle("Добавление записи")
scroll_widget = QWidget()
self.general_layout = QVBoxLayout()
scroll_area = QScrollArea()
l = QVBoxLayout()
headBox = QHBoxLayout()
lblHeader = QLabel("<B>Таблица: " + tblDescr)
l.addLayout(headBox)
#palet = QPalette(lblHeader.palette())
#lblHeader.setPalette(palet)
headBox.addWidget(lblHeader)
hboxBtn = QHBoxLayout()
btnOk = QPushButton('Записать')
btnOk.clicked.connect(lambda: self.save())
btnCancel = QPushButton('Закрыть')
btnCancel.clicked.connect(lambda: self.close())
# ПРОВЕРКА ВВОДА, добавить в цикл генерации формы в зависимости от типа поля
# grid_layout.addWidget(QLabel("Введите IP-адрес", self), 0, 0)
#
# ipRange = "(?:[0-1]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])" # Часть регулярного выржение
# # Само регулярное выражение
# ipRegex = QRegExp("^" + ipRange + "\\." + ipRange + "\\." + ipRange + "\\." + ipRange + "$")
# ipValidator = QRegExpValidator(ipRegex, self) # Валидатор для QLineEdit
#
# lineEdit = QLineEdit()
# lineEdit.setValidator(ipValidator) # Устанавливаем валидатор
i=0 i=0
for item in dm.getTableStructure(tblName): if tabRelationsData.count():
#print(item) tabRelationsData.clear()
hboxEdit = QHBoxLayout() #print(tabRelationsData.count())
lbl = QLabel(item) while i <= tabRelationsData.count():
edit = QLineEdit() #print(i)
hboxEdit.addWidget(lbl)
hboxEdit.addWidget(edit) tabRelationsData.removeTab(i)
l.addLayout(hboxEdit)
i = i+1 i = i+1
hboxBtn.addWidget(btnOk) addDataIntoTable(dm.getTablesNameOfDescription(listTables.model().data(listTables.currentIndex())), tblDataWidget)
hboxBtn.addWidget(btnCancel)
l.addLayout(hboxBtn)
self.general_layout.addLayout(l)
scroll_widget.setLayout(self.general_layout)
scroll_area.setWidget(scroll_widget)
self.setCentralWidget(scroll_area)
def save(self):
print(self.children())
def addDataIntoTable(tbl_name, tblDataWidget, data='NULL'): def addDataIntoTable(tbl_name, tblDataWidget, data='NULL'):
global tblList global tblList, tabRelationsData
# выбираем название таблицы по описанию
# for i in tblList:
# if i[1] == tbl_descr:
# tbl_name = i[0]
# else:
# tbl_name = tbl_descr
#print(tbl_name)
if data == 'NULL': if data == 'NULL':
data = dm.selectData(tbl_name) data = dm.selectData(tbl_name)
#print(data)
fieldNames = dm.getTableStructure(tbl_name) fieldNames = dm.getTableStructure(tbl_name)
#print(fieldNames)
# проверка на наличие записей в таблице # проверка на наличие записей в таблице
if data: if data:
# количество строк # количество строк
@ -232,12 +219,9 @@ def addDataIntoTable(tbl_name, tblDataWidget, data='NULL'):
for item in fieldNames: for item in fieldNames:
fName = item[0] fName = item[0]
fDescr = item[1] fDescr = item[1]
#fieldNames = item + ','
# установка заголовков столбцов таблицы # установка заголовков столбцов таблицы
#item = '<b>' + item + '</b>'
tblDataWidget.setHorizontalHeaderItem(n, QTableWidgetItem(fDescr)) tblDataWidget.setHorizontalHeaderItem(n, QTableWidgetItem(fDescr))
n = n + 1 n = n + 1
n = 0 n = 0
for key in data: for key in data:
m = 0 m = 0
@ -333,44 +317,6 @@ def addNewRecord():
#editForm.setParent(tblRelationsData) #editForm.setParent(tblRelationsData)
#editForm = Example() #editForm = Example()
def main():
global tblList, listTables, tabRelationsData
app = QApplication(sys.argv)
mainWin = QMainWindow()
workArea = QWidget()
mainWin.setCentralWidget(workArea)
hbox = QHBoxLayout()
listTables = QListWidget()
listTables.setFrameShape(QFrame.StyledPanel)
listTables.setFixedWidth(200)
#tblData = QTableWidget()
tblData = MyTable()
tblData.setFrameShape(QFrame.StyledPanel)
tabRelationsData = QTabWidget()
#tabRelationsData.setFrameShape(QFrame.StyledPanel)
splitter1 = QSplitter(Qt.Horizontal)
splitter1.addWidget(listTables)
splitter2 = QSplitter(Qt.Vertical)
splitter2.addWidget(tblData)
splitter2.addWidget(tabRelationsData)
splitter1.addWidget(splitter2)
hbox.addWidget(splitter1)
workArea.setLayout(hbox)
showMenuToolbar(mainWin)
listTables.itemClicked.connect(lambda: addDataIntoTable(dm.getTablesNameOfDescription(listTables.model().data(listTables.currentIndex())), tblData))
# выводим список таблиц в левом поле
tblList = dm.initDBstructure()
for i in tblList:
listTables.addItem(i[1])
mainWin.setGeometry(300, 300, 800, 600)
mainWin.setWindowTitle('Data manipulator')
mainWin.show()
return app.exec_()
def showRelationsRecords(fieldIndex, fieldValue): def showRelationsRecords(fieldIndex, fieldValue):
global tabRelationsData, listTables global tabRelationsData, listTables
tblDescr = listTables.model().data(listTables.currentIndex()) tblDescr = listTables.model().data(listTables.currentIndex())
@ -385,25 +331,62 @@ def showRelationsRecords(fieldIndex, fieldValue):
fieldNamesList = dm.getTableStructure(tblName) fieldNamesList = dm.getTableStructure(tblName)
fieldName = fieldNamesList[fieldIndex][0] fieldName = fieldNamesList[fieldIndex][0]
print(fieldNamesList) # print(fieldNamesList)
print(fieldName) # print(fieldName)
print("showRelations") # print("showRelations")
print(tblName) # print(tblName)
print(fieldValue) # print(fieldValue)
data = dm.selectRelationsDataFromDB(tblName, fieldName, fieldValue) data = dm.selectRelationsDataFromDB(tblName, fieldName, fieldValue)
#print(data) #print(data)
for item in data: for item in data:
tbl = item[0] tbl = item[0]
qweryResult = item[1] qweryResult = item[1]
if qweryResult: if qweryResult:
print('report' + str(qweryResult) + 'report') #print('report' + str(qweryResult) + 'report')
tblRelationsData = MyTable() tblRelationsData = MyTable()
tblRelationsData.setParent(tabRelationsData) tblRelationsData.setParent(tabRelationsData)
tabRelationsData.addTab(tblRelationsData, dm.getTablesDescriptionOfName(tbl)) tabRelationsData.addTab(tblRelationsData, dm.getTablesDescriptionOfName(tbl))
addDataIntoTable(tbl, tblRelationsData, qweryResult) addDataIntoTable(tbl, tblRelationsData, qweryResult)
# def main():
# global tblList, listTables, tabRelationsData
app = QApplication(sys.argv)
mainWin = QMainWindow()
workArea = QWidget()
mainWin.setCentralWidget(workArea)
hbox = QHBoxLayout()
listTables = QListWidget()
listTables.setFrameShape(QFrame.StyledPanel)
listTables.setFixedWidth(200)
#tblData = QTableWidget()
tblData = MyTable()
tblData.setFrameShape(QFrame.StyledPanel)
tabRelationsData = QTabWidget()
#tabRelationsData.setFrameShape(QFrame.StyledPanel)
splitter1 = QSplitter(Qt.Horizontal)
splitter1.addWidget(listTables)
splitter2 = QSplitter(Qt.Vertical)
splitter2.addWidget(tblData)
splitter2.addWidget(tabRelationsData)
splitter1.addWidget(splitter2)
hbox.addWidget(splitter1)
workArea.setLayout(hbox)
showMenuToolbar(mainWin)
listTables.itemClicked.connect(lambda: clickTablesList(dm.getTablesNameOfDescription(listTables.model().data(listTables.currentIndex())), tblData))
# выводим список таблиц в левом поле
tblList = dm.initDBstructure()
for i in tblList:
listTables.addItem(i[1])
mainWin.setGeometry(300, 300, 800, 600)
mainWin.setWindowTitle('Data manipulator')
mainWin.show()
return app.exec_()
if __name__ == '__main__': if __name__ == '__main__':
main() main()