#wip(py): In Developt
This commit is contained in:
parent
d3b0b4de72
commit
5cdd592aab
193
Python/v2/ErrorsManager.py
Normal file
193
Python/v2/ErrorsManager.py
Normal file
@ -0,0 +1,193 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from typing import Self, Any, Optional, Sequence
|
||||
from math import log2
|
||||
from re import compile as re_compile, Pattern as REPattern, IGNORECASE as RE_IGNORE_CASE
|
||||
|
||||
class ErrorsManager:
|
||||
|
||||
RE_KEY:REPattern = re_compile(r'^[a-z_][a-z0-9_]*$', RE_IGNORE_CASE)
|
||||
|
||||
def __init__(self:Self, inputs:Optional[str|dict[str, Any|None]|Sequence[Any|None]] = None) -> None:
|
||||
|
||||
alphabet:str|Sequence[str] = self.unique(self.get_value("alphabet", (
|
||||
inputs := {"alphabet" : inputs} if isinstance(inputs, str) else
|
||||
inputs), "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="))
|
||||
maximum_base:int = int(log2(len(alphabet)))
|
||||
|
||||
self.__alphabet:tuple[str] = (
|
||||
tuple(alphabet) if isinstance(alphabet, (list, str)) else
|
||||
alphabet)
|
||||
self.__alphabet_dictionary:dict[str, int] = {character : i for i, character in enumerate(self.__alphabet)}
|
||||
self.__base:int = self.get_value("base", inputs, maximum_base)
|
||||
self.__mask:int
|
||||
|
||||
if self.__base > maximum_base:
|
||||
self.__base = maximum_base
|
||||
self.__mask = ~-(1 << self.__base)
|
||||
|
||||
print([self.__mask, self.__base, self.__alphabet])
|
||||
|
||||
def to_string(self:Self, code:str|int|Sequence[int]) -> str:
|
||||
if isinstance(code, str):
|
||||
return code
|
||||
if isinstance(code, (list, tuple)):
|
||||
return "".join([self.__alphabet[hexa] for hexa in code])
|
||||
if isinstance(code, int):
|
||||
|
||||
string:str = ""
|
||||
|
||||
while code:
|
||||
string = self.__alphabet[code & self.__mask] + string
|
||||
code >>= self.__base
|
||||
|
||||
return string
|
||||
return ""
|
||||
|
||||
def to_integer(self:Self, code:str|int|Sequence[int]) -> int:
|
||||
if isinstance(code, str):
|
||||
|
||||
integer:int = 0
|
||||
hexa:str
|
||||
|
||||
for i, hexa in enumerate(reversed(code)):
|
||||
integer |= self.__alphabet_dictionary[hexa] << self.__base * i
|
||||
|
||||
return integer
|
||||
if isinstance(code, (list, tuple)):
|
||||
|
||||
integer:int = 0
|
||||
hexa:int
|
||||
|
||||
for i, hexa in enumerate(reversed(code)):
|
||||
integer |= hexa << self.__base * i
|
||||
|
||||
return integer
|
||||
if isinstance(code, int):
|
||||
return code
|
||||
return 0
|
||||
|
||||
def to_array(self:Self, code:str|int|Sequence[int]) -> list[int]:
|
||||
if isinstance(code, str):
|
||||
return [self.__alphabet_dictionary[hexa] for hexa in code]
|
||||
if isinstance(code, list):
|
||||
return list(code)
|
||||
if isinstance(code, tuple):
|
||||
return code
|
||||
if isinstance(code, int):
|
||||
|
||||
array:list[int] = []
|
||||
|
||||
while code:
|
||||
array.append(code & self.__mask)
|
||||
code >>= self.__base
|
||||
|
||||
return list(reversed(array))
|
||||
return []
|
||||
|
||||
def reset(self:Self, code:int, start:int, length:int) -> int:
|
||||
return code and (code & ~(~-(1 << length) << start))
|
||||
|
||||
def set(self:Self, code:int, map:Sequence[int], codes:Sequence[int], start:int = 0, clean_bits:int = 0) -> int:
|
||||
|
||||
new_code:int = 0
|
||||
shift:int = 0
|
||||
block:int
|
||||
i:int
|
||||
|
||||
code = self.reset(code, start, clean_bits)
|
||||
|
||||
for i, block in enumerate(map):
|
||||
new_code |= (codes[i] or (code >> start + shift & ~-(1 << block))) << shift
|
||||
shift += block
|
||||
|
||||
return (
|
||||
(code & ~-(1 << start)) |
|
||||
(new_code << start) |
|
||||
# ((code >> start + shift) << start + shift)
|
||||
(code & ~(~-(1 << start + shift)))
|
||||
)
|
||||
|
||||
def validate(self:Self,
|
||||
code:int,
|
||||
map:Sequence[int],
|
||||
messages:Sequence[Sequence[str]] = []
|
||||
) -> tuple[tuple[int, str]]:
|
||||
|
||||
errors:list[tuple[int, str]] = []
|
||||
|
||||
if code:
|
||||
|
||||
shift:int = 0
|
||||
l:int = len(messages)
|
||||
i:int
|
||||
block:int
|
||||
|
||||
for i, block in enumerate(map):
|
||||
|
||||
subcode:int = (code >> shift) & ~-(1 << block)
|
||||
|
||||
shift += block
|
||||
subcode and errors.append((i, (
|
||||
messages[i][subcode - 1] if i < l and subcode - 1 < len(messages[i]) else
|
||||
"error_" + str(i) + "_" + str(subcode))))
|
||||
|
||||
return len(errors) != 0, tuple(errors)
|
||||
|
||||
@classmethod
|
||||
def get_keys(cls:type[Self], *items:Sequence[Any|None]) -> list[str]:
|
||||
|
||||
keys:list[str] = []
|
||||
item:Any|None
|
||||
|
||||
for item in items:
|
||||
if isinstance(item, str):
|
||||
cls.RE_KEY.match(item) and keys.append(item)
|
||||
elif isinstance(item, (list, tuple)):
|
||||
keys.extend(cls.get_keys(*item))
|
||||
|
||||
return keys
|
||||
|
||||
@classmethod
|
||||
def get_dictionaries(cls:type[Self], *items:Sequence[Any|None]) -> list[dict[str, Any|None]]:
|
||||
|
||||
dictionaries:list[str] = []
|
||||
item:Any|None
|
||||
|
||||
for item in items:
|
||||
if isinstance(item, dict):
|
||||
dictionaries.append(item)
|
||||
elif isinstance(item, (list, tuple)):
|
||||
dictionaries.extend(cls.get_dictionaries(*item))
|
||||
|
||||
return dictionaries
|
||||
|
||||
@classmethod
|
||||
def get_value(cls:type[Self],
|
||||
keys:str|Sequence[str],
|
||||
inputs:dict[str, Any|None]|Sequence[Any|None],
|
||||
default:Optional[Any] = None
|
||||
) -> Any|None:
|
||||
if len(keys := cls.get_keys(keys)):
|
||||
|
||||
subinputs:dict[str, Any|None]
|
||||
|
||||
for subinputs in cls.get_dictionaries(inputs):
|
||||
|
||||
key:str
|
||||
|
||||
for key in keys:
|
||||
if key in subinputs:
|
||||
return subinputs[key]
|
||||
return default
|
||||
|
||||
@staticmethod
|
||||
def unique(items:str|Sequence[Any|None]) -> str|Sequence[Any|None]:
|
||||
if isinstance(items, str):
|
||||
return "".join(character for i, character in enumerate(items) if items.index(character) == i)
|
||||
if isinstance(items, tuple):
|
||||
return tuple(item for i, item in enumerate(items) if items.index(item) == i)
|
||||
if isinstance(items, list):
|
||||
return [item for i, item in enumerate(items) if items.index(item) == i]
|
||||
return items
|
||||
48
Python/v2/tests.py
Normal file
48
Python/v2/tests.py
Normal file
@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from ErrorsManager import ErrorsManager
|
||||
|
||||
class Tests:
|
||||
|
||||
@staticmethod
|
||||
def builder() -> None:
|
||||
print(ErrorsManager())
|
||||
|
||||
@staticmethod
|
||||
def conversions() -> None:
|
||||
|
||||
option:str|int|list[int]
|
||||
errors:ErrorsManager = ErrorsManager()
|
||||
|
||||
for option in (
|
||||
"Hola", 923452, [45, 2, 0, 12]
|
||||
):
|
||||
|
||||
string:str = errors.to_string(option)
|
||||
integer:int = errors.to_integer(option)
|
||||
array:list[int] = errors.to_array(option)
|
||||
|
||||
print(option)
|
||||
print(["T", {
|
||||
"s" : string,
|
||||
"i" : integer,
|
||||
"a" : array
|
||||
}])
|
||||
print(["S", {
|
||||
"s" : errors.to_string(string),
|
||||
"i" : errors.to_integer(string),
|
||||
"a" : errors.to_array(string)
|
||||
}])
|
||||
print(["I", {
|
||||
"s" : errors.to_string(integer),
|
||||
"i" : errors.to_integer(integer),
|
||||
"a" : errors.to_array(integer)
|
||||
}])
|
||||
print(["A", {
|
||||
"s" : errors.to_string(array),
|
||||
"i" : errors.to_integer(array),
|
||||
"a" : errors.to_array(array)
|
||||
}])
|
||||
|
||||
Tests.conversions()
|
||||
Loading…
Reference in New Issue
Block a user