| 321 | | """ |
|---|
| 322 | | if run_module is True: |
|---|
| 323 | | from runpy import run_module |
|---|
| | 317 | :Paramaters: |
|---|
| | 318 | run_module |
|---|
| | 319 | If False the module will *not* be executed. Otherwise it should |
|---|
| | 320 | be the either: The explicit name of the module to run or any |
|---|
| | 321 | value that evalutes True. If its true and its *not* a string |
|---|
| | 322 | then the module name corresponding to the *first* module file |
|---|
| | 323 | referenced in `argv` is implied. |
|---|
| | 324 | modify_sys |
|---|
| | 325 | If False sys.argv and sys.path will *not* be changed. Otherwise |
|---|
| | 326 | sys.argv and sys.path will be updated appropriately only if |
|---|
| | 327 | run_module is not False. |
|---|
| | 328 | |
|---|
| | 329 | :Returns: |
|---|
| | 330 | If a module is run the return value is the result of |
|---|
| | 331 | `runpy.run_module` otherwise it is a 3 element tuple: |
|---|
| | 332 | |
|---|
| | 333 | (pthextend, minfos, ia) |
|---|
| | 334 | |
|---|
| | 335 | * `pthextend` is a list of the paths that were discovered. |
|---|
| | 336 | * `minfos` is a list of tuples describing the results of examining |
|---|
| | 337 | any module files. |
|---|
| | 338 | * `ia` is index of the first option argument encountered after the |
|---|
| | 339 | discovery paths. |
|---|
| | 340 | |
|---|
| | 341 | """ |
|---|
| | 342 | |
|---|
| | 343 | if run_module: |
|---|
| | 344 | import runpy |
|---|
| 328 | | if run_module and minfos: |
|---|
| 329 | | sys.path[0:0] = pthextend[:] |
|---|
| 330 | | sys.argv[:] = [] |
|---|
| 331 | | sys.argv.append(minfos[0][1]) |
|---|
| 332 | | sys.argv.extend(argv[ia:]) |
|---|
| 333 | | return run_module(sys.argv[0], run_name='__main__', alter_sys=True) |
|---|
| | 349 | |
|---|
| | 350 | if run_module: |
|---|
| | 351 | |
|---|
| | 352 | if not isinstance(run_module, types.StringTypes): |
|---|
| | 353 | run_module = minfos[0][1] |
|---|
| | 354 | |
|---|
| | 355 | if modify_sys: |
|---|
| | 356 | # We are running the module, eat the artificial `--` delimiter |
|---|
| | 357 | # if it artificially terminated the argv |
|---|
| | 358 | if ia < len(argv) and argv[ia] == '--': |
|---|
| | 359 | del argv[ia] |
|---|
| | 360 | sys.path[0:0] = pthextend[:] |
|---|
| | 361 | sys.argv[:] = [] |
|---|
| | 362 | sys.argv.append(run_module) |
|---|
| | 363 | sys.argv.extend(argv[ia:]) |
|---|
| | 364 | |
|---|
| | 365 | return runpy.run_module( |
|---|
| | 366 | run_module, run_name='__main__', alter_sys=True |
|---|
| | 367 | ) |
|---|
| | 368 | |
|---|
| | 372 | def runex(argv=None): |
|---|
| | 373 | """Provides Extened `pyrun` features on the command line.""" |
|---|
| | 374 | |
|---|
| | 375 | # Process the command line arguments. |
|---|
| | 376 | import optparse |
|---|
| | 377 | parser = optparse.OptionParser(usage=USAGE_runex) |
|---|
| | 378 | default_opts = {} |
|---|
| | 379 | for shrt, kw in OPTIONS_runex: |
|---|
| | 380 | default_opts[shrt[1]] = kw['default'] |
|---|
| | 381 | parser.add_option(shrt, **kw) |
|---|
| | 382 | |
|---|
| | 383 | parser.disable_interspersed_args() |
|---|
| | 384 | |
|---|
| | 385 | opts, args = parser.parse_args() |
|---|
| | 386 | argv = args[:] |
|---|
| | 387 | argv.insert(0, None) |
|---|
| | 388 | |
|---|
| | 389 | try: |
|---|
| | 390 | pthextend, minfos, ia = discover_path(1, *argv) |
|---|
| | 391 | |
|---|
| | 392 | # If there are no unconsumed arguments: We have already determined |
|---|
| | 393 | # the user does not want to run a module. So we are done. |
|---|
| | 394 | |
|---|
| | 395 | assert ia <= len(argv), ( |
|---|
| | 396 | 'ia=%s, argv="%s"' |
|---|
| | 397 | ) % (ia, str(argv) |
|---|
| | 398 | ) |
|---|
| | 399 | if ia == len(argv): |
|---|
| | 400 | argv.append('--') |
|---|
| | 401 | |
|---|
| | 402 | # Unconsumed arguments exist and start at index `ia` in `argv` As a |
|---|
| | 403 | # convenience we allow any *one* of the pyrun options to be used as to |
|---|
| | 404 | # delimit the end of the discovery path. This means that we need to |
|---|
| | 405 | # examine the first remaining option and determine whether its intended |
|---|
| | 406 | # for pyrun and if so whether it means we have more to do. But, and |
|---|
| | 407 | # this is *IMPORTANT*, if any option was set before the discovery path |
|---|
| | 408 | # it is assumed to be for the target module and hence is ignored. For |
|---|
| | 409 | # example ``pyrun -m bar ~/foo -m 12`` means search under `~/foo` for |
|---|
| | 410 | # package paths, then run module `bar` with an argv of: |
|---|
| | 411 | # ``['bar', '-m', '12']`` |
|---|
| | 412 | # |
|---|
| | 413 | |
|---|
| | 414 | if argv[ia] == '--': |
|---|
| | 415 | del argv[ia] |
|---|
| | 416 | else: |
|---|
| | 417 | # All pyrun options are short options. |
|---|
| | 418 | nextopt = argv[ia][1:] |
|---|
| | 419 | if nextopt in default_opts: |
|---|
| | 420 | |
|---|
| | 421 | # It's possibly a pyrun option. |
|---|
| | 422 | |
|---|
| | 423 | # Distinguish between those arguments that require values and |
|---|
| | 424 | # those that don't |
|---|
| | 425 | if nextopt in flagOPTIONS_runex: |
|---|
| | 426 | |
|---|
| | 427 | setattr(opts, nextopt, not default_opts[nextopt]) |
|---|
| | 428 | del argv[ia] |
|---|
| | 429 | |
|---|
| | 430 | else: |
|---|
| | 431 | # if its not a flag and it is a pyrun option then it |
|---|
| | 432 | # takes a single argument. |
|---|
| | 433 | if len(argv) < ia+1: |
|---|
| | 434 | print ('The `-%s` pyrun option requires a module name' |
|---|
| | 435 | ) % nextopt |
|---|
| | 436 | return -1 |
|---|
| | 437 | |
|---|
| | 438 | setattr(opts, nextopt, argv[ia+1]) |
|---|
| | 439 | del argv[ia:ia+2] |
|---|
| | 440 | |
|---|
| | 441 | # else: its definitely *not* a pyrun option |
|---|
| | 442 | |
|---|
| | 443 | modname = opts.m or (minfos and minfos[0][1]) or '' |
|---|
| | 444 | |
|---|
| | 445 | target_argv = [] |
|---|
| | 446 | if modname: |
|---|
| | 447 | target_argv.append(modname) |
|---|
| | 448 | target_argv.extend(argv[ia:]) |
|---|
| | 449 | def run_module(): |
|---|
| | 450 | if opts.n: |
|---|
| | 451 | print 'execution of module disabled by user options' |
|---|
| | 452 | return 0 |
|---|
| | 453 | if not target_argv: |
|---|
| | 454 | print 'argv is empty' |
|---|
| | 455 | return 0 |
|---|
| | 456 | import runpy |
|---|
| | 457 | sys.argv[:] = target_argv[:] |
|---|
| | 458 | sys.path[0:0] = pthextend[:] |
|---|
| | 459 | return runpy.run_module( |
|---|
| | 460 | modname, run_name='__main__', alter_sys=True |
|---|
| | 461 | ) |
|---|
| | 462 | if opts.d: |
|---|
| | 463 | import pdb |
|---|
| | 464 | pdb.set_trace() |
|---|
| | 465 | if opts.i: |
|---|
| | 466 | banner='' |
|---|
| | 467 | if opts.p: |
|---|
| | 468 | banner += 'Discovered paths:\n\t%s' % '\n\t'.join( |
|---|
| | 469 | pthextend |
|---|
| | 470 | ) |
|---|
| | 471 | if opts.P: |
|---|
| | 472 | banner += '\n\nPYTONPATH=%s' % os.pathsep.join( |
|---|
| | 473 | pthextend |
|---|
| | 474 | ) |
|---|
| | 475 | if opts.p or opts.P: |
|---|
| | 476 | banner += '\n\n' |
|---|
| | 477 | banner += """\ |
|---|
| | 478 | Call `run_module` with no arguments to execute the implied or explicit |
|---|
| | 479 | module. You can safely manipulate the target sys.path and sys.argv before |
|---|
| | 480 | calling `run_module` by updating `target_argv` and `pthextend` in place. |
|---|
| | 481 | `minfos` is a list of tuples describing any module files you listed in |
|---|
| | 482 | the discovery path.""" |
|---|
| | 483 | import code |
|---|
| | 484 | code.interact(banner=banner, local=locals()) |
|---|
| | 485 | if pthextend and opts.p and not opts.i: |
|---|
| | 486 | for p in pthextend: |
|---|
| | 487 | print p |
|---|
| | 488 | if pthextend and opts.P and not opts.i: |
|---|
| | 489 | print os.pathsep.join(pthextend) |
|---|
| | 490 | |
|---|
| | 491 | if not (opts.n or opts.d or opts.i) and opts.m: |
|---|
| | 492 | return run_module() |
|---|
| | 493 | return 0 |
|---|
| | 494 | |
|---|
| | 495 | except SystemExit: |
|---|
| | 496 | raise |
|---|
| | 497 | except: |
|---|
| | 498 | einfo = sys.exc_info() |
|---|
| | 499 | msg = exc_string(einfo=einfo) |
|---|
| | 500 | print msg |
|---|
| | 501 | if opts.d: |
|---|
| | 502 | import pdb |
|---|
| | 503 | pdb.post_mortem(einfo[2]) |
|---|
| | 504 | return -1 |
|---|
| | 505 | |
|---|
| | 506 | |
|---|
| 356 | | def runex(argv=None): |
|---|
| 357 | | return run(argv) |
|---|
| 358 | | |
|---|
| | 534 | OPTIONS_runex=[ |
|---|
| | 535 | |
|---|
| | 536 | ('-p', dict(default=False, action='store_true', metavar='PRINTPATH', help= |
|---|
| | 537 | "Print the discovered path")), |
|---|
| | 538 | |
|---|
| | 539 | ('-P', dict(default=False, action='store_true', metavar='PRINTPATH', help= |
|---|
| | 540 | "Print the discovered path in a PYTHONPATH compatible format")), |
|---|
| | 541 | |
|---|
| | 542 | |
|---|
| | 543 | ('-n', dict(default=False, action='store_true', metavar='NORUN', help= |
|---|
| | 544 | '''NORUN. Don't run any of the modules implied by module file references in |
|---|
| | 545 | the discovery path.''')), |
|---|
| | 546 | |
|---|
| | 547 | ('-m', dict(default='', metavar='MODULE', help= |
|---|
| | 548 | "Explicitly select a module to run.")), |
|---|
| | 549 | |
|---|
| | 550 | ('-d', dict(default=False, action='store_true', metavar='DEBUG', help= |
|---|
| | 551 | """DEBUG session. Prepare for execution, but start a pdb session using |
|---|
| | 552 | `pdb.set_trace`.""")), |
|---|
| | 553 | |
|---|
| | 554 | ('-i', dict(default=False, action='store_true', metavar='INTERACTIVE', help= |
|---|
| | 555 | "INTERACTIVE session with prepared sys.argv and sys.path.")), |
|---|
| | 556 | |
|---|
| | 557 | ('-c', dict(default=False, metavar='STATEMENT', help= |
|---|
| | 558 | """Update sys.argv and sys.path then execute statement in a new |
|---|
| | 559 | python module. [NYI]""")), |
|---|
| | 560 | |
|---|
| | 561 | ('-C', dict(default=False, metavar='STATEMENT', help= |
|---|
| | 562 | """Update sys.argv and sys.path then execute statement in the context of the |
|---|
| | 563 | selected module. [NYI]""")) |
|---|
| | 564 | |
|---|
| | 565 | ] |
|---|
| | 566 | |
|---|
| | 567 | flagOPTIONS_runex=tuple([o[1:] for o, kw in OPTIONS_runex |
|---|
| | 568 | if kw.get('action', None) in ('store_true', 'store_false')] |
|---|
| | 569 | ) |
|---|
| | 570 | |
|---|
| | 571 | USAGE_runex="""\ |
|---|
| | 572 | %prog [-nidP] [BASEPATH 1] [BASEPATH 2] ... [BASEPATH n] |
|---|
| | 573 | [-m mod.name | -c STATEMENT | -C STATEMENT | '--'] [TARGET-OPTIONS] |
|---|
| | 574 | |
|---|
| | 575 | In most cases the solo '--' is not required. It tends to be useful when you |
|---|
| | 576 | implicitly select the module to run AND you want to pass a non option argument |
|---|
| | 577 | as the first value in the command line for that module. It can also be |
|---|
| | 578 | necessary when the target module has short options, without long-name |
|---|
| | 579 | alternatives, which collide with those defined for pyrun. |
|---|
| | 580 | |
|---|
| | 581 | Discover python packages and modules under PATH. Run the first module file |
|---|
| | 582 | named in `PATH` *OR* explicitly nominated using the `-m` option. |
|---|
| | 583 | |
|---|
| | 584 | NOTE: Any option that is marked [NYI] is Not Yet Implemented.""" |
|---|
| | 585 | |
|---|