quality: fix type confusion + mypy not actually checking the functions because of the is_unit_operation decorator, which requires typing wizardry to understan the signature change

This commit is contained in:
Alexandre Aubin 2024-08-15 19:29:12 +02:00
parent efce7f9f05
commit fe1c04fb2c
2 changed files with 17 additions and 19 deletions

View file

@ -388,12 +388,17 @@ def log_show(
def log_share(path):
return log_show(path, share=True)
from typing import TypeVar, Callable, Concatenate, ParamSpec
#FuncT = TypeVar("FuncT", bound=Callable[..., Any])
Param = ParamSpec("Param")
RetType = TypeVar("RetType")
def is_unit_operation(
entities=["app", "domain", "group", "service", "user"],
exclude=["password"],
operation_key=None,
):
entities = ["app", "domain", "group", "service", "user"],
exclude = ["password"],
) -> Callable[[Callable[Concatenate["OperationLogger", Param], RetType]], Callable[Param, RetType]]:
"""
Configure quickly a unit operation
@ -410,17 +415,10 @@ def is_unit_operation(
called 'password' are removed. If an argument is an object, you need to
exclude it or create manually the unit operation without this decorator.
operation_key A key to describe the unit operation log used to create the
filename and search a translation. Please ensure that this key prefixed by
'log_' is present in locales/en.json otherwise it won't be translatable.
"""
def decorate(func):
def decorate(func: Callable[Concatenate["OperationLogger", Param], RetType]) -> Callable[Param, RetType]:
def func_wrapper(*args, **kwargs):
op_key = operation_key
if op_key is None:
op_key = func.__name__
# If the function is called directly from an other part of the code
# and not by the moulinette framework, we need to complete kwargs
@ -471,7 +469,7 @@ def is_unit_operation(
context[field] = value.name
except Exception:
context[field] = "IOBase"
operation_logger = OperationLogger(op_key, related_to, args=context)
operation_logger = OperationLogger(func.__name__, related_to, args=context)
try:
# Start the actual function, and give the unit operation

View file

@ -234,7 +234,7 @@ def user_create(
uid_guid_found = False
while not uid_guid_found:
# LXC uid number is limited to 65536 by default
uid = str(random.randint(1001, 65000))
uid: str = str(random.randint(1001, 65000))
uid_guid_found = uid not in all_uid and uid not in all_gid
if not loginShell:
@ -931,7 +931,7 @@ def user_import(operation_logger: "OperationLogger", csvfile: TextIO, update: bo
user["username"],
user["domain"],
user["password"],
user["mailbox-quota"],
mailbox_quota=user["mailbox-quota"],
from_import=True,
fullname=(user["firstname"] + " " + user["lastname"]).strip(),
)
@ -1008,7 +1008,7 @@ def user_group_list(full: bool = False, include_primary_groups: bool = True) ->
@is_unit_operation([("groupname", "group")])
def user_group_create(
operation_logger: "OperationLogger", groupname: str, gid: Optional[int] = None, primary_group: bool = False, sync_perm: bool = True
operation_logger: "OperationLogger", groupname: str, gid: Optional[str] = None, primary_group: bool = False, sync_perm: bool = True
) -> dict[str, str]:
"""
Create group
@ -1044,17 +1044,17 @@ def user_group_create(
if not gid:
# Get random GID
all_gid = {x.gr_gid for x in grp.getgrall()}
all_gid = {str(x.gr_gid) for x in grp.getgrall()}
uid_guid_found = False
while not uid_guid_found:
gid = random.randint(200, 99999)
gid = str(random.randint(200, 99999))
uid_guid_found = gid not in all_gid
attr_dict = {
"objectClass": ["top", "groupOfNamesYnh", "posixGroup"],
"cn": groupname,
"gidNumber": gid,
"gidNumber": [gid],
}
# Here we handle the creation of a primary group