def add_parent(self, path, parent_dir): _log.info(f"add_parent: {path} -> {parent_dir}") _CheckPath(path) _CheckPath(parent_dir) with self._lock: targetPath = join(parent_dir, basename(path)) idsFromPath = self._itemsFromPath(targetPath) # don't allow violation of our requirement to keep filename unique inside new directory if targetPath in idsFromPath: raise FileExists(targetPath) parentDirItem = idsFromPath.get(parent_dir) if parentDirItem is None: raise ResourceNotFound(parent_dir) if parentDirItem["mimeType"] != _folderMimeType: raise DirectoryExpected(parent_dir) sourceItem = self._itemFromPath(path) if sourceItem is None: raise ResourceNotFound(path) self.drive.files().update( fileId=sourceItem["id"], addParents=parentDirItem["id"], body={}).execute(num_retries=self.retryCount)
def listdir(self, path: str) -> List[str]: """Get a list of the resource names in a directory. This method will return a list of the resources in a directory. A *resource* is a file, directory, or one of the other types defined in `~fs.enums.ResourceType`. Arguments: path (str): A path to a directory on the filesystem Returns: list: list of names, relative to ``path``. Raises: fs.errors.DirectoryExpected: If ``path`` is not a directory. fs.errors.ResourceNotFound: If ``path`` does not exist. """ if self._get_type(path) != ResourceType.directory: raise DirectoryExpected(path) _, entries = self._get_container(path) full_path = self._make_full_path(path) prefix = full_path[1:] # drop leading slash prefix += "/" if prefix else "" return [(entry.get("subdir") or entry["name"])[len(prefix):] for entry in entries]
def listdir(self, path: str) -> List[str]: path = self.validatepath(path) info = self.getinfo(path) if not info.is_dir: raise DirectoryExpected(path) path_obj, resource = self._get_file_at_path(path) local_files = [str(filename) for filename in resource.keys()] return local_files
def opendir(self, path: str) -> FATDirectoryEntry: """Get a filesystem object for a sub-directory. :param path: str: Path to a directory on the filesystem. """ dir_entry = self._get_dir_entry(path) if not dir_entry.is_directory(): raise DirectoryExpected(path) return dir_entry
def scandir(self, path, namespaces=None, page=None): _log.info(f'scandir({path}, {namespaces}, {page})') path = self.validatepath(path) with self._lock: metadata = self._itemFromPath(path) if metadata is None: raise ResourceNotFound(path=path) if metadata['mimeType'] != _folderMimeType: raise DirectoryExpected(path=path) children = self._childrenById(metadata['id']) return _GenerateChildren(children, page)
def opendir(self, path: str, factory=None) -> SubFS: """Get a filesystem object for a sub-directory. :param path: str: Path to a directory on the filesystem. """ factory = factory or self.subfs_class or SubFS dir_entry = self._get_dir_entry(path) if not dir_entry.is_directory(): raise DirectoryExpected(path) return factory(self, path)
def removedir(self, path): _CheckPath(path) with self._lock: info(f"removedir: {path}") metadata = self._itemFromPath(path) if metadata is None: raise ResourceNotFound(path=path) if metadata["mimeType"] != _folderMimeType: raise DirectoryExpected(path=path) children = self._childrenById(metadata["id"]) if len(children) > 0: raise DirectoryNotEmpty(path=path) self.drive.files().delete(fileId=metadata["id"]).execute()
def scandir(self, path, namespaces=None, page=None): _CheckPath(path) with self._lock: _log.info(f"scandir: {path}, {namespaces}, {page}") metadata = self._itemFromPath(path) if metadata is None: raise ResourceNotFound(path=path) if metadata["mimeType"] != _folderMimeType: raise DirectoryExpected(path=path) children = self._childrenById(metadata["id"]) return self._generateChildren(children, page)
def listdir(self, path: str): """List contents of given directory entry. :param path: Path to directory on filesystem """ dir_entry = self._get_dir_entry(path) try: dirs, files, _ = dir_entry.get_entries() except PyFATException as e: if e.errno == errno.ENOTDIR: raise DirectoryExpected(path) raise e return [str(e) for e in dirs+files]
def scandir(self, path, namespaces=None, page=None): _CheckPath(path) with self._lock: info(f"scandir: {path}, {namespaces}, {page}") metadata = self._itemFromPath(path) if metadata is None: raise ResourceNotFound(path=path) if metadata["mimeType"] != _folderMimeType: raise DirectoryExpected(path=path) children = self._childrenById(metadata["id"]) if page is not None: return (self._infoFromMetadata(x) for x in children[page[0]:page[1]]) return (self._infoFromMetadata(x) for x in children)
async def create_file(self, src_file: UploadFile, src_link: str, dst_path: str): """ Upload file directly or through url """ # Check that dst_path are valid and pointing to a folder with suppress_fs_exceptions(): if not self.home.isdir(dst_path): raise DirectoryExpected(dst_path) if src_file is not None: if src_file.content_type not in ALLOWED_CONTENT_TYPES: raise HTTPException( status_code=HTTP_400_BAD_REQUEST, detail=f'Content type {src_file.content_type} not allowed') path = fs.path.join(dst_path, src_file.filename) with suppress_fs_exceptions(): self.home.create(path, wipe=False) self.home.writebytes(path, await src_file.read()) return JSONResponse(path) if src_link is not None: # Request file by url with suppress_requests_exceptions(): src_file = requests.get(src_link, stream=True) # Check content type if src_file.headers.get( 'content-type') not in ALLOWED_CONTENT_TYPES: raise HTTPException( status_code=HTTP_400_BAD_REQUEST, detail= f'Content type {src_file.headers.get("content-type")} not allowed' ) # Get file name from url name = fs.path.basename(src_link) # Make destination path path = fs.path.join(dst_path, name) # Create file with suppress_fs_exceptions(): if self.home.isfile(path): raise DestinationExists(path) self.home.create(path, wipe=False) self.home.upload(path, src_file.raw) return JSONResponse(path) # If src_file and src_link are both None raise HTTP_400_BAD_REQUEST return HTTPException(status_code=HTTP_400_BAD_REQUEST, detail='Source not provided')
def makedir(self, path, permissions=None, recreate=False): parentDir = dirname(path) itemRequest = self.client.item(path=parentDir) try: item = itemRequest.get() except OneDriveError as e: raise ResourceNotFound(path=parentDir, exc=e) if item.folder is None: raise DirectoryExpected(path=parentDir) newItem = Item() newItem.name = basename(path) newItem.folder = Folder() itemRequest.children.add(entity=newItem) # don't need to close this filesystem so we return the non-closing version return SubFS(self, path)
def removedir(self, path): _log.info(f'removedir({path})') path = self.validatepath(path) if path == '/': raise RemoveRootError() with self._lock: metadata = self._itemFromPath(path) if metadata is None: raise ResourceNotFound(path=path) if metadata['mimeType'] != _folderMimeType: raise DirectoryExpected(path=path) children = self._childrenById(metadata['id']) if len(children) > 0: raise DirectoryNotEmpty(path=path) self._drive.files().delete( fileId=metadata['id'], **self._file_kwargs, ).execute(num_retries=self.retryCount)
def makedir(self, path, permissions=None, recreate=False): parentMetadata = self._itemFromPath(dirname(path)) if parentMetadata is None: raise DirectoryExpected(path=path) childMetadata = self._childByName(parentMetadata["id"], basename(path)) if childMetadata is not None: if recreate is False: raise DirectoryExists(path=path) else: return SubFS(self, path) newMetadata = { "name": basename(path), "parents": [parentMetadata["id"]], "mimeType": _folderMimeType } newMetadataId = self.drive.files().create(body=newMetadata, fields="id").execute() return SubFS(self, path)
def removetree(self, dir_path: str): """Recursively remove the contents of a directory. :param dir_path: ``str``: Path to a directory on the filesystem. """ dir_entry = self._get_dir_entry(dir_path) if not dir_entry.is_directory(): raise DirectoryExpected(dir_path) dirs, files, _ = dir_entry.get_entries() for f in files: self._remove(dir_entry, f) for d in dirs: self.removetree(posixpath.join(dir_path, str(d))) return self.removedir(dir_path)
def scandir(self, path, namespaces=None, page=None): itemRequest = self.client.item(path=path) try: item = itemRequest.get() except OneDriveError as e: raise ResourceNotFound(path=path, exc=e) if item.folder is None: raise DirectoryExpected(path=path) childrenRequest = itemRequest.children.request() children = childrenRequest.get() result = (self._itemInfo(x) for x in children) while hasattr(children, "_next_page_link"): childrenRequest = childrenRequest.get_next_page_request(children, self.client) children = childrenRequest.get() result = chain(result, (self._itemInfo(x) for x in children)) return result
def removedir(self, path): _CheckPath(path) with self._lock: # need to get the item id for this path response = self.session.get(_PathUrl(path, "")) if response.status_code == 404: raise ResourceNotFound(path) itemData = response.json() if "folder" not in itemData: raise DirectoryExpected(path) response = self.session.get(_PathUrl(path, ":/children")) response.raise_for_status() childrenData = response.json() if len(childrenData["value"]) > 0: raise DirectoryNotEmpty(path) itemId = itemData[ "id"] # let JSON parsing exceptions propagate for now response = self.session.delete(_ItemUrl(itemId, "")) assert response.status_code == 204, itemId # this is according to the spec
def scandir(self, path, namespaces=None, page=None): _CheckPath(path) with self._lock: response = self.session.get(_PathUrl( path, "")) # assumes path is the full path, starting with "/" if response.status_code == 404: raise ResourceNotFound(path=path) if "folder" not in response.json(): debug(f"{response.json()}") raise DirectoryExpected(path=path) response = self.session.get( _PathUrl(path, ":/children" )) # assumes path is the full path, starting with "/" if response.status_code == 404: raise ResourceNotFound(path=path) parsedResult = response.json() assert "@odata.context" in parsedResult if page is not None: return (self._itemInfo(x) for x in parsedResult["value"][page[0]:page[1]]) return (self._itemInfo(x) for x in parsedResult["value"])
def removedir(self, path: str): """Remove empty directories from the filesystem. :param path: `str`: Directory to remove """ dir_entry = self._get_dir_entry(path) try: base = dir_entry.get_parent_dir() except PyFATException as e: if e.errno == errno.ENOENT: # Don't remove root directory raise RemoveRootError(path) raise e # Verify if the directory is empty try: if not dir_entry.is_empty(): raise DirectoryNotEmpty(path) except PyFATException as e: if e.errno == errno.ENOTDIR: raise DirectoryExpected(path) self._remove(base, dir_entry)
def removedir(self, path): metadata = self._itemFromPath(path) if metadata is None: raise DirectoryExpected(path=path) self.drive.files().delete(fileId=metadata["id"]).execute()
def removedir(self, path): itemRequest = self.client.item(path=path) if itemRequest.get().folder is None: raise DirectoryExpected(path=path) itemRequest.delete()