Commit f2201c1ace91ebbd921cb1cac00037814a7720c1
1 parent
94193f22
Code generator for new module adjusts now all relevant configuration, setup and Makefiles (#2190)
Showing
1 changed file
with
259 additions
and
8 deletions
dev/codegen.py
| ... | ... | @@ -141,7 +141,7 @@ def add_file(infile, outfile, tokens): |
| 141 | 141 | |
| 142 | 142 | # If we have a header line than format the line |
| 143 | 143 | if is_header: |
| 144 | - text = gammalib.strip_whitespace(line[2:69]) | |
| 144 | + text = line.strip(' *\n') | |
| 145 | 145 | if n_header == 2: |
| 146 | 146 | line = ' *'+gammalib.centre(text,73)+'*\n' |
| 147 | 147 | elif n_header == 4: |
| ... | ... | @@ -202,7 +202,8 @@ def set_tokens(name, instrument, author): |
| 202 | 202 | year = str(date.today().year) |
| 203 | 203 | |
| 204 | 204 | # Set tokens |
| 205 | - tokens = [{'pattern': 'XXX', 'string': name.upper()}, | |
| 205 | + tokens = [{'pattern': 'xxx', 'string': name.lower()}, | |
| 206 | + {'pattern': 'XXX', 'string': name.upper()}, | |
| 206 | 207 | {'pattern': '[INSTRUMENT]', 'string': instrument}, |
| 207 | 208 | {'pattern': '[AUTHOR]', 'string': author}, |
| 208 | 209 | {'pattern': '[YEAR]', 'string': year}] |
| ... | ... | @@ -247,9 +248,9 @@ def module_menu(): |
| 247 | 248 | |
| 248 | 249 | # Ask to confirm module summary |
| 249 | 250 | print('All right. Have now:') |
| 250 | - print(' Module name ....: "%s"' % name) | |
| 251 | - print(' Instrument name : "%s"' % instrument) | |
| 252 | - print(' Your name ......: "%s"' % author) | |
| 251 | + print('Module name .....: "%s"' % name) | |
| 252 | + print('Instrument name .: "%s"' % instrument) | |
| 253 | + print('Your name .......: "%s"' % author) | |
| 253 | 254 | if confirm('Is this correct?'): |
| 254 | 255 | break |
| 255 | 256 | |
| ... | ... | @@ -257,12 +258,12 @@ def module_menu(): |
| 257 | 258 | tokens = set_tokens(name, instrument, author) |
| 258 | 259 | |
| 259 | 260 | # If the module exists already then determine all base classes that are |
| 260 | - # not yet implemented | |
| 261 | + # not yet implemented and propose to add them one by one ... | |
| 261 | 262 | if os.path.isdir('inst/%s' % name): |
| 262 | 263 | |
| 263 | 264 | # Determine which of the baseclasses are not yet implemented |
| 264 | 265 | baseclasses = ['GObservation', 'GResponse', |
| 265 | - 'GEventAtom', 'GEventBin', 'GEventCube', 'GEventList', | |
| 266 | + 'GEventList', 'GEventAtom', 'GEventCube', 'GEventBin', | |
| 266 | 267 | 'GInstDir', 'GRoi'] |
| 267 | 268 | files = glob.glob('inst/%s/include/*.hpp' % name) |
| 268 | 269 | for file in files: |
| ... | ... | @@ -276,7 +277,7 @@ def module_menu(): |
| 276 | 277 | 'are already implemented. Return now to main menu.') |
| 277 | 278 | return |
| 278 | 279 | else: |
| 279 | - print("All right. Now let's add some classes:") | |
| 280 | + print('All right. Now let\'s add some classes:') | |
| 280 | 281 | |
| 281 | 282 | # Loop over all missing baseclasses |
| 282 | 283 | for baseclass in baseclasses: |
| ... | ... | @@ -284,6 +285,256 @@ def module_menu(): |
| 284 | 285 | if confirm('Add "%s" class?' % classname): |
| 285 | 286 | add_instrument_class(name, tokens, classname) |
| 286 | 287 | |
| 288 | + # ... otherwise add a new module | |
| 289 | + else: | |
| 290 | + | |
| 291 | + # Setup base classes | |
| 292 | + baseclasses = ['GObservation', 'GResponse'] | |
| 293 | + | |
| 294 | + # Ask further questions | |
| 295 | + print('All right. You want a new "%s" instrument module.' % name) | |
| 296 | + while True: | |
| 297 | + add_list = confirm('Do you want event list support?') | |
| 298 | + add_bin = confirm('Do you want binned event data support?') | |
| 299 | + if not add_list and not add_bin: | |
| 300 | + print('*** Warning: You need no support for event lists and ' | |
| 301 | + 'binned event data. This means that you have no data :o') | |
| 302 | + if confirm('Is this true? You want a module that cannot handle data?'): | |
| 303 | + break | |
| 304 | + else: | |
| 305 | + break | |
| 306 | + | |
| 307 | + # Add base classes according to choice | |
| 308 | + if add_list or add_bin: | |
| 309 | + baseclasses.append('GInstDir') | |
| 310 | + if add_list: | |
| 311 | + baseclasses.extend(['GEventList', 'GEventAtom', 'GRoi']) | |
| 312 | + if add_bin: | |
| 313 | + baseclasses.extend(['GEventCube', 'GEventBin']) | |
| 314 | + | |
| 315 | + # Create directory structure | |
| 316 | + os.mkdir('inst/%s' % name) | |
| 317 | + os.mkdir('inst/%s/caldb' % name) | |
| 318 | + os.mkdir('inst/%s/include' % name) | |
| 319 | + os.mkdir('inst/%s/pyext' % name) | |
| 320 | + os.mkdir('inst/%s/src' % name) | |
| 321 | + os.mkdir('inst/%s/test' % name) | |
| 322 | + os.mkdir('inst/%s/test/data' % name) | |
| 323 | + | |
| 324 | + # Add some files | |
| 325 | + add_file('src/template/inst_Makefile.am', | |
| 326 | + 'inst/%s/Makefile.am' % name, tokens) | |
| 327 | + add_file('src/template/inst_README.md', | |
| 328 | + 'inst/%s/README.md' % name, tokens) | |
| 329 | + add_file('src/template/GXXXLib.hpp', | |
| 330 | + 'inst/%s/include/G%sLib.hpp' % (name, name.upper()), tokens) | |
| 331 | + add_file('src/template/xxx.i', | |
| 332 | + 'inst/%s/pyext/%s.i' % (name, name), tokens) | |
| 333 | + add_file('src/template/inst_test_Makefile.am', | |
| 334 | + 'inst/%s/test/Makefile.am' % name, tokens) | |
| 335 | + add_file('src/template/inst_test_XXX.hpp', | |
| 336 | + 'inst/%s/test/test_%s.hpp' % (name, name.upper()), tokens) | |
| 337 | + add_file('src/template/inst_test_XXX.cpp', | |
| 338 | + 'inst/%s/test/test_%s.cpp' % (name, name.upper()), tokens) | |
| 339 | + add_file('src/template/inst_test_XXX.py', | |
| 340 | + 'inst/%s/test/test_%s.py' % (name, name.upper()), tokens) | |
| 341 | + | |
| 342 | + # Adjust configuration | |
| 343 | + adjust_config(name) | |
| 344 | + | |
| 345 | + # Adjust Python configuration | |
| 346 | + adjust_python_config(name, instrument) | |
| 347 | + | |
| 348 | + # Adjust test configuration | |
| 349 | + adjust_test_config(name, instrument) | |
| 350 | + | |
| 351 | + | |
| 352 | + # Loop over all baseclasses | |
| 353 | + #for baseclass in baseclasses: | |
| 354 | + # classname = 'G'+name.upper()+baseclass[1:] | |
| 355 | + # if confirm('Add "%s" class?' % classname): | |
| 356 | + # add_instrument_class(name, tokens, classname) | |
| 357 | + | |
| 358 | + # Return | |
| 359 | + return | |
| 360 | + | |
| 361 | + | |
| 362 | +# ============================================== # | |
| 363 | +# Adjust configuration for new instrument module # | |
| 364 | +# ============================================== # | |
| 365 | +def adjust_config(name): | |
| 366 | + """ | |
| 367 | + Parameters | |
| 368 | + ---------- | |
| 369 | + name : str | |
| 370 | + Module name | |
| 371 | + """ | |
| 372 | + # Adjust inst/Makefile.am | |
| 373 | + config = 'if WITH_INST_%s\nINST_%s = %s\nendif\n' % (name.upper(), name.upper(), name) | |
| 374 | + for line in fileinput.FileInput('inst/Makefile.am',inplace=1): | |
| 375 | + if 'Detect configuration' in line: | |
| 376 | + line = line.replace(line, line+config) | |
| 377 | + elif 'SUBDIRS=' in line.replace(' ', ''): | |
| 378 | + line = line.replace(line, line[:-1]+' $(INST_%s)\n' % name.upper()) | |
| 379 | + print line, | |
| 380 | + | |
| 381 | + # Adjust configure.ac | |
| 382 | + checks = '# Checks for %s interface\n' \ | |
| 383 | + 'AC_ARG_WITH([%s],\n' \ | |
| 384 | + ' [AS_HELP_STRING([--with-%s],\n' \ | |
| 385 | + ' [compile in %s specific interface [default=yes]])],\n' \ | |
| 386 | + ' [],\n' \ | |
| 387 | + ' [with_%s=yes])\n' \ | |
| 388 | + 'if test "x$with_%s" = "xyes"; then\n' \ | |
| 389 | + ' AC_CHECK_FILE([$srcdir/inst/%s/README.md],\n' \ | |
| 390 | + ' [with_%s=yes],\n' \ | |
| 391 | + ' [with_%s=no])\n' \ | |
| 392 | + 'fi\n' \ | |
| 393 | + 'AM_CONDITIONAL(WITH_INST_%s, test "x$with_%s" = "xyes")\n' % \ | |
| 394 | + (name.upper(), name, name, name.upper(), name, name, name, | |
| 395 | + name, name, name.upper(), name) | |
| 396 | + wrap = ' if test "x$with_%s" = "xyes"; then\n' \ | |
| 397 | + ' AC_CHECK_FILES([$srcdir/pyext/gammalib/%s_wrap.cpp\n' \ | |
| 398 | + ' $srcdir/pyext/gammalib/%s.py],,\n' \ | |
| 399 | + ' [has_wrappers="no"])\n' \ | |
| 400 | + ' fi' % (name, name, name) | |
| 401 | + files = 'if test "x$with_%s" = "xyes"; then\n' \ | |
| 402 | + ' AC_CONFIG_FILES([inst/%s/Makefile])\n' \ | |
| 403 | + ' AC_CONFIG_FILES([inst/%s/test/Makefile])\n' \ | |
| 404 | + 'fi' % (name, name, name) | |
| 405 | + info = 'if test "x$with_%s" = "xyes"; then\n' \ | |
| 406 | + ' echo " * %s interface (yes)"\n' \ | |
| 407 | + 'else\n' \ | |
| 408 | + ' echo " - %s interface (no)"\n' \ | |
| 409 | + 'fi' % (name, name.upper(), name.upper()) | |
| 410 | + for line in fileinput.FileInput('configure.ac',inplace=1): | |
| 411 | + if '# Insert new checks here' in line: | |
| 412 | + print(checks) | |
| 413 | + elif '# Insert new wrappers here' in line: | |
| 414 | + print(wrap) | |
| 415 | + elif '# Inset new Makefiles here' in line: | |
| 416 | + print(files) | |
| 417 | + elif '# Insert new interface informations here' in line: | |
| 418 | + print(info) | |
| 419 | + print line, | |
| 420 | + | |
| 421 | + # Return | |
| 422 | + return | |
| 423 | + | |
| 424 | + | |
| 425 | +# ===================================================== # | |
| 426 | +# Adjust Python configuration for new instrument module # | |
| 427 | +# ===================================================== # | |
| 428 | +def adjust_python_config(name, instrument): | |
| 429 | + """ | |
| 430 | + Parameters | |
| 431 | + ---------- | |
| 432 | + name : str | |
| 433 | + Module name | |
| 434 | + instrument : str | |
| 435 | + Instrument | |
| 436 | + """ | |
| 437 | + # Adjust pyext/setup.py.in | |
| 438 | + module = 'if \'@WITH_INST_%s_TRUE@\' != \'#\':\n' \ | |
| 439 | + ' print(\'Include %s instrument interface in gammalib Python module.\')\n' \ | |
| 440 | + ' inst_modules.append(\'%s\')' % \ | |
| 441 | + (name.upper(), instrument, name) | |
| 442 | + for line in fileinput.FileInput('pyext/setup.py.in',inplace=1): | |
| 443 | + if '# Insert new module here' in line: | |
| 444 | + print(module) | |
| 445 | + print line, | |
| 446 | + | |
| 447 | + # Adjust pyext/Makefile.am | |
| 448 | + target = 'if WITH_INST_%s\n' \ | |
| 449 | + ' %s_SWIG_TARGETS = $(wrapperdir)/gammalib/%s_wrap.cpp \\\n' \ | |
| 450 | + ' $(wrapperdir)/gammalib/%s.py\n' \ | |
| 451 | + ' %s_TESTS = $(top_srcdir)/inst/%s/test/test_%s.py\n' \ | |
| 452 | + 'endif' % (name.upper(), name.upper(), name, name, | |
| 453 | + name.upper(), name, name.upper()) | |
| 454 | + targets = ' $(%s_SWIG_TARGETS) ' % name.upper() | |
| 455 | + rule = '# Rule for %s module\n' \ | |
| 456 | + 'if WITH_INST_%s\n' \ | |
| 457 | + '$(wrapperdir)/gammalib/%s.py: $(wrapperdir)/gammalib/%s_wrap.cpp\n' \ | |
| 458 | + '$(wrapperdir)/gammalib/%s_wrap.cpp: $(top_srcdir)/inst/%s/pyext/%s.i\n' \ | |
| 459 | + ' if $(SWIGCOMPILE) -MMD -MF "gammalib/%s.Tpi" -I$(top_srcdir)/pyext -o gammalib/%s_wrap.cpp -outdir gammalib $<; \\\n' \ | |
| 460 | + ' then mv -f "gammalib/%s.Tpi" "gammalib/%s.Pi"; else rm -f "gammalib/%s.Tpi"; exit 1; fi\n' \ | |
| 461 | + 'endif\n' % (name.upper(), name.upper(), name, name, name, | |
| 462 | + name, name, name, name, name, name, name) | |
| 463 | + for line in fileinput.FileInput('pyext/Makefile.am',inplace=1): | |
| 464 | + if '# Insert new target here' in line: | |
| 465 | + print(target) | |
| 466 | + elif 'INST_SWIG_TARGETS=' in line.replace(' ', ''): | |
| 467 | + last = line[-2] | |
| 468 | + line = line.replace(line, line+targets+last+'\n') | |
| 469 | + elif '$(MWL_TESTS)' in line: | |
| 470 | + line = line.replace(line, line[:-1]+' $(%s_TESTS)\n' % name.upper()) | |
| 471 | + if '# Insert new rule here' in line: | |
| 472 | + print(rule) | |
| 473 | + print line, | |
| 474 | + | |
| 475 | + # Return | |
| 476 | + return | |
| 477 | + | |
| 478 | + | |
| 479 | +# =================================================== # | |
| 480 | +# Adjust test configuration for new instrument module # | |
| 481 | +# =================================================== # | |
| 482 | +def adjust_test_config(name, instrument): | |
| 483 | + """ | |
| 484 | + Parameters | |
| 485 | + ---------- | |
| 486 | + name : str | |
| 487 | + Module name | |
| 488 | + instrument : str | |
| 489 | + Instrument | |
| 490 | + """ | |
| 491 | + # Adjust test/Makefile.am | |
| 492 | + test = 'if WITH_INST_%s\n' \ | |
| 493 | + ' INST_%s = $(top_builddir)/inst/%s/test/test_%s\n' \ | |
| 494 | + ' TEST_%s = :$(top_srcdir)/inst/%s/test\n' \ | |
| 495 | + ' TEST_%s_ENV = TEST_%s_DATA=$(top_srcdir)/inst/%s/test/data\n' \ | |
| 496 | + 'endif' % (name.upper(), name.upper(), name, name.upper(), | |
| 497 | + name.upper(), name, name.upper(), name.upper(), | |
| 498 | + name) | |
| 499 | + testenv = ' $(TEST_%s_ENV) ' % name.upper() | |
| 500 | + tests = ' $(INST_%s) \\\n' % name.upper() | |
| 501 | + for line in fileinput.FileInput('test/Makefile.am',inplace=1): | |
| 502 | + if '# Insert new test here' in line: | |
| 503 | + print(test) | |
| 504 | + elif 'TEST_PYTHON_ENV=' in line.replace(' ', ''): | |
| 505 | + line = line.replace(line, line[:-1]+'$(TEST_%s)\n' % name.upper()) | |
| 506 | + elif 'TEST_DATA=$(top_srcdir)/test/data' in line: | |
| 507 | + last = line[-2] | |
| 508 | + line = line.replace(line, line+testenv+last+'\n') | |
| 509 | + elif '$(TEST_PYTHON_SCRIPT)' in line: | |
| 510 | + line = line.replace(line, tests+line) | |
| 511 | + print line, | |
| 512 | + | |
| 513 | + # Adjust test/test_python.py | |
| 514 | + test = '# Try importing %s tests\n' \ | |
| 515 | + 'try:\n' \ | |
| 516 | + ' import test_%s\n' \ | |
| 517 | + ' has_%s = True\n' \ | |
| 518 | + 'except:\n' \ | |
| 519 | + ' has_%s = False\n' % \ | |
| 520 | + (instrument, name.upper(), name, name) | |
| 521 | + data = ' os.environ[\'TEST_%s_DATA\'] = \'%s/data\'' % \ | |
| 522 | + (name.upper(), name) | |
| 523 | + suite = ' # Optionally handle %s suite\n' \ | |
| 524 | + ' if has_%s:\n' \ | |
| 525 | + ' suite_%s = test_%s.Test()\n' \ | |
| 526 | + ' suite_%s.set()\n' \ | |
| 527 | + ' suites.append(suite_%s)\n' % \ | |
| 528 | + (instrument, name, name, name.upper(), name, name) | |
| 529 | + for line in fileinput.FileInput('test/test_python.py',inplace=1): | |
| 530 | + if '# Insert new test here' in line: | |
| 531 | + print(test) | |
| 532 | + if '# Insert new environment here' in line: | |
| 533 | + print(data) | |
| 534 | + if '# Insert new suite here' in line: | |
| 535 | + print(suite) | |
| 536 | + print line, | |
| 537 | + | |
| 287 | 538 | # Return |
| 288 | 539 | return |
| 289 | 540 | ... | ... |