def __call__(self, end_coord, buf, toks): """ Called once processing of the directive is complete. :param end_coord: The coordinates at which the directive processing completed. :type end_coord: ``hypocrite.location.Coordinate`` :param list buf: A list of lines, including trailing newlines, enclosed within the directive. :param list toks: A list of tokens. Will be ``None`` if the directive was closed by the end of file. :returns: A ``None`` value to indicate no further processing is necessary. :raises hypocrite.perfile.ParseException: An error occurred while parsing the directive. """ # Check for errors if toks is None: raise perfile.ParseException( 'Unclosed %%preamble directive at end of file; ' 'starts at %s' % self.start_coord) elif len(toks) != 0: raise perfile.ParseException( 'Invalid end of %%preamble directive at %s' % end_coord) # Update the preamble data self.values['preamble'].append( Preamble(self.start_coord - end_coord, buf)) return None
def teardown(self, end_coord, buf, toks): """ Called once processing of the teardown directive is complete. :param end_coord: The coordinates at which the directive processing completed. :type end_coord: ``hypocrite.location.Coordinate`` :param list buf: A list of lines, including trailing newlines, enclosed within the directive. :param list toks: A list of tokens. Will be ``None`` if the directive was closed by the end of file. :returns: A ``None`` value to indicate no further processing is necessary. :raises hypocrite.perfile.ParseException: An error occurred while parsing the directive. """ # Check for errors if toks is None: raise perfile.ParseException( 'Unclosed %%teardown directive at end of file; starts at %s' % self.block_start) elif len(toks) != 0: raise perfile.ParseException( 'Invalid end of %%teardown directive at %s' % end_coord) # Create the fixture self.values['fixtures'][self.name] = Fixture( self.start_coord - end_coord, self.name, self.type_, self.code, buf) return None
def __init__(self, values, start_coord, toks): """ Initialize a ``TestDirective`` instance. :param dict values: The values dictionary that the directive's return value may be placed in. :param start_coord: The coordinates the directive started at. :type start_coord: ``hypocrite.location.Coordinate`` :param list toks: A list of tokens. :raises hypocrite.perfile.ParseException: An error occurred while parsing the directive. """ # Make sure the token list is correct if (len(toks) < 2 or toks[0].type_ != perfile.TOK_WORD or not toks[0].value or toks[-1] != (perfile.TOK_CHAR, '{')): raise perfile.ParseException('Invalid %%test directive at %s' % start_coord) # Save the gunk we need for __call__() self.name = toks[0].value self.fixtures = [] self.values = values self.start_coord = start_coord # Extract the optional fixtures if len(toks) > 2: if (toks[1] != (perfile.TOK_CHAR, '(') or toks[-2] != (perfile.TOK_CHAR, ')')): raise perfile.ParseException('Invalid %%test directive at %s' % start_coord) for fix_toks in perfile.split_toks(toks[2:-2], {(perfile.TOK_CHAR, ',')}): # Sanity-check the tokens if len(fix_toks) < 1 or len(fix_toks) > 2: raise perfile.ParseException( 'Invalid fixture specification in %%test directive ' 'at %s' % start_coord) # Determine if it's an injectable inject = True if fix_toks[0] == (perfile.TOK_CHAR, '!'): inject = False fix_toks.pop(0) # Determine the fixture name if (len(fix_toks) != 1 or fix_toks[0].type_ != perfile.TOK_WORD or not fix_toks[0].value): raise perfile.ParseException( 'Invalid fixture specification in %%test directive ' 'at %s' % start_coord) # Add the fixture injection self.fixtures.append( HypoFixtureInjection(fix_toks[0].value, inject))
def __init__(self, values, start_coord, toks): """ Initialize a ``FixtureDirective`` instance. :param dict values: The values dictionary that the directive's return value may be placed in. :param start_coord: The coordinates the directive started at. :type start_coord: ``hypocrite.location.Coordinate`` :param list toks: A list of tokens. :raises hypocrite.perfile.ParseException: An error occurred while parsing the directive. """ # Parse the directive end_expected = False for type_, name, delim in _extract_type(toks, {(perfile.TOK_CHAR, '{')}): # Were we expecting the end of the directive? if end_expected: if type_ or name or delim: raise perfile.ParseException( 'Unexpected tokens after %%fixture directive at %s' % start_coord) # Just here to exhaust the iterator for coverage continue # pragma: no cover # OK, was it the end of the directive? elif not delim: raise perfile.ParseException( 'Premature end of arguments in %%fixture directive at %s' % start_coord) # Found the open brace end_expected = True # Sanity-check the name token if not name or name.type_ != perfile.TOK_WORD or not name.value: raise perfile.ParseException( 'Invalid %%fixture directive at %s' % start_coord) # Save the fixture's type and name self.name = name.value self.type_ = (None if not type_ or type_ == [(perfile.TOK_WORD, 'void')] else _make_type(type_, 'fixture', start_coord)) self.values = values self.start_coord = start_coord self.block_start = start_coord
def target_directive(values, start_coord, toks): """ The ``%target`` directive. Should contain a single TOK_STR token giving the name of the source file being tested. :param dict values: The values dictionary that the directive's return value may be placed in. :param start_coord: The coordinates the directive started at. :type start_coord: ``hypocrite.location.Coordinate`` :param list toks: A list of tokens. :returns: A ``None`` value to indicate no further processing is necessary. :raises hypocrite.perfile.ParseException: An error occurred while parsing the directive. """ # Make sure the token list is correct if len(toks) != 1 or toks[0].type_ != perfile.TOK_STR or not toks[0].value: raise perfile.ParseException('Invalid %%file directive at %s' % start_coord) # Save the target file values['target'] = toks[0].value return None
def insert(values, start_coord, toks): """ The ``%insert`` directive. Should contain a single TOK_WORD token giving the name of the section to insert into the file's structure. :param dict values: The values dictionary that the directive's return value may be placed in. :param start_coord: The coordinates the directive started at. :type start_coord: ``hypocrite.location.Coordinate`` :param list toks: A list of tokens. :returns: A ``None`` value to indicate no further processing is necessary. :raises hypocrite.perfile.ParseException: An error occurred while parsing the directive. """ # Make sure the token list is correct if (len(toks) != 1 or toks[0].type_ != perfile.TOK_WORD or not toks[0].value): raise perfile.ParseException('Invalid %%insert directive at %s' % start_coord) # Add an insert-section directive values['structure'].append( InsertSection(start_coord - start_coord, toks[0].value)) return None
def __init__(self, values, start_coord, toks): """ Initialize a ``SectionDirective`` instance. :param dict values: The values dictionary that the directive's return value may be placed in. :param start_coord: The coordinates the directive started at. :type start_coord: ``hypocrite.location.Coordinate`` :param list toks: A list of tokens. :raises hypocrite.perfile.ParseException: An error occurred while parsing the directive. """ # Make sure the token list is correct if (len(toks) < 2 or toks[0].type_ != perfile.TOK_WORD or not toks[0].value or toks[-1] != (perfile.TOK_CHAR, '{')): raise perfile.ParseException('Invalid %%section directive at %s' % start_coord) # Check for requirements requires = set() if len(toks) > 2: if (len(toks) < 4 or toks[1] != (perfile.TOK_CHAR, '(') or toks[-2] != (perfile.TOK_CHAR, ')')): raise perfile.ParseException( 'Invalid %%section directive at %s' % start_coord) for requirement in perfile.split_toks(toks[2:-2], {(perfile.TOK_CHAR, ',')}): if (len(requirement) != 1 or requirement[0].type_ != perfile.TOK_WORD or not requirement[0].value): raise perfile.ParseException( 'Invalid %%section directive at %s' % start_coord) requires.add(requirement[0].value) # Save the gunk we need for __call__() self.name = toks[0].value self.requires = requires self.values = values self.start_coord = start_coord
def __call__(self, end_coord, buf, toks): """ Called once processing of the directive is complete. :param end_coord: The coordinates at which the directive processing completed. :type end_coord: ``hypocrite.location.Coordinate`` :param list buf: A list of lines, including trailing newlines, enclosed within the directive. :param list toks: A list of tokens. Will be ``None`` if the directive was closed by the end of file. :returns: A ``None`` value to indicate no further processing is necessary, or a callable to collect the remaining lines. :raises hypocrite.perfile.ParseException: An error occurred while parsing the directive. """ # Check for errors if toks is None: raise perfile.ParseException( 'Unclosed %%fixture directive at end of file; starts at %s' % self.block_start) elif (len(toks) != 0 and toks != [(perfile.TOK_WORD, 'teardown'), (perfile.TOK_CHAR, '{')]): raise perfile.ParseException('Invalid %%teardown directive at %s' % end_coord) # If we have a teardown clause, save the code clause and chain if toks: self.code = buf self.block_start = end_coord # update to start of teardown return self.teardown # Create the fixture self.values['fixtures'][self.name] = Fixture( self.start_coord - end_coord, self.name, self.type_, buf) return None
def __init__(self, values, start_coord, toks): """ Initialize a ``PreambleDirective`` instance. :param dict values: The values dictionary that the directive's return value may be placed in. :param start_coord: The coordinates the directive started at. :type start_coord: ``hypocrite.location.Coordinate`` :param list toks: A list of tokens. :raises hypocrite.perfile.ParseException: An error occurred while parsing the directive. """ # Make sure the token list is correct if len(toks) != 1 or toks[0] != (perfile.TOK_CHAR, '{'): raise perfile.ParseException('Invalid %%preamble directive at %s' % start_coord) # Save the gunk we need for __call__() self.values = values self.start_coord = start_coord
def _make_type(toks, directive, coord): """ Construct a type string from a sequence of tokens. :param list toks: The list of tokens to form the type string from. :param str directive: The name of the directive. This is used for error reporting. :param coord: The coordinates the tokens are from. This is used for error reporting. :type coord: ``Coordinates`` :returns: A type string. :raises HypocriteException: An error occurred while parsing the directive. """ type_ = [] last_tok = None for tok in toks: # Watch out for bogus token types if tok.type_ != perfile.TOK_WORD and tok != (perfile.TOK_CHAR, '*'): raise perfile.ParseException('Invalid %%%s directive at %s' % (directive, coord)) if (last_tok and tok.type_ == perfile.TOK_CHAR and last_tok.type_ == perfile.TOK_CHAR): # Avoid spaces between subsequent '*' tokens type_[-1] += tok.value else: type_.append(tok.value) last_tok = tok # Create and return the type string return ' '.join(type_)
def mock(values, start_coord, toks): """ The ``%mock`` directive. Should contain a sequence of tokens declaring a function to be mocked, excluding any trailing semicolon (';'). :param dict values: The values dictionary that the directive's return value may be placed in. :param start_coord: The coordinates the directive started at. :type start_coord: ``hypocrite.location.Coordinate`` :param list toks: A list of tokens. :returns: A ``None`` value to indicate no further processing is necessary. :raises hypocrite.perfile.ParseException: An error occurred while parsing the directive. """ # Initialize the type iterator type_iter = _extract_type(toks, _mock_type_delims) # First, have to collect the return type and function name try: type_, name, delim = six.next(type_iter) except StopIteration: # pragma: no cover # Shouldn't ever actually happen raise perfile.ParseException('Invalid %%mock directive at %s' % start_coord) # Make sure the tokens make sense if (not type_ or name.type_ != perfile.TOK_WORD or not name.value or delim != (perfile.TOK_CHAR, '(')): raise perfile.ParseException('Invalid %%mock directive at %s' % start_coord) # Initialize the mock information func_name = name.value return_type = _make_type(type_, 'mock', start_coord) args = [] # Extract argument information end_expected = False for type_, name, delim in type_iter: # Were we expecting the end of the directive? if end_expected: if type_ or name or delim: raise perfile.ParseException( 'Unexpected tokens after %%mock directive at %s' % start_coord) # Just here to exhaust the iterator for coverage continue # pragma: no cover # OK, was it the end of the directive? elif not delim: raise perfile.ParseException( 'Premature end of arguments in %%mock directive at %s' % start_coord) # Found the closing parenthesis elif delim == (perfile.TOK_CHAR, ')'): end_expected = True # Handles the case of 'void foo()' and 'void foo(void)' if not args and ( (not type_ and not name) or (not type_ and name == (perfile.TOK_WORD, 'void'))): continue # Sanity-check the argument if (not type_ or not name or name.type_ != perfile.TOK_WORD or not name.value or delim == (perfile.TOK_CHAR, '(')): raise perfile.ParseException('Invalid %%mock directive at %s' % start_coord) # Save the argument args.append( HypoMockArg(_make_type(type_, 'mock', start_coord), name.value)) # Construct and save the mock values['mocks'][func_name] = HypocriteMock(start_coord - start_coord, func_name, return_type, args)