diff --git a/www/doc/en/jsobjects.md b/www/doc/en/jsobjects.md index a9c086943..a4bd85f89 100644 --- a/www/doc/en/jsobjects.md +++ b/www/doc/en/jsobjects.md @@ -368,17 +368,29 @@ s1.addEventListener('load', function(script){ > translation to Javascript. The result can be executed by `eval()` > to trigger the script execution. -*`__BRYTHON__`.runPythonSource(_src_[, _script_id_])* +*`__BRYTHON__`.runPythonSource(_src_[, _attributes_])* -> executes Python source code `src` as if it was a script with optional -> identifier _script_id_. Returns the Javascript object that represents the +> executes Python source code `src` as if it was a script with the specified +> _attributes_. If _attributes_ is a string, it is the script `id`, otherwise +> it must be a Javascript object. + +> [Execution options](options.html) such as debug level, path for imports, +> etc. can be passed as attributes, for instance + +
+```xml +var src = "import some_module" +__BRYTHON__.runPythonSource(src, {pythonpath: 'my_modules', debug: 2}) +``` ++ +> Returns the Javascript object that represents the > module (also available as `__BRYTHON__.getPythonModule(script_id)`)
```xml diff --git a/www/src/brython.js b/www/src/brython.js index 0eba4b7f5..77dd42640 100644 --- a/www/src/brython.js +++ b/www/src/brython.js @@ -148,9 +148,16 @@ $B.getPythonModule=function(name){return $B.imported[name]} $B.python_to_js=function(src,script_id){ return "(function() {\n"+from_py(src,script_id)+"\nreturn locals}())"} $B.pythonToJS=$B.python_to_js -$B.runPythonSource=function(src,script_id){var js=from_py(src,script_id)+'\nreturn locals' -var func=new Function('$B','_b_',js) -$B.imported[script_id]=func($B,$B.builtins) +function fakeScript(filename){this.options={}} +fakeScript.prototype.getAttribute=function(key){return this.options[key]?? null} +fakeScript.prototype.dispatchEvent=function(){} +$B.runPythonSource=function(src,options){var script_id +if(options){if(typeof options=='string'){script_id=options}else if(options.constructor===Object){if(options.hasOwnProperty('id')){script_id=options.id +delete options.id}}else{console.debug('invalid options argument:',options)}} +var script=new fakeScript(),url=$B.script_path=globalThis.location.href.split('#')[0] +if(options){for(var[key,value]of Object.entries(options)){script.options[key]=value}} +script_id=script_id ?? 'python_script_'+$B.UUID() +$B.run_script(script,src,script_id,url,true) return $B.imported[script_id]}})(__BRYTHON__) ; __BRYTHON__.ast_classes={Add:'',And:'',AnnAssign:'target,annotation,value?,simple',Assert:'test,msg?',Assign:'targets*,value,type_comment?',AsyncFor:'target,iter,body*,orelse*,type_comment?',AsyncFunctionDef:'name,args,body*,decorator_list*,returns?,type_comment?,type_params*',AsyncWith:'items*,body*,type_comment?',Attribute:'value,attr,ctx',AugAssign:'target,op,value',Await:'value',BinOp:'left,op,right',BitAnd:'',BitOr:'',BitXor:'',BoolOp:'op,values*',Break:'',Call:'func,args*,keywords*',ClassDef:'name,bases*,keywords*,body*,decorator_list*,type_params*',Compare:'left,ops*,comparators*',Constant:'value,kind?',Continue:'',Del:'',Delete:'targets*',Dict:'keys*,values*',DictComp:'key,value,generators*',Div:'',Eq:'',ExceptHandler:'type?,name?,body*',Expr:'value',Expression:'body',FloorDiv:'',For:'target,iter,body*,orelse*,type_comment?',FormattedValue:'value,conversion,format_spec?',FunctionDef:'name,args,body*,decorator_list*,returns?,type_comment?,type_params*',FunctionType:'argtypes*,returns',GeneratorExp:'elt,generators*',Global:'names*',Gt:'',GtE:'',If:'test,body*,orelse*',IfExp:'test,body,orelse',Import:'names*',ImportFrom:'module?,names*,level?',In:'',Interactive:'body*',Invert:'',Is:'',IsNot:'',JoinedStr:'values*',LShift:'',Lambda:'args,body',List:'elts*,ctx',ListComp:'elt,generators*',Load:'',Lt:'',LtE:'',MatMult:'',Match:'subject,cases*',MatchAs:'pattern?,name?',MatchClass:'cls,patterns*,kwd_attrs*,kwd_patterns*',MatchMapping:'keys*,patterns*,rest?',MatchOr:'patterns*',MatchSequence:'patterns*',MatchSingleton:'value',MatchStar:'name?',MatchValue:'value',Mod:'',Module:'body*,type_ignores*',Mult:'',Name:'id,ctx',NamedExpr:'target,value',Nonlocal:'names*',Not:'',NotEq:'',NotIn:'',Or:'',ParamSpec:'name',Pass:'',Pow:'',RShift:'',Raise:'exc?,cause?',Return:'value?',Set:'elts*',SetComp:'elt,generators*',Slice:'lower?,upper?,step?',Starred:'value,ctx',Store:'',Sub:'',Subscript:'value,slice,ctx',Try:'body*,handlers*,orelse*,finalbody*',TryStar:'body*,handlers*,orelse*,finalbody*',Tuple:'elts*,ctx',TypeAlias:'name,type_params*,value',TypeIgnore:'lineno,tag',TypeVar:'name,bound?',TypeVarTuple:'name',UAdd:'',USub:'',UnaryOp:'op,operand',While:'test,body*,orelse*',With:'items*,body*,type_comment?',Yield:'value?',YieldFrom:'value',alias:'name,asname?',arg:'arg,annotation?,type_comment?',arguments:'posonlyargs*,args*,vararg?,kwonlyargs*,kw_defaults*,kwarg?,defaults*',boolop:['And','Or'],cmpop:['Eq','NotEq','Lt','LtE','Gt','GtE','Is','IsNot','In','NotIn'],comprehension:'target,iter,ifs*,is_async',excepthandler:['ExceptHandler'],expr:['BoolOp','NamedExpr','BinOp','UnaryOp','Lambda','IfExp','Dict','Set','ListComp','SetComp','DictComp','GeneratorExp','Await','Yield','YieldFrom','Compare','Call','FormattedValue','JoinedStr','Constant','Attribute','Subscript','Starred','Name','List','Tuple','Slice'],expr_context:['Load','Store','Del'],keyword:'arg?,value',match_case:'pattern,guard?,body*',mod:['Module','Interactive','Expression','FunctionType'],operator:['Add','Sub','Mult','MatMult','Div','Mod','Pow','LShift','RShift','BitOr','BitXor','BitAnd','FloorDiv'],pattern:['MatchValue','MatchSingleton','MatchSequence','MatchMapping','MatchClass','MatchStar','MatchAs','MatchOr'],stmt:['FunctionDef','AsyncFunctionDef','ClassDef','Return','Delete','Assign','TypeAlias','AugAssign','AnnAssign','For','AsyncFor','While','If','With','AsyncWith','Match','Raise','Try','TryStar','Assert','Import','ImportFrom','Global','Nonlocal','Expr','Pass','Break','Continue'],type_ignore:['TypeIgnore'],type_param:['TypeVar','ParamSpec','TypeVarTuple'],unaryop:['Invert','Not','UAdd','USub'],withitem:'context_expr,optional_vars?'} @@ -173,8 +180,8 @@ $B.unicode_bidi_whitespace=[9,10,11,12,13,28,29,30,31,32,133,5760,8192,8193,8194 ; __BRYTHON__.implementation=[3,12,3,'dev',0] __BRYTHON__.version_info=[3,12,0,'final',0] -__BRYTHON__.compiled_date="2024-04-24 21:31:15.551547" -__BRYTHON__.timestamp=1713987075551 +__BRYTHON__.compiled_date="2024-04-27 08:04:32.357791" +__BRYTHON__.timestamp=1714197872357 __BRYTHON__.builtin_module_names=["_ajax","_ast","_base64","_binascii","_io_classes","_json","_jsre","_locale","_multiprocessing","_posixsubprocess","_profile","_random","_sre","_sre_utils","_string","_strptime","_svg","_symtable","_tokenize","_webcomponent","_webworker","_zlib_utils","_zlib_utils1","_zlib_utils_kozh","array","builtins","dis","encoding_cp932","encoding_cp932_v2","hashlib","html_parser","marshal","math","modulefinder","posix","pyexpat","python_re","python_re_new","unicodedata"] ; @@ -892,7 +899,7 @@ scripts.push(script)}else{console.log(`no script with id '${id}'`) throw _b_.KeyError.$factory(`no script with id '${id}'`)}}}else if($B.isWebWorker){}else{scripts=python_scripts.slice()} run_scripts(scripts)} function convert_option(option,value){ -if(option=='debug'){if(typeof value=='string' && value.match(/^\d+$/)){return parseInt(value)}else{if(value !==null && value !==undefined){console.debug(`Invalid value for debug: ${value}`)}}}else if(option=='cache' || +if(option=='debug'){if(typeof value=='string' && value.match(/^\d+$/)){return parseInt(value)}else if(typeof value=='number'){return value}else{if(value !==null && value !==undefined){console.debug(`Invalid value for debug: ${value}`)}}}else if(option=='cache' || option=='indexeddb' || option=='static_stdlib_import'){if(value=='1' ||value.toLowerCase()=='true'){return true}else if(value=='0' ||value.toLowerCase()=='false'){return false}else{console.debug(`Invalid value for ${option}: ${value}`)}}else if(option=='ids' ||option=='pythonpath' ||option=='args'){ if(typeof value=='string'){if(value.trim().length==0){return[]} diff --git a/www/src/brython_builtins.js b/www/src/brython_builtins.js index aeeb5ce8c..628a44594 100644 --- a/www/src/brython_builtins.js +++ b/www/src/brython_builtins.js @@ -431,10 +431,44 @@ $B.python_to_js = function(src, script_id){ $B.pythonToJS = $B.python_to_js -$B.runPythonSource = function(src, script_id){ - var js = from_py(src, script_id) + '\nreturn locals' - var func = new Function('$B', '_b_', js) - $B.imported[script_id] = func($B, $B.builtins) +function fakeScript(filename){ + this.options = {} +} + +fakeScript.prototype.getAttribute = function(key){ + return this.options[key] ?? null +} + +fakeScript.prototype.dispatchEvent = function(){ + // ignore +} + +$B.runPythonSource = function(src, options){ + var script_id + + if(options){ + if(typeof options == 'string'){ + script_id = options + }else if(options.constructor === Object){ + if(options.hasOwnProperty('id')){ + script_id = options.id + delete options.id + } + }else{ + console.debug('invalid options argument:', options) + } + } + // Simulate an HTML