Merge branch 'develop' into feature/drawrects

This commit is contained in:
Jörn-Michael Miehe 2023-09-03 16:45:01 +00:00
commit f0bac2d168
8 changed files with 54 additions and 63 deletions

View file

@ -20,25 +20,15 @@
"vscode": { "vscode": {
// Set *default* container specific settings.json values on container create. // Set *default* container specific settings.json values on container create.
"settings": { "settings": {
"python.defaultInterpreterPath": "/usr/local/bin/python", "python.defaultInterpreterPath": "/usr/local/bin/python"
"python.linting.enabled": true,
"python.linting.pylintEnabled": true,
"python.formatting.autopep8Path": "/usr/local/py-utils/bin/autopep8",
"python.formatting.blackPath": "/usr/local/py-utils/bin/black",
"python.formatting.yapfPath": "/usr/local/py-utils/bin/yapf",
"python.linting.banditPath": "/usr/local/py-utils/bin/bandit",
"python.linting.flake8Path": "/usr/local/py-utils/bin/flake8",
"python.linting.mypyPath": "/usr/local/py-utils/bin/mypy",
"python.linting.pycodestylePath": "/usr/local/py-utils/bin/pycodestyle",
"python.linting.pydocstylePath": "/usr/local/py-utils/bin/pydocstyle",
"python.linting.pylintPath": "/usr/local/py-utils/bin/pylint"
}, },
// Add the IDs of extensions you want installed when the container is created. // Add the IDs of extensions you want installed when the container is created.
"extensions": [ "extensions": [
"be5invis.toml", "be5invis.toml",
"mhutchie.git-graph", "mhutchie.git-graph",
"ms-python.python", "ms-python.python",
"ms-python.flake8", "ms-python.black-formatter",
// "ms-python.flake8",
"ms-python.isort", "ms-python.isort",
"ms-python.vscode-pylance" "ms-python.vscode-pylance"
] ]

4
api/.flake8 Normal file
View file

@ -0,0 +1,4 @@
[flake8]
max-line-length = 80
select = C,E,F,W,B,B950
extend-ignore = E203, E501

View file

@ -1,17 +1,16 @@
{ {
"python.testing.pytestArgs": [
"tests"
],
"python.testing.unittestEnabled": false,
"python.testing.pytestEnabled": true,
"python.linting.enabled": true, "python.linting.enabled": true,
"python.linting.pylintEnabled": false, "python.linting.pylintEnabled": false,
"python.linting.flake8Enabled": true, "python.linting.flake8Enabled": true,
"python.languageServer": "Pylance", "python.languageServer": "Pylance",
"editor.formatOnSave": true, "editor.formatOnSave": true,
"[python]": {
"editor.defaultFormatter": "ms-python.black-formatter"
},
"editor.codeActionsOnSave": { "editor.codeActionsOnSave": {
"source.organizeImports": true "source.organizeImports": true
}, },
"git.closeDiffOnOperation": true, "git.closeDiffOnOperation": true,
"python.analysis.typeCheckingMode": "basic" "python.analysis.typeCheckingMode": "basic",
"python.analysis.diagnosticMode": "workspace",
} }

View file

@ -6,22 +6,20 @@ from webdav3.client import Client as WebDAVclient
from .settings import SETTINGS from .settings import SETTINGS
_WEBDAV_CLIENT = WebDAVclient({ _WEBDAV_CLIENT = WebDAVclient(
{
"webdav_hostname": SETTINGS.webdav.url, "webdav_hostname": SETTINGS.webdav.url,
"webdav_login": SETTINGS.webdav.username, "webdav_login": SETTINGS.webdav.username,
"webdav_password": SETTINGS.webdav.password, "webdav_password": SETTINGS.webdav.password,
"disable_check": SETTINGS.webdav.disable_check, "disable_check": SETTINGS.webdav.disable_check,
}) }
)
@AsyncTTL(time_to_live=SETTINGS.cache_ttl) @AsyncTTL(time_to_live=SETTINGS.cache_ttl)
async def dav_list_files(regex: re.Pattern, directory: str = "") -> list[str]: async def dav_list_files(regex: re.Pattern, directory: str = "") -> list[str]:
ls = _WEBDAV_CLIENT.list(directory) ls = _WEBDAV_CLIENT.list(directory)
return [ return [f"{directory}/{path}" for path in ls if regex.search(path)]
f"{directory}/{path}"
for path in ls
if regex.search(path)
]
@AsyncTTL(time_to_live=SETTINGS.cache_ttl) @AsyncTTL(time_to_live=SETTINGS.cache_ttl)

View file

@ -1,5 +1,6 @@
import colorsys import colorsys
from dataclasses import dataclass from dataclasses import dataclass
from typing import Self
import numpy as np import numpy as np
from PIL import Image, ImageDraw, ImageFont from PIL import Image, ImageDraw, ImageFont
@ -10,7 +11,7 @@ class AdventImage:
img: Image.Image img: Image.Image
@classmethod @classmethod
async def load_standard(cls, fp) -> "AdventImage": async def load_standard(cls, fp) -> Self:
""" """
Bild laden und einen quadratischen Ausschnitt Bild laden und einen quadratischen Ausschnitt
aus der Mitte nehmen aus der Mitte nehmen
@ -24,16 +25,18 @@ class AdventImage:
square = min(width, height) square = min(width, height)
# Bild zuschneiden und skalieren # Bild zuschneiden und skalieren
img = img.crop(box=( img = img.crop(
box=(
int((width - square) / 2), int((width - square) / 2),
int((height - square) / 2), int((height - square) / 2),
int((width + square) / 2), int((width + square) / 2),
int((height + square) / 2), int((height + square) / 2),
)) )
)
img = img.resize( img = img.resize(
size=(500, 500), size=(500, 500),
resample=Image.ANTIALIAS, resample=Image.LANCZOS,
) )
# Farbmodell festlegen # Farbmodell festlegen
@ -79,7 +82,7 @@ class AdventImage:
""" """
pixel_data = self.img.crop(box).getdata() pixel_data = self.img.crop(box).getdata()
mean_color: np.ndarray = np.mean(pixel_data, axis=0) mean_color: np.ndarray = np.mean(a=pixel_data, axis=0)
return tuple(mean_color.astype(int).tolist()) return tuple(mean_color.astype(int).tolist())
@ -98,11 +101,7 @@ class AdventImage:
# betroffenen Bildbereich bestimmen # betroffenen Bildbereich bestimmen
text_box = await self.get_text_box( text_box = await self.get_text_box(
xy=xy, xy=xy, text=text, font=font, anchor=anchor, **text_kwargs
text=text,
font=font,
anchor=anchor,
**text_kwargs
) )
if text_box is not None: if text_box is not None:
@ -131,5 +130,5 @@ class AdventImage:
font=font, font=font,
fill=text_color, fill=text_color,
anchor=anchor, anchor=anchor,
**text_kwargs **text_kwargs,
) )

View file

@ -1,7 +1,7 @@
import itertools import itertools
import random import random
import re import re
from typing import Any, Sequence from typing import Any, Self, Sequence
from fastapi import Depends from fastapi import Depends
from PIL import ImageFont from PIL import ImageFont
@ -17,7 +17,7 @@ from ._image import AdventImage
class Random(random.Random): class Random(random.Random):
@classmethod @classmethod
async def get(cls, bonus_salt: Any = "") -> "Random": async def get(cls, bonus_salt: Any = "") -> Self:
cfg = await get_config() cfg = await get_config()
return cls(f"{cfg.puzzle.solution}{bonus_salt}") return cls(f"{cfg.puzzle.solution}{bonus_salt}")
@ -36,6 +36,7 @@ async def shuffle(seq: Sequence, rnd: random.Random | None = None) -> list:
# Elemente mischen # Elemente mischen
return rnd.sample(seq, len(seq)) return rnd.sample(seq, len(seq))
######### #########
# IMAGE # # IMAGE #
######### #########

View file

@ -22,8 +22,10 @@ async def uwe(
) -> str: ) -> str:
kurix = await get_kurix(kgs) kurix = await get_kurix(kgs)
return f"UWE hat bei {firma} einen beachtlichen Haufen von " \ return (
f"UWE hat bei {firma} einen beachtlichen Haufen von "
f"{kgs} Kg ({kurix:.3f} Kurix) auf den Läufer geschissen." f"{kgs} Kg ({kurix:.3f} Kurix) auf den Läufer geschissen."
)
@router.get("/torsten/{ding}") @router.get("/torsten/{ding}")
@ -41,8 +43,8 @@ async def torsten(ding: str) -> str:
status.HTTP_418_IM_A_TEAPOT: { status.HTTP_418_IM_A_TEAPOT: {
"description": "Commit Sudoku", "description": "Commit Sudoku",
"content": None, "content": None,
} },
} },
) )
async def kys() -> None: async def kys() -> None:
""" """

View file

@ -13,9 +13,7 @@ async def user_is_admin(
credentials: HTTPBasicCredentials = Depends(security), credentials: HTTPBasicCredentials = Depends(security),
config: Config = Depends(get_config), config: Config = Depends(get_config),
) -> bool: ) -> bool:
username_correct = secrets.compare_digest( username_correct = secrets.compare_digest(credentials.username, config.admin.name)
credentials.username, config.admin.name
)
password_correct = secrets.compare_digest( password_correct = secrets.compare_digest(
credentials.password, config.admin.password credentials.password, config.admin.password