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 ,typecheck
,wrong-import-order ,wrong-import-order
,wrong-import-position ,wrong-import-position
,missing-module-docstring
,fixme
[REPORTS] [REPORTS]

View File

@ -44,13 +44,20 @@ def _get_bool(var: str, default: bool) -> bool:
@dataclass @dataclass
class DatabaseSqliteConfig: 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( pragmas: Dict[str, Any] = field(
default_factory=lambda: constants.DEFAULT_SQLITE_PRAGMAS default_factory=lambda: constants.DEFAULT_SQLITE_PRAGMAS
) )
@classmethod @classmethod
def from_env(cls): def from_env(cls):
"""Build dataclass from environment"""
return cls( return cls(
path=_get_path("KODAK_DATABASE_SQLITE_PATH", cls.path), path=_get_path("KODAK_DATABASE_SQLITE_PATH", cls.path),
pragmas=json.loads(os.environ["KODAK_DATABASE_SQLITE_PRAGMAS"]) pragmas=json.loads(os.environ["KODAK_DATABASE_SQLITE_PRAGMAS"])
@ -61,6 +68,14 @@ class DatabaseSqliteConfig:
@dataclass @dataclass
class DatabaseMariaConfig: 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" hostname: str = "localhost"
username: str = "root" username: str = "root"
@ -70,6 +85,7 @@ class DatabaseMariaConfig:
@classmethod @classmethod
def from_env(cls): def from_env(cls):
"""Build dataclass from environment"""
return cls( return cls(
hostname=os.getenv("KODAK_DATABASE_MARIADB_HOSTNAME", cls.hostname), hostname=os.getenv("KODAK_DATABASE_MARIADB_HOSTNAME", cls.hostname),
username=os.getenv("KODAK_DATABASE_MARIADB_USERNAME", cls.username), username=os.getenv("KODAK_DATABASE_MARIADB_USERNAME", cls.username),
@ -81,6 +97,12 @@ class DatabaseMariaConfig:
@dataclass @dataclass
class DatabaseConfig: 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 backend: constants.DatabaseBackend = constants.DatabaseBackend.SQLITE
sqlite: DatabaseSqliteConfig = field(default_factory=DatabaseSqliteConfig.from_env) sqlite: DatabaseSqliteConfig = field(default_factory=DatabaseSqliteConfig.from_env)
@ -88,6 +110,7 @@ class DatabaseConfig:
@classmethod @classmethod
def from_env(cls): def from_env(cls):
"""Build dataclass from environment"""
return cls( return cls(
backend=_get_enum_by_name( backend=_get_enum_by_name(
"KODAK_DATABASE_BACKEND", constants.DatabaseBackend, cls.backend "KODAK_DATABASE_BACKEND", constants.DatabaseBackend, cls.backend
@ -97,12 +120,20 @@ class DatabaseConfig:
@dataclass @dataclass
class ManipCropConfig: 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 horizontal: Optional[int] = None
vertical: Optional[int] = None vertical: Optional[int] = None
anchor: constants.CropAnchor = constants.CropAnchor.C anchor: constants.CropAnchor = constants.CropAnchor.C
@classmethod @classmethod
def from_env(cls, key: str): def from_env(cls, key: str):
"""Build dataclass from environment"""
return cls( return cls(
anchor=_get_enum_by_value( anchor=_get_enum_by_value(
f"KODAK_MANIP_{key}_CROP_ANCHOR", constants.CropAnchor, cls.anchor f"KODAK_MANIP_{key}_CROP_ANCHOR", constants.CropAnchor, cls.anchor
@ -114,12 +145,28 @@ class ManipCropConfig:
@dataclass @dataclass
class ManipScaleConfig: 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 horizontal: Optional[Union[int, float]] = None
vertical: Optional[Union[int, float]] = None vertical: Optional[Union[int, float]] = None
strategy: constants.ScaleStrategy = constants.ScaleStrategy.ABSOLUTE strategy: constants.ScaleStrategy = constants.ScaleStrategy.ABSOLUTE
@classmethod @classmethod
def from_env(cls, key: str): def from_env(cls, key: str):
"""Build dataclass from environment"""
strategy = _get_enum_by_name( strategy = _get_enum_by_name(
f"KODAK_MANIP_{key}_SCALE_STRATEGY", constants.ScaleStrategy, cls.strategy f"KODAK_MANIP_{key}_SCALE_STRATEGY", constants.ScaleStrategy, cls.strategy
) )
@ -140,6 +187,15 @@ class ManipScaleConfig:
@dataclass @dataclass
class ManipConfig: 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 name: str
crop: ManipCropConfig = field(default_factory=ManipCropConfig.from_env) crop: ManipCropConfig = field(default_factory=ManipCropConfig.from_env)
scale: ManipScaleConfig = field(default_factory=ManipScaleConfig.from_env) scale: ManipScaleConfig = field(default_factory=ManipScaleConfig.from_env)
@ -147,6 +203,7 @@ class ManipConfig:
default_factory=lambda: constants.DEFAULT_SUPPORTED_FORMATS default_factory=lambda: constants.DEFAULT_SUPPORTED_FORMATS
) )
black_and_white: bool = False black_and_white: bool = False
# TODO: Implement support for these settings # TODO: Implement support for these settings
# brightness: int = 0 # brightness: int = 0
# contrast: int = 0 # contrast: int = 0
@ -154,15 +211,14 @@ class ManipConfig:
@classmethod @classmethod
def from_env(cls, key: str): def from_env(cls, key: str):
"""Build dataclass from environment"""
return cls( return cls(
name=os.getenv(f"KODAK_MANIP_{key}_NAME", key.lower()), name=os.getenv(f"KODAK_MANIP_{key}_NAME", key.lower()),
crop=ManipCropConfig.from_env(key), crop=ManipCropConfig.from_env(key),
scale=ManipScaleConfig.from_env(key), scale=ManipScaleConfig.from_env(key),
formats=set( formats=set(
[ constants.ImageFormat[item.strip().upper()]
constants.ImageFormat[item.strip().upper()] for item in os.environ[f"KODAK_MANIP_{key}_FORMATS"].split(",")
for item in os.environ[f"KODAK_MANIP_{key}_FORMATS"].split(",")
]
) )
if f"KODAK_MANIP_{key}_FORMATS" in os.environ if f"KODAK_MANIP_{key}_FORMATS" in os.environ
else constants.DEFAULT_SUPPORTED_FORMATS, else constants.DEFAULT_SUPPORTED_FORMATS,
@ -174,32 +230,46 @@ class ManipConfig:
@dataclass @dataclass
class KodakConfig: 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) database: DatabaseConfig = field(default_factory=DatabaseConfig.from_env)
sourcedir: Path = Path.cwd() / "images" manips: Dict[str, ManipConfig] = field(default_factory=dict)
manipdir: Path = Path.cwd() / "images" source_dir: Path = Path.cwd() / "images"
content_dir: Path = Path.cwd() / "images"
expose_source: bool = False expose_source: bool = False
private: bool = False private: bool = False
manips: Dict[str, ManipConfig] = field(default_factory=dict)
@classmethod @classmethod
def from_env(cls): def from_env(cls):
"""Build dataclass from environment"""
manip_names = set( manip_names = set(
[ key.replace("KODAK_MANIP_", "").partition("_")[0]
key.replace("KODAK_MANIP_", "").partition("_")[0] for key in os.environ
for key in os.environ.keys() if key.startswith("KODAK_MANIP_")
if key.startswith("KODAK_MANIP_")
]
) )
manips = [ManipConfig.from_env(name) for name in manip_names]
return cls( return cls(
sourcedir=_get_path("KODAK_SOURCEDIR", cls.sourcedir), source_dir=_get_path("KODAK_SOURCE_DIR", cls.source_dir),
manipdir=_get_path("KODAK_MANIPDIR", cls.manipdir), content_dir=_get_path("KODAK_CONTENT_DIR", cls.content_dir),
expose_source=_get_bool("KODAK_EXPOSE_SOURCE", cls.expose_source), expose_source=_get_bool("KODAK_EXPOSE_SOURCE", cls.expose_source),
private=_get_bool("KODAK_PRIVATE", cls.private), 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: def load() -> KodakConfig:
"""Load the application configuration from environment variables
:returns: Populated environment configuration
"""
try: try:
return KodakConfig.from_env() return KodakConfig.from_env()
except (ValueError, TypeError, IndexError, KeyError) as err: except (ValueError, TypeError, IndexError, KeyError) as err:

View File

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