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

Cannot use env vars from within functions #22

Open
aksdb opened this issue Jul 1, 2019 · 2 comments
Open

Cannot use env vars from within functions #22

aksdb opened this issue Jul 1, 2019 · 2 comments

Comments

@aksdb
Copy link

aksdb commented Jul 1, 2019

Example:

###env
base_url = 'http://localhost:8080'
session_id = 'myid'

def apicall(path):
	return "{}{};jsessid={}".format(base_url, path, session_id)
###env

# Profile
get(apicall("/api/foo"))

The call fails because base_url and session_id are empty in the defined function. Declaring them nonlocal doesn't help. How can this be accomplished without duplicating the constants?

@kylebebak
Copy link
Owner

kylebebak commented Jul 5, 2019

Hey there! So, I dug in a little and found that the first request fails, but the second doesn't. The first one fails because the env dict Requester creates to be used in the actual calls to requests doesn't form a closure for apicall.

In other words, apicall doesn't have access to variables defined in its enclosing scope, such as base_url and session_id.

And yes, this is counter-intuitive because you wouldn't run into this limitation if you pasted this code into the Python interpreter and ran it.

I'm not sure if there's a way to change the code that creates the env dict to ensure that closures are created for functions such as apicall... I'm looking into it.

###env
base_url = 'http://localhost:8080'
session_id = 'myid'

def apicall(path):
  return "{}{}?jsessid={}".format(base_url, path, session_id)

def _apicall(path):
  return "http://localhost:8080{}?jsessid=myid".format(path)
###env

# Profile
get(apicall("/api/foo"))

get(_apicall("/api/foo"))

@kylebebak
Copy link
Owner

kylebebak commented Jul 5, 2019

So, this works just fine.

###env
def caller(path):
  def call():
    return "http://localhost:8080{}?jsessid=myid".format(path)
  return call

###env

# Profile
get(caller("/api/foo")())

Which means the env parsing code can create closures for functions as long as the variables they're referencing aren't assigned in the "top-level".

I'm not sure I can fix this. It requires deeper knowledge of the imp module, exec and closures than I currently have.

My suggestion is to do something like the following:

###env
def apicall(path):
  return "{}{}?jsessid={}".format('http://localhost:8080', path, 'myid')
###env

get(apicall("/api/foo"))

Or, equivalently, but more verbose and weird:

###env
base_url = 'http://localhost:8080'
session_id = 'myid'

def apicall(base_url, path, session_id):
  return "{}{}?jsessid={}".format(base_url, path, session_id)
###env

get(apicall(base_url, "/api/foo", session_id))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants