def translateCode(self, event=None): """For each code box, translate Python code to JavaScript. """ param = self.params['Code Type'] param.val = param.allowedVals[self.codeTypeMenu.GetSelection()] if not param.val == "Auto->JS": return for boxName in self.codeBoxes: if 'JS' not in boxName: jsBox = boxName.replace(' ', ' JS ') pythonCode = self.codeBoxes[boxName].GetValue() jsCode = self.codeBoxes[jsBox].GetValue() if jsCode: dlg = CodeOverwriteDialog( self, -1, "Warning: Python to JavaScript Translation") retVal = dlg.ShowModal() if not retVal == wx.ID_OK: return if not pythonCode: # Skip empty code panel continue if not hasMetapensiero: # metapensiero required for translation self.codeBoxes[jsBox].SetValue(( "// Py to JS auto-translation requires the metapensiero libray\n" "// metapensiero is available for Python 3.5+")) return try: jsCode = translatePythonToJavaScript(pythonCode) self.codeBoxes[jsBox].SetValue(jsCode) except Exception as err: print("{} : {}".format(boxName, err)) if event: event.Skip()
def expression2js(expr): """Convert a short expression (e.g. a Component Parameter) Python to JS""" # if the code contains a tuple (anywhere), convert parenths to be list. # This now works for compounds like `(2*(4, 5))` where the inner # parenths becomes a list and the outer parens indicate priority. # This works by running an ast transformer class to swap the contents of the tuple # into a list for the number of tuples in the expression. try: syntaxTree = ast.parse(expr) except Exception: try: syntaxTree = ast.parse(unicode(expr)) except Exception as err: logging.error(err) return for node in ast.walk(syntaxTree): TupleTransformer().visit(node) # Transform tuples to list # for py2 using 'unicode_literals' we don't want if isinstance(node, ast.Str) and type(node.s)==bytes: node.s = unicode(node.s, 'utf-8') elif isinstance(node, ast.Str) and node.s.startswith("u'"): node.s = node.s[1:] if isinstance(node, ast.Name): if node.id == 'undefined': continue node.id = namesJS[node.id] jsStr = unparse(syntaxTree).strip() if not any(ch in jsStr for ch in ("=",";","\n")): try: jsStr = translatePythonToJavaScript(jsStr) if jsStr.endswith(';\n'): jsStr = jsStr[:-2] except: # If translation fails, just use old translation pass return jsStr
def writeFrameCodeJS(self, buff): BaseVisualComponent.writeFrameCodeJS(self, buff) # do writing of init inits = getInitVals(self.params, 'PsychoJS') # Get callback from params callback = inits['callback'] if inits['callback'].val: callback = translatePythonToJavaScript(str(callback)) else: callback = "" # Check for current and last button press code = ("if (%(name)s.status === PsychoJS.Status.STARTED) {\n") buff.writeIndentedLines(code % inits) buff.setIndentLevel(1, relative=True) code = ("// check whether %(name)s has been pressed\n" "if (%(name)s.isClicked) {\n") buff.writeIndentedLines(code % inits) buff.setIndentLevel(1, relative=True) code = ("if (!%(name)s.wasClicked) {\n") buff.writeIndentedLines(code % inits) buff.setIndentLevel(1, relative=True) code = ("// store time of first click\n" "%(name)s.timesOn.push(%(name)s.clock.getTime());\n" "// store time clicked until\n" "%(name)s.timesOff.push(%(name)s.clock.getTime());\n") buff.writeIndentedLines(code % inits) buff.setIndentLevel(-1, relative=True) code = ("} else {\n") buff.writeIndentedLines(code % inits) buff.setIndentLevel(1, relative=True) code = ( "// update time clicked until;\n" "%(name)s.timesOff[%(name)s.timesOff.length - 1] = %(name)s.clock.getTime();\n" ) buff.writeIndentedLines(code % inits) buff.setIndentLevel(-1, relative=True) code = ("}\n") buff.writeIndentedLines(code % inits) if self.params['oncePerClick'] or self.params['forceEndRoutine']: code = ("if (!%(name)s.wasClicked) {\n") buff.writeIndentedLines(code % inits) buff.setIndentLevel(1, relative=True) if self.params['forceEndRoutine']: code = ("// end routine when %(name)s is clicked\n" "continueRoutine = false;\n") buff.writeIndentedLines(code % inits) if self.params['oncePerClick']: buff.writeIndentedLines(callback % inits) buff.setIndentLevel(-1, relative=True) code = ("}\n") buff.writeIndentedLines(code % inits) if not self.params['oncePerClick']: buff.writeIndentedLines(callback % inits) # Store current button press as last code = ( "// if %(name)s is still clicked next frame, it is not a new click\n" "%(name)s.wasClicked = true;\n") buff.writeIndentedLines(code % inits) buff.setIndentLevel(-1, relative=True) code = ("} else {\n") buff.writeIndentedLines(code % inits) buff.setIndentLevel(1, relative=True) code = ("// if %(name)s is clicked next frame, it is a new click\n" "%(name)s.wasClicked = false\n") buff.writeIndentedLines(code % inits) buff.setIndentLevel(-1, relative=True) code = ("}\n") buff.writeIndentedLines(code % inits) buff.setIndentLevel(-1, relative=True) code = ("} else {\n") buff.writeIndentedLines(code % inits) buff.setIndentLevel(1, relative=True) code = ( "// keep clock at 0 if %(name)s hasn't started / has finished\n" "%(name)s.clock.reset();\n" "// if %(name)s is clicked next frame, it is a new click\n" "%(name)s.wasClicked = false;\n") buff.writeIndentedLines(code % inits) buff.setIndentLevel(-1, relative=True) code = ("}\n") buff.writeIndentedLines(code % inits)
def runTranspile(self, py, js): transpiledCode = translatePythonToJavaScript(py) assert (js == transpiledCode)