Fix warnings from Ruff and ffmpeg
This commit is contained in:
6
.vscode/settings.json
vendored
Normal file
6
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"python.analysis.typeCheckingMode": "standard",
|
||||
"cSpell.words": [
|
||||
"dotenv"
|
||||
]
|
||||
}
|
@ -21,7 +21,7 @@ app: FastAPI = FastAPI(
|
||||
|
||||
|
||||
@app.post("/uploadfiles/", description="Where to send a POST request to upload files.")
|
||||
async def upload_file(file: Annotated[UploadFile, File()]):
|
||||
async def upload_file(file: Annotated[UploadFile, File()]) -> JSONResponse:
|
||||
"""Page for uploading files.
|
||||
|
||||
If it is a video, we need to make an HTML file, and a thumbnail
|
||||
@ -42,9 +42,9 @@ async def upload_file(file: Annotated[UploadFile, File()]):
|
||||
return JSONResponse(content={"error": "Content type is None"}, status_code=500)
|
||||
|
||||
if file.content_type.startswith("video/"):
|
||||
html_url: str = await do_things(file)
|
||||
html_url: str = do_things(file)
|
||||
else:
|
||||
filename: str = await remove_illegal_chars(file.filename)
|
||||
filename: str = remove_illegal_chars(file.filename)
|
||||
|
||||
with Path.open(Path(settings.upload_folder, filename), "wb+") as f:
|
||||
f.write(file.file.read())
|
||||
@ -55,7 +55,7 @@ async def upload_file(file: Annotated[UploadFile, File()]):
|
||||
return JSONResponse(content={"html_url": html_url})
|
||||
|
||||
|
||||
async def remove_illegal_chars(file_name: str) -> str:
|
||||
def remove_illegal_chars(file_name: str) -> str:
|
||||
"""Remove illegal characters from the filename.
|
||||
|
||||
Args:
|
||||
@ -113,7 +113,7 @@ index_html: str = """
|
||||
|
||||
|
||||
@app.get("/", response_class=HTMLResponse, include_in_schema=False)
|
||||
async def main(request: Request): # noqa: ARG001
|
||||
async def main(request: Request) -> str: # noqa: ARG001
|
||||
"""Our index view.
|
||||
|
||||
You can upload files here.
|
||||
|
@ -54,14 +54,25 @@ def make_thumbnail(path_video: str, file_filename: str) -> str:
|
||||
path_video: Path where video file is stored.
|
||||
file_filename: File name for URL.
|
||||
|
||||
Raises:
|
||||
ffmpeg.Error: If there is an error creating the thumbnail.
|
||||
|
||||
Returns:
|
||||
Returns thumbnail filename.
|
||||
"""
|
||||
output_path: str = f"{settings.upload_folder}/{file_filename}.jpg"
|
||||
try:
|
||||
(
|
||||
ffmpeg.input(path_video, ss="1")
|
||||
.output(f"{settings.upload_folder}/{file_filename}.jpg", vframes=1)
|
||||
.output(output_path, vframes=1, format="image2", update=1)
|
||||
.overwrite_output()
|
||||
.run()
|
||||
)
|
||||
except ffmpeg.Error:
|
||||
logger.exception("Error creating thumbnail")
|
||||
raise
|
||||
|
||||
logger.info("Thumbnail created: %s", output_path)
|
||||
|
||||
# Return URL for thumbnail.
|
||||
return f"{settings.serve_domain}/{file_filename}.jpg"
|
||||
|
@ -57,7 +57,7 @@ def save_to_disk(file: UploadFile) -> VideoFile:
|
||||
return VideoFile(filename, str(file_location))
|
||||
|
||||
|
||||
async def do_things(file: UploadFile) -> str:
|
||||
def do_things(file: UploadFile) -> str:
|
||||
"""Save video to disk, generate HTML, thumbnail, and return a .html URL.
|
||||
|
||||
Args:
|
||||
|
1141
poetry.lock
generated
1141
poetry.lock
generated
File diff suppressed because it is too large
Load Diff
@ -1,8 +1,25 @@
|
||||
[project]
|
||||
name = "discord-embed"
|
||||
version = "1.0.0"
|
||||
description = "Make nice embeds for Discord"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.13"
|
||||
dependencies = [
|
||||
"fastapi",
|
||||
"ffmpeg-python",
|
||||
"discord-webhook",
|
||||
"python-multipart",
|
||||
"python-dotenv",
|
||||
"Jinja2",
|
||||
"uvicorn[standard]",
|
||||
]
|
||||
|
||||
[dependency-groups]
|
||||
dev = ["pytest", "httpx"]
|
||||
|
||||
[build-system]
|
||||
build-backend = "poetry.core.masonry.api"
|
||||
requires = [
|
||||
"poetry-core>=1",
|
||||
]
|
||||
requires = ["poetry-core>=1"]
|
||||
|
||||
[tool.poetry]
|
||||
name = "discord-embed"
|
||||
@ -12,38 +29,58 @@ authors = [ "Joakim Hellsén <tlovinator@gmail.com>" ]
|
||||
license = "GPL-3.0-or-later"
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = "^3.12"
|
||||
fastapi = "^0.115.0"
|
||||
ffmpeg-python = "^0.2.0"
|
||||
discord-webhook = "^1.3.1"
|
||||
python-multipart = "^0.0.20"
|
||||
python-dotenv = "^1.0.1"
|
||||
Jinja2 = "^3.1.4"
|
||||
uvicorn = { extras = [ "standard" ], version = "^0.34.0" }
|
||||
python = "^3.13"
|
||||
fastapi = "*"
|
||||
ffmpeg-python = "*"
|
||||
discord-webhook = "*"
|
||||
python-multipart = "*"
|
||||
python-dotenv = "*"
|
||||
Jinja2 = "*"
|
||||
uvicorn = {extras = ["standard"], version = "*"}
|
||||
|
||||
[tool.poetry.group.dev.dependencies]
|
||||
httpx = "^0.28.0"
|
||||
pytest = "^8.3.2"
|
||||
pre-commit = "^4.0.0"
|
||||
httpx = "*"
|
||||
pytest = "*"
|
||||
|
||||
[tool.ruff]
|
||||
preview = true
|
||||
fix = true
|
||||
unsafe-fixes = true
|
||||
lint.select = [
|
||||
"ALL",
|
||||
]
|
||||
lint.select = ["ALL"]
|
||||
lint.pydocstyle.convention = "google"
|
||||
lint.isort.required-imports = ["from __future__ import annotations"]
|
||||
lint.pycodestyle.ignore-overlong-task-comments = true
|
||||
line-length = 120
|
||||
|
||||
lint.ignore = [
|
||||
"ANN201",
|
||||
"CPY001",
|
||||
"D100",
|
||||
"D104",
|
||||
"RUF029",
|
||||
"CPY001", # Checks for the absence of copyright notices within Python files.
|
||||
"D100", # Checks for undocumented public module definitions.
|
||||
"D104", # Checks for undocumented public package definitions.
|
||||
"D106", # Checks for undocumented public class definitions, for nested classes.
|
||||
"ERA001", # Checks for commented-out Python code.
|
||||
"FIX002", # Checks for "TODO" comments.
|
||||
|
||||
# Conflicting lint rules when using Ruff's formatter
|
||||
# https://docs.astral.sh/ruff/formatter/#conflicting-lint-rules
|
||||
"COM812", # Checks for the absence of trailing commas.
|
||||
"COM819", # Checks for the presence of prohibited trailing commas.
|
||||
"D206", # Checks for docstrings that are indented with tabs.
|
||||
"D300", # Checks for docstrings that use '''triple single quotes''' instead of """triple double quotes""".
|
||||
"E111", # Checks for indentation with a non-multiple of 4 spaces.
|
||||
"E114", # Checks for indentation of comments with a non-multiple of 4 spaces.
|
||||
"E117", # Checks for over-indented code.
|
||||
"ISC001", # Checks for implicitly concatenated strings on a single line.
|
||||
"ISC002", # Checks for implicitly concatenated strings that span multiple lines.
|
||||
"Q000", # Checks for inline strings that use single quotes or double quotes, depending on the value of the lint.flake8-quotes.inline-quotes option.
|
||||
"Q001", # Checks for multiline strings that use single quotes or double quotes, depending on the value of the lint.flake8-quotes.multiline-quotes setting.
|
||||
"Q002", # Checks for docstrings that use single quotes or double quotes, depending on the value of the lint.flake8-quotes.docstring-quotes setting.
|
||||
"Q003", # Checks for strings that include escaped quotes, and suggests changing the quote style to avoid the need to escape them.
|
||||
"W191", # Checks for indentation that uses tabs.
|
||||
]
|
||||
|
||||
lint.per-file-ignores."tests/**/*.py" = [
|
||||
[tool.ruff.lint.per-file-ignores]
|
||||
"**/test_*.py" = [
|
||||
"ARG", # Unused function args -> fixtures nevertheless are functionally relevant...
|
||||
"FBT", # Don't care about booleans as positional arguments in tests, e.g. via @pytest.mark.parametrize()
|
||||
"PLR2004", # Magic value used in comparison, ...
|
||||
"S101", # asserts allowed in tests...
|
||||
"S311", # Standard pseudo-random generators are not suitable for cryptographic purposes
|
||||
]
|
||||
lint.pydocstyle.convention = "google"
|
||||
|
@ -11,8 +11,7 @@ def test_generate_html_for_videos() -> None:
|
||||
domain: str = os.environ["SERVE_DOMAIN"]
|
||||
|
||||
# Remove trailing slash from domain
|
||||
if domain.endswith("/"):
|
||||
domain = domain[:-1]
|
||||
domain = domain.removesuffix("/")
|
||||
|
||||
# Delete the old HTML file if it exists
|
||||
if Path.exists(Path("Uploads/test_video.mp4.html")):
|
||||
|
@ -1,6 +1,5 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import imghdr
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
@ -24,13 +23,11 @@ def test_make_thumbnail() -> None:
|
||||
domain: str = domain[:-1]
|
||||
|
||||
# Remove thumbnail if it exists
|
||||
if Path.exists(Path(f"{settings.upload_folder}/test.mp4.jpg")):
|
||||
Path.unlink(Path(f"{settings.upload_folder}/test.mp4.jpg"))
|
||||
thumbnail_path = Path(f"{settings.upload_folder}/test.mp4.jpg")
|
||||
if thumbnail_path.exists():
|
||||
thumbnail_path.unlink()
|
||||
|
||||
thumbnail: str = make_thumbnail(TEST_FILE, "test.mp4")
|
||||
|
||||
# Check if thumbnail is a jpeg.
|
||||
assert imghdr.what(f"{settings.upload_folder}/test.mp4.jpg") == "jpeg"
|
||||
|
||||
# Check if it returns the correct URL.
|
||||
assert thumbnail == f"{domain}/test.mp4.jpg"
|
||||
|
Reference in New Issue
Block a user