Skip to content

Commit 5ef045c

Browse files
committed
Merge pull request skulpt#436 from skulpt/update-hacking
Adds info on import / using python in js to Hacking.rst
2 parents e94cd09 + 82e6d22 commit 5ef045c

File tree

1 file changed

+56
-0
lines changed

1 file changed

+56
-0
lines changed

HACKING.rst

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,62 @@ The Sk.builtin.func method creates a function. For module creation we typically
509509

510510
Well, I think this should be enough to get you going. Its worth repeating, if you made it this far, don't forget to call m docbi or m dist after you make changes in your module, its easy to get into the mode of thinking that the new javascript is automatically loaded. But skulpt-stdlib.js is not automatically rebuilt!
511511

512+
Importing/Using a module in another module
513+
------------------------------------------
514+
515+
While working on the namedtuple factory in the collections module I needed to add code to make
516+
sure that the fields named in the named tuple did not duplicate python keywords. while I was
517+
looking around for a list of keywords I discovered that there already was a list of keywords
518+
in the keyword module. Why not use that? A couple of problems:
519+
520+
* How do you import a module into another module? Especially under the condition
521+
where you are writing a module in javascript and the module you want to include is a python
522+
module?
523+
524+
* How do you call a function that was imported from a python module? Here is the snippet
525+
that demonstrates
526+
527+
.. code-block:: javascript
528+
529+
var keywds = Sk.importModule("keyword", false, false);
530+
531+
mod.namedtuple = function (name, fields) {
532+
var nm = Sk.ffi.remapToJs(name);
533+
// fields could be a string or a tuple or list of strings
534+
var flds = Sk.ffi.remapToJs(fields);
535+
536+
if (typeof(flds) === 'string') {
537+
flds = flds.split(/\s+/);
538+
}
539+
// use the keyword module function iskeyword
540+
for (i = 0; i < flds.length; i++) {
541+
if (Sk.ffi.remapToJs(Sk.misceval.callsim(keywds.$d['iskeyword'],Sk.ffi.remapToPy(flds[i])))) {
542+
throw new Sk.builtin.ValueError("Type names and field names cannot be a keyword: " + flds[i]);
543+
}
544+
}
545+
546+
The importing part is easy: ``Sk.importModule(name, dumpJS, canSuspend)``
547+
548+
The not-so-obvious part is the
549+
line: ``Sk.ffi.remapToJs(Sk.misceval.callsim(keywds.$d['iskeyword'],Sk.ffi.remapToPy(flds[i])))``
550+
551+
Working inside out: We use ``Sk.misceval.callsim`` to call the python function ``iskeyword`` which we
552+
retrieve from the module's dictionary of methods ``$d`` Because we are calling a Python function we need
553+
to remap the parameter from a javascript string to a Python string object. Hence the ``remapToPy`` call
554+
in the parameter. Since ``iskeyword`` will return a Python bool object we need to remap that back
555+
to javscript for our if statement.
556+
557+
You can use a similar strategy for creating an instance of a class:
558+
559+
.. code-block:: javascript
560+
561+
var io = Sk.importModule("io", false, false);
562+
var stdin = Sk.misceval.callsim(io.$d["TextIOWrapper"]);
563+
564+
565+
Seems like a lot of work to check for a keyword in an array. But knowing how to do this for much more
566+
complicated methods in other modules will pay off.
567+
512568
513569
Debugging
514570
---------

0 commit comments

Comments
 (0)