Blender V2.61 - r43446
|
00001 # ##### BEGIN GPL LICENSE BLOCK ##### 00002 # 00003 # This program is free software; you can redistribute it and/or 00004 # modify it under the terms of the GNU General Public License 00005 # as published by the Free Software Foundation; either version 2 00006 # of the License, or (at your option) any later version. 00007 # 00008 # This program is distributed in the hope that it will be useful, 00009 # but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00011 # GNU General Public License for more details. 00012 # 00013 # You should have received a copy of the GNU General Public License 00014 # along with this program; if not, write to the Free Software Foundation, 00015 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00016 # 00017 # ##### END GPL LICENSE BLOCK ##### 00018 00019 # <pep8 compliant> 00020 00021 import sys 00022 import os 00023 00024 00025 # may split this out into a new file 00026 def replace_bpy_app_version(): 00027 """ So MD5's are predictable from output which uses blenders versions. 00028 """ 00029 00030 import bpy 00031 00032 app = bpy.app 00033 app_fake = type(bpy)("bpy.app") 00034 00035 for attr in dir(app): 00036 if not attr.startswith("_"): 00037 setattr(app_fake, attr, getattr(app, attr)) 00038 00039 app_fake.version = 0, 0, 0 00040 app_fake.version_string = "0.00 (sub 0)" 00041 bpy.app = app_fake 00042 00043 00044 def clear_startup_blend(): 00045 import bpy 00046 00047 for scene in bpy.data.scenes: 00048 for obj in scene.objects: 00049 scene.objects.unlink(obj) 00050 00051 00052 def blend_to_md5(): 00053 import bpy 00054 scene = bpy.context.scene 00055 ROUND = 4 00056 00057 def matrix2str(matrix): 00058 return "".join([str(round(axis, ROUND)) for vector in matrix for axis in vector]).encode('ASCII') 00059 00060 def coords2str(seq, attr): 00061 return "".join([str(round(axis, ROUND)) for vertex in seq for axis in getattr(vertex, attr)]).encode('ASCII') 00062 00063 import hashlib 00064 00065 md5 = hashlib.new("md5") 00066 md5_update = md5.update 00067 00068 for obj in scene.objects: 00069 md5_update(matrix2str(obj.matrix_world)) 00070 data = obj.data 00071 00072 if type(data) == bpy.types.Mesh: 00073 md5_update(coords2str(data.vertices, "co")) 00074 elif type(data) == bpy.types.Curve: 00075 for spline in data.splines: 00076 md5_update(coords2str(spline.bezier_points, "co")) 00077 md5_update(coords2str(spline.points, "co")) 00078 00079 return md5.hexdigest() 00080 00081 00082 def main(): 00083 argv = sys.argv 00084 print(" args:", " ".join(argv)) 00085 argv = argv[argv.index("--") + 1:] 00086 00087 def arg_extract(arg, optional=True, array=False): 00088 arg += "=" 00089 if array: 00090 value = [] 00091 else: 00092 value = None 00093 00094 i = 0 00095 while i < len(argv): 00096 if argv[i].startswith(arg): 00097 item = argv[i][len(arg):] 00098 del argv[i] 00099 i -= 1 00100 00101 if array: 00102 value.append(item) 00103 else: 00104 value = item 00105 break 00106 00107 i += 1 00108 00109 if (not value) and (not optional): 00110 print(" '%s' not set" % arg) 00111 sys.exit(1) 00112 00113 return value 00114 00115 run = arg_extract("--run", optional=False) 00116 md5 = arg_extract("--md5", optional=False) 00117 md5_method = arg_extract("--md5_method", optional=False) # 'SCENE' / 'FILE' 00118 00119 # only when md5_method is 'FILE' 00120 md5_source = arg_extract("--md5_source", optional=True, array=True) 00121 00122 # save blend file, for testing 00123 write_blend = arg_extract("--write-blend", optional=True) 00124 00125 # ensure files are written anew 00126 for f in md5_source: 00127 if os.path.exists(f): 00128 os.remove(f) 00129 00130 import bpy 00131 00132 replace_bpy_app_version() 00133 if not bpy.data.filepath: 00134 clear_startup_blend() 00135 00136 print(" Running: '%s'" % run) 00137 print(" MD5: '%s'!" % md5) 00138 00139 try: 00140 result = eval(run) 00141 except: 00142 import traceback 00143 traceback.print_exc() 00144 sys.exit(1) 00145 00146 if write_blend is not None: 00147 print(" Writing Blend: %s" % write_blend) 00148 bpy.ops.wm.save_mainfile(filepath=write_blend, check_existing=False) 00149 00150 print(" Result: '%s'" % str(result)) 00151 if not result: 00152 print(" Running: %s -> False" % run) 00153 sys.exit(1) 00154 00155 if md5_method == 'SCENE': 00156 md5_new = blend_to_md5() 00157 elif md5_method == 'FILE': 00158 if not md5_source: 00159 print(" Missing --md5_source argument") 00160 sys.exit(1) 00161 00162 for f in md5_source: 00163 if not os.path.exists(f): 00164 print(" Missing --md5_source=%r argument does not point to a file") 00165 sys.exit(1) 00166 00167 import hashlib 00168 00169 md5_instance = hashlib.new("md5") 00170 md5_update = md5_instance.update 00171 00172 for f in md5_source: 00173 filehandle = open(f, "rb") 00174 md5_update(filehandle.read()) 00175 filehandle.close() 00176 00177 md5_new = md5_instance.hexdigest() 00178 00179 else: 00180 print(" Invalid --md5_method=%s argument is not a valid source") 00181 sys.exit(1) 00182 00183 if md5 != md5_new: 00184 print(" Running: %s\n MD5 Recieved: %s\n MD5 Expected: %s" % (run, md5_new, md5)) 00185 sys.exit(1) 00186 00187 print(" Success: %s" % run) 00188 00189 00190 if __name__ == "__main__": 00191 # So a python error exits(1) 00192 try: 00193 main() 00194 except: 00195 import traceback 00196 traceback.print_exc() 00197 sys.exit(1)