Settings loader update with basic email check, and on check abort if not valid

In the settings checker, if a regex_clean is set as None then we will abort the script with error
if the regex is not matching

Add regex check for email basic

Also add a regex_constants list with regex entries (not compiled and compiled)
This commit is contained in:
Clemens Schwaighofer
2025-07-14 15:57:19 +09:00
parent 7183d05dd6
commit 6c2637ad34
8 changed files with 79 additions and 16 deletions

View File

@@ -0,0 +1,10 @@
"""
List of regex compiled strings that can be used
"""
EMAIL_REGEX_BASIC = r"""
^[A-Za-z0-9!#$%&'*+\-\/=?^_`{|}~][A-Za-z0-9!#$%:\(\)&'*+\-\/=?^_`{|}~\.]{0,63}
@(?!-)[A-Za-z0-9-]{1,63}(?<!-)(?:\.[A-Za-z0-9-]{1,63}(?<!-))*\.[a-zA-Z]{2,6}$
"""
# __END__

View File

@@ -52,15 +52,17 @@ class SettingsLoader:
# entries that have to be split
self.entry_split_char: dict[str, str] = {}
self.entry_convert: dict[str, str] = {}
# config parser
# config parser, load config file first
self.config_parser: configparser.ConfigParser | None = self.__load_config_file()
# all settings
self.settings: dict[str, dict[str, Any]] | None = None
# remove file name and get base path and check
if not self.config_file.parent.is_dir():
raise ValueError(f"Cannot find the config folder: {self.config_file.parent}")
# load the config file before we parse anything
# for check settings, abort flag
self._check_settings_abort: bool = False
# MARK: load settings
def load_settings(self, config_id: str, config_validate: dict[str, list[str]]) -> dict[str, str]:
"""
neutral settings loader
@@ -184,6 +186,8 @@ class SettingsLoader:
settings[config_id][entry] = self.__check_settings(
check, entry, settings[config_id][entry]
)
if self._check_settings_abort is True:
error = True
elif check.startswith("matching:"):
checks = check.replace("matching:", "").split("|")
if __result := is_list_in_list(convert_to_list(settings[config_id][entry]), list(checks)):
@@ -253,6 +257,7 @@ class SettingsLoader:
return settings[config_id]
# MARK: build from/to/requal logic
def __build_from_to_equal(
self, entry: str, check: str, convert_to_int: bool = False
) -> Tuple[float | None, float | None, float | None]:
@@ -306,6 +311,7 @@ class SettingsLoader:
__equal
)
# MARK: length/range validation
def __length_range_validate(
self,
entry: str,
@@ -347,6 +353,7 @@ class SettingsLoader:
continue
return valid
# MARK: load config file data from file
def __load_config_file(self) -> configparser.ConfigParser | None:
"""
load and parse the config file
@@ -358,13 +365,14 @@ class SettingsLoader:
return config
return None
# MARK: regex clean up one
def __clean_invalid_setting(
self,
entry: str,
validate: str,
value: str,
regex: str,
regex_clean: str,
regex_clean: str | None,
replace: str = "",
print_error: bool = True,
) -> str:
@@ -380,18 +388,24 @@ class SettingsLoader:
replace (str): replace with character. Defaults to ''
print_error (bool): print the error message. Defaults to True
"""
check = re.compile(regex)
clean = re.compile(regex_clean)
check = re.compile(regex, re.VERBOSE)
clean: re.Pattern[str] | None = None
if regex_clean is not None:
clean = re.compile(regex_clean, re.VERBOSE)
if not check.search(value):
self.__print(
f"[!] Invalid content for '{entry}' with check '{validate}' and data: {value}",
'ERROR', print_error
)
# clean up
return clean.sub(replace, value)
# clean up if clean up is not none, else return EMPTY string
if clean is not None:
return clean.sub(replace, value)
self._check_settings_abort = True
return ''
# else return as is
return value
# MARK: check settings, regx
def __check_settings(
self,
check: str, entry: str, setting_value: list[str] | str
@@ -439,6 +453,7 @@ class SettingsLoader:
# return data
return setting_value
# MARK: check arguments, for config file load fail
def __check_arguments(self, arguments: dict[str, list[str]], all_set: bool = False) -> bool:
"""
check if ast least one argument is set
@@ -468,6 +483,7 @@ class SettingsLoader:
return has_argument
# MARK: get argument from args dict
def __get_arg(self, entry: str) -> Any:
"""
check if an argument entry xists, if None -> returns None else value of argument
@@ -482,6 +498,7 @@ class SettingsLoader:
return None
return self.args.get(entry)
# MARK: error print
def __print(self, msg: str, level: str, print_error: bool = True, raise_exception: bool = False):
"""
print out error, if Log class is set then print to log instead

View File

@@ -3,12 +3,15 @@ Class of checks that can be run on value entries
"""
from typing import TypedDict
from corelibs.check_handling.regex_compiled_constants import EMAIL_REGEX_BASIC
class SettingsLoaderCheckValue(TypedDict):
"""Settings check entries"""
regex: str
regex_clean: str
# if None, then on error we exit, eles we clean up data
regex_clean: str | None
replace: str
@@ -16,29 +19,37 @@ class SettingsLoaderCheck:
"""
check:<NAME> or check:list+<NAME>
"""
CHECK_SETTINGS: dict[str, SettingsLoaderCheckValue] = {
"int": {
"regex": r"^[0-9]+$",
"regex_clean": r"[^0-9]",
"replace": ""
"replace": "",
},
"string.alphanumeric": {
"regex": r"^[a-zA-Z0-9]+$",
"regex_clean": r"[^a-zA-Z0-9]",
"replace": ""
"replace": "",
},
"string.alphanumeric.lower.dash": {
"regex": r"^[a-z0-9-]+$",
"regex_clean": r"[^a-z0-9-]",
"replace": ""
"replace": "",
},
# A-Z a-z 0-9 _ - . ONLY
# This one does not remove, but replaces with _
"string.alphanumeric.extended.replace": {
"regex": r"^[_.a-zA-Z0-9-]+$",
"regex_clean": r"[^_.a-zA-Z0-9-]",
"replace": "_"
"replace": "_",
},
# This does a baisc email check, only alphanumeric with special characters
"string.email.basic": {
"regex": EMAIL_REGEX_BASIC,
"regex_clean": None,
"replace": "",
},
}
# __END__