Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make all shutil calls asynchronous #1245

Merged
merged 1 commit into from
Feb 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion betty/cache.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""
Provide the Cache API.
"""
import asyncio
import logging
import shutil
from contextlib import suppress
Expand All @@ -22,5 +23,5 @@ def __init__(self, localizer: Localizer):

async def clear(self) -> None:
with suppress(FileNotFoundError):
shutil.rmtree(fs.CACHE_DIRECTORY_PATH)
await asyncio.to_thread(shutil.rmtree, fs.CACHE_DIRECTORY_PATH)
logging.getLogger(__name__).info(self._localizer._('All caches cleared.'))
5 changes: 3 additions & 2 deletions betty/extension/cotton_candy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"""
from __future__ import annotations

import asyncio
import logging
import re
from collections import defaultdict
Expand Down Expand Up @@ -224,8 +225,8 @@ async def npm_build(self, working_directory_path: Path, assets_directory_path: P

async def _copy_npm_build(self, source_directory_path: Path, destination_directory_path: Path) -> None:
await makedirs(destination_directory_path, exist_ok=True)
copy2(source_directory_path / 'cotton_candy.css', destination_directory_path / 'cotton_candy.css')
copy2(source_directory_path / 'cotton_candy.js', destination_directory_path / 'cotton_candy.js')
await asyncio.to_thread(copy2, source_directory_path / 'cotton_candy.css', destination_directory_path / 'cotton_candy.css')
await asyncio.to_thread(copy2, source_directory_path / 'cotton_candy.js', destination_directory_path / 'cotton_candy.js')

async def generate(self, task_context: GenerationContext) -> None:
assets_directory_path = await self.app.extensions[_Npm].ensure_assets(self)
Expand Down
5 changes: 3 additions & 2 deletions betty/extension/http_api_doc/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""Integrate Betty with `ReDoc <https://redocly.com/redoc/>`_."""
from __future__ import annotations

import asyncio
import logging
from pathlib import Path
from shutil import copy2
Expand All @@ -21,7 +22,7 @@ def depends_on(cls) -> set[type[Extension]]:

async def npm_build(self, working_directory_path: Path, assets_directory_path: Path) -> None:
await self.app.extensions[_Npm].install(type(self), working_directory_path)
copy2(working_directory_path / 'node_modules' / 'redoc' / 'bundles' / 'redoc.standalone.js', assets_directory_path / 'http-api-doc.js')
await asyncio.to_thread(copy2, working_directory_path / 'node_modules' / 'redoc' / 'bundles' / 'redoc.standalone.js', assets_directory_path / 'http-api-doc.js')
logging.getLogger(__name__).info(self._app.localizer._('Built the HTTP API documentation.'))

@classmethod
Expand All @@ -31,7 +32,7 @@ def npm_cache_scope(cls) -> CacheScope:
async def generate(self, task_context: GenerationContext) -> None:
assets_directory_path = await self.app.extensions[_Npm].ensure_assets(self)
await makedirs(self.app.project.configuration.www_directory_path, exist_ok=True)
copy2(assets_directory_path / 'http-api-doc.js', self.app.project.configuration.www_directory_path / 'http-api-doc.js')
await asyncio.to_thread(copy2, assets_directory_path / 'http-api-doc.js', self.app.project.configuration.www_directory_path / 'http-api-doc.js')

@classmethod
def assets_directory_path(cls) -> Path | None:
Expand Down
7 changes: 4 additions & 3 deletions betty/extension/maps/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""Integrate Betty with `Leaflet.js <https://leafletjs.com/>`_."""
from __future__ import annotations

import asyncio
import logging
from contextlib import suppress
from pathlib import Path
Expand Down Expand Up @@ -29,10 +30,10 @@ async def npm_build(self, working_directory_path: Path, assets_directory_path: P

async def _copy_npm_build(self, source_directory_path: Path, destination_directory_path: Path) -> None:
await makedirs(destination_directory_path, exist_ok=True)
copy2(source_directory_path / 'maps.css', destination_directory_path / 'maps.css')
copy2(source_directory_path / 'maps.js', destination_directory_path / 'maps.js')
await asyncio.to_thread(copy2, source_directory_path / 'maps.css', destination_directory_path / 'maps.css')
await asyncio.to_thread(copy2, source_directory_path / 'maps.js', destination_directory_path / 'maps.js')
with suppress(FileNotFoundError):
copytree(source_directory_path / 'images', destination_directory_path / 'images')
await asyncio.to_thread(copytree, source_directory_path / 'images', destination_directory_path / 'images')

@classmethod
def npm_cache_scope(cls) -> CacheScope:
Expand Down
6 changes: 4 additions & 2 deletions betty/extension/npm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"""
from __future__ import annotations

import asyncio
import logging
import os
import shutil
Expand Down Expand Up @@ -168,7 +169,7 @@ async def _build_assets_to_directory_path(extension: NpmBuilder & Extension, ass
assert isinstance(extension, Extension)
assert isinstance(extension, NpmBuilder)
with suppress(FileNotFoundError):
shutil.rmtree(assets_directory_path)
await asyncio.to_thread(shutil.rmtree, assets_directory_path)
os.makedirs(assets_directory_path)
async with TemporaryDirectory() as working_directory_path_str:
working_directory_path = Path(working_directory_path_str)
Expand Down Expand Up @@ -202,7 +203,8 @@ async def install(self, extension_type: type[NpmBuilder & Extension], working_di
if self._npm_requirement:
self._npm_requirement.assert_met()

shutil.copytree(
await asyncio.to_thread(
shutil.copytree,
_get_assets_src_directory_path(extension_type),
working_directory_path,
dirs_exist_ok=True,
Expand Down
5 changes: 3 additions & 2 deletions betty/extension/trees/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""Provide interactive family trees by integrating Betty with `Cytoscape.js <https://cytoscape.org/>`_."""
from __future__ import annotations

import asyncio
import logging
import subprocess
from pathlib import Path
Expand Down Expand Up @@ -29,8 +30,8 @@ async def npm_build(self, working_directory_path: Path, assets_directory_path: P

async def _copy_npm_build(self, source_directory_path: Path, destination_directory_path: Path) -> None:
await makedirs(destination_directory_path, exist_ok=True)
copy2(source_directory_path / 'trees.css', destination_directory_path / 'trees.css')
copy2(source_directory_path / 'trees.js', destination_directory_path / 'trees.js')
await asyncio.to_thread(copy2, source_directory_path / 'trees.css', destination_directory_path / 'trees.css')
await asyncio.to_thread(copy2, source_directory_path / 'trees.js', destination_directory_path / 'trees.js')

@classmethod
def npm_cache_scope(cls) -> CacheScope:
Expand Down
2 changes: 1 addition & 1 deletion betty/fs.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ def open(self, *file_paths: Path) -> _Open:
async def copy2(self, source_path: Path, destination_path: Path) -> Path:
for fs_path, _ in self._paths:
with suppress(FileNotFoundError):
copy2(fs_path / source_path, destination_path)
await asyncio.to_thread(copy2, fs_path / source_path, destination_path)
return destination_path
tried_paths = [str(fs_path / source_path) for fs_path, _ in self._paths]
raise FileNotFoundError('Could not find any of %s.' % ', '.join(tried_paths))
Expand Down
3 changes: 2 additions & 1 deletion betty/generate.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"""
from __future__ import annotations

import asyncio
import json
import logging
import multiprocessing
Expand Down Expand Up @@ -164,7 +165,7 @@ async def generate(app: App) -> None:
task_context = GenerationContext(app)

with suppress(FileNotFoundError):
shutil.rmtree(app.project.configuration.output_directory_path)
await asyncio.to_thread(shutil.rmtree, app.project.configuration.output_directory_path)
await aiofiles_os.makedirs(app.project.configuration.output_directory_path, exist_ok=True)
logger.info(app.localizer._('Generating your site to {output_directory}.').format(output_directory=app.project.configuration.output_directory_path))

Expand Down
3 changes: 2 additions & 1 deletion betty/os.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"""
from __future__ import annotations

import asyncio
import os
import shutil
from contextlib import suppress
Expand All @@ -26,7 +27,7 @@ async def link_or_copy(source_path: Path, destination_path: Path) -> None:
await link(source_path, destination_path)
except OSError:
with suppress(shutil.SameFileError):
shutil.copyfile(source_path, destination_path)
await asyncio.to_thread(shutil.copyfile, source_path, destination_path)


class ChDir:
Expand Down
Loading