SimpleSallap:SimpleProxy:DataClass Config - P3

Add a helper base class to try map data class's attributes into
underlying dict.

TODO: this potentially duplicates data in both normal attribute
space as well as dict items space. And will require additional
standard helper logics to be overridden to ensure sync between
both space etal. Rather given distance from python internals for
a long time now, on pausing and thinking a bit, better to move
into a simpler arch where attributes are directly worked on for
dict [] style access.
This commit is contained in:
hanishkvc 2025-12-05 20:47:33 +05:30
parent 5560840099
commit 4f790cb646
2 changed files with 28 additions and 14 deletions

View File

@ -2,7 +2,7 @@
# by Humans for All # by Humans for All
# #
from dataclasses import dataclass, field from dataclasses import dataclass, field, fields
from typing import Any, Optional from typing import Any, Optional
import http.server import http.server
import ssl import ssl
@ -11,11 +11,25 @@ import urlvalidator as mUV
import debug as mDebug import debug as mDebug
gConfigNeeded = [ 'acl.schemes', 'acl.domains', 'sec.bearer' ] gConfigNeeded = [ 'acl.schemes', 'acl.domains', 'sec.bearerAuth' ]
@dataclass
class DictDataclassMixin(dict):
"""
Mixin to ensure dataclass attributes get mapped as dict keys in __post_init__
"""
def __post_init__(self):
"""
Skip if already set using maybe say dict init mechanism or ...
"""
for f in fields(self):
if f.name not in self:
self[f.name] = getattr(self, f.name)
@dataclass(frozen=True) @dataclass
class Sec(dict): class Sec(DictDataclassMixin, dict):
""" """
Used to store security related config entries Used to store security related config entries
""" """
@ -24,17 +38,17 @@ class Sec(dict):
bearerAuth: str = "" bearerAuth: str = ""
@dataclass @dataclass
class ACL(dict): class ACL(DictDataclassMixin, dict):
schemes: Optional[list[str]] = None schemes: list[str] = field(default_factory=list)
domains: list[str] = field(default_factory=list) domains: list[str] = field(default_factory=list)
@dataclass @dataclass
class Network(dict): class Network(DictDataclassMixin, dict):
port: int = 3128 port: int = 3128
addr: str = '' addr: str = ''
@dataclass @dataclass
class Op(dict): class Op(DictDataclassMixin, dict):
configFile: str = "/dev/null" configFile: str = "/dev/null"
debug: bool = False debug: bool = False
server: http.server.ThreadingHTTPServer|None = None server: http.server.ThreadingHTTPServer|None = None
@ -43,7 +57,7 @@ class Op(dict):
bearerTransformedYear: str = "" bearerTransformedYear: str = ""
@dataclass @dataclass
class Config(dict): class Config(DictDataclassMixin, dict):
op: Op = field(default_factory=Op) op: Op = field(default_factory=Op)
sec: Sec = field(default_factory=Sec) sec: Sec = field(default_factory=Sec)
acl: ACL = field(default_factory=ACL) acl: ACL = field(default_factory=ACL)
@ -104,7 +118,7 @@ class Config(dict):
exit(112) exit(112)
self.set_value(cfg, gotValue) self.set_value(cfg, gotValue)
except KeyError: except KeyError:
print(f"ERRR:LoadConfig:{cfg}:UnknownCommand") print(f"ERRR:LoadConfig:{cfg}:UnknownConfig!")
exit(113) exit(113)
def process_args(self, args: list[str]): def process_args(self, args: list[str]):
@ -142,7 +156,7 @@ class Config(dict):
if cArg == 'op.configFile': if cArg == 'op.configFile':
self.load_config(aValue) self.load_config(aValue)
except KeyError: except KeyError:
print(f"ERRR:ProcessArgs:{iArg}:{cArg}:UnknownCommand:{sys.exception()}") print(f"ERRR:ProcessArgs:{iArg}:{cArg}:UnknownArgCommand!:{sys.exception()}")
exit(103) exit(103)
print(self) print(self)
self.validate() self.validate()

View File

@ -1,10 +1,10 @@
{ {
"allowed.schemes": [ "acl.schemes": [
"file", "file",
"http", "http",
"https" "https"
], ],
"allowed.domains": [ "acl.domains": [
".*\\.wikipedia\\.org$", ".*\\.wikipedia\\.org$",
".*\\.bing\\.com$", ".*\\.bing\\.com$",
"^www\\.bing\\.com$", "^www\\.bing\\.com$",
@ -51,5 +51,5 @@
"^github\\.com$", "^github\\.com$",
".*\\.github\\.com$" ".*\\.github\\.com$"
], ],
"bearer.insecure": "NeverSecure" "sec.bearerAuth": "NeverSecure"
} }