Exemple #1
0
def save_program (user):

    body = request.json
    if not type_check (body, 'dict'):
        return 'body must be an object', 400
    if not object_check (body, 'code', 'str'):
        return 'code must be a string', 400
    if not object_check (body, 'name', 'str'):
        return 'name must be a string', 400
    if not object_check (body, 'level', 'int'):
        return 'level must be an integer', 400
    if 'adventure_name' in body:
        if not object_check (body, 'adventure_name', 'str'):
            return 'if present, adventure_name must be a string', 400

    # We execute the saved program to see if it would generate an error or not
    error = None
    try:
        hedy_errors = TRANSLATIONS.get_translations(requested_lang(), 'HedyErrorMessages')
        result = hedy.transpile(body ['code'], body ['level'])
    except hedy.HedyException as E:
        error_template = hedy_errors[E.error_code]
        error = error_template.format(**E.arguments)
    except Exception as E:
        error = str(E)

    name = body ['name']

    # If name ends with (N) or (NN), we strip them since it's very likely these addenda were added by our server to avoid overwriting existing programs.
    name = re.sub (' \(\d+\)$', '', name)
    # We check if a program with a name `xyz` exists in the database for the username. If it does, we exist whether `xyz (1)` exists, until we find a program `xyz (NN)` that doesn't exist yet.
    # It'd be ideal to search by username & program name, but since DynamoDB doesn't allow searching for two indexes at the same time, this would require to create a special index to that effect, which is cumbersome.
    # For now, we bring all existing programs for the user and then search within them for repeated names.
    existing = db_get_many ('programs', {'username': user ['username']}, True)
    name_counter = 0
    for program in existing:
        if re.match ('^' + re.escape (name) + '( \(\d+\))*', program ['name']):
            name_counter = name_counter + 1
    if name_counter:
        name = name + ' (' + str (name_counter) + ')'

    stored_program = {
        'id': uuid.uuid4().hex,
        'session': session_id(),
        'date': timems (),
        'lang': requested_lang(),
        'version': version(),
        'level': body ['level'],
        'code': body ['code'],
        'name': name,
        'server_error': error,
        'username': user ['username']
    }

    if 'adventure_name' in body:
        stored_program ['adventure_name'] = body ['adventure_name']

    db_set('programs', stored_program)

    program_count = 0
    if 'program_count' in user:
        program_count = user ['program_count']
    db_set('users', {'username': user ['username'], 'program_count': program_count + 1})

    return jsonify({'name': name})
Exemple #2
0
 def test_transpile_ask(self):
     result = hedy.transpile("antwoord is ask 'wat is je lievelingskleur?'",
                             self.level)
     expected = "antwoord = input('wat is je lievelingskleur?')"
     self.assertEqual(expected, result.code)
     self.assertEqual(False, result.has_turtle)
Exemple #3
0
 def test_print_with_var(self):
     result = hedy.transpile("naam is Hedy\nprint('ik heet' naam)", 19)
     self.assertEqual("naam = 'Hedy'\nprint('ik heet'+str(naam))", result)
Exemple #4
0
 def test_transpile_ask(self):
     result = hedy.transpile(
         "antwoord is input('wat is je lievelingskleur?')", 17)
     self.assertEqual(result,
                      "antwoord = input('wat is je lievelingskleur?')")
Exemple #5
0
 def test_print_with_var(self):
     result = hedy.transpile("naam is Hedy\nprint 'ik heet' naam",
                             self.level)
     expected = "naam = 'Hedy'\nprint('ik heet'+str(naam))"
     self.assertEqual(expected, result.code)
     self.assertEqual(False, result.has_turtle)
Exemple #6
0
 def test_print(self):
     result = hedy.transpile("print Hallo welkom bij Hedy!", self.level)
     expected = "print('Hallo welkom bij Hedy!')"
     self.assertEqual(expected, result.code)
     self.assertEqual(False, result.has_turtle)
     self.assertEqual('Hallo welkom bij Hedy!', self.run_code(result))
Exemple #7
0
def parse():
    body = request.json
    if not body:
        return "body must be an object", 400
    if 'code' not in body:
        return "body.code must be a string", 400
    if 'level' not in body:
        return "body.level must be a string", 400
    if 'adventure_name' in body and not isinstance(body['adventure_name'],
                                                   str):
        return "if present, body.adventure_name must be a string", 400

    code = body['code']
    level = int(body['level'])

    # Language should come principally from the request body,
    # but we'll fall back to browser default if it's missing for whatever
    # reason.
    lang = body.get('lang', requested_lang())

    # true if kid enabled the read aloud option
    read_aloud = body.get('read_aloud', False)

    response = {}
    username = current_user(request)['username'] or None

    querylog.log_value(level=level,
                       lang=lang,
                       session_id=session_id(),
                       username=username)

    try:
        hedy_errors = TRANSLATIONS.get_translations(lang, 'HedyErrorMessages')
        with querylog.log_time('transpile'):
            transpile_result = hedy.transpile(code, level)
            python_code = transpile_result.code
            has_turtle = transpile_result.has_turtle

        response['has_turtle'] = has_turtle
        if has_turtle:
            response["Code"] = textwrap.dedent("""\
            # coding=utf8
            import random, time, turtle
            t = turtle.Turtle()
            t.hideturtle()
            t.speed(0)
            t.penup()
            t.goto(50,100)
            t.showturtle()
            t.pendown()
            t.speed(3)
            """) + python_code
        else:
            response["Code"] = "# coding=utf8\nimport random\n" + python_code

    except hedy.InvalidSpaceException as ex:
        traceback.print_exc()
        response = invalid_space_error_to_response(ex, hedy_errors)
    except hedy.ParseException as ex:
        traceback.print_exc()
        response = parse_error_to_response(ex, hedy_errors)
    except hedy.HedyException as ex:
        traceback.print_exc()
        response = hedy_error_to_response(ex, hedy_errors)

    except Exception as E:
        traceback.print_exc()
        print(f"error transpiling {code}")
        response["Error"] = str(E)
    querylog.log_value(server_error=response.get('Error'))
    parse_logger.log({
        'session': session_id(),
        'date': str(datetime.datetime.now()),
        'level': level,
        'lang': lang,
        'code': code,
        'server_error': response.get('Error'),
        'version': version(),
        'username': username,
        'read_aloud': read_aloud,
        'is_test': 1 if os.getenv('IS_TEST_ENV') else None,
        'adventure_name': body.get('adventure_name', None)
    })

    return jsonify(response)
Exemple #8
0
 def test_echo_without_argument(self):
     result = hedy.transpile("ask wat?\necho", self.level)
     expected = "answer = input('wat?')\nprint(answer)"
     self.assertEqual(expected, result.code)
     self.assertEqual(False, result.has_turtle)
Exemple #9
0
 def test_forward(self):
     result = hedy.transpile("forward 50", self.level)
     expected = textwrap.dedent("""\
 t.forward(50)
 time.sleep(0.1)""")
     self.assertEqual(expected, result.code)
Exemple #10
0
 def test_print_multiple_lines(self):
     result = hedy.transpile("print Hallo welkom bij Hedy\nprint Mooi hoor",
                             self.level)
     expected = "print('Hallo welkom bij Hedy')\nprint('Mooi hoor')"
     self.assertEqual(expected, result.code)
     self.assertEqual(False, result.has_turtle)
Exemple #11
0
 def test_ask_Spanish(self):
     result = hedy.transpile("ask ask Cuál es tu color favorito?",
                             self.level)
     expected = "answer = input('ask Cuál es tu color favorito?')"
     self.assertEqual(expected, result.code)
     self.assertEqual(False, result.has_turtle)
Exemple #12
0
    def test_transpile_print_level_2(self):
        with self.assertRaises(Exception) as context:
            result = hedy.transpile("print felienne 123", 3)

        self.assertEqual('Unquoted Text', context.exception.args[0]
                         )  # hier moet nog we een andere foutmelding komen!
Exemple #13
0
 def test_transpile_other(self):
     with self.assertRaises(Exception) as context:
         result = hedy.transpile("abc felienne 123", 3)
     self.assertEqual(str(context.exception), 'Invalid')
Exemple #14
0
    def test_simple_calculation_without_space(self):
        code = "nummer is 4+5"
        result = hedy.transpile(code, 6)

        expected = "nummer = int(4) + int(5)"
        self.assertEqual(expected, result)
Exemple #15
0
 def test_incomplete_gives_Incomplete(self):
     with self.assertRaises(hedy.IncompleteCommandException) as context:
         result = hedy.transpile("print", self.level)
     self.assertEqual('Incomplete', context.exception.error_code)
Exemple #16
0
 def test_turn_no_args(self):
     result = hedy.transpile("turn", self.level)
     expected = textwrap.dedent("""\
 t.right(90)""")
     self.assertEqual(expected, result.code)
     self.assertEqual(True, result.has_turtle)
Exemple #17
0
 def test_incomplete_on_line_2_gives_Incomplete(self):
     with self.assertRaises(hedy.IncompleteCommandException) as context:
         result = hedy.transpile("print lalalala\nprint", self.level)
     self.assertEqual('Incomplete', context.exception.error_code)
     self.assertEqual(
         'print', str(context.exception.arguments['incomplete_command']))
Exemple #18
0
 def test_one_turn_left(self):
     result = hedy.transpile("turn left", self.level)
     expected = textwrap.dedent("""\
 t.left(90)""")
     self.assertEqual(expected, result.code)
     self.assertEqual(True, result.has_turtle)
Exemple #19
0
 def test_identifies_backtick_inside_conditional(self):
   self.assertRaises(hedy.UnquotedTextException, lambda: hedy.transpile("if 1 is 1 print `yay!` else print `nay`", self.level))
Exemple #20
0
 def test_lines_with_spaces_gives_invalid(self):
     with self.assertRaises(hedy.InvalidSpaceException) as context:
         result = hedy.transpile(
             " print Hallo welkom bij Hedy!\n print Hallo welkom bij Hedy!",
             self.level)
     self.assertEqual('Invalid Space', context.exception.error_code)
Exemple #21
0
def parse():
    body = request.json
    if not body:
        return "body must be an object", 400
    if 'code' not in body:
        return "body.code must be a string", 400
    if 'level' not in body:
        return "body.level must be a string", 400

    code = body['code']
    level = int(body['level'])
    # Language should come principally from the request body,
    # but we'll fall back to browser default if it's missing for whatever
    # reason.
    lang = body.get('lang', requested_lang())

    # For debugging
    print(f"got code {code}")

    response = {}
    username = current_user(request)['username'] or None

    # Check if user sent code
    if not code:
        response["Error"] = "no code found, please send code."
    # is so, parse
    else:
        try:
            hedy_errors = TRANSLATIONS.get_translations(
                lang, 'HedyErrorMessages')
            result = hedy.transpile(code, level)
            response["Code"] = "# coding=utf8\nimport random\n" + result
        except hedy.HedyException as E:
            # some 'errors' can be fixed, for these we throw an exception, but also
            # return fixed code, so it can be ran
            if E.args[0] == "Invalid Space":
                error_template = hedy_errors[E.error_code]
                response[
                    "Code"] = "# coding=utf8\n" + E.arguments['fixed_code']
                response["Warning"] = error_template.format(**E.arguments)
            elif E.args[0] == "Parse":
                error_template = hedy_errors[E.error_code]
                # Localize the names of characters
                if 'character_found' in E.arguments:
                    E.arguments['character_found'] = hedy_errors[
                        E.arguments['character_found']]
                response["Error"] = error_template.format(**E.arguments)
            elif E.args[0] == "Unquoted Text":
                error_template = hedy_errors[E.error_code]
                response["Error"] = error_template.format(**E.arguments)
            else:
                error_template = hedy_errors[E.error_code]
                response["Error"] = error_template.format(**E.arguments)
        except Exception as E:
            print(f"error transpiling {code}")
            response["Error"] = str(E)

    logger.log({
        'session': session_id(),
        'date': str(datetime.datetime.now()),
        'level': level,
        'lang': lang,
        'code': code,
        'server_error': response.get('Error'),
        'version': version(),
        'username': username,
        'is_test': 1 if os.getenv('IS_TEST_ENV') else None
    })

    return jsonify(response)
Exemple #22
0
 def test_word_plus_period_gives_invalid(self):
     with self.assertRaises(hedy.InvalidCommandException) as context:
         result = hedy.transpile("word.", self.level)
     self.assertEqual('Invalid', context.exception.error_code)
Exemple #23
0
 def test_print(self):
     result = hedy.transpile("print 'ik heet'", self.level)
     expected = "print('ik heet')"
     self.assertEqual(expected, result.code)
     self.assertEqual(False, result.has_turtle)
Exemple #24
0
 def test_empty_gives_exception(self):
     with self.assertRaises(hedy.EmptyProgramException) as context:
         result = hedy.transpile("", self.level)
Exemple #25
0
 def test_print_with_calc_no_spaces(self):
     result = hedy.transpile("print '5 keer 5 is ' 5*5", self.level)
     expected = "print('5 keer 5 is '+str(int(5) * int(5)))"
     self.assertEqual(expected, result.code)
     self.assertEqual(False, result.has_turtle)
Exemple #26
0
 def test_non_keyword_gives_Invalid(self):
     with self.assertRaises(hedy.InvalidCommandException) as context:
         result = hedy.transpile("groen", self.level)
     self.assertEqual('Invalid', context.exception.error_code)
Exemple #27
0
 def test_print(self):
     result = hedy.transpile("print('ik heet')", 19)
     self.assertEqual("print('ik heet')", result)
Exemple #28
0
 def test_lonely_echo_gives_LonelyEcho(self):
     code = "echo wat dan?"
     with self.assertRaises(hedy.LonelyEchoException) as context:
         result = hedy.transpile(code, self.level)
     self.assertEqual('Lonely Echo', context.exception.error_code)
Exemple #29
0
 def test_print_with_calc_no_spaces(self):
     result = hedy.transpile("print('5 keer 5 is ' 5*5)", 19)
     self.assertEqual("print('5 keer 5 is '+str(int(5) * int(5)))", result)
Exemple #30
0
 def test_transpile_ask(self):
     result = hedy.transpile("kleur is ask wat is je lievelingskleur?", 2)
     self.assertEqual(
         result,
         "import random\nkleur = input('wat is je lievelingskleur'+'?')")