Changeset 13e46abe in sasview for src/sas/models/c_extension/python_wrapper/WrapperGenerator.py
- Timestamp:
- Mar 2, 2015 4:29:01 PM (10 years ago)
- Branches:
- master, ESS_GUI, ESS_GUI_Docs, ESS_GUI_batch_fitting, ESS_GUI_bumps_abstraction, ESS_GUI_iss1116, ESS_GUI_iss879, ESS_GUI_iss959, ESS_GUI_opencl, ESS_GUI_ordering, ESS_GUI_sync_sascalc, costrafo411, magnetic_scatt, release-4.1.1, release-4.1.2, release-4.2.2, release_4.0.1, ticket-1009, ticket-1094-headless, ticket-1242-2d-resolution, ticket-1243, ticket-1249, ticket885, unittest-saveload
- Children:
- 038c00cf
- Parents:
- 6bd3a8d1
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/sas/models/c_extension/python_wrapper/WrapperGenerator.py
rfd5ac0d r13e46abe 3 3 """ 4 4 5 import os, sys, re5 import os, sys, re 6 6 import lineparser 7 7 8 class WrapperGenerator :8 class WrapperGenerator(object): 9 9 """ Python wrapper generator for C models 10 11 The developer must provide a header file describing 10 11 The developer must provide a header file describing 12 12 the new model. 13 13 14 14 To provide the name of the Python class to be 15 generated, the .h file must contain the following 15 generated, the .h file must contain the following 16 16 string in the comments: 17 17 18 18 // [PYTHONCLASS] = my_model 19 19 20 20 where my_model must be replaced by the name of the 21 21 class that you want to import from sas.models. 22 22 (example: [PYTHONCLASS] = MyModel 23 23 will create a class MyModel in sas.models.MyModel. 24 It will also create a class CMyModel in 24 It will also create a class CMyModel in 25 25 sas_extension.c_models.) 26 27 Also in comments, each parameter of the params 26 27 Also in comments, each parameter of the params 28 28 dictionary must be declared with a default value 29 29 in the following way: 30 30 31 31 // [DEFAULT]=param_name=default_value 32 32 33 33 (example: 34 34 // [DEFAULT]=radius=20.0 35 35 ) 36 36 37 37 See cylinder.h for an example. 38 39 38 40 39 A .c file corresponding to the .h file should also 41 40 be provided (example: my_model.h, my_model.c). 42 41 43 42 The .h file should define two function definitions. For example, 44 43 cylinder.h defines the following: 45 44 46 45 /// 1D scattering function 47 46 double cylinder_analytical_1D(CylinderParameters *pars, double q); 48 47 49 48 /// 2D scattering function 50 49 double cylinder_analytical_2D(CylinderParameters *pars, double q, double phi); 51 50 52 51 The .c file implements those functions. 53 52 54 53 @author: Mathieu Doucet / UTK 55 54 @contact: mathieu.doucet@nist.gov 56 55 """ 57 56 58 57 def __init__(self, filename, output_dir='.', c_wrapper_dir='.'): 59 58 """ Initialization """ 60 59 61 60 ## Name of .h file to generate wrapper from 62 61 self.file = filename 63 62 64 63 # Info read from file 65 64 66 65 ## Name of python class to write 67 66 self.pythonClass = None … … 83 82 self.disp_params = [] 84 83 #model description 85 self.description =''84 self.description = '' 86 85 # paramaters for fittable 87 self.fixed = []86 self.fixed = [] 88 87 # paramaters for non-fittable 89 self.non_fittable = []88 self.non_fittable = [] 90 89 ## parameters with orientation 91 self.orientation_params = []90 self.orientation_params = [] 92 91 ## parameter with magnetism 93 92 self.magentic_params = [] … … 100 99 self.c_wrapper_dir = c_wrapper_dir 101 100 102 103 104 101 def __repr__(self): 105 102 """ Simple output for printing """ 106 107 rep 103 104 rep = "\n Python class: %s\n\n" % self.pythonClass 108 105 rep += " struc name: %s\n\n" % self.structName 109 106 rep += " params: %s\n\n" % self.params 110 107 rep += " description: %s\n\n" % self.description 111 rep += " Fittable parameters: %s\n\n" % self.fixed112 rep += " Non-Fittable parameters: %s\n\n" % self.non_fittable113 rep += " Orientation parameters: %s\n\n" % self.orientation_params114 rep += " Magnetic parameters: %s\n\n" % self.magnetic_params108 rep += " Fittable parameters: %s\n\n" % self.fixed 109 rep += " Non-Fittable parameters: %s\n\n" % self.non_fittable 110 rep += " Orientation parameters: %s\n\n" % self.orientation_params 111 rep += " Magnetic parameters: %s\n\n" % self.magnetic_params 115 112 return rep 116 113 117 114 def read(self): 118 115 """ Reads in the .h file to catch parameters of the wrapper """ 119 116 120 117 # Check if the file is there 121 118 if not os.path.isfile(self.file): 122 119 raise ValueError, "File %s is not a regular file" % self.file 123 120 124 121 # Read file 125 f = open(self.file, 'r')122 f = open(self.file, 'r') 126 123 buf = f.read() 127 124 128 125 self.default_list = "\n List of default parameters:\n\n" 129 126 #lines = string.split(buf,'\n') 130 127 lines = buf.split('\n') 131 self.details 128 self.details = "## Parameter details [units, min, max]\n" 132 129 self.details += " self.details = {}\n" 133 130 134 131 #open item in this case Fixed 135 text ='text'136 key2 ="<%s>"%text.lower()132 text = 'text' 133 key2 = "<%s>" % text.lower() 137 134 # close an item in this case fixed 138 text ='TexT'139 key3 ="</%s>"%text.lower()140 135 text = 'TexT' 136 key3 = "</%s>" % text.lower() 137 141 138 ## Catch fixed parameters 142 139 key = "[FIXED]" 143 140 try: 144 self.fixed = lineparser.readhelper(lines, key,145 key2, key3, file=self.file)141 self.fixed = lineparser.readhelper(lines, key, 142 key2, key3, file=self.file) 146 143 except: 147 raise144 raise 148 145 ## Catch non-fittable parameters parameters 149 146 key = "[NON_FITTABLE_PARAMS]" 150 147 try: 151 self.non_fittable = lineparser.readhelper(lines, key, key2,152 key3, file=self.file)148 self.non_fittable = lineparser.readhelper(lines, key, key2, 149 key3, file=self.file) 153 150 except: 154 raise151 raise 155 152 156 153 ## Catch parameters with orientation 157 key = "[ORIENTATION_PARAMS]" 154 key = "[ORIENTATION_PARAMS]" 158 155 try: 159 self.orientation_params = lineparser.readhelper(lines, key, 160 key2, key3, file=self.file)156 self.orientation_params = lineparser.readhelper(lines, key, 157 key2, key3, file=self.file) 161 158 except: 162 raise163 159 raise 160 164 161 ## Catch parameters with orientation 165 key = "[MAGNETIC_PARAMS]" 162 key = "[MAGNETIC_PARAMS]" 166 163 try: 167 self.magnetic_params = lineparser.readhelper( lines,key,168 key2,key3, file=self.file)164 self.magnetic_params = lineparser.readhelper(lines, key, 165 key2, key3, file=self.file) 169 166 except: 170 raise171 167 raise 168 172 169 ## Catch Description 173 170 key = "[DESCRIPTION]" 174 171 175 172 find_description = False 176 temp =""173 temp = "" 177 174 for line in lines: 178 if line.count(key)>0 : 179 175 if line.count(key) > 0: 180 176 try: 181 find_description = True177 find_description = True 182 178 index = line.index(key) 183 toks = line[index:].split("=", 1)184 temp =toks[1].lstrip().rstrip()185 text ='text'186 key2 ="<%s>"%text.lower()187 if re.match(key2, temp)!=None:188 189 toks2 =temp.split(key2,1)190 self.description =toks2[1]191 text ='text'192 key2 ="</%s>"%text.lower()193 if re.search(key2, toks2[1])!=None:194 temp =toks2[1].split(key2,1)195 self.description =temp[0]179 toks = line[index:].split("=", 1) 180 temp = toks[1].lstrip().rstrip() 181 text = 'text' 182 key2 = "<%s>" % text.lower() 183 if re.match(key2, temp) != None: 184 185 toks2 = temp.split(key2, 1) 186 self.description = toks2[1] 187 text = 'text' 188 key2 = "</%s>" % text.lower() 189 if re.search(key2, toks2[1]) != None: 190 temp = toks2[1].split(key2, 1) 191 self.description = temp[0] 196 192 break 197 193 198 194 else: 199 self.description =temp195 self.description = temp 200 196 break 201 197 except: 202 198 raise ValueError, "Could not parse file %s" % self.file 203 199 elif find_description: 204 text ='text'205 key2 ="</%s>"%text.lower()206 if re.search(key2, line)!=None:207 tok =line.split(key2,1)208 temp =tok[0].split("//",1)209 self.description +=tok[1].lstrip().rstrip()200 text = 'text' 201 key2 = "</%s>" % text.lower() 202 if re.search(key2, line) != None: 203 tok = line.split(key2, 1) 204 temp = tok[0].split("//", 1) 205 self.description += tok[1].lstrip().rstrip() 210 206 break 211 207 else: 212 if re.search("//", line)!=None:213 temp =line.split("//",1)214 self.description +='\n\t\t'+temp[1].lstrip().rstrip()215 208 if re.search("//", line) != None: 209 temp = line.split("//", 1) 210 self.description += '\n\t\t' + temp[1].lstrip().rstrip() 211 216 212 else: 217 self.description +='\n\t\t'+line.lstrip().rstrip()218 219 220 213 self.description += '\n\t\t' + line.lstrip().rstrip() 214 215 216 221 217 for line in lines: 222 218 223 219 # Catch class name 224 220 key = "[PYTHONCLASS]" 225 if line.count(key) >0:221 if line.count(key) > 0: 226 222 try: 227 223 index = line.index(key) 228 toks = line[index:].split("=" 224 toks = line[index:].split("=") 229 225 self.pythonClass = toks[1].lstrip().rstrip() 230 226 231 227 except: 232 228 raise ValueError, "Could not parse file %s" % self.file 233 229 234 230 key = "[CATEGORY]" 235 if line.count(key) >0:231 if line.count(key) > 0: 236 232 try: 237 233 index = line.index(key) … … 255 251 # Catch struct name 256 252 # C++ class definition 257 if line.count("class") >0:253 if line.count("class") > 0: 258 254 # We are entering a class definition 259 255 self.inParDefs = True 260 256 self.foundCPP = True 261 257 262 258 # Old-Style C struct definition 263 if line.count("typedef struct") >0:259 if line.count("typedef struct") > 0: 264 260 # We are entering a struct block 265 261 self.inParDefs = True 266 262 self.inStruct = True 267 268 if self.inParDefs and line.count("}") >0:263 264 if self.inParDefs and line.count("}") > 0: 269 265 # We are exiting a struct block 270 266 self.inParDefs = False 271 267 272 268 if self.inStruct: 273 269 self.inStruct = False 274 270 # Catch the name of the struct 275 271 index = line.index("}") 276 toks = line[index +1:].split(";")272 toks = line[index + 1:].split(";") 277 273 # Catch pointer definition 278 274 toks2 = toks[0].split(',') 279 275 self.structName = toks2[0].lstrip().rstrip() 280 276 281 277 # Catch struct content 282 278 key = "[DEFAULT]" 283 if self.inParDefs and line.count(key) >0:279 if self.inParDefs and line.count(key) > 0: 284 280 # Found a new parameter 285 281 try: … … 295 291 self.default_list += " * %-15s = %s %s\n" % \ 296 292 (toks[1], val, units) 297 293 298 294 # Check for min and max 299 min = "None"300 max = "None"295 value_min = "None" 296 value_max = "None" 301 297 if len(toks2) == 4: 302 min = toks2[2]303 max = toks2[3]304 298 value_min = toks2[2] 299 value_max = toks2[3] 300 305 301 self.details += " self.details['%s'] = ['%s', %s, %s]\n" % \ 306 (toks[1].lstrip().rstrip(), units.lstrip().rstrip(), min,max)302 (toks[1].lstrip().rstrip(), units.lstrip().rstrip(), value_min, value_max) 307 303 except: 308 304 raise ValueError, "Could not parse input file %s \n %s" % \ 309 305 (self.file, sys.exc_value) 310 311 306 307 312 308 # Catch need for numerical calculations 313 309 key = "CalcParameters calcPars" 314 if line.count(key) >0:310 if line.count(key) > 0: 315 311 self.modelCalcFlag = True 316 312 317 313 # Catch list of dispersed parameters 318 314 key = "[DISP_PARAMS]" 319 if line.count(key) >0:315 if line.count(key) > 0: 320 316 try: 321 317 index = line.index(key) … … 330 326 The file is written in C[PYTHONCLASS].c 331 327 """ 332 file_path = os.path.join(self.c_wrapper_dir, 333 "C" +self.pythonClass+'.cpp')328 file_path = os.path.join(self.c_wrapper_dir, 329 "C" + self.pythonClass + '.cpp') 334 330 file = open(file_path, 'w') 335 336 template = open(os.path.join(os.path.dirname(__file__), 331 332 template = open(os.path.join(os.path.dirname(__file__), 337 333 "classTemplate.txt"), 'r') 338 334 339 335 tmp_buf = template.read() 340 336 #tmp_lines = string.split(tmp_buf,'\n') 341 337 tmp_lines = tmp_buf.split('\n') 342 338 343 339 for tmp_line in tmp_lines: 344 340 345 341 # Catch class name 346 newline = self.replaceToken(tmp_line, 347 "[PYTHONCLASS]", 'C' +self.pythonClass)342 newline = self.replaceToken(tmp_line, 343 "[PYTHONCLASS]", 'C' + self.pythonClass) 348 344 #Catch model description 349 345 #newline = self.replaceToken(tmp_line, 350 346 # "[DESCRIPTION]", self.description) 351 347 # Catch C model name 352 newline = self.replaceToken(newline, 348 newline = self.replaceToken(newline, 353 349 "[CMODEL]", self.pythonClass) 354 350 355 351 # Catch class name 356 newline = self.replaceToken(newline, 352 newline = self.replaceToken(newline, 357 353 "[MODELSTRUCT]", self.structName) 358 354 359 355 # Sort model initialization based on multifunc 360 if (self.is_multifunc):356 if self.is_multifunc: 361 357 line = "int level = 1;\nPyArg_ParseTuple(args,\"i\",&level);\n" 362 358 line += "self->model = new " + self.pythonClass + "(level);" 363 359 else: 364 360 line = "self->model = new " + self.pythonClass + "();" 365 366 newline = self.replaceToken(newline,"[INITIALIZE_MODEL]", 367 line) 368 361 362 newline = self.replaceToken(newline, "[INITIALIZE_MODEL]", line) 363 369 364 # Dictionary initialization 370 param_str = "// Initialize parameter dictionary\n" 365 param_str = "// Initialize parameter dictionary\n" 371 366 for par in self.params: 372 367 param_str += " PyDict_SetItemString(self->params,\"%s\",Py_BuildValue(\"d\",%10.12f));\n" % \ 373 368 (par, self.params[par]) 374 369 375 if len(self.disp_params) >0:370 if len(self.disp_params) > 0: 376 371 param_str += " // Initialize dispersion / averaging parameter dict\n" 377 372 param_str += " DispersionVisitor* visitor = new DispersionVisitor();\n" … … 384 379 param_str += " self->model->%s.dispersion->accept_as_source(visitor, self->model->%s.dispersion, disp_dict);\n" % (par, par) 385 380 param_str += " PyDict_SetItemString(self->dispersion, \"%s\", disp_dict);\n" % par 386 381 387 382 # Initialize dispersion object dictionnary 388 383 param_str += "\n" 389 390 384 385 391 386 newline = self.replaceToken(newline, 392 387 "[INITDICTIONARY]", param_str) 393 388 394 389 # Read dictionary 395 390 param_str = " // Reader parameter dictionary\n" … … 397 392 param_str += " self->model->%s = PyFloat_AsDouble( PyDict_GetItemString(self->params, \"%s\") );\n" % \ 398 393 (par, par) 399 400 if len(self.disp_params) >0:394 395 if len(self.disp_params) > 0: 401 396 param_str += " // Read in dispersion parameters\n" 402 397 param_str += " PyObject* disp_dict;\n" … … 408 403 param_str += " disp_dict = PyDict_GetItemString(self->dispersion, \"%s\");\n" % par 409 404 param_str += " self->model->%s.dispersion->accept_as_destination(visitor, self->model->%s.dispersion, disp_dict);\n" % (par, par) 410 405 411 406 newline = self.replaceToken(newline, "[READDICTIONARY]", param_str) 412 407 413 408 # Name of .c file 414 409 #toks = string.split(self.file,'.') … … 416 411 toks = basename.split('.') 417 412 newline = self.replaceToken(newline, "[C_FILENAME]", toks[0]) 418 413 419 414 # Include file 420 415 basename = os.path.basename(self.file) 421 newline = self.replaceToken(newline, 422 "[INCLUDE_FILE]", self.file) 416 newline = self.replaceToken(newline, 417 "[INCLUDE_FILE]", self.file) 423 418 if self.foundCPP: 424 newline = self.replaceToken(newline, 425 "[C_INCLUDE_FILE]", "") 426 newline = self.replaceToken(newline, 427 "[CPP_INCLUDE_FILE]", "#include \"%s\"" % basename) 428 else: 429 newline = self.replaceToken(newline, 430 "[C_INCLUDE_FILE]", "#include \"%s\"" % basename) 431 newline = self.replaceToken(newline, 432 "[CPP_INCLUDE_FILE]", "#include \"models.hh\"") 433 419 newline = self.replaceToken(newline, "[C_INCLUDE_FILE]", "") 420 newline = self.replaceToken(newline, 421 "[CPP_INCLUDE_FILE]", 422 "#include \"%s\"" % basename) 423 else: 424 newline = self.replaceToken(newline, 425 "[C_INCLUDE_FILE]", 426 "#include \"%s\"" % basename) 427 newline = self.replaceToken(newline, 428 "[CPP_INCLUDE_FILE]", 429 "#include \"models.hh\"") 430 434 431 # Numerical calcs dealloc 435 432 dealloc_str = "\n" 436 433 if self.modelCalcFlag: 437 434 dealloc_str = " modelcalculations_dealloc(&(self->model_pars.calcPars));\n" 438 newline = self.replaceToken(newline, 439 "[NUMERICAL_DEALLOC]", dealloc_str) 440 435 newline = self.replaceToken(newline, 436 "[NUMERICAL_DEALLOC]", dealloc_str) 437 441 438 # Numerical calcs init 442 439 init_str = "\n" 443 440 if self.modelCalcFlag: 444 441 init_str = " modelcalculations_init(&(self->model_pars.calcPars));\n" 445 newline = self.replaceToken(newline, 446 "[NUMERICAL_INIT]", init_str) 447 442 newline = self.replaceToken(newline, 443 "[NUMERICAL_INIT]", init_str) 444 448 445 # Numerical calcs reset 449 446 reset_str = "\n" 450 447 if self.modelCalcFlag: 451 448 reset_str = "modelcalculations_reset(&(self->model_pars.calcPars));\n" 452 newline = self.replaceToken(newline, 453 "[NUMERICAL_RESET]", reset_str) 454 449 newline = self.replaceToken(newline, 450 "[NUMERICAL_RESET]", reset_str) 451 455 452 # Setting dispsertion weights 456 453 set_weights = " // Ugliness necessary to go from python to C\n" … … 463 460 set_weights += " self->model->%s.dispersion = dispersion;\n" % par 464 461 set_weights += " } else" 465 newline = self.replaceToken(newline, 466 "[SET_DISPERSION]", set_weights) 467 462 newline = self.replaceToken(newline, 463 "[SET_DISPERSION]", set_weights) 464 468 465 # Write new line to the wrapper .c file 469 file.write(newline +'\n')470 471 466 file.write(newline + '\n') 467 468 472 469 file.close() 473 470 474 471 def write_python_wrapper(self): 475 472 """ Writes the python file to create the python extension class 476 473 The file is written in ../[PYTHONCLASS].py 477 474 """ 478 file_path = os.path.join(self.output_dir, self.pythonClass +'.py')475 file_path = os.path.join(self.output_dir, self.pythonClass + '.py') 479 476 file = open(file_path, 'w') 480 template = open(os.path.join(os.path.dirname(__file__), 477 template = open(os.path.join(os.path.dirname(__file__), 481 478 "modelTemplate.txt"), 'r') 482 479 483 480 tmp_buf = template.read() 484 481 tmp_lines = tmp_buf.split('\n') 485 482 486 483 for tmp_line in tmp_lines: 487 484 488 485 # Catch class name 489 newline = self.replaceToken(tmp_line, 490 "[CPYTHONCLASS]", 486 newline = self.replaceToken(tmp_line, 487 "[CPYTHONCLASS]", 491 488 'C' + self.pythonClass) 492 489 493 490 # Catch class name 494 newline = self.replaceToken(newline, 491 newline = self.replaceToken(newline, 495 492 "[PYTHONCLASS]", self.pythonClass) 496 493 497 494 # Include file 498 newline = self.replaceToken(newline, 499 "[INCLUDE_FILE]", self.file) 500 495 newline = self.replaceToken(newline, 496 "[INCLUDE_FILE]", self.file) 497 501 498 # Include file 502 newline = self.replaceToken(newline, 499 newline = self.replaceToken(newline, 503 500 "[DEFAULT_LIST]", self.default_list) 504 501 # model description 505 newline = self.replaceToken(newline, 502 newline = self.replaceToken(newline, 506 503 "[DESCRIPTION]", self.description) 507 504 # Parameter details 508 newline = self.replaceToken(newline, 505 newline = self.replaceToken(newline, 509 506 "[PAR_DETAILS]", self.details) 510 507 511 508 # Call base constructor 512 509 if self.is_multifunc: 513 newline = self.replaceToken(newline, "[CALL_CPYTHON_INIT]",514 'C' + self.pythonClass + \510 newline = self.replaceToken(newline, "[CALL_CPYTHON_INIT]", 511 'C' + self.pythonClass + \ 515 512 ".__init__(self,multfactor)\n\tself.is_multifunc = True") 516 newline = self.replaceToken(newline, "[MULTIPLICITY_INFO]",513 newline = self.replaceToken(newline, "[MULTIPLICITY_INFO]", 517 514 self.multiplicity_info) 518 515 else: 519 newline = self.replaceToken(newline, "[CALL_CPYTHON_INIT]",520 'C' + self.pythonClass + \516 newline = self.replaceToken(newline, "[CALL_CPYTHON_INIT]", 517 'C' + self.pythonClass + \ 521 518 ".__init__(self)\n self.is_multifunc = False") 522 newline = self.replaceToken(newline, 519 newline = self.replaceToken(newline, 523 520 "[MULTIPLICITY_INFO]", "None") 524 521 525 526 522 # fixed list details 527 523 fixed_str = str(self.fixed) 528 524 fixed_str = fixed_str.replace(', ', ',\n ') 529 525 newline = self.replaceToken(newline, "[FIXED]", fixed_str) 530 526 531 527 # non-fittable list details 532 528 pars_str = str(self.non_fittable) 533 pars_str = pars_str.replace(', ', 529 pars_str = pars_str.replace(', ', 534 530 ',\n ') 535 newline = self.replaceToken(newline, 531 newline = self.replaceToken(newline, 536 532 "[NON_FITTABLE_PARAMS]", pars_str) 537 533 538 534 ## parameters with orientation 539 535 oriented_str = str(self.orientation_params) 540 536 formatted_endl = ',\n ' 541 537 oriented_str = oriented_str.replace(', ', formatted_endl) 542 newline = self.replaceToken(newline, 543 "[ORIENTATION_PARAMS]", oriented_str) 544 ## parameters with magnetism 545 newline = self.replaceToken(newline, 546 "[MAGNETIC_PARAMS]", str(self.magnetic_params)) 538 newline = self.replaceToken(newline, 539 "[ORIENTATION_PARAMS]", oriented_str) 540 ## parameters with magnetism 541 newline = self.replaceToken(newline, 542 "[MAGNETIC_PARAMS]", 543 str(self.magnetic_params)) 547 544 548 545 if self.category: 549 newline = self.replaceToken(newline, "[CATEGORY]", 546 newline = self.replaceToken(newline, "[CATEGORY]", 550 547 '"' + self.category + '"') 551 548 else: 552 549 newline = self.replaceToken(newline, "[CATEGORY]", 553 550 "None") 554 551 555 552 556 553 557 554 # Write new line to the wrapper .c file 558 file.write(newline +'\n')559 555 file.write(newline + '\n') 556 560 557 file.close() 561 562 558 559 563 560 def replaceToken(self, line, key, value): #pylint: disable-msg=R0201 564 561 """ Replace a token in the template file … … 570 567 lenkey = len(key) 571 568 newline = line 572 573 while newline.count(key) >0:569 570 while newline.count(key) > 0: 574 571 index = newline.index(key) 575 newline = newline[:index] +value+newline[index+lenkey:]576 572 newline = newline[:index] + value + newline[index + lenkey:] 573 577 574 return newline 578 575 579 576 def getModelName(self): 580 577 return self.pythonClass 581 578 582 579 583 580 584 581 # main 585 582 if __name__ == '__main__': 586 if len(sys.argv) >1:583 if len(sys.argv) > 1: 587 584 print "Will look for file %s" % sys.argv[1] 588 585 app = WrapperGenerator(sys.argv[1]) … … 593 590 app.write_python_wrapper() 594 591 print app 595 592 596 593 # End of file
Note: See TracChangeset
for help on using the changeset viewer.