home *** CD-ROM | disk | FTP | other *** search
/ Enter 2004 April / enter-2004-04.iso / files / EVE_1424_100181.exe / nasty.py < prev    next >
Encoding:
Python Source  |  2004-04-20  |  40.7 KB  |  1,105 lines

  1. ##########################################################################################
  2. ## ///////////////////////////////////////////////////////////////////////////////////////
  3. ## //
  4. ## //   nasty.py
  5. ## //
  6. ## //   Authors:   Eggert J≤n Magn·sson, Matthφas Gu≡mundsson
  7. ## //   Created:   November 2001
  8. ## //   Project:   EVE
  9. ## //
  10. ## //   Description:
  11. ## //
  12. ## //      Nasty, the managed-object system.
  13. ## //
  14. ## //   Dependencies:
  15. ## //
  16. ## //      None
  17. ## //
  18. ## //   (c) CCP 2001
  19. ## //
  20. ## //
  21.  
  22. import log
  23. import types
  24. import blue
  25. import sys
  26. sysold = sys
  27. import imp
  28. from stackless import getcurrent
  29. import copy
  30. import weakref
  31. import tokenize
  32.  
  33. #########################################################################################
  34. ## //////////////////////////////////////////////////////////////////////////////////////
  35. ## //
  36. ## //   Class NamespaceFailedException
  37. ## //
  38. ## //   Raised when exceptions
  39. ## //
  40. ## //
  41.  
  42.  
  43.  
  44. class NamespaceFailedException(Exception):
  45.     __guid__ = 'exceptions.NamespaceFailed'
  46.     __persistvars__ = ['args']
  47.     def __init__(self,*args):
  48.         self.args = args
  49.     def __repr__(self):
  50.         return 'NamespaceFailed: The namespace '+self.args[0]+' was not found.'
  51. NamespaceFailedException.__module__ = 'exceptions'
  52.  
  53.  
  54. #########################################################################################
  55. ## //////////////////////////////////////////////////////////////////////////////////////
  56. ## //
  57. ## //   Class NamespaceAttributeFailedException
  58. ## //
  59. ## //   Does stuff yah!!
  60. ## //
  61. ## //
  62.  
  63. class NamespaceAttributeFailedException(NamespaceFailedException):
  64.     __guid__ = 'exceptions.NamespaceAttributeFailed'
  65.     __persistvars__ = ['args']
  66.     def __repr__(self):
  67.         return 'NamespaceAttributeFailed: The namespace member '+self.args[0]+'.'+self.args[1]+' was not found.'
  68.  
  69. NamespaceAttributeFailedException.__module__ = 'exceptions'
  70.  
  71.  
  72.  
  73. class Namespace:
  74.     def __init__(self,name,space):
  75.         self.__dict__['name'] = name
  76.         self.__dict__["space"] = space
  77.     def __getattr__(self,attr):
  78.         if self.space.has_key(attr):
  79.             return self.space[attr]
  80.         else:
  81.             raise AttributeError, (attr, self.space) #NamespaceAttributeFailedException,(self.name,str(attr))
  82.     def __setattr__(self,attr):
  83.         raise NamespaceAttributeFailedException,(self.name,str(attr))
  84.  
  85.  
  86. #########################################################################################
  87. ## //////////////////////////////////////////////////////////////////////////////////////
  88. ## //
  89. ## //   Class Nasty
  90. ## //
  91. ## //   Does stuff yah!!
  92. ## //
  93. ## //
  94.  
  95. # -----------------------------------------------------------------------------------
  96. '''
  97.     The UTLS for the main dude.
  98.  
  99.  
  100.     LocalStorage is actually "session local storage" as currently used, with thread
  101.         inheritance
  102.  
  103.     PrivateStorage is thread local storage, without inheritance.
  104. '''
  105.  
  106. # -----------------------------------------------------------------------------------
  107. mainPrivateStorage = {}
  108.  
  109. # -----------------------------------------------------------------------------------
  110. def GetPrivateStorage():
  111.     '''
  112.         Gets the uthread private storage, whether this is the main tasklet or a taskletext
  113.     '''
  114.     t = getcurrent()
  115.     if not hasattr(t,"privateStorage"):
  116.         global mainPrivateStorage
  117.         return mainPrivateStorage
  118.     else:
  119.         if t.privateStorage is None:
  120.             t.privateStorage = {}
  121.         return t.privateStorage
  122.  
  123. # -----------------------------------------------------------------------------------
  124. def GetLocalStorage():
  125.     '''
  126.         Gets the uthread local storage, whether this is the main tasklet or a taskletext
  127.     '''
  128.     t = getcurrent()
  129.  
  130.     if not hasattr(t,"localStorage"):
  131.         return mainLocalStorage
  132.     else:
  133.         if t.localStorage is None:
  134.             t.localStorage = {}
  135.         return t.localStorage
  136.  
  137. # -----------------------------------------------------------------------------------
  138. def GetOtherLocalStorage(t):
  139.     '''
  140.         Gets the uthread local storage for t, whether this is the main tasklet or a taskletext
  141.     '''
  142.     if not hasattr(t,"localStorage"):
  143.         return mainLocalStorage
  144.     else:
  145.         if t.localStorage is None:
  146.             t.localStorage = {}
  147.         return t.localStorage
  148.  
  149. # -----------------------------------------------------------------------------------
  150. def SetLocalStorage(s):
  151.     '''
  152.         Sets the uthread local storage, whether this is the main tasklet or a taskletext
  153.     '''
  154.     t = getcurrent()
  155.  
  156.     if not hasattr(t,"localStorage"):
  157.         global mainLocalStorage
  158.         mainLocalStorage = s
  159.     else:
  160.         t.localStorage = s
  161.  
  162. # -----------------------------------------------------------------------------------
  163. def UpdateLocalStorage(props):
  164.     '''
  165.         Adds the given properties to the local storage, and returns the storage that
  166.         you should restore to.
  167.     '''
  168.     ls = GetLocalStorage()
  169.     ret = ls
  170.     ls = copy.copy(ls)
  171.     ls.update(props)
  172.     SetLocalStorage(ls)
  173.     return ret
  174.  
  175. # -----------------------------------------------------------------------------------
  176. class Sissy:
  177.     '''
  178.         A Sissy is a wrapper for a uthread local storage object, kept in builtins,
  179.         that forwards all the appropriate stuff to an internal object.
  180.     '''
  181.  
  182.     def __init__(self,what):
  183.         self.__dict__["__sissywhat__"] = what
  184.  
  185.     def __nonzero__(self):
  186.         try:
  187.             sissy = GetLocalStorage().get(self.__sissywhat__,None)
  188.             if (sissy is not None) and (type(sissy)!=types.StringType):
  189.                 sissy = sissy()
  190.         except ReferenceError:
  191.             sissy = None
  192.         return sissy is not None
  193.  
  194.     def __str__(self):
  195.         try:
  196.             sissy = GetLocalStorage().get(self.__sissywhat__,None)
  197.             if (sissy is not None) and (type(sissy)!=types.StringType):
  198.                 sissy = sissy()
  199.         except ReferenceError:
  200.             sissy = None
  201.         return 'Sissy:'+str(sissy)
  202.  
  203.     def __repr__(self):
  204.         return self.__str__()
  205.  
  206.     def __getattr__(self,k):
  207.         if self.__dict__.has_key(k):
  208.             return self.__dict__[k]
  209.         # if the internal object is None, we want to raise the same as getattr(None,k) would anyway.
  210.         try:
  211.             sissy = GetLocalStorage().get(self.__sissywhat__,None)
  212.             if (sissy is not None) and (type(sissy)!=types.StringType):
  213.                 sissy = sissy()
  214.         except ReferenceError:
  215.             sissy = None
  216.         return getattr(sissy, k)
  217.  
  218.     def __setattr__(self,k,v):
  219.         try:
  220.             sissy = GetLocalStorage().get(self.__sissywhat__,None)
  221.             if (sissy is not None) and (type(sissy)!=types.StringType):
  222.                 sissy = sissy()
  223.         except ReferenceError:
  224.             sissy = None
  225.         setattr(sissy, k, v)
  226.  
  227. class Nasty:
  228.     # -----------------------------------------------------------------------------------
  229.     # Nasty - Constructor
  230.     # -----------------------------------------------------------------------------------
  231.     def __init__(self):
  232.  
  233.         self.compiledCode = {}
  234.         self.loadeddlls = []
  235.  
  236.         # const replacement
  237.         self.constants = None
  238.  
  239.         import __builtin__
  240.  
  241.         if hasattr(__builtin__, "Using"):
  242.             raise "Only one instance of nasty can be running, i.e. only load nasty.py once"
  243.         __builtin__.Import = self.Import
  244.         __builtin__.Using = self.Using
  245.         __builtin__.GetPrivateStorage = GetPrivateStorage
  246.         __builtin__.GetLocalStorage = GetLocalStorage
  247.         __builtin__.GetOtherLocalStorage = GetOtherLocalStorage
  248.         __builtin__.SetLocalStorage = SetLocalStorage
  249.         __builtin__.UpdateLocalStorage = UpdateLocalStorage
  250.         __builtin__.RecompileFile = self.RecompileFile
  251.  
  252.         blue.pyos.AddExitProc(self.Release)
  253.  
  254.         self.lastModified = 0 #blue.os.GetTime()
  255.         blue.pyos.SpyDirectory("script:/", self.OnFileModified)
  256.  
  257.         self.waiting = {}
  258.         self.files = {}
  259.         self.namespaces = {"exceptions":{"NamespaceFailed":NamespaceFailedException,"NamespaceAttributeFailed":NamespaceAttributeFailedException}}
  260.         self.globs = {}
  261.         self.preloads = {}
  262.         self.mods = {}
  263.         __builtin__.Sissy    = Sissy
  264.         __builtin__.mainLocalStorage = {}
  265.         __builtin__.charsession = Sissy("base.charsession")
  266.         __builtin__.currentcall = Sissy("base.currentcall")
  267.         __builtin__.session     = Sissy("base.session")
  268.         __builtin__.caller      = Sissy("base.caller")
  269.         self.__fallbackimport__ = __builtin__.__import__
  270.         __builtin__.__import__ = self.ImportBackwards
  271.         __builtin__.Using = self.Using
  272.         __builtin__.Import = self.Import
  273.         __builtin__.CreateInstance = self.CreateInstance
  274.         __builtin__.RegisterConstant = self.RegisterConstant
  275.  
  276.         # Guard against reetrancy to OnFileModified
  277.         self.willCheckModifieds = 0
  278.  
  279.         # Blue MUST be in the namespace and Uthread MUST be loaded,
  280.         # or runner.py will go nuts in case of any error. If service
  281.         # is ommitted here, everything will also go haywire.
  282.         self.Run(["blue.dll"])
  283.  
  284.         self.Run(["script:/common/sys/uthread.py"])
  285.         self.Run(["script:/common/sys/service.py"])
  286.  
  287.  
  288.     def ImportBackwards(self,name, glob=None, loc=None, fromlist=None):
  289.         if not self.mods.has_key(name):
  290.             if self.namespaces.has_key(name):
  291. #            ret = self.Import(name)
  292.                 haveOldModule = 0
  293.                 try:
  294.                     self.mods[name] = imp.new_module(name)
  295.                     if name+'.dll' not in self.loadeddlls:
  296.                         ret1 = self.__fallbackimport__(name,glob,loc,fromlist)
  297.                     else:
  298.                         ret1 = imp.new_module(name) #dll loading import! what's up with that ?
  299.                     #print 'name',ret1
  300.                     self.mods[name] = ret1
  301.                     haveOldModule = 1
  302.                 except ImportError,e:
  303.                     #print 'Importing',name,'failed'
  304.                     ret1 = imp.new_module(name)
  305.     #                self.mods[name] = ret1
  306.                 try:
  307.                     ret = self.Import(name,0)
  308.                     for i in ret.space.iterkeys():
  309.                         if i != '__class__': #grumble, NetClient exposes this?
  310.                             setattr(ret1,i,getattr(ret,i))
  311.  
  312.     #
  313.                 except ImportError,e:
  314.                     if not haveOldModule:
  315.                         raise
  316.  
  317.                 self.mods[name] = ret1
  318.         if self.mods.has_key(name):
  319.             return self.mods[name]
  320.  
  321.         return self.__fallbackimport__(name,glob,loc,fromlist)
  322.  
  323.     # -----------------------------------------------------------------------------------
  324.     # Initialize
  325.     # -----------------------------------------------------------------------------------
  326.     def Initialize(self):
  327.         now = blue.os.GetTime(1)
  328.         files = self.BrowseScriptFile("script:/")
  329.  
  330.         # We'll recompile everything if any .py file is newer than
  331.         # the compiled.code file.
  332.         codefile = blue.os.CreateInstance("blue.ResFile")
  333.         check = blue.os.CreateInstance("blue.ResFile")
  334.         recompile = 1
  335.         codedate = None
  336.  
  337.         args = blue.pyos.GetArg()
  338.  
  339.         for each in args:
  340.             if each.startswith("/wait"):
  341.                 blue.pyos.synchro.Sleep(1000 * int(each[6:]))
  342.  
  343.         if ("/recompile" not in args) and (codefile.Open("script:/compiled.code") and codefile.size > 0):
  344.             modified = codefile.GetFileInfo()["ftLastWriteTime"]
  345.             codedate = blue.os.FormatUTC(modified)
  346.             recompile = 0
  347.  
  348.             # Enumerate all python files
  349.             for file in files:
  350.                 if file.find("uthread.py") != -1:
  351.                     continue
  352.                 if file.find("service.py") != -1:
  353.                     continue
  354.                 if check.Open(file) and check.GetFileInfo()["ftLastWriteTime"] >= modified:
  355.                     recompile = 1
  356.                     new = blue.os.FormatUTC(check.GetFileInfo()["ftLastWriteTime"])
  357.                     print "Rebuilding code file from %s %s, %s is dated %s %s" % (codedate[0], codedate[2], file, new[0], new[2])
  358.                     break
  359.  
  360.             del check
  361.  
  362.             if not recompile:
  363.                 import cPickle
  364.                 from marshal import loads
  365.                 datain = cPickle.loads(str(codefile.Read()))
  366.                 for k, v in datain:
  367.                     self.compiledCode[k] = loads(v)
  368.  
  369.         codefile.Close()
  370.  
  371.         if not recompile:
  372.             print "Using compiled code from %s %s" % (codedate[0], codedate[2])
  373.         else:
  374.             constfile = blue.os.CreateInstance("blue.ResFile")
  375.             if constfile.Open("script:/constants.marshal"):
  376.                 self.constants = blue.marshal.Load(constfile.Read())
  377.             else:
  378.                 self.constants = None
  379.  
  380.         self.Run(files)
  381.         self.lastModified = blue.os.GetTime()
  382.  
  383.         if recompile:
  384.             import cPickle
  385.             out = blue.os.CreateInstance("blue.ResFile")
  386.             out.Create("script:/compiled.code")
  387.  
  388.             # Need to marshal pickle the code objects
  389.             from marshal import dumps
  390.             dataout = []
  391.  
  392.             for k, v in self.compiledCode.iteritems():
  393.                 dataout.append((k, dumps(v)))
  394.  
  395.             out.Write(cPickle.dumps(dataout, 1))
  396.  
  397.         self.constants = None
  398.         print "Code initialized in %.2f sec." % (float(blue.os.GetTime(1) - now) / 10000000.0, )
  399.  
  400.         if "/compile" in blue.pyos.GetArg():
  401.             rot = blue.os.CreateInstance("blue.Rot")
  402.             report = blue.os.CreateInstance("blue.ResFile")
  403.             report.Create(blue.os.rootpath + "../codefiles.txt")
  404.  
  405.             for name in self.compiledCode.iterkeys():
  406.                 if name.find("uthread.py") != -1:
  407.                     continue
  408.                 if name.find("service.py") != -1:
  409.                     continue
  410.                 name = rot.PathToFilename(name)
  411.                 name = name.replace("/", "\\")
  412.                 report.Write(name + "\r\n")
  413.             del report
  414.  
  415.             blue.pyos.Quit("Quitting after compile-only run.")
  416.  
  417.  
  418.  
  419.     # -----------------------------------------------------------------------------------
  420.     # OnFileModified
  421.     # -----------------------------------------------------------------------------------
  422.     def OnFileModified(self):
  423.         if self.willCheckModifieds:
  424.             return
  425.  
  426.         self.willCheckModifieds = 1
  427.         Import("uthread")
  428.         uthread.new(self.OnFileModified_)
  429.  
  430.     def OnFileModified_(self):
  431.  
  432.         try:
  433.             # Give files chance to write completely to disk
  434.             blue.pyos.synchro.Sleep(550)
  435.             fl = []
  436.  
  437.             for each in self.files.itervalues():
  438.                 if each not in fl and each[-3:] == '.py':
  439.                     fl.append(each)
  440.             x = blue.os.CreateInstance('blue.ResFile')
  441.             lm = 0
  442.             files = []
  443.             now = blue.os.GetTime()
  444.  
  445.             for each in fl:
  446.                 x.OpenAlways(each)
  447.                 ftLast = x.GetFileInfo()['ftLastWriteTime']
  448.                 if ftLast > now:
  449.                     # File from the future - very mysterious
  450.                     print "File from the future detected. It might scew up my auto-compile feature."
  451.                     print "    ", blue.os.FormatUTC(ftLast)[0], blue.os.FormatUTC(ftLast)[2], each
  452.  
  453.                 if ftLast > self.lastModified:
  454.                     print 'Change detected in file',each,'reloading classes'
  455.                     files.append(each)
  456.                     # Without this check, after a syntax error, this del fails everytime the
  457.                     # file is modified.
  458.                     if self.compiledCode.has_key(each):
  459.                         del self.compiledCode[each]
  460.                     lm = max(ftLast,lm)
  461.  
  462.  
  463.             guids = self.GatherFileGuids()
  464.             servicesToReload = []
  465.             for each in files:
  466.                 for guid in guids[each]:
  467.                     if len(guid) > 4 and guid[:4] == 'svc.':
  468.                         servicesToReload.append(guid[4:])
  469.  
  470.             self.Run(files,1)
  471.             import __builtin__
  472.             if hasattr(__builtin__,'sm'):
  473.                 sm.Reload(servicesToReload)
  474.             import linecache
  475.             linecache.clearcache()
  476.             self.lastModified = max(lm,self.lastModified)
  477.         finally:
  478.             self.willCheckModifieds = 0
  479.  
  480.     # -----------------------------------------------------------------------------------
  481.     # ReloadFile
  482.     # -----------------------------------------------------------------------------------
  483.     def RecompileFile(self, fileName):
  484.         '''
  485.             Reloads the specified file.  Filename should be script:/ based, f.ex.
  486.             script:/util/format.py
  487.         '''
  488.         print 'Recompiling ',fileName
  489.         if fileName in self.compiledCode:
  490.             del self.compiledCode[fileName]
  491.         guids = self.GatherFileGuids()
  492.         servicesToReload = []
  493.         if fileName in guids:
  494.             for guid in guids[fileName]:
  495.                 if len(guid) > 4 and guid[:4] == 'svc.':
  496.                     servicesToReload.append(guid[4:])
  497.         self.Run([fileName],1)
  498.         import __builtin__
  499.         if hasattr(__builtin__,'sm'):
  500.             sm.Reload(servicesToReload)
  501.         import linecache
  502.         linecache.clearcache()
  503.  
  504.     # -----------------------------------------------------------------------------------
  505.     # BrowseScriptFile
  506.     # -----------------------------------------------------------------------------------
  507.     def BrowseScriptFile(self, directory):
  508.         files = []
  509.         file = blue.os.CreateInstance("blue.ResFile")
  510.         filename = directory + "index.txt"
  511.  
  512.         if not file.Open(filename):
  513.             return []
  514.  
  515.         lines = str(file.Read()).split("\r\n")
  516.         filecount = 0
  517.         dircount = 0
  518.  
  519.         for line in lines:
  520.             if len(line) and line[0] != ' ' and line[0] != '#':
  521.                 #print "candidate:",line
  522.                 if line[-1] == '/':
  523.                     # directory
  524.                     dircount = dircount + 1
  525.                     files = files + self.BrowseScriptFile(directory + line)
  526.                 else:
  527.                     # a file, hopefully
  528.                     if line[-3:] == ".py":
  529.                         filecount = filecount + 1
  530.                         files.append(directory + line)
  531.         return files
  532.  
  533.         print "%s (%d files, %d directories)" % (filename, filecount, dircount)
  534.  
  535.  
  536.     # -----------------------------------------------------------------------------------
  537.     # ExtractClassfiles
  538.     # -----------------------------------------------------------------------------------
  539.     def ExtractClassfiles(self):
  540.         for guid, filename in self.files.iteritems():
  541.             print 'Guid: ',guid,'Filename:',filename
  542.  
  543.  
  544.     # -----------------------------------------------------------------------------------
  545.     # Run
  546.     # -----------------------------------------------------------------------------------
  547.     def Run(self,filesToScan,fromReload = 0):
  548.         #print 'Scanning %d files' % (len(filesToScan), )
  549.         unsuccessful = list(filesToScan[:])
  550.  
  551.         stacktrace = 0
  552.         while len(unsuccessful):
  553.             resolveFailures = {}
  554.             files = unsuccessful[:]
  555.             removed = 0
  556.             for each in files:
  557.  
  558.                 try:
  559. #                    if each[-3:]=='dll':
  560. #                        print 'browsing class file',each
  561.                     self.BrowseClassFile(each,0,fromReload)
  562.                     #print "Loading", each
  563.                     unsuccessful.remove(each)
  564.                     removed = 1
  565.                 except ImportError,val:
  566.                     if stacktrace:
  567.                         StackTrace()
  568.                     if not resolveFailures.has_key(each):
  569.                         resolveFailures[each]= [(val,None)]
  570.                     else:
  571.                         resolveFailures[each].append((val,None))
  572.                     #print 'Namespace lookup failed in file "%s" for namespace "%s"'%(each,val)
  573.                 except AttributeError,val:
  574.                     if stacktrace:
  575.                         StackTrace()
  576.                     if not resolveFailures.has_key(each):
  577.                         resolveFailures[each]= [val]
  578.                     else:
  579.                         resolveFailures[each].append(val)
  580.                 except:
  581.                     StackTrace()
  582.                     unsuccessful.remove(each) #we don't want to run this file again.
  583.                     raise
  584.  
  585.             if removed == 0:
  586.                 if stacktrace==0:
  587.                     import log
  588.                     log.general.Log("All hope lost while loading  '%s'"%each, log.fatal)
  589.                     stacktrace = 1
  590.                 else:
  591.                     for filename in unsuccessful:
  592.                         log.general.Log("Failed loading file %s"%filename,log.fatal)
  593.                     raise RuntimeError("ResolutionFailure")
  594.  
  595.     # -----------------------------------------------------------------------------------
  596.     # ReloadClass
  597.     # -----------------------------------------------------------------------------------
  598.     def ReloadClass(self,cid):
  599.         if self.files.has_key(cid):
  600.             self.BrowseClassFile(self.files[cid])
  601.  
  602.  
  603.     # -----------------------------------------------------------------------------------
  604.     # ReloadFile
  605.     # -----------------------------------------------------------------------------------
  606.     def ReloadFile(self, filename):
  607.         return self.BrowseClassFile(filename)
  608.  
  609.  
  610.     # -----------------------------------------------------------------------------------
  611.     # Import
  612.     # -----------------------------------------------------------------------------------
  613.     def Import(self,name,hack = 1):
  614.         #if name == 'PyAIO':
  615.             #raise 'heha'
  616.         if hack:
  617.             loc = sysold._getframe().f_back.f_globals
  618.         #if name == 'PyAIO':
  619.         #    print 'Importing PyAIO'
  620.  
  621.         if not self.namespaces.has_key(name):
  622.             #raise ImportError,name
  623.             success = 0
  624.             try:
  625.                 prefix = "script:"
  626.  
  627.                 f = sysold._getframe().f_back
  628.                 currdir = f.f_code.co_filename
  629.  
  630.                 idx = currdir.find("script/")
  631.                 if currdir[-len(name)-3:-3] == name:
  632.                     return
  633.                 #if currdir.rfind(name) == len(name) +3:
  634.  
  635.                 if idx != -1:
  636.                     # do path mangling
  637.                     if name[0] == "/":
  638.                         prefix = "script:"
  639.                     else:
  640.                         prefix = currdir[idx+7:]
  641.                         prefix = prefix[:prefix.rfind("/")]
  642.                         prefix = "script:/" + prefix
  643.                         #print "%s importing %s, result is %s" % (currdir, name, prefix + "/" + name + '.py')
  644.  
  645.                 #print "### %s importing %s, result is %s" % (currdir, name, prefix + "/" + name + '.py')
  646.                 #self.BrowseClassFile("script:/" + name + '.py')
  647.                 #import log
  648.                 ###log.general.Log("###### " + prefix + "/" + name + '.py')
  649. #                if name == 'PyAIO':
  650. #                    print 'Browsing file',prefix + "/" + name + '.py'
  651.                 self.BrowseClassFile(prefix + "/" + name + '.py')
  652. #                if name == 'PyAIO':
  653. #                    print 'Imported PyAIO, that was a good success',prefix + "/" + name + '.py'
  654.                 success = 1
  655.             except IOError,val:
  656.                 pass
  657.             except blue.error,val:
  658.                 pass
  659.             #if not success:
  660.             #    try:
  661.             #        self.BrowseClassFile(self.ExpandFiles('script:/'+name+'/'))
  662.             #        success = 1
  663.              #   except IOError,val:
  664.              #       pass
  665.             if not success:
  666.                 # only try if .dll is found
  667.                 check = blue.os.CreateInstance("blue.ResFile")
  668.  
  669.                 if check.Open("%s%s.dll" % (blue.os.binpath, name)):
  670.                     del check
  671. #                    if name == 'PyAIO':
  672. #                        print 'found file, '+name+'.dll, browsing'
  673.                     self.BrowseClassFile(name + '.dll')
  674.                     success = 1
  675. #                else:
  676. #                    if name == 'PyAIO':
  677. #                        print "Didn't find no file, PyAIO.dll"
  678.  
  679.             if name.find('/'):
  680.                 name = name.split('/')[-1]
  681.             if not self.namespaces.has_key(name):
  682.                 raise ImportError,name
  683.  
  684.         ns = Namespace(name,self.namespaces[name])
  685.         if hack:
  686.             loc[name] = ns
  687.         return ns
  688.  
  689.  
  690.     # -----------------------------------------------------------------------------------
  691.     # Release
  692.     # -----------------------------------------------------------------------------------
  693.     def Release(self):
  694.         blue.pyos.SpyDirectory()
  695.         import __builtin__
  696.         if getattr(__builtin__,"Using") == self.Using:
  697.             delattr(__builtin__,"Using")
  698.             #delattr(__builtin__,"Include")
  699.             delattr(__builtin__,"CreateInstance")
  700.             del __builtin__.RegisterConstant
  701.         self.namespaces = {}
  702.         self.globs = {}
  703.         self.preloads = {}
  704.  
  705.  
  706.     # -----------------------------------------------------------------------------------
  707.     # AddPreLoadVariable
  708.     # -----------------------------------------------------------------------------------
  709.     def AddPreLoadVariable(self,name,var):
  710.         self.preloads[name] = var
  711.  
  712.  
  713.     # -----------------------------------------------------------------------------------
  714.     def Compile(self, filename):
  715.         print filename
  716.  
  717.         if self.constants is None:
  718.             file = blue.os.CreateInstance("blue.ResFile")
  719.             file.OpenAlways(filename)
  720.             try:
  721.                 code = compile(str(file.Read()).replace("\r\n", "\n") + "\n", filename, "exec")
  722.             except Exception, e:
  723.                 import log
  724.                 log.general.Log("Compile failed on %s: %s" % (filename, e), log.fatal)
  725.                 print "Compile failed on %s: %s" % (filename, e)
  726.                 raise
  727.             return code
  728.  
  729.  
  730.         print "    Preprocessing..",
  731.         rot = blue.os.CreateInstance("blue.Rot")
  732.         source = open(rot.PathToFilename(filename))
  733.         tokens = tokenize.generate_tokens(source.readline)
  734.         processed = []
  735.         replaced = 0
  736.  
  737.         for token in tokens:
  738.             toktype, string, begin, end, linetext = token
  739.  
  740.             if toktype == tokenize.NAME and string == "const":
  741.                 # replace a little
  742.                 dot = tokens.next() # skip dot
  743.                 tok = tokens.next() # this is the const name
  744.                 if dot[1] == "." and tok[1] in self.constants:
  745.                     newtoken = (tokenize.NUMBER, str(self.constants[tok[1]]), begin, tok[3], linetext)
  746.                     processed.append(newtoken)
  747.                     replaced += 1
  748.                 else:
  749.                     # leave as is
  750.                     processed.append(token)
  751.                     processed.append(dot)
  752.                     processed.append(tok)
  753.             else:
  754.                 processed.append(token)
  755.  
  756.         src = ""
  757.         lastop = -1
  758.         ind = 0
  759.         indentNow = 0
  760.  
  761.         for token in processed:
  762.             if token[0] == tokenize.INDENT:
  763.                 ind += 1
  764.             elif token[0] == tokenize.DEDENT:
  765.                 ind -= 1
  766.             elif token[0] in (tokenize.NEWLINE, tokenize.NL):
  767.                 if lastop != tokenize.COMMENT or src[-1] != '\n' or token[4] == '\n':
  768.                     src += '\n'
  769.                 indentNow = 1
  770.             elif token[0] == tokenize.COMMENT:
  771.                 if lastop in (tokenize.NEWLINE, tokenize.NL):
  772.                     src += token[4]
  773.                 else:
  774.                     src += " " + token[1]
  775.             else:
  776.                 if indentNow:
  777.                     indentNow = 0
  778.                     src += "    " * ind
  779.  
  780.                 if lastop == token[0] == tokenize.NAME:
  781.                     src += " "
  782.  
  783.                 if token[0] == tokenize.OP:
  784.                     if token[1][0] in ('+-*/=i%'):
  785.                         src += " " + token[1] + " "
  786.                     elif token[1][0] in (','):
  787.                         src += token[1] + " "
  788.                     else:
  789.                         src += token[1]
  790.                 elif token[0] == tokenize.STRING:
  791.                     if lastop in (tokenize.NAME, ) and src[-1] != ' ':
  792.                         src += " " + token[1]
  793.                     else:
  794.                         src += token[1]
  795.                 elif token[0] == tokenize.NUMBER:
  796.                     if lastop in (tokenize.NAME, ):
  797.                         src += " " + token[1]
  798.                     else:
  799.                         src += token[1]
  800.                 elif token[0] == tokenize.NAME and token[1] == "in":
  801.                     if src[-1] != ' ':
  802.                         src += " "
  803.                     src += token[1] + " "
  804.                 else:
  805.                     src += token[1]
  806.  
  807.             lastop = token[0]
  808.  
  809.         src += '\n'
  810.  
  811.         # For debugging, this writes out the processed source
  812.         ##file = blue.os.CreateInstance("blue.ResFile")
  813.         ##file.Create(filename + ".processed.py")
  814.         ##file.Write(src)
  815.         ##del file
  816.  
  817.         try:
  818.             print "%s consts replaced" % replaced
  819.             print "    Compiling..",
  820.             code = compile(src, filename, "exec")
  821.             print "finished."
  822.         except Exception, e:
  823.             print "Compile failed on %s: %s" % (filename, e)
  824.             file = blue.os.CreateInstance("blue.ResFile")
  825.             file.Create(filename + ".failed.py")
  826.             file.Write(src)
  827.             del file
  828.             self.constants = None
  829.             raise
  830.  
  831.         print ""
  832.         return code
  833.  
  834.  
  835.     # -----------------------------------------------------------------------------------
  836.     # BrowseClassFile
  837.     # -----------------------------------------------------------------------------------
  838.     def BrowseClassFile(self,filename,noReload=0,fromReload=1):
  839.         #print 'BrowseClassFile',filename
  840.         #if filename == "PyAIO":
  841.         #    raise "wtf!!!"
  842.  
  843.         ret = []
  844.         #if type(filename) == type('fokk'):
  845.         #    filename = [filename]
  846.  
  847.         if not len(filename):
  848.             return
  849.  
  850.         import blue, types
  851.  
  852.         #for each in filename:
  853.         if noReload and filename in self.files.itervalues():
  854.             return self.GatherFileGuids()[filename]
  855.  
  856.  
  857.  
  858.         if filename[:8] == 'script:/':
  859.             globaldict = {}
  860.             globaldict.update(self.preloads)
  861.             oldKeys = globaldict.keys()
  862.             #blue.pyos.ExecFile(filename, globaldict)
  863.             scriptfile = blue.os.scriptpath + filename[8:]
  864.             #check = blue.os.CreateInstance("blue.ResFile")
  865.             #if not check.Open(scriptfile):
  866.             #    raise IOError,filename
  867.             #if not self.compiledCode.has_key(filename):
  868.             #    raise IOError,filename
  869.  
  870.  
  871.             #check.Close()
  872.             #check = None
  873.             #execfile(blue.os.rootpath + "script/"+filename[8:],globaldict)
  874.  
  875.             if self.compiledCode.has_key(filename):
  876.                 code = self.compiledCode[filename]
  877.                 exec(code, globaldict)
  878.             else:
  879.                 check = blue.os.CreateInstance("blue.ResFile")
  880.                 if not check.Open(scriptfile):
  881.                     raise IOError,filename
  882.                 check.Close()
  883.                 try:
  884.                     code = self.Compile(scriptfile)
  885.                     self.compiledCode[filename] = code
  886.                     exec(code, globaldict)
  887.                 except:
  888.                     import log
  889.                     log.general.Log("Failed to execute script '%s'"%scriptfile, log.warn)
  890.                     raise
  891.                 self.compiledCode[filename] = code
  892.  
  893.  
  894.             if globaldict.has_key("exports"):
  895.                 exports = globaldict["exports"]
  896.             else:
  897.                 exports = {}
  898.  
  899.             for each in globaldict.iterkeys():
  900.                 if each not in oldKeys:
  901.                     v = globaldict[each]
  902. #                    if type(v) == type(self.__class__): #as a test, ejm 03/06/02
  903.                     if hasattr(v,"__guid__"):
  904.                         if not exports.has_key(v.__guid__):
  905.                             exports[v.__guid__] = v
  906.             for cid in exports.iterkeys():
  907.                 ret.append(cid)
  908.  
  909.                 namespace,name = cid.split(".")
  910.                 var = exports[cid]
  911.                 if self.mods.has_key(namespace):
  912.                     setattr(self.mods[namespace],name,var)
  913.  
  914.                 if not self.namespaces.has_key(namespace):
  915.                     self.namespaces[namespace] = {}
  916.                 if type(var) == types.ClassType:
  917.                     var.__module__ = namespace
  918.                     if self.files.has_key(cid) and fromReload:
  919.                         self.RecurseBases(self.namespaces[namespace][name],exports.keys())
  920.                 self.namespaces[namespace][name] = var
  921.                 if not self.globs.has_key(namespace):
  922.                     self.globs[namespace] = {}
  923.                 self.globs[namespace][name] = globaldict
  924.                 if not self.files.has_key(cid):
  925.                     self.files[cid] = filename
  926.  
  927.         elif filename[-3:] == 'dll':
  928.              if filename in self.loadeddlls:
  929.                 return []
  930.              class BlueCreateWrapper:
  931.                  def __init__(self,cid):
  932.                      self.cid = cid
  933.  
  934.                  def __call__(self,*args):
  935.                     import blue
  936.                      #print self.cid,'called!'
  937.                     return blue.os.CreateInstance(self.cid,args)
  938.  
  939.              #import blue
  940.              modulename = filename[:-4]
  941.              m = blue.os.LoadModule(modulename)
  942.              myList = blue.os.GetClassTypes()
  943.              for each in myList:
  944.                  moduleInfo = each[0]
  945.                  moduleName = moduleInfo["module"]
  946.                  className = moduleInfo["classname"]
  947.  
  948.                  #if moduleName[0].upper() == 'P':
  949.             #                 if moduleName == 'PyAIO':
  950.  
  951. #                     print 'registering',moduleName,'.',className
  952.                  if not self.namespaces.has_key(moduleName):
  953.                      self.namespaces[moduleName] = {}
  954.                  else:
  955.                     if self.namespaces[moduleName].has_key(className):
  956.                         continue
  957.                  bc = BlueCreateWrapper(moduleName+'.'+className)
  958.                  self.namespaces[moduleName][className] = bc
  959.                  self.files[moduleName+"."+className] = filename
  960.                  if self.mods.has_key(moduleName):
  961.                     setattr(self.mods[moduleName],className,bc)
  962.              if self.mods.has_key(modulename):
  963.                 for attr in dir(m):
  964.                     var = getattr(m,attr)
  965.                     setattr(self.mods[modulename],attr,var)
  966.              for attr in dir(m):
  967.                  if not self.namespaces.has_key(modulename):
  968.                      self.namespaces[modulename] = {}
  969.                  var = getattr(m,attr)
  970.                  self.namespaces[modulename][attr] = var
  971.                  self.files[modulename+"."+attr] = filename
  972.              self.loadeddlls.append(filename)
  973.         return ret
  974.  
  975.     def RecurseBases(self,kl,excepts):
  976.         #print 'RecurseBases 1'
  977.         if type(kl) == type(self.__class__):
  978.             #print 'RecurseBases 2'
  979.             filesToLoad = []
  980.             for ns,space in self.namespaces.iteritems():
  981.                 for attribute,kl2 in space.iteritems():
  982.                     guid = ns+'.'+attribute
  983.                     if type(kl2) == type(self.__class__):
  984.                         #print 'checking guid',guid,type(kl2)
  985.                         if issubclass(kl2,kl) and kl2 != kl:
  986.                         #    print 'Want to reload',guid
  987.                             if guid not in excepts:
  988.                         #        print 'Reloading',guid
  989.                                 fn = self.files.get(guid,None)
  990.                                 if (fn is not None) and (fn not in filesToLoad):
  991.                                     filesToLoad.append(fn)
  992.             for f in filesToLoad:
  993.                 self.BrowseClassFile(f, fromReload = 0)
  994.  
  995.     # -----------------------------------------------------------------------------------
  996.     # Using
  997.     # -----------------------------------------------------------------------------------
  998.     def CreateInstance(self,cid,arguments = ()):
  999.         """For blue to python marriage"""
  1000.         try:
  1001.             namespace,name = cid.split('.')
  1002.         except:
  1003.             raise "InvalidClassID",cid
  1004.         #print namespace,name
  1005.         #print arguments
  1006. #        if name != 'dvec':
  1007.         try:
  1008.             ns = self.namespaces[namespace]
  1009.         except:
  1010.             raise NamespaceFailedException,namespace
  1011.         try:
  1012.             constructor = ns[name]
  1013.         except:
  1014.             raise AttributeError,name
  1015.  
  1016.         ret = apply(constructor,arguments)
  1017.  
  1018.         if hasattr(ret,"__persistvars__"):
  1019.             for each in ret.__persistvars__:
  1020.                 if not hasattr(ret,each):
  1021.                     setattr(ret,each,None)
  1022.  
  1023.         if hasattr(ret,"__nonpersistvars__"):
  1024.             for each in ret.__nonpersistvars__:
  1025.                 if not hasattr(ret,each):
  1026.                     setattr(ret,each,None)
  1027.  
  1028.         return ret
  1029.  
  1030.  
  1031.     # -----------------------------------------------------------------------------------
  1032.     # Using
  1033.     # -----------------------------------------------------------------------------------
  1034.     def Using(self,namespace):
  1035.         import blue, types
  1036.  
  1037.         f = sysold._getframe().f_back
  1038.         loc = f.f_globals
  1039.  
  1040.         if type(namespace) == types.InstanceType:
  1041. #            print namespace.__class__.__name__
  1042.             if namespace.__class__.__name__ == 'Namespace':
  1043. #                print 'is namespace'
  1044. #                print 'caller',f.f_code
  1045. #                print loc
  1046.                 ns = namespace.space
  1047.                 for k,v in ns.iteritems():
  1048.                     loc[k] = v
  1049.                     #f.f_nlocals = f.f_nlocals + 1
  1050.             else:
  1051.                 #print 'caller',f.f_code
  1052.                 ns = namespace.__dict__
  1053.                 for k,v in ns.iteritems():
  1054.                     loc[k] = v
  1055.                     #f.f_nlocals = f.f_nlocals + 1
  1056.  
  1057.         elif type(namespace) == type(blue.os):
  1058.             meths = namespace.TypeInfo()[3].iterkeys()
  1059.             for each in meths:
  1060.                 loc[each] = getattr(namespace,each)
  1061.             attrs = namespace.TypeInfo()[2].iterkeys()
  1062.             for each in attrs:
  1063.                 loc[each] = getattr(namespace,each)
  1064.         else:
  1065.             raise TypeError,namespace
  1066.  
  1067.  
  1068.     # -----------------------------------------------------------------------------------
  1069.     # SetGlobal
  1070.     # -----------------------------------------------------------------------------------
  1071.     def SetGlobal(self,classId,attr,var):
  1072.         namespace,name = classId.split('.')
  1073.         if not self.globs.has_key(namespace):
  1074.             raise ImportError,namespace
  1075.         if not self.globs[namespace].has_key(name):
  1076.             raise AttributeError,var
  1077. #        if self.globs[namespace][name].has_key(attr):
  1078.             #if self.globs[namespace][name][attr] != var:
  1079.                 #raise "GlobalSharingError",(classId,attr)
  1080.         self.globs[namespace][name][attr] = var
  1081.  
  1082.  
  1083.     # -----------------------------------------------------------------------------------
  1084.     # RegisterConstant
  1085.     # -----------------------------------------------------------------------------------
  1086.     def RegisterConstant(self,name,var):
  1087.         #namespace,name = classId.split('.')
  1088.         namespace = "const"
  1089.         if not self.namespaces.has_key(namespace):
  1090.             self.namespaces[namespace] = {}
  1091.         self.namespaces[namespace][name] = var
  1092.  
  1093.     # -----------------------------------------------------------------------------------
  1094.     # GatherFileGuids
  1095.     # -----------------------------------------------------------------------------------
  1096.     def GatherFileGuids(self):
  1097.         exports = {}
  1098.         for guid,filename in self.files.iteritems():
  1099.             if not exports.has_key(filename):
  1100.                 exports[filename] = []
  1101.             exports[filename].append(guid)
  1102.         return exports
  1103.  
  1104. Nasty().Initialize()
  1105.