4

I need to write a python script that read and parse setup python file. setup contain some variables and function calls.

example:

setup.py
x = 5
mylist [ 1, 2, 3]
myfunc(4)
myfunc(5)
myfunc(30)


main.py
.
parse_setup('setup.py')
.

I would like parse the setup file and "see" what kind of variables were defined and what kind of function calls. since the setup file in written in python, I was thinking that the easiest thing would be to dynamically import the setup file (dynamically because setup file path is the input for main).

the problem is that import fails since myfucn(), called in setup.py, is not defined.

is there a way for me to intercept the myfunc() calls in setup.py and execute my own function defined in main.py?

what if the function I want to execute is a member function?

can anyone think of a better way for extracting the data in the setup file, I really don't want to read it line by line.

Thanks!

dnlcrl
  • 5,022
  • 3
  • 32
  • 40
idanshmu
  • 5,061
  • 6
  • 46
  • 92
  • How does the setup run at all, if myfunc() is not defined? If you just want nice configuration in python script format, refactor the functions to be used by the config out in a separate module and import that from within the setup. – Jonas Schäfer Nov 04 '12 at 15:27
  • If it's not a valid python file (i.e. running it gets an exception) then you won't be able to `import`. You can however [read](http://stackoverflow.com/a/6475407/1240268) it like any other text file? – Andy Hayden Nov 04 '12 at 15:43
  • this is exactly what I wish to avoid. setup.py is actually a text file to be filled by the user. The reason setup file is in python language is because it is continent to define variables and function "calls". myfunc() is just a description of an operation the user wish main.py to perform. – idanshmu Nov 04 '12 at 15:49
  • thank you all for the quick response. martineau answer worked for me. thanks again. – idanshmu Nov 04 '12 at 16:18

2 Answers2

1

If your setup.py file contained these Python statements:

x = 5
mylist = [ 1, 2, 3]
y = myfunc(4)
z = myfunc(x)

You could do something like this in main.py to find out what it defined:

def myfunc(n):
    return n**2

def parse_setup(filename):
    globalsdict = {'__builtins__': None, 'myfunc': myfunc}  # put predefined things here
    localsdict = {}  # will be populated by executed script
    execfile(filename, globalsdict, localsdict)
    return localsdict

results = parse_setup('setup.py')
print results  # {'y': 16, 'x': 5, 'z': 25, 'mylist': [1, 2, 3]}
martineau
  • 119,623
  • 25
  • 170
  • 301
  • I just want to add, @user1798187, that you're having a huge security breach here. A user could easily social-engineer another user into running a config doing a localroot or an ``rm -rf ~``. – Jonas Schäfer Nov 05 '12 at 17:09
  • @Jonas Wielicki: To address your concerns I have added a `'__builtins__': None` entry to the globals dictionary's definition to prevent Python from automatically adding a reference to the standard `__builtin__` module it would otherwise do -- which greatly diminishes the security issue by exercising more control over the context in which the setup file is executed. Doing so means that all of the possibly destructive built-ins that Python has, notably `__import__`, will **not** be available to the script to use for nefarious purposes. – martineau Nov 05 '12 at 18:48
  • Since this script is an internal one I don't think I should be worrying about that BUT as long that we are on the subject can you elaborate what exactly do you mean by that? can you give an example for a vicious setup.py file? – idanshmu Nov 06 '12 at 05:19
  • @user1798187: Off the top of my head: It could `import` the `os` module and use `os.remove()` or `os.removedirs()` to delete things. It could use the `urllib2` module to access the Internet and download unsavory things or upload personal information. @Jonas Wielicki may have a better examples. – martineau Nov 06 '12 at 11:05
  • You cannot sandbox python totally. Good example [over there](http://stackoverflow.com/q/11951701/1248008). – Jonas Schäfer Nov 06 '12 at 14:44
  • (sorry for comment spam, but I felt like adding, that the impossiblity of sandboxing is more rooted in the implementation of CPython than in python itself. [pypy for example supports sandboxing](http://pypy.org/features.html#sandboxing) by marshalling all syscalls) – Jonas Schäfer Nov 06 '12 at 15:20
  • @Jonas Wielicki: As user1798187 pointed out, security is not a big concern for every Python application. I've been using something like this in a personal utility for many years and couldn't care less about the issue with regards to it. – martineau Nov 06 '12 at 15:24
  • @martineau: Agreed – I just want to point such things out, because if someone stumbles across this question, y'know. – Jonas Schäfer Nov 07 '12 at 14:03
  • Another alternative which might be even simpler would be to just `import setup`. Things the module defines could be accessed with `setup.x`, `setup.mylist`, etc. Such a `setup.py` module could itself `import` something else that had the definition of `myfunc()` in it. – martineau Nov 10 '12 at 18:53
0

If the setup.py file is valid python you can use execfile() or import().

execfile is close to what you seem to be looking for.

setup.py

def function(): print "called"

main.py

execfile("setup.py")
function() # will print called

http://docs.python.org/2/library/functions.html#execfile

After reading again your question a better example may be:

setup.py

func("one")
func("two")

main.py

def func(s): print s
execfile("setup.py") 
# will print:
# one
# two

Note that the file loading have to be done after the functions have been defined.

iagorubio
  • 111
  • 6
  • setup.py does not defined any function. it just "call" the function. actually, setup.py can be thought of as a text file to be provided to the user. user is not familiar with python. he uses main.py to firstly generate a template setup.py file, then he fills this file with the data he wants. I need to extract this data and find out how did the user intended to activate main.py. – idanshmu Nov 04 '12 at 15:43
  • thank you for the quick response. martineau answer worked for me. I wasn't able to try you solution but thank you anyway. – idanshmu Nov 04 '12 at 16:18