import inspect
import executing
import types
import sys

__version__ = "1.0.5"


def vardict(*args, **kwargs):
    if len(args) == 0:
        return dict(kwargs)

    frame = real_caller_frame()
    call_node = executing.Source.executing(frame).node
    if call_node is None:
        raise ValueError("could not determine variables")
    source = executing.Source.for_frame(frame)
    result = {}
    for node, right in zip(call_node.args, args):
        left = source.asttokens().get_text(node)
        if not left.isidentifier():
            raise ValueError(f"{left!r} not a valid identifier")
        if left in kwargs:
            raise ValueError(f"parameter {left!r} repeated")
        result[left] = right
    return result | kwargs

def real_caller_frame():
    # this will return the frame of the first frame on the stack that does not belong to this module,
    # so in the 'user' space
    frame = inspect.currentframe()
    frame_name = frame.f_globals.get('__name__')
    frame=frame.f_back                
    while frame is not None and frame_name == frame.f_globals.get('__name__'):                  
        frame = frame.f_back    
    return frame

class _vardictModule(types.ModuleType):
    def __call__(self, *args, **kwargs):
        return vardict(*args, **kwargs)


if __name__ != "__main__":
    sys.modules["vardict"].__class__ = _vardictModule

