Skip to content

Commit c7301bc

Browse files
committed
Type-check arg to Sprite.touching()
Previously, code like elephant.touching("Giraffe") gave an unhelpful "internal error"-type message. Instead, type-check the arg and provide a hopefully more helpful error if invalid.
2 parents 10ab76e + ccba195 commit c7301bc

3 files changed

Lines changed: 56 additions & 0 deletions

File tree

src/lib/pytch/actor.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
play_sound,
33
_get_actor_sound_mix_bus_gain,
44
_set_actor_sound_mix_bus_gain,
5+
_is_Pytch_registered_Sprite,
56
registered_instances,
67
unregister_running_instance,
78
wait_seconds,
@@ -359,6 +360,11 @@ def costume_name(self):
359360

360361
def touching(self, target_class):
361362
"(TARGET) Return whether SELF touches any TARGET instance"
363+
if not _is_Pytch_registered_Sprite(target_class):
364+
raise TypeError(
365+
"in touching(target_class), target_class must be"
366+
" a Pytch-registered Sprite class"
367+
)
362368
return (self._pytch_parent_project
363369
.instance_is_touching_any_of(self, target_class))
364370

src/lib/pytch/syscalls.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,26 @@ var $builtinmodule = function (name) {
289289
`(SECONDS) Pause for the given number of seconds`,
290290
);
291291

292+
mod._is_Pytch_registered_Sprite = skulpt_function(
293+
(obj) => {
294+
if (!Sk.builtin.checkClass(obj))
295+
return Sk.builtin.bool.false$;
296+
297+
const actor = obj.$pytchActor
298+
const is_Sprite = (
299+
actor != null
300+
&& actor.class_kind_name === "Sprite"
301+
)
302+
303+
return (
304+
is_Sprite
305+
? Sk.builtin.bool.true$
306+
: Sk.builtin.bool.false$
307+
);
308+
},
309+
"Whether the given OBJ is the class object for a Sprite"
310+
);
311+
292312
mod._effective_source_object = skulpt_function(
293313
(py_cls_or_obj) => {
294314
if (Sk.builtin.checkClass(py_cls_or_obj)) {

test/pytch/test_collision_detection.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ const {
66
assert,
77
assert_has_bbox,
88
call_method,
9+
import_deindented,
10+
one_frame,
11+
pytch_errors,
912
} = require("./pytch-testing.js");
1013
configure_mocha();
1114

@@ -15,6 +18,33 @@ configure_mocha();
1518
// Bounding box computation, collision detection.
1619

1720
describe("collision detection", () => {
21+
[
22+
{ label: "string", expr: '"Giraffe"' },
23+
{ label: "number", expr: '42' },
24+
{ label: "Stage", expr: 'AnimalStage' },
25+
{ label: "non-Sprite class", expr: 'EmptyClass' },
26+
].forEach(spec =>
27+
it(`rejects touching() of ${spec.label}`, async () => {
28+
const project = await import_deindented(`
29+
import pytch
30+
class EmptyClass: pass
31+
class AnimalStage(pytch.Stage):
32+
Backdrops = ["solid-white-stage.png"]
33+
class Elephant(pytch.Sprite):
34+
@pytch.when_I_receive("go")
35+
def try_go(self):
36+
if self.touching(${spec.expr}):
37+
pass
38+
`);
39+
40+
project.do_synthetic_broadcast("go")
41+
one_frame(project);
42+
pytch_errors.assert_sole_error_matches(
43+
/target_class must be.*Sprite class/
44+
);
45+
})
46+
);
47+
1848
with_project("py/project/bounding_boxes.py", (import_project) => {
1949
it("can extract bounding boxes", async () => {
2050
let project = await import_project();

0 commit comments

Comments
 (0)