From a41d3447f0890f6a8fe73c35e0058e108f6c61d9 Mon Sep 17 00:00:00 2001 From: Boryana Goncharenko <3010723+boryanagoncharenko@users.noreply.github.com> Date: Thu, 7 Mar 2024 15:04:37 +0200 Subject: [PATCH] Add user-friendly errors for calculations with incorrect types #3465 --- hedy.py | 174 ++++++++++------ messages.pot | 23 +- prefixes/normal.py | 24 +++ static/js/appbundle.js | 25 +++ static/js/pythonPrefixes.ts | 25 +++ tests/Tester.py | 49 +++-- tests/test_level/test_level_01.py | 16 +- tests/test_level/test_level_02.py | 10 +- tests/test_level/test_level_03.py | 23 +- tests/test_level/test_level_05.py | 10 +- tests/test_level/test_level_06.py | 75 ++++--- tests/test_level/test_level_07.py | 22 +- tests/test_level/test_level_08.py | 28 +-- tests/test_level/test_level_09.py | 12 +- tests/test_level/test_level_11.py | 10 +- tests/test_level/test_level_12.py | 266 +++++++++++++++--------- tests/test_level/test_level_14.py | 22 +- tests/test_level/test_level_16.py | 12 +- tests/test_level/test_level_17.py | 26 +-- tests/test_level/test_level_18.py | 26 +-- translations/ar/LC_MESSAGES/messages.po | 48 +++-- translations/en/LC_MESSAGES/messages.po | 40 ++-- 22 files changed, 598 insertions(+), 368 deletions(-) diff --git a/hedy.py b/hedy.py index 943afc0421e..2be62b44dbc 100644 --- a/hedy.py +++ b/hedy.py @@ -179,37 +179,47 @@ def needs_colon(rule): return f'{rule[0:pos]} _COLON {rule[pos:]}' -def _translate_index_error(code, list_name): - exception_text = gettext('catch_index_exception').replace('{list_name}', style_command(list_name)) - return textwrap.dedent(f"""\ - try: - {code} - except IndexError: - raise Exception({repr(exception_text)}) - """) +PREPROCESS_RULES = { + 'needs_colon': needs_colon +} + + +def translate_value_error(command, value, suggested_type): + return translate_error(gettext('catch_value_exception'), [ + ('{command}', command, 1), + ('{value}', value, 1), + ('{suggestion}', translate_suggestion(suggested_type), 0) + ]) + + +def translate_values_error(command, suggested_type): + return translate_error(gettext("catch_multiple_values_exception"), [ + ('{command}', command, 1), + ('{value}', '{}', 1), + ('{suggestion}', translate_suggestion(suggested_type), 0) + ]) + +def translate_error(exception_text, variables): + for template, value, is_highlighted in variables: + result = style_command(value) if is_highlighted else value + exception_text = exception_text.replace(template, result) + # The error is transpiled in f-strings with ", ' and ''' quotes. The only option is to use """. + return '"""' + exception_text + '"""' -def translate_value_error(command, value, suggestion_type): - exception_text = gettext('catch_value_exception') + +def translate_suggestion(suggestion_type): # Right now we only have three types of suggestion # In the future we might change this if the number increases if suggestion_type == 'number': - suggestion_text = gettext('suggestion_number') + return gettext('suggestion_number') elif suggestion_type == 'color': - suggestion_text = gettext('suggestion_color') + return gettext('suggestion_color') elif suggestion_type == 'note': - suggestion_text = gettext('suggestion_note') - - exception_text = exception_text.replace('{command}', style_command(command)) - exception_text = exception_text.replace('{value}', style_command(value)) - exception_text = exception_text.replace('{suggestion}', suggestion_text) - - return repr(exception_text) - - -PREPROCESS_RULES = { - 'needs_colon': needs_colon -} + return gettext('suggestion_note') + elif suggestion_type == 'numbers_or_strings': + return gettext('suggestion_numbers_or_strings') + return '' class Command: @@ -1709,7 +1719,7 @@ def make_color(self, parameter, language): def make_turtle_command(self, parameter, command, command_text, add_sleep, type): exception = '' if isinstance(parameter, str): - exception = self.make_catch_exception([parameter]) + exception = self.make_index_error_check_if_list([parameter]) variable = self.get_fresh_var('__trtl') exception_text = translate_value_error(command, variable, 'number') transpiled = exception + textwrap.dedent(f"""\ @@ -1742,27 +1752,35 @@ def make_turtle_color_command(self, parameter, command, command_text, language): {variable} = color_dict[{variable}] t.{command_text}({variable}){self.add_debug_breakpoint()}""") - def make_catch_exception(self, args): + def make_index_error_check_if_list(self, args): lists_names = [] list_args = [] - var_regex = r"[\p{Lu}\p{Ll}\p{Lt}\p{Lm}\p{Lo}\p{Nl}_]+|[\p{Mn}\p{Mc}\p{Nd}\p{Pc}·]+" # List usage comes in indexation and random choice - list_regex = fr"(({var_regex})+\[int\(({var_regex})\)-1\])|(random\.choice\(({var_regex})\))" + var_regex = r"[\p{Lu}\p{Ll}\p{Lt}\p{Lm}\p{Lo}\p{Nl}_]+|[\p{Mn}\p{Mc}\p{Nd}\p{Pc}·]+" + list_access_with_int_cast = fr"(({var_regex})+\[int\(({var_regex})\)-1\])" + list_access_without_cast = fr"(({var_regex})+\[({var_regex})-1\])" + list_access_random = fr"(random\.choice\(({var_regex})\))" + list_regex = f"{list_access_with_int_cast}|{list_access_without_cast}|{list_access_random}" for arg in args: # Expressions come inside a Tree object, so unpack them if isinstance(arg, Tree): arg = arg.children[0] for group in regex.findall(list_regex, arg): - if group[0] != '': - list_args.append(group[0]) - lists_names.append(group[1]) - else: - list_args.append(group[3]) - lists_names.append(group[4]) - code = "" - for i, list_name in enumerate(lists_names): - code += _translate_index_error(list_args[i], list_name) - return code + match = [e for e in group if e][:2] + list_args.append(match[0]) + lists_names.append(match[1]) + + errors = [self.make_index_error(list_args[i], list_name) for i, list_name in enumerate(lists_names)] + return ''.join(errors) + + def make_index_error(self, code, list_name): + exception_text = translate_error(gettext('catch_index_exception'), [('{list_name}', list_name, 1)]) + return textwrap.dedent(f"""\ + try: + {code} + except IndexError: + raise Exception({exception_text}) + """) @v_args(meta=True) @@ -1830,7 +1848,7 @@ def print(self, meta, args): r"[·\p{Lu}\p{Ll}\p{Lt}\p{Lm}\p{Lo}\p{Nl}\p{Mn}\p{Mc}\p{Nd}\p{Pc}]+|[^·\p{Lu}\p{Ll}\p{Lt}\p{Lm}\p{Lo}\p{Nl}]+", a) args_new.append(''.join([self.process_variable_for_fstring(x, meta.line) for x in res])) - exception = self.make_catch_exception(args) + exception = self.make_index_error_check_if_list(args) argument_string = ' '.join(args_new) if not self.microbit: return exception + f"print(f'{argument_string}'){self.add_debug_breakpoint()}" @@ -1883,7 +1901,7 @@ def assign(self, meta, args): value = args[1] if self.is_random(value) or self.is_list(value): - exception = self.make_catch_exception([value]) + exception = self.make_index_error_check_if_list([value]) return exception + variable_name + " = " + value + self.add_debug_breakpoint() else: if self.is_variable(value, meta.line): # if the value is a variable, this is a reassign @@ -1902,7 +1920,7 @@ def sleep(self, meta, args): value = f'"{args[0]}"' if self.is_int(args[0]) else args[0] if not self.is_int(args[0]): self.add_variable_access_location(value, meta.line) - exceptions = self.make_catch_exception(args) + exceptions = self.make_index_error_check_if_list(args) try_prefix = "try:\n" + textwrap.indent(exceptions, " ") exception_text = translate_value_error(Command.sleep, value, 'number') code = try_prefix + textwrap.dedent(f"""\ @@ -2010,7 +2028,7 @@ def print_ask_args(self, meta, args): def print(self, meta, args): argument_string = self.print_ask_args(meta, args) - exceptions = self.make_catch_exception(args) + exceptions = self.make_index_error_check_if_list(args) if not self.microbit: return exceptions + f"print(f'{argument_string}'){self.add_debug_breakpoint()}" else: @@ -2167,7 +2185,7 @@ def sleep(self, meta, args): if not self.is_int(args[0]): self.add_variable_access_location(value, meta.line) - exceptions = self.make_catch_exception(args) + exceptions = self.make_index_error_check_if_list(args) try_prefix = "try:\n" + textwrap.indent(exceptions, " ") exception_text = translate_value_error(Command.sleep, value, 'number') code = try_prefix + textwrap.dedent(f"""\ @@ -2208,7 +2226,7 @@ def assign(self, meta, args): if self.is_variable(value, meta.line): value = self.process_variable(value, meta.line) if self.is_list(value) or self.is_random(value): - exception = self.make_catch_exception([value]) + exception = self.make_index_error_check_if_list([value]) return exception + parameter + " = " + value + self.add_debug_breakpoint() else: return parameter + " = " + value @@ -2227,13 +2245,23 @@ def process_token_or_tree(self, argument, meta): self.add_variable_access_location(argument, meta.line) return f'int({argument})' + def process_token_or_tree_for_calculation(self, argument, command, meta): + if type(argument) is Tree: + return f'{str(argument.children[0])}' + if argument.isnumeric(): + latin_numeral = int(argument) + return f'int({latin_numeral})' + self.add_variable_access_location(argument, meta.line) + exception_text = translate_value_error(command, argument, 'number') + return f'int_with_error({argument}, {exception_text})' + def process_calculation(self, args, operator, meta): # arguments of a sum are either a token or a # tree resulting from earlier processing # for trees we need to grap the inner string # for tokens we add int around them - args = [self.process_token_or_tree(a, meta) for a in args] + args = [self.process_token_or_tree_for_calculation(a, operator, meta) for a in args] return Tree('sum', [f'{args[0]} {operator} {args[1]}']) def addition(self, meta, args): @@ -2478,7 +2506,7 @@ def call(self, meta, args): def returns(self, meta, args): argument_string = self.print_ask_args(meta, args) - exception = self.make_catch_exception(args) + exception = self.make_index_error_check_if_list(args) return exception + f"return f'''{argument_string}'''" def number(self, meta, args): @@ -2507,14 +2535,6 @@ def text_in_quotes(self, meta, args): return f'"{text}"' return f"'{text}'" - def process_token_or_tree(self, argument, meta): - if isinstance(argument, Tree): - return f'{str(argument.children[0])}' - else: - # this is a variable, add to the table - self.add_variable_access_location(argument, meta.line) - return argument - def print_ask_args(self, meta, args): result = super().print_ask_args(meta, args) if "'''" in result: @@ -2523,7 +2543,7 @@ def print_ask_args(self, meta, args): def print(self, meta, args): argument_string = self.print_ask_args(meta, args) - exception = self.make_catch_exception(args) + exception = self.make_index_error_check_if_list(args) if not self.microbit: return exception + f"print(f'''{argument_string}''')" + self.add_debug_breakpoint() else: @@ -2573,11 +2593,11 @@ def assign(self, meta, args): self.check_var_usage_when_quotes_are_required(right_hand_side, meta) if isinstance(right_hand_side, Tree): - exception = self.make_catch_exception([right_hand_side.children[0]]) + exception = self.make_index_error_check_if_list([right_hand_side.children[0]]) return exception + left_hand_side + " = " + right_hand_side.children[0] + self.add_debug_breakpoint() else: # we no longer escape quotes here because they are now needed - exception = self.make_catch_exception([right_hand_side]) + exception = self.make_index_error_check_if_list([right_hand_side]) return exception + left_hand_side + " = " + right_hand_side + "" + self.add_debug_breakpoint() def var(self, meta, args): @@ -2612,6 +2632,40 @@ def make_turn(self, parameter): def make_forward(self, parameter): return self.make_turtle_command(parameter, Command.forward, 'forward', True, 'float') + def process_token_or_tree(self, argument, meta): + if isinstance(argument, Tree): + return f'{str(argument.children[0])}' + else: + # this is a variable, add to the table + self.add_variable_access_location(argument, meta.line) + return argument + + def process_token_or_tree_for_calculation(self, argument, command, meta): + if type(argument) is Tree: + return f'{str(argument.children[0])}' + else: + # this is a variable, add to the table + self.add_variable_access_location(argument, meta.line) + exception_text = translate_value_error(command, argument, 'number') + return f'number_with_error({argument}, {exception_text})' + + def process_token_or_tree_for_addition(self, argument, meta): + if type(argument) is Tree: + return f'{str(argument.children[0])}' + else: + # this is a variable, add to the table + self.add_variable_access_location(argument, meta.line) + return argument + + # From level 12 concatenation should also work, so the args could be either numbers or strings + def addition(self, meta, args): + args = [self.process_token_or_tree_for_addition(a, meta) for a in args] + if all([self.is_int(a) or self.is_float(a) for a in args]): + return Tree('sum', [f'{args[0]} + {args[1]}']) + else: + exception_text = translate_values_error(Command.addition, 'numbers_or_strings') + return Tree('sum', [f'sum_with_error({args[0]}, {args[1]}, {exception_text})']) + def division(self, meta, args): return self.process_calculation(args, '/', meta) @@ -2671,7 +2725,7 @@ def while_loop(self, meta, args): all_lines = [ConvertToPython.indent(x) for x in args[1:]] body = "\n".join(all_lines) body = add_sleep_to_command(body, True, self.is_debug, location="after") - exceptions = self.make_catch_exception([args[0]]) + exceptions = self.make_index_error_check_if_list([args[0]]) return exceptions + "while " + args[0] + ":" + self.add_debug_breakpoint() + "\n" + body def ifpressed(self, meta, args): @@ -2715,12 +2769,12 @@ def change_list_item(self, meta, args): self.add_variable_access_location(args[1], meta.line) self.add_variable_access_location(args[2], meta.line) - exception = _translate_index_error(left_side, args[0]) + exception = self.make_index_error_check_if_list([left_side]) return exception + left_side + ' = ' + right_side + self.add_debug_breakpoint() def ifs(self, meta, args): all_lines = [ConvertToPython.indent(x) for x in args[1:]] - exceptions = self.make_catch_exception([args[0]]) + exceptions = self.make_index_error_check_if_list([args[0]]) return exceptions + "if " + args[0] + ":" + self.add_debug_breakpoint() + "\n" + "\n".join(all_lines) diff --git a/messages.pot b/messages.pot index 07bda68cdca..44244be100d 100644 --- a/messages.pot +++ b/messages.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2024-02-28 13:55+0100\n" +"POT-Creation-Date: 2024-03-07 22:34+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -278,6 +278,9 @@ msgstr "" msgid "catch_index_exception" msgstr "" +msgid "catch_multiple_values_exception" +msgstr "" + msgid "catch_value_exception" msgstr "" @@ -1427,6 +1430,9 @@ msgstr "" msgid "select_lang" msgstr "" +msgid "select_levels" +msgstr "" + msgid "select_tag" msgstr "" @@ -1451,12 +1457,6 @@ msgstr "" msgid "share_by_giving_link" msgstr "" -msgid "share_confirm" -msgstr "" - -msgid "share_success_detail" -msgstr "" - msgid "share_your_program" msgstr "" @@ -1571,6 +1571,9 @@ msgstr "" msgid "suggestion_number" msgstr "" +msgid "suggestion_numbers_or_strings" +msgstr "" + msgid "surname" msgstr "" @@ -1742,12 +1745,6 @@ msgstr "" msgid "unsaved_class_changes" msgstr "" -msgid "unshare_confirm" -msgstr "" - -msgid "unshare_success_detail" -msgstr "" - msgid "update_adventure_prompt" msgstr "" diff --git a/prefixes/normal.py b/prefixes/normal.py index 6495b1e3173..0a8451a8186 100644 --- a/prefixes/normal.py +++ b/prefixes/normal.py @@ -95,3 +95,27 @@ def convert_numerals(alphabet, number): T = int number = ''.join(all_numerals_converted) return T(f'{sign}{number}') + + +def int_with_error(s, err): + try: + return int(str(s)) + except ValueError: + raise Exception(err.format(s)) + + +def number_with_error(s, err): + try: + return int(str(s)) + except ValueError: + try: + return float(str(s)) + except ValueError: + raise Exception(err.format(s)) + + +def sum_with_error(left, right, err): + try: + return left + right + except Exception: + raise Exception(err.format(left, right)) diff --git a/static/js/appbundle.js b/static/js/appbundle.js index f75b1be3902..cc325ac3308 100644 --- a/static/js/appbundle.js +++ b/static/js/appbundle.js @@ -71914,6 +71914,31 @@ def convert_numerals(alphabet, number): T = int number = ''.join(all_numerals_converted) return T(f'{sign}{number}') + + +def int_with_error(s, err): + try: + return int(str(s)) + except ValueError: + raise Exception(err.format(s)) + + +def number_with_error(s, err): + try: + return int(str(s)) + except ValueError: + try: + return float(str(s)) + except ValueError: + raise Exception(err.format(s)) + + +def sum_with_error(left, right, err): + try: + return left + right + except Exception: + raise Exception(err.format(left, right)) + `; var music_prefix = ` notes_mapping = { diff --git a/static/js/pythonPrefixes.ts b/static/js/pythonPrefixes.ts index d6dcef8f852..dbd8762c5a6 100644 --- a/static/js/pythonPrefixes.ts +++ b/static/js/pythonPrefixes.ts @@ -145,6 +145,31 @@ def convert_numerals(alphabet, number): T = int number = ''.join(all_numerals_converted) return T(f'{sign}{number}') + + +def int_with_error(s, err): + try: + return int(str(s)) + except ValueError: + raise Exception(err.format(s)) + + +def number_with_error(s, err): + try: + return int(str(s)) + except ValueError: + try: + return float(str(s)) + except ValueError: + raise Exception(err.format(s)) + + +def sum_with_error(left, right, err): + try: + return left + right + except Exception: + raise Exception(err.format(left, right)) + `; export const music_prefix = diff --git a/tests/Tester.py b/tests/Tester.py index ef63785251f..79472613ba6 100644 --- a/tests/Tester.py +++ b/tests/Tester.py @@ -138,7 +138,7 @@ def run_code(parse_result): code = re.sub(r'time\.sleep\([^\n]*\)', 'pass', code) with HedyTester.captured_output() as (out, err): - exec(code) + exec(code, locals()) return out.getvalue().strip() def name(self): @@ -380,36 +380,36 @@ def turtle_command_transpiled(command, val, level): type = 'int' if level < 12 else 'float' - return textwrap.dedent(f"""\ + return textwrap.dedent(f'''\ __trtl = {val} try: __trtl = {type}(__trtl) except ValueError: - raise Exception('catch_value_exception') - t.{command}(min(600, __trtl) if __trtl > 0 else max(-600, __trtl)){suffix}""") + raise Exception("""catch_value_exception""") + t.{command}(min(600, __trtl) if __trtl > 0 else max(-600, __trtl)){suffix}''') @staticmethod def sleep_command_transpiled(val): - return textwrap.dedent(f"""\ + return textwrap.dedent(f'''\ try: time.sleep(int({val})) except ValueError: - raise Exception('catch_value_exception')""") + raise Exception("""catch_value_exception""")''') @staticmethod def turtle_color_command_transpiled(val, lang="en"): color_dict = {hedy_translation.translate_keyword_from_en(x, lang): x for x in hedy.english_colors} both_colors = hedy.command_make_color_local(lang) - return textwrap.dedent(f"""\ + return textwrap.dedent(f'''\ __trtl = f'{val}' color_dict = {color_dict} if __trtl not in {both_colors}: - raise Exception('catch_value_exception') + raise Exception("""catch_value_exception""") else: if not __trtl in {hedy.english_colors}: __trtl = color_dict[__trtl] - t.pencolor(__trtl)""") + t.pencolor(__trtl)''') @staticmethod def input_transpiled(var_name, text): @@ -433,22 +433,45 @@ def remove_transpiled(list_name, value): @staticmethod def list_access_transpiled(list_access): - return textwrap.dedent(f"""\ + return textwrap.dedent(f'''\ try: {list_access} except IndexError: - raise Exception('catch_index_exception')""") + raise Exception("""catch_index_exception""")''') @staticmethod def variable_type_check_transpiled(variable, type_,): - return textwrap.dedent(f"""\ + return textwrap.dedent(f'''\ try: {type_}({variable}) except ValueError: - raise Exception(f'catch_value_exception')""") + raise Exception(f"""catch_value_exception""")''') + + @staticmethod + def int_cast_transpiled(val, quotes=True): + value = f"'{val}'" if quotes else val + return f'''int_with_error({value}, """catch_value_exception""")''' + + @staticmethod + def number_cast_transpiled(val, quotes=False): + value = f"'{val}'" if quotes else val + return f'''number_with_error({value}, """catch_value_exception""")''' + + @staticmethod + def addition_transpiled(left, right): + return f'''sum_with_error({left}, {right}, """catch_multiple_values_exception""")''' + + @staticmethod + def value_exception_transpiled(): + return '"""catch_value_exception"""' + + @staticmethod + def index_exception_transpiled(): + return '"""catch_index_exception"""' # Used to overcome indentation issues when the above code is inserted # in test cases which use different indentation style (e.g. 2 or 4 spaces) + @staticmethod def dedent(*args): return '\n'.join([textwrap.indent(textwrap.dedent(a[0]), a[1]) if isinstance(a, tuple) else textwrap.dedent(a) diff --git a/tests/test_level/test_level_01.py b/tests/test_level/test_level_01.py index 9cdd342c56c..7328a9ad863 100644 --- a/tests/test_level/test_level_01.py +++ b/tests/test_level/test_level_01.py @@ -288,9 +288,9 @@ def test_ask_en_code_transpiled_in_nl(self): def test_play_no_args(self): code = "play " - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ if 'C4' not in notes_mapping.keys() and 'C4' not in notes_mapping.values(): - raise Exception('catch_value_exception') + raise Exception({self.value_exception_transpiled()}) play(notes_mapping.get(str('C4'), str('C4'))) time.sleep(0.5)""") @@ -303,9 +303,9 @@ def test_play_no_args(self): def test_play(self): code = "play A" - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ if 'A' not in notes_mapping.keys() and 'A' not in notes_mapping.values(): - raise Exception('catch_value_exception') + raise Exception({self.value_exception_transpiled()}) play(notes_mapping.get(str('A'), str('A'))) time.sleep(0.5)""") @@ -333,9 +333,9 @@ def test_print_microbit(self): def test_play_lowercase(self): code = "play a" - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ if 'A' not in notes_mapping.keys() and 'A' not in notes_mapping.values(): - raise Exception('catch_value_exception') + raise Exception({self.value_exception_transpiled()}) play(notes_mapping.get(str('A'), str('A'))) time.sleep(0.5)""") @@ -347,9 +347,9 @@ def test_play_lowercase(self): def test_play_int(self): code = "play 34" - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ if '34' not in notes_mapping.keys() and '34' not in notes_mapping.values(): - raise Exception('catch_value_exception') + raise Exception({self.value_exception_transpiled()}) play(notes_mapping.get(str('34'), str('34'))) time.sleep(0.5)""") diff --git a/tests/test_level/test_level_02.py b/tests/test_level/test_level_02.py index 373a9134394..0d4836a2a23 100644 --- a/tests/test_level/test_level_02.py +++ b/tests/test_level/test_level_02.py @@ -341,19 +341,19 @@ def test_turn_with_non_latin_number_var(self): الزاوية هو ٩٠ استدر الزاوية تقدم ١٠٠""") - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ الزاوية = '٩٠' __trtl = الزاوية try: __trtl = int(__trtl) except ValueError: - raise Exception('catch_value_exception') + raise Exception({self.value_exception_transpiled()}) t.right(min(600, __trtl) if __trtl > 0 else max(-600, __trtl)) __trtl = 100 try: __trtl = int(__trtl) except ValueError: - raise Exception('catch_value_exception') + raise Exception({self.value_exception_transpiled()}) t.forward(min(600, __trtl) if __trtl > 0 else max(-600, __trtl)) time.sleep(0.1)""") @@ -845,11 +845,11 @@ def test_play(self): n is C4 play n""") - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ n = 'C4' chosen_note = str(n).upper() if chosen_note not in notes_mapping.keys() and chosen_note not in notes_mapping.values(): - raise Exception('catch_value_exception') + raise Exception({self.value_exception_transpiled()}) play(notes_mapping.get(chosen_note, chosen_note)) time.sleep(0.5)""") diff --git a/tests/test_level/test_level_03.py b/tests/test_level/test_level_03.py index 19a31431b84..5d2357a2f63 100644 --- a/tests/test_level/test_level_03.py +++ b/tests/test_level/test_level_03.py @@ -181,16 +181,16 @@ def test_sleep_with_list_access(self): code = textwrap.dedent("""\ n is 1, 2, 3 sleep n at 1""") - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ n = ['1', '2', '3'] try: try: n[int(1)-1] except IndexError: - raise Exception('catch_index_exception') + raise Exception({self.index_exception_transpiled()}) time.sleep(int(n[int(1)-1])) except ValueError: - raise Exception('catch_value_exception')""") + raise Exception({self.value_exception_transpiled()})""") self.multi_level_tester(max_level=11, code=code, expected=expected) @@ -199,10 +199,9 @@ def test_sleep_with_time_variable(self): time is 10 sleep time""") - expected = HedyTester.dedent("""\ - _time = '10'""", - HedyTester.sleep_command_transpiled('_time') - ) + expected = HedyTester.dedent( + "_time = '10'", + HedyTester.sleep_command_transpiled('_time')) self.multi_level_tester( code=code, @@ -214,16 +213,16 @@ def test_sleep_with_list_random(self): code = textwrap.dedent("""\ n is 1, 2, 3 sleep n at random""") - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ n = ['1', '2', '3'] try: try: random.choice(n) except IndexError: - raise Exception('catch_index_exception') + raise Exception({self.index_exception_transpiled()}) time.sleep(int(random.choice(n))) except ValueError: - raise Exception('catch_value_exception')""") + raise Exception({self.value_exception_transpiled()})""") self.multi_level_tester(max_level=11, code=code, expected=expected) @@ -869,11 +868,11 @@ def test_play_random(self): notes is C4, E4, D4, F4, G4 play notes at random""") - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ notes = ['C4', 'E4', 'D4', 'F4', 'G4'] chosen_note = str(random.choice(notes)).upper() if chosen_note not in notes_mapping.keys() and chosen_note not in notes_mapping.values(): - raise Exception('catch_value_exception') + raise Exception({self.value_exception_transpiled()}) play(notes_mapping.get(chosen_note, chosen_note)) time.sleep(0.5)""") diff --git a/tests/test_level/test_level_05.py b/tests/test_level/test_level_05.py index e1c34899051..443ac42fa39 100644 --- a/tests/test_level/test_level_05.py +++ b/tests/test_level/test_level_05.py @@ -1554,11 +1554,11 @@ def test_turn_if_play(self): answer is ask 'What is the capital of Zimbabwe?' if answer is Harare play C6""") - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ answer = input(f'What is the capital of Zimbabwe?') if answer == 'Harare': if 'C6' not in notes_mapping.keys() and 'C6' not in notes_mapping.values(): - raise Exception('catch_value_exception') + raise Exception({self.value_exception_transpiled()}) play(notes_mapping.get(str('C6'), str('C6'))) time.sleep(0.5)""") @@ -1572,16 +1572,16 @@ def test_turn_if_else_play(self): answer is ask 'What is the capital of Zimbabwe?' if answer is Harare play C6 else play C1""") - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ answer = input(f'What is the capital of Zimbabwe?') if answer == 'Harare': if 'C6' not in notes_mapping.keys() and 'C6' not in notes_mapping.values(): - raise Exception('catch_value_exception') + raise Exception({self.value_exception_transpiled()}) play(notes_mapping.get(str('C6'), str('C6'))) time.sleep(0.5) else: if 'C1' not in notes_mapping.keys() and 'C1' not in notes_mapping.values(): - raise Exception('catch_value_exception') + raise Exception({self.value_exception_transpiled()}) play(notes_mapping.get(str('C1'), str('C1'))) time.sleep(0.5)""") diff --git a/tests/test_level/test_level_06.py b/tests/test_level/test_level_06.py index 92566418a72..ffd2ee25709 100644 --- a/tests/test_level/test_level_06.py +++ b/tests/test_level/test_level_06.py @@ -120,15 +120,14 @@ def test_assign_text_with_space(self): expected=expected ) - def test_assign_substract_negative_number(self): - + def test_assign_subtract_negative_number(self): code = textwrap.dedent("""\ - n = -3-4 - print n""") + n = -3-4 + print n""") - expected = textwrap.dedent("""\ - n = int(-3) - int(4) - print(f'{n}')""") + expected = textwrap.dedent(f"""\ + n = {self.int_cast_transpiled('-3', False)} - int(4) + print(f'{{n}}')""") self.multi_level_tester( max_level=11, @@ -151,9 +150,9 @@ def test_play_calculation(self, op, expected_op): play note {op} 1""") expected = textwrap.dedent(f"""\ note = '34' - chosen_note = str(int(note) {expected_op} int(1)).upper() + chosen_note = str({self.int_cast_transpiled('note', False)} {expected_op} int(1)).upper() if chosen_note not in notes_mapping.keys() and chosen_note not in notes_mapping.values(): - raise Exception('catch_value_exception') + raise Exception({self.value_exception_transpiled()}) play(notes_mapping.get(chosen_note, chosen_note)) time.sleep(0.5)""") @@ -314,12 +313,12 @@ def test_if_equality_assign_calc(self): acu is 0 if test is cmp acu is acu + 1""") - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ cmp = '1' test = '2' acu = '0' if convert_numerals('Latin', test) == convert_numerals('Latin', cmp): - acu = int(acu) + int(1)""") + acu = {self.int_cast_transpiled('acu', False)} + int(1)""") self.multi_level_tester(max_level=7, code=code, expected=expected) @@ -404,14 +403,14 @@ def test_if_equality_assign_else_assign(self): else acu is acu + 5""") - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ cmp = '1' test = '2' acu = '0' if convert_numerals('Latin', test) == convert_numerals('Latin', cmp): - acu = int(acu) + int(1) + acu = {self.int_cast_transpiled('acu', False)} + int(1) else: - acu = int(acu) + int(5)""") + acu = {self.int_cast_transpiled('acu', False)} + int(5)""") self.multi_level_tester(max_level=7, code=code, expected=expected) @@ -624,9 +623,9 @@ def test_print_calc_with_var(self): code = textwrap.dedent("""\ var is 5 print var + 5""") - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ var = '5' - print(f'{int(var) + int(5)}')""") + print(f'{{{self.int_cast_transpiled('var', False)} + int(5)}}')""") self.multi_level_tester(max_level=11, code=code, expected=expected) @@ -658,7 +657,7 @@ def test_assign_calc_with_vars(self, op, transpiled_op, output): expected = textwrap.dedent(f"""\ nummer = '8' nummertwee = '2' - getal = int(nummer) {transpiled_op} int(nummertwee) + getal = {self.int_cast_transpiled('nummer', False)} {transpiled_op} {self.int_cast_transpiled('nummertwee', False)} print(f'{{getal}}')""") self.multi_level_tester(max_level=11, code=code, expected=expected, output=output) @@ -675,10 +674,10 @@ def test_print_calc_with_vars(self, op, transpiled_op, output): nummertwee is 2 print nummer {op} nummertwee""") - expected = textwrap.dedent(f"""\ + expected = textwrap.dedent(f'''\ nummer = '8' nummertwee = '2' - print(f'{{int(nummer) {transpiled_op} int(nummertwee)}}')""") + print(f'{{{self.int_cast_transpiled('nummer', False)} {transpiled_op} {self.int_cast_transpiled('nummertwee', False)}}}')''') self.multi_level_tester(max_level=11, code=code, expected=expected, output=output) @@ -697,7 +696,7 @@ def test_print_calc_with_vars_arabic(self, op, transpiled_op, output): expected = textwrap.dedent(f"""\ nummer = '٨' nummertwee = '٢' - print(f'{{int(nummer) {transpiled_op} int(nummertwee)}}')""") + print(f'{{{self.int_cast_transpiled('nummer', False)} {transpiled_op} {self.int_cast_transpiled('nummertwee', False)}}}')""") self.multi_level_tester(max_level=11, code=code, expected=expected, output=output) @@ -785,10 +784,10 @@ def test_print_calc_chained_vars(self): b is a + 1 print a + b""") - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ a = '5' - b = int(a) + int(1) - print(f'{int(a) + int(b)}')""") + b = {self.int_cast_transpiled('a', False)} + int(1) + print(f'{{{self.int_cast_transpiled('a', False)} + {self.int_cast_transpiled('b', False)}}}')""") self.multi_level_tester( code=code, @@ -805,11 +804,11 @@ def test_type_reassignment_to_proper_type_valid(self): b is a + 1 print a + b""") - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ a = 'Hello' a = '5' - b = int(a) + int(1) - print(f'{int(a) + int(b)}')""") + b = {self.int_cast_transpiled('a', False)} + int(1) + print(f'{{{self.int_cast_transpiled('a', False)} + {self.int_cast_transpiled('b', False)}}}')""") self.multi_level_tester( code=code, @@ -858,12 +857,12 @@ def test_if_calc_else_calc_print(self): punten = '0'""", HedyTester.list_access_transpiled('random.choice(keuzes)'), "worp = random.choice(keuzes)", - """\ + f"""\ if convert_numerals('Latin', worp) == convert_numerals('Latin', 'regenworm'): - punten = int(punten) + int(5) + punten = {self.int_cast_transpiled('punten', False)} + int(5) else: - punten = int(punten) + int(worp) - print(f'dat zijn dan {punten}')""") + punten = {self.int_cast_transpiled('punten', False)} + {self.int_cast_transpiled('worp', False)} + print(f'dat zijn dan {{punten}}')""") self.multi_level_tester(max_level=7, code=code, expected=expected) @@ -959,10 +958,10 @@ def test_negative_variable(self): a = -3 b = a + 3 print b""") - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ a = '-3' - b = int(a) + int(3) - print(f'{b}')""") + b = {self.int_cast_transpiled('a', False)} + int(3) + print(f'{{b}}')""") self.multi_level_tester(code=code, expected=expected, output='0', max_level=11) def test_turtle_with_expression(self): @@ -972,19 +971,19 @@ def test_turtle_with_expression(self): turn num + 10 forward 10 + num""") - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ num = '10' - __trtl = int(num) + int(10) + __trtl = {self.int_cast_transpiled('num', False)} + int(10) try: __trtl = int(__trtl) except ValueError: - raise Exception('catch_value_exception') + raise Exception({self.value_exception_transpiled()}) t.right(min(600, __trtl) if __trtl > 0 else max(-600, __trtl)) - __trtl = int(10) + int(num) + __trtl = int(10) + {self.int_cast_transpiled('num', False)} try: __trtl = int(__trtl) except ValueError: - raise Exception('catch_value_exception') + raise Exception({self.value_exception_transpiled()}) t.forward(min(600, __trtl) if __trtl > 0 else max(-600, __trtl)) time.sleep(0.1)""") diff --git a/tests/test_level/test_level_07.py b/tests/test_level/test_level_07.py index e161d0c6518..492e74bd06b 100644 --- a/tests/test_level/test_level_07.py +++ b/tests/test_level/test_level_07.py @@ -440,7 +440,7 @@ def test_repeat_if_pressed_multiple(self): repeat 3 times if y is pressed forward 15 else forward -15 repeat 3 times if z is pressed forward 15 else forward -15""") - expected = HedyTester.dedent("""\ + expected = HedyTester.dedent(f"""\ for __i__ in range(int('3')): pygame_end = False while not pygame_end: @@ -456,7 +456,7 @@ def test_repeat_if_pressed_multiple(self): try: __trtl = int(__trtl) except ValueError: - raise Exception('catch_value_exception') + raise Exception({self.value_exception_transpiled()}) t.forward(min(600, __trtl) if __trtl > 0 else max(-600, __trtl)) time.sleep(0.1) break @@ -465,7 +465,7 @@ def test_repeat_if_pressed_multiple(self): try: __trtl = int(__trtl) except ValueError: - raise Exception('catch_value_exception') + raise Exception({self.value_exception_transpiled()}) t.forward(min(600, __trtl) if __trtl > 0 else max(-600, __trtl)) time.sleep(0.1) break @@ -486,7 +486,7 @@ def test_repeat_if_pressed_multiple(self): try: __trtl = int(__trtl) except ValueError: - raise Exception('catch_value_exception') + raise Exception({self.value_exception_transpiled()}) t.forward(min(600, __trtl) if __trtl > 0 else max(-600, __trtl)) time.sleep(0.1) break @@ -495,7 +495,7 @@ def test_repeat_if_pressed_multiple(self): try: __trtl = int(__trtl) except ValueError: - raise Exception('catch_value_exception') + raise Exception({self.value_exception_transpiled()}) t.forward(min(600, __trtl) if __trtl > 0 else max(-600, __trtl)) time.sleep(0.1) break @@ -516,7 +516,7 @@ def test_repeat_if_pressed_multiple(self): try: __trtl = int(__trtl) except ValueError: - raise Exception('catch_value_exception') + raise Exception({self.value_exception_transpiled()}) t.forward(min(600, __trtl) if __trtl > 0 else max(-600, __trtl)) time.sleep(0.1) break @@ -525,7 +525,7 @@ def test_repeat_if_pressed_multiple(self): try: __trtl = int(__trtl) except ValueError: - raise Exception('catch_value_exception') + raise Exception({self.value_exception_transpiled()}) t.forward(min(600, __trtl) if __trtl > 0 else max(-600, __trtl)) time.sleep(0.1) break @@ -599,10 +599,10 @@ def test_play_repeat(self): code = textwrap.dedent("""\ repeat 3 times play C4""") - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ for __i__ in range(int('3')): if 'C4' not in notes_mapping.keys() and 'C4' not in notes_mapping.values(): - raise Exception('catch_value_exception') + raise Exception({self.value_exception_transpiled()}) play(notes_mapping.get(str('C4'), str('C4'))) time.sleep(0.5) time.sleep(0.1)""") @@ -621,12 +621,12 @@ def test_play_repeat_random(self): notes is C4, E4, D4, F4, G4 repeat 3 times play notes at random""") - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ notes = ['C4', 'E4', 'D4', 'F4', 'G4'] for __i__ in range(int('3')): chosen_note = str(random.choice(notes)).upper() if chosen_note not in notes_mapping.keys() and chosen_note not in notes_mapping.values(): - raise Exception('catch_value_exception') + raise Exception({self.value_exception_transpiled()}) play(notes_mapping.get(chosen_note, chosen_note)) time.sleep(0.5) time.sleep(0.1)""") diff --git a/tests/test_level/test_level_08.py b/tests/test_level/test_level_08.py index 3ded5132c6f..38cf78c4864 100644 --- a/tests/test_level/test_level_08.py +++ b/tests/test_level/test_level_08.py @@ -292,12 +292,12 @@ def test_if_equality_assign_calc(self): if test is cmp acu is acu + 1""") - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ cmp = '1' test = '2' acu = '0' if convert_numerals('Latin', test) == convert_numerals('Latin', cmp): - acu = int(acu) + int(1)""") + acu = {self.int_cast_transpiled('acu', False)} + int(1)""") self.multi_level_tester(code=code, expected=expected, max_level=11) @@ -741,11 +741,11 @@ def test_repeat_print_assign_addition(self): print count ' times 12 is ' count * 12 count is count + 1""") - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ count = '1' for i in range(int('12')): - print(f'{count} times 12 is {int(count) * int(12)}') - count = int(count) + int(1) + print(f'{{count}} times 12 is {{{self.int_cast_transpiled('count', False)} * int(12)}}') + count = {self.int_cast_transpiled('count', False)} + int(1) time.sleep(0.1)""") self.multi_level_tester(code=code, expected=expected, max_level=11) @@ -1257,18 +1257,18 @@ def test_play_repeat_random(self): print note play note""") - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ for i in range(int('10')): notes = ['C4', 'E4', 'D4', 'F4', 'G4'] try: random.choice(notes) except IndexError: - raise Exception('catch_index_exception') + raise Exception({self.index_exception_transpiled()}) note = random.choice(notes) - print(f'{note}') + print(f'{{note}}') chosen_note = str(note).upper() if chosen_note not in notes_mapping.keys() and chosen_note not in notes_mapping.values(): - raise Exception('catch_value_exception') + raise Exception({self.value_exception_transpiled()}) play(notes_mapping.get(chosen_note, chosen_note)) time.sleep(0.5) time.sleep(0.1)""") @@ -1289,12 +1289,12 @@ def test_play_integers(self): repeat 10 times play notes at random""") - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ notes = ['1', '2', '3'] for i in range(int('10')): chosen_note = str(random.choice(notes)).upper() if chosen_note not in notes_mapping.keys() and chosen_note not in notes_mapping.values(): - raise Exception('catch_value_exception') + raise Exception({self.value_exception_transpiled()}) play(notes_mapping.get(chosen_note, chosen_note)) time.sleep(0.5) time.sleep(0.1)""") @@ -1315,15 +1315,15 @@ def test_play_repeat_with_calc(self): play note note is note + 1""") - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ note = '34' for i in range(int('3')): chosen_note = str(note).upper() if chosen_note not in notes_mapping.keys() and chosen_note not in notes_mapping.values(): - raise Exception('catch_value_exception') + raise Exception({self.value_exception_transpiled()}) play(notes_mapping.get(chosen_note, chosen_note)) time.sleep(0.5) - note = int(note) + int(1) + note = {self.int_cast_transpiled('note', False)} + int(1) time.sleep(0.1)""") self.multi_level_tester( diff --git a/tests/test_level/test_level_09.py b/tests/test_level/test_level_09.py index 3ef8f1cbf9f..8d4da49b515 100644 --- a/tests/test_level/test_level_09.py +++ b/tests/test_level/test_level_09.py @@ -143,14 +143,14 @@ def test_if_nested_in_repeat(self): prijs is prijs + 1 print 'Dat is in totaal ' prijs ' euro.'""") - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ prijs = '0' for i in range(int('7')): ingredient = input(f'wat wil je kopen?') if convert_numerals('Latin', ingredient) == convert_numerals('Latin', 'appel'): - prijs = int(prijs) + int(1) + prijs = {self.int_cast_transpiled('prijs', False)} + int(1) time.sleep(0.1) - print(f'Dat is in totaal {prijs} euro.')""") + print(f'Dat is in totaal {{prijs}} euro.')""") self.multi_level_tester(code=code, expected=expected, max_level=11) @@ -163,14 +163,14 @@ def test_if_nested_in_repeat_with_comment(self): prijs is prijs + 1 print 'Dat is in totaal ' prijs ' euro.'""") - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ prijs = '0' for i in range(int('7')): ingredient = input(f'wat wil je kopen?') if convert_numerals('Latin', ingredient) == convert_numerals('Latin', 'appel'): - prijs = int(prijs) + int(1) + prijs = {self.int_cast_transpiled('prijs', False)} + int(1) time.sleep(0.1) - print(f'Dat is in totaal {prijs} euro.')""") + print(f'Dat is in totaal {{prijs}} euro.')""") self.multi_level_tester(code=code, expected=expected, max_level=11) diff --git a/tests/test_level/test_level_11.py b/tests/test_level/test_level_11.py index 50a636da00c..c864a07d025 100644 --- a/tests/test_level/test_level_11.py +++ b/tests/test_level/test_level_11.py @@ -26,10 +26,10 @@ def test_for_loop(self): code = textwrap.dedent("""\ for i in range 1 to 10 a is i + 1""") - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ step = 1 if int(1) < int(10) else -1 for i in range(int(1), int(10) + step, step): - a = int(i) + int(1) + a = {self.int_cast_transpiled('i', False)} + int(1) time.sleep(0.1)""") self.single_level_tester( @@ -113,13 +113,13 @@ def test_for_loop_multiline_body(self): a is a + 2 b is b + 2""") - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ a = '2' b = '3' step = 1 if int(2) < int(4) else -1 for a in range(int(2), int(4) + step, step): - a = int(a) + int(2) - b = int(b) + int(2) + a = {self.int_cast_transpiled('a', False)} + int(2) + b = {self.int_cast_transpiled('b', False)} + int(2) time.sleep(0.1)""") self.single_level_tester(code=code, expected=expected) diff --git a/tests/test_level/test_level_12.py b/tests/test_level/test_level_12.py index bf489e8d20b..84deff3f601 100644 --- a/tests/test_level/test_level_12.py +++ b/tests/test_level/test_level_12.py @@ -55,7 +55,7 @@ def test_print_float(self): def test_print_division_float(self): code = "print 3 / 2" - expected = "print(f'''{3 / 2}''')" + expected = f"print(f'''{{{self.number_cast_transpiled(3)} / {self.number_cast_transpiled(2)}}}''')" output = "1.5" self.multi_level_tester( @@ -67,8 +67,8 @@ def test_print_division_float(self): def test_sleep_division_float(self): code = "sleep 1 / 20" - expected = HedyTester.dedent( - HedyTester.sleep_command_transpiled("1 / 20")) + expected = HedyTester.sleep_command_transpiled( + f'{self.number_cast_transpiled(1)} / {self.number_cast_transpiled(20)}') self.multi_level_tester( code=code, @@ -170,7 +170,7 @@ def test_print_list_gives_type_error(self): def test_print_subtraction_with_text(self): code = "print 'And the winner is ' 5 - 5" - expected = "print(f'''And the winner is {5 - 5}''')" + expected = f"print(f'''And the winner is {{{self.number_cast_transpiled(5)} - {self.number_cast_transpiled(5)}}}''')" output = 'And the winner is 0' self.multi_level_tester(max_level=17, code=code, expected=expected, output=output) @@ -375,13 +375,15 @@ def test_print_quoted_var_reference(self): @parameterized.expand(HedyTester.quotes) def test_print_concat_quoted_strings(self, q): code = f"""print {q}Hi {q} + {q}there{q}""" - expected = """print(f'''{'Hi ' + 'there'}''')""" + expected = f"""print(f'''{{{self.addition_transpiled("'Hi '", "'there'")}}}''')""" self.multi_level_tester(code=code, expected=expected, max_level=17) def test_print_concat_double_quoted_strings_with_inner_single_quotes(self): code = '''print "Hi there! " + "It's Hedy!"''' - expected = """print(f'''{'Hi there! ' + "It's Hedy!"}''')""" + left = "'Hi there! '" + right = '"It\'s Hedy!"' + expected = f"""print(f'''{{{self.addition_transpiled(left, right)}}}''')""" self.multi_level_tester(code=code, expected=expected, max_level=17) @@ -390,9 +392,9 @@ def test_print_concat_var_and_literal_string(self, q): code = textwrap.dedent(f"""\ hi = {q}Hi{q} print hi + {q} there{q}""") - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ hi = 'Hi' - print(f'''{hi + ' there'}''')""") + print(f'''{{{self.addition_transpiled('hi', "' there'")}}}''')""") self.multi_level_tester(code=code, expected=expected, max_level=17) @@ -402,10 +404,10 @@ def test_print_chained_assignments(self): y is x + 3 print y + 4""") - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ x = 1 + 2 - y = x + 3 - print(f'''{y + 4}''')""") + y = {self.addition_transpiled('x', 3)} + print(f'''{{{self.addition_transpiled('y', 4)}}}''')""") self.multi_level_tester(code=code, expected=expected, max_level=17) @@ -415,14 +417,14 @@ def test_assign_to_list_access(self): field at 1 = 'x' print field at 1""") - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ field = ['.', '.', '.', '.', '.', '.'] field[int(1)-1] = 'x' try: field[int(1)-1] except IndexError: - raise Exception('catch_index_exception') - print(f'''{field[int(1)-1]}''')""") + raise Exception({self.index_exception_transpiled()}) + print(f'''{{field[int(1)-1]}}''')""") self.multi_level_tester(code=code, expected=expected, max_level=15) @@ -452,9 +454,9 @@ def test_print_calc(self): var is 5 print var + 5""") - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ var = 5 - print(f'''{var + 5}''')""") + print(f'''{{{self.addition_transpiled('var', 5)}}}''')""") self.multi_level_tester(code=code, expected=expected, max_level=17) @@ -547,8 +549,8 @@ def test_turtle_with_expression(self): expected = HedyTester.dedent( "num = 10.6", - HedyTester.turn_transpiled('num + 10.5', self.level), - HedyTester.forward_transpiled('10.5 + num', self.level) + HedyTester.turn_transpiled(self.addition_transpiled('num', '10.5'), self.level), + HedyTester.forward_transpiled(self.addition_transpiled('10.5', 'num'), self.level) ) self.multi_level_tester(code=code, expected=expected) @@ -652,7 +654,7 @@ def test_ask_number_answer(self): prijs is ask 'hoeveel?' gespaard is 7 sparen is prijs - gespaard""") - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ prijs = input(f'''hoeveel?''') try: prijs = int(prijs) @@ -662,7 +664,7 @@ def test_ask_number_answer(self): except ValueError: pass gespaard = 7 - sparen = prijs - gespaard""") + sparen = {self.number_cast_transpiled('prijs')} - {self.number_cast_transpiled('gespaard')}""") self.multi_level_tester(code=code, unused_allowed=True, expected=expected, max_level=17) @@ -671,11 +673,11 @@ def test_play(self): n = 'C4' # play n""") - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ n = 'C4' chosen_note = str(n).upper() if chosen_note not in notes_mapping.keys() and chosen_note not in notes_mapping.values(): - raise Exception('catch_value_exception') + raise Exception({self.value_exception_transpiled()}) play(notes_mapping.get(chosen_note, chosen_note)) time.sleep(0.5)""") @@ -879,16 +881,16 @@ def test_sleep_with_list_access(self): code = textwrap.dedent("""\ n is 1, 2, 3 sleep n at 1""") - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ n = [1, 2, 3] try: try: n[int(1)-1] except IndexError: - raise Exception('catch_index_exception') + raise Exception({self.index_exception_transpiled()}) time.sleep(int(n[int(1)-1])) except ValueError: - raise Exception('catch_value_exception')""") + raise Exception({self.value_exception_transpiled()})""") self.multi_level_tester(max_level=15, code=code, expected=expected) @@ -897,16 +899,16 @@ def test_sleep_with_list_random(self): code = textwrap.dedent("""\ n is 1, 2, 3 sleep n at random""") - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ n = [1, 2, 3] try: try: random.choice(n) except IndexError: - raise Exception('catch_index_exception') + raise Exception({self.index_exception_transpiled()}) time.sleep(int(random.choice(n))) except ValueError: - raise Exception('catch_value_exception')""") + raise Exception({self.value_exception_transpiled()})""") self.multi_level_tester(max_level=15, code=code, expected=expected) @@ -942,8 +944,10 @@ def test_sleep_with_calc(self): code = textwrap.dedent("""\ n is 1 * 2 + 3 sleep n""") + + expected_multiply = f'{self.number_cast_transpiled(1)} * {self.number_cast_transpiled(2)}' expected = HedyTester.dedent( - "n = 1 * 2 + 3", + f"n = {self.addition_transpiled(expected_multiply, '3')}", HedyTester.sleep_command_transpiled("n")) self.multi_level_tester(code=code, expected=expected) @@ -1082,7 +1086,9 @@ def test_assign_python_keyword(self): def test_assign_concat(self): code = """a = "It's" + ' "Hedy"!'""" - expected = """a = "It's" + ' "Hedy"!'""" + left = '''"It's"''' + right = """' "Hedy"!'""" + expected = f"""a = {self.addition_transpiled(left, right)}""" self.multi_level_tester(code=code, unused_allowed=True, expected=expected) @@ -1651,11 +1657,11 @@ def test_repeat_print_assign_addition(self): print count ' times 12 is ' count * 12 count is count + 1""") - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ count = 1 for i in range(int('12')): - print(f'''{count} times 12 is {count * 12}''') - count = count + 1 + print(f'''{{count}} times 12 is {{{self.number_cast_transpiled('count')} * {self.number_cast_transpiled(12)}}}''') + count = {self.addition_transpiled('count', 1)} time.sleep(0.1)""") self.multi_level_tester(code=code, expected=expected, max_level=17) @@ -1787,11 +1793,11 @@ def test_for_loop(self): for i in range 1 to 10 a is i + 1 print a""") - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ step = 1 if 1 < 10 else -1 for i in range(1, 10 + step, step): - a = i + 1 - print(f'''{a}''') + a = {self.addition_transpiled('i', '1')} + print(f'''{{a}}''') time.sleep(0.1)""") self.multi_level_tester( @@ -1825,13 +1831,13 @@ def test_for_loop_multiline_body(self): a is a + 2 b is b + 2""") - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ a = 2 b = 3 step = 1 if 2 < 4 else -1 for a in range(2, 4 + step, step): - a = a + 2 - b = b + 2 + a = {self.addition_transpiled('a', '2')} + b = {self.addition_transpiled('b', '2')} time.sleep(0.1)""") self.multi_level_tester(code=code, expected=expected, max_level=16) @@ -1911,43 +1917,65 @@ def test_for_loop_if(self): @parameterized.expand([ ('*', '*', '12'), ('/', '/', '3.0'), - ('+', '+', '8'), ('-', '-', '4')]) def test_int_calc(self, op, transpiled_op, output): code = f"print 6 {op} 2" - expected = f"print(f'''{{6 {transpiled_op} 2}}''')" + expected = f"print(f'''{{{self.number_cast_transpiled(6)} {transpiled_op} {self.number_cast_transpiled(2)}}}''')" self.multi_level_tester(code=code, unused_allowed=True, expected=expected, output=output, max_level=17) + def test_int_sum(self): + code = f"print 6 + 2" + expected = f"print(f'''{{6 + 2}}''')" + + self.multi_level_tester(code=code, unused_allowed=True, expected=expected, output='8', max_level=17) + @parameterized.expand([ ('*', '*', '100'), ('/', '/', '1.0'), - ('+', '+', '17'), ('-', '-', '3')]) def test_nested_int_calc(self, op, transpiled_op, output): code = f"print 10 {op} 5 {op} 2" - expected = f"print(f'''{{10 {transpiled_op} 5 {transpiled_op} 2}}''')" + expected = f"print(f'''{{{self.number_cast_transpiled(10)} {transpiled_op} {self.number_cast_transpiled(5)} {transpiled_op} {self.number_cast_transpiled(2)}}}''')" self.multi_level_tester(code=code, unused_allowed=True, expected=expected, output=output, max_level=17) - @parameterized.expand(HedyTester.arithmetic_operations) + @parameterized.expand(['-', '*', '/']) def test_float_calc(self, op): code = f"print 2.5 {op} 2.5" - expected = f"print(f'''{{2.5 {op} 2.5}}''')" + expected = f"print(f'''{{{self.number_cast_transpiled('2.5')} {op} {self.number_cast_transpiled('2.5')}}}''')" + + self.multi_level_tester(code=code, expected=expected, max_level=17) + + def test_float_sum(self): + code = f"print 2.5 + 2.5" + expected = "print(f'''{2.5 + 2.5}''')" self.multi_level_tester(code=code, expected=expected, max_level=17) - @parameterized.expand(HedyTester.arithmetic_operations) + @parameterized.expand(['-', '*', '/']) def test_float_calc_arabic(self, op): code = f"print ١.٥ {op} ١.٥" - expected = f"print(f'''{{1.5 {op} 1.5}}''')" + expected = f"print(f'''{{{self.number_cast_transpiled('1.5')} {op} {self.number_cast_transpiled('1.5')}}}''')" + + self.multi_level_tester(code=code, expected=expected, max_level=17) + + def test_float_sum_arabic(self): + code = f"print ١.٥ + ١.٥" + expected = "print(f'''{1.5 + 1.5}''')" self.multi_level_tester(code=code, expected=expected, max_level=17) - @parameterized.expand(HedyTester.arithmetic_operations) + @parameterized.expand(['-', '*', '/']) def test_print_float_calc_with_string(self, op): code = f"print 'het antwoord is ' 2.5 {op} 2.5" - expected = f"print(f'''het antwoord is {{2.5 {op} 2.5}}''')" + expected = f"print(f'''het antwoord is {{{self.number_cast_transpiled('2.5')} {op} {self.number_cast_transpiled('2.5')}}}''')" + + self.multi_level_tester(code=code, expected=expected, max_level=17) + + def test_print_float_sum_with_string(self): + code = f"print 'het antwoord is ' 2.5 + 2.5" + expected = "print(f'''het antwoord is {2.5 + 2.5}''')" self.multi_level_tester(code=code, expected=expected, max_level=17) @@ -1961,7 +1989,7 @@ def test_print_add_negative_number(self): self.multi_level_tester(code=code, expected=expected, max_level=17) - @parameterized.expand(HedyTester.arithmetic_operations) + @parameterized.expand(['-', '*', '/']) def test_float_calc_with_var(self, op): code = textwrap.dedent(f"""\ getal1 is 5 @@ -1970,11 +1998,23 @@ def test_float_calc_with_var(self, op): expected = textwrap.dedent(f"""\ getal1 = 5 getal2 = 4.3 - print(f'''dat is dan: {{getal1 {op} getal2}}''')""") + print(f'''dat is dan: {{{self.number_cast_transpiled('getal1')} {op} {self.number_cast_transpiled('getal2')}}}''')""") self.multi_level_tester(code=code, expected=expected, max_level=17) - @parameterized.expand(HedyTester.arithmetic_operations) + def test_float_sum_with_var(self): + code = textwrap.dedent("""\ + getal1 is 5 + getal2 is 4.3 + print 'dat is dan: ' getal1 + getal2""") + expected = textwrap.dedent(f"""\ + getal1 = 5 + getal2 = 4.3 + print(f'''dat is dan: {{{self.addition_transpiled('getal1', 'getal2')}}}''')""") + + self.multi_level_tester(code=code, expected=expected, max_level=17) + + @parameterized.expand(['-', '*', '/']) def test_int_calc_with_var(self, op): code = textwrap.dedent(f"""\ a is 1 @@ -1983,7 +2023,19 @@ def test_int_calc_with_var(self, op): expected = textwrap.dedent(f"""\ a = 1 b = 2 - c = a {op} b""") + c = {self.number_cast_transpiled('a')} {op} {self.number_cast_transpiled('b')}""") + + self.multi_level_tester(code=code, unused_allowed=True, expected=expected, max_level=17) + + def test_int_sum_with_var(self): + code = textwrap.dedent(f"""\ + a is 1 + b is 2 + c is a + b""") + expected = textwrap.dedent(f"""\ + a = 1 + b = 2 + c = {self.addition_transpiled('a', 'b')}""") self.multi_level_tester(code=code, unused_allowed=True, expected=expected, max_level=17) @@ -1993,11 +2045,11 @@ def test_concat_calc_with_var(self): getal2 is '6' getal3 is '7' print 'dat is dan: ' getal1 + getal2 + getal3""") - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ getal1 = '5' getal2 = '6' getal3 = '7' - print(f'''dat is dan: {getal1 + getal2 + getal3}''')""") + print(f'''dat is dan: {{{self.addition_transpiled(self.addition_transpiled('getal1', 'getal2'), 'getal3')}}}''')""") check_output = (lambda x: HedyTester.run_code(x) == 'dat is dan: 567') @@ -2014,10 +2066,10 @@ def test_int_calc_chained_vars(self): b is a + 1 print a + b""") - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ a = 5 - b = a + 1 - print(f'''{a + b}''')""") + b = {self.addition_transpiled('a', 1)} + print(f'''{{{self.addition_transpiled('a', 'b')}}}''')""") self.multi_level_tester( code=code, @@ -2069,7 +2121,7 @@ def test_concat_promotes_ask_input_to_string(self): answer is ask 'Yes or No?' print 'The answer is ' + answer""") - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ answer = input(f'''Yes or No?''') try: answer = int(answer) @@ -2078,7 +2130,7 @@ def test_concat_promotes_ask_input_to_string(self): answer = float(answer) except ValueError: pass - print(f'''{'The answer is ' + answer}''')""") + print(f'''{{{self.addition_transpiled("'The answer is '", 'answer')}}}''')""") self.multi_level_tester( code=code, @@ -2091,7 +2143,7 @@ def test_concat_promotes_ask_input_to_int(self): answer is ask '1 or 2?' print 5 + answer""") - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ answer = input(f'''1 or 2?''') try: answer = int(answer) @@ -2100,7 +2152,7 @@ def test_concat_promotes_ask_input_to_int(self): answer = float(answer) except ValueError: pass - print(f'''{5 + answer}''')""") + print(f'''{{{self.addition_transpiled('5', 'answer')}}}''')""") self.multi_level_tester( code=code, @@ -2113,7 +2165,7 @@ def test_concat_promotes_ask_input_to_float(self): answer is ask '1 or 2?' print 0.5 + answer""") - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ answer = input(f'''1 or 2?''') try: answer = int(answer) @@ -2122,7 +2174,7 @@ def test_concat_promotes_ask_input_to_float(self): answer = float(answer) except ValueError: pass - print(f'''{0.5 + answer}''')""") + print(f'''{{{self.addition_transpiled('0.5', 'answer')}}}''')""") self.multi_level_tester( code=code, @@ -2385,10 +2437,10 @@ def test_function_use(self): print call func with 1, 2""") - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ def func(n1, n2): - return f'''{n1 + n2}''' - print(f'''{func(1, 2)}''')""") + return f'''{{{self.addition_transpiled('n1', 'n2')}}}''' + print(f'''{{func(1, 2)}}''')""") self.multi_level_tester( code=code, @@ -2426,10 +2478,10 @@ def test_function_use_builtin_name(self): print call sum with 1, 2""") - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ def sum(n1, n2): - return f'''{n1 + n2}''' - print(f'''{sum(1, 2)}''')""") + return f'''{{{self.addition_transpiled('n1', 'n2')}}}''' + print(f'''{{sum(1, 2)}}''')""") self.multi_level_tester( code=code, @@ -2486,10 +2538,10 @@ def test_addition(self): b = 7 print a + b""") - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ a = 5 b = 7 - print(f'''{a + b}''')""") + print(f'''{{{self.addition_transpiled('a', 'b')}}}''')""") self.multi_level_tester( code=code, @@ -2505,14 +2557,13 @@ def test_return_values(self): print call func with 1, 2""") - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ def func(n1, n2): - return f'''{n1 + n2}''' - print(f'''{func(1, 2)}''')""") + return f'''{{{self.addition_transpiled('n1', 'n2')}}}''' + print(f'''{{func(1, 2)}}''')""") - self.multi_level_tester( + self.single_level_tester( code=code, - max_level=16, skip_faulty=False, expected=expected ) @@ -2532,7 +2583,7 @@ def test_source_map(self): price = price + 2.35 print 'That will be ' price ' dollar, please'""") - expected_code = textwrap.dedent("""\ + expected_code = textwrap.dedent(f"""\ price = 0.0 food = input(f'''What would you like to order?''') try: @@ -2551,14 +2602,14 @@ def test_source_map(self): except ValueError: pass if convert_numerals('Latin', food) == convert_numerals('Latin', 'hamburger'): - price = price + 6.5 + price = {self.addition_transpiled('price', '6.5')} if convert_numerals('Latin', food) == convert_numerals('Latin', 'pizza'): - price = price + 5.75 + price = {self.addition_transpiled('price', '5.75')} if convert_numerals('Latin', drink) == convert_numerals('Latin', 'water'): - price = price + 1.2 + price = {self.addition_transpiled('price', '1.2')} if convert_numerals('Latin', drink) == convert_numerals('Latin', 'soda'): - price = price + 2.35 - print(f'''That will be {price} dollar, please''')""") + price = {self.addition_transpiled('price', '2.35')} + print(f'''That will be {{price}} dollar, please''')""") expected_source_map = { '1/1-1/6': '1/1-1/6', @@ -2571,26 +2622,26 @@ def test_source_map(self): '4/4-4/23': '18/4-18/77', '5/5-5/10': '21/1-21/6', '5/13-5/18': '23/1-23/6', - '5/5-5/25': '19/1-19/20', - '4/1-5/34': '18/1-19/22', + '5/5-5/25': '19/1-19/74', + '4/1-5/34': '18/1-19/76', '6/4-6/8': '4/14-4/18', '6/4-6/19': '20/4-20/73', '7/5-7/10': '25/1-25/6', '7/13-7/18': '1/1-1/6', - '7/5-7/25': '21/1-21/21', - '6/1-7/34': '20/1-21/23', + '7/5-7/25': '21/1-21/75', + '6/1-7/34': '20/1-21/77', '8/4-8/9': '10/42-10/47', '8/4-8/20': '22/4-22/74', '9/5-9/10': '19/1-19/6', '9/13-9/18': '21/1-21/6', - '9/5-9/25': '23/1-23/20', - '8/1-9/34': '22/1-23/22', + '9/5-9/25': '23/1-23/74', + '8/1-9/34': '22/1-23/76', '10/4-10/9': '12/3-12/8', '10/4-10/19': '24/4-24/73', '11/5-11/10': '23/1-23/6', '11/13-11/18': '25/1-25/6', - '11/5-11/25': '25/1-25/21', - '10/1-11/34': '24/1-25/23', + '11/5-11/25': '25/1-25/75', + '10/1-11/34': '24/1-25/77', '12/23-12/28': '26/25-26/30', '12/1-12/46': '26/1-26/50', '1/1-12/47': '1/1-26/50' @@ -2630,11 +2681,11 @@ def test_play_random(self): notes = 'C4', 'E4', 'D4', 'F4', 'G4' play notes at random""") - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ notes = ['C4', 'E4', 'D4', 'F4', 'G4'] chosen_note = str(random.choice(notes)).upper() if chosen_note not in notes_mapping.keys() and chosen_note not in notes_mapping.values(): - raise Exception('catch_value_exception') + raise Exception({self.value_exception_transpiled()}) play(notes_mapping.get(chosen_note, chosen_note)) time.sleep(0.5)""") @@ -2654,12 +2705,12 @@ def test_play_integers(self): repeat 10 times play notes at random""") - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ notes = [1, 2, 3] for i in range(int('10')): chosen_note = str(random.choice(notes)).upper() if chosen_note not in notes_mapping.keys() and chosen_note not in notes_mapping.values(): - raise Exception('catch_value_exception') + raise Exception({self.value_exception_transpiled()}) play(notes_mapping.get(chosen_note, chosen_note)) time.sleep(0.5) time.sleep(0.1)""") @@ -2673,16 +2724,34 @@ def test_play_integers(self): max_level=15 ) - @parameterized.expand(HedyTester.arithmetic_operations) + @parameterized.expand(['-', '*', '/']) def test_play_calculation(self, op): code = textwrap.dedent(f"""\ note is 34 play note {op} 1""") expected = textwrap.dedent(f"""\ note = 34 - chosen_note = str(note {op} 1).upper() + chosen_note = str({self.number_cast_transpiled('note')} {op} {self.number_cast_transpiled(1)}).upper() + if chosen_note not in notes_mapping.keys() and chosen_note not in notes_mapping.values(): + raise Exception({self.value_exception_transpiled()}) + play(notes_mapping.get(chosen_note, chosen_note)) + time.sleep(0.5)""") + + self.multi_level_tester( + code=code, + translate=False, + expected=expected + ) + + def test_play_sum(self): + code = textwrap.dedent(f"""\ + note is 34 + play note + 1""") + expected = textwrap.dedent(f"""\ + note = 34 + chosen_note = str({self.addition_transpiled('note', 1)}).upper() if chosen_note not in notes_mapping.keys() and chosen_note not in notes_mapping.values(): - raise Exception('catch_value_exception') + raise Exception({self.value_exception_transpiled()}) play(notes_mapping.get(chosen_note, chosen_note)) time.sleep(0.5)""") @@ -2690,5 +2759,4 @@ def test_play_calculation(self, op): code=code, translate=False, expected=expected, - # max_level=11 ) diff --git a/tests/test_level/test_level_14.py b/tests/test_level/test_level_14.py index 82a5a2e3d04..53f365ef954 100644 --- a/tests/test_level/test_level_14.py +++ b/tests/test_level/test_level_14.py @@ -418,7 +418,7 @@ def test_missing_indent_else(self): ) def test_simple_function(self): - code = textwrap.dedent("""\ + code = textwrap.dedent(f"""\ define test_function_1 int = 1 return "Test function " int @@ -443,7 +443,7 @@ def test_simple_function(self): print call test_function_2 with m print call test_function_2 with 4.0 print call test_function_2 with "5" - print call test_function_2 with 4 * 1.5 + print call test_function_2 with 1.5 * 4 print "" call test_function_3 with 4 print "" @@ -451,12 +451,12 @@ def test_simple_function(self): print "" call test_function_3 with 6""") - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ def test_function_1(): _int = 1 - return f'''Test function {_int}''' + return f'''Test function {{_int}}''' def test_function_2(_int): - return f'''Test function {_int}''' + return f'''Test function {{_int}}''' def test_function_3(_input): if convert_numerals('Latin', _input)!=convert_numerals('Latin', 5): print(f'''NE5''') @@ -470,13 +470,13 @@ def test_function_3(_input): print(f'''GTE5''') if convert_numerals('Latin', _input) == convert_numerals('Latin', '5'): print(f'''E5''') - print(f'''{test_function_1()}''') - print(f'''{test_function_2(2)}''') + print(f'''{{test_function_1()}}''') + print(f'''{{test_function_2(2)}}''') m = 3 - print(f'''{test_function_2(m)}''') - print(f'''{test_function_2(4.0)}''') - print(f'''{test_function_2('5')}''') - print(f'''{test_function_2(4 * 1.5)}''') + print(f'''{{test_function_2(m)}}''') + print(f'''{{test_function_2(4.0)}}''') + print(f'''{{test_function_2('5')}}''') + print(f'''{{test_function_2({self.number_cast_transpiled('1.5')} * {self.number_cast_transpiled('4')})}}''') print(f'''''') test_function_3(4) print(f'''''') diff --git a/tests/test_level/test_level_16.py b/tests/test_level/test_level_16.py index 20d923f14ab..4888431b4bb 100644 --- a/tests/test_level/test_level_16.py +++ b/tests/test_level/test_level_16.py @@ -228,11 +228,11 @@ def test_access_plus(self): "lijst = [1, 2, 3]", HedyTester.list_access_transpiled('lijst[int(1)-1]'), HedyTester.list_access_transpiled('lijst[int(2)-1]'), - "optellen = lijst[int(1)-1] + lijst[int(2)-1]", + f"optellen = {self.addition_transpiled('lijst[int(1)-1]','lijst[int(2)-1]')}", HedyTester.list_access_transpiled('lijst[int(3)-1]'), - """\ - optellen = optellen + lijst[int(3)-1] - print(f'''{optellen}''')""") + f"""\ + optellen = {self.addition_transpiled('optellen','lijst[int(3)-1]')} + print(f'''{{optellen}}''')""") self.multi_level_tester( code=code, @@ -820,11 +820,11 @@ def test_play_random(self): notes = ['C4', 'E4', 'D4', 'F4', 'G4'] play notes[random]""") - expected = textwrap.dedent("""\ + expected = textwrap.dedent(f"""\ notes = ['C4', 'E4', 'D4', 'F4', 'G4'] chosen_note = str(random.choice(notes)).upper() if chosen_note not in notes_mapping.keys() and chosen_note not in notes_mapping.values(): - raise Exception('catch_value_exception') + raise Exception({self.value_exception_transpiled()}) play(notes_mapping.get(chosen_note, chosen_note)) time.sleep(0.5)""") diff --git a/tests/test_level/test_level_17.py b/tests/test_level/test_level_17.py index 7adcf7db693..bff6a6de76e 100644 --- a/tests/test_level/test_level_17.py +++ b/tests/test_level/test_level_17.py @@ -129,19 +129,19 @@ def test_if_elif_boolean(self): def test_for_loop(self): code = textwrap.dedent("""\ - a is 2 - b is 3 - for a in range 2 to 4: - a is a + 2 - b is b + 2""") - expected = textwrap.dedent("""\ - a = 2 - b = 3 - step = 1 if 2 < 4 else -1 - for a in range(2, 4 + step, step): - a = a + 2 - b = b + 2 - time.sleep(0.1)""") + a is 2 + b is 3 + for a in range 2 to 4: + a is a + 2 + b is b + 2""") + expected = textwrap.dedent(f"""\ + a = 2 + b = 3 + step = 1 if 2 < 4 else -1 + for a in range(2, 4 + step, step): + a = {self.addition_transpiled('a', 2)} + b = {self.addition_transpiled('b', 2)} + time.sleep(0.1)""") self.single_level_tester(code=code, expected=expected) diff --git a/tests/test_level/test_level_18.py b/tests/test_level/test_level_18.py index d39ea80f166..fd2ee4ecf9b 100644 --- a/tests/test_level/test_level_18.py +++ b/tests/test_level/test_level_18.py @@ -162,19 +162,19 @@ def test_if_else(self): def test_for_loop(self): code = textwrap.dedent("""\ - a is 2 - b is 3 - for a in range(2, 4): - a is a + 2 - b is b + 2""") - expected = textwrap.dedent("""\ - a = 2 - b = 3 - step = 1 if 2 < 4 else -1 - for a in range(2, 4 + step, step): - a = a + 2 - b = b + 2 - time.sleep(0.1)""") + a is 2 + b is 3 + for a in range(2, 4): + a is a + 2 + b is b + 2""") + expected = textwrap.dedent(f"""\ + a = 2 + b = 3 + step = 1 if 2 < 4 else -1 + for a in range(2, 4 + step, step): + a = {self.addition_transpiled('a', 2)} + b = {self.addition_transpiled('b', 2)} + time.sleep(0.1)""") self.multi_level_tester( code=code, diff --git a/translations/ar/LC_MESSAGES/messages.po b/translations/ar/LC_MESSAGES/messages.po index 542695a2076..0c65b0f1cf1 100644 --- a/translations/ar/LC_MESSAGES/messages.po +++ b/translations/ar/LC_MESSAGES/messages.po @@ -7,16 +7,15 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2024-02-26 13:05+0100\n" +"POT-Creation-Date: 2024-03-07 22:34+0200\n" "PO-Revision-Date: 2024-03-03 07:14+0000\n" "Last-Translator: Snoring Parrot \n" -"Language-Team: ar \n" "Language: ar\n" +"Language-Team: ar \n" +"Plural-Forms: nplurals=6; plural=(n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=0 && n%100<=2 ? 4 : 5);\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=6; plural=(n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=0 && n%100<=2 ? 4 : 5);\n" -"X-Generator: Weblate 5.5-dev\n" "Generated-By: Babel 2.14.0\n" #, fuzzy @@ -73,16 +72,16 @@ msgstr "It looks like you forgot to use a command with the text you put in line msgid "Missing Additional Command" msgstr "It looks like you forgot to complete writing {command} on line {line_number}." -#, fuzzy -msgid "Missing Square Brackets" -msgstr "It looks like you forgot to use square brackets [] around the list you were creating on line {line_number}." - msgid "Missing Command" msgstr "يبدو أنك نسيت استخدام أمر برمجي في السطر رقم {line_number}." msgid "Missing Inner Command" msgstr "يبدو أنك نسيت استخدام أمر برمجي مع الجملة {command} التي استعملتها في السطر رقم {line_number}." +#, fuzzy +msgid "Missing Square Brackets" +msgstr "It looks like you forgot to use square brackets [] around the list you were creating on line {line_number}." + #, fuzzy msgid "Missing Variable" msgstr "It looks like your {command} is missing a variable at the start of the line." @@ -309,6 +308,9 @@ msgstr "Couldn't parse the program" msgid "catch_index_exception" msgstr "You tried to access the list {list_name} but it is either empty or the index is not there." +msgid "catch_multiple_values_exception" +msgstr "" + #, fuzzy msgid "catch_value_exception" msgstr "While running your program the command {command} received the value {value} which is not allowed. {suggestion}." @@ -1615,6 +1617,9 @@ msgstr "Select all" msgid "select_lang" msgstr "اختر اللغة" +msgid "select_levels" +msgstr "" + msgid "select_tag" msgstr "اختر العلامة" @@ -1641,12 +1646,6 @@ msgstr "اعداداتي الشخصية" msgid "share_by_giving_link" msgstr "Show your program to other people by giving them the link below:" -msgid "share_confirm" -msgstr "هل أنت متأكد من أنك تريد جعل البرنامج عاماً/علنياً؟" - -msgid "share_success_detail" -msgstr "تم مشاركة البرنامج بنجاح." - #, fuzzy msgid "share_your_program" msgstr "Share your program" @@ -1777,6 +1776,9 @@ msgstr "Use a note between C0 and B9 or a number between 1 and 70" msgid "suggestion_number" msgstr "Try changing the value to a number" +msgid "suggestion_numbers_or_strings" +msgstr "" + msgid "surname" msgstr "الاسم الأول" @@ -1980,12 +1982,6 @@ msgstr "Unlock level thresholds" msgid "unsaved_class_changes" msgstr "There are unsaved changes, are you sure you want to leave this page?" -msgid "unshare_confirm" -msgstr "هل أنت متأكد من أنك تريد جعل البرنامج خاصاً/سرّياً؟" - -msgid "unshare_success_detail" -msgstr "تم التراجع عن مشاركة البرنامج بنجاح." - msgid "update_adventure_prompt" msgstr "هل أنت متأكد أنك تريد تعديل هذه المغامرة؟" @@ -2241,3 +2237,15 @@ msgstr "Your program" #~ msgid "hide_quiz" #~ msgstr "نهاية الفحص السريع" +#~ msgid "share_confirm" +#~ msgstr "هل أنت متأكد من أنك تريد جعل البرنامج عاماً/علنياً؟" + +#~ msgid "share_success_detail" +#~ msgstr "تم مشاركة البرنامج بنجاح." + +#~ msgid "unshare_confirm" +#~ msgstr "هل أنت متأكد من أنك تريد جعل البرنامج خاصاً/سرّياً؟" + +#~ msgid "unshare_success_detail" +#~ msgstr "تم التراجع عن مشاركة البرنامج بنجاح." + diff --git a/translations/en/LC_MESSAGES/messages.po b/translations/en/LC_MESSAGES/messages.po index c4d4c198cce..bdb0d32692b 100644 --- a/translations/en/LC_MESSAGES/messages.po +++ b/translations/en/LC_MESSAGES/messages.po @@ -7,16 +7,15 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2024-02-26 13:05+0100\n" +"POT-Creation-Date: 2024-03-07 22:34+0200\n" "PO-Revision-Date: 2024-03-03 07:14+0000\n" "Last-Translator: Snoring Parrot \n" -"Language-Team: en \n" "Language: en\n" +"Language-Team: en \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 5.5-dev\n" "Generated-By: Babel 2.14.0\n" msgid "Access Before Assign" @@ -280,6 +279,9 @@ msgstr "Couldn't parse the program" msgid "catch_index_exception" msgstr "You tried to access the list {list_name} but it is either empty or the index is not there." +msgid "catch_multiple_values_exception" +msgstr "While running your program the command {command} received the values {value} and {value} which are not allowed. {suggestion}." + msgid "catch_value_exception" msgstr "While running your program the command {command} received the value {value} which is not allowed. {suggestion}." @@ -1457,6 +1459,9 @@ msgstr "Select all" msgid "select_lang" msgstr "Select language" +msgid "select_levels" +msgstr "" + msgid "select_tag" msgstr "Select tag" @@ -1481,12 +1486,6 @@ msgstr "My personal settings" msgid "share_by_giving_link" msgstr "Show your program to other people by giving them the link below:" -msgid "share_confirm" -msgstr "Are you sure you want to make the program public?" - -msgid "share_success_detail" -msgstr "Program shared successfully." - msgid "share_your_program" msgstr "Share your program" @@ -1601,6 +1600,9 @@ msgstr "Use a note between C0 and B9 or a number between 1 and 70" msgid "suggestion_number" msgstr "Try changing the value to a number" +msgid "suggestion_numbers_or_strings" +msgstr "Try changing the values to be all text or all numbers" + msgid "surname" msgstr "First Name" @@ -1783,12 +1785,6 @@ msgstr "Unlock level thresholds" msgid "unsaved_class_changes" msgstr "There are unsaved changes, are you sure you want to leave this page?" -msgid "unshare_confirm" -msgstr "Are you sure you want to make the program private?" - -msgid "unshare_success_detail" -msgstr "Program unshared successfully." - msgid "update_adventure_prompt" msgstr "Are you sure you want to update this adventure?" @@ -2057,3 +2053,15 @@ msgstr "Your program" #~ msgid "hide_quiz" #~ msgstr "Hide quiz" +#~ msgid "share_confirm" +#~ msgstr "Are you sure you want to make the program public?" + +#~ msgid "share_success_detail" +#~ msgstr "Program shared successfully." + +#~ msgid "unshare_confirm" +#~ msgstr "Are you sure you want to make the program private?" + +#~ msgid "unshare_success_detail" +#~ msgstr "Program unshared successfully." +