Example #1
0
def _rmtree_unsafe(path, onerror):
    try:
        if testos.path.islink(path):
            # symlinks to directories are forbidden, see bug #1669
            raise OSError("Cannot call rmtree on a symbolic link")
    except OSError:
        onerror(testos.path.islink, path, sys.exc_info())
        # can't continue even if onerror hook returns
        return
    names = []
    try:
        names = testos.listdir(path)
    except OSError:
        onerror(testos.listdir, path, sys.exc_info())
    for name in names:
        fullname = testos.path.join(path, name)
        try:
            mode = testos.lstat(fullname).st_mode
        except OSError:
            mode = 0
        if stat.S_ISDIR(mode):
            _rmtree_unsafe(fullname, onerror)
        else:
            try:
                testos.unlink(fullname)
            except OSError:
                onerror(testos.unlink, fullname, sys.exc_info())
    try:
        testos.rmdir(path)
    except OSError:
        onerror(testos.rmdir, path, sys.exc_info())
Example #2
0
 def release(self):
     if not self.is_locked():
         raise NotLocked("%s is not locked" % self.path)
     elif not testos.path.exists(self.unique_name):
         raise NotMyLock("%s is locked, but not by me" % self.path)
     testos.unlink(self.unique_name)
     testos.rmdir(self.lock_file)
Example #3
0
def rmtree(path, ignore_errors=False, onerror=None):
    """Recursively delete a directory tree.

    If ignore_errors is set, errors are ignored; otherwise, if onerror
    is set, it is called to handle the error with arguments (func,
    path, exc_info) where func is platform and implementation dependent;
    path is the argument to that function that caused it to fail; and
    exc_info is a tuple returned by sys.exc_info().  If ignore_errors
    is false and onerror is None, an exception is raised.

    """
    if ignore_errors:

        def onerror(*args):
            pass
    elif onerror is None:

        def onerror(*args):
            raise

    if _use_fd_functions:
        # While the unsafe rmtree works fine on bytes, the fd based does not.
        if isinstance(path, bytes):
            path = testos.fsdecode(path)
        # Note: To guard against symlink races, we use the standard
        # lstat()/open()/fstat() trick.
        try:
            orig_st = testos.lstat(path)
        except Exception:
            onerror(testos.lstat, path, sys.exc_info())
            return
        try:
            fd = testos.open(path, testos.O_RDONLY)
        except Exception:
            onerror(testos.lstat, path, sys.exc_info())
            return
        try:
            if testos.path.samestat(orig_st, testos.fstat(fd)):
                _rmtree_safe_fd(fd, path, onerror)
                try:
                    testos.rmdir(path)
                except OSError:
                    onerror(testos.rmdir, path, sys.exc_info())
            else:
                try:
                    # symlinks to directories are forbidden, see bug #1669
                    raise OSError("Cannot call rmtree on a symbolic link")
                except OSError:
                    onerror(testos.path.islink, path, sys.exc_info())
        finally:
            testos.close(fd)
    else:
        return _rmtree_unsafe(path, onerror)
Example #4
0
def rmtree(path, ignore_errors=False, onerror=None):
    """Recursively delete a directory tree.

    If ignore_errors is set, errors are ignored; otherwise, if onerror
    is set, it is called to handle the error with arguments (func,
    path, exc_info) where func is os.listdir, os.remove, or os.rmdir;
    path is the argument to that function that caused it to fail; and
    exc_info is a tuple returned by sys.exc_info().  If ignore_errors
    is false and onerror is None, an exception is raised.

    """
    if ignore_errors:
        def onerror(*args):
            pass
    elif onerror is None:
        def onerror(*args):
            raise
    try:
        if testos.path.islink(path):
            # symlinks to directories are forbidden, see bug #1669
            raise OSError("Cannot call rmtree on a symbolic link")
    except OSError:
        onerror(testos.path.islink, path, sys.exc_info())
        # can't continue even if onerror hook returns
        return
    names = []
    try:
        names = testos.listdir(path)
    except testos.error:
        onerror(testos.listdir, path, sys.exc_info())
    for name in names:
        fullname = testos.path.join(path, name)
        try:
            mode = testos.lstat(fullname).st_mode
        except testos.error:
            mode = 0
        if stat.S_ISDIR(mode):
            rmtree(fullname, ignore_errors, onerror)
        else:
            try:
                testos.remove(fullname)
            except testos.error:
                onerror(testos.remove, fullname, sys.exc_info())
    try:
        testos.rmdir(path)
    except testos.error:
        onerror(testos.rmdir, path, sys.exc_info())
Example #5
0
def _rmtree_safe_fd(topfd, path, onerror):
    names = []
    try:
        names = testos.listdir(topfd)
    except OSError as err:
        err.filename = path
        onerror(testos.listdir, path, sys.exc_info())
    for name in names:
        fullname = testos.path.join(path, name)
        try:
            orig_st = testos.stat(name, dir_fd=topfd, follow_symlinks=False)
            mode = orig_st.st_mode
        except OSError:
            mode = 0
        if stat.S_ISDIR(mode):
            try:
                dirfd = testos.open(name, testos.O_RDONLY, dir_fd=topfd)
            except OSError:
                onerror(testos.open, fullname, sys.exc_info())
            else:
                try:
                    if testos.path.samestat(orig_st, testos.fstat(dirfd)):
                        _rmtree_safe_fd(dirfd, fullname, onerror)
                        try:
                            testos.rmdir(name, dir_fd=topfd)
                        except OSError:
                            onerror(testos.rmdir, fullname, sys.exc_info())
                    else:
                        try:
                            # This can only happen if someone replaces
                            # a directory with a symlink after the call to
                            # stat.S_ISDIR above.
                            raise OSError("Cannot call rmtree on a symbolic "
                                          "link")
                        except OSError:
                            onerror(testos.path.islink, fullname,
                                    sys.exc_info())
                finally:
                    testos.close(dirfd)
        else:
            try:
                testos.unlink(name, dir_fd=topfd)
            except OSError:
                onerror(testos.unlink, fullname, sys.exc_info())
Example #6
0
def unpack(src_dir, dst_dir):
    '''Move everything under `src_dir` to `dst_dir`, and delete the former.'''
    for dirpath, dirnames, filenames in testos.walk(src_dir):
        subdir = testos.path.relpath(dirpath, src_dir)
        for f in filenames:
            src = testos.path.join(dirpath, f)
            dst = testos.path.join(dst_dir, subdir, f)
            testos.renames(src, dst)
        for n, d in reversed(list(enumerate(dirnames))):
            src = testos.path.join(dirpath, d)
            dst = testos.path.join(dst_dir, subdir, d)
            if not testos.path.exists(dst):
                # Directory does not exist in destination,
                # rename it and prune it from os.walk list.
                testos.renames(src, dst)
                del dirnames[n]
    # Cleanup.
    for dirpath, dirnames, filenames in testos.walk(src_dir, topdown=True):
        assert not filenames
        testos.rmdir(dirpath)
Example #7
0
 def install_as_egg(self, destination_eggdir):
     '''Install wheel as an egg directory.'''
     with zipfile.ZipFile(self.filename) as zf:
         dist_basename = '%s-%s' % (self.project_name, self.version)
         dist_info = '%s.dist-info' % dist_basename
         dist_data = '%s.data' % dist_basename
         def get_metadata(name):
             with zf.open('%s/%s' % (dist_info, name)) as fp:
                 value = fp.read().decode('utf-8') if PY3 else fp.read()
                 return email.parser.Parser().parsestr(value)
         wheel_metadata = get_metadata('WHEEL')
         dist_metadata = get_metadata('METADATA')
         # Check wheel format version is supported.
         wheel_version = parse_version(wheel_metadata.get('Wheel-Version'))
         if not parse_version('1.0') <= wheel_version < parse_version('2.0dev0'):
             raise ValueError('unsupported wheel format version: %s' % wheel_version)
         # Extract to target directory.
         testos.mkdir(destination_eggdir)
         zf.extractall(destination_eggdir)
         # Convert metadata.
         dist_info = testos.path.join(destination_eggdir, dist_info)
         dist = Distribution.from_location(
             destination_eggdir, dist_info,
             metadata=PathMetadata(destination_eggdir, dist_info)
         )
         # Note: we need to evaluate and strip markers now,
         # as we can't easily convert back from the syntax:
         # foobar; "linux" in sys_platform and extra == 'test'
         def raw_req(req):
             req.marker = None
             return str(req)
         install_requires = list(sorted(map(raw_req, dist.requires())))
         extras_require = {
             extra: list(sorted(
                 req
                 for req in map(raw_req, dist.requires((extra,)))
                 if req not in install_requires
             ))
             for extra in dist.extras
         }
         egg_info = testos.path.join(destination_eggdir, 'EGG-INFO')
         testos.rename(dist_info, egg_info)
         testos.rename(testos.path.join(egg_info, 'METADATA'),
                       testos.path.join(egg_info, 'PKG-INFO'))
         setup_dist = SetuptoolsDistribution(attrs=dict(
             install_requires=install_requires,
             extras_require=extras_require,
         ))
         write_requirements(setup_dist.get_command_obj('egg_info'),
                            None, testos.path.join(egg_info, 'requires.txt'))
         # Move data entries to their correct location.
         dist_data = testos.path.join(destination_eggdir, dist_data)
         dist_data_scripts = testos.path.join(dist_data, 'scripts')
         if testos.path.exists(dist_data_scripts):
             egg_info_scripts = testos.path.join(destination_eggdir,
                                             'EGG-INFO', 'scripts')
             testos.mkdir(egg_info_scripts)
             for entry in testos.listdir(dist_data_scripts):
                 # Remove bytecode, as it's not properly handled
                 # during easy_install scripts install phase.
                 if entry.endswith('.pyc'):
                     testos.unlink(testos.path.join(dist_data_scripts, entry))
                 else:
                     testos.rename(testos.path.join(dist_data_scripts, entry),
                                   testos.path.join(egg_info_scripts, entry))
             testos.rmdir(dist_data_scripts)
         for subdir in filter(testos.path.exists, (
             testos.path.join(dist_data, d)
             for d in ('data', 'headers', 'purelib', 'platlib')
         )):
             unpack(subdir, destination_eggdir)
         if testos.path.exists(dist_data):
             testos.rmdir(dist_data)
         # Fix namespace packages.
         namespace_packages = testos.path.join(egg_info, 'namespace_packages.txt')
         if testos.path.exists(namespace_packages):
             with open(namespace_packages) as fp:
                 namespace_packages = fp.read().split()
             for mod in namespace_packages:
                 mod_dir = testos.path.join(destination_eggdir, *mod.split('.'))
                 mod_init = testos.path.join(mod_dir, '__init__.py')
                 if testos.path.exists(mod_dir) and not testos.path.exists(mod_init):
                     with open(mod_init, 'w') as fp:
                         fp.write(NAMESPACE_PACKAGE_INIT)
Example #8
0
 def break_lock(self):
     if testos.path.exists(self.lock_file):
         for name in testos.listdir(self.lock_file):
             testos.unlink(testos.path.join(self.lock_file, name))
         testos.rmdir(self.lock_file)