1
0
mirror of https://github.com/enpaul/keyosk.git synced 2025-04-21 10:03:29 +00:00
keyosk/keyosk/config/storage.py
Ethan Paul 07828f0063 Refactor datatypes into submodules
Gonna do some composition up in here
Add py38 tox env
2020-02-25 22:28:45 -05:00

171 lines
5.3 KiB
Python

"""Data containers and utilities related to the storage configuration"""
import enum
from dataclasses import asdict
from dataclasses import dataclass
from dataclasses import field
from pathlib import Path
from typing import Any
from typing import Dict
from typing import Mapping
from typing import Optional
from typing import Union
import marshmallow as msh
from keyosk import fields as custom_fields
@enum.unique
class StorageBackend(enum.Enum):
"""Supported storage backends"""
SQLITE = "sqlite"
MARIA = "maria"
def _default_sqlite_pragmas() -> Dict[str, Any]:
"""Generate the default pragmas for the sqlite connection
Default are taken from
`here <http://docs.peewee-orm.com/en/latest/peewee/database.html#recommended-settings>`_
"""
return {
"journal_mode": "wal",
"cache_size": -1 * 64000,
"foreign_keys": 1,
"ignore_check_constraints": 0,
"synchronous": 0,
}
@dataclass
class KeyoskSQLiteStorageConfig:
"""Config data container for the SQLite config options
:param path: Path to the SQLite database file
:param pragmas: Mapping of SQLite pragmas to apply to the database connection
"""
path: Path = Path("/usr/share/keyosk.db")
pragmas: Mapping[str, Any] = field(default_factory=_default_sqlite_pragmas)
class SQLiteStorageConfigSerializer(msh.Schema):
"""De/serializer for the SQLite configuration parameters
Fields on this class map 1:1 with the dataclass parameters on the
:class:`KeyoskSQLiteStorageConfig` class.
"""
path = custom_fields.PathString()
pragmas = msh.fields.Dict(keys=msh.fields.String(), values=msh.fields.Raw())
# pylint: disable=unused-argument,no-self-use
@msh.post_load
def _make_dataclass(self, data: Mapping[str, Any], *args, **kwargs):
return KeyoskSQLiteStorageConfig(**data)
@msh.pre_dump
def _unmake_dataclass(
self, data: Union[Mapping[str, Any], KeyoskSQLiteStorageConfig], *args, **kwargs
):
if isinstance(data, KeyoskSQLiteStorageConfig):
return asdict(data)
return data
@dataclass
class KeyoskMariaStorageConfig:
"""Config data container for the MariaDB config options
:param schema: Database schema to use
:param host: IP address or hostname of the database server to connect to
:param port: Port to connect to the database server on
:param username: Username for connecting to the database server
:param password: Password for the user account to use for connecting to the database
server
.. note:: The MySQL driver treats the hosts ``localhost`` and ``127.0.0.1``
differently: using ``localhost`` will cause the client to always attempt
to use a socket connection, while ``127.0.0.1`` will cause the client to
always attempt to use a TCP connection.
"""
schema: str = "keyosk"
host: str = "localhost"
port: int = 3306
username: str = "keyosk"
password: Optional[str] = None
class MariaStorageConfigSerializer(msh.Schema):
"""De/serializer for the MariaDB configuration parameters
Fields on this class map 1:1 with the dataclass parameters on the
:class:`KeyoskMariaStorageConfig` class.
"""
schema = msh.fields.String()
host = msh.fields.String()
port = msh.fields.Integer(validate=msh.validate.Range(min=1, max=65535))
username = msh.fields.String()
password = msh.fields.String(allow_none=True)
# pylint: disable=unused-argument,no-self-use
@msh.post_load
def _make_dataclass(self, data: Mapping[str, Any], *args, **kwargs):
return KeyoskMariaStorageConfig(**data)
@msh.pre_dump
def _unmake_dataclass(
self, data: Union[Mapping[str, Any], KeyoskMariaStorageConfig], *args, **kwargs
):
if isinstance(data, KeyoskMariaStorageConfig):
return asdict(data)
return data
@dataclass
class KeyoskStorageConfig:
"""Config data container for storage related parameters
:param backend: The backend database system the application should use
:param sqlite: Configuration parameters for the SQLite backend
:param maria: Configuration parameters for the MariaDB backend
.. note:: Only one of the ``sqlite`` or ``maria`` parameters will be used at any one
time, depending on the value of the ``backend`` setting.
"""
backend: StorageBackend = StorageBackend.SQLITE
sqlite: KeyoskSQLiteStorageConfig = KeyoskSQLiteStorageConfig()
maria: KeyoskMariaStorageConfig = KeyoskMariaStorageConfig()
class StorageConfigSerializer(msh.Schema):
"""De/serializer for the storage configuration parameters
Fields on this class map 1:1 with the dataclass parameters on the
:class:`KeyoskStorageConfig` class.
"""
backend = custom_fields.EnumItem(StorageBackend, pretty_names=True)
sqlite = msh.fields.Nested(SQLiteStorageConfigSerializer)
maria = msh.fields.Nested(MariaStorageConfigSerializer)
# pylint: disable=unused-argument,no-self-use
@msh.post_load
def _make_dataclass(self, data: Mapping[str, Any], *args, **kwargs):
return KeyoskStorageConfig(**data)
@msh.pre_dump
def _unmake_dataclass(
self, data: Union[Mapping[str, Any], KeyoskStorageConfig], *args, **kwargs
):
if isinstance(data, KeyoskStorageConfig):
return asdict(data)
return data