Lint and document config and constants modules

This commit is contained in:
Ethan Paul 2021-10-29 19:29:01 -04:00
parent dac9fd0b18
commit 37303ccc50
No known key found for this signature in database
GPG Key ID: D0E2CBF1245E92BF
3 changed files with 101 additions and 21 deletions

View File

@ -17,6 +17,8 @@ disable=logging-fstring-interpolation
,typecheck
,wrong-import-order
,wrong-import-position
,missing-module-docstring
,fixme
[REPORTS]

View File

@ -44,13 +44,20 @@ def _get_bool(var: str, default: bool) -> bool:
@dataclass
class DatabaseSqliteConfig:
path: Path = Path.cwd() / "fresnel.db"
"""SQLite database backend configuration options
:param path: Path to the SQLite database file
:param pragmas: Mapping of SQLite pragmas to apply to the database connection
"""
path: Path = Path.cwd() / "kodak.db"
pragmas: Dict[str, Any] = field(
default_factory=lambda: constants.DEFAULT_SQLITE_PRAGMAS
)
@classmethod
def from_env(cls):
"""Build dataclass from environment"""
return cls(
path=_get_path("KODAK_DATABASE_SQLITE_PATH", cls.path),
pragmas=json.loads(os.environ["KODAK_DATABASE_SQLITE_PRAGMAS"])
@ -61,6 +68,14 @@ class DatabaseSqliteConfig:
@dataclass
class DatabaseMariaConfig:
"""MariaDB database backend configuration options
:param hostname: Hostname or IP address of the host running the database server
:param username: Username of the account to use for connecting to the database server
:param password: Password for the account to use for connecting to the database server
:param port: Port on the host that the database server is listening on
:param schema: Database schema that the application should use
"""
hostname: str = "localhost"
username: str = "root"
@ -70,6 +85,7 @@ class DatabaseMariaConfig:
@classmethod
def from_env(cls):
"""Build dataclass from environment"""
return cls(
hostname=os.getenv("KODAK_DATABASE_MARIADB_HOSTNAME", cls.hostname),
username=os.getenv("KODAK_DATABASE_MARIADB_USERNAME", cls.username),
@ -81,6 +97,12 @@ class DatabaseMariaConfig:
@dataclass
class DatabaseConfig:
"""Database backend configuration
:param backend: Enum selecting the backend to use for storing data
:param sqlite: Container of SQLite settings
:param mariadb: Container of MariaDB settings
"""
backend: constants.DatabaseBackend = constants.DatabaseBackend.SQLITE
sqlite: DatabaseSqliteConfig = field(default_factory=DatabaseSqliteConfig.from_env)
@ -88,6 +110,7 @@ class DatabaseConfig:
@classmethod
def from_env(cls):
"""Build dataclass from environment"""
return cls(
backend=_get_enum_by_name(
"KODAK_DATABASE_BACKEND", constants.DatabaseBackend, cls.backend
@ -97,12 +120,20 @@ class DatabaseConfig:
@dataclass
class ManipCropConfig:
"""Settings for cropping an image
:param horizontal: Size the image should be cropped to (in pixels) in the horizontal direction
:param vertical: Size the image should be cropped to (in pixels) in the vertical direction
:param anchor: Image location anchor that cropping should be done relative to
"""
horizontal: Optional[int] = None
vertical: Optional[int] = None
anchor: constants.CropAnchor = constants.CropAnchor.C
@classmethod
def from_env(cls, key: str):
"""Build dataclass from environment"""
return cls(
anchor=_get_enum_by_value(
f"KODAK_MANIP_{key}_CROP_ANCHOR", constants.CropAnchor, cls.anchor
@ -114,12 +145,28 @@ class ManipCropConfig:
@dataclass
class ManipScaleConfig:
"""Settings for scaling an image
:param horizontal: Horizontal scaling dimension. If ``strategy`` is ``ABSOLUTE`` then this is
the pixel measurement that the horizontal dimension will be scaled up or
down to; if ``strategy`` is ``RELATIVE`` then this is a percentage modifier
that will be applied to the image's existing horizontal dimension.
:param vertical: Vertical scaling dimension. If ``strategy`` is ``ABSOLUTE`` then this is the
pixel measurement that the vertical dimension will be scaled up or down to;
if ``strategy`` is ``RELATIVE`` then this is a percentage modifier that will
be applied to the image's existing vertical dimension.
:param strategy: Strategy to use for scaling the image. Use ``ABSOLUTE`` to scale to an
absolute pixel measurement and use ``RELATIVE`` to scale relative to the
existing dimensions.
"""
horizontal: Optional[Union[int, float]] = None
vertical: Optional[Union[int, float]] = None
strategy: constants.ScaleStrategy = constants.ScaleStrategy.ABSOLUTE
@classmethod
def from_env(cls, key: str):
"""Build dataclass from environment"""
strategy = _get_enum_by_name(
f"KODAK_MANIP_{key}_SCALE_STRATEGY", constants.ScaleStrategy, cls.strategy
)
@ -140,6 +187,15 @@ class ManipScaleConfig:
@dataclass
class ManipConfig:
"""Image manipulation configuration settings
:param name: Name of the manipulation that will be accessed in the URL
:param crop: Contaienr of settings for cropping an image
:param scale: Container of settings for scaling an image
:param formats: Set of image formats that the source can be dynamically converted into
:param black_and_white: Whether the image should be converted to black and white
"""
name: str
crop: ManipCropConfig = field(default_factory=ManipCropConfig.from_env)
scale: ManipScaleConfig = field(default_factory=ManipScaleConfig.from_env)
@ -147,6 +203,7 @@ class ManipConfig:
default_factory=lambda: constants.DEFAULT_SUPPORTED_FORMATS
)
black_and_white: bool = False
# TODO: Implement support for these settings
# brightness: int = 0
# contrast: int = 0
@ -154,15 +211,14 @@ class ManipConfig:
@classmethod
def from_env(cls, key: str):
"""Build dataclass from environment"""
return cls(
name=os.getenv(f"KODAK_MANIP_{key}_NAME", key.lower()),
crop=ManipCropConfig.from_env(key),
scale=ManipScaleConfig.from_env(key),
formats=set(
[
constants.ImageFormat[item.strip().upper()]
for item in os.environ[f"KODAK_MANIP_{key}_FORMATS"].split(",")
]
constants.ImageFormat[item.strip().upper()]
for item in os.environ[f"KODAK_MANIP_{key}_FORMATS"].split(",")
)
if f"KODAK_MANIP_{key}_FORMATS" in os.environ
else constants.DEFAULT_SUPPORTED_FORMATS,
@ -174,32 +230,46 @@ class ManipConfig:
@dataclass
class KodakConfig:
"""Global application configuration settings
:param database: Container of database backend settings
:param manips: Mapping of manipulation config names to image manipulation configurations
:param source_dir: Path to where source images should be loaded from
:param content_dir: Path to where the application should store generated images
:param expose_source: Whether the original image should be exposed to clients
:param private: Whether authentication is required for accessing the server
"""
database: DatabaseConfig = field(default_factory=DatabaseConfig.from_env)
sourcedir: Path = Path.cwd() / "images"
manipdir: Path = Path.cwd() / "images"
manips: Dict[str, ManipConfig] = field(default_factory=dict)
source_dir: Path = Path.cwd() / "images"
content_dir: Path = Path.cwd() / "images"
expose_source: bool = False
private: bool = False
manips: Dict[str, ManipConfig] = field(default_factory=dict)
@classmethod
def from_env(cls):
"""Build dataclass from environment"""
manip_names = set(
[
key.replace("KODAK_MANIP_", "").partition("_")[0]
for key in os.environ.keys()
if key.startswith("KODAK_MANIP_")
]
key.replace("KODAK_MANIP_", "").partition("_")[0]
for key in os.environ
if key.startswith("KODAK_MANIP_")
)
manips = [ManipConfig.from_env(name) for name in manip_names]
return cls(
sourcedir=_get_path("KODAK_SOURCEDIR", cls.sourcedir),
manipdir=_get_path("KODAK_MANIPDIR", cls.manipdir),
source_dir=_get_path("KODAK_SOURCE_DIR", cls.source_dir),
content_dir=_get_path("KODAK_CONTENT_DIR", cls.content_dir),
expose_source=_get_bool("KODAK_EXPOSE_SOURCE", cls.expose_source),
private=_get_bool("KODAK_PRIVATE", cls.private),
manips={name.lower(): ManipConfig.from_env(name) for name in manip_names},
manips={item.name: item for item in manips},
)
def load() -> KodakConfig:
"""Load the application configuration from environment variables
:returns: Populated environment configuration
"""
try:
return KodakConfig.from_env()
except (ValueError, TypeError, IndexError, KeyError) as err:

View File

@ -4,21 +4,22 @@ import peewee
class DatabaseBackend(enum.Enum):
"""Enum of supported database backends"""
MARIADB = peewee.MySQLDatabase
SQLITE = peewee.SqliteDatabase
class ScaleStrategy(enum.Enum):
"""Available strategies for scaling images"""
RELATIVE = enum.auto()
ABSOLUTE = enum.auto()
class ImageFormat(enum.Enum):
JPEG = enum.auto()
PNG = enum.auto()
class CropAnchor(enum.Enum):
"""Anchor locations for cropping images"""
TL = "top-left"
TC = "top-center"
TR = "top-center"
@ -30,6 +31,13 @@ class CropAnchor(enum.Enum):
BR = "bottom-right"
class ImageFormat(enum.Enum):
"""Supported image conversion formats"""
JPEG = enum.auto()
PNG = enum.auto()
DEFAULT_SQLITE_PRAGMAS = {
"journal_mode": "wal",
"cache_size": -1 * 64000,