Index: Lib/trace.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/trace.py,v retrieving revision 1.10 diff -c -r1.10 trace.py *** Lib/trace.py 27 Jun 2003 19:22:11 -0000 1.10 --- Lib/trace.py 7 Jul 2003 01:42:35 -0000 *************** *** 80,86 **** -r, --report Generate a report from a counts file; do not execute any code. `--file' must specify the results file to read, which must have been created in a previous run ! with `--count --file=FILE'. Modifiers: -f, --file= File to accumulate counts over several runs. --- 80,91 ---- -r, --report Generate a report from a counts file; do not execute any code. `--file' must specify the results file to read, which must have been created in a previous run ! with `--count --file=FILE'. If --coverdir is not ! specified, the .cover files will be written into the ! directory that the modules were in when the report was ! generated. Whether or not --coverdir is specified, ! --report will always create the cover file directory if ! necessary. Modifiers: -f, --file= File to accumulate counts over several runs. *************** *** 184,189 **** --- 189,244 ---- filename, ext = os.path.splitext(base) return filename + # The following function is copied from the fileutil module from the pyutil + # project: + # http://cvs.sf.net/cgi-bin/viewcvs.cgi/pyutil/pyutil_new/pyutil/fileutil.py?rev=HEAD&content-type=text/vnd.viewcvs-markup + # We use this function instead of os.makedirs() so that we don't get a + # spurious exception when someone else creates the directory at the same + # moment we do. (For example, another thread or process that is also running + # trace.) + def make_dirs(dirname, mode=0777, strictmode=False): + """ + A threadsafe and idempotent version of os.makedirs(). If the dir already + exists, do nothing and return without raising an exception. If this call + creates the dir, return without raising an exception. If there is an + error that prevents creation or if the directory gets deleted after + make_dirs() creates it and before make_dirs() checks that it exists, raise + an exception. + + @param strictmode if true, then make_dirs() will raise an exception if the + directory doesn't have the desired mode. For example, if the + directory already exists, and has a different mode than the one + specified by the mode parameter, then if strictmode is true, + make_dirs() will raise an exception, else it will ignore the + discrepancy. + """ + tx = None + try: + os.makedirs(dirname, mode) + except OSError, x: + tx = x + + if not os.path.isdir(dirname): + if tx: + raise tx + raise exceptions.IOError, "unknown error prevented creation of directory, or deleted the directory immediately after creation: %s" % dirname # careful not to construct an IOError with a 2-tuple, as that has a special meaning... + + tx = None + if hasattr(os, 'chmod'): + try: + os.chmod(dirname, mode) + except OSError, x: + tx = x + + if strictmode: + if hasattr(os, 'stat'): + s = os.stat(dirname) + resmode = stat.S_IMODE(s.st_mode) + if resmode != mode: + if tx: + raise tx + raise exceptions.IOError, "unknown error prevented setting correct mode of directory, or changed mode of the directory immediately after creation. dirname: %s, mode: %04o, resmode: %04o" % (dirname, mode, resmode,) # careful not to construct an IOError with a 2-tuple, as that has a special meaning... + class CoverageResults: def __init__(self, counts=None, calledfuncs=None, infile=None, outfile=None): *************** *** 252,265 **** if filename.endswith(".pyc") or filename.endswith(".pyo"): filename = filename[:-1] ! if coverdir is None: ! dir = os.path.dirname(os.path.abspath(filename)) ! modulename = modname(filename) ! else: dir = coverdir - if not os.path.exists(dir): - os.makedirs(dir) modulename = fullmodname(filename) # If desired, get a list of the line numbers which represent # executable content (returned as a dict for better lookup speed) --- 306,319 ---- if filename.endswith(".pyc") or filename.endswith(".pyo"): filename = filename[:-1] ! if coverdir is not None: dir = coverdir modulename = fullmodname(filename) + else: + dir = os.path.dirname(os.path.abspath(filename)) + modulename = modname(filename) + + make_dirs(dir) # If desired, get a list of the line numbers which represent # executable content (returned as a dict for better lookup speed)