| OLD | NEW |
| 1 """ | 1 """ |
| 2 TestCmd.py: a testing framework for commands and scripts. | 2 TestCmd.py: a testing framework for commands and scripts. |
| 3 | 3 |
| 4 The TestCmd module provides a framework for portable automated testing | 4 The TestCmd module provides a framework for portable automated testing |
| 5 of executable commands and scripts (in any language, not just Python), | 5 of executable commands and scripts (in any language, not just Python), |
| 6 especially commands and scripts that require file system interaction. | 6 especially commands and scripts that require file system interaction. |
| 7 | 7 |
| 8 In addition to running tests and evaluating conditions, the TestCmd | 8 In addition to running tests and evaluating conditions, the TestCmd |
| 9 module manages and cleans up one or more temporary workspace | 9 module manages and cleans up one or more temporary workspace |
| 10 directories, and provides methods for creating files and directories in | 10 directories, and provides methods for creating files and directories in |
| (...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 304 | 304 |
| 305 try: | 305 try: |
| 306 zip | 306 zip |
| 307 except NameError: | 307 except NameError: |
| 308 def zip(*lists): | 308 def zip(*lists): |
| 309 result = [] | 309 result = [] |
| 310 for i in xrange(min(map(len, lists))): | 310 for i in xrange(min(map(len, lists))): |
| 311 result.append(tuple(map(lambda l, i=i: l[i], lists))) | 311 result.append(tuple(map(lambda l, i=i: l[i], lists))) |
| 312 return result | 312 return result |
| 313 | 313 |
| 314 class Collector: | |
| 315 def __init__(self, top): | |
| 316 self.entries = [top] | |
| 317 def __call__(self, arg, dirname, names): | |
| 318 pathjoin = lambda n, d=dirname: os.path.join(d, n) | |
| 319 self.entries.extend(map(pathjoin, names)) | |
| 320 | |
| 321 def _caller(tblist, skip): | 314 def _caller(tblist, skip): |
| 322 string = "" | 315 string = "" |
| 323 arr = [] | 316 arr = [] |
| 324 for file, line, name, text in tblist: | 317 for file, line, name, text in tblist: |
| 325 if file[-10:] == "TestCmd.py": | 318 if file[-10:] == "TestCmd.py": |
| 326 break | 319 break |
| 327 arr = [(file, line, name, text)] + arr | 320 arr = [(file, line, name, text)] + arr |
| 328 atfrom = "at" | 321 atfrom = "at" |
| 329 for file, line, name, text in arr[skip:]: | 322 for file, line, name, text in arr[skip:]: |
| 330 if name in ("?", "<module>"): | 323 if name in ("?", "<module>"): |
| (...skipping 1124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1455 except OSError: pass | 1448 except OSError: pass |
| 1456 else: os.chmod(fname, stat.S_IMODE(st[stat.ST_MODE]&~stat.S_IREA
D)) | 1449 else: os.chmod(fname, stat.S_IMODE(st[stat.ST_MODE]&~stat.S_IREA
D)) |
| 1457 | 1450 |
| 1458 if os.path.isfile(top): | 1451 if os.path.isfile(top): |
| 1459 # If it's a file, that's easy, just chmod it. | 1452 # If it's a file, that's easy, just chmod it. |
| 1460 do_chmod(top) | 1453 do_chmod(top) |
| 1461 elif read: | 1454 elif read: |
| 1462 # It's a directory and we're trying to turn on read | 1455 # It's a directory and we're trying to turn on read |
| 1463 # permission, so it's also pretty easy, just chmod the | 1456 # permission, so it's also pretty easy, just chmod the |
| 1464 # directory and then chmod every entry on our walk down the | 1457 # directory and then chmod every entry on our walk down the |
| 1465 # tree. Because os.path.walk() is top-down, we'll enable | 1458 # tree. Because os.walk() is top-down, we'll enable |
| 1466 # read permission on any directories that have it disabled | 1459 # read permission on any directories that have it disabled |
| 1467 # before os.path.walk() tries to list their contents. | 1460 # before os.walk() tries to list their contents. |
| 1468 do_chmod(top) | 1461 do_chmod(top) |
| 1469 | 1462 |
| 1470 def chmod_entries(arg, dirname, names, do_chmod=do_chmod): | 1463 for dirname, dirnames, filenames in os.walk(top): |
| 1471 for n in names: | 1464 for n in dirnames: |
| 1472 do_chmod(os.path.join(dirname, n)) | 1465 do_chmod(os.path.join(dirname, n)) |
| 1473 | 1466 for n in filenames: |
| 1474 os.path.walk(top, chmod_entries, None) | 1467 do_chmod(os.path.join(dirname, n)) |
| 1475 else: | 1468 else: |
| 1476 # It's a directory and we're trying to turn off read | 1469 # It's a directory and we're trying to turn off read |
| 1477 # permission, which means we have to chmod the directoreis | 1470 # permission, which means we have to chmod the directoreis |
| 1478 # in the tree bottom-up, lest disabling read permission from | 1471 # in the tree bottom-up, lest disabling read permission from |
| 1479 # the top down get in the way of being able to get at lower | 1472 # the top down get in the way of being able to get at lower |
| 1480 # parts of the tree. But os.path.walk() visits things top | 1473 # parts of the tree. |
| 1481 # down, so we just use an object to collect a list of all | 1474 for dirname, dirnames, filenames in os.walk(top, topdown=False): |
| 1482 # of the entries in the tree, reverse the list, and then | 1475 for n in dirnames: |
| 1483 # chmod the reversed (bottom-up) list. | 1476 do_chmod(os.path.join(dirname, n)) |
| 1484 col = Collector(top) | 1477 for n in filenames: |
| 1485 os.path.walk(top, col, None) | 1478 do_chmod(os.path.join(dirname, n)) |
| 1486 col.entries.reverse() | 1479 |
| 1487 for d in col.entries: do_chmod(d) | 1480 do_chmod(top) |
| 1488 | 1481 |
| 1489 def writable(self, top, write=1): | 1482 def writable(self, top, write=1): |
| 1490 """Make the specified directory tree writable (write == 1) | 1483 """Make the specified directory tree writable (write == 1) |
| 1491 or not (write == None). | 1484 or not (write == None). |
| 1492 """ | 1485 """ |
| 1493 | 1486 |
| 1494 if sys.platform == 'win32': | 1487 if sys.platform == 'win32': |
| 1495 | 1488 |
| 1496 if write: | 1489 if write: |
| 1497 def do_chmod(fname): | 1490 def do_chmod(fname): |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1511 else: os.chmod(fname, stat.S_IMODE(st[stat.ST_MODE]|0200)) | 1504 else: os.chmod(fname, stat.S_IMODE(st[stat.ST_MODE]|0200)) |
| 1512 else: | 1505 else: |
| 1513 def do_chmod(fname): | 1506 def do_chmod(fname): |
| 1514 try: st = os.stat(fname) | 1507 try: st = os.stat(fname) |
| 1515 except OSError: pass | 1508 except OSError: pass |
| 1516 else: os.chmod(fname, stat.S_IMODE(st[stat.ST_MODE]&~0200)) | 1509 else: os.chmod(fname, stat.S_IMODE(st[stat.ST_MODE]&~0200)) |
| 1517 | 1510 |
| 1518 if os.path.isfile(top): | 1511 if os.path.isfile(top): |
| 1519 do_chmod(top) | 1512 do_chmod(top) |
| 1520 else: | 1513 else: |
| 1521 col = Collector(top) | 1514 do_chmod(top) |
| 1522 os.path.walk(top, col, None) | 1515 for dirname, dirnames, filenames in os.walk(top): |
| 1523 for d in col.entries: do_chmod(d) | 1516 for n in dirnames: |
| 1517 do_chmod(os.path.join(dirname, n)) |
| 1518 for n in filenames: |
| 1519 do_chmod(os.path.join(dirname, n)) |
| 1524 | 1520 |
| 1525 def executable(self, top, execute=1): | 1521 def executable(self, top, execute=1): |
| 1526 """Make the specified directory tree executable (execute == 1) | 1522 """Make the specified directory tree executable (execute == 1) |
| 1527 or not (execute == None). | 1523 or not (execute == None). |
| 1528 | 1524 |
| 1529 This method has no effect on Windows systems, which use a | 1525 This method has no effect on Windows systems, which use a |
| 1530 completely different mechanism to control file executability. | 1526 completely different mechanism to control file executability. |
| 1531 """ | 1527 """ |
| 1532 | 1528 |
| 1533 if sys.platform == 'win32': | 1529 if sys.platform == 'win32': |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1544 except OSError: pass | 1540 except OSError: pass |
| 1545 else: os.chmod(fname, stat.S_IMODE(st[stat.ST_MODE]&~stat.S_IEXE
C)) | 1541 else: os.chmod(fname, stat.S_IMODE(st[stat.ST_MODE]&~stat.S_IEXE
C)) |
| 1546 | 1542 |
| 1547 if os.path.isfile(top): | 1543 if os.path.isfile(top): |
| 1548 # If it's a file, that's easy, just chmod it. | 1544 # If it's a file, that's easy, just chmod it. |
| 1549 do_chmod(top) | 1545 do_chmod(top) |
| 1550 elif execute: | 1546 elif execute: |
| 1551 # It's a directory and we're trying to turn on execute | 1547 # It's a directory and we're trying to turn on execute |
| 1552 # permission, so it's also pretty easy, just chmod the | 1548 # permission, so it's also pretty easy, just chmod the |
| 1553 # directory and then chmod every entry on our walk down the | 1549 # directory and then chmod every entry on our walk down the |
| 1554 # tree. Because os.path.walk() is top-down, we'll enable | 1550 # tree. Because os.walk() is top-down, we'll enable |
| 1555 # execute permission on any directories that have it disabled | 1551 # execute permission on any directories that have it disabled |
| 1556 # before os.path.walk() tries to list their contents. | 1552 # before os.walk() tries to list their contents. |
| 1557 do_chmod(top) | 1553 do_chmod(top) |
| 1558 | 1554 |
| 1559 def chmod_entries(arg, dirname, names, do_chmod=do_chmod): | 1555 for dirname, dirnames, filenames in os.walk(top): |
| 1560 for n in names: | 1556 for n in dirnames: |
| 1561 do_chmod(os.path.join(dirname, n)) | 1557 do_chmod(os.path.join(dirname, n)) |
| 1562 | 1558 for n in filenames: |
| 1563 os.path.walk(top, chmod_entries, None) | 1559 do_chmod(os.path.join(dirname, n)) |
| 1564 else: | 1560 else: |
| 1565 # It's a directory and we're trying to turn off execute | 1561 # It's a directory and we're trying to turn off execute |
| 1566 # permission, which means we have to chmod the directories | 1562 # permission, which means we have to chmod the directories |
| 1567 # in the tree bottom-up, lest disabling execute permission from | 1563 # in the tree bottom-up, lest disabling execute permission from |
| 1568 # the top down get in the way of being able to get at lower | 1564 # the top down get in the way of being able to get at lower |
| 1569 # parts of the tree. But os.path.walk() visits things top | 1565 # parts of the tree. |
| 1570 # down, so we just use an object to collect a list of all | 1566 for dirname, dirnames, filenames in os.walk(top, topdown=False): |
| 1571 # of the entries in the tree, reverse the list, and then | 1567 for n in dirnames: |
| 1572 # chmod the reversed (bottom-up) list. | 1568 do_chmod(os.path.join(dirname, n)) |
| 1573 col = Collector(top) | 1569 for n in filenames: |
| 1574 os.path.walk(top, col, None) | 1570 do_chmod(os.path.join(dirname, n)) |
| 1575 col.entries.reverse() | 1571 |
| 1576 for d in col.entries: do_chmod(d) | 1572 do_chmod(top) |
| 1577 | 1573 |
| 1578 def write(self, file, content, mode = 'wb'): | 1574 def write(self, file, content, mode = 'wb'): |
| 1579 """Writes the specified content text (second argument) to the | 1575 """Writes the specified content text (second argument) to the |
| 1580 specified file name (first argument). The file name may be | 1576 specified file name (first argument). The file name may be |
| 1581 a list, in which case the elements are concatenated with the | 1577 a list, in which case the elements are concatenated with the |
| 1582 os.path.join() method. The file is created under the temporary | 1578 os.path.join() method. The file is created under the temporary |
| 1583 working directory. Any subdirectories in the path must already | 1579 working directory. Any subdirectories in the path must already |
| 1584 exist. The I/O mode for the file may be specified; it must | 1580 exist. The I/O mode for the file may be specified; it must |
| 1585 begin with a 'w'. The default is 'wb' (binary write). | 1581 begin with a 'w'. The default is 'wb' (binary write). |
| 1586 """ | 1582 """ |
| 1587 file = self.canonicalize(file) | 1583 file = self.canonicalize(file) |
| 1588 if mode[0] != 'w': | 1584 if mode[0] != 'w': |
| 1589 raise ValueError, "mode must begin with 'w'" | 1585 raise ValueError, "mode must begin with 'w'" |
| 1590 with open(file, mode) as f: | 1586 with open(file, mode) as f: |
| 1591 f.write(content) | 1587 f.write(content) |
| 1592 | 1588 |
| 1593 # Local Variables: | 1589 # Local Variables: |
| 1594 # tab-width:4 | 1590 # tab-width:4 |
| 1595 # indent-tabs-mode:nil | 1591 # indent-tabs-mode:nil |
| 1596 # End: | 1592 # End: |
| 1597 # vim: set expandtab tabstop=4 shiftwidth=4: | 1593 # vim: set expandtab tabstop=4 shiftwidth=4: |
| OLD | NEW |