datacamp/pythonwhat

add check_class_def

machow opened this issue · 3 comments

cc @hugobowne

To test cases like...

class A(object):
    def __init__(self): pass

Here is the AST. Note that the body of the class is just python expressions, so we would only need to add an SCT to select the ClassDef node (and maybe to grab the bases).

image

@gvwilson I'll walk through this on Friday morning, to illustrate pythonwhat. Below are details for how to implement a check_class_def SCT.

Useful lines of code

Experimenting with AST

from pythonwhat.State import State
def create_state(sol_code, stu_code="", pe_code=""):
        s = State(
                student_code = stu_code,
                solution_code = sol_code,
                full_student_code = stu_code,
                full_solution_code = sol_code,
                pre_exercise_code = pe_code,
                student_process = None,
                solution_process = None,
                raw_student_output = ""
                )
        return s
code = """
class C:
    def a(self): print('hey')
"""

state = create_state(code, code, "")
state.student_ast                          # this is what the ast-viewer graphs

# we can dump the AST to text for inspection
import ast
from pythonwhat import utils_ast
ast.dump(state.student_ast)
utils_ast.pdp(state.student_ast)

Steps to implement

Add a parsing class to pythonwhat.parsing.py, that looks something like...

class ClassDefParser(Parser):
    """Find class def structures.
    A parser which inherits from the basic parser to find class def structures.
    Only 'top-level' class def structures will be found!
    """

    def __init__(self):
        self.out = []

    def visit_ClassDef(self, node):
        self.out.append({
            'node': node,
            'name': "name": getattr(node, 'name', None),
            'bases': [{'node': base} for base in node.bases],
            'body': node.body,
            })

Update pythonwhat/check_wrappers.py here with something like

'class_def': 'class definition of `{index}`'

Update pythonwhat/check_wrappers.py here with

'bases': '{ordinal} base class'

Update the parses dict in pythonwhat/parsing.py. This is used by pythonwhat/state.py here to put property methods on the State class for each parser.

@machow has this also been coded up at some point?

@filipsch I don't think so, the other parsing related issue that was never implemented is async functions

#210