diff --git a/api/.devcontainer/devcontainer.json b/api/.devcontainer/devcontainer.json index 2ee4cb2..d8d6a33 100644 --- a/api/.devcontainer/devcontainer.json +++ b/api/.devcontainer/devcontainer.json @@ -4,7 +4,7 @@ "name": "Advent22 API", "dockerComposeFile": "docker-compose.yml", "service": "api", - "workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}", + "workspaceFolder": "/workspaces/advent22/${localWorkspaceFolderBasename}", // Configure tool-specific properties. "customizations": { // Configure properties specific to VS Code. diff --git a/api/.devcontainer/docker-compose.yml b/api/.devcontainer/docker-compose.yml index ea9650f..ae045b7 100644 --- a/api/.devcontainer/docker-compose.yml +++ b/api/.devcontainer/docker-compose.yml @@ -16,7 +16,7 @@ services: TZ: "Europe/Berlin" volumes: - - "../..:/workspaces:cached" + - "../..:/workspaces/advent22:cached" # Overrides default command so things don't shut down after the process ends. command: "sleep infinity" diff --git a/api/.env b/api/.env new file mode 100644 index 0000000..f1ecb50 --- /dev/null +++ b/api/.env @@ -0,0 +1 @@ +COMPOSE_PROJECT_NAME="advent22_api" diff --git a/api/.gitignore b/api/.gitignore index 55be276..d4c7259 100644 --- a/api/.gitignore +++ b/api/.gitignore @@ -152,3 +152,4 @@ cython_debug/ # option (not recommended) you can uncomment the following to ignore the entire idea folder. #.idea/ +api.conf diff --git a/api/advent22_api/core/dav/helpers.py b/api/advent22_api/core/dav/helpers.py index e15617d..a6e2bd2 100644 --- a/api/advent22_api/core/dav/helpers.py +++ b/api/advent22_api/core/dav/helpers.py @@ -1,4 +1,5 @@ from json import JSONDecodeError +from typing import Callable, Hashable import requests from cachetools.keys import hashkey @@ -8,11 +9,17 @@ from redis.typing import EncodableT from webdav3.client import Client as __WebDAVclient -def davkey(name, _, *args, **kwargs): - """Return a cache key for use with cached methods.""" +def davkey( + name: str, + slice: slice = slice(1, None), +) -> Callable[..., tuple[Hashable, ...]]: + def func(*args, **kwargs) -> tuple[Hashable, ...]: + """Return a cache key for use with cached methods.""" - key = hashkey(name, *args, **kwargs) - return hashkey(*(str(key_item) for key_item in key)) + key = hashkey(name, *args[slice], **kwargs) + return hashkey(*(str(key_item) for key_item in key)) + + return func class WebDAVclient(__WebDAVclient): diff --git a/api/advent22_api/core/dav/webdav.py b/api/advent22_api/core/dav/webdav.py index 4c316a5..acb5097 100644 --- a/api/advent22_api/core/dav/webdav.py +++ b/api/advent22_api/core/dav/webdav.py @@ -1,4 +1,3 @@ -import functools import logging import re from io import BytesIO @@ -34,10 +33,7 @@ class WebDAV: @classmethod @asyncify - @cachedmethod( - cache=lambda cls: cls._cache, - key=functools.partial(davkey, "list_files"), - ) + @cachedmethod(cache=lambda cls: cls._cache, key=davkey("list_files")) def list_files( cls, directory: str = "", @@ -55,10 +51,7 @@ class WebDAV: @classmethod @asyncify - @cachedmethod( - cache=lambda cls: cls._cache, - key=functools.partial(davkey, "exists"), - ) + @cachedmethod(cache=lambda cls: cls._cache, key=davkey("exists")) def exists(cls, path: str) -> bool: """ `True` iff there is a WebDAV resource at `path` @@ -69,10 +62,7 @@ class WebDAV: @classmethod @asyncify - @cachedmethod( - cache=lambda cls: cls._cache, - key=functools.partial(davkey, "read_bytes"), - ) + @cachedmethod(cache=lambda cls: cls._cache, key=davkey("read_bytes")) def read_bytes(cls, path: str) -> bytes: """ Load WebDAV file from `path` as bytes @@ -105,7 +95,7 @@ class WebDAV: cls._webdav_client.upload_to(buffer, path) # invalidate cache entry - cls._cache.pop(davkey("read_bytes", None, path)) + cls._cache.pop(davkey("read_bytes")(path)) @classmethod async def write_str(cls, path: str, content: str, encoding="utf-8") -> None: diff --git a/api/advent22_api/core/settings.py b/api/advent22_api/core/settings.py index c509978..8ddcfee 100644 --- a/api/advent22_api/core/settings.py +++ b/api/advent22_api/core/settings.py @@ -48,7 +48,7 @@ class Settings(BaseSettings): """ model_config = SettingsConfigDict( - env_file=".env", + env_file="api.conf", env_file_encoding="utf-8", env_nested_delimiter="__", )