I can add multiple tabs

This commit is contained in:
2025-11-14 22:32:26 +01:00
parent 7ff8b3ea14
commit 93f6da66a5
9 changed files with 452 additions and 164 deletions

View File

@@ -223,116 +223,15 @@ def debug_session(session):
return session.get("user_info", {}).get("email", "** UNKNOWN USER **")
import inspect
from typing import Optional
def build_args_kwargs(
parameters,
values,
default_args: Optional[list] = None,
default_kwargs: Optional[dict] = None
):
"""
Build (args, kwargs) from a sequence or dict of inspect.Parameter and a dict of values.
- POSITIONAL_ONLY and POSITIONAL_OR_KEYWORD fill `args`
- KEYWORD_ONLY fill `kwargs`
- VAR_POSITIONAL (*args) accepts list/tuple values
- VAR_KEYWORD (**kwargs) accepts dict values
- If not found, fallback to default_args / default_kwargs when provided
- Raises ValueError for missing required or unknown parameters
"""
if not isinstance(parameters, dict):
parameters = {p.name: p for p in parameters}
ordered_params = list(parameters.values())
has_var_positional = any(p.kind == inspect.Parameter.VAR_POSITIONAL for p in ordered_params)
has_var_keyword = any(p.kind == inspect.Parameter.VAR_KEYWORD for p in ordered_params)
args = []
kwargs = {}
consumed_names = set()
default_args = default_args or []
default_kwargs = default_kwargs or {}
# 1 Handle positional parameters
positional_params = [
p for p in ordered_params
if p.kind in (inspect.Parameter.POSITIONAL_ONLY, inspect.Parameter.POSITIONAL_OR_KEYWORD)
]
for i, p in enumerate(positional_params):
if p.name in values:
args.append(values[p.name])
consumed_names.add(p.name)
elif i < len(default_args):
args.append(default_args[i])
elif p.default is not inspect.Parameter.empty:
args.append(p.default)
else:
raise ValueError(f"Missing required positional argument: {p.name}")
# 2 Handle *args
for p in ordered_params:
if p.kind == inspect.Parameter.VAR_POSITIONAL:
if p.name in values:
val = values[p.name]
if not isinstance(val, (list, tuple)):
raise ValueError(f"*{p.name} must be a list or tuple, got {type(val).__name__}")
args.extend(val)
consumed_names.add(p.name)
elif len(default_args) > len(positional_params):
# Add any remaining default_args beyond fixed positionals
args.extend(default_args[len(positional_params):])
# 3 Handle keyword-only parameters
for p in ordered_params:
if p.kind == inspect.Parameter.KEYWORD_ONLY:
if p.name in values:
kwargs[p.name] = values[p.name]
consumed_names.add(p.name)
elif p.name in default_kwargs:
kwargs[p.name] = default_kwargs[p.name]
elif p.default is not inspect.Parameter.empty:
kwargs[p.name] = p.default
else:
raise ValueError(f"Missing required keyword-only argument: {p.name}")
# 4 Handle **kwargs
for p in ordered_params:
if p.kind == inspect.Parameter.VAR_KEYWORD:
if p.name in values:
val = values[p.name]
if not isinstance(val, dict):
raise ValueError(f"**{p.name} must be a dict, got {type(val).__name__}")
kwargs.update(val)
consumed_names.add(p.name)
# Merge any unmatched names if **kwargs exists
remaining = {
k: v for k, v in values.items()
if k not in consumed_names and k not in parameters
}
# Also merge default_kwargs not used yet
for k, v in default_kwargs.items():
if k not in kwargs:
kwargs[k] = v
kwargs.update(remaining)
break
# 5 Handle unknown / unexpected parameters (if no **kwargs)
if not has_var_keyword:
unexpected = [k for k in values if k not in consumed_names and k in parameters]
if unexpected:
raise ValueError(f"Unexpected parameters: {unexpected}")
extra = [k for k in values if k not in consumed_names and k not in parameters]
if extra:
raise ValueError(f"Unknown parameters: {extra}")
return args, kwargs
def get_id(obj):
if isinstance(obj, str):
return obj
elif hasattr(obj, "id"):
return obj.id
elif hasattr(obj, "get_id"):
return obj.get_id()
else:
return str(obj)
@utils_rt(Routes.Commands)