def mkdir(self, path) -> str: fpath = self.join(self.namespace_id, path) with self._api(): parent = self.dirname(fpath) if os.path.isfile(parent) or os.path.isfile(fpath): raise ex.CloudFileExistsError() if not os.path.exists(fpath): os.mkdir(fpath) return self._fpath_to_oid(fpath)
def __exit__(self, ty, exception, tb): if isinstance(exception, FileNotFoundError): raise ex.CloudFileNotFoundError if isinstance(exception, FileExistsError): raise ex.CloudFileExistsError if isinstance(exception, IsADirectoryError): raise ex.CloudFileExistsError("Is a dir: %s" % exception) if isinstance(exception, NotADirectoryError): raise ex.CloudFileExistsError("Not a dir: %s" % exception) if isinstance(exception, OSError): if exception.errno == errno.ENOTEMPTY: raise ex.CloudFileExistsError("Dir not empty: %s" % exception) if exception.errno == errno.ENOTDIR: raise ex.CloudFileExistsError("Not a dir: %s" % exception) if exception.errno == errno.ENOSPC: raise ex.CloudOutOfSpaceError("no space: %s" % exception) if exception.errno == errno.ENAMETOOLONG: raise ex.CloudFileNameError("Invalid name: %s" % exception) raise
def smart_rename(self, side, oid, new_path) -> str: """smartsync aware rename""" # oid MUST exist on the specified side # then, if target exists on same side, renaming on that side will fail in the rename # check if target exists only on the other side, and raise the FileExists here if so other = other_side(side) other_side_new_path = self.translate(other, new_path) if self.providers[other].exists_path(other_side_new_path): other_side_adverb = "remotely" if other_side == REMOTE else "locally" raise ex.CloudFileExistsError( "Rename target %s already exists %s as %s" % (new_path, other_side_adverb, other_side_new_path)) return self.providers[side].rename(oid, new_path)
def rename(self, oid, path) -> str: fpath = self.join(self.namespace_id, path) with self._api(): path_from = self._oid_to_fpath(oid) if not os.path.exists(path_from): raise ex.CloudFileNotFoundError parent = self.dirname(fpath) if not os.path.exists(parent): raise ex.CloudFileNotFoundError(parent) if not os.path.isdir(parent): raise ex.CloudFileExistsError(fpath) if not self.paths_match(path_from, fpath, for_display=True): from_dir = os.path.isdir(path_from) to_dir = os.path.isdir(fpath) has_contents = False if os.path.exists(fpath): if to_dir: has_contents = self._folder_path_has_contents(fpath) if (not to_dir or to_dir != from_dir or (to_dir and has_contents)): if not self.paths_match(path_from, fpath): raise ex.CloudFileExistsError(fpath) try: assert os.path.exists(path_from) assert os.path.exists(parent) log.info("rename %s -> %s", path_from, fpath) os.rename(path_from, fpath) except FileExistsError: if not has_contents and is_windows() and to_dir: # win32 doesn't allow this, so force it tmpname = fpath + os.urandom(16).hex() os.rename(fpath, tmpname) os.rename(path_from, fpath) self._rmdirs.append(tmpname) else: raise return self._fpath_to_oid(fpath)
def delete(self, oid): with self._api(): path = self._oid_to_fpath(oid) if os.path.isdir(path): log.debug("delete dir %s", path) if self._folder_oid_has_contents(oid): raise ex.CloudFileExistsError( "Cannot delete non-empty folder %s:%s" % (oid, path)) os.rmdir(path) elif os.path.exists(path): log.debug("delete file %s", path) os.unlink(path) else: log.debug("delete ??? %s", path)
def create(self, path, file_like, metadata=None) -> OInfo: fpath = self.join(self.namespace_id, path) with self._api(): parent = self.dirname(fpath) if os.path.exists(fpath) or (os.path.exists(parent) and not os.path.isdir(parent)): raise ex.CloudFileExistsError() with open(fpath, "wb") as dest: try: shutil.copyfileobj(file_like, dest) except Exception: if os.path.exists(fpath): dest.close() os.unlink(fpath) raise log.debug("create ok %s", fpath) self._clear_hash_cache(fpath) return self.__info_path(path, fpath)
def upload(self, oid, file_like, metadata=None) -> OInfo: with self._api(): fpath = self._oid_to_fpath(oid) if os.path.isdir(fpath): raise ex.CloudFileExistsError() if not os.path.exists(fpath): raise ex.CloudFileNotFoundError(oid) tmpdir = tempfile.gettempdir() tmp_file = os.path.join(tmpdir, "tmp." + os.urandom(16).hex()) with open(tmp_file, "wb") as f: shutil.copyfileobj(file_like, f) try: with open(tmp_file, "rb") as src, open(fpath, "wb") as dest: shutil.copyfileobj(src, dest) finally: try: os.unlink(tmp_file) except Exception: log.debug("cannot remove temp %s", tmp_file) self._clear_hash_cache(fpath) return self.info_oid(oid)