diff --git a/readmeai/preprocessor/directory_cleaner.py b/readmeai/preprocessor/directory_cleaner.py index c2b7e061..6faf2d34 100644 --- a/readmeai/preprocessor/directory_cleaner.py +++ b/readmeai/preprocessor/directory_cleaner.py @@ -13,6 +13,27 @@ async def remove_directory(path: Path) -> None: await asyncio.to_thread(shutil.rmtree, path, ignore_errors=True) +def onerror(func, path, exc_info): + """ + Error handler for ``shutil.rmtree``. + + Windows may experience an access error when a file is labeled "read + only". In this instance, the function will attempt to add write + permissions and then retry the function. If the error persists or raises + for another reason, the original error gets re-raised. + + Usage: ``shutil.rmtree(path, onerror=onerror)`` + """ + import stat + + # Is the error an access error? + if not os.access(path, os.W_OK): + os.chmod(path, stat.S_IWUSR) + func(path) + else: + raise + + async def remove_hidden_contents(directory: Path) -> None: """Remove hidden files and directories from a specified directory.""" for item in directory.iterdir(): @@ -20,6 +41,6 @@ async def remove_hidden_contents(directory: Path) -> None: continue if item.name.startswith("."): if item.is_dir(): - shutil.rmtree(item) + shutil.rmtree(item, onerror=onerror) else: item.unlink()