Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

some cases of argname don't know how to deal #95

Closed
wulidongdong opened this issue Apr 7, 2023 · 2 comments
Closed

some cases of argname don't know how to deal #95

wulidongdong opened this issue Apr 7, 2023 · 2 comments
Labels
question Further information is requested

Comments

@wulidongdong
Copy link

Hi Devs,

I got some dumb questions when I using argname. I would like to know if the following two cases can be achieved:
First, I defined a class and three variables:


def test(a=None, b=None, c=None):
    return argname('b')

x = [[111]]
y = [[222]]
z = [x, y]

The first question is how to know when calling a function that one of the variables is a list.

That is, when I call it like this:
test(a=x,b=z,c=y)
I expect the return result of the current function to be
'[x,y]'
but the return result of the current function is
'z'
I tried to call
test(a=x,b=[x,y],c=y)
but it reports an error.

    498 source = argument_sources[farg_name]
    499 if isinstance(source, ast.AST):
--> 500     raise ImproperUseError(
    501         f"Argument {ast.dump(source)} is not a variable "
    502         "or an attribute."
    503     )
    505 if isinstance(farg_subscript, int) and not isinstance(source, tuple):
    506     raise ImproperUseError(
    507         f"`{farg_name}` is not a positional argument."
    508     )

ImproperUseError: Argument List(elts=[Name(id='x', ctx=Load()), Name(id='y', ctx=Load())], ctx=Load()) is not a variable or an attribute.

The second problem is that using argname and exec at the same time seems to report an error. For example, executing

test_str = 'test(a=x,b=z,c=y)'
exec(test_str)

will report an error:

    439 # Only do it when func_node are available
    440 if not func_node:
    441     # We can do something at bytecode level, when a single positional
    442     # argument passed to both functions (argname and the target function)
    443     # However, it's hard to ensure that there is only a single positional
    444     # arguments passed to the target function, at bytecode level.
--> 445     raise VarnameRetrievingError(
    446         "Cannot retrieve the node where the function is called."
    447     )
    449 func_node = reconstruct_func_node(func_node)
    451 if not func:

VarnameRetrievingError: Cannot retrieve the node where the function is called.

Can the above two problems be solved? Thank you for your time

@wulidongdong
Copy link
Author

I have read other issues, it seems to be solved by wrapper.

from varname.helpers import Wrapper

def test(a=None, b=None, c=None):
    for i in b:
        print(i.name, i.value)

x = Wrapper([[111]])
y = Wrapper([[222]])
z = [x, y]
test(a=x,b=z,c=y) # x [[111]] y[[222]]

and exec can work!

test_str = 'test(a=x,b=z,c=y)'
exec(test_str) # x [[111]] y[[222]]

cool, although I do not know why it can work

@pwwang
Copy link
Owner

pwwang commented Apr 7, 2023

Remember that argname() gets what directly pass to the function. So test(a=x,b=z,c=y) is supposed to return 'z'. To get [x,y] for test(a=x,b=[x,y],c=y), you need:

def test(a=None, b=None, c=None):
    return argname('b', vars_only=False)

exec('test(a=x,b=[x,y],c=y)') won't work because we are not able to retrieve the source/AST at runtime.


The solution you posted later does not use the source/AST when test is called (because you don't call argname inside). If you did mean argname, then test(a=x,b=z,c=y) should return z. Anyway, it is a good solution if it meets your need.

@pwwang pwwang added the question Further information is requested label Apr 7, 2023
@pwwang pwwang closed this as completed Apr 10, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants