Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(141)

Side by Side Diff: test/lib/TestCmd.py

Issue 1454433002: Python 3 compatibility Base URL: https://chromium.googlesource.com/external/gyp.git@master
Patch Set: Rebase with master (4ec6c4e3a94bd04a6da2858163d40b2429b8aad1) Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
207 # SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF 207 # SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF
208 # THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 208 # THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
209 # DAMAGE. 209 # DAMAGE.
210 # 210 #
211 # THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT 211 # THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
212 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 212 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
213 # PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, 213 # PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS,
214 # AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, 214 # AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
215 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 215 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
216 216
217 from __future__ import print_function
218
217 __author__ = "Steven Knight <knight at baldmt dot com>" 219 __author__ = "Steven Knight <knight at baldmt dot com>"
218 __revision__ = "TestCmd.py 0.37.D001 2010/01/11 16:55:50 knight" 220 __revision__ = "TestCmd.py 0.37.D001 2010/01/11 16:55:50 knight"
219 __version__ = "0.37" 221 __version__ = "0.37"
220 222
221 import errno 223 import errno
222 import os 224 import os
223 import os.path 225 import os.path
224 import re 226 import re
225 import shutil 227 import shutil
226 import stat 228 import stat
227 import string
228 import sys 229 import sys
229 import tempfile 230 import tempfile
230 import time 231 import time
231 import traceback 232 import traceback
232 import types 233 try:
233 import UserList 234 from UserList import UserList
235 except ImportError:
236 from collections import UserList
234 237
235 __all__ = [ 238 __all__ = [
236 'diff_re', 239 'diff_re',
237 'fail_test', 240 'fail_test',
238 'no_result', 241 'no_result',
239 'pass_test', 242 'pass_test',
240 'match_exact', 243 'match_exact',
241 'match_re', 244 'match_re',
242 'match_re_dotall', 245 'match_re_dotall',
243 'python_executable', 246 'python_executable',
244 'TestCmd' 247 'TestCmd'
245 ] 248 ]
246 249
247 try: 250 try:
248 import difflib 251 import difflib
249 except ImportError: 252 except ImportError:
250 __all__.append('simple_diff') 253 __all__.append('simple_diff')
251 254
252 def is_List(e): 255 def is_List(e):
253 return type(e) is types.ListType \ 256 return type(e) is list \
254 or isinstance(e, UserList.UserList) 257 or isinstance(e, UserList)
255 258
256 try: 259 try:
257 from UserString import UserString 260 from UserString import UserString
258 except ImportError: 261 except ImportError:
259 class UserString: 262 try:
260 pass 263 from collections import UserString
264 except ImportError:
265 class UserString:
266 pass
261 267
262 if hasattr(types, 'UnicodeType'): 268 try:
263 def is_String(e): 269 basestring = basestring
264 return type(e) is types.StringType \ 270 except NameError:
265 or type(e) is types.UnicodeType \ 271 basestring = str
266 or isinstance(e, UserString) 272
267 else: 273 def is_String(e):
268 def is_String(e): 274 return isinstance(e, basestring) \
269 return type(e) is types.StringType or isinstance(e, UserString) 275 or isinstance(e, UserString)
270 276
271 tempfile.template = 'testcmd.' 277 tempfile.template = 'testcmd.'
272 if os.name in ('posix', 'nt'): 278 if os.name in ('posix', 'nt'):
273 tempfile.template = 'testcmd.' + str(os.getpid()) + '.' 279 tempfile.template = 'testcmd.' + str(os.getpid()) + '.'
274 else: 280 else:
275 tempfile.template = 'testcmd.' 281 tempfile.template = 'testcmd.'
276 282
277 re_space = re.compile('\s') 283 re_space = re.compile('\s')
278 284
279 _Cleanup = [] 285 _Cleanup = []
280 286
281 _chain_to_exitfunc = None 287 _chain_to_exitfunc = None
282 288
283 def _clean(): 289 def _clean():
284 global _Cleanup 290 global _Cleanup
285 cleanlist = filter(None, _Cleanup) 291 for test in reversed(_Cleanup):
292 if test:
293 test.cleanup()
286 del _Cleanup[:] 294 del _Cleanup[:]
287 cleanlist.reverse()
288 for test in cleanlist:
289 test.cleanup()
290 if _chain_to_exitfunc: 295 if _chain_to_exitfunc:
291 _chain_to_exitfunc() 296 _chain_to_exitfunc()
292 297
293 try: 298 try:
294 import atexit 299 import atexit
295 except ImportError: 300 except ImportError:
296 # TODO(1.5): atexit requires python 2.0, so chain sys.exitfunc 301 # TODO(1.5): atexit requires python 2.0, so chain sys.exitfunc
297 try: 302 try:
298 _chain_to_exitfunc = sys.exitfunc 303 _chain_to_exitfunc = sys.exitfunc
299 except AttributeError: 304 except AttributeError:
300 pass 305 pass
301 sys.exitfunc = _clean 306 sys.exitfunc = _clean
302 else: 307 else:
303 atexit.register(_clean) 308 atexit.register(_clean)
304 309
305 try: 310 try:
306 zip 311 zip
307 except NameError: 312 except NameError:
308 def zip(*lists): 313 def zip(*lists):
309 result = [] 314 result = []
310 for i in xrange(min(map(len, lists))): 315 for i in range(min(map(len, lists))):
311 result.append(tuple(map(lambda l, i=i: l[i], lists))) 316 result.append(tuple(map(lambda l, i=i: l[i], lists)))
312 return result 317 return result
313 318
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): 319 def _caller(tblist, skip):
322 string = "" 320 string = ""
323 arr = [] 321 arr = []
324 for file, line, name, text in tblist: 322 for file, line, name, text in tblist:
325 if file[-10:] == "TestCmd.py": 323 if file[-10:] == "TestCmd.py":
326 break 324 break
327 arr = [(file, line, name, text)] + arr 325 arr = [(file, line, name, text)] + arr
328 atfrom = "at" 326 atfrom = "at"
329 for file, line, name, text in arr[skip:]: 327 for file, line, name, text in arr[skip:]:
330 if name in ("?", "<module>"): 328 if name in ("?", "<module>"):
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
403 return 401 return
404 if not function is None: 402 if not function is None:
405 function() 403 function()
406 sys.stderr.write("PASSED\n") 404 sys.stderr.write("PASSED\n")
407 sys.exit(0) 405 sys.exit(0)
408 406
409 def match_exact(lines = None, matches = None): 407 def match_exact(lines = None, matches = None):
410 """ 408 """
411 """ 409 """
412 if not is_List(lines): 410 if not is_List(lines):
413 lines = string.split(lines, "\n") 411 lines = lines.split("\n")
414 if not is_List(matches): 412 if not is_List(matches):
415 matches = string.split(matches, "\n") 413 matches = matches.split("\n")
416 if len(lines) != len(matches): 414 if len(lines) != len(matches):
417 return 415 return
418 for i in range(len(lines)): 416 for i in range(len(lines)):
419 if lines[i] != matches[i]: 417 if lines[i] != matches[i]:
420 return 418 return
421 return 1 419 return 1
422 420
423 def match_re(lines = None, res = None): 421 def match_re(lines = None, res = None):
424 """ 422 """
425 """ 423 """
426 if not is_List(lines): 424 if not is_List(lines):
427 lines = string.split(lines, "\n") 425 lines = lines.split("\n")
428 if not is_List(res): 426 if not is_List(res):
429 res = string.split(res, "\n") 427 res = res.split("\n")
430 if len(lines) != len(res): 428 if len(lines) != len(res):
431 return 429 return
432 for i in range(len(lines)): 430 for i in range(len(lines)):
433 s = "^" + res[i] + "$" 431 s = "^" + res[i] + "$"
434 try: 432 try:
435 expr = re.compile(s) 433 expr = re.compile(s)
436 except re.error, e: 434 except re.error as e:
437 msg = "Regular expression error in %s: %s" 435 msg = "Regular expression error in %s: %s"
438 raise re.error, msg % (repr(s), e[0]) 436 raise re.error(msg % (repr(s), e[0]))
439 if not expr.search(lines[i]): 437 if not expr.search(lines[i]):
440 return 438 return
441 return 1 439 return 1
442 440
443 def match_re_dotall(lines = None, res = None): 441 def match_re_dotall(lines = None, res = None):
444 """ 442 """
445 """ 443 """
446 if not type(lines) is type(""): 444 if not type(lines) is type(""):
447 lines = string.join(lines, "\n") 445 lines = "\n".join(lines)
448 if not type(res) is type(""): 446 if not type(res) is type(""):
449 res = string.join(res, "\n") 447 res = "\n".join(res)
450 s = "^" + res + "$" 448 s = "^" + res + "$"
451 try: 449 try:
452 expr = re.compile(s, re.DOTALL) 450 expr = re.compile(s, re.DOTALL)
453 except re.error, e: 451 except re.error as e:
454 msg = "Regular expression error in %s: %s" 452 msg = "Regular expression error in %s: %s"
455 raise re.error, msg % (repr(s), e[0]) 453 raise re.error(msg % (repr(s), e[0]))
456 if expr.match(lines): 454 if expr.match(lines):
457 return 1 455 return 1
458 456
459 try: 457 try:
460 import difflib 458 import difflib
461 except ImportError: 459 except ImportError:
462 pass 460 pass
463 else: 461 else:
464 def simple_diff(a, b, fromfile='', tofile='', 462 def simple_diff(a, b, fromfile='', tofile='',
465 fromfiledate='', tofiledate='', n=3, lineterm='\n'): 463 fromfiledate='', tofiledate='', n=3, lineterm='\n'):
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
499 diff = len(a) - len(b) 497 diff = len(a) - len(b)
500 if diff < 0: 498 if diff < 0:
501 a = a + ['']*(-diff) 499 a = a + ['']*(-diff)
502 elif diff > 0: 500 elif diff > 0:
503 b = b + ['']*diff 501 b = b + ['']*diff
504 i = 0 502 i = 0
505 for aline, bline in zip(a, b): 503 for aline, bline in zip(a, b):
506 s = "^" + aline + "$" 504 s = "^" + aline + "$"
507 try: 505 try:
508 expr = re.compile(s) 506 expr = re.compile(s)
509 except re.error, e: 507 except re.error as e:
510 msg = "Regular expression error in %s: %s" 508 msg = "Regular expression error in %s: %s"
511 raise re.error, msg % (repr(s), e[0]) 509 raise re.error(msg % (repr(s), e[0]))
512 if not expr.search(bline): 510 if not expr.search(bline):
513 result.append("%sc%s" % (i+1, i+1)) 511 result.append("%sc%s" % (i+1, i+1))
514 result.append('< ' + repr(a[i])) 512 result.append('< ' + repr(a[i]))
515 result.append('---') 513 result.append('---')
516 result.append('> ' + repr(b[i])) 514 result.append('> ' + repr(b[i]))
517 i = i+1 515 i = i+1
518 return result 516 return result
519 517
520 if os.name == 'java': 518 if os.name == 'java':
521 519
522 python_executable = os.path.join(sys.prefix, 'jython') 520 python_executable = os.path.join(sys.prefix, 'jython')
523 521
524 else: 522 else:
525 523
526 python_executable = sys.executable 524 python_executable = sys.executable
527 525
528 if sys.platform == 'win32': 526 if sys.platform == 'win32':
529 527
530 default_sleep_seconds = 2 528 default_sleep_seconds = 2
531 529
532 def where_is(file, path=None, pathext=None): 530 def where_is(file, path=None, pathext=None):
533 if path is None: 531 if path is None:
534 path = os.environ['PATH'] 532 path = os.environ['PATH']
535 if is_String(path): 533 if is_String(path):
536 path = string.split(path, os.pathsep) 534 path = path.split(os.pathsep)
537 if pathext is None: 535 if pathext is None:
538 pathext = os.environ['PATHEXT'] 536 pathext = os.environ['PATHEXT']
539 if is_String(pathext): 537 if is_String(pathext):
540 pathext = string.split(pathext, os.pathsep) 538 pathext = pathext.split(os.pathsep)
541 for ext in pathext: 539 for ext in pathext:
542 if string.lower(ext) == string.lower(file[-len(ext):]): 540 if ext.lower() == file[-len(ext):].lower():
543 pathext = [''] 541 pathext = ['']
544 break 542 break
545 for dir in path: 543 for dir in path:
546 f = os.path.join(dir, file) 544 f = os.path.join(dir, file)
547 for ext in pathext: 545 for ext in pathext:
548 fext = f + ext 546 fext = f + ext
549 if os.path.isfile(fext): 547 if os.path.isfile(fext):
550 return fext 548 return fext
551 return None 549 return None
552 550
553 else: 551 else:
554 552
555 def where_is(file, path=None, pathext=None): 553 def where_is(file, path=None, pathext=None):
556 if path is None: 554 if path is None:
557 path = os.environ['PATH'] 555 path = os.environ['PATH']
558 if is_String(path): 556 if is_String(path):
559 path = string.split(path, os.pathsep) 557 path = path.split(os.pathsep)
560 for dir in path: 558 for dir in path:
561 f = os.path.join(dir, file) 559 f = os.path.join(dir, file)
562 if os.path.isfile(f): 560 if os.path.isfile(f):
563 try: 561 try:
564 st = os.stat(f) 562 st = os.stat(f)
565 except OSError: 563 except OSError:
566 continue 564 continue
567 if stat.S_IMODE(st[stat.ST_MODE]) & 0111: 565 if stat.S_IMODE(st[stat.ST_MODE]) & 0o111:
568 return f 566 return f
569 return None 567 return None
570 568
571 default_sleep_seconds = 1 569 default_sleep_seconds = 1
572 570
573 571
574 572
575 try: 573 try:
576 import subprocess 574 import subprocess
577 except ImportError: 575 except ImportError:
578 # The subprocess module doesn't exist in this version of Python, 576 # The subprocess module doesn't exist in this version of Python,
579 # so we're going to cobble up something that looks just enough 577 # so we're going to cobble up something that looks just enough
580 # like its API for our purposes below. 578 # like its API for our purposes below.
581 import new 579 import new
582 580
583 subprocess = new.module('subprocess') 581 subprocess = new.module('subprocess')
584 582
585 subprocess.PIPE = 'PIPE' 583 subprocess.PIPE = 'PIPE'
586 subprocess.STDOUT = 'STDOUT' 584 subprocess.STDOUT = 'STDOUT'
587 subprocess.mswindows = (sys.platform == 'win32')
588 585
589 try: 586 try:
590 import popen2 587 import popen2
591 popen2.Popen3 588 popen2.Popen3
592 except AttributeError: 589 except AttributeError:
593 class Popen3: 590 class Popen3(object):
594 universal_newlines = 1 591 universal_newlines = 1
595 def __init__(self, command, **kw): 592 def __init__(self, command, **kw):
596 if sys.platform == 'win32' and command[0] == '"': 593 if sys.platform == 'win32' and command[0] == '"':
597 command = '"' + command + '"' 594 command = '"' + command + '"'
598 (stdin, stdout, stderr) = os.popen3(' ' + command) 595 (stdin, stdout, stderr) = os.popen3(' ' + command)
599 self.stdin = stdin 596 self.stdin = stdin
600 self.stdout = stdout 597 self.stdout = stdout
601 self.stderr = stderr 598 self.stderr = stderr
602 def close_output(self): 599 def close_output(self):
603 self.stdout.close() 600 self.stdout.close()
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
645 os.close(c2pwrite) 642 os.close(c2pwrite)
646 self.fromchild = os.fdopen(c2pread, 'r', bufsize) 643 self.fromchild = os.fdopen(c2pread, 'r', bufsize)
647 popen2._active.append(self) 644 popen2._active.append(self)
648 645
649 popen2.Popen4 = Popen4 646 popen2.Popen4 = Popen4
650 647
651 class Popen3(popen2.Popen3, popen2.Popen4): 648 class Popen3(popen2.Popen3, popen2.Popen4):
652 universal_newlines = 1 649 universal_newlines = 1
653 def __init__(self, command, **kw): 650 def __init__(self, command, **kw):
654 if kw.get('stderr') == 'STDOUT': 651 if kw.get('stderr') == 'STDOUT':
655 apply(popen2.Popen4.__init__, (self, command, 1)) 652 popen2.Popen4.__init__(self, command, 1)
656 else: 653 else:
657 apply(popen2.Popen3.__init__, (self, command, 1)) 654 popen2.Popen3.__init__(self, command, 1)
658 self.stdin = self.tochild 655 self.stdin = self.tochild
659 self.stdout = self.fromchild 656 self.stdout = self.fromchild
660 self.stderr = self.childerr 657 self.stderr = self.childerr
661 def wait(self, *args, **kw): 658 def wait(self, *args, **kw):
662 resultcode = apply(popen2.Popen3.wait, (self,)+args, kw) 659 resultcode = popen2.Popen3.wait(self, *args, **kw)
663 if os.WIFEXITED(resultcode): 660 if os.WIFEXITED(resultcode):
664 return os.WEXITSTATUS(resultcode) 661 return os.WEXITSTATUS(resultcode)
665 elif os.WIFSIGNALED(resultcode): 662 elif os.WIFSIGNALED(resultcode):
666 return os.WTERMSIG(resultcode) 663 return os.WTERMSIG(resultcode)
667 else: 664 else:
668 return None 665 return None
669 666
670 subprocess.Popen = Popen3 667 subprocess.Popen = Popen3
671 668
672 669
673 670
674 # From Josiah Carlson, 671 # From Josiah Carlson,
675 # ASPN : Python Cookbook : Module to allow Asynchronous subprocess use on Window s and Posix platforms 672 # ASPN : Python Cookbook : Module to allow Asynchronous subprocess use on Window s and Posix platforms
676 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/440554 673 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/440554
677 674
678 PIPE = subprocess.PIPE 675 PIPE = subprocess.PIPE
679 676
680 if subprocess.mswindows: 677 if sys.platform == 'win32':
681 from win32file import ReadFile, WriteFile 678 from win32file import ReadFile, WriteFile
682 from win32pipe import PeekNamedPipe 679 from win32pipe import PeekNamedPipe
683 import msvcrt 680 import msvcrt
684 else: 681 else:
685 import select 682 import select
686 import fcntl 683 import fcntl
687 684
688 try: fcntl.F_GETFL 685 try: fcntl.F_GETFL
689 except AttributeError: fcntl.F_GETFL = 3 686 except AttributeError: fcntl.F_GETFL = 3
690 687
(...skipping 14 matching lines...) Expand all
705 if maxsize is None: 702 if maxsize is None:
706 maxsize = 1024 703 maxsize = 1024
707 elif maxsize < 1: 704 elif maxsize < 1:
708 maxsize = 1 705 maxsize = 1
709 return getattr(self, which), maxsize 706 return getattr(self, which), maxsize
710 707
711 def _close(self, which): 708 def _close(self, which):
712 getattr(self, which).close() 709 getattr(self, which).close()
713 setattr(self, which, None) 710 setattr(self, which, None)
714 711
715 if subprocess.mswindows: 712 if sys.platform == 'win32':
716 def send(self, input): 713 def send(self, input):
717 if not self.stdin: 714 if not self.stdin:
718 return None 715 return None
719 716
720 try: 717 try:
721 x = msvcrt.get_osfhandle(self.stdin.fileno()) 718 x = msvcrt.get_osfhandle(self.stdin.fileno())
722 (errCode, written) = WriteFile(x, input) 719 (errCode, written) = WriteFile(x, input)
723 except ValueError: 720 except ValueError:
724 return self._close('stdin') 721 return self._close('stdin')
725 except (subprocess.pywintypes.error, Exception), why: 722 except (subprocess.pywintypes.error, Exception) as why:
726 if why[0] in (109, errno.ESHUTDOWN): 723 if why[0] in (109, errno.ESHUTDOWN):
727 return self._close('stdin') 724 return self._close('stdin')
728 raise 725 raise
729 726
730 return written 727 return written
731 728
732 def _recv(self, which, maxsize): 729 def _recv(self, which, maxsize):
733 conn, maxsize = self.get_conn_maxsize(which, maxsize) 730 conn, maxsize = self.get_conn_maxsize(which, maxsize)
734 if conn is None: 731 if conn is None:
735 return None 732 return None
736 733
737 try: 734 try:
738 x = msvcrt.get_osfhandle(conn.fileno()) 735 x = msvcrt.get_osfhandle(conn.fileno())
739 (read, nAvail, nMessage) = PeekNamedPipe(x, 0) 736 (read, nAvail, nMessage) = PeekNamedPipe(x, 0)
740 if maxsize < nAvail: 737 if maxsize < nAvail:
741 nAvail = maxsize 738 nAvail = maxsize
742 if nAvail > 0: 739 if nAvail > 0:
743 (errCode, read) = ReadFile(x, nAvail, None) 740 (errCode, read) = ReadFile(x, nAvail, None)
744 except ValueError: 741 except ValueError:
745 return self._close(which) 742 return self._close(which)
746 except (subprocess.pywintypes.error, Exception), why: 743 except (subprocess.pywintypes.error, Exception) as why:
747 if why[0] in (109, errno.ESHUTDOWN): 744 if why[0] in (109, errno.ESHUTDOWN):
748 return self._close(which) 745 return self._close(which)
749 raise 746 raise
750 747
751 #if self.universal_newlines: 748 #if self.universal_newlines:
752 # read = self._translate_newlines(read) 749 # read = self._translate_newlines(read)
753 return read 750 return read
754 751
755 else: 752 else:
756 def send(self, input): 753 def send(self, input):
757 if not self.stdin: 754 if not self.stdin:
758 return None 755 return None
759 756
760 if not select.select([], [self.stdin], [], 0)[1]: 757 if not select.select([], [self.stdin], [], 0)[1]:
761 return 0 758 return 0
762 759
763 try: 760 try:
764 written = os.write(self.stdin.fileno(), input) 761 written = os.write(self.stdin.fileno(), input)
765 except OSError, why: 762 except OSError as why:
766 if why[0] == errno.EPIPE: #broken pipe 763 if why[0] == errno.EPIPE: #broken pipe
767 return self._close('stdin') 764 return self._close('stdin')
768 raise 765 raise
769 766
770 return written 767 return written
771 768
772 def _recv(self, which, maxsize): 769 def _recv(self, which, maxsize):
773 conn, maxsize = self.get_conn_maxsize(which, maxsize) 770 conn, maxsize = self.get_conn_maxsize(which, maxsize)
774 if conn is None: 771 if conn is None:
775 return None 772 return None
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
824 # TODO(3.0: rewrite to use memoryview() 821 # TODO(3.0: rewrite to use memoryview()
825 def send_all(p, data): 822 def send_all(p, data):
826 while len(data): 823 while len(data):
827 sent = p.send(data) 824 sent = p.send(data)
828 if sent is None: 825 if sent is None:
829 raise Exception(disconnect_message) 826 raise Exception(disconnect_message)
830 data = buffer(data, sent) 827 data = buffer(data, sent)
831 828
832 829
833 830
834 try:
835 object
836 except NameError:
837 class object:
838 pass
839
840
841
842 class TestCmd(object): 831 class TestCmd(object):
843 """Class TestCmd 832 """Class TestCmd
844 """ 833 """
845 834
846 def __init__(self, description = None, 835 def __init__(self, description = None,
847 program = None, 836 program = None,
848 interpreter = None, 837 interpreter = None,
849 workdir = None, 838 workdir = None,
850 subdir = None, 839 subdir = None,
851 verbose = None, 840 verbose = None,
(...skipping 23 matching lines...) Expand all
875 try: 864 try:
876 difflib 865 difflib
877 except NameError: 866 except NameError:
878 pass 867 pass
879 else: 868 else:
880 self.diff_function = simple_diff 869 self.diff_function = simple_diff
881 #self.diff_function = difflib.context_diff 870 #self.diff_function = difflib.context_diff
882 #self.diff_function = difflib.unified_diff 871 #self.diff_function = difflib.unified_diff
883 self._dirlist = [] 872 self._dirlist = []
884 self._preserve = {'pass_test': 0, 'fail_test': 0, 'no_result': 0} 873 self._preserve = {'pass_test': 0, 'fail_test': 0, 'no_result': 0}
885 if os.environ.has_key('PRESERVE') and not os.environ['PRESERVE'] is '': 874 if 'PRESERVE' in os.environ and os.environ['PRESERVE'] is not '':
886 self._preserve['pass_test'] = os.environ['PRESERVE'] 875 self._preserve['pass_test'] = os.environ['PRESERVE']
887 self._preserve['fail_test'] = os.environ['PRESERVE'] 876 self._preserve['fail_test'] = os.environ['PRESERVE']
888 self._preserve['no_result'] = os.environ['PRESERVE'] 877 self._preserve['no_result'] = os.environ['PRESERVE']
889 else: 878 else:
890 try: 879 try:
891 self._preserve['pass_test'] = os.environ['PRESERVE_PASS'] 880 self._preserve['pass_test'] = os.environ['PRESERVE_PASS']
892 except KeyError: 881 except KeyError:
893 pass 882 pass
894 try: 883 try:
895 self._preserve['fail_test'] = os.environ['PRESERVE_FAIL'] 884 self._preserve['fail_test'] = os.environ['PRESERVE_FAIL']
(...skipping 24 matching lines...) Expand all
920 width = self.banner_width 909 width = self.banner_width
921 return s + self.banner_char * (width - len(s)) 910 return s + self.banner_char * (width - len(s))
922 911
923 if os.name == 'posix': 912 if os.name == 'posix':
924 913
925 def escape(self, arg): 914 def escape(self, arg):
926 "escape shell special characters" 915 "escape shell special characters"
927 slash = '\\' 916 slash = '\\'
928 special = '"$' 917 special = '"$'
929 918
930 arg = string.replace(arg, slash, slash+slash) 919 arg = arg.replace(slash, slash+slash)
931 for c in special: 920 for c in special:
932 arg = string.replace(arg, c, slash+c) 921 arg = arg.replace(c, slash+c)
933 922
934 if re_space.search(arg): 923 if re_space.search(arg):
935 arg = '"' + arg + '"' 924 arg = '"' + arg + '"'
936 return arg 925 return arg
937 926
938 else: 927 else:
939 928
940 # Windows does not allow special characters in file names 929 # Windows does not allow special characters in file names
941 # anyway, so no need for an escape function, we will just quote 930 # anyway, so no need for an escape function, we will just quote
942 # the arg. 931 # the arg.
943 def escape(self, arg): 932 def escape(self, arg):
944 if re_space.search(arg): 933 if re_space.search(arg):
945 arg = '"' + arg + '"' 934 arg = '"' + arg + '"'
946 return arg 935 return arg
947 936
948 def canonicalize(self, path): 937 def canonicalize(self, path):
949 if is_List(path): 938 if is_List(path):
950 path = apply(os.path.join, tuple(path)) 939 path = os.path.join(*path)
951 if not os.path.isabs(path): 940 if not os.path.isabs(path):
952 path = os.path.join(self.workdir, path) 941 path = os.path.join(self.workdir, path)
953 return path 942 return path
954 943
955 def chmod(self, path, mode): 944 def chmod(self, path, mode):
956 """Changes permissions on the specified file or directory 945 """Changes permissions on the specified file or directory
957 path name.""" 946 path name."""
958 path = self.canonicalize(path) 947 path = self.canonicalize(path)
959 os.chmod(path, mode) 948 os.chmod(path, mode)
960 949
(...skipping 13 matching lines...) Expand all
974 appropriate for the exit status. 963 appropriate for the exit status.
975 """ 964 """
976 if not self._dirlist: 965 if not self._dirlist:
977 return 966 return
978 os.chdir(self._cwd) 967 os.chdir(self._cwd)
979 self.workdir = None 968 self.workdir = None
980 if condition is None: 969 if condition is None:
981 condition = self.condition 970 condition = self.condition
982 if self._preserve[condition]: 971 if self._preserve[condition]:
983 for dir in self._dirlist: 972 for dir in self._dirlist:
984 print "Preserved directory", dir 973 print("Preserved directory", dir)
985 else: 974 else:
986 list = self._dirlist[:] 975 list = self._dirlist[:]
987 list.reverse() 976 list.reverse()
988 for dir in list: 977 for dir in list:
989 self.writable(dir, 1) 978 self.writable(dir, 1)
990 shutil.rmtree(dir, ignore_errors = 1) 979 shutil.rmtree(dir, ignore_errors = 1)
991 self._dirlist = [] 980 self._dirlist = []
992 981
993 try: 982 try:
994 global _Cleanup 983 global _Cleanup
(...skipping 13 matching lines...) Expand all
1008 interpreter = self.interpreter 997 interpreter = self.interpreter
1009 if not type(program) in [type([]), type(())]: 998 if not type(program) in [type([]), type(())]:
1010 program = [program] 999 program = [program]
1011 cmd = list(program) 1000 cmd = list(program)
1012 if interpreter: 1001 if interpreter:
1013 if not type(interpreter) in [type([]), type(())]: 1002 if not type(interpreter) in [type([]), type(())]:
1014 interpreter = [interpreter] 1003 interpreter = [interpreter]
1015 cmd = list(interpreter) + cmd 1004 cmd = list(interpreter) + cmd
1016 if arguments: 1005 if arguments:
1017 if type(arguments) == type(''): 1006 if type(arguments) == type(''):
1018 arguments = string.split(arguments) 1007 arguments = arguments.split()
1019 cmd.extend(arguments) 1008 cmd.extend(arguments)
1020 return cmd 1009 return cmd
1021 1010
1022 def description_set(self, description): 1011 def description_set(self, description):
1023 """Set the description of the functionality being tested. 1012 """Set the description of the functionality being tested.
1024 """ 1013 """
1025 self.description = description 1014 self.description = description
1026 1015
1027 try: 1016 try:
1028 difflib 1017 difflib
1029 except NameError: 1018 except NameError:
1030 def diff(self, a, b, name, *args, **kw): 1019 def diff(self, a, b, name, *args, **kw):
1031 print self.banner('Expected %s' % name) 1020 print(self.banner('Expected %s' % name))
1032 print a 1021 print(a)
1033 print self.banner('Actual %s' % name) 1022 print(self.banner('Actual %s' % name))
1034 print b 1023 print(b)
1035 else: 1024 else:
1036 def diff(self, a, b, name, *args, **kw): 1025 def diff(self, a, b, name, *args, **kw):
1037 print self.banner(name) 1026 print(self.banner(name))
1038 args = (a.splitlines(), b.splitlines()) + args 1027 args = (a.splitlines(), b.splitlines()) + args
1039 lines = apply(self.diff_function, args, kw) 1028 lines = self.diff_function(*args, **kw)
1040 for l in lines: 1029 for l in lines:
1041 print l 1030 print(l)
1042 1031
1043 def fail_test(self, condition = 1, function = None, skip = 0): 1032 def fail_test(self, condition = 1, function = None, skip = 0):
1044 """Cause the test to fail. 1033 """Cause the test to fail.
1045 """ 1034 """
1046 if not condition: 1035 if not condition:
1047 return 1036 return
1048 self.condition = 'fail_test' 1037 self.condition = 'fail_test'
1049 fail_test(self = self, 1038 fail_test(self = self,
1050 condition = condition, 1039 condition = condition,
1051 function = function, 1040 function = function,
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
1108 for cond in conditions: 1097 for cond in conditions:
1109 self._preserve[cond] = 1 1098 self._preserve[cond] = 1
1110 1099
1111 def program_set(self, program): 1100 def program_set(self, program):
1112 """Set the executable program or script to be tested. 1101 """Set the executable program or script to be tested.
1113 """ 1102 """
1114 if program and not os.path.isabs(program): 1103 if program and not os.path.isabs(program):
1115 program = os.path.join(self._cwd, program) 1104 program = os.path.join(self._cwd, program)
1116 self.program = program 1105 self.program = program
1117 1106
1118 def read(self, file, mode = 'rb'): 1107 def read(self, file, mode = 'r'):
1119 """Reads and returns the contents of the specified file name. 1108 """Reads and returns the contents of the specified file name.
1120 The file name may be a list, in which case the elements are 1109 The file name may be a list, in which case the elements are
1121 concatenated with the os.path.join() method. The file is 1110 concatenated with the os.path.join() method. The file is
1122 assumed to be under the temporary working directory unless it 1111 assumed to be under the temporary working directory unless it
1123 is an absolute path name. The I/O mode for the file may 1112 is an absolute path name. The I/O mode for the file may
1124 be specified; it must begin with an 'r'. The default is 1113 be specified; it must begin with an 'r'. The default is
1125 'rb' (binary read). 1114 'r' (string read).
1126 """ 1115 """
1127 file = self.canonicalize(file) 1116 file = self.canonicalize(file)
1128 if mode[0] != 'r': 1117 if mode[0] != 'r':
1129 raise ValueError, "mode must begin with 'r'" 1118 raise ValueError("mode must begin with 'r'")
1130 with open(file, mode) as f: 1119 with open(file, mode) as f:
1131 result = f.read() 1120 result = f.read()
1132 return result 1121 return result
1133 1122
1134 def rmdir(self, dir): 1123 def rmdir(self, dir):
1135 """Removes the specified dir name. 1124 """Removes the specified dir name.
1136 The dir name may be a list, in which case the elements are 1125 The dir name may be a list, in which case the elements are
1137 concatenated with the os.path.join() method. The dir is 1126 concatenated with the os.path.join() method. The dir is
1138 assumed to be under the temporary working directory unless it 1127 assumed to be under the temporary working directory unless it
1139 is an absolute path name. 1128 is an absolute path name.
1140 The dir must be empty. 1129 The dir must be empty.
1141 """ 1130 """
1142 dir = self.canonicalize(dir) 1131 dir = self.canonicalize(dir)
1143 os.rmdir(dir) 1132 os.rmdir(dir)
1144 1133
1145 def start(self, program = None, 1134 def start(self, program = None,
1146 interpreter = None, 1135 interpreter = None,
1147 arguments = None, 1136 arguments = None,
1148 universal_newlines = None, 1137 universal_newlines = None,
1149 **kw): 1138 **kw):
1150 """ 1139 """
1151 Starts a program or script for the test environment. 1140 Starts a program or script for the test environment.
1152 1141
1153 The specified program will have the original directory 1142 The specified program will have the original directory
1154 prepended unless it is enclosed in a [list]. 1143 prepended unless it is enclosed in a [list].
1155 """ 1144 """
1156 cmd = self.command_args(program, interpreter, arguments) 1145 cmd = self.command_args(program, interpreter, arguments)
1157 cmd_string = string.join(map(self.escape, cmd), ' ') 1146 cmd_string = ' '.join(map(self.escape, cmd))
1158 if self.verbose: 1147 if self.verbose:
1159 sys.stderr.write(cmd_string + "\n") 1148 sys.stderr.write(cmd_string + "\n")
1160 if universal_newlines is None: 1149 if universal_newlines is None:
1161 universal_newlines = self.universal_newlines 1150 universal_newlines = self.universal_newlines
1162 1151
1163 # On Windows, if we make stdin a pipe when we plan to send 1152 # On Windows, if we make stdin a pipe when we plan to send
1164 # no input, and the test program exits before 1153 # no input, and the test program exits before
1165 # Popen calls msvcrt.open_osfhandle, that call will fail. 1154 # Popen calls msvcrt.open_osfhandle, that call will fail.
1166 # So don't use a pipe for stdin if we don't need one. 1155 # So don't use a pipe for stdin if we don't need one.
1167 stdin = kw.get('stdin', None) 1156 stdin = kw.get('stdin', None)
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
1312 1301
1313 test.subdir('sub', ['sub', 'dir'], ['sub', 'dir', 'ectory']) 1302 test.subdir('sub', ['sub', 'dir'], ['sub', 'dir', 'ectory'])
1314 1303
1315 Returns the number of subdirectories actually created. 1304 Returns the number of subdirectories actually created.
1316 """ 1305 """
1317 count = 0 1306 count = 0
1318 for sub in subdirs: 1307 for sub in subdirs:
1319 if sub is None: 1308 if sub is None:
1320 continue 1309 continue
1321 if is_List(sub): 1310 if is_List(sub):
1322 sub = apply(os.path.join, tuple(sub)) 1311 sub = os.path.join(*sub)
1323 new = os.path.join(self.workdir, sub) 1312 new = os.path.join(self.workdir, sub)
1324 try: 1313 try:
1325 os.mkdir(new) 1314 os.mkdir(new)
1326 except OSError: 1315 except OSError:
1327 pass 1316 pass
1328 else: 1317 else:
1329 count = count + 1 1318 count = count + 1
1330 return count 1319 return count
1331 1320
1332 def symlink(self, target, link): 1321 def symlink(self, target, link):
(...skipping 27 matching lines...) Expand all
1360 try: 1349 try:
1361 os.chdir(path) 1350 os.chdir(path)
1362 path = os.getcwd() 1351 path = os.getcwd()
1363 finally: 1352 finally:
1364 os.chdir(cwd) 1353 os.chdir(cwd)
1365 1354
1366 # Uppercase the drive letter since the case of drive 1355 # Uppercase the drive letter since the case of drive
1367 # letters is pretty much random on win32: 1356 # letters is pretty much random on win32:
1368 drive,rest = os.path.splitdrive(path) 1357 drive,rest = os.path.splitdrive(path)
1369 if drive: 1358 if drive:
1370 path = string.upper(drive) + rest 1359 path = drive.upper() + rest
1371 1360
1372 # 1361 #
1373 self._dirlist.append(path) 1362 self._dirlist.append(path)
1374 global _Cleanup 1363 global _Cleanup
1375 try: 1364 try:
1376 _Cleanup.index(self) 1365 _Cleanup.index(self)
1377 except ValueError: 1366 except ValueError:
1378 _Cleanup.append(self) 1367 _Cleanup.append(self)
1379 1368
1380 return path 1369 return path
(...skipping 21 matching lines...) Expand all
1402 1391
1403 def verbose_set(self, verbose): 1392 def verbose_set(self, verbose):
1404 """Set the verbose level. 1393 """Set the verbose level.
1405 """ 1394 """
1406 self.verbose = verbose 1395 self.verbose = verbose
1407 1396
1408 def where_is(self, file, path=None, pathext=None): 1397 def where_is(self, file, path=None, pathext=None):
1409 """Find an executable file. 1398 """Find an executable file.
1410 """ 1399 """
1411 if is_List(file): 1400 if is_List(file):
1412 file = apply(os.path.join, tuple(file)) 1401 file = os.path.join(*file)
1413 if not os.path.isabs(file): 1402 if not os.path.isabs(file):
1414 file = where_is(file, path, pathext) 1403 file = where_is(file, path, pathext)
1415 return file 1404 return file
1416 1405
1417 def workdir_set(self, path): 1406 def workdir_set(self, path):
1418 """Creates a temporary working directory with the specified 1407 """Creates a temporary working directory with the specified
1419 path name. If the path is a null string (''), a unique 1408 path name. If the path is a null string (''), a unique
1420 directory name is created. 1409 directory name is created.
1421 """ 1410 """
1422 if (path != None): 1411 if (path != None):
1423 if path == '': 1412 if path == '':
1424 path = None 1413 path = None
1425 path = self.tempdir(path) 1414 path = self.tempdir(path)
1426 self.workdir = path 1415 self.workdir = path
1427 1416
1428 def workpath(self, *args): 1417 def workpath(self, *args):
1429 """Returns the absolute path name to a subdirectory or file 1418 """Returns the absolute path name to a subdirectory or file
1430 within the current temporary working directory. Concatenates 1419 within the current temporary working directory. Concatenates
1431 the temporary working directory name with the specified 1420 the temporary working directory name with the specified
1432 arguments using the os.path.join() method. 1421 arguments using the os.path.join() method.
1433 """ 1422 """
1434 return apply(os.path.join, (self.workdir,) + tuple(args)) 1423 return os.path.join(self.workdir, *args)
1435 1424
1436 def readable(self, top, read=1): 1425 def readable(self, top, read=1):
1437 """Make the specified directory tree readable (read == 1) 1426 """Make the specified directory tree readable (read == 1)
1438 or not (read == None). 1427 or not (read == None).
1439 1428
1440 This method has no effect on Windows systems, which use a 1429 This method has no effect on Windows systems, which use a
1441 completely different mechanism to control file readability. 1430 completely different mechanism to control file readability.
1442 """ 1431 """
1443 1432
1444 if sys.platform == 'win32': 1433 if sys.platform == 'win32':
(...skipping 10 matching lines...) Expand all
1455 except OSError: pass 1444 except OSError: pass
1456 else: os.chmod(fname, stat.S_IMODE(st[stat.ST_MODE]&~stat.S_IREA D)) 1445 else: os.chmod(fname, stat.S_IMODE(st[stat.ST_MODE]&~stat.S_IREA D))
1457 1446
1458 if os.path.isfile(top): 1447 if os.path.isfile(top):
1459 # If it's a file, that's easy, just chmod it. 1448 # If it's a file, that's easy, just chmod it.
1460 do_chmod(top) 1449 do_chmod(top)
1461 elif read: 1450 elif read:
1462 # It's a directory and we're trying to turn on read 1451 # It's a directory and we're trying to turn on read
1463 # permission, so it's also pretty easy, just chmod the 1452 # permission, so it's also pretty easy, just chmod the
1464 # directory and then chmod every entry on our walk down the 1453 # directory and then chmod every entry on our walk down the
1465 # tree. Because os.path.walk() is top-down, we'll enable 1454 # tree. Because os.walk() is top-down, we'll enable
1466 # read permission on any directories that have it disabled 1455 # read permission on any directories that have it disabled
1467 # before os.path.walk() tries to list their contents. 1456 # before os.walk() tries to list their contents.
1468 do_chmod(top) 1457 do_chmod(top)
1469 1458
1470 def chmod_entries(arg, dirname, names, do_chmod=do_chmod): 1459 for dirname, dirnames, filenames in os.walk(top):
1471 for n in names: 1460 for n in dirnames:
1472 do_chmod(os.path.join(dirname, n)) 1461 do_chmod(os.path.join(dirname, n))
1473 1462 for n in filenames:
1474 os.path.walk(top, chmod_entries, None) 1463 do_chmod(os.path.join(dirname, n))
1475 else: 1464 else:
1476 # It's a directory and we're trying to turn off read 1465 # It's a directory and we're trying to turn off read
1477 # permission, which means we have to chmod the directoreis 1466 # permission, which means we have to chmod the directoreis
1478 # in the tree bottom-up, lest disabling read permission from 1467 # 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 1468 # 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 1469 # parts of the tree.
1481 # down, so we just use an object to collect a list of all 1470 for dirname, dirnames, filenames in os.walk(top, topdown=False):
1482 # of the entries in the tree, reverse the list, and then 1471 for n in dirnames:
1483 # chmod the reversed (bottom-up) list. 1472 do_chmod(os.path.join(dirname, n))
1484 col = Collector(top) 1473 for n in filenames:
1485 os.path.walk(top, col, None) 1474 do_chmod(os.path.join(dirname, n))
1486 col.entries.reverse() 1475
1487 for d in col.entries: do_chmod(d) 1476 do_chmod(top)
1488 1477
1489 def writable(self, top, write=1): 1478 def writable(self, top, write=1):
1490 """Make the specified directory tree writable (write == 1) 1479 """Make the specified directory tree writable (write == 1)
1491 or not (write == None). 1480 or not (write == None).
1492 """ 1481 """
1493 1482
1494 if sys.platform == 'win32': 1483 if sys.platform == 'win32':
1495 1484
1496 if write: 1485 if write:
1497 def do_chmod(fname): 1486 def do_chmod(fname):
1498 try: os.chmod(fname, stat.S_IWRITE) 1487 try: os.chmod(fname, stat.S_IWRITE)
1499 except OSError: pass 1488 except OSError: pass
1500 else: 1489 else:
1501 def do_chmod(fname): 1490 def do_chmod(fname):
1502 try: os.chmod(fname, stat.S_IREAD) 1491 try: os.chmod(fname, stat.S_IREAD)
1503 except OSError: pass 1492 except OSError: pass
1504 1493
1505 else: 1494 else:
1506 1495
1507 if write: 1496 if write:
1508 def do_chmod(fname): 1497 def do_chmod(fname):
1509 try: st = os.stat(fname) 1498 try: st = os.stat(fname)
1510 except OSError: pass 1499 except OSError: pass
1511 else: os.chmod(fname, stat.S_IMODE(st[stat.ST_MODE]|0200)) 1500 else: os.chmod(fname, stat.S_IMODE(st[stat.ST_MODE]|0o200))
1512 else: 1501 else:
1513 def do_chmod(fname): 1502 def do_chmod(fname):
1514 try: st = os.stat(fname) 1503 try: st = os.stat(fname)
1515 except OSError: pass 1504 except OSError: pass
1516 else: os.chmod(fname, stat.S_IMODE(st[stat.ST_MODE]&~0200)) 1505 else: os.chmod(fname, stat.S_IMODE(st[stat.ST_MODE]&~0o200))
1517 1506
1518 if os.path.isfile(top): 1507 if os.path.isfile(top):
1519 do_chmod(top) 1508 do_chmod(top)
1520 else: 1509 else:
1521 col = Collector(top) 1510 do_chmod(top)
1522 os.path.walk(top, col, None) 1511 for dirname, dirnames, filenames in os.walk(top):
1523 for d in col.entries: do_chmod(d) 1512 for n in dirnames:
1513 do_chmod(os.path.join(dirname, n))
1514 for n in filenames:
1515 do_chmod(os.path.join(dirname, n))
1524 1516
1525 def executable(self, top, execute=1): 1517 def executable(self, top, execute=1):
1526 """Make the specified directory tree executable (execute == 1) 1518 """Make the specified directory tree executable (execute == 1)
1527 or not (execute == None). 1519 or not (execute == None).
1528 1520
1529 This method has no effect on Windows systems, which use a 1521 This method has no effect on Windows systems, which use a
1530 completely different mechanism to control file executability. 1522 completely different mechanism to control file executability.
1531 """ 1523 """
1532 1524
1533 if sys.platform == 'win32': 1525 if sys.platform == 'win32':
(...skipping 10 matching lines...) Expand all
1544 except OSError: pass 1536 except OSError: pass
1545 else: os.chmod(fname, stat.S_IMODE(st[stat.ST_MODE]&~stat.S_IEXE C)) 1537 else: os.chmod(fname, stat.S_IMODE(st[stat.ST_MODE]&~stat.S_IEXE C))
1546 1538
1547 if os.path.isfile(top): 1539 if os.path.isfile(top):
1548 # If it's a file, that's easy, just chmod it. 1540 # If it's a file, that's easy, just chmod it.
1549 do_chmod(top) 1541 do_chmod(top)
1550 elif execute: 1542 elif execute:
1551 # It's a directory and we're trying to turn on execute 1543 # It's a directory and we're trying to turn on execute
1552 # permission, so it's also pretty easy, just chmod the 1544 # permission, so it's also pretty easy, just chmod the
1553 # directory and then chmod every entry on our walk down the 1545 # directory and then chmod every entry on our walk down the
1554 # tree. Because os.path.walk() is top-down, we'll enable 1546 # tree. Because os.walk() is top-down, we'll enable
1555 # execute permission on any directories that have it disabled 1547 # execute permission on any directories that have it disabled
1556 # before os.path.walk() tries to list their contents. 1548 # before os.walk() tries to list their contents.
1557 do_chmod(top) 1549 do_chmod(top)
1558 1550
1559 def chmod_entries(arg, dirname, names, do_chmod=do_chmod): 1551 for dirname, dirnames, filenames in os.walk(top):
1560 for n in names: 1552 for n in dirnames:
1561 do_chmod(os.path.join(dirname, n)) 1553 do_chmod(os.path.join(dirname, n))
1562 1554 for n in filenames:
1563 os.path.walk(top, chmod_entries, None) 1555 do_chmod(os.path.join(dirname, n))
1564 else: 1556 else:
1565 # It's a directory and we're trying to turn off execute 1557 # It's a directory and we're trying to turn off execute
1566 # permission, which means we have to chmod the directories 1558 # permission, which means we have to chmod the directories
1567 # in the tree bottom-up, lest disabling execute permission from 1559 # 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 1560 # 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 1561 # parts of the tree.
1570 # down, so we just use an object to collect a list of all 1562 for dirname, dirnames, filenames in os.walk(top, topdown=False):
1571 # of the entries in the tree, reverse the list, and then 1563 for n in dirnames:
1572 # chmod the reversed (bottom-up) list. 1564 do_chmod(os.path.join(dirname, n))
1573 col = Collector(top) 1565 for n in filenames:
1574 os.path.walk(top, col, None) 1566 do_chmod(os.path.join(dirname, n))
1575 col.entries.reverse()
1576 for d in col.entries: do_chmod(d)
1577 1567
1578 def write(self, file, content, mode = 'wb'): 1568 do_chmod(top)
1569
1570 def write(self, file, content, mode = 'w'):
1579 """Writes the specified content text (second argument) to the 1571 """Writes the specified content text (second argument) to the
1580 specified file name (first argument). The file name may be 1572 specified file name (first argument). The file name may be
1581 a list, in which case the elements are concatenated with the 1573 a list, in which case the elements are concatenated with the
1582 os.path.join() method. The file is created under the temporary 1574 os.path.join() method. The file is created under the temporary
1583 working directory. Any subdirectories in the path must already 1575 working directory. Any subdirectories in the path must already
1584 exist. The I/O mode for the file may be specified; it must 1576 exist. The I/O mode for the file may be specified; it must
1585 begin with a 'w'. The default is 'wb' (binary write). 1577 begin with a 'w'. The default is 'w' (string write).
1586 """ 1578 """
1587 file = self.canonicalize(file) 1579 file = self.canonicalize(file)
1588 if mode[0] != 'w': 1580 if mode[0] != 'w':
1589 raise ValueError, "mode must begin with 'w'" 1581 raise ValueError("mode must begin with 'w'")
1590 with open(file, mode) as f: 1582 with open(file, mode) as f:
1591 f.write(content) 1583 f.write(content)
1592 1584
1593 # Local Variables: 1585 # Local Variables:
1594 # tab-width:4 1586 # tab-width:4
1595 # indent-tabs-mode:nil 1587 # indent-tabs-mode:nil
1596 # End: 1588 # End:
1597 # vim: set expandtab tabstop=4 shiftwidth=4: 1589 # vim: set expandtab tabstop=4 shiftwidth=4:
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698