Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
file_util.py236 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=1,67    preserve_times=1,68    update=0,69    link=None,70    verbose=1,71    dry_run=0,72):73    """Copy a file 'src' to 'dst'.  If 'dst' is a directory, then 'src' is74    copied there with the same name; otherwise, it must be a filename.  (If75    the file exists, it will be ruthlessly clobbered.)  If 'preserve_mode'76    is true (the default), the file's mode (type and permission bits, or77    whatever is analogous on the current platform) is copied.  If78    'preserve_times' is true (the default), the last-modified and79    last-access times are copied as well.  If 'update' is true, 'src' will80    only be copied if 'dst' does not exist, or if 'dst' does exist but is81    older than 'src'.82 83    'link' allows you to make hard links (os.link) or symbolic links84    (os.symlink) instead of copying: set it to "hard" or "sym"; if it is85    None (the default), files are copied.  Don't set 'link' on systems that86    don't support it: 'copy_file()' doesn't check if hard or symbolic87    linking is available. If hardlink fails, falls back to88    _copy_file_contents().89 90    Under Mac OS, uses the native file copy function in macostools; on91    other systems, uses '_copy_file_contents()' to copy file contents.92 93    Return a tuple (dest_name, copied): 'dest_name' is the actual name of94    the output file, and 'copied' is true if the file was copied (or would95    have been copied, if 'dry_run' true).96    """97    # XXX if the destination file already exists, we clobber it if98    # copying, but blow up if linking.  Hmmm.  And I don't know what99    # macostools.copyfile() does.  Should definitely be consistent, and100    # should probably blow up if destination exists and we would be101    # changing it (ie. it's not already a hard/soft link to src OR102    # (not update) and (src newer than dst).103 104    from distutils._modified import newer105    from stat import S_IMODE, ST_ATIME, ST_MODE, ST_MTIME106 107    if not os.path.isfile(src):108        raise DistutilsFileError(109            "can't copy '%s': doesn't exist or not a regular file" % src110        )111 112    if os.path.isdir(dst):113        dir = dst114        dst = os.path.join(dst, os.path.basename(src))115    else:116        dir = os.path.dirname(dst)117 118    if update and not newer(src, dst):119        if verbose >= 1:120            log.debug("not copying %s (output up-to-date)", src)121        return (dst, 0)122 123    try:124        action = _copy_action[link]125    except KeyError:126        raise ValueError("invalid value '%s' for 'link' argument" % link)127 128    if verbose >= 1:129        if os.path.basename(dst) == os.path.basename(src):130            log.info("%s %s -> %s", action, src, dir)131        else:132            log.info("%s %s -> %s", action, src, dst)133 134    if dry_run:135        return (dst, 1)136 137    # If linking (hard or symbolic), use the appropriate system call138    # (Unix only, of course, but that's the caller's responsibility)139    elif link == 'hard':140        if not (os.path.exists(dst) and os.path.samefile(src, dst)):141            try:142                os.link(src, dst)143                return (dst, 1)144            except OSError:145                # If hard linking fails, fall back on copying file146                # (some special filesystems don't support hard linking147                #  even under Unix, see issue #8876).148                pass149    elif link == 'sym':150        if not (os.path.exists(dst) and os.path.samefile(src, dst)):151            os.symlink(src, dst)152            return (dst, 1)153 154    # Otherwise (non-Mac, not linking), copy the file contents and155    # (optionally) copy the times and mode.156    _copy_file_contents(src, dst)157    if preserve_mode or preserve_times:158        st = os.stat(src)159 160        # According to David Ascher <da@ski.org>, utime() should be done161        # before chmod() (at least under NT).162        if preserve_times:163            os.utime(dst, (st[ST_ATIME], st[ST_MTIME]))164        if preserve_mode:165            os.chmod(dst, S_IMODE(st[ST_MODE]))166 167    return (dst, 1)168 169 170# XXX I suspect this is Unix-specific -- need porting help!171def move_file(src, dst, verbose=1, dry_run=0):  # noqa: C901172    """Move a file 'src' to 'dst'.  If 'dst' is a directory, the file will173    be moved into it with the same name; otherwise, 'src' is just renamed174    to 'dst'.  Return the new full name of the file.175 176    Handles cross-device moves on Unix using 'copy_file()'.  What about177    other systems???178    """179    import errno180    from os.path import basename, dirname, exists, isdir, isfile181 182    if verbose >= 1:183        log.info("moving %s -> %s", src, dst)184 185    if dry_run:186        return dst187 188    if not isfile(src):189        raise DistutilsFileError("can't move '%s': not a regular file" % src)190 191    if isdir(dst):192        dst = os.path.join(dst, basename(src))193    elif exists(dst):194        raise DistutilsFileError(195            f"can't move '{src}': destination '{dst}' already exists"196        )197 198    if not isdir(dirname(dst)):199        raise DistutilsFileError(200            f"can't move '{src}': destination '{dst}' not a valid path"201        )202 203    copy_it = False204    try:205        os.rename(src, dst)206    except OSError as e:207        (num, msg) = e.args208        if num == errno.EXDEV:209            copy_it = True210        else:211            raise DistutilsFileError(f"couldn't move '{src}' to '{dst}': {msg}")212 213    if copy_it:214        copy_file(src, dst, verbose=verbose)215        try:216            os.unlink(src)217        except OSError as e:218            (num, msg) = e.args219            try:220                os.unlink(dst)221            except OSError:222                pass223            raise DistutilsFileError(224                f"couldn't move '{src}' to '{dst}' by copy/delete: "225                f"delete '{src}' failed: {msg}"226            )227    return dst228 229 230def write_file(filename, contents):231    """Create a file with the specified name and write 'contents' (a232    sequence of strings without line terminators) to it.233    """234    with open(filename, 'w', encoding='utf-8') as f:235        f.writelines(line + '\n' for line in contents)236 
codekingpro/portable-devtools · Team Ai