+ self.jinja = JinjaEnv(loader=JinjaFSLoader(TEMPLATES_DIR))
+
+
+class ParamsParser:
+ """Wrapper for validating and retrieving GET params."""
+
+ def __init__(self, params: dict[str, list[str]]) -> None:
+ self.params = params
+
+ def get_str(self, key: str, default: str = '') -> str:
+ """Retrieve string value of key from self.params."""
+ if key not in self.params or 0 == len(self.params[key]):
+ return default
+ return self.params[key][0]
+
+ def get_int_or_none(self, key: str) -> int | None:
+ """Retrieve int value of key from self.params, on empty return None."""
+ if key not in self.params or \
+ 0 == len(''.join(list(self.params[key]))):
+ return None
+ val_str = self.params[key][0]
+ try:
+ return int(val_str)
+ except ValueError as e:
+ raise BadFormatException(f'Bad ?{key}= value: {val_str}') from e
+
+
+class PostvarsParser:
+ """Postvars wrapper for validating and retrieving form data."""
+
+ def __init__(self, postvars: dict[str, list[str]]) -> None:
+ self.postvars = postvars
+
+ def get_str(self, key: str) -> str:
+ """Retrieve string value of key from self.postvars."""
+ all_str = self.get_all_str(key)
+ if 0 == len(all_str):
+ raise BadFormatException(f'missing value for key: {key}')
+ return all_str[0]
+
+ def get_int(self, key: str) -> int:
+ """Retrieve int value of key from self.postvars."""
+ val = self.get_str(key)
+ try:
+ return int(val)
+ except ValueError as e:
+ msg = f'cannot int form field value: {val}'
+ raise BadFormatException(msg) from e
+
+ def get_int_or_none(self, key: str) -> int | None:
+ """Retrieve int value of key from self.postvars, or None."""
+ if key not in self.postvars or \
+ 0 == len(''.join(list(self.postvars[key]))):
+ return None
+ return self.get_int(key)
+
+ def get_float(self, key: str) -> float:
+ """Retrieve float value of key from self.postvars."""
+ val = self.get_str(key)
+ try:
+ return float(val)
+ except ValueError as e:
+ msg = f'cannot float form field value: {val}'
+ raise BadFormatException(msg) from e
+
+ def get_all_str(self, key: str) -> list[str]:
+ """Retrieve list of string values at key from self.postvars."""
+ if key not in self.postvars:
+ return []
+ return self.postvars[key]
+
+ def get_all_int(self, key: str) -> list[int]:
+ """Retrieve list of int values at key from self.postvars."""
+ all_str = self.get_all_str(key)
+ try:
+ return [int(s) for s in all_str if len(s) > 0]
+ except ValueError as e:
+ msg = f'cannot int a form field value: {all_str}'
+ raise BadFormatException(msg) from e