Changeset 792
- Timestamp:
- 08/19/07 15:06:23 (1 year ago)
- Files:
-
- pyrun/trunk/ChangeLog (modified) (1 diff)
- pyrun/trunk/pyrun.py (modified) (17 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
pyrun/trunk/ChangeLog
r791 r792 3 3 4 4 0.1.1: 5 * Added support for directory exclusions and path prunes. 6 exclusion prevents discovery descending into a directory if that 7 directory startswith an element in the exclusion set (see new option -x). 8 prune operates on the result of the discovery. Any path which 9 contains one of the strings specified by a prune is removed from the 10 discovered path. 11 exclusion hides directories from the discovery process, prune removes 12 results after the fact. 13 . 14 exclusions are enabled by -x 15 prunes are enabled by -X 16 empty strings are *always* removed from -x and -X. 17 . 18 Note that no mechanism is provided for adding a path back in *under* 19 and excluded directory. 20 * Decided to use logging instead of print for notification, I had avoided 21 this previously because I did not want to polute the logging configuration 22 of the target app. I consider this change provisional, if it causes to 23 much trouble I will revert to print 5 24 * Added support for including .pth files in the discovery phase. This 6 25 makes it possible to insert paths to directories which do not contain pyrun/trunk/pyrun.py
r791 r792 7 7 from os.path import join, dirname, basename, isfile, isdir, exists 8 8 from os.path import splitext 9 10 import logging 11 log = logging.getLogger(__name__) 9 12 10 13 have_runpy=False … … 269 272 270 273 pthset = set(kw.pop('pth', [])) 274 exclude = kw.pop('exclude', []) 271 275 pth = [] 272 276 273 evpp = lambda p,name='': evaluate_packagepath(p) 277 evpp = lambda p, name='': evaluate_packagepath(p) 278 279 def allow_descent(path): 280 for e in exclude: 281 if path.startswith(e): 282 log.info('Excluding: "%s" as it startswith "%s" %s' % ( 283 path, e, type(exclude) 284 )) 285 return False 286 return isdir(path) and not isegg_path(path) 274 287 275 288 for rp in rootpaths: 276 289 ep = evpp(rp) 290 291 # Don't apply exclude to explicitly listed python files. 277 292 if ep and ep not in pthset: 278 293 pthset.add(ep) … … 282 297 continue 283 298 for top in find_top_packages(rp, 284 evaluate_packagelocation=evpp 299 evaluate_packagelocation=evpp, 300 allow_descent=allow_descent 285 301 ): 286 302 for p in top[1]: … … 303 319 304 320 305 def discover_path( offset, *args):321 def discover_path(exclude, offset, *args): 306 322 307 323 """Discover a python path. … … 342 358 """ 343 359 360 if exclude is None: 361 exclude = frozenset([]) 344 362 doesnotexist = [] 345 363 minfos = [] … … 369 387 elif isfile(a) and splitext(a)[1] == '.pth': 370 388 if findpaths: 371 newpaths = find_package_paths(pth=pthset, 389 newpaths = find_package_paths( 390 pth=pthset, exclude=exclude, 372 391 *findpaths 373 392 ) … … 400 419 findpaths.append(a) 401 420 402 newpaths = find_package_paths(pth=pthset, 421 newpaths = find_package_paths( 422 pth=pthset, exclude=exclude, 403 423 *findpaths 404 424 ) … … 408 428 409 429 410 def discover_and_run(argv=None, run_module=True, modify_sys=True): 430 def discover_and_run(argv=None, run_module=True, modify_sys=True, 431 exclude=frozenset([])): 411 432 """Discover package paths and run the last module listed in argv. 412 433 … … 444 465 argv = argv or sys.argv[:] 445 466 446 pthextend, minfos, ia, doesnotexist = discover_path( 1, *argv)467 pthextend, minfos, ia, doesnotexist = discover_path(exclude, 1, *argv) 447 468 448 469 # We are running the module, eat the artificial `--` delimiter … … 570 591 the sys.argv the module sees.""" 571 592 593 def int_log_level(level): 594 """Coerce a log level to an integer. 595 596 In a manner cognizant of run time configured level names.""" 597 598 try: 599 return int(level) 600 except ValueError: 601 try: 602 return getattr(logging, level) 603 except AttributeError: 604 level = logging.getLevelName(level) 605 level = logging.getLevelName(level) 606 assert isinstance(level, int) 607 return level 608 609 572 610 def runex(argv=None): 573 611 """Provides Extened `pyrun` features on the command line.""" … … 587 625 argv.insert(0, None) 588 626 627 logging.basicConfig( 628 level=int_log_level(getattr(opts, 'log_level', 'WARNING')), 629 format='%(message)s' 630 ) 631 632 exclude = [] 633 if opts.x: 634 for e in opts.x.split(os.pathsep): 635 if not e: 636 log.warning( 637 'Warning: empty path found in (and removed from) your ' 638 'exclusion path (-x)' 639 ) 640 continue 641 exclude.append(e) 642 643 prune = [] 644 for p in opts.X: 645 if not p: 646 log.warning( 647 'Warning: empty path found in (and removed from) your ' 648 'prune list (-X)' 649 ) 650 continue 651 prune.append(p) 652 589 653 try: 590 654 source = False 591 655 sourcefile = None 592 656 if opts.c and opts.C and not opts.q: 593 printstriplines(('''657 log.warning(striplines((''' 594 658 Warning: -c and -C can not be used together. Ignoring "-C %s" 595 ''' % opts.C) 659 ''' % opts.C)) 596 660 ) 597 661 … … 605 669 606 670 pthextend, minfos, ia, doesnotexist = discover_path( 607 1, *argv)671 exclude, 1, *argv) 608 672 609 673 if not opts.q and doesnotexist: 610 printstriplines('''\674 log.warning(striplines('''\ 611 675 Warning: your discovery path arguments referenced the following 612 676 files or directories which do not exist on the file system: 613 677 ''') 614 print '\t' + '\n\t'.join(doesnotexist) 678 ) 679 log.warning('\t' + '\n\t'.join(doesnotexist)) 615 680 616 681 … … 668 733 669 734 if opts.c and opts.C and not opts.q: 670 print(735 log.warning(( 671 736 'Warning: -c and -C can not be used together. Ignoring "-C %s"' 672 737 ) % opts.C 738 ) 673 739 674 740 if opts.C: … … 681 747 modname = not source and (opts.m or (minfos and minfos[0][1]) or '') 682 748 749 # prune and paths which contain *non empty* strings spefcified by -X 750 for X in prune: 751 if not X: 752 log.warning( 753 'Warning: An empty string was specified using -X, ' 754 'as this would prune *all* paths it will be ignored.' 755 ) 756 continue 757 pthextend[:] = [p for p in pthextend if X not in p] 758 683 759 # Allways update the sys path. pthextend is the record of what we have 684 760 # done. The record only matters for interative mode in cases where you … … 696 772 def run(): 697 773 if opts.n: 698 print 'execution of module disabled by user options'774 log.critical('execution of module disabled by user options') 699 775 return 0 700 776 if not target_argv: 701 print 'argv is empty'777 log.critical('argv is empty') 702 778 return 0 703 779 sys.argv[:] = target_argv[:] … … 808 884 809 885 OPTIONS_runex=[ 886 ('--log-level', dict(default=False)), 810 887 ('-q', dict(default=False, action='store_true', metavar='QUIET', help= 811 888 """Suppress all warnings about missing paths etc. Useful when you are … … 849 926 ('-c', dict(default=False, metavar='STATEMENT', help= 850 927 """Update sys.argv and sys.path then execute the statement in a new, clean, 851 module context.""")) 928 module context.""")), 929 930 ('-x', dict(default="", metavar='EXCLUDE', help= 931 """Exclude one or more directorys, seperated by "%s", from the discovery 932 path.""" % os.pathsep)), 933 ('-X', dict(default=[], metavar='PRUNE', action="append", type="string", help= 934 """Prune all paths which contain this value from the set of paths which *were* 935 discovered. Specify multiple -X options if you whish too prune based on 936 more than one string.""")) 852 937 853 938 ]