

import re
import pkgutil

sys.setrecursionlimit(100000)


try:
    import cPickle as pickle
except:
    import pickle

def strify(inp, rt=False):
    pick=False
    _inp = inp
    t = type(inp)
    if t == list or t == tuple:
        g =[]
        for b in inp:
            g.append(strify(b))
        _inp = g
        if t == tuple:
            _inp = tuple(g)
    else:
        if t == dict:
            g = {}
            for b in inp:
                g[strify(b)] = strify(inp[b])
            _inp = g
        else:
            if t != int and t != float and t != str:
                try:
                    _inp = pickle.dumps(inp)
                    pick=True
                except:
                    _inp = "unfetchable"
    try:
        v = re.findall(r"\[(.*)\]", str([_inp]), flags=re.DOTALL)[0]
        if pick:
            v = "pickle.loads(%s)"%v
        if not rt:
            if t == str:
                v = v[1:-1]
        return v
    except:
        return "''"

class buildProxy:
    
    def __init__(self, inp):
        _inp = inp
        self._mods=[]
        self._imps = []
        if type(inp) == str:
            exec("import %s"%inp)
            _inp = eval(inp)
        self.r="try:\n\timport cPickle as pickle\nexcept:\n\timport pickle\n\n"
        self.r+=self(_inp,0)
    
    def _impModule(self, inp, depth):
        r=""
        try:
            for p,d,f in pkgutil.iter_modules(inp.__path__, inp.__name__+"."):
                try:
                    r += self(p.load_module(d), depth)
                except:
                    try:
                        exec("import %s"%d)
                        r += self(eval(d), depth)
                    except:
                        pass
        except:
            pass                        
        return r
    
    def __call__(self, inp, depth):
        if inp in self._mods:
            return ""
        self._mods.append(inp)
        if "." in inp.__name__:
            snam = inp.__name__.rsplit(".", 1)[1]
        else:
            snam = inp.__name__
        print "Loading: "+inp.__name__
        r = "%sclass %s:\n"%("\t"*depth, snam)
        r += "%sdef __init__(self, *args, **kwargs):\n%spass\n"%("\t"*(depth+1), "\t"*(depth+2))
        for k in sorted(inp.__dict__.keys()):
            if len(re.findall("__(.+)__", k)) > 0:
                continue
            o = inp.__dict__[k]
            typ = type(o).__name__
            if "module" in typ:
                """
                try:
                    r += "%s%s=%s\n"%("\t"*(depth+1), k, o.__name__)
                    if o.__name__ not in self._imps:
                        self._imps.append(o.__name__)
                    continue
                except:
                    pass
                """
                continue
            if "function" in typ:
                r+= "%sdef %s(self, *args, **kwargs):\n%spass\n"%("\t"*(depth+1), k, "\t"*(depth+2))
                continue
            if "method" in typ:
                r+= "%sdef %s(self, *args, **kwargs):\n%spass\n"%("\t"*(depth+1), k, "\t"*(depth+2))
                continue
            if "class" in typ or "type" in typ:
                try:
                    r+=self(o, depth+1)
                    continue
                except:
                    pass
            r+="%s%s=%s\n"%("\t"*(depth+1), k, strify(o, True))
        r+=self._impModule(inp, depth+1)
        return r
        
    def gets(self):
        r=""
        for im in self._imps:
            #r += "try:\n\timport %s\nexcept:\n\tpass\n\n"%im
            pass
        return r+self.r



def BuildProxies(outdir, modules):
	for m in modules:
		prox = buildProxy(m).gets()
		f = open(outdir+"/"+m+".py","wb")
		f.write(prox)
		f.close()
	print "ALL DONE!"










# Change output directory to where you want it to write out the proxy modules
OUT_DIR = "/tmp/"

# Nuke = ["nuke","nukscripts"]
# Houdini = ["hou"]
# Maya = ["maya"]

MODULES = ["maya"]

try:
	os.makedirs(OUT_DIR)
except:
	pass

BuildProxies(OUT_DIR, MODULES)


