From 96e03d722546913b14e07a610b5975ecb9198619 Mon Sep 17 00:00:00 2001 From: "create-issue-branch[bot]" <53036503+create-issue-branch[bot]@users.noreply.github.com> Date: Mon, 27 Mar 2023 17:00:44 +0100 Subject: [PATCH] Write py5 python blob logic (#414) closes #390 --------- Co-authored-by: loiswells97 Co-authored-by: Lois Wells Co-authored-by: Lois Wells <88904316+loiswells97@users.noreply.github.com> Co-authored-by: Patrick Cherry --- CHANGELOG.md | 1 + cypress/e2e/spec.cy.js | 8 + public/py5_imported_mode.py | 1 - public/{ => shims/processing/p5}/p5-shim.js | 181 +++++++++--------- public/{ => shims/processing/py5}/py5-shim.js | 40 ++++ .../py5_imported_mode/py5_imported.js | 51 +++++ .../py5_imported_mode/py5_imported_mode.py | 2 + public/{ => shims/pygal}/pygal.js | 0 .../sense_hat}/_internal_sense_hat.js | 0 .../{ => shims/sense_hat}/sense_hat_blob.py | 0 .../Runners/PythonRunner/PythonRunner.js | 93 ++++----- .../Runners/PythonRunner/PythonRunner.test.js | 60 ++++++ 12 files changed, 289 insertions(+), 148 deletions(-) delete mode 100644 public/py5_imported_mode.py rename public/{ => shims/processing/p5}/p5-shim.js (90%) rename public/{ => shims/processing/py5}/py5-shim.js (97%) create mode 100644 public/shims/processing/py5_imported_mode/py5_imported.js create mode 100644 public/shims/processing/py5_imported_mode/py5_imported_mode.py rename public/{ => shims/pygal}/pygal.js (100%) rename public/{ => shims/sense_hat}/_internal_sense_hat.js (100%) rename public/{ => shims/sense_hat}/sense_hat_blob.py (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index b72180ac1..bf7b6e529 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - Load project based on locale (#410) - Ability to recognise py5 magic comment (#412) +- Python blob and skulpt module for py5 imported mode (#414) ### Changed diff --git a/cypress/e2e/spec.cy.js b/cypress/e2e/spec.cy.js index cbf034018..73d0800d7 100644 --- a/cypress/e2e/spec.cy.js +++ b/cypress/e2e/spec.cy.js @@ -22,3 +22,11 @@ it("runs with the magic comment present", () => { cy.get(".pythonrunner-console-output-line").should("contain", "hello world") }) + +it("runs basic skecth with py5 magic comment present", () => { + cy.visit(baseUrl) + cy.get("div[class=cm-content]").invoke('text', '# Py5: imported mode\ndef setup():\n\tsize(400,400)\n\ndef draw():\n\tprint("hello world")\nrun_sketch()') + cy.get(".btn--run").click() + + cy.get(".pythonrunner-console-output-line").should("contain", "hello world") +}) diff --git a/public/py5_imported_mode.py b/public/py5_imported_mode.py deleted file mode 100644 index 8b1378917..000000000 --- a/public/py5_imported_mode.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/public/p5-shim.js b/public/shims/processing/p5/p5-shim.js similarity index 90% rename from public/p5-shim.js rename to public/shims/processing/p5/p5-shim.js index 10f9b8016..4ebe101e7 100644 --- a/public/p5-shim.js +++ b/public/shims/processing/p5/p5-shim.js @@ -248,7 +248,7 @@ const $builtinmodule = function (name) { return new Sk.builtin.float_(mod.pInst.hue(...argVals)); }); - mod.lerpColor = new Sk.builtin.func(function (c1, c2, amt) { + mod.lerp_color = new Sk.builtin.func(function (c1, c2, amt) { const c = Sk.misceval.callsimArray(mod.color, [ new Sk.builtin.int_(0), new Sk.builtin.int_(0), @@ -282,7 +282,7 @@ const $builtinmodule = function (name) { mod.pInst.clear(); }); - mod.colorMode = new Sk.builtin.func(function () { + mod.color_mode = new Sk.builtin.func(function () { const argVals = processArgs(arguments); mod.pInst.colorMode(...argVals); }); @@ -310,7 +310,7 @@ const $builtinmodule = function (name) { mod.pInst.erase(...argVals); }); - mod.noErase = new Sk.builtin.func(function () { + mod.no_erase = new Sk.builtin.func(function () { mod.pInst.noErase(); }); @@ -363,11 +363,11 @@ const $builtinmodule = function (name) { }); // Attributes - mod.ellipseMode = new Sk.builtin.func(function (mode) { + mod.ellipse_mode = new Sk.builtin.func(function (mode) { mod.pInst.ellipseMode(mode.v); }); - mod.noSmooth = new Sk.builtin.func(function () { + mod.no_smooth = new Sk.builtin.func(function () { mod.pInst.noSmooth(); }); @@ -379,11 +379,11 @@ const $builtinmodule = function (name) { mod.pInst.smooth(); }); - mod.strokeCap = new Sk.builtin.func(function (cap) { + mod.stroke_cap = new Sk.builtin.func(function (cap) { mod.pInst.strokeCap(cap.v); }); - mod.strokeJoin = new Sk.builtin.func(function (join) { + mod.stroke_join = new Sk.builtin.func(function (join) { mod.pInst.strokeJoin(join.v); }); @@ -397,15 +397,15 @@ const $builtinmodule = function (name) { mod.pInst.bezier(...argVals); }); - mod.bezierDetail = new Sk.builtin.func(function (detail) { + mod.bezier_detail = new Sk.builtin.func(function (detail) { mod.pInst.bezierDetail(detail.v); }); - mod.bezierPoint = new Sk.builtin.func(function (a, b, c, d, t) { + mod.bezier_point = new Sk.builtin.func(function (a, b, c, d, t) { mod.pInst.bezierPoint(a.v, b.v, c.v, d.v, t.v); }); - mod.bezierTangent = new Sk.builtin.func(function (a, b, c, d, t) { + mod.bezier_tangent = new Sk.builtin.func(function (a, b, c, d, t) { mod.pInst.bezierTangent(a.v, b.v, c.v, d.v, t.v); }); @@ -414,28 +414,28 @@ const $builtinmodule = function (name) { mod.pInst.curve(...argVals); }); - mod.curveDetail = new Sk.builtin.func(function (resolution) { + mod.curve_detail = new Sk.builtin.func(function (resolution) { mod.pInst.curveDetail(resolution.v); }); - mod.curveTightness = new Sk.builtin.func(function (amount) { + mod.curve_tightness = new Sk.builtin.func(function (amount) { mod.pInst.curveTightness(amount.v); }); - mod.curvePoint = new Sk.builtin.func(function (a, b, c, d, t) { + mod.curve_point = new Sk.builtin.func(function (a, b, c, d, t) { mod.pInst.curvePoint(a.v, b.v, c.v, d.v, t.v); }); - mod.curveTangent = new Sk.builtin.func(function (a, b, c, d, t) { + mod.curve_tangent = new Sk.builtin.func(function (a, b, c, d, t) { mod.pInst.curveTangent(a.v, b.v, c.v, d.v, t.v); }); // Vertex - mod.beginContour = new Sk.builtin.func(function () { + mod.begin_contour = new Sk.builtin.func(function () { mod.pInst.beginContour(); }); - mod.beginShape = new Sk.builtin.func(function (kind) { + mod.begin_shape = new Sk.builtin.func(function (kind) { if (typeof(kind) === "undefined") { mod.pInst.beginShape(); } else { @@ -443,12 +443,12 @@ const $builtinmodule = function (name) { } }); - mod.bezierVertex = new Sk.builtin.func(function () { + mod.bezier_vertex = new Sk.builtin.func(function () { const argVals = processArgs(arguments); mod.pInst.bezierVertex(...argVals); }); - mod.curveVertex = new Sk.builtin.func(function (x, y, z) { + mod.curve_vertex = new Sk.builtin.func(function (x, y, z) { // curveVertex(x, y) // curveVertex(x, y, z) if (typeof(z) === "undefined") { @@ -458,11 +458,11 @@ const $builtinmodule = function (name) { } }); - mod.endContour = new Sk.builtin.func(function () { + mod.end_contour = new Sk.builtin.func(function () { mod.pInst.endContour(); }); - mod.endShape = new Sk.builtin.func(function (mode) { + mod.end_shape = new Sk.builtin.func(function (mode) { if (typeof(mode) === "undefined") { mod.pInst.endShape(); } else { @@ -470,7 +470,7 @@ const $builtinmodule = function (name) { } }); - mod.quadraticVertex = new Sk.builtin.func(function () { + mod.quadratic_vertex = new Sk.builtin.func(function () { const argVals = processArgs(arguments); mod.pInst.quadraticVertex(...argVals); }); @@ -544,7 +544,7 @@ const $builtinmodule = function (name) { } }); - mod.textLeading = new Sk.builtin.func(function (leading) { + mod.text_leading = new Sk.builtin.func(function (leading) { mod.pInst.textLeading(leading.v); }); @@ -552,24 +552,24 @@ const $builtinmodule = function (name) { mod.pInst.textSize(theSize.v); }); - mod.textStyle = new Sk.builtin.func(function (theStyle) { + mod.text_style = new Sk.builtin.func(function (theStyle) { mod.pInst.textStyle(theStyle.v); }); - mod.textWidth = new Sk.builtin.func(function (theText) { + mod.text_width = new Sk.builtin.func(function (theText) { return new Sk.builtin.float_(mod.pInst.textWidth(theText.v)); }); - mod.textAscent = new Sk.builtin.func(function () { + mod.text_ascent = new Sk.builtin.func(function () { return new Sk.builtin.float_(mod.pInst.textAscent()); }); - mod.textDescent = new Sk.builtin.func(function () { + mod.text_descent = new Sk.builtin.func(function () { return new Sk.builtin.float_(mod.pInst.textDescent()); }); // Loading & Displaying - mod.loadFont = new Sk.builtin.func(function (path) { + mod.load_font = new Sk.builtin.func(function (path) { const font = Sk.misceval.callsimArray(mod.PFont); font.v = mod.pInst.loadFont(path.v); return font; @@ -579,7 +579,7 @@ const $builtinmodule = function (name) { mod.pInst.text(theText.v, x.v, y.v); }); - mod.textFont = new Sk.builtin.func(function (font, size) { + mod.text_font = new Sk.builtin.func(function (font, size) { // textFont(font) // textFont(font, size) if (typeof(size) === "undefined") { @@ -602,19 +602,6 @@ const $builtinmodule = function (name) { mod.PFont = Sk.misceval.buildClass(mod, fontClass, "PFont", []); - - - - - - - - - - - - - mod.ambient = new Sk.builtin.func(function (r, g, b) { // ambient(gray) // ambient(red, green blue) @@ -632,7 +619,7 @@ const $builtinmodule = function (name) { } }); - mod.ambientLight = new Sk.builtin.func(function (v1, v2, v3, x, y, z) { + mod.ambient_light = new Sk.builtin.func(function (v1, v2, v3, x, y, z) { // ambientLight(v1,v2,v3) // ambientLight(v1,v2,v3,x,y,z) if (typeof(x) === "undefined") { @@ -646,16 +633,10 @@ const $builtinmodule = function (name) { } }); - mod.beginCamera = new Sk.builtin.func(function () { + mod.begin_camera = new Sk.builtin.func(function () { mod.pInst.beginCamera(); }); - - - - - - mod.blend = new Sk.builtin.func(function (v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) { if (other instanceof Sk.builtin.int_ || other instanceof Sk.builtin.float_) { @@ -669,7 +650,7 @@ const $builtinmodule = function (name) { } }); - mod.blendColor = new Sk.builtin.func(function (c1, c2, mode) { + mod.blend_color = new Sk.builtin.func(function (c1, c2, mode) { // blendColor(c1,c2,MODE) const c = Sk.misceval.callsimArray(mod.color, [ new Sk.builtin.int_(0), @@ -712,7 +693,7 @@ const $builtinmodule = function (name) { } }); - mod.createFont = new Sk.builtin.func(function (name, size, smooth, charset) { + mod.create_font = new Sk.builtin.func(function (name, size, smooth, charset) { // createFont(name, size) // createFont(name, size, smooth) // createFont(name, size, smooth, charset) @@ -727,7 +708,7 @@ const $builtinmodule = function (name) { return font; }); - mod.createGraphics = new Sk.builtin.func(function (width, height, renderer) { + mod.create_graphics = new Sk.builtin.func(function (width, height, renderer) { // createGraphics(width, height) // createGraphics(width, height, renderer) const graphics = Sk.misceval.callsimArray(mod.PGraphics); @@ -739,7 +720,7 @@ const $builtinmodule = function (name) { return graphics; }); - mod.createImage = new Sk.builtin.func(function (width, height) { + mod.create_image = new Sk.builtin.func(function (width, height) { const image = Sk.misceval.callsimArray(mod.PImage, [width, height]); image.v = mod.pInst.createImage(width.v, height.v); return image; @@ -773,7 +754,7 @@ const $builtinmodule = function (name) { return new Sk.builtin.float_(mod.pInst.degrees(angle.v)); }); - mod.directionalLight = new Sk.builtin.func(function (v1,v2,v3,nx,ny,nz) { + mod.directional_light = new Sk.builtin.func(function (v1,v2,v3,nx,ny,nz) { // directionalLight(v1,v2,v3,nx,ny,nz) mod.pInst.directionalLight(v1.v,v2.v,v3.v,nx.v,ny.v,nz.v); }); @@ -803,7 +784,7 @@ const $builtinmodule = function (name) { } }); - mod.endCamera = new Sk.builtin.func(function () { + mod.end_camera = new Sk.builtin.func(function () { // endCamera() mod.pInst.endCamera(); }); @@ -846,7 +827,7 @@ const $builtinmodule = function (name) { - mod.lightFalloff = new Sk.builtin.func(function (constant, linear, quadratic) { + mod.light_falloff = new Sk.builtin.func(function (constant, linear, quadratic) { // lightFalloff(constant,linear,quadratic) mod.pInst.lightFalloff(constant.v, linear.v, quadratic.v); }); @@ -855,12 +836,12 @@ const $builtinmodule = function (name) { mod.pInst.lights(); }); - mod.lightSpecular = new Sk.builtin.func(function (v1, v2, v3) { + mod.light_specular = new Sk.builtin.func(function (v1, v2, v3) { // lightSpecular(v1,v2,v3) mod.pInst.lightSpecular(v1.v, v2.v, v3.v); }); - mod.loadBytes = new Sk.builtin.func(function (filename) { + mod.load_bytes = new Sk.builtin.func(function (filename) { // loadBytes(filename) // returns byte[] return new Sk.builtin.list(mod.pInst.loadBytes(filename.v)); @@ -868,7 +849,7 @@ const $builtinmodule = function (name) { - mod.loadShape = new Sk.builtin.func(function (filename) { + mod.load_shape = new Sk.builtin.func(function (filename) { // loadShape(filename) // returns shape const shape = Sk.misceval.callsimArray(mod.PShapeSVG, [ @@ -877,7 +858,7 @@ const $builtinmodule = function (name) { return shape; }); - mod.loadStrings = new Sk.builtin.func(function (filename) { + mod.load_strings = new Sk.builtin.func(function (filename) { // loadStrings(filename) // returns string [] return new Sk.builtin.list(mod.pInst.loadStrings(filename.v)); @@ -909,19 +890,19 @@ const $builtinmodule = function (name) { return new Sk.builtin.int_(mod.pInst.minute()); }); - mod.modelX = new Sk.builtin.func(function (x, y, z) { + mod.model_x = new Sk.builtin.func(function (x, y, z) { // modelX(x,y,z) // returns float return new Sk.builtin.float_(mod.pInst.modelX(x.v, y.v, z.v)); }); - mod.modelY = new Sk.builtin.func(function (x, y, z) { + mod.model_y = new Sk.builtin.func(function (x, y, z) { // modelY(x,y,z) // returns float return new Sk.builtin.float_(mod.pInst.modelY(x.v, y.v, z.v)); }); - mod.modelZ = new Sk.builtin.func(function (x, y, z) { + mod.model_z = new Sk.builtin.func(function (x, y, z) { // modelZ(x,y,z) // returns float return new Sk.builtin.float_(mod.pInst.modelZ(x.v, y.v, z.v)); @@ -931,7 +912,7 @@ const $builtinmodule = function (name) { return new Sk.builtin.int_(mod.pInst.month()); }); - mod.noCursor = new Sk.builtin.func(function () { + mod.no_cursor = new Sk.builtin.func(function () { mod.pInst.noCursor(); }); @@ -949,19 +930,19 @@ const $builtinmodule = function (name) { } }); - mod.noiseDetail = new Sk.builtin.func(function (octaves, falloff) { + mod.noise_detail = new Sk.builtin.func(function (octaves, falloff) { // noiseDetail(octaves); // noiseDetail(octaves,falloff); mod.pInst.noiseDetail(octaves.v, falloff.v); }); - mod.noiseSeed = new Sk.builtin.func(function (value) { + mod.noise_seed = new Sk.builtin.func(function (value) { // noiseSeed(value); int // returns float return new Sk.builtin.float_(mod.pInst.noiseSeed(value.v)); }); - mod.noLights = new Sk.builtin.func(function () { + mod.no_lights = new Sk.builtin.func(function () { mod.pInst.noLights(); }); @@ -1004,13 +985,13 @@ const $builtinmodule = function (name) { } }); - mod.pointLight = new Sk.builtin.func(function (v1,v2,v3,nx,ny,nz) { + mod.point_light = new Sk.builtin.func(function (v1,v2,v3,nx,ny,nz) { // pointLight(v1,v2,v3,nx,ny,nz) // returns None mod.pInst.pointLight(v1.v,v2.v,v3.v,nx.v,ny.v,nz.v); }); - mod.printCamera = new Sk.builtin.func(function () { + mod.print_camera = new Sk.builtin.func(function () { // printCamera() // returns None mod.pInst.printCamera(); @@ -1021,7 +1002,7 @@ const $builtinmodule = function (name) { mod.pInst.println(data.v); }); - mod.printProjection = new Sk.builtin.func(function () { + mod.print_projection = new Sk.builtin.func(function () { // printProjection() // returns None mod.pInst.printProjection(); @@ -1033,7 +1014,7 @@ const $builtinmodule = function (name) { return new Sk.builtin.float_(mod.pInst.radians(angle.v)); }); - mod.randomSeed = new Sk.builtin.func(function (value) { + mod.random_seed = new Sk.builtin.func(function (value) { // noiseSeed(value); // returns float return new Sk.builtin.float_(mod.pInst.randomSeed(value.v)); @@ -1053,7 +1034,7 @@ const $builtinmodule = function (name) { } }); - mod.requestImage = new Sk.builtin.func(function (filename, extension) { + mod.request_image = new Sk.builtin.func(function (filename, extension) { // requestImage(filename) // requestImage(filename, extension) const image = Sk.misceval.callsimArray(mod.PImage); @@ -1073,7 +1054,7 @@ const $builtinmodule = function (name) { mod.pInst.save(filename.v); }); - mod.saveFrame = new Sk.builtin.func(function (filename) { + mod.save_frame = new Sk.builtin.func(function (filename) { // saveFrame() // saveFrame(filename-####.ext) // returns None @@ -1084,24 +1065,24 @@ const $builtinmodule = function (name) { } }); - mod.saveStrings = new Sk.builtin.func(function (filename, strings) { + mod.save_strings = new Sk.builtin.func(function (filename, strings) { // saveStrings(filename,strings) mod.pInst.saveStrings(filename.v, strings.v); }); - mod.screenX = new Sk.builtin.func(function (x, y, z) { + mod.screen_x = new Sk.builtin.func(function (x, y, z) { // screenX(x,y,z) // returns float return new Sk.builtin.float_(mod.pInst.screenX(x.v, y.v, z.v)); }); - mod.screenY = new Sk.builtin.func(function (x, y, z) { + mod.screen_y = new Sk.builtin.func(function (x, y, z) { // screenY(x,y,z) // returns float return new Sk.builtin.float_(mod.pInst.screenY(x.v, y.v, z.v)); }); - mod.screenZ = new Sk.builtin.func(function (x, y, z) { + mod.screen_z = new Sk.builtin.func(function (x, y, z) { // screenZ(x,y,z) // returns float return new Sk.builtin.float_(mod.pInst.screenZ(x.v, y.v, z.v)); @@ -1129,7 +1110,7 @@ const $builtinmodule = function (name) { } }); - mod.shapeMode = new Sk.builtin.func(function (mode) { + mod.shape_mode = new Sk.builtin.func(function (mode) { // shapeMode(MODE) mod.pInst.shapeMode(mode.v); }); @@ -1153,7 +1134,7 @@ const $builtinmodule = function (name) { } }); - mod.spotLight = new Sk.builtin.func(function (v1,v2,v3,nx,ny,nz,angle,concentration) { + mod.spot_light = new Sk.builtin.func(function (v1,v2,v3,nx,ny,nz,angle,concentration) { // spotLight(v1,v2,v3,nx,ny,nz,angle,concentration) // returns None mod.pInst.spotLight(v1.v,v2.v,v3.v,nx.v,ny.v,nz.v,angle.v,concentration.v); @@ -1178,7 +1159,7 @@ const $builtinmodule = function (name) { - mod.textMode = new Sk.builtin.func(function (mode) { + mod.text_mode = new Sk.builtin.func(function (mode) { // textMode(MODE) // returns None mod.pInst.textMode(mode.v); @@ -1192,7 +1173,7 @@ const $builtinmodule = function (name) { mod.pInst.texture(img.v); }); - mod.textureMode = new Sk.builtin.func(function (mode) { + mod.texture_mode = new Sk.builtin.func(function (mode) { // textureMode(MODE) // returns None mod.pInst.textureMode(mode.v); @@ -1220,7 +1201,7 @@ const $builtinmodule = function (name) { } }); - mod.updatePixels = new Sk.builtin.func(function () { + mod.update_pixels = new Sk.builtin.func(function () { // updatePixels() mod.pInst.updatePixels(); }); @@ -1242,7 +1223,7 @@ const $builtinmodule = function (name) { mod.pInst.loop(); }); - mod.noLoop = new Sk.builtin.func(function () { + mod.no_loop = new Sk.builtin.func(function () { if (mod.pInst === null) { throw new Sk.builtin.Exception("noLoop() should be called after run()"); } @@ -1307,13 +1288,13 @@ const $builtinmodule = function (name) { // NOTE: difference with ProcessingJS // Use pmouseX() or mouse.px rather than pmouseX - mod.pmouseX = new Sk.builtin.func(function () { + mod.pmouse_x = new Sk.builtin.func(function () { return new Sk.builtin.float_(mod.pInst.pmouseX); }); // NOTE: difference with ProcessingJS // Use pmouseY() or mouse.py rather than pmouseY - mod.pmouseY = new Sk.builtin.func(function () { + mod.pmouse_y = new Sk.builtin.func(function () { return new Sk.builtin.float_(mod.pInst.pmouseY); }); @@ -1339,15 +1320,15 @@ const $builtinmodule = function (name) { mod.pInst.rotate(rads.v); }); - mod.rotateX = new Sk.builtin.func(function(rads) { + mod.rotate_x = new Sk.builtin.func(function(rads) { mod.pInst.rotateX(rads.v); }); - mod.rotateY = new Sk.builtin.func(function(rads) { + mod.rotate_y = new Sk.builtin.func(function(rads) { mod.pInst.rotateY(rads.v); }); - mod.rotateZ = new Sk.builtin.func(function(rads) { + mod.rotate_z = new Sk.builtin.func(function(rads) { mod.pInst.rotateZ(rads.v); }); @@ -1387,7 +1368,7 @@ const $builtinmodule = function (name) { mod.pInst.push(); }); - mod.applyMatrix = new Sk.builtin.func(function() { + mod.apply_matrix = new Sk.builtin.func(function() { const args = Array.prototype.slice.call(arguments, 0, 16); for (let i = 0; i < args.length; i++) { @@ -1397,11 +1378,11 @@ const $builtinmodule = function (name) { mod.pInst.applyMatrix.apply(mod.pInst, args); }); - mod.resetMatrix = new Sk.builtin.func(function() { + mod.reset_matrix = new Sk.builtin.func(function() { mod.pInst.resetMatrix(); }); - mod.printMatrix = new Sk.builtin.func(function() { + mod.print_matrix = new Sk.builtin.func(function() { return Sk.ffi.remapToPy(mod.pInst.printMatrix()); }); @@ -1426,13 +1407,18 @@ const $builtinmodule = function (name) { mod.pInst = sketch; + const isPy5Version = [Sk.builtin.str("py5"), Sk.builtin.str("py5_imported")].includes(mod.__name__) + sketch.preload = function () { - if (Sk.globals["preload"]) { + if (Sk.globals["preload"] && !isPy5Version) { Sk.misceval.callsimArray(Sk.globals["preload"]); } }; sketch.setup = function () { + if (Sk.globals["settings"] && isPy5Version) { + Sk.misceval.callsimArray(Sk.globals["settings"]); + } if (Sk.globals["setup"]) { Sk.misceval.callsimArray(Sk.globals["setup"]); @@ -1447,7 +1433,12 @@ const $builtinmodule = function (name) { mod.pInst.frameRate(frame_rate.v) sketch.draw = function () { - Sk.builtins.frame_count = new Sk.builtin.int_(sketch.frameCount); + if (mod.__name__ === Sk.builtin.str("py5")) { + mod.frame_count = new Sk.builtin.int_(sketch.frameCount); + } else { + Sk.builtins.frame_count = new Sk.builtin.int_(sketch.frameCount); + } + if (Sk.globals["draw"]) { try { Sk.misceval.callsimArray(Sk.globals["draw"]); @@ -1584,7 +1575,7 @@ const $builtinmodule = function (name) { mod.screen = Sk.misceval.callsimArray(mod.Screen); - mod.loadPixels = new Sk.builtin.func(function () { + mod.load_pixels = new Sk.builtin.func(function () { mod.pInst.loadPixels(); }); @@ -1746,7 +1737,7 @@ const $builtinmodule = function (name) { self.v.limit(value.v); }); - $loc.angleBetween = new Sk.builtin.func(function (self, vec) { + $loc.angle_between = new Sk.builtin.func(function (self, vec) { // angleBetween() Calculates the angle between two vectors return Sk.builtin.assk$(self.v.angleBetween(vec.v)); }); diff --git a/public/py5-shim.js b/public/shims/processing/py5/py5-shim.js similarity index 97% rename from public/py5-shim.js rename to public/shims/processing/py5/py5-shim.js index e71023896..57d8cc634 100644 --- a/public/py5-shim.js +++ b/public/shims/processing/py5/py5-shim.js @@ -1723,3 +1723,43 @@ const $builtinmodule = function (name) { return mod; }; + +// TODO: Make the below work without suspension error when run for the first time +// const $builtinmodule = function (name) { +// var py5 = Sk.importModule('py5_imported', false, false) +// const mod = py5.$d +// mod.__name__ = new Sk.builtin.str("py5") + +// mod.py5 = {} + +// mod.height = new Sk.builtin.int_(0) +// mod.width = new Sk.builtin.int_(0) + +// mod.size = new Sk.builtin.func(function (w, h, mode) { +// if (typeof(mode) === "undefined") { +// mode = mod.P2D; +// } +// mod.pInst.createCanvas(w.v, h.v, mode.v); +// mod.width = new Sk.builtin.int_(mod.pInst.width); +// mod.height = new Sk.builtin.int_(mod.pInst.height); +// mod.renderMode = mode; +// }); + +// mod.mouse_x = new Sk.builtin.float_(0) +// mod.mouse_y = new Sk.builtin.float_(0) + +// const updateMouseCoords = (e) => { +// if (mod.pInst && mod.pInst.mouseX>=0 && mod.pInst.mouseY>=0 && mod.pInst.mouseX <= mod.width && mod.pInst.mouseY <= mod.height) { +// mod.mouse_x = new Sk.builtin.float_(mod.pInst.mouseX); +// mod.mouse_y = new Sk.builtin.float_(mod.pInst.mouseY); +// } +// } +// document.getElementById(Sk.p5.sketch).addEventListener('mousemove', updateMouseCoords) + +// delete Sk.builtins.height +// delete Sk.builtins.width +// delete Sk.builtins.mouse_x +// delete Sk.builtins.mouse_y + +// return mod +// } diff --git a/public/shims/processing/py5_imported_mode/py5_imported.js b/public/shims/processing/py5_imported_mode/py5_imported.js new file mode 100644 index 000000000..f6d0b1285 --- /dev/null +++ b/public/shims/processing/py5_imported_mode/py5_imported.js @@ -0,0 +1,51 @@ +const $builtinmodule = function(name) { + var py5 = Sk.importModule('p5', false, false) + const mod = py5.$d + mod.__name__ = new Sk.builtin.str("py5_imported") + + const processArgs = function processArgumentValues(arguments_) { + const argVals = []; + for (a of arguments_) { + if (typeof(a) !== 'undefined') { + argVals.push(a.v); + } + } + + return argVals; + }; + + mod.frame_rate = new Sk.builtin.func(function (fr) { + mod.pInst.frameRate(fr.v); + }); + + mod.color = mod.Color + delete mod.Color + mod.get = new Sk.builtin.func(function () { + const argVals = processArgs(arguments); + const colorArgs = mod.pInst.get(...argVals) + const colorArgsArray = [ + new Sk.builtin.float_(colorArgs[0]), + new Sk.builtin.float_(colorArgs[1]), + new Sk.builtin.float_(colorArgs[2]) + ] + return new Sk.misceval.callsimArray(mod.color, colorArgsArray) + }); + + runFunction = mod.run + mod.run_sketch = new Sk.builtin.func(function () { + Sk.misceval.callsim(runFunction) + }) + delete mod.run + + mod.remap = mod.map + delete mod.map + + delete mod.DEGREES + delete mod.RADIANS + delete mod.lightness + delete mod.erase + delete mod.no_erase + delete mod.text_style + + return mod +} diff --git a/public/shims/processing/py5_imported_mode/py5_imported_mode.py b/public/shims/processing/py5_imported_mode/py5_imported_mode.py new file mode 100644 index 000000000..388d28ad4 --- /dev/null +++ b/public/shims/processing/py5_imported_mode/py5_imported_mode.py @@ -0,0 +1,2 @@ +import p5 +from py5_imported import * diff --git a/public/pygal.js b/public/shims/pygal/pygal.js similarity index 100% rename from public/pygal.js rename to public/shims/pygal/pygal.js diff --git a/public/_internal_sense_hat.js b/public/shims/sense_hat/_internal_sense_hat.js similarity index 100% rename from public/_internal_sense_hat.js rename to public/shims/sense_hat/_internal_sense_hat.js diff --git a/public/sense_hat_blob.py b/public/shims/sense_hat/sense_hat_blob.py similarity index 100% rename from public/sense_hat_blob.py rename to public/shims/sense_hat/sense_hat_blob.py diff --git a/src/components/Editor/Runners/PythonRunner/PythonRunner.js b/src/components/Editor/Runners/PythonRunner/PythonRunner.js index 40b7dbf94..393b59c2f 100644 --- a/src/components/Editor/Runners/PythonRunner/PythonRunner.js +++ b/src/components/Editor/Runners/PythonRunner/PythonRunner.js @@ -14,6 +14,40 @@ import VisualOutputPane from './VisualOutputPane'; import OutputViewToggle from './OutputViewToggle'; import { SettingsContext } from '../../../../settings'; +const externalLibraries = { + "./pygal/__init__.js": { + path: `${process.env.PUBLIC_URL}/shims/pygal/pygal.js`, + dependencies: [ + 'https://cdnjs.cloudflare.com/ajax/libs/highcharts/6.0.2/highcharts.js', + 'https://cdnjs.cloudflare.com/ajax/libs/highcharts/6.0.2/js/highcharts-more.js' + ], + }, + "./py5/__init__.js": { + path: `${process.env.PUBLIC_URL}/shims/processing/py5/py5-shim.js`, + dependencies: [ + 'https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.1/p5.js' + ] + }, + "./py5_imported/__init__.js": { + path: `${process.env.PUBLIC_URL}/shims/processing/py5_imported_mode/py5_imported.js`, + }, + "./py5_imported_mode.py": { + path: `${process.env.PUBLIC_URL}/shims/processing/py5_imported_mode/py5_imported_mode.py` + }, + "./p5/__init__.js": { + path: `${process.env.PUBLIC_URL}/shims/processing/p5/p5-shim.js`, + dependencies: [ + 'https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.1/p5.js' + ] + }, + "./_internal_sense_hat/__init__.js": { + path: `${process.env.PUBLIC_URL}/shims/sense_hat/_internal_sense_hat.js` + }, + "./sense_hat.py": { + path: `${process.env.PUBLIC_URL}/shims/sense_hat/sense_hat_blob.py` + } +}; + const PythonRunner = () => { const projectCode = useSelector((state) => state.editor.project.components); const isSplitView = useSelector((state) => state.editor.isSplitView); @@ -64,40 +98,10 @@ const PythonRunner = () => { [drawTriggered, codeRunTriggered] ) - const externalLibraries = { - "./pygal/__init__.js": { - path: `${process.env.PUBLIC_URL}/pygal.js`, - dependencies: [ - 'https://cdnjs.cloudflare.com/ajax/libs/highcharts/6.0.2/highcharts.js', - 'https://cdnjs.cloudflare.com/ajax/libs/highcharts/6.0.2/js/highcharts-more.js' - ], - }, - "./py5/__init__.js": { - path: `${process.env.PUBLIC_URL}/py5-shim.js`, - dependencies: [ - 'https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.1/p5.js' - ] - }, - "./p5/__init__.js": { - path: `${process.env.PUBLIC_URL}/p5-shim.js`, - dependencies: [ - 'https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.1/p5.js' - ] - }, - "./_internal_sense_hat/__init__.js": { - path: `${process.env.PUBLIC_URL}/_internal_sense_hat.js` - }, - "./sense_hat.py": { - path: `${process.env.PUBLIC_URL}/sense_hat_blob.py` - }, - "./py5_imported_mode.py": { - path: `${process.env.PUBLIC_URL}/py5_imported_mode.py` - } - }; - const visualLibraries =[ "./pygal/__init__.js", "./py5/__init__.js", + "./py5_imported/__init__.js", "./p5/__init__.js", "./_internal_sense_hat/__init__.js", "src/builtin/turtle/__init__.js" @@ -120,9 +124,11 @@ const PythonRunner = () => { dispatch(setSenseHatEnabled(true)) } - if(x === "./py5/__init__.js" || x === "./p5/__init__.js") { + if(x === "./p5/__init__.js" || x === "./py5/__init__.js") { dispatch(triggerDraw()) } + + // TODO: Handle pre-importing py5_imported when refactored py5 shim imported if (visualLibraries.includes(x)) { setHasVisualOutput(true) @@ -144,29 +150,13 @@ const PythonRunner = () => { if (externalLibraries[x]) { var externalLibraryInfo = externalLibraries[x]; - return Sk.misceval.promiseToSuspension( - new Promise(function (resolve, reject) { - // get the main skulpt extenstion - var request = new XMLHttpRequest(); - request.open("GET", externalLibraryInfo.path); - request.onload = function () { - if (request.status === 200) { - resolve(request.responseText); - } else { - reject("File not found: '" + x + "'"); - } - }; - request.onerror = function () { - reject("File not found: '" + x + "'"); - } - - request.send(); - }).then(function (code) { + return externalLibraries[x].code || Sk.misceval.promiseToSuspension( + fetch(externalLibraryInfo.path).then((response) => response.text()).then((code) => { if (!code) { throw new Sk.builtin.ImportError("Failed to load remote module"); } - + externalLibraries[x].code = code var promise; function mapUrlToPromise(path) { @@ -186,7 +176,6 @@ const PythonRunner = () => { }); } } - if (externalLibraryInfo.loadDepsSynchronously) { promise = (externalLibraryInfo.dependencies || []).reduce((p, url) => { return p.then(() => mapUrlToPromise(url)); diff --git a/src/components/Editor/Runners/PythonRunner/PythonRunner.test.js b/src/components/Editor/Runners/PythonRunner/PythonRunner.test.js index ff0e9e8d8..00cb5ef50 100644 --- a/src/components/Editor/Runners/PythonRunner/PythonRunner.test.js +++ b/src/components/Editor/Runners/PythonRunner/PythonRunner.test.js @@ -180,6 +180,36 @@ describe('When in split view, py5 imported and code run', () => { }) }) +describe('When in split view, py5_imported imported and code run', () => { + let store; + let queryByText; + beforeEach(() => { + const middlewares = [] + const mockStore = configureStore(middlewares) + const initialState = { + editor: { + project: { + components: [ + { + content: "import py5_imported" + } + ], + image_list: [] + }, + codeRunTriggered: true, + isSplitView: true + } + } + store = mockStore(initialState); + ({queryByText} = render()); + }) + + test('Visual tab is shown', async () => { + const visualTab = queryByText('output.visualOutput') + expect(visualTab).toBeInTheDocument() + }) +}) + describe('When in split view, pygal imported and code run', () => { let store; let queryByText; @@ -335,6 +365,36 @@ describe('When in tabbed view, py5 imported and code run', () => { }) }) +describe('When in tabbed view, py5_imported imported and code run', () => { + let store; + let queryByText; + beforeEach(() => { + const middlewares = [] + const mockStore = configureStore(middlewares) + const initialState = { + editor: { + project: { + components: [ + { + content: "import py5_imported" + } + ], + image_list: [] + }, + codeRunTriggered: true, + isSplitView: false + } + } + store = mockStore(initialState); + ({queryByText} = render()); + }) + + test('Visual tab is not hidden', async () => { + const visualTab = queryByText('output.visualOutput') + expect(visualTab).toBeInTheDocument() + }) +}) + describe('When in tabbed view, pygal imported and code run', () => { let store; let queryByText;