def post_instantiation(self): # TODO(albert): rewrite test validation. Inconsistent leading space is # currently not validated correctly (see tests). self.docstring = textwrap.dedent(self.docstring) code = [] prompt_on = False leading_space = '' for line in self.docstring.split('\n'): prompt_match = self.prompt_re.match(line) if prompt_match: if prompt_on and not line.startswith(leading_space): raise ex.SerializeException( 'Inconsistent tabs for doctest') elif not prompt_on: prompt_on = True leading_space = prompt_match.group(1) code.append(line.lstrip()) elif not line.strip(): prompt_on = False leading_space = '' elif prompt_on: if not line.startswith(leading_space): raise ex.SerializeException( 'Inconsistent tabs for doctest') code.append(line.lstrip()) module = self.SETUP.format(importing.path_to_module_string(self.file)) self.case = doctest_case.DoctestCase(self.console, module, code='\n'.join(code))
def post_instantiation(self): # TODO(albert): rewrite test validation. Inconsistent leading space is # currently not validated correctly (see tests). self.docstring = textwrap.dedent(self.docstring) code = [] prompt_on = False leading_space = '' for line in self.docstring.split('\n'): prompt_match = self.prompt_re.match(line) if interpreter.Console.CASE_PREFIX in line.strip(): self.console.show_all_cases = True if prompt_match: if prompt_on and not line.startswith(leading_space): raise ex.SerializeException( 'Inconsistent tabs for doctest') elif not prompt_on: prompt_on = True leading_space = prompt_match.group(1) code.append(line.lstrip()) elif line.endswith('...'): # A line consisting only of ... is treated as a noop. See # issue #46 continue elif not line.strip(): prompt_on = False leading_space = '' elif prompt_on: if not line.startswith(leading_space): raise ex.SerializeException( 'Inconsistent tabs for doctest') code.append(line[len(leading_space):]) module = self.SETUP.format(importing.path_to_module_string(self.file)) self.case = interpreter.CodeCase(self.console, module, code='\n'.join(code))
def post_instantiation(self): for i, suite in enumerate(self.suites): if not isinstance(suite, dict): raise ex.SerializeException('Test cases must be dictionaries') elif 'type' not in suite: raise ex.SerializeException('Suites must have field "type"') elif suite['type'] not in self.suite_map: raise ex.SerializeException('Invalid suite type: ' '{}'.format(suite['type'])) self.suites[i] = self.suite_map[suite['type']]( self.verbose, self.interactive, self.timeout, **suite)
def coerce(self, value): if self._type is None: try: return list(value) except TypeError as e: raise ex.SerializeException(str(e)) else: # TODO(albert): find a way to do better element-wise type coercion # so that constructors can take additional arguments try: return [self._type(elem) for elem in value] except TypeError as e: raise ex.SerializeException(str(e))
def prettyjson(json, indentation=' '): """Formats a Python-object into a string in a JSON like way, but uses triple quotes for multiline strings. PARAMETERS: json -- Python object that is serializable into json. indentation -- str; represents one level of indentation NOTES: All multiline strings are treated as raw strings. RETURNS: str; the formatted json-like string. """ if isinstance(json, int) or isinstance(json, float): return str(json) elif isinstance(json, str): if '\n' in json: return 'r"""\n' + dedent(json) + '\n"""' return repr(json) elif isinstance(json, list): lst = [indent(prettyjson(el, indentation), indentation) for el in json] return '[\n' + ',\n'.join(lst) + '\n]' elif isinstance(json, dict): pairs = [] for k, v in sorted(json.items()): k = prettyjson(k, indentation) v = prettyjson(v, indentation) pairs.append(indent(k + ': ' + v, indentation)) return '{\n' + ',\n'.join(pairs) + '\n}' else: raise exceptions.SerializeException( 'Invalid json type: {}'.format(json))
def __init__(self, optional=False, **kargs): self._optional = optional if 'default' in kargs: value = kargs['default'] if not self.is_valid(value): raise ex.SerializeException( 'Invalid default: {}'.format(value)) self._optional = True self._default = value
def __call__(cls, *args, **kargs): obj = type.__call__(cls, *args, **kargs) # Validate existing arguments for attr, value in kargs.items(): if attr not in cls._fields: raise ex.SerializeException( '__init__() got an unexpected ' 'keyword argument: {}'.format(attr)) else: setattr(obj, attr, value) # Check for missing/default fields for attr, value in cls._fields.items(): if attr in kargs: continue elif value.optional: setattr(obj, attr, value.default) else: raise ex.SerializeException('__init__() missing expected ' 'argument {}'.format(attr)) obj.post_instantiation() return obj
def coerce(self, value): """Subclasses should override this method for type coercion. Default version will simply return the argument. If the argument is not valid, a SerializeException is raised. For primitives like booleans, ints, floats, and strings, use this default version to avoid unintended type conversions.""" if not self.is_valid(value): raise ex.SerializeException('{} is not a valid value for ' 'type {}'.format( value, self.__class__.__name__)) return value
def coerce(self, value): try: coerced = self._constructor(value) except TypeError as e: raise ex.SerializeException(str(e)) result = self._constructor() for k, v in coerced.items(): if self._keys is not None: k = self._keys(k) elif self._values is not None: v = self._values(k) result[k] = v return result
def post_instantiation(self): for i, case in enumerate(self.cases): if not isinstance(case, dict): raise ex.SerializeException('Test cases must be dictionaries') self.cases[i] = ConceptCase(**case)
def to_json(self, value): """Subclasses should override this method for JSON encoding.""" if not self.is_valid(value): raise ex.SerializeException('Invalid value: {}'.format(value)) return value
def post_instantiation(self): for i, case in enumerate(self.cases): if not isinstance(case, dict): raise ex.SerializeException('Test cases must be dictionaries') self.cases[i] = interpreter.CodeCase(self.console, self.setup, self.teardown, **case)