Skip to content

Commit d248f40

Browse files
authored
chore: Turtle test exercise and production Python execution environment (#3029)
The Python execution environment is identical to production and a Turtle example was added for easy local testing.
1 parent 78231dd commit d248f40

File tree

7 files changed

+118
-6
lines changed

7 files changed

+118
-6
lines changed

db/seeds/turtle/default.pylintrc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[MASTER]
2+
3+
[MESSAGES CONTROL]
4+
5+
[REPORTS]
6+
7+
[BASIC]

db/seeds/turtle/main.py

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# This example is based on content from the 2020 openHPI course
2+
# "Programmieren lernen mit Python" ("Learning to Program with Python")
3+
# Authors: Kira Grammel, Nina Ihde, Selina Reinhard, and Sebastian Serth
4+
# Published by: openHPI, Hasso-Plattner-Institut für Digital Engineering gGmbH
5+
# License: CC BY-NC-SA 4.0, https://creativecommons.org/licenses/by-nc-sa/4.0
6+
#
7+
# The course is freely available at: https://open.hpi.de/courses/pythonjunior2020
8+
9+
from turtle import *
10+
11+
def erstelle_turtle(x, y, rotationsWinkel = 0, shape = "triangle", color = "green"):
12+
steuerung = Turtle()
13+
steuerung.speed(0) # schnellste Animationsgeschwindigkeit, um sichtbare Bewegung zu vermeiden
14+
steuerung.shape(shape)
15+
steuerung.color(color)
16+
steuerung.right(rotationsWinkel)
17+
steuerung.penup()
18+
steuerung.goto(x, y)
19+
steuerung.direction = "stop" # nur für Kopf relevant
20+
return steuerung
21+
22+
rechts = erstelle_turtle(180, -160)
23+
unten = erstelle_turtle(160, -180, 90)
24+
links = erstelle_turtle(140, -160, 180)
25+
oben = erstelle_turtle(160, -140, 270)
26+
kopf = erstelle_turtle(0, 0, 0, "square", "black")
27+
28+
def setze_richtung(dahin, dahinNicht):
29+
# Vermeiden, dass Schlangenkopf zurück in sich selbst laufen kann
30+
if kopf.direction != dahinNicht:
31+
kopf.direction = dahin
32+
kopf_bewegen()
33+
34+
def kopf_bewegen():
35+
if kopf.direction == "down":
36+
y = kopf.ycor()
37+
kopf.sety(y - 20)
38+
39+
elif kopf.direction == "right":
40+
x = kopf.xcor()
41+
kopf.setx(x + 20)
42+
43+
elif kopf.direction == "up":
44+
y = kopf.ycor()
45+
kopf.sety(y + 20)
46+
47+
elif kopf.direction == "left":
48+
x = kopf.xcor()
49+
kopf.setx(x - 20)
50+
51+
52+
def checke_kollision_mit_fensterrand():
53+
if kopf.xcor() > 190 or kopf.xcor() < -190 or kopf.ycor() > 190 or kopf.ycor() < -190:
54+
spiel_neustarten()
55+
56+
57+
def interpretiere_eingabe(x, y):
58+
if (x >= 170 and x <= 190 and y >= -170 and y <= -150):
59+
setze_richtung("right", "left")
60+
elif (x >= 150 and x <= 170 and y >= -190 and y <= -170):
61+
setze_richtung("down", "up")
62+
elif (x >= 130 and x <= 150 and y >= -170 and y <= -150):
63+
setze_richtung("left", "right")
64+
elif (x >= 150 and x <= 170 and y >= -150 and y <= -130):
65+
setze_richtung("up", "down")
66+
else:
67+
return None
68+
checke_kollision_mit_fensterrand()
69+
70+
def spiel_neustarten():
71+
kopf.goto(0, 0)
72+
kopf.direction = "stop"
73+
74+
onclick(interpretiere_eingabe)
75+
mainloop()

db/seeds/turtle/test_style.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from pylint import epylint as lint
2+
import glob
3+
4+
pylint_opts = ['--rcfile=default.pylintrc']
5+
exercise = glob.glob('main.py')[0]
6+
lint.lint(exercise, options=pylint_opts)
7+
exit()

spec/factories/execution_environment.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,18 +73,18 @@
7373
created_by_teacher
7474
default_memory_limit
7575
default_cpu_limit
76-
docker_image { 'openhpi/co_execenv_python:3.4' }
76+
docker_image { 'openhpi/co_execenv_python:3.8' }
7777
file_type { association :dot_py, user: }
7878
help
79-
name { 'Python 3.4' }
79+
name { 'Python 3.8' }
8080
network_enabled { false }
8181
privileged_execution { false }
8282
permitted_execution_time { 10.seconds }
8383
pool_size { 0 }
84-
run_command { 'python3 %{filename}' }
84+
run_command { 'python3 -B /usr/lib/python3.8/webpython.py -f %{filename}' }
8585
singleton_execution_environment
8686
test_command { 'python3 -m unittest --verbose %{module_name}' }
87-
testing_framework { 'PyUnitAdapter' }
87+
testing_framework { 'PyUnitAndPyLintAdapter' }
8888
end
8989

9090
factory :ruby, class: 'ExecutionEnvironment' do

spec/factories/exercise.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,20 @@ def create_seed_file(exercise, path, file_attributes = {})
7575
end
7676
end
7777

78+
factory :turtle, class: 'Exercise' do
79+
created_by_teacher
80+
description { 'Interactive Turtle test exercise.' }
81+
execution_environment { association :python, user: }
82+
instructions
83+
title { 'Interactive Turtle' }
84+
85+
after(:create) do |exercise|
86+
create_seed_file(exercise, 'turtle/main.py', role: 'main_file')
87+
create_seed_file(exercise, 'turtle/test_style.py', feedback_message: 'Your solution is not correctly formated.', hidden: true, role: 'teacher_defined_linter')
88+
create_seed_file(exercise, 'turtle/default.pylintrc', hidden: true, role: 'regular_file')
89+
end
90+
end
91+
7892
factory :fibonacci, class: 'Exercise' do
7993
created_by_teacher
8094
description { 'Implement a recursive function that calculates a requested Fibonacci number.' }

spec/factories/file_type.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,15 @@
124124
singleton_file_type
125125
end
126126

127+
factory :dot_pylintrc, class: 'FileType' do
128+
created_by_admin
129+
editor_mode { 'ace/mode/ini' }
130+
file_extension { '.pylintrc' }
131+
indent_size { 4 }
132+
name { 'Pylintrc' }
133+
singleton_file_type
134+
end
135+
127136
factory :dot_rb, class: 'FileType' do
128137
created_by_admin
129138
editor_mode { 'ace/mode/ruby' }

spec/services/proforma_service/convert_task_to_exercise_spec.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
ProformaXML::Task.new(
3333
title: 'title',
3434
description:,
35-
proglang: {name: 'python', version: '3.4'},
35+
proglang: {name: 'python', version: '3.8'},
3636
uuid: 'uuid',
3737
parent_uuid: 'parent_uuid',
3838
language: 'language',
@@ -146,7 +146,7 @@
146146
before { create(:python) }
147147

148148
it 'sets the execution_environment based on proglang name and value' do
149-
expect(convert_to_exercise_service).to have_attributes(execution_environment: have_attributes(name: 'Python 3.4'))
149+
expect(convert_to_exercise_service).to have_attributes(execution_environment: have_attributes(name: 'Python 3.8'))
150150
end
151151
end
152152

0 commit comments

Comments
 (0)