Skip to content

Commit

Permalink
Remove aiofiles dependency
Browse files Browse the repository at this point in the history
Remove dependency on aiofiles, `NamedTemporaryFile` was causing issues.
Replace temporary files with a temporary file in `artifacts/tmp`.
  • Loading branch information
b-rowan committed Sep 13, 2024
1 parent fc1f1cd commit 4b61382
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 18 deletions.
3 changes: 1 addition & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@ repos:
rev: v1.11.2
hooks:
- id: mypy
additional_dependencies:
[types-pyyaml==6.0.12.20240808, types-aiofiles==24.1.0.20240626]
additional_dependencies: [types-pyyaml==6.0.12.20240808]
- repo: local
hooks:
- id: pytest
Expand Down
21 changes: 14 additions & 7 deletions goosebit/api/v1/software/routes.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import aiofiles
from anyio import Path
import random
import string

from anyio import Path, open_file
from fastapi import APIRouter, File, Form, HTTPException, Security, UploadFile
from fastapi.requests import Request

Expand Down Expand Up @@ -69,11 +71,16 @@ async def post_update(_: Request, file: UploadFile | None = File(None), url: str
# local file
artifacts_dir = Path(config.artifacts_dir)
file_path = artifacts_dir.joinpath(file.filename)

async with aiofiles.tempfile.NamedTemporaryFile("w+b") as f:
await f.write(await file.read())
absolute = await file_path.absolute()
software = await create_software_update(absolute.as_uri(), Path(f.name))
tmp_file_path = artifacts_dir.joinpath("tmp", ("".join(random.choices(string.ascii_lowercase, k=12)) + ".tmp"))
await tmp_file_path.parent.mkdir(parents=True, exist_ok=True)
file_absolute_path = await file_path.absolute()
tmp_file_absolute_path = await tmp_file_path.absolute()
try:
async with await open_file(tmp_file_path, "w+b") as f:
await f.write(await file.read())
software = await create_software_update(file_absolute_path.as_uri(), tmp_file_absolute_path)
finally:
await tmp_file_path.unlink(missing_ok=True)
else:
raise HTTPException(422)

Expand Down
11 changes: 7 additions & 4 deletions goosebit/updates/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ async def create_software_update(uri: str, temp_file: Path | None) -> Software:
parsed_uri = urlparse(uri)

# parse swu header into update_info
if parsed_uri.scheme == "file" and temp_file is not None:
if parsed_uri.scheme == "file":
if temp_file is None:
raise HTTPException(500, "Temporary file missing, cannot parse file information")
try:
update_info = await swdesc.parse_file(temp_file)
except Exception:
Expand All @@ -30,7 +32,6 @@ async def create_software_update(uri: str, temp_file: Path | None) -> Software:
update_info = await swdesc.parse_remote(uri)
except Exception:
raise HTTPException(422, "Software swu header cannot be parsed")

else:
raise HTTPException(422, "Software URI protocol unknown")

Expand All @@ -43,11 +44,13 @@ async def create_software_update(uri: str, temp_file: Path | None) -> Software:
raise HTTPException(409, "Software with same version and overlapping compatibility already exists")

# for local file: rename temp file to final name
if parsed_uri.scheme == "file" and temp_file is not None:
if parsed_uri.scheme == "file":
if temp_file is None:
raise HTTPException(500, "Temporary file missing, cannot parse file information")
filename = Path(url2pathname(unquote(parsed_uri.path))).name
path = Path(config.artifacts_dir).joinpath(update_info["hash"], filename)
await path.parent.mkdir(parents=True, exist_ok=True)
await temp_file.rename(path)
await temp_file.replace(path)
absolute = await path.absolute()
uri = absolute.as_uri()

Expand Down
18 changes: 14 additions & 4 deletions goosebit/updates/swdesc.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import hashlib
import logging
import random
import string
from typing import Any

import aiofiles
import httpx
import libconf
import semver
from anyio import AsyncFile, Path, open_file

from goosebit.settings import config

logger = logging.getLogger(__name__)


Expand Down Expand Up @@ -68,9 +71,16 @@ async def parse_file(file: Path):
async def parse_remote(url: str):
async with httpx.AsyncClient() as c:
file = await c.get(url)
async with aiofiles.tempfile.NamedTemporaryFile("w+b") as f:
await f.write(file.content)
return await parse_file(Path(str(f.name)))
artifacts_dir = Path(config.artifacts_dir)
tmp_file_path = artifacts_dir.joinpath("tmp", ("".join(random.choices(string.ascii_lowercase, k=12)) + ".tmp"))
await tmp_file_path.parent.mkdir(parents=True, exist_ok=True)
try:
async with await open_file(tmp_file_path, "w+b") as f:
await f.write(file.content)
file_data = await parse_file(Path(str(f.name)))
finally:
await tmp_file_path.unlink()
return file_data


async def _sha1_hash_file(fileobj: AsyncFile):
Expand Down
4 changes: 3 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ jinja2 = "^3.1.4"
itsdangerous = "^2.2.0"
tortoise-orm = "^0.21.4"
aerich = "^0.7.2"
aiofiles = "^24.1.0"
websockets = "^12.0"
argon2-cffi = "^23.1.0"
joserfc = "^1.0.0"
Expand Down Expand Up @@ -64,6 +63,9 @@ tortoise_orm = "goosebit.db.config.TORTOISE_CONF"
location = "goosebit/db/migrations"
src_folder = "./goosebit"

[tool.mypy]
explicit_package_bases = true

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

0 comments on commit 4b61382

Please sign in to comment.