Update context values for student and solution environments. When ``has_equal_x()`` is used after this, the context values (in ``for`` loops and function definitions, for example) will have the values specified through his function. It is the function equivalent of the ``context_vals`` argu
(state, *args, **kwargs)
| 162 | |
| 163 | |
| 164 | def set_context(state, *args, **kwargs): |
| 165 | """Update context values for student and solution environments. |
| 166 | |
| 167 | When ``has_equal_x()`` is used after this, the context values (in ``for`` loops and function definitions, for example) |
| 168 | will have the values specified through his function. It is the function equivalent of the ``context_vals`` argument of |
| 169 | the ``has_equal_x()`` functions. |
| 170 | |
| 171 | - Note 1: excess args and unmatched kwargs will be unused in the student environment. |
| 172 | - Note 2: When you try to set context values that don't match any target variables in the solution code, |
| 173 | ``set_context()`` raises an exception that lists the ones available. |
| 174 | - Note 3: positional arguments are more robust to the student using different names for context values. |
| 175 | - Note 4: You have to specify arguments either by position, either by name. A combination is not possible. |
| 176 | |
| 177 | :Example: |
| 178 | |
| 179 | Solution code:: |
| 180 | |
| 181 | total = 0 |
| 182 | for i in range(10): |
| 183 | print(i ** 2) |
| 184 | |
| 185 | Student submission that will pass (different iterator, different calculation):: |
| 186 | |
| 187 | total = 0 |
| 188 | for j in range(10): |
| 189 | print(j * j) |
| 190 | |
| 191 | SCT:: |
| 192 | |
| 193 | # set_context is robust against different names of context values. |
| 194 | Ex().check_for_loop().check_body().multi( |
| 195 | set_context(1).has_equal_output(), |
| 196 | set_context(2).has_equal_output(), |
| 197 | set_context(3).has_equal_output() |
| 198 | ) |
| 199 | |
| 200 | # equivalent SCT, by setting context_vals in has_equal_output() |
| 201 | Ex().check_for_loop().check_body().\\ |
| 202 | multi([s.has_equal_output(context_vals=[i]) for i in range(1, 4)]) |
| 203 | |
| 204 | """ |
| 205 | |
| 206 | stu_crnt = state.student_context.context |
| 207 | sol_crnt = state.solution_context.context |
| 208 | |
| 209 | # for now, you can't specify both |
| 210 | if len(args) > 0 and len(kwargs) > 0: |
| 211 | raise InstructorError.from_message( |
| 212 | "In `set_context()`, specify arguments either by position, either by name." |
| 213 | ) |
| 214 | |
| 215 | # set args specified by pos ----------------------------------------------- |
| 216 | if args: |
| 217 | # stop if too many pos args for solution |
| 218 | if len(args) > len(sol_crnt): |
| 219 | raise InstructorError.from_message( |
| 220 | "Too many positional args. There are {} context vals, but tried to set {}".format( |
| 221 | len(sol_crnt), len(args) |