| Script scripterng_runtime |  | 
  1  """ 
  2  This runtime module contains everything about running  
  3  Python and QtScript scripts inside Scribus. 
  4   
  5  Look at run_filename for details. 
  6  """ 
  7  import os 
  8  import hashlib 
  9  from ConfigParser import ConfigParser 
 10   
 11  import sip 
 12  from PyQt4.QtCore import QThread, QObject, QVariant 
 13  from PyQt4.QtGui import qApp,  QMessageBox 
 14  from PyQt4.QtScript import QScriptEngine, QScriptValue 
 15   
 16  from safe_eval import checkCode 
 17  import permitdlg 
 18   
 19  import __main__ 
 20   
 21  from inspect import getargspec 
 24       
 25       
 26       
 27       
 28       
 29   
 31          ConfigParser.__init__(self) 
 32           
 33          path = os.path.expanduser("~/.scribus/scripterng") 
 34          if not os.path.exists(path): 
 35              os.makedirs(path) 
 36          self.filename = os.path.join(path, "runtime.cfg") 
 37          self.read([self.filename]) 
  38   
 39   
 41          fp = open(self.filename, "w") 
 42          self.write(fp) 
 43          fp.close() 
  44   
 45   
 46 -    def set(self, section, key, value): 
  47          if not self.has_section(section): 
 48              self.add_section(section) 
 49          ConfigParser.set(self, section, key, value) 
 50          self.save() 
  51       
 52   
 54          value = self.get(section, key).strip().lower() 
 55          if value and value in ["true", "on", "yes", "1"]: 
 56              return True 
 57          elif value and value in ["false", "off", "no", "0"]: 
 58              return False 
 59          else: 
 60              raise ValueError, "Invalid boolean value %r" % value 
   61   
 62   
 63  runtime_config = RuntimeConfig() 
 64   
 65  extension_namespace = __main__.__dict__ 
 66   
 67   
 68  qts_engine = None 
 74   
 77      def wrapper(context, engine): 
 78          args = [] 
 79          (fargs, fvarargs, fvarkw, fdefaults) = getargspec(func) 
 80          if len(fargs) and fargs[0] == "self": 
 81              args.append(context.thisObject()) 
 82          for i in xrange(context.argumentCount()): 
 83              args.append(context.argument(i)) 
 84          try: 
 85              result = func(*args) 
 86          except Exception, e: 
 87               
 88               
 89              return context.throwValue(QScriptValue(engine, str(e))) 
 90          if result: 
 91              return QScriptValue(engine, result) 
 92          else: 
 93              return QScriptValue() 
  94      return wrapper 
 95   
 96   
 97  @qts_func_decorator 
 98 -def alert(msg_qsv): 
  99      msg = msg_qsv.toString() 
100      QMessageBox.information(ScripterNG.dialogs.mainWindow.qt, "Alert", msg) 
 101   
104      go = engine.globalObject() 
105      for name, value in ns.items(): 
106          if isinstance(value, QObject): 
107              value = engine.newQObject(value) 
108          elif callable(value): 
109              value = engine.newFunction(value) 
110           
111           
112          go.setProperty(name, value) 
 113   
116      engine = QScriptEngine() 
117      update_qs_namespace(engine,  
118         {  
119            "Application": qApp, 
120            "ScripterNG": ScripterNG.qt, 
121            "alert": alert 
122         }) 
123      return engine 
 124   
125   
126 -def run_qtscript(filename, subroutine=None, extension=False): 
 127      global qts_engine 
128      if not extension: 
129          engine = newQScriptEngine() 
130      else: 
131          engine = qts_engine = qts_engine or newQScriptEngine() 
132      code = open(filename).read() 
133      engine.clearExceptions() 
134      result = engine.evaluate(code) 
135      engine.collectGarbage() 
136      if not engine.hasUncaughtException() and subroutine: 
137          sub = engine.globalObject().property(subroutine) 
138          sub.call() 
139      if engine.hasUncaughtException(): 
140          bt = engine.uncaughtExceptionBacktrace() 
141          raise QtSRuntimeError("%s\nTraceback:\%s" % ( 
142                str(engine.uncaughtException().toString()), 
143                "\n".join(["  %s" % l for l in list(bt)]))) 
 144   
147       
148      source = source or open(filename).read() 
149      return "%s:%s:%s" % ( 
150          os.path.basename(filename), len(filename), hashlib.sha256(source).hexdigest()) 
 151   
154      filename = os.path.abspath(os.path.expanduser(filename)) 
155      path = os.path.dirname(filename) 
156       
157       
158      if path == os.path.join(ScripterNG.path, "autoload"): 
159          return True 
160      code = open(filename).read() 
161      h = hash_source(filename, code) 
162      if runtime_config.has_option("permissions", h): 
163          return runtime_config.getbool("permissions", h) 
164   
165      problems = checkCode(code) 
166      if problems and len(problems) == 1 and isinstance(problems[0], SyntaxError): 
167          return True  
168      elif problems: 
169          ok = permitdlg.ask(filename, problems) 
170          if ok == -2:  
171              runtime_config.set("permissions", h, False) 
172              return False 
173          elif ok == 2:  
174              return False 
175          elif ok == -1:  
176              runtime_config.set("permissions", h, True) 
177          elif ok == 1:  
178              pass 
179          else: 
180              raise ValueError, "Inknown return code for permission dialog: %r" % ok 
181      return True 
 182   
183   
184 -def run_python(filename, subroutine=None, extension=False): 
 185      if not extension: 
186          namespace = { 
187          __name__: "__scribus__", 
188          __file__: filename 
189          } 
190      else: 
191          namespace = extension_namespace 
192      if not check_python(filename): 
193          return 
194      execfile(filename, namespace) 
195      if subroutine: 
196          sub = namespace[subroutine] 
197          sub() 
198      if not extension: 
199          del namespace 
 200   
201   
202  threads = [] 
217           
220      thread = RunThread(func, *args) 
221      thread.start() 
222       
223      return thread 
 224   
228      """ 
229      mark every child of ScripterNG.collector to keep 
230      """ 
231      for child in ScripterNG.collector.children(): 
232          if hasattr(child, "qt"): child = child.qt         
233          child.setProperty("keep", QVariant(True)) 
 234   
238      """  
239      delete every child which is not marked as keep 
240      """ 
241      for child in ScripterNG.collector.children(): 
242          if hasattr(child, "qt"): child = child.qt 
243          v = child.property("keep") 
244          if v and v.toBool() == True: 
245               
246              continue 
247          print "* deleting collected", child 
248          sip.delete(child) 
 249   
250   
251   
252 -def run_filename(filename, subroutine=None, extension=False, background=False): 
 253      """ 
254      Call this function to run a script and nothing else.  
255      It will do everything for you, including garbage collection 
256      for QtScript (very simple implementation, see mark_keep and cleanup). 
257      Running as extension uses the __main__ namespace and does not 
258      delete objects after execution. 
259      Running in background as a thread is not much tested and  
260      should only be used for non-GUI scripts. 
261      """ 
262      mark_keep() 
263      if background: 
264          run_func = run_background 
265      else: 
266          run_func = lambda func, *args: func(*args) 
267      if filename.endswith((".sqts", ".qts", ".sjs", ".js")): 
268          run_func(run_qtscript, filename, subroutine, extension) 
269      else: 
270          run_func(run_python, filename, subroutine, extension) 
271      if not background and not extension: 
272           
273          cleanup() 
 274