ai_regression_ui.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. #!/usr/bin/env python3
  2. # -*- Coding: UTF-8 -*-
  3. # ---------------------------------------------------------------------------
  4. # Open Asset Import Library (ASSIMP)
  5. # ---------------------------------------------------------------------------
  6. #
  7. # Copyright (c) 2006-2020, ASSIMP Development Team
  8. #
  9. # All rights reserved.
  10. #
  11. # Redistribution and use of this software in source and binary forms,
  12. # with or without modification, are permitted provided that the following
  13. # conditions are met:
  14. #
  15. # * Redistributions of source code must retain the above
  16. # copyright notice, this list of conditions and the
  17. # following disclaimer.
  18. #
  19. # * Redistributions in binary form must reproduce the above
  20. # copyright notice, this list of conditions and the
  21. # following disclaimer in the documentation and/or other
  22. # materials provided with the distribution.
  23. #
  24. # * Neither the name of the ASSIMP team, nor the names of its
  25. # contributors may be used to endorse or promote products
  26. # derived from this software without specific prior
  27. # written permission of the ASSIMP Development Team.
  28. #
  29. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  30. # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  31. # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  32. # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  33. # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  34. # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  35. # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  36. # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  37. # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  38. # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  39. # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  40. # ---------------------------------------------------------------------------
  41. from tkinter import *
  42. import sys
  43. import os
  44. import platform
  45. import run
  46. import subprocess
  47. import result_checker as rc
  48. INFO = 0
  49. WARN = 1
  50. ERROR = 2
  51. # -------------------------------------------------------------------------------
  52. def log( sev, msg ):
  53. """
  54. This function is used to log info, warnings and errors.
  55. """
  56. logEntry = ""
  57. if sev == 0:
  58. logEntry = logEntry + "[INFO]: "
  59. elif sev == 1:
  60. logEntry = logEntry + "[WARN]: "
  61. elif sev == 2:
  62. logEntry = logEntry + "[ERR] : "
  63. logEntry = logEntry + str( msg )
  64. print( logEntry )
  65. # -------------------------------------------------------------------------------
  66. class BaseDialog( Toplevel ):
  67. """
  68. Helper base class for dialogs used in the UI.
  69. """
  70. def __init__(self, parent, title = None, buttons=""):
  71. """
  72. Constructor
  73. """
  74. Toplevel.__init__( self, parent )
  75. self.transient(parent)
  76. if title:
  77. self.title(title)
  78. self.parent = parent
  79. self.result = None
  80. body = Frame(self)
  81. self.initial_focus = self.body(body)
  82. body.pack(padx=5, pady=5)
  83. self.buttonbox(buttons)
  84. self.grab_set()
  85. if not self.initial_focus:
  86. self.initial_focus = self
  87. self.protocol("WM_DELETE_WINDOW", self.cancel)
  88. self.geometry("+%d+%d" % (parent.winfo_rootx() + 50,
  89. parent.winfo_rooty() + 50))
  90. self.initial_focus.focus_set()
  91. self.wait_window(self)
  92. def body(self, master):
  93. # create dialog body. return widget that should have
  94. # initial focus. this method should be overridden
  95. pass
  96. def buttonbox(self, buttons):
  97. # add standard button box. override if you don't want the
  98. # standard buttons
  99. box = Frame(self)
  100. w = Button(box, text="OK", width=40, command=self.ok, default=ACTIVE)
  101. w.pack(side=LEFT, padx=5, pady=5)
  102. self.bind("<Return>", self.ok)
  103. box.pack()
  104. def ok(self, event=None):
  105. if not self.validate():
  106. self.initial_focus.focus_set() # put focus back
  107. return
  108. self.withdraw()
  109. self.update_idletasks()
  110. self.apply()
  111. self.cancel()
  112. def cancel(self, event=None):
  113. # put focus back to the parent window
  114. self.parent.focus_set()
  115. self.destroy()
  116. def validate(self):
  117. return 1 # override
  118. def apply(self):
  119. pass # override
  120. # -------------------------------------------------------------------------------
  121. class VersionDialog( BaseDialog ):
  122. """
  123. This class is used to create the info dialog.
  124. """
  125. def body(self, master):
  126. # info will be read from assimp command line tool
  127. version = "Asset importer lib version unknown"
  128. exe = run.getEnvVar( "assimp_path" )
  129. if len( exe ) != 0:
  130. command = [exe, "version" ]
  131. log( INFO, "command = " + str(command))
  132. stdout = subprocess.check_output(command)
  133. for line in stdout.splitlines():
  134. pos = str(line).find( "Version" )
  135. if -1 != pos:
  136. version = line
  137. Label(master, text=version).pack()
  138. def apply(self):
  139. pass
  140. # -------------------------------------------------------------------------------
  141. class SetupDialog( BaseDialog ):
  142. """
  143. This class is used to create the setup dialog.
  144. """
  145. def body(self, master):
  146. Label(master, justify=LEFT, text="Assimp: " ).grid(row=0, column=0)
  147. Label(master, justify=LEFT, text=run.getEnvVar("assimp_path")).grid(row=0, column=1)
  148. Label(master, text="New executable:").grid(row=1)
  149. self.e1 = Entry(master)
  150. self.e1.grid(row=1, column=1)
  151. return self.e1 # initial focus
  152. def apply(self):
  153. exe = str( self.e1.get() )
  154. if len( exe ) == 0:
  155. return 0
  156. if os.path.isfile( exe ):
  157. log( INFO, "Set executable at " + exe)
  158. self.assimp_bin_path = exe
  159. run.setEnvVar("assimp_path", self.assimp_bin_path)
  160. else:
  161. log( ERROR, "Executable not found at "+exe )
  162. return 0
  163. # -------------------------------------------------------------------------------
  164. class RegDialog( object ):
  165. """
  166. This class is used to create a simplified user interface for running the regression test suite.
  167. """
  168. def __init__(self, bin_path ):
  169. """
  170. Constructs the dialog, you can define which executable shal be used.
  171. @param bin_path [in] Path to assimp binary.
  172. """
  173. run.setEnvVar( "assimp_path", bin_path )
  174. self.b_run_ = None
  175. self.b_update_ = None
  176. self.b_res_checker_ = None
  177. self.b_quit_ = None
  178. if platform.system() == "Windows":
  179. self.editor = "notepad"
  180. elif platform.system() == "Linux":
  181. self.editor = "vim"
  182. self.root = None
  183. self.width=40
  184. def run_reg(self):
  185. log(INFO, "Starting regression test suite.")
  186. run.run_test()
  187. rc.run()
  188. self.b_update_.config( state=ACTIVE )
  189. return 0
  190. def reg_update(self):
  191. assimp_exe = run.getEnvVar( "assimp_path" )
  192. if len( assimp_exe ) == 0:
  193. return 1
  194. exe = "python"
  195. command = [ exe, "gen_db.py", assimp_exe ]
  196. log(INFO, "command = " + str(command))
  197. stdout = subprocess.call(command)
  198. log(INFO, stdout)
  199. return 0
  200. def shop_diff( self ):
  201. log(WARN, "ToDo!")
  202. return 0
  203. def open_log(self):
  204. command = [ self.editor, "../results/run_regression_suite_output.txt", ]
  205. log(INFO, "command = " + str( command ) )
  206. r = subprocess.call(command)
  207. return 0
  208. def show_version( self ):
  209. d = VersionDialog( self.root )
  210. return 0
  211. def setup(self):
  212. d = SetupDialog( self.root )
  213. return 0
  214. def quit(self):
  215. log( INFO, "quit" )
  216. sys.exit( 0 )
  217. def initUi(self):
  218. # create the frame with buttons
  219. self.root = Tk()
  220. self.root.title( "Assimp-Regression UI")
  221. self.b_run_ = Button( self.root, text="Run regression ", command=self.run_reg, width = self.width )
  222. self.b_update_ = Button( self.root, text="Update database", command=self.reg_update, width = self.width )
  223. self.b_show_diff_ = Button( self.root, text="Show diff", command=self.shop_diff, width = self.width )
  224. self.b_log_ = Button( self.root, text="Open log", command=self.open_log, width = self.width )
  225. self.b_setup_ = Button( self.root, text="Setup", command=self.setup, width = self.width )
  226. self.b_version_ = Button( self.root, text="Show version", command=self.show_version, width = self.width )
  227. self.b_quit_ = Button( self.root, text="Quit", command=self.quit, width = self.width )
  228. # define the used grid
  229. self.b_run_.grid( row=0, column=0, sticky=W+E )
  230. self.b_update_.grid( row=1, column=0, sticky=W+E )
  231. self.b_show_diff_.grid( row=2, column=0, sticky=W+E )
  232. self.b_log_.grid( row=3, column=0, sticky=W+E )
  233. self.b_setup_.grid( row=4, column=0, sticky=W+E )
  234. self.b_version_.grid( row=5, column=0, sticky=W+E )
  235. self.b_quit_.grid( row=6, column=0, sticky=W+E )
  236. #self.b_update_.config( state=DISABLED )
  237. self.b_show_diff_.config( state=DISABLED )
  238. # run mainloop
  239. self.root.mainloop()
  240. # -------------------------------------------------------------------------------
  241. def getDefaultExecutable():
  242. assimp_bin_path = ""
  243. if platform.system() == "Windows":
  244. assimp_bin_path = '..\\..\\bin\\debug\\assimpd.exe'
  245. elif platform.system() == "Linux":
  246. assimp_bin_path = '../../bin/assimp'
  247. return assimp_bin_path
  248. # -------------------------------------------------------------------------------
  249. if __name__ == "__main__":
  250. if len(sys.argv) > 1:
  251. assimp_bin_path = sys.argv[1]
  252. else:
  253. assimp_bin_path = getDefaultExecutable()
  254. log( INFO, 'Using assimp binary: ' + assimp_bin_path )
  255. dlg = RegDialog(assimp_bin_path)
  256. dlg.initUi()
  257. # vim: ai ts=4 sts=4 et sw=4