sdwebserver/extractdatafromsvn.py

409 lines
16 KiB
Python
Executable File

#!/usr/bin/env python3
# this python script copy all
# default car previews
# tracks outlines
# from the tgiven svn repo to a specified folder in the webserver
# todo: check if directories exist: "cars" and "tracks" in "img",
# if not create them
import os
import sys
import shutil
import threading
import xml.etree.ElementTree as ET
import tkinter as tk
from tkinter import ttk, filedialog
class ExtractData(threading.Thread):
def __init__(self, sdRepoFolder, addStatus=None):
self.sdRepoFolder = sdRepoFolder
self.addStatus = addStatus
if not os.path.isdir(self.sdRepoFolder) or not os.access(self.sdRepoFolder, os.R_OK):
text = sys.argv[1] + " folder does not exist, is not a folder or does not have read permissions"
if self.addStatus:
self.addStatus(text)
else:
print(text, flush=True)
exit(1)
carMainFolder = self.sdRepoFolder + 'data/cars/models/'
carCatMainFolder = self.sdRepoFolder + 'data/cars/categories/'
trackMainFolder = self.sdRepoFolder + 'data/tracks/'
trackCatMainFolder = self.sdRepoFolder + 'data/tracks/'
self.root = None
##============================
## EXTRACT CARS CATEGORY DATA
##============================
carCategories = {}
catFiles = os.listdir(carCatMainFolder)
for catFile in catFiles:
xmlCatFile = carCatMainFolder+catFile
fileName, fileExtension = os.path.splitext(xmlCatFile)
if fileExtension == '.xml':
if os.path.isfile(xmlCatFile):
xmlFileUrl = xmlCatFile
parser = ET.XMLParser()
tree = ET.parse(xmlFileUrl, parser=parser)
# And get the self.root of the xml tree
self.root = tree.getroot()
catName = self.root.attrib['name']
catId = self.getTagAttr('Car', attstr='category')['val']
carCategories[catId] = {}
carCategories[catId]['cars'] = []
carCategories[catId]['name'] = catName
#print 'Processed: '+catId+' : '+catName
##============================
## EXTRACT CARS DATA
##============================
cars = {}
carFolders = os.listdir(carMainFolder)
for folder in carFolders:
dirName = carMainFolder + folder + '/'
xmlFileUrl = dirName+folder+'.xml'
imgFileUrl = dirName+folder+'-preview.jpg'
if os.path.isfile(xmlFileUrl):
if os.path.isfile(imgFileUrl):
newImgUrl = './public/img/cars/'+folder+'-preview.jpg'
carImg = './img/cars/'+folder+'-preview.jpg'
shutil.copyfile(imgFileUrl, newImgUrl)
tree = ET.parse(xmlFileUrl)
# And get the self.root of the xml tree
self.root = tree.getroot()
# Car name
carName = self.root.attrib['name']
carId = folder
# Car category
carCategory = self.getTagAttr('Car', attstr='category')['val']
carWidth = self.getTagAttr('Car', attnum='body length')['val']
# print('Processing car: {} : {} : {}'.format(carId, carName, carWidth))
text = 'Processing car: {} : {} : {}'.format(carId, carName, carWidth)
if self.addStatus:
self.addStatus(text)
else:
print(text, flush=True)
# Assign the car to a car categorie
carCategories[carCategory]['cars'].append(carId)
# Populate the car object with all the infos of the car
cars[carId] = {}
cars[carId]['id'] = carId
cars[carId]['name'] = carName
cars[carId]['img'] = carImg
cars[carId]['category'] = carCategory
try:
overall_width = self.getTagAttr('Car', attnum='overall width')
cars[carId]['width'] = '{} {}'.format(
overall_width['unit'],
overall_width['val']
)
except:
cars[carId]['width'] = "data unavailable"
try:
overall_length = self.getTagAttr('Car', attnum='overall length')
cars[carId]['length'] = '{} {}'.format(
overall_length['unit'],
overall_length['val']
)
except:
cars[carId]['lenght'] = "data unavailable"
try:
overall_mass = self.getTagAttr('Car', attnum='mass')
cars[carId]['mass'] = '{} {}'.format(
overall_mass['unit'],
overall_mass['val']
)
except:
cars[carId]['mass'] = "data unavailable"
# mpa11 musarasama has problems (missing some data)
try:
overall_fueltank = self.getTagAttr('Car', attnum='fuel tank')
cars[carId]['fueltank'] = '{} {}'.format(
overall_fueltank['unit'],
overall_fueltank['val']
)
except:
cars[carId]['fueltank'] = "data unavailable"
try:
cylinders = self.getTagAttr('Engine', attnum='cylinders')
shape = self.getTagAttr('Engine', attstr='shape')
capacity = self.getTagAttr('Engine', attnum='capacity')
cars[carId]['engine'] = '{} cylinders {} {} {}'.format(
cylinders['val'],
shape['val'],
capacity['val'],
capacity['unit']
)
except:
cars[carId]['engine'] = "data unavailable"
cars[carId]['drivetrain'] = self.getTagAttr('Drivetrain', attstr='type')['val']
text = 'Processed car: {} : {}'.format(carId, carName)
if self.addStatus:
self.addStatus(text)
else:
print(text, flush=True)
#self.addStatus(text)
##============================
## EXTRACT TRACKS CATEGORY DATA
##============================
trackCategories = {}
##============================
## EXTRACT TRACKS DATA
##============================
tracks = {}
trackCategoryFolders = os.listdir(trackMainFolder)
for category in trackCategoryFolders:
categoryFolder = trackMainFolder + category+'/'
if not os.path.isfile(trackMainFolder + category):
categoryFolders = os.listdir(categoryFolder)
# Log car categories info
trackCategories[category] = {}
trackCategories[category]['id'] = category
trackCategories[category]['name'] = category
trackCategories[category]['tracks'] = []
for track in categoryFolders:
#print categoryFolder+'\n'
#print track+'\n\n'
if not os.path.isfile(categoryFolder+track):
trackFolder = categoryFolder+track+'/'
xmlFileUrl = trackFolder+track+'.xml'
#print categoryFolder+track
if not os.path.isfile(categoryFolder+track):
if os.path.isfile(xmlFileUrl):
#print xmlFileUrl
parser = ET.XMLParser()
#parser._parser.UseForeignDTD(True)
parser.entity['default-surfaces'] = u'\u00A0'
parser.entity['default-objects'] = u'\u00A0'
tree = ET.parse(xmlFileUrl, parser=parser)
# And get the self.root of the xml tree
self.root = tree.getroot()
#trackId=self.root.attrib['name']
trackId = track
trackName = self.getTagAttr('Header', attstr='name')['val']
trackCategory = self.getTagAttr('Header', attstr='category')['val']
imgFileUrl = trackFolder+'outline.png'
# We want to ignore development tracks
if (trackCategory == "development"):
#print('INFO: Ignoring track as is a development one for: ' + trackId + ' : ' + trackName)
text = 'INFO: Ignoring track as is a development one for: {} : {}'.format(trackId, trackName)
if self.addStatus:
self.addStatus(text)
else:
print(text, flush=True)
continue
if os.path.isfile(imgFileUrl):
newImgUrl = './public/img/tracks/' + track + '-outline.png'
trackImg = './img/tracks/' + track + '-outline.png'
shutil.copyfile(imgFileUrl, newImgUrl)
else:
'''print('WARNING: No track image defined for: {} : {}'.format(
trackId,
trackName
))'''
text = 'WARNING: No track image defined for: {} : {}'.format(
trackId,
trackName
)
if self.addStatus:
self.addStatus(text)
else:
print(text, flush=True)
trackImg = ''
# Populate the car object with all the infos of the track
tracks[trackId] = {}
tracks[trackId]['id'] = trackId
tracks[trackId]['name'] = trackName
tracks[trackId]['img'] = trackImg
tracks[trackId]['category'] = trackCategory
tracks[trackId]['author'] = self.getTagAttr('Header', attstr='author')['val']
temp = self.getTagAttr('Header', attstr='description')['val'].replace("'", "*")
tracks[trackId]['description'] = temp
#tracks[trackId]['version']=self.root.findall("./section[@name='Header']/attstr[@name='version']")[0].attrib['val']
trackCategories[category]['tracks'].append(trackId)
text = 'Processed track: {} : {}'.format(trackId, trackName)
if self.addStatus:
self.addStatus(text)
else:
print(text, flush=True)
# Save he carCategory info into a file
out_file = open("./writable/data/carCategories.txt", "w")
out_file.write(str(carCategories))
out_file.close()
# Save the cars info into a file
out_file = open("./writable/data/cars.txt", "w")
out_file.write(str(cars))
out_file.close()
# Save the carTrack info into a file
out_file = open("./writable/data/trackCategories.txt", "w")
out_file.write(str(trackCategories))
out_file.close()
# Save the tracks info into a file
out_file = open("./writable/data/tracks.txt", "w")
out_file.write(str(tracks))
out_file.close()
def getTagAttr(self, section, attstr=None, attnum=None):
"""
Find a attstr or attnum tag and return he attributes.
Args:
section (str): The section to find
attstr (str, optional): If find a attstr tag. Defaults to None.
attnum (str, optional): If find a attnum tag. Defaults to None.
"""
attribs = None
element = None
if attstr:
element = self.root.findall(
"./section[@name='{}']/attstr[@name='{}']".format(
section,
attstr
)
)
elif attnum:
element = self.root.findall(
"./section[@name='{}']/attnum[@name='{}']".format(
section,
attnum
)
)
if element and len(element) > 0:
attribs = element[0].attrib
return attribs
class Gui(tk.Frame):
def __init__(self, parent, gui=True, sdRepoFolder=None):
super().__init__(parent)
self.root = None
self.gui = gui
self.sdRepoFolder = sdRepoFolder
self.status = None
if self.gui:
top = self.winfo_toplevel()
top.rowconfigure(1, weight=1)
top.columnconfigure(2, weight=1)
self.entryFolder = tk.Entry(width=50)
self.entryFolder.grid(column=0, row=0, sticky='e')
self.openBtn = tk.Button(text='Open folder', command=self.selDataDir)
self.openBtn.grid(column=1, row=0, sticky='w')
frame = tk.Frame()
scroll_bar = ttk.Scrollbar(frame, orient=tk.VERTICAL)
self.status = tk.Listbox(frame, yscrollcommand=scroll_bar.set)
self.status.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
scroll_bar.configure(command=self.status.yview)
scroll_bar.pack(side=tk.RIGHT, fill=tk.Y)
frame.rowconfigure('all', weight=1)
frame.columnconfigure('all', weight=1)
frame.grid(column=0, row=1, columnspan=3, sticky="nsew")
self.startBtn = tk.Button(
text='Extract',
command=self.startThread,
state=tk.DISABLED)
self.startBtn.grid(column=2, row=0, sticky='w')
else:
self.startThread()
def selDataDir(self):
self.sdRepoFolder = filedialog.askdirectory() + '/'
if self.sdRepoFolder:
self.entryFolder.insert(0, self.sdRepoFolder)
self.startBtn['state'] = tk.NORMAL
def startThread(self):
threading.Thread(
target=ExtractData,
args=(self.sdRepoFolder, self.addStatus)
).start()
def addStatus(self, text):
if (self.gui):
self.status.insert(tk.END, text)
else:
print(text)
if len(sys.argv) == 2:
sdRepoFolder = sys.argv[1]
threading.Thread(
target=ExtractData,
args=(sdRepoFolder,)
).start()
else:
window = tk.Tk()
window.title("Speed Dreams: Extract Data from SVN")
window.geometry('640x480')
app = Gui(window)
window.mainloop()