def schema_config(self): """Define the configuration options for ListGrader""" # Construct the default AbstractGrader schema schema = super(ListGrader, self).schema_config # Append options return schema.extend({ Required('ordered', default=False): bool, Required('subgraders'): Any(AbstractGrader, [AbstractGrader]), Required('grouping', default=[]): [Positive(int)], Required('answers', default=[]): Any(list, (list, )) # Allow for a tuple of lists })
def __init__(self, config=None, **kwargs): super(IntegralGrader, self).__init__(config, **kwargs) self.true_input_positions = self.validate_input_positions( self.config['input_positions']) # The below are copied from FormulaGrader.__init__ # Set up the various lists we use self.functions, self.random_funcs = construct_functions( self.config["whitelist"], self.config["blacklist"], self.config["user_functions"]) self.constants = construct_constants(self.config["user_constants"]) # TODO I would like to move this into construct_constants at some point, # perhaps giving construct_constants and optional argument specifying additional defaults if 'infty' not in self.constants: self.constants['infty'] = float('inf') # Construct the schema for sample_from # First, accept all VariableSamplingSets # Then, accept any list that RealInterval can interpret # Finally, single numbers or tuples of numbers will be handled by DiscreteSet schema_sample_from = Schema({ Required(varname, default=RealInterval()): Any(VariableSamplingSet, All(list, lambda pair: RealInterval(pair)), lambda tup: DiscreteSet(tup)) for varname in self.config['variables'] }) self.config['sample_from'] = schema_sample_from( self.config['sample_from'])
def __init__(self, config=None, **kwargs): """ Validate the Formulagrader's configuration. First, we allow the ItemGrader initializer to construct the function list. We then construct the lists of functions, suffixes and constants. Finally, we refine the sample_from entry. """ super(FormulaGrader, self).__init__(config, **kwargs) # Set up the various lists we use self.functions, self.random_funcs = construct_functions(self.config["whitelist"], self.config["blacklist"], self.config["user_functions"]) self.constants = construct_constants(self.config["user_constants"]) self.suffixes = construct_suffixes(self.config["metric_suffixes"]) # Construct the schema for sample_from # First, accept all VariableSamplingSets # Then, accept any list that RealInterval can interpret # Finally, single numbers or tuples of numbers will be handled by DiscreteSet schema_sample_from = Schema({ Required(varname, default=RealInterval()): Any(VariableSamplingSet, All(list, lambda pair: RealInterval(pair)), lambda tup: DiscreteSet(tup)) for varname in self.config['variables'] }) self.config['sample_from'] = schema_sample_from(self.config['sample_from'])
def schema_answer(self): """Defines the schema that a fully-specified answer should satisfy.""" return Schema({ Required('expect'): self.schema_expect, Required('grade_decimal', default=1): All(numbers.Number, Range(0, 1)), Required('msg', default=''): str, Required('ok', default='computed'): Any('computed', True, False, 'partial') })
def NumberRange(number_type=Number): """ Schema that allows for a start and stop, or alternatively, a list [start, stop] The type of number can be restricted by specifying number_type=int, for example """ return Schema(Any( { Required('start', default=1): number_type, Required('stop', default=5): number_type }, number_range_alternate(number_type) ))
def schema_config(self): """Define the configuration options for IntegralGrader""" # Construct the default AbstractGrader schema schema = super(IntegralGrader, self).schema_config default_input_positions = { 'lower': 1, 'upper': 2, 'integrand': 3, 'integration_variable': 4 } # Append options return schema.extend({ Required('answers'): { Required('lower'): str, Required('upper'): str, Required('integrand'): str, Required('integration_variable'): str }, Required('input_positions', default=default_input_positions): { Required('lower', default=None): Any(None, Positive(int)), Required('upper', default=None): Any(None, Positive(int)), Required('integrand', default=None): Any(None, Positive(int)), Required('integration_variable', default=None): Any(None, Positive(int)), }, Required('integrator_options', default={'full_output': 1}): { Required('full_output', default=1): 1, Extra: object }, Required('complex_integrand', default=False): bool, # Most of the below are copied from FormulaGrader Required('user_functions', default={}): { Extra: Any(is_callable, [is_callable], FunctionSamplingSet) }, Required('user_constants', default={}): { Extra: Number }, Required('blacklist', default=[]): [str], Required('whitelist', default=[]): [Any(str, None)], Required('tolerance', default='0.01%'): Any(PercentageString, NonNegative(Number)), Required('case_sensitive', default=True): bool, Required('samples', default=1): Positive(int), # default changed to 1 Required('variables', default=[]): [str], Required('sample_from', default={}): dict, Required('failable_evals', default=0): NonNegative(int) })
def schema_config(self): """Define the configuration options for NumericalGrader""" # Construct the default FormulaGrader schema schema = super(NumericalGrader, self).schema_config # Modify the default FormulaGrader options return schema.extend({ Required('user_functions', default={}): {Extra: is_callable}, Required('tolerance', default='5%'): Any(PercentageString, NonNegative(Number)), Required('samples', default=1): 1, Required('variables', default=[]): [], Required('sample_from', default={}): {}, Required('failable_evals', default=0): 0 })
def schema_config(self): """Define the configuration options for FormulaGrader""" # Construct the default ItemGrader schema schema = super(FormulaGrader, self).schema_config # Append options forbidden_default = "Invalid Input: This particular answer is forbidden" return schema.extend({ Required('user_functions', default={}): {Extra: Any(is_callable, [is_callable], FunctionSamplingSet)}, Required('user_constants', default={}): {Extra: Number}, Required('blacklist', default=[]): [str], Required('whitelist', default=[]): [Any(str, None)], Required('forbidden_strings', default=[]): [str], Required('forbidden_message', default=forbidden_default): str, Required('required_functions', default=[]): [str], Required('tolerance', default='0.01%'): Any(PercentageString, NonNegative(Number)), Required('case_sensitive', default=True): bool, Required('metric_suffixes', default=False): bool, Required('samples', default=5): Positive(int), Required('variables', default=[]): [str], Required('sample_from', default={}): dict, Required('failable_evals', default=0): NonNegative(int) })
def schema_config(self): """Define the configuration options for SingleListGrader""" # Construct the default ItemGrader schema schema = super(SingleListGrader, self).schema_config # Append options, replacing the ItemGrader 'answers' key return schema.extend({ Required('ordered', default=False): bool, Required('length_error', default=False): bool, Required('delimiter', default=','): str, Required('partial_credit', default=True): bool, Required('subgrader'): ItemGrader, Required('answers', default=[]): Any(list, (list, )) # Allow for a tuple of lists })