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

executing #3

Closed
alexmojaki opened this issue Apr 19, 2020 · 10 comments
Closed

executing #3

alexmojaki opened this issue Apr 19, 2020 · 10 comments

Comments

@alexmojaki
Copy link
Collaborator

Just letting you know that magically detecting the call has been done more robustly in executing and building on that is sorcery which has functions that do the kind of thing varname does.

@pwwang
Copy link
Owner

pwwang commented Apr 19, 2020

Thanks, but can you provide an example of how the variable names are retrieved using those packages?

@pwwang
Copy link
Owner

pwwang commented Apr 19, 2020

Ohh, did you mean the way to retrieve the frame information using executing, instead of I parse it by myself? Good idea, but let us see if it is worthy since the package has no dependencies now.

@pwwang
Copy link
Owner

pwwang commented Apr 19, 2020

Well, I have read the codes you mentioned. I still don't get any ways to retrieve something like:

def func():
   print("I am called and returned to variable: ", varname())

x = func()
# I am called and returned to variable x

Or you just meant what I said in the above post?

@pwwang
Copy link
Owner

pwwang commented Apr 19, 2020

This looks very like it:

    Instead of:
        class Thing(Enum):
            foo = 'foo'
            bar = 'bar'
    write:
        class Thing(Enum):
            foo, bar = assigned_names()

But the variables have to be defined inside class/function. Let me think about it.

@alexmojaki
Copy link
Collaborator Author

import sorcery


@sorcery.spell
def func(frame_info):
    (name,), assign_node = frame_info.assigned_names(allow_one=True)
    print("I am called and returned to variable:", name)


x = func()

@pwwang
Copy link
Owner

pwwang commented Apr 19, 2020

Looks like I can write my own spell to implement it using your library?

@alexmojaki
Copy link
Collaborator Author

I don't think you can write a function with the same API as varname() using sorcery, but you can do it with executing. In any case:

Note: previously spells had a complicated implementation that placed limitations on how they could be called. Now spells are just a thin wrapper around executing which is much better. You may be better off using executing directly depending on your use case. This repo is now mostly just a fun collection of things to do with it.

Here's a rough implementation:

import ast

import executing
import sys


def varname(caller=0):
    ex = executing.Source.executing(sys._getframe(caller + 1))
    node = ex.node
    if not node:
        return "var1"  # etc

    while hasattr(node, 'parent'):
        node = node.parent

        if isinstance(node, ast.Assign):
            # Need to actually check that there's just one
            target = node.targets[0]

            # Need to check that it's a variable
            return target.id


def function():
    # I know that at which stack this will be called
    return varname(caller=3)


def function1():
    return function()


def function2():
    return function1()


func = function2()
print(func)

x = varname()
print(x)

@pwwang
Copy link
Owner

pwwang commented Apr 19, 2020

WOW! This is awesome! I can see a couple of limitations/issues that the current package has that can be potentially solved by this. For example, calling from alias functions, getting rid of the context thing and more reliably get the name using executing/ast.

I will take a very close look at this, thank you so much!

@pwwang
Copy link
Owner

pwwang commented Apr 20, 2020

Introduced in v0.1.0

@pwwang pwwang closed this as completed Apr 20, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants