/** * An automatically generated file, based on the files in `instructors/`. * We need to have the python code in these files made available in the * JS files, so we load them in via a preprocessing step. */ var $INSTRUCTOR_MODULES_EXTENDED = {}; $INSTRUCTOR_MODULES_EXTENDED["instructor_append.py"] = "from instructor_utility import *\ndef append_group_on_change():\n wrong_not_append_to_list()\ndef append_group():\n missing_append_in_iteration()\n missing_append_list_initialization()\n wrong_append_list_initiatization()\n wrong_not_append_to_list()\n append_list_wrong_slot()\ndef find_append_in(node):\n appendList = []\n calls = node.find_all(\"Call\")\n for node in calls:\n if node.func.attr == \"append\":\n appendList.append(node)\n return appendList\ndef missing_append_in_iteration():\n ast = parse_program()\n for_loops = ast.find_all(\"For\")\n for loop in for_loops:\n if len(find_append_in(loop)):\n return False\n explain(\"You must construct a list by appending values one at a time to the list.

(app_in_iter)
\")\n return True\ndef wrong_not_append_to_list():\n ast = parse_program()\n for_loops = ast.find_all(\"For\")\n for loop in for_loops:\n append_nodes = find_append_in(loop)\n for node in append_nodes:\n listNode = node.func.value\n if listNode.data_type != \"List\" and listNode.id != \"___\":\n explain(\"Values can only be appended to a list. The variable {0!s} is either not initialized, not initialized correctly, or is confused with another variable.

(app_not_list)
\".format(listNode.id))\ndef missing_append_list_initialization():\n ast = parse_program()\n for_loops = ast.find_all(\"For\")\n loop_appends = []\n for loop in for_loops:\n loop_appends.extend(find_append_in(loop));\n assignments = ast.find_all(\"Assign\")\n for append_call in loop_appends:\n append_loc = append_call.lineno\n append_var = append_call.func.value\n found_init = False\n for assignment in assignments:\n if assignment.has(append_var) and assignment.lineno < append_loc:\n found_init = True\n break\n if found_init == False and append_var.id != \"___\":\n explain(\"The list variable {0!s} must be initialized.

(no_app_list_init)
\".format(append_var.id))\n return True\n return False\n\ndef wrong_append_list_initiatization():\n ast = parse_program()\n for_loops = ast.find_all(\"For\")\n loop_appends = []\n for loop in for_loops:\n loop_appends.extend(find_append_in(loop));\n assignments = ast.find_all(\"Assign\")\n for append_call in loop_appends:\n append_loc = append_call.lineno\n append_var = append_call.func.value\n init_fail = False\n for assignment in assignments:\n if assignment.has(append_var) and assignment.lineno < append_loc:\n if assignment.value.ast_name == \"List\":\n if len(assignment.value.elts) != 0:\n init_fail = True\n else:#or if its not even a list\n init_fail = True\n if init_fail and append_var.id != \"___\":\n explain(\"The list variable {0!s} is either not initialized correctly or mistaken for another variable. The list you append to should be initialized to an empty list.

(app_list_init)
\".format(append_var.id))\n return\ndef append_list_wrong_slot():\n ast = parse_program()\n append_calls = find_append_in(ast)\n for append_call in append_calls:\n arg = append_call.args[0]\n caller = append_call.func.value\n if arg.ast_name == \"Name\":\n if arg.data_type == \"List\" and caller.id != \"___\":\n explain(\"You should not append a list ({0!s}) to {1!s}.

(app_list_slot)
\".format(arg.id, caller.id))" $INSTRUCTOR_MODULES_EXTENDED["instructor_files.py"] = "from instructor import *\nfrom instructor_utility import *\n\ndef files_not_handled_correctly(*filenames):\n if filenames and isinstance(filenames[0], int):\n num_filenames = filenames[0]\n actual_filenames = False\n else:\n num_filenames = len(filenames)\n actual_filenames = True\n ast = parse_program()\n calls = ast.find_all(\"Call\")\n called_open = []\n closed = []\n for a_call in calls:\n if a_call.func.ast_name == 'Name':\n if a_call.func.id == 'open':\n if not a_call.args:\n gently(\"You have called the open function without any arguments. It needs a filename.\")\n return True\n called_open.append(a_call)\n elif a_call.func.id == 'close':\n explain(\"You have attempted to call close as a function, but it is actually a method of the file object.\")\n return True\n elif a_call.func.ast_name == 'Attribute':\n if a_call.func.attr == 'open':\n gently(\"You have attempted to call open as a method, but it is actually a built-in function.\")\n return True\n elif a_call.func.attr == 'close':\n closed.append(a_call)\n \n if len(called_open) < num_filenames:\n gently(\"You have not opened all the files you were supposed to.\")\n return True\n elif len(called_open) > num_filenames:\n gently(\"You have opened more files than you were supposed to.\")\n return True\n withs = ast.find_all(\"With\")\n if len(withs) + len(closed) < num_filenames:\n gently(\"You have not closed all the files you were supposed to.\")\n return True\n elif len(withs) + len(closed) > num_filenames:\n gently(\"You have closed more files than you were supposed to.\")\n return True\n if actual_filenames:\n ensure_literal(*filenames)\n return False\n" $INSTRUCTOR_MODULES_EXTENDED["instructor_filter.py"] = "from instructor_utility import *\ndef filter_group():\n missing_if_in_for()\n append_not_in_if()\n'''\nName: missing_if_in_for\nPattern:\nmissing\nfor in ___ :\n if … … :\n\nFeedback: The arrangement of decision and iteration is not correct for the filter pattern.\n\n'''\ndef missing_if_in_for():\n ast = parse_program()\n loops = ast.find_all(\"For\")\n for loop in loops:\n iter_prop = loop.target\n ifs = loop.find_all(\"If\")\n if len(ifs) > 0:\n return False\n explain(\"The arrangement of decision and iteration is not correct for the filter pattern.

(missing_if_in_for)
\")\n return True\n'''\nName: append_not_in_if\nPattern:\nmissing\nif … :\n ___.append(___)\n\nFeedback: Only items satisfying some condition should be appended to the list.\n\n'''\ndef append_not_in_if():\n ast = parse_program()\n ifs = ast.find_all(\"If\")\n for if_block in ifs:\n calls = if_block.find_all(\"Call\")\n for node in calls:\n if node.func.attr == \"append\":\n return False\n explain(\"Only items satisfying some condition should be appended to the list.

(app_not_in_if)
\")\n return True" $INSTRUCTOR_MODULES_EXTENDED["instructor_functions.py"] = "from instructor import *\n\nDELTA = 0.001\n\ndef match_signature(name, length, *parameters):\n ast = parse_program()\n defs = ast.find_all('FunctionDef')\n for a_def in defs:\n if a_def._name == name:\n found_length = len(a_def.args.args)\n if found_length < length:\n gently(\"The function named {} has fewer parameters ({}) than expected ({}).\".format(name, found_length, length))\n elif found_length > length:\n gently(\"The function named {} has more parameters ({}) than expected ({}).\".format(name, found_length, length))\n elif parameters:\n for parameter, arg in zip(parameters, a_def.args.args):\n if arg.id != parameter:\n gently(\"Error in definition of {}. Expected a parameter named {}, instead found {}.\".format(name, parameter, arg.id))\n else:\n return a_def\n else:\n return a_def\n else:\n gently(\"No function named {} was found.\".format(name))\n return None\n \ndef output_test(name, *tests):\n if name in student.data:\n the_function = student.data[name]\n if callable(the_function):\n for test in tests:\n inp = test[:-1]\n out = test[-1]\n tip = \"\"\n if isinstance(out, tuple):\n tip = \"

\"+out[1]\n out = out[0]\n template = \"Your {} function did not produce the correct printed output.
Given arguments: {}
Expected output: {}
Actual output: {}\"\n reset_output()\n the_function(*inp)\n test_out = get_output()\n inputs = ', '.join([\"{}\".format(repr(i)) for i in inp])\n if isinstance(out, str):\n if len(test_out) < 1:\n gently(template.format(name, inputs, repr(out), \"No output\", tip))\n return None\n elif len(test_out) > 1:\n gently(template.format(name, inputs, repr(out), \"Too many outputs\", tip))\n return None\n elif out not in test_out:\n gently(template.format(name, inputs, repr(out), repr(test_out[0]), tip))\n return None\n elif out != test_out:\n out = '
{}
'.format('\\n'.join(out))\n test_out = '
{}
'.format('\\n'.join(test_out))\n gently(template.format(name, inputs, out, test_out, tip))\n return None\n else:\n return the_function\n else:\n gently(\"You defined {}, but did not define it as a function.\".format(name))\n return None\n else:\n gently(\"The function {} was not defined.\".format(name))\n return None\n\n \ndef unit_test(name, *tests):\n if name in student.data:\n the_function = student.data[name]\n if callable(the_function):\n for test in tests:\n inp = test[:-1]\n out = test[-1]\n tip = \"\"\n if isinstance(out, tuple):\n tip = \"

\"+out[1]\n out = out[0]\n message = \"Your {} function did not return the right value.
Given arguments: {}
Expected return: {}
Actually returned: {}{}\"\n test_out = the_function(*inp)\n inputs = ', '.join([\"{}\".format(repr(i)) for i in inp])\n message = message.format(name, inputs, repr(out), repr(test_out), tip)\n if (isinstance(out, float) and \n isinstance(test_out, (float, int)) and\n abs(out-test_out) < DELTA):\n continue\n elif out != test_out:\n gently(message)\n return None\n else:\n return the_function\n else:\n gently(\"You defined {}, but did not define it as a function.\".format(name))\n return None\n else:\n gently(\"The function {} was not defined.\".format(name))\n return None\n" $INSTRUCTOR_MODULES_EXTENDED["instructor_histogram.py"] = "from instructor_utility import *\ndef histogram_group():\n histogram_argument_not_list()\n histogram_wrong_list()\n histogram_missing()\n plot_show_missing()\n'''\nName: histogram_missing\nPattern:\n\nMissing\n plt.hist(___)\n\nFeedback: The program should display a histogram.\n\n'''\ndef histogram_missing():\n ast = parse_program()\n calls = ast.find_all(\"Call\")\n plotting = False\n for call in calls:\n if call.func.attr == \"hist\" and call.func.value.id == \"plt\":\n plotting = True\n break\n if plotting == False:\n explain(\"The program should display a histogram.

(histo_missing)
\")\n return not plotting\n'''\nName: plot_show_missing\nPattern:\nMissing\n plt.show()\n\nFeedback: The plot must be explicitly shown to appear in the Printer area.\n'''\ndef plot_show_missing():\n ast = parse_program()\n calls = ast.find_all(\"Call\")\n plotting = False\n for call in calls:\n if call.func.attr == \"show\" and call.func.value.id == \"plt\":\n plotting = True\n break\n if plotting == False:\n explain(\"The plot must be explicitly shown to appear in the Printer area.

(plot_show_missing)
\")\n return not plotting\n'''\nName: histogram_argument_not_list\nPattern:\n plt.hist()\nWhere type() is not \"list\"\n\nFeedback: Making a histogram requires a list; is not a list.\n\n'''\ndef histogram_argument_not_list():\n ast = parse_program()\n calls = ast.find_all(\"Call\")\n arg_name = \"\"\n for call in calls:\n if call.func.attr == \"hist\" and call.func.value.id == \"plt\":\n arg = call.args[0]\n if arg != None and not (arg.data_type == \"List\" or arg.ast_name == \"List\"):\n arg_name = arg.id\n break\n if arg_name != \"\":\n if arg_name == \"___\":\n explain(\"Making a histogram requires a list; the list is missing.

(hist_arg_not_list_blank)
\")\n else:\n explain(\"Making a histogram requires a list; {0!s} is not a list.

(hist_arg_not_list)
\".format(arg_name))\n return arg_name != \"\"\n'''\nName: histogram_wrong_list\nPattern:\n\nfor ___ in ___:\n .append(___)\nplt.hist()\n\nwhere name() != name()\n\nFeedback: The list created in the iteration is not the list being used to create the histogram.\n\n'''\n\ndef histogram_wrong_list():\n ast = parse_program()\n loops = ast.find_all(\"For\")\n append_targets = []\n for loop in loops:\n calls = loop.find_all(\"Call\")\n for call in calls:\n if call.func.attr == \"append\":\n append_targets.append(call.func.value)\n all_proper_plot = True\n #should probably actually check for the location of plt.hist\n calls = ast.find_all(\"Call\")\n for call in calls:\n if call.func.attr == \"hist\" and call.func.value.id == \"plt\":\n arg = call.args[0]\n proper_plot = False\n if arg.ast_name == \"Name\":\n for name in append_targets:\n if name.id == arg.id:\n proper_plot = True\n break\n if not proper_plot:\n all_proper_plot = False\n break\n else:\n all_proper_plot = False\n break\n if not all_proper_plot:\n explain(\"The list created in the iteration is not the list being used to create the histogram.

(histo_wrong_list)
\")\n return not all_proper_plot" $INSTRUCTOR_MODULES_EXTENDED["instructor_imports.py"] = "from instructor import *\n\ndef ensure_imports(*modules):\n ast = parse_program()\n for module in modules:\n imports= ast.find_all(\"Import\")\n import_froms = ast.find_all(\"ImportFrom\")\n if not imports and not import_froms:\n gently(\"You need to import the {} module!\".format(module))\n return True\n success = False\n if imports:\n if any(alias._name == module\n for i in imports\n for alias in i.names):\n success = True\n if import_froms:\n if any(i.module == module for i in import_froms):\n success = True\n if not success:\n gently(\"You need to import the {} module.\".format(module))\n return True\n return False" $INSTRUCTOR_MODULES_EXTENDED["instructor_iteration.py"] = "from instructor import *\ndef iteration_group():\n list_initialization_misplaced()\n wrong_target_is_list()\n wrong_list_repeated_in_for()\n missing_iterator_initialization()\n list_not_initialized_on_run()\n wrong_iterator_not_list()\n missing_target_slot_empty()\n missing_for_slot_empty()\n wrong_target_reassigned()\ndef iteration_group_on_change():\n wrong_target_is_list()\n wrong_list_repeated_in_for()\n wrong_iterator_not_list()\ndef all_for_loops():\n ast = parse_program()\n return ast.find_all(\"For\")\n#this conflics with list_repeated_in_for\ndef wrong_target_is_list():\n for_loops = all_for_loops()\n for loop in for_loops:\n iter_prop = loop.target\n if iter_prop.ast_name == \"Name\" and iter_prop.data_type == \"List\":\n explain('The variable {0!s} is a list and should not be placed in the iteration variable slot of the \"for\" block

(target_is_list)
.'.format(iter_prop.id))\n return False\n#this conflics with list_in_wrong_slot_in_for\ndef wrong_list_repeated_in_for():\n for_loops = all_for_loops()\n for loop in for_loops:\n iter_prop = loop.target\n list_prop = loop.iter\n if iter_prop.ast_name == \"Name\" and list_prop.ast_name == \"Name\" and iter_prop.id == list_prop.id and iter_prop.data_type == \"List\":\n explain('The {0!s} variable can only appear once in the \"for\" block

(list_repeat)
'.format(list_prop.id))\n return False\n#this isn't consistent with the pattern you wrote\ndef missing_iterator_initialization():\n ast = parse_program()\n for_loops = all_for_loops()\n for loop in for_loops:\n list_prop = loop.iter\n if list_prop.ast_name != \"List\" and (list_prop.data_type != \"List\" or def_use_error(list_prop)):\n if list_prop.id == \"___\":\n explain(\"The slot to hold a list in the iteration is empty.

(no_iter_init-blank)
\".format(list_prop.id))\n else:\n explain(\"The variable {0!s} is in the list slot of the iteration but is not a list.

(no_iter_init)
\".format(list_prop.id))\n return True\n return False\n#TODO: We need to cover the different cases for these\ndef wrong_iterator_not_list():\n for_loops = all_for_loops()\n for loop in for_loops:\n list_prop = loop.iter\n if list_prop.ast_name != \"List\" and list_prop.data_type != \"List\" and list_prop.id != \"___\":\n if list_prop.ast_name == \"Name\":\n explain(\"The variable {0!s} has been set to something that is not a list but is placed in the iteration block that must be a list.

(iter_not_list)
\".format(list_prop.id))\n return True\n return False\ndef missing_target_slot_empty():\n for_loops = all_for_loops()\n for loop in for_loops:\n iter_prop = loop.target\n if iter_prop.id == \"___\":\n explain(\"You must fill in the empty slot in the iteration.

(target_empty)
\")\n return True\n return False\ndef list_not_initialized_on_run():\n for_loops = all_for_loops()\n for loop in for_loops:\n list_prop = loop.iter\n if list_prop.data_type == None:\n explain(\"The list in your for loop has not been initialized

(no_list_init)
\")\ndef list_initialization_misplaced():\n for_loops = all_for_loops()\n for loop in for_loops:\n list_prop = loop.iter\n if list_prop.data_type == \"List\" and def_use_error(list_prop):\n explain(\"Initialization of {0!s} is a list but either in the wrong place or redefined

(list_init_misplaced)
\".format(list_prop.id))\ndef missing_for_slot_empty():\n for_loops = all_for_loops()\n is_missing = False\n for loop in for_loops:\n list_prop = loop.iter\n iter_prop = loop.target\n if list_prop.ast_name == \"Name\" and list_prop.id == \"___\":\n is_missing = True\n break\n if iter_prop.ast_name == \"Name\" and iter_prop.id == \"___\":\n is_missing = True\n break\n if is_missing:\n explain(\"You must fill in the empty slot in the iteration.

(for_incomplete)
\")\ndef wrong_target_reassigned():\n ast = parse_program()\n for_loops = all_for_loops()\n is_reassigned = False\n iter_props = []\n for loop in for_loops:\n iter_props.append(loop.target)\n assignments = ast.find_all(\"Assign\")\n off_prop = \"\"\n for assignment in assignments:\n left = assignment.targets\n for iter_prop in iter_props:\n if left.id == iter_prop.id:\n off_prop = left.id\n is_reassigned = True\n break\n if is_reassigned:\n break\n if is_reassigned:\n explain(\"The variable {0!s} has been reassigned. The iteration variable shouldn't be reassigned

(target_reassign)
\".format(off_prop))" $INSTRUCTOR_MODULES_EXTENDED["instructor_plotting.py"] = "from instructor import *\nfrom instructor_utility import *\n\n\nPLOT_LABEL = {'plot': 'line plot', \n 'hist': 'histogram', \n 'scatter': 'scatter plot'}\ndef prevent_incorrect_plt():\n ast = parse_program()\n plts = [n for n in ast.find_all(\"Name\") if n.id == 'plt']\n if plts and def_use_error(plts[0]):\n explain(\"You have imported the matplotlib.pyplot module, but you did not rename it to plt using import matplotlib.pyplot as plt.\", 'verifier')\n return True\n for name in ['plot', 'hist', 'scatter', 'title', 'xlabel', 'ylabel', 'show']:\n for n in ast.find_all(\"Name\"):\n if n.id == name:\n if def_use_error(n):\n explain(\"You have attempt to use the MatPlotLib function named {0}. However, you imported MatPlotLib in a way that does not allow you to use the function directly. I recommend you use plt.{0} instead, after you use import matplotlib.pyplot as plt.\".format(name), 'verifier')\n return True\n return False\n \ndef ensure_correct_plot(type):\n for a_plot, label in PLOT_LABEL.items():\n if type == a_plot:\n if not function_is_called(type):\n gently(\"You are not calling the {} function.\".format(type))\n return True\n elif function_is_called(a_plot):\n gently(\"You have called the {} function, which makes a {}.\".format(a_plot, label))\n return True\n return False\n\ndef ensure_show():\n if not function_is_called(\"show\"):\n gently(\"You have not called show function, which actually creates the graph.\")\n return True\n return False\n\ndef compare_data(type, correct, given):\n if type == 'hist':\n return correct == given\n elif not correct:\n return False\n elif isinstance(correct[0], list):\n if len(correct[0]) != len(given):\n return False\n for x, y, g in zip(correct[0], correct[1], given):\n if x != g['x'] or y != g['y']:\n return False\n return True\n elif len(given) != len(correct):\n return False\n else:\n for x, (g, c) in enumerate(zip(given, correct)):\n if c != g['y'] or x != g['x']:\n return False\n return True\n \n\nGRAPH_TYPES = {'line': 'line plot', \n 'hist': 'histogram', \n 'scatter': 'scatter plot'}\ndef check_for_plot(type, data):\n '''\n Returns any errors found for this plot type and data.\n In other words, if it returns False, the plot was found correctly.\n '''\n type_found = False\n data_found = False\n for line in get_output():\n if not isinstance(line, list):\n continue\n for a_plot in line:\n data_found_here = compare_data(type, data, a_plot['data'])\n if a_plot['type'] == type and data_found_here:\n return False\n if a_plot['type'] == type:\n type_found = True\n if a_plot['data'] == data_found_here:\n data_found = True\n type = GRAPH_TYPES.get(type, type)\n if type_found and data_found:\n return (\"You have created a {}, but it does not have the right data. That data appears to have been plotted in another graph.\".format(type))\n elif type_found:\n return (\"You have created a {}, but it does not have the right data.\".format(type))\n elif data_found:\n return (\"You have plotted the right data, but you appear to have not plotted it as a {}.\".format(type))\n else:\n return (\"You have not created a {} with the proper data.\".format(type))" $INSTRUCTOR_MODULES_EXTENDED["instructor_printing.py"] = "from instructor import *\nfrom instructor_utility import *\n\ndef ensure_prints(count):\n prints = find_function_calls('print')\n if not prints:\n gently(\"You are not using the print function!\")\n return False\n elif len(prints) > count:\n gently(\"You are printing too many times!\")\n return False\n elif len(prints) < count:\n gently(\"You are not printing enough things!\")\n return False\n else:\n for a_print in prints:\n if not is_top_level(a_print):\n gently(\"You have a print function that is not at the top level. That is incorrect for this problem!\")\n return False\n return prints\n" $INSTRUCTOR_MODULES_EXTENDED["instructor_upload.py"] = "import re\nfrom instructor import *\n\n# Feedback for author's name\ndef check_author_name_on_header():\n code = get_program()\n m_author = re.search('Author: \\\\w+', code)\n if not m_author:\n gently(\"You need to add your name to the author field at the top of the file.\")\n \ndef get_plots(output):\n # The p[0] is the first plot in a graph/show\n return [p[0] for p in output if isinstance(p[0],dict)]\n \ndef find_plot_of_type(plot_list, plot_type):\n return [p['data'] for p in plot_list if p['type'] == plot_type]\n \n# Feedback for copying output of the program in the documentation\ndef check_output_on_header(expected_output):\n code = get_program()\n expected_output = str(expected_output)\n between_stars = code.split(\"*****\")[2].strip()\n between_stars = \"\\\\n\".join([x.strip() for x in between_stars.split(\"\\\\n\")])\n if 'REPLACE THIS TEXT WITH THE OUTPUT OF THIS PROGRAM' in between_stars:\n gently(\"In your code, you need to 'REPLACE THIS TEXT WITH THE OUTPUT OF THIS PROGRAM'\")\n elif not expected_output in between_stars:\n gently(\"The output you copied between the *****, seems to be incorrect. You may have copied it into the wrong location, or it is incomplete.\")\n\ndef check_print_output(multiple_lines):\n for line in multiple_lines:\n if line not in get_output():\n gently(\"You are not doing the correct calculation\")\n" $INSTRUCTOR_MODULES_EXTENDED["instructor_utility.py"] = "from instructor import *\n\ndef is_top_level(ast_node):\n ast = parse_program()\n for element in ast.body:\n if element.ast_name == 'Expr':\n if element.value == ast_node:\n return True\n elif element == ast_node:\n return True\n return False\n \ndef no_nested_function_definitions():\n ast = parse_program()\n defs = ast.find_all('FunctionDef')\n for a_def in defs:\n if not is_top_level(a_def):\n gently(\"You have defined a function inside of another block. For instance, you may have placed it inside another function definition, or inside of a loop. Do not nest your function definition!\")\n return False\n return True\n \ndef function_prints():\n ast = parse_program()\n defs = ast.find_all('FunctionDef')\n for a_def in defs:\n all_calls = a_def.find_all('Call')\n for a_call in all_calls:\n if a_call.func.ast_name == 'Name':\n if a_call.func.id == 'print':\n return True\n return False\n\ndef find_function_calls(name):\n ast = parse_program()\n all_calls = ast.find_all('Call')\n calls = []\n for a_call in all_calls:\n if a_call.func.ast_name == 'Attribute':\n if a_call.func.attr == name:\n calls.append(a_call)\n elif a_call.func.ast_name == 'Name':\n if a_call.func.id == name:\n calls.append(a_call)\n return calls\n\ndef function_is_called(name):\n return len(find_function_calls(name))\n \ndef no_nonlist_nums():\n pass\n \ndef only_printing_variables():\n ast = parse_program()\n all_calls = ast.find_all('Call')\n count = 0\n for a_call in all_calls:\n if a_call.func.ast_name == 'Name' and a_call.func.id == \"print\":\n for arg in a_call.args:\n if arg.ast_name != \"Name\":\n return False\n return True\n\ndef find_prior_initializations(node):\n if node.ast_name != \"Name\":\n return None\n ast = parse_program()\n assignments = ast.find_all(\"Assign\")\n cur_line_no = node.lineno\n all_assignments = []\n for assignment in assignments:\n if assignment.has(node):\n if assignment.lineno < cur_line_no:\n all_assignments.append(assignment)\n return all_assignments\n \ndef prevent_unused_result():\n ast = parse_program()\n exprs = ast.find_all('Expr')\n for expr in exprs:\n if expr.value.ast_name == \"Call\":\n a_call = expr.value\n if a_call.func.ast_name == 'Attribute':\n if a_call.func.attr == 'append':\n pass\n elif a_call.func.attr in ('replace', 'strip', 'lstrip', 'rstrip'):\n gently(\"Remember! You cannot modify a string directly. Instead, you should assign the result back to the string variable.\")\n \ndef prevent_builtin_usage(function_names):\n # Prevent direction calls\n ast = parse_program()\n all_calls = ast.find_all('Call')\n for a_call in all_calls:\n if a_call.func.ast_name == 'Name':\n if a_call.func.id in function_names:\n explain(\"You cannot use the builtin function {}.\".format(a_call.func.id))\n return a_call.func.id\n # Prevent tricky redeclarations!\n names = ast.find_all('Name')\n seen = set()\n for name in names:\n if name.id not in seen:\n if name.ctx == \"Load\" and name.id in function_names:\n explain(\"You cannot use the builtin function {}. If you are naming a variable, consider a more specific name.\".format(name.id))\n seen.add(name.id)\n return name.id\n return None\n \ndef prevent_literal(*literals):\n ast = parse_program()\n str_values = [s.s for s in ast.find_all(\"Str\")]\n num_values = [n.n for n in ast.find_all(\"Num\")]\n for literal in literals:\n if isinstance(literal, (int, float)):\n if literal in num_values:\n explain(\"Do not use the literal value {} in your code.\".format(repr(literal)))\n return literal\n elif isinstance(literal, str):\n if literal in str_values:\n explain(\"Do not use the literal value {} in your code.\".format(repr(literal)))\n return literal\n return False\ndef ensure_literal(*literals):\n ast = parse_program()\n str_values = [s.s for s in ast.find_all(\"Str\")]\n num_values = [n.n for n in ast.find_all(\"Num\")]\n for literal in literals:\n if isinstance(literal, (int, float)):\n if literal not in num_values:\n explain(\"You need the literal value {} in your code.\".format(repr(literal)))\n return literal\n elif isinstance(literal, str):\n if literal not in str_values:\n explain(\"You need the literal value {} in your code.\".format(repr(literal)))\n return literal\n return False\n \ndef prevent_advanced_iteration():\n ast = parse_program()\n if ast.find_all('While'):\n explain(\"You should not use a while loop to solve this problem.\")\n prevent_builtin_usage(['sum', 'map', 'filter', 'reduce', 'len', 'max', 'min',\n 'max', 'sorted', 'all', 'any', 'getattr', 'setattr',\n 'eval', 'exec', 'iter'])\n\nCOMPARE_OP_NAMES = {\n \"==\": \"Eq\", \n \"<\": \"Lt\", \n \"<=\": \"Lte\", \n \">=\": \"Gte\", \n \">\": \"Gt\", \n \"!=\": \"NotEq\", \n \"is\": \"Is\", \n \"is not\": \"IsNot\", \n \"in\": \"In_\", \n \"not in\": \"NotIn\"}\nBOOL_OP_NAMES = {\n \"and\": \"And\",\n \"or\": \"Or\"}\nBIN_OP_NAMES = {\n \"+\": \"Add\",\n \"-\": \"Sub\",\n \"*\": \"Mult\",\n \"/\": \"Div\",\n \"//\": \"FloorDiv\",\n \"%\": \"Mod\",\n \"**\": \"Pow\",\n \">>\": \"LShift\",\n \"<<\": \"RShift\",\n \"|\": \"BitOr\",\n \"^\": \"BitXor\",\n \"&\": \"BitAnd\",\n \"@\": \"MatMult\"}\nUNARY_OP_NAMES = {\n #\"+=\": \"UAdd\",\n #\"-=\": \"USub\",\n \"not\": \"Not\",\n \"~\": \"Invert\"\n}\ndef ensure_operation(op_name, root=None):\n if root is None:\n root = parse_program()\n result = find_operation(op_name, root)\n if result == False:\n gently(\"You are not using the {} operator.\".format(op_name))\n return result\ndef prevent_operation(op_name, root=None):\n if root is None:\n root = parse_program()\n result = find_operation(op_name, root)\n if result != False:\n gently(\"You may not use the {} operator.\".format(op_name))\n return result\n \ndef find_operation(op_name, root): \n if op_name in COMPARE_OP_NAMES:\n compares = root.find_all(\"Compare\")\n for compare in compares:\n for op in compare.ops:\n if op == COMPARE_OP_NAMES[op_name]:\n return compare\n elif op_name in BOOL_OP_NAMES:\n boolops = root.find_all(\"BoolOp\")\n for boolop in boolops:\n if boolop.op == BOOL_OP_NAMES[op_name]:\n return boolop\n elif op_name in BIN_OP_NAMES:\n binops = root.find_all(\"BinOp\")\n for binop in binops:\n if binop.op == BIN_OP_NAMES[op_name]:\n return binop\n elif op_name in UNARY_OP_NAMES:\n unaryops = root.find_all(\"UnaryOp\")\n for unaryop in unaryops:\n if unaryop.op == UNARY_OP_NAMES[op_name]:\n return unaryop\n return False\n'''\n \n mod.no_nonlist_nums = new Sk.builtin.func(function(source) {\n Sk.builtin.pyCheckArgs(\"no_nonlist_nums\", arguments, 1, 1);\n Sk.builtin.pyCheckType(\"source\", \"string\", Sk.builtin.checkString(source));\n \n source = source.v;\n \n var num_list = getNonListNums(source);\n \n var count = 0;\n for (var i = 0, len = num_list.length; i < len; i = i+1) {\n if (num_list[i].v != 0 && num_list[i].v != 1) {\n return Sk.ffi.remapToPy(true);\n }\n }\n return Sk.ffi.remapToPy(false);\n });\n\n\n \n /**\n * Given source code as a string, return a list of all of the AST elements\n * that are Num (aka numeric literals) but that are not inside List elements.\n *\n * @param {String} source - Python source code.\n * @returns {Array.number} The list of JavaScript numeric literals that were found.\n */\n function getNonListNums(source) {\n if (!(source in parses)) {\n var parse = Sk.parse(\"__main__\", source);\n parses[source] = Sk.astFromParse(parse.cst, \"__main__\", parse.flags);\n }\n var ast = parses[source];\n var visitor = new NodeVisitor();\n var insideList = false;\n var nums = [];\n visitor.visit_List = function(node) {\n insideList = true;\n this.generic_visit(node);\n insideList = false;\n }\n visitor.visit_Num = function(node) {\n if (!insideList) {\n nums.push(node.n);\n }\n this.generic_visit(node);\n }\n visitor.visit(ast);\n return nums;\n }\n \n \n '''"