Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
file_util.py229 linesDownload Raw Back to _distutils
1"""distutils.file_util2 3Utility functions for operating on single files.4"""5 6import os7 8from ._log import log9from .errors import DistutilsFileError10 11# for generating verbose output in 'copy_file()'12_copy_action = {None: 'copying', 'hard': 'hard linking', 'sym': 'symbolically linking'}13 14 15def _copy_file_contents(src, dst, buffer_size=16 * 1024):  # noqa: C90116    """Copy the file 'src' to 'dst'; both must be filenames.  Any error17    opening either file, reading from 'src', or writing to 'dst', raises18    DistutilsFileError.  Data is read/written in chunks of 'buffer_size'19    bytes (default 16k).  No attempt is made to handle anything apart from20    regular files.21    """22    # Stolen from shutil module in the standard library, but with23    # custom error-handling added.24    fsrc = None25    fdst = None26    try:27        try:28            fsrc = open(src, 'rb')29        except OSError as e:30            raise DistutilsFileError(f"could not open '{src}': {e.strerror}")31 32        if os.path.exists(dst):33            try:34                os.unlink(dst)35            except OSError as e:36                raise DistutilsFileError(f"could not delete '{dst}': {e.strerror}")37 38        try:39            fdst = open(dst, 'wb')40        except OSError as e:41            raise DistutilsFileError(f"could not create '{dst}': {e.strerror}")42 43        while True:44            try:45                buf = fsrc.read(buffer_size)46            except OSError as e:47                raise DistutilsFileError(f"could not read from '{src}': {e.strerror}")48 49            if not buf:50                break51 52            try:53                fdst.write(buf)54            except OSError as e:55                raise DistutilsFileError(f"could not write to '{dst}': {e.strerror}")56    finally:57        if fdst:58            fdst.close()59        if fsrc:60            fsrc.close()61 62 63def copy_file(  # noqa: C90164    src,65    dst,66    preserve_mode=True,67    preserve_times=True,68    update=False,69    link=None,70    verbose=True,71):72    """Copy a file 'src' to 'dst'.  If 'dst' is a directory, then 'src' is73    copied there with the same name; otherwise, it must be a filename.  (If74    the file exists, it will be ruthlessly clobbered.)  If 'preserve_mode'75    is true (the default), the file's mode (type and permission bits, or76    whatever is analogous on the current platform) is copied.  If77    'preserve_times' is true (the default), the last-modified and78    last-access times are copied as well.  If 'update' is true, 'src' will79    only be copied if 'dst' does not exist, or if 'dst' does exist but is80    older than 'src'.81 82    'link' allows you to make hard links (os.link) or symbolic links83    (os.symlink) instead of copying: set it to "hard" or "sym"; if it is84    None (the default), files are copied.  Don't set 'link' on systems that85    don't support it: 'copy_file()' doesn't check if hard or symbolic86    linking is available. If hardlink fails, falls back to87    _copy_file_contents().88 89    Under Mac OS, uses the native file copy function in macostools; on90    other systems, uses '_copy_file_contents()' to copy file contents.91 92    Return a tuple (dest_name, copied): 'dest_name' is the actual name of93    the output file, and 'copied' is true if the file was copied.94    """95    # XXX if the destination file already exists, we clobber it if96    # copying, but blow up if linking.  Hmmm.  And I don't know what97    # macostools.copyfile() does.  Should definitely be consistent, and98    # should probably blow up if destination exists and we would be99    # changing it (ie. it's not already a hard/soft link to src OR100    # (not update) and (src newer than dst).101 102    from distutils._modified import newer103    from stat import S_IMODE, ST_ATIME, ST_MODE, ST_MTIME104 105    if not os.path.isfile(src):106        raise DistutilsFileError(107            f"can't copy '{src}': doesn't exist or not a regular file"108        )109 110    if os.path.isdir(dst):111        dir = dst112        dst = os.path.join(dst, os.path.basename(src))113    else:114        dir = os.path.dirname(dst)115 116    if update and not newer(src, dst):117        if verbose >= 1:118            log.debug("not copying %s (output up-to-date)", src)119        return (dst, False)120 121    try:122        action = _copy_action[link]123    except KeyError:124        raise ValueError(f"invalid value '{link}' for 'link' argument")125 126    if verbose >= 1:127        if os.path.basename(dst) == os.path.basename(src):128            log.info("%s %s -> %s", action, src, dir)129        else:130            log.info("%s %s -> %s", action, src, dst)131 132    # If linking (hard or symbolic), use the appropriate system call133    # (Unix only, of course, but that's the caller's responsibility)134    if link == 'hard':135        if not (os.path.exists(dst) and os.path.samefile(src, dst)):136            try:137                os.link(src, dst)138            except OSError:139                # If hard linking fails, fall back on copying file140                # (some special filesystems don't support hard linking141                #  even under Unix, see issue #8876).142                pass143            else:144                return (dst, True)145    elif link == 'sym':146        if not (os.path.exists(dst) and os.path.samefile(src, dst)):147            os.symlink(src, dst)148            return (dst, True)149 150    # Otherwise (non-Mac, not linking), copy the file contents and151    # (optionally) copy the times and mode.152    _copy_file_contents(src, dst)153    if preserve_mode or preserve_times:154        st = os.stat(src)155 156        # According to David Ascher <da@ski.org>, utime() should be done157        # before chmod() (at least under NT).158        if preserve_times:159            os.utime(dst, (st[ST_ATIME], st[ST_MTIME]))160        if preserve_mode:161            os.chmod(dst, S_IMODE(st[ST_MODE]))162 163    return (dst, True)164 165 166# XXX I suspect this is Unix-specific -- need porting help!167def move_file(src, dst, verbose=True):  # noqa: C901168    """Move a file 'src' to 'dst'.  If 'dst' is a directory, the file will169    be moved into it with the same name; otherwise, 'src' is just renamed170    to 'dst'.  Return the new full name of the file.171 172    Handles cross-device moves on Unix using 'copy_file()'.  What about173    other systems???174    """175    import errno176    from os.path import basename, dirname, exists, isdir, isfile177 178    if verbose >= 1:179        log.info("moving %s -> %s", src, dst)180 181    if not isfile(src):182        raise DistutilsFileError(f"can't move '{src}': not a regular file")183 184    if isdir(dst):185        dst = os.path.join(dst, basename(src))186    elif exists(dst):187        raise DistutilsFileError(188            f"can't move '{src}': destination '{dst}' already exists"189        )190 191    if not isdir(dirname(dst)):192        raise DistutilsFileError(193            f"can't move '{src}': destination '{dst}' not a valid path"194        )195 196    copy_it = False197    try:198        os.rename(src, dst)199    except OSError as e:200        (num, msg) = e.args201        if num == errno.EXDEV:202            copy_it = True203        else:204            raise DistutilsFileError(f"couldn't move '{src}' to '{dst}': {msg}")205 206    if copy_it:207        copy_file(src, dst, verbose=verbose)208        try:209            os.unlink(src)210        except OSError as e:211            (num, msg) = e.args212            try:213                os.unlink(dst)214            except OSError:215                pass216            raise DistutilsFileError(217                f"couldn't move '{src}' to '{dst}' by copy/delete: "218                f"delete '{src}' failed: {msg}"219            )220    return dst221 222 223def write_file(filename, contents):224    """Create a file with the specified name and write 'contents' (a225    sequence of strings without line terminators) to it.226    """227    with open(filename, 'w', encoding='utf-8') as f:228        f.writelines(line + '\n' for line in contents)229 
codekingpro/portable-devtools · Team Ai