import.js.html 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="utf-8">
  5. <title>JSDoc: Source: import.js</title>
  6. <script src="scripts/prettify/prettify.js"> </script>
  7. <script src="scripts/prettify/lang-css.js"> </script>
  8. <!--[if lt IE 9]>
  9. <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
  10. <![endif]-->
  11. <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
  12. <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
  13. </head>
  14. <body>
  15. <div id="main">
  16. <h1 class="page-title">Source: import.js</h1>
  17. <section>
  18. <article>
  19. <pre class="prettyprint source linenums"><code>/**
  20. * @namespace Sk
  21. *
  22. */
  23. // this is stored into sys specially, rather than created by sys
  24. Sk.sysmodules = new Sk.builtin.dict([]);
  25. Sk.realsyspath = undefined;
  26. Sk.externalLibraryCache = {};
  27. Sk.loadExternalLibraryInternal_ = function (path, inject) {
  28. var scriptElement;
  29. var request, result;
  30. if (path == null) {
  31. return void(0);
  32. }
  33. if (Sk.externalLibraryCache[path]) {
  34. return Sk.externalLibraryCache[path];
  35. }
  36. request = new XMLHttpRequest();
  37. request.open("GET", path, false);
  38. request.send();
  39. if (request.status !== 200) {
  40. return void(0);
  41. }
  42. result = request.responseText;
  43. if (inject) {
  44. scriptElement = document.createElement("script");
  45. scriptElement.type = "text/javascript";
  46. scriptElement.text = result;
  47. document.getElementsByTagName("head")[0].appendChild(scriptElement);
  48. }
  49. return result;
  50. };
  51. Sk.loadExternalLibrary = function (name) {
  52. var i;
  53. var externalLibraryInfo, path, module,
  54. dependencies, dep, ext, extMatch, co;
  55. // check if the library has already been loaded and cached
  56. if (Sk.externalLibraryCache[name]) {
  57. return Sk.externalLibraryCache[name];
  58. }
  59. externalLibraryInfo = Sk.externalLibraries &amp;&amp; Sk.externalLibraries[name];
  60. // if no external library info can be found, bail out
  61. if (!externalLibraryInfo) {
  62. return void(0);
  63. }
  64. // if the external library info is just a string, assume it is the path
  65. // otherwise dig into the info to find the path
  66. path = typeof externalLibraryInfo === "string" ?
  67. externalLibraryInfo :
  68. externalLibraryInfo.path;
  69. if (typeof path !== "string") {
  70. throw new Sk.builtin.ImportError("Invalid path specified for " + name);
  71. }
  72. // attempt to determine the type of the library (js or py)
  73. // which is either specified explicitly in the library info
  74. // or inferred from the file extension
  75. ext = externalLibraryInfo.type;
  76. if (!ext) {
  77. extMatch = path.match(/\.(js|py)$/);
  78. ext = extMatch &amp;&amp; extMatch[1];
  79. }
  80. if (!ext) {
  81. throw new Sk.builtin.ImportError("Invalid file extension specified for " + name);
  82. }
  83. module = Sk.loadExternalLibraryInternal_(path, false);
  84. if (!module) {
  85. throw new Sk.builtin.ImportError("Failed to load remote module '" + name + "'");
  86. }
  87. // if the library has any js dependencies, load them in now
  88. dependencies = externalLibraryInfo.dependencies;
  89. if (dependencies &amp;&amp; dependencies.length) {
  90. for (i = 0; i &lt; dependencies.length; i++) {
  91. dep = Sk.loadExternalLibraryInternal_(dependencies[i], true);
  92. if (!dep) {
  93. throw new Sk.builtin.ImportError("Failed to load dependencies required for " + name);
  94. }
  95. }
  96. }
  97. if (ext === "js") {
  98. co = { funcname: "$builtinmodule", code: module };
  99. } else {
  100. co = Sk.compile(module, path, "exec", true);
  101. }
  102. Sk.externalLibraryCache[name] = co;
  103. return co;
  104. };
  105. /**
  106. * @param {string} name to look for
  107. * @param {string} ext extension to use (.py or .js)
  108. * @param {boolean=} failok will throw if not true
  109. * @param {boolean=} canSuspend can we suspend?
  110. */
  111. Sk.importSearchPathForName = function (name, ext, failok, canSuspend) {
  112. var fn;
  113. var j;
  114. var fns = [];
  115. var nameAsPath = name.replace(/\./g, "/");
  116. var L = Sk.realsyspath;
  117. var it, i;
  118. for (it = L.tp$iter(), i = it.tp$iternext(); i !== undefined; i = it.tp$iternext()) {
  119. fns.push(i.v + "/" + nameAsPath + ext); // module
  120. fns.push(i.v + "/" + nameAsPath + "/__init__" + ext); // package
  121. }
  122. j = 0;
  123. return (function tryNextPath() {
  124. var handleRead = function handleRead(s) {
  125. var ns;
  126. if (s instanceof Sk.misceval.Suspension) {
  127. ns = new Sk.misceval.Suspension(undefined, s);
  128. ns.resume = function() {
  129. try {
  130. return handleRead(s.resume());
  131. } catch (e) {
  132. j++;
  133. return tryNextPath();
  134. }
  135. };
  136. return ns;
  137. } else {
  138. return {filename: fns[j], code: s};
  139. }
  140. };
  141. var s;
  142. while (j &lt; fns.length) {
  143. // Ew, this is the only way to check for existence.
  144. // Even worse, it reports non-existence through exceptions, so we have to
  145. // write a custom resume() function to catch downstream exceptions and interpret
  146. // them as "file not found, move on".
  147. try {
  148. s = Sk.read(fns[j]);
  149. if (!canSuspend) {
  150. s = Sk.misceval.retryOptionalSuspensionOrThrow(s);
  151. }
  152. return handleRead(s);
  153. } catch (e) {
  154. j++;
  155. }
  156. }
  157. if (failok) {
  158. return null;
  159. } else {
  160. throw new Sk.builtin.ImportError("No module named " + name);
  161. }
  162. })();
  163. };
  164. /**
  165. * Complete any initialization of Python classes which relies on internal
  166. * dependencies.
  167. *
  168. * This includes making Python classes subclassable and ensuring that the
  169. * {@link Sk.builtin.object} magic methods are wrapped inside Python functions.
  170. *
  171. * @return {undefined}
  172. */
  173. Sk.doOneTimeInitialization = function () {
  174. var proto, name, i, x, func;
  175. var builtins = [];
  176. // can't fill these out when making the type because tuple/dict aren't
  177. // defined yet.
  178. Sk.builtin.type.basesStr_ = new Sk.builtin.str("__bases__");
  179. Sk.builtin.type.mroStr_ = new Sk.builtin.str("__mro__");
  180. // Register a Python class with an internal dictionary, which allows it to
  181. // be subclassed
  182. var setUpClass = function (child) {
  183. var parent = child.tp$base;
  184. var bases = [];
  185. var base;
  186. for (base = parent; base !== undefined; base = base.tp$base) {
  187. bases.push(base);
  188. }
  189. child["$d"] = new Sk.builtin.dict([]);
  190. child["$d"].mp$ass_subscript(Sk.builtin.type.basesStr_, new Sk.builtin.tuple(bases));
  191. child["$d"].mp$ass_subscript(Sk.builtin.type.mroStr_, new Sk.builtin.tuple([child]));
  192. };
  193. for (x in Sk.builtin) {
  194. func = Sk.builtin[x];
  195. if ((func.prototype instanceof Sk.builtin.object ||
  196. func === Sk.builtin.object) &amp;&amp; !func.sk$abstract) {
  197. setUpClass(func);
  198. }
  199. }
  200. // Wrap the inner Javascript code of Sk.builtin.object's Python methods inside
  201. // Sk.builtin.func, as that class was undefined when these functions were declared
  202. proto = Sk.builtin.object.prototype;
  203. for (i = 0; i &lt; Sk.builtin.object.pythonFunctions.length; i++) {
  204. name = Sk.builtin.object.pythonFunctions[i];
  205. if (proto[name] instanceof Sk.builtin.func) {
  206. // If functions have already been initialized, do not wrap again.
  207. break;
  208. }
  209. proto[name] = new Sk.builtin.func(proto[name]);
  210. }
  211. };
  212. /**
  213. * currently only pull once from Sk.syspath. User might want to change
  214. * from js or from py.
  215. */
  216. Sk.importSetUpPath = function () {
  217. var i;
  218. var paths;
  219. if (!Sk.realsyspath) {
  220. paths = [
  221. new Sk.builtin.str("src/builtin"),
  222. new Sk.builtin.str("src/lib"),
  223. new Sk.builtin.str(".")
  224. ];
  225. for (i = 0; i &lt; Sk.syspath.length; ++i) {
  226. paths.push(new Sk.builtin.str(Sk.syspath[i]));
  227. }
  228. Sk.realsyspath = new Sk.builtin.list(paths);
  229. Sk.doOneTimeInitialization();
  230. }
  231. };
  232. if (COMPILED) {
  233. var js_beautify = function (x) {
  234. return x;
  235. };
  236. }
  237. /**
  238. * @param {string} name name of module to import
  239. * @param {boolean=} dumpJS whether to output the generated js code
  240. * @param {string=} modname what to call the module after it's imported if
  241. * it's to be renamed (i.e. __main__)
  242. * @param {string=} suppliedPyBody use as the body of the text for the module
  243. * rather than Sk.read'ing it.
  244. * @param {boolean=} canSuspend whether we may return a Suspension object
  245. */
  246. Sk.importModuleInternal_ = function (name, dumpJS, modname, suppliedPyBody, canSuspend) {
  247. //dumpJS = true;
  248. var parentModule;
  249. var modlocs;
  250. var namestr;
  251. var withLineNumbers;
  252. var finalcode;
  253. var result;
  254. var filename, codeAndPath, co, isPy, googClosure, external;
  255. var module;
  256. var prev;
  257. var parentModName;
  258. var modNameSplit;
  259. var toReturn;
  260. Sk.importSetUpPath();
  261. // if no module name override, supplied, use default name
  262. if (modname === undefined) {
  263. modname = name;
  264. }
  265. toReturn = null;
  266. modNameSplit = modname.split(".");
  267. // if leaf is already in sys.modules, early out
  268. try {
  269. prev = Sk.sysmodules.mp$subscript(modname);
  270. // if we're a dotted module, return the top level, otherwise ourselves
  271. if (modNameSplit.length > 1) {
  272. return Sk.sysmodules.mp$subscript(modNameSplit[0]);
  273. } else {
  274. return prev;
  275. }
  276. } catch (x) {
  277. // not in sys.modules, continue
  278. }
  279. if (modNameSplit.length > 1) {
  280. // if we're a module inside a package (i.e. a.b.c), then we'll need to return the
  281. // top-level package ('a'). recurse upwards on our parent, importing
  282. // all parent packages. so, here we're importing 'a.b', which will in
  283. // turn import 'a', and then return 'a' eventually.
  284. parentModName = modNameSplit.slice(0, modNameSplit.length - 1).join(".");
  285. toReturn = Sk.importModuleInternal_(parentModName, dumpJS, undefined, undefined, canSuspend);
  286. // If this suspends, we suspend. When that suspension is done, we can just
  287. // repeat this whole function call
  288. if (toReturn instanceof Sk.misceval.Suspension) {
  289. // no canSuspend check here; we'll only get a Suspension out of importModuleInternal_ if
  290. // canSuspend is true anyway
  291. return (function waitForPreviousLoad(susp) {
  292. if (susp instanceof Sk.misceval.Suspension) {
  293. // They're still going
  294. return new Sk.misceval.Suspension(waitForPreviousLoad, susp);
  295. } else {
  296. // They're done!
  297. // Re-call ourselves, and this time "toReturn = Sk.importModuleInternal_(...)"
  298. // will hit the cache and complete immediately.
  299. return Sk.importModuleInternal_(name, dumpJS, modname, suppliedPyBody, canSuspend);
  300. }
  301. })(toReturn);
  302. }
  303. }
  304. // otherwise:
  305. // - create module object
  306. // - add module object to sys.modules
  307. // - compile source to (function(){...});
  308. // - run module and set the module locals returned to the module __dict__
  309. module = new Sk.builtin.module();
  310. Sk.sysmodules.mp$ass_subscript(name, module);
  311. if (suppliedPyBody) {
  312. filename = name + ".py";
  313. co = Sk.compile(suppliedPyBody, filename, "exec", canSuspend);
  314. } else {
  315. // If an onBeforeImport method is supplied, call it and if
  316. // the result is false or a string, prevent the import.
  317. // This allows for a user to conditionally prevent the usage
  318. // of certain libraries.
  319. if (Sk.onBeforeImport &amp;&amp; typeof Sk.onBeforeImport === "function") {
  320. result = Sk.onBeforeImport(name);
  321. if (result === false) {
  322. throw new Sk.builtin.ImportError("Importing " + name + " is not allowed");
  323. } else if (typeof result === "string") {
  324. throw new Sk.builtin.ImportError(result);
  325. }
  326. }
  327. // check first for an externally loaded library
  328. external = Sk.loadExternalLibrary(name);
  329. if (external) {
  330. co = external;
  331. } else {
  332. // Try loading as a builtin (i.e. already in JS) module, then try .py files
  333. codeAndPath = Sk.importSearchPathForName(name, ".js", true, canSuspend);
  334. co = (function compileReadCode(codeAndPath) {
  335. if (codeAndPath instanceof Sk.misceval.Suspension) {
  336. return new Sk.misceval.Suspension(compileReadCode, codeAndPath);
  337. } else if (!codeAndPath) {
  338. goog.asserts.assert(!isPy, "Sk.importReadFileFromPath did not throw when loading Python file failed");
  339. isPy = true;
  340. return compileReadCode(Sk.importSearchPathForName(name, ".py", false, canSuspend));
  341. } else {
  342. return isPy ? Sk.compile(codeAndPath.code, codeAndPath.filename, "exec", canSuspend)
  343. : { funcname: "$builtinmodule", code: codeAndPath.code };
  344. }
  345. })(codeAndPath);
  346. }
  347. }
  348. return (function importCompiledCode(co) {
  349. if (co instanceof Sk.misceval.Suspension) {
  350. return canSuspend ? new Sk.misceval.Suspension(importCompiledCode, co) : Sk.misceval.retryOptionalSuspensionOrThrow(co);
  351. }
  352. module.$js = co.code; // todo; only in DEBUG?
  353. finalcode = co.code;
  354. if (Sk.dateSet == null || !Sk.dateSet) {
  355. finalcode = "Sk.execStart = Sk.lastYield = new Date();\n" + co.code;
  356. Sk.dateSet = true;
  357. }
  358. // if (!COMPILED)
  359. // {
  360. if (dumpJS) {
  361. withLineNumbers = function (code) {
  362. var j;
  363. var pad;
  364. var width;
  365. var i;
  366. var beaut = js_beautify(code);
  367. var lines = beaut.split("\n");
  368. for (i = 1; i &lt;= lines.length; ++i) {
  369. width = ("" + i).length;
  370. pad = "";
  371. for (j = width; j &lt; 5; ++j) {
  372. pad += " ";
  373. }
  374. lines[i - 1] = "/* " + pad + i + " */ " + lines[i - 1];
  375. }
  376. return lines.join("\n");
  377. };
  378. finalcode = withLineNumbers(finalcode);
  379. Sk.debugout(finalcode);
  380. }
  381. // }
  382. namestr = "new Sk.builtin.str('" + modname + "')";
  383. finalcode += "\n" + co.funcname + "(" + namestr + ");";
  384. modlocs = goog.global["eval"](finalcode);
  385. return (function finishLoading(modlocs) {
  386. if (modlocs instanceof Sk.misceval.Suspension) {
  387. if (canSuspend) {
  388. return new Sk.misceval.Suspension(finishLoading, modlocs);
  389. } else {
  390. modlocs = Sk.misceval.retryOptionalSuspensionOrThrow(modlocs, "Module \""+modname+"\" suspended or blocked during load, and it was loaded somewhere that does not permit this");
  391. }
  392. }
  393. // pass in __name__ so the module can set it (so that the code can access
  394. // it), but also set it after we're done so that builtins don't have to
  395. // remember to do it.
  396. if (!modlocs["__name__"]) {
  397. modlocs["__name__"] = new Sk.builtin.str(modname);
  398. }
  399. module["$d"] = modlocs;
  400. // doc string is None, when not present
  401. if (!modlocs["__doc__"]) {
  402. modlocs["__doc__"] = Sk.builtin.none.none$;
  403. }
  404. // If an onAfterImport method is defined on the global Sk
  405. // then call it now after a library has been successfully imported
  406. // and compiled.
  407. if (Sk.onAfterImport &amp;&amp; typeof Sk.onAfterImport === "function") {
  408. try {
  409. Sk.onAfterImport(name);
  410. } catch (e) {
  411. }
  412. }
  413. if (toReturn) {
  414. // if we were a dotted name, then we want to return the top-most
  415. // package. we store ourselves into our parent as an attribute
  416. parentModule = Sk.sysmodules.mp$subscript(parentModName);
  417. parentModule.tp$setattr(modNameSplit[modNameSplit.length - 1], module);
  418. //print("import returning parent module, modname", modname, "__name__", toReturn.tp$getattr("__name__").v);
  419. return toReturn;
  420. }
  421. //print("name", name, "modname", modname, "returning leaf");
  422. // otherwise we return the actual module that we just imported
  423. return module;
  424. })(modlocs);
  425. })(co);
  426. };
  427. /**
  428. * @param {string} name the module name
  429. * @param {boolean=} dumpJS print out the js code after compilation for debugging
  430. * @param {boolean=} canSuspend can this function suspend and return a Suspension object?
  431. */
  432. Sk.importModule = function (name, dumpJS, canSuspend) {
  433. return Sk.importModuleInternal_(name, dumpJS, undefined, undefined, canSuspend);
  434. };
  435. Sk.importMain = function (name, dumpJS, canSuspend) {
  436. Sk.dateSet = false;
  437. Sk.filesLoaded = false;
  438. // Added to reset imports
  439. Sk.sysmodules = new Sk.builtin.dict([]);
  440. Sk.realsyspath = undefined;
  441. Sk.resetCompiler();
  442. return Sk.importModuleInternal_(name, dumpJS, "__main__", undefined, canSuspend);
  443. };
  444. /**
  445. * **Run Python Code in Skulpt**
  446. *
  447. * When you want to hand Skulpt a string corresponding to a Python program this is the function.
  448. *
  449. * @param name {string} File name to use for messages related to this run
  450. * @param dumpJS {boolean} print out the compiled javascript
  451. * @param body {string} Python Code
  452. * @param canSuspend {boolean} Use Suspensions for async execution
  453. *
  454. */
  455. Sk.importMainWithBody = function (name, dumpJS, body, canSuspend) {
  456. Sk.dateSet = false;
  457. Sk.filesLoaded = false;
  458. // Added to reset imports
  459. Sk.sysmodules = new Sk.builtin.dict([]);
  460. Sk.realsyspath = undefined;
  461. Sk.resetCompiler();
  462. return Sk.importModuleInternal_(name, dumpJS, "__main__", body, canSuspend);
  463. };
  464. Sk.builtin.__import__ = function (name, globals, locals, fromlist) {
  465. // Save the Sk.globals variable importModuleInternal_ may replace it when it compiles
  466. // a Python language module. for some reason, __name__ gets overwritten.
  467. var saveSk = Sk.globals;
  468. var ret = Sk.importModuleInternal_(name, undefined, undefined, undefined, true);
  469. return (function finalizeImport(ret) {
  470. if (ret instanceof Sk.misceval.Suspension) {
  471. return new Sk.misceval.Suspension(finalizeImport, ret);
  472. }
  473. if (saveSk !== Sk.globals) {
  474. Sk.globals = saveSk;
  475. }
  476. if (!fromlist || fromlist.length === 0) {
  477. return ret;
  478. }
  479. // if there's a fromlist we want to return the actual module, not the
  480. // toplevel namespace
  481. ret = Sk.sysmodules.mp$subscript(name);
  482. goog.asserts.assert(ret);
  483. return ret;
  484. })(ret);
  485. };
  486. Sk.importStar = function (module, loc, global) {
  487. // from the global scope, globals and locals can be the same. So the loop below
  488. // could accidentally overwrite __name__, erasing __main__.
  489. var i;
  490. var nn = global["__name__"];
  491. var props = Object["getOwnPropertyNames"](module["$d"]);
  492. for (i in props) {
  493. loc[props[i]] = module["$d"][props[i]];
  494. }
  495. if (global["__name__"] !== nn) {
  496. global["__name__"] = nn;
  497. }
  498. };
  499. goog.exportSymbol("Sk.importMain", Sk.importMain);
  500. goog.exportSymbol("Sk.importMainWithBody", Sk.importMainWithBody);
  501. goog.exportSymbol("Sk.builtin.__import__", Sk.builtin.__import__);
  502. goog.exportSymbol("Sk.importStar", Sk.importStar);
  503. </code></pre>
  504. </article>
  505. </section>
  506. </div>
  507. <nav>
  508. <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Sk.abstr.iter-seqIter.html">seqIter</a></li><li><a href="Sk.builtin.bool.html">bool</a></li><li><a href="Sk.builtin.float_.html">float_</a></li><li><a href="Sk.builtin.func.html">func</a></li><li><a href="Sk.builtin.int_.html">int_</a></li><li><a href="Sk.builtin.none.html">none</a></li><li><a href="Sk.builtin.NotImplemented.html">NotImplemented</a></li><li><a href="Sk.builtin.numtype.html">numtype</a></li><li><a href="Sk.builtin.object.html">object</a></li><li><a href="Sk.builtin.seqtype.html">seqtype</a></li><li><a href="Sk.misceval.Suspension.html">Suspension</a></li></ul><h3>Namespaces</h3><ul><li><a href="Sk.html">Sk</a></li><li><a href="Sk.abstr.html">abstr</a></li><li><a href="Sk.builtin.html">builtin</a></li><li><a href="Sk.ffi.html">ffi</a></li><li><a href="Sk.misceval.html">misceval</a></li></ul>
  509. </nav>
  510. <br class="clear">
  511. <footer>
  512. Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.3.0</a> on Thu Aug 13 2015 08:14:27 GMT-0500 (CDT)
  513. </footer>
  514. <script> prettyPrint(); </script>
  515. <script src="scripts/linenumber.js"> </script>
  516. </body>
  517. </html>