mirror of
https://code.lenaisten.de/Lenaisten/advent22.git
synced 2024-11-23 00:03:07 +00:00
Merge branch 'develop' into feature/drawrects
This commit is contained in:
commit
f0bac2d168
8 changed files with 54 additions and 63 deletions
|
@ -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
4
api/.flake8
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
[flake8]
|
||||||
|
max-line-length = 80
|
||||||
|
select = C,E,F,W,B,B950
|
||||||
|
extend-ignore = E203, E501
|
31
api/.vscode/settings.json
vendored
31
api/.vscode/settings.json
vendored
|
@ -1,17 +1,16 @@
|
||||||
{
|
{
|
||||||
"python.testing.pytestArgs": [
|
"python.linting.enabled": true,
|
||||||
"tests"
|
"python.linting.pylintEnabled": false,
|
||||||
],
|
"python.linting.flake8Enabled": true,
|
||||||
"python.testing.unittestEnabled": false,
|
"python.languageServer": "Pylance",
|
||||||
"python.testing.pytestEnabled": true,
|
"editor.formatOnSave": true,
|
||||||
"python.linting.enabled": true,
|
"[python]": {
|
||||||
"python.linting.pylintEnabled": false,
|
"editor.defaultFormatter": "ms-python.black-formatter"
|
||||||
"python.linting.flake8Enabled": true,
|
},
|
||||||
"python.languageServer": "Pylance",
|
"editor.codeActionsOnSave": {
|
||||||
"editor.formatOnSave": true,
|
"source.organizeImports": true
|
||||||
"editor.codeActionsOnSave": {
|
},
|
||||||
"source.organizeImports": true
|
"git.closeDiffOnOperation": true,
|
||||||
},
|
"python.analysis.typeCheckingMode": "basic",
|
||||||
"git.closeDiffOnOperation": true,
|
"python.analysis.diagnosticMode": "workspace",
|
||||||
"python.analysis.typeCheckingMode": "basic"
|
}
|
||||||
}
|
|
|
@ -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_login": SETTINGS.webdav.username,
|
"webdav_hostname": SETTINGS.webdav.url,
|
||||||
"webdav_password": SETTINGS.webdav.password,
|
"webdav_login": SETTINGS.webdav.username,
|
||||||
"disable_check": SETTINGS.webdav.disable_check,
|
"webdav_password": SETTINGS.webdav.password,
|
||||||
})
|
"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)
|
||||||
|
|
|
@ -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(
|
||||||
int((width - square)/2),
|
box=(
|
||||||
int((height - square)/2),
|
int((width - square) / 2),
|
||||||
int((width + square)/2),
|
int((height - square) / 2),
|
||||||
int((height + square)/2),
|
int((width + 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,
|
||||||
)
|
)
|
||||||
|
|
|
@ -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 #
|
||||||
#########
|
#########
|
||||||
|
|
|
@ -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:
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue