coalib.results package — coala 0.11.0.rc1 documentation

# coalib.results package

## Subpackages

- coalib.results.result_actions package
  - Submodules
  - coalib.results.result_actions.ApplyPatchAction module
  - coalib.results.result_actions.IgnoreResultAction module
  - coalib.results.result_actions.OpenEditorAction module
  - coalib.results.result_actions.PrintAspectAction module
  - coalib.results.result_actions.PrintDebugMessageAction module
  - coalib.results.result_actions.PrintMoreInfoAction module
  - coalib.results.result_actions.ResultAction module
  - coalib.results.result_actions.ShowPatchAction module
  - Module contents

## Submodules

## coalib.results.AbsolutePosition module

class `coalib.results.AbsolutePosition.` `AbsolutePosition`(text: (<class 'tuple'>, <class 'list'>, None) = None, position: (<class 'int'>, None) = None)

  Bases: `coalib.results.TextPosition.TextPosition`

  `position`

`coalib.results.AbsolutePosition.` `calc_line_col`(text, position)

  Creates a tuple containing (line, column) by calculating line number and column in the text, from position.

  The position represents the index of a character. In the following example ‘a’ is at position ‘0’ and it’s corresponding line and column are:

      >>> calc_line_col(('a\n',), 0)
      (1, 1)

  All special characters(including the newline character) belong in the same line, and have their own position. A line is an item in the tuple:

      >>> calc_line_col(('a\n', 'b\n'), 1)
      (1, 2)
      >>> calc_line_col(('a\n', 'b\n'), 2)
      (2, 1)

  Parameters: | text – A tuple/list of lines in which position is to be calculated. position – Position (starting from 0) of character to be found in the (line, column) form.
  Returns: | A tuple of the form (line, column), where both line and column start from 1.

## coalib.results.Diff module

class `coalib.results.Diff.` `Diff`(file_list, rename=False, delete=False)

  Bases: `object`

  A Diff result represents a difference for one file.

  `add_line`(line_nr_before, line)

    Adds line after the given line number.

    Parameters: | line_nr_before – Line number of the line before the addition. Use 0 to insert line before everything. line – Line to add.

  `add_lines`(line_nr_before, lines)

    Adds lines after the given line number.

    Parameters: | line_nr_before – Line number of the line before the additions. Use 0 for insert lines before everything. lines – A list of lines to add.

  `affected_code`(filename)

    Creates a list of SourceRange objects which point to the related code. Changes on continuous lines will be put into one SourceRange.

    Parameters: | filename – The filename to associate the SourceRange’s to.
    Returns: | A list of all related SourceRange objects.

  `change_line`(line_nr, original_line, replacement)
  `delete`

    Returns: | True if file is set to be deleted.

  `delete_line`(line_nr)

    Mark the given line nr as deleted. The first line is line number 1.

    Raises an exception if line number doesn’t exist in the diff.

  `delete_lines`(line_nr_start, line_nr_end)

    Delete lines in a specified range, inclusively.

    The range must be valid, i.e. lines must exist in diff, else an exception is raised.

  classmethod `from_clang_fixit`(fixit, file)

    Creates a Diff object from a given clang fixit and the file contents.

    Parameters: | fixit – A cindex.Fixit object. file – A list of lines in the file to apply the fixit to.
    Returns: | The corresponding Diff object.

  classmethod `from_string_arrays`(file_array_1, file_array_2, rename=False)

    Creates a Diff object from two arrays containing strings.

    If this Diff is applied to the original array, the second array will be created.

    Parameters: | file_array_1 – Original array file_array_2 – Array to compare rename – False or str containing new name of file.

  classmethod `from_unified_diff`(unified_diff, original_file)

    Creates a `Diff` object from given unified diff.

    If the provided unified diff does not contain any patch, the `Diff` object initialized from the original file is returned.

    Parameters: | unified_diff – Unified diff string. original_file – The contents of the original file (line-splitted).
    Raises: | RuntimeError – Raised when the context lines or the lines to be removed do not match in the original file and the unified diff.

  `insert`(position, text)

    Inserts (multiline) text at arbitrary position.

        >>> from coalib.results.TextPosition import TextPosition
        >>> test_text = ['123\n', '456\n', '789\n']
        >>> def insert(position, text):
        ...     diff = Diff(test_text)
        ...     diff.insert(position, text)
        ...     return diff.modified
        >>> insert(TextPosition(2, 3), 'woopy doopy')
        ['123\n', '45woopy doopy6\n', '789\n']
        >>> insert(TextPosition(1, 1), 'woopy\ndoopy')
        ['woopy\n', 'doopy123\n', '456\n', '789\n']
        >>> insert(TextPosition(2, 4), '\nwoopy\ndoopy\n')
        ['123\n', '456\n', 'woopy\n', 'doopy\n', '\n', '789\n']

    Parameters: | position – The `TextPosition` where to insert text. text – The text to insert.

  `modified`

    Calculates the modified file, after applying the Diff to the original.

  `modify_line`(line_nr, replacement)

    Changes the given line with the given line number. The replacement will be there instead.

    Given an empty diff object:

        >>> diff = Diff(['Hey there! Gorgeous.\n',
        ...              "It's nice that we're here.\n"])

    We can change a line easily:

        >>> diff.modify_line(1,
        ...                  'Hey there! This is sad.\n')
        >>> diff.modified
        ['Hey there! This is sad.\n', "It's nice that we're here.\n"]

    We can even merge changes within one line:

        >>> diff.modify_line(1,
        ...                  'Hello. :( Gorgeous.\n')
        >>> diff.modified
        ['Hello. :( This is sad.\n', "It's nice that we're here.\n"]

    However, if we change something that has been changed before, we’ll get a conflict:

        >>> diff.modify_line(1,  # +ELLIPSIS
        ...                  'Hello. This is not ok. Gorgeous.\n')
        Traceback (most recent call last):
         ...
        coalib.results.LineDiff.ConflictError: ...

  `original`

    Retrieves the original file.

  `range`(filename)

    Calculates a SourceRange spanning over the whole Diff. If something is added after the 0th line (i.e. before the first line) the first line will be included in the SourceRange.

    The range of an empty diff will only affect the filename:

        >>> range = Diff([]).range("file")
        >>> range.file is None
        False
        >>> print(range.start.line)
        None

    Parameters: | filename – The filename to associate the SourceRange with.
    Returns: | A SourceRange object.

  `remove`(range)

    Removes a piece of text in a given range.

        >>> from coalib.results.TextRange import TextRange
        >>> test_text = ['nice\n', 'try\n', 'bro\n']
        >>> def remove(range):
        ...     diff = Diff(test_text)
        ...     diff.remove(range)
        ...     return diff.modified
        >>> remove(TextRange.from_values(1, 1, 1, 4))
        ['e\n', 'try\n', 'bro\n']
        >>> remove(TextRange.from_values(1, 5, 2, 1))
        ['nicetry\n', 'bro\n']
        >>> remove(TextRange.from_values(1, 3, 3, 2))
        ['niro\n']
        >>> remove(TextRange.from_values(2, 1, 2, 1))
        ['nice\n', 'try\n', 'bro\n']

    Parameters: | range – The range to delete.

  `rename`

    Returns: | string containing new name of the file.

  `replace`(range, replacement)

    Replaces a part of text. Allows to span multiple lines.

    This function uses `add_lines` and `delete_lines` accordingly, so calls of those functions on lines given `range` affects after usage or vice versa lead to `ConflictError`.

        >>> from coalib.results.TextRange import TextRange
        >>> test_text = ['hello\n', 'world\n', '4lines\n', 'done\n']
        >>> def replace(range, text):
        ...     diff = Diff(test_text)
        ...     diff.replace(range, text)
        ...     return diff.modified
        >>> replace(TextRange.from_values(1, 5, 4, 3), '\nyeah\ncool\nno')
        ['hell\n', 'yeah\n', 'cool\n', 'none\n']
        >>> replace(TextRange.from_values(2, 1, 3, 5), 'b')
        ['hello\n', 'bes\n', 'done\n']
        >>> replace(TextRange.from_values(1, 6, 4, 3), '')
        ['hellone\n']

    Parameters: | range – The `TextRange` that gets replaced. replacement – The replacement string. Can be multiline.

  `split_diff`(distance=1)

    Splits this diff into small pieces, such that several continuously altered lines are still together in one diff. All subdiffs will be yielded.

    A diff like this with changes being together closely won’t be splitted:

        >>> diff = Diff.from_string_arrays([     'b', 'c', 'e'],
        ...                                ['a', 'b', 'd', 'f'])
        >>> len(list(diff.split_diff()))
        1

    If we set the distance to 0, it will be splitted:

        >>> len(list(diff.split_diff(distance=0)))
        2

    If a negative distance is given, every change will be yielded as an own diff, even if they are right beneath each other:

        >>> len(list(diff.split_diff(distance=-1)))
        3

    If a file gets renamed or deleted only, it will be yielded as is:

        >>> len(list(Diff([], rename='test').split_diff()))
        1

    An empty diff will not yield any diffs:

        >>> len(list(Diff([]).split_diff()))
        0

    Parameters: | distance – Number of unchanged lines that are allowed in between two changed lines so they get yielded as one diff.

  `stats`()

    Returns tuple containing number of additions and deletions in the diff.

  `unified_diff`

    Generates a unified diff corresponding to this patch.

    Note that the unified diff is not deterministic and thus not suitable for equality comparison.

## coalib.results.HiddenResult module

class `coalib.results.HiddenResult.` `HiddenResult`(origin, contents)

  Bases: `coalib.results.Result.Result`

  This is a result that is not meant to be shown to the user. It can be used to transfer any data from a dependent bear to others.

## coalib.results.LineDiff module

exception `coalib.results.LineDiff.` `ConflictError`

  Bases: `Exception`

class `coalib.results.LineDiff.` `LineDiff`(change=False, delete=False, add_after=False)

  Bases: `object`

  A LineDiff holds the difference between two strings.

  `add_after`
  `change`
  `delete`

## coalib.results.RESULT_SEVERITY module

## coalib.results.Result module

class `coalib.results.Result.` `Result`(origin, message: str, affected_code: (<class 'tuple'>, <class 'list'>) = (), severity: int = 1, additional_info: str = '', debug_msg='', diffs: (<class 'dict'>, None) = None, confidence: int = 100, aspect: (<class 'coalib.bearlib.aspects.base.aspectbase'>, None) = None, message_arguments: dict = {})

  Bases: `object`

  A result is anything that has an origin and a message.

  Optionally it might affect a file.

  Result messages can also have arguments. The message is python style formatted with these arguments.

      >>> r = Result('origin','{arg1} and {arg2}',            message_arguments={'arg1': 'foo', 'arg2': 'bar'})
      >>> r.message
      'foo and bar'

  Message arguments may be changed later. The result message will also reflect these changes.

      >>> r.message_arguments = {'arg1': 'spam', 'arg2': 'eggs'}
      >>> r.message
      'spam and eggs'

  `apply`(file_dict: dict)

    Applies all contained diffs to the given file_dict. This operation will be done in-place.

    Parameters: | file_dict – A dictionary containing all files with filename as key and all lines a value. Will be modified.

  classmethod `from_values`(origin, message: str, file: str, line: (<class 'int'>, None) = None, column: (<class 'int'>, None) = None, end_line: (<class 'int'>, None) = None, end_column: (<class 'int'>, None) = None, severity: int = 1, additional_info: str = '', debug_msg='', diffs: (<class 'dict'>, None) = None, confidence: int = 100, aspect: (<class 'coalib.bearlib.aspects.base.aspectbase'>, None) = None, message_arguments: dict = {})

    Creates a result with only one SourceRange with the given start and end locations.

    Parameters: | origin – Class name or creator object of this object. message – Base message to show with this result. message_arguments – Arguments to be provided to the base message file – The related file. line – The first related line in the file. (First line is 1) column – The column indicating the first character. (First character is 1) end_line – The last related line in the file. end_column – The column indicating the last character. severity – Severity of this result. additional_info – A long description holding additional information about the issue and/or how to fix it. You can use this like a manual entry for a category of issues. debug_msg – A message which may help the user find out why this result was yielded. diffs – A dictionary with filename as key and `Diff` object associated with it as value. confidence – A number between 0 and 100 describing the likelihood of this result being a real issue. aspect – An Aspect object which this result is associated to. Note that this should be a leaf of the aspect tree! (If you have a node, spend some time figuring out which of the leafs exactly your result belongs to.)

  `location_repr`()

    Retrieves a string, that briefly represents the affected code of the result.

    Returns: | A string containing all of the affected files separated by a comma.

  `message`
  `overlaps`(ranges)

    Determines if the result overlaps with source ranges provided.

    Parameters: | ranges – A list SourceRange objects to check for overlap.
    Returns: | True if the ranges overlap with the result.

  `to_string_dict`()

    Makes a dictionary which has all keys and values as strings and contains all the data that the base Result has.

    FIXME: diffs are not serialized ATM. FIXME: Only the first SourceRange of affected_code is serialized. If there are more, this data is currently missing.

    Returns: | Dictionary with keys and values as string.

## coalib.results.ResultFilter module

`coalib.results.ResultFilter.` `basics_match`(original_result, modified_result)

  Checks whether the following properties of two results match: * origin * message * severity * debug_msg

  Parameters: | original_result – A result of the old files modified_result – A result of the new files
  Returns: | Boolean value whether or not the properties match

`coalib.results.ResultFilter.` `ensure_files_present`(original_file_dict, modified_file_dict)

  Ensures that all files are available as keys in both dicts.

  Parameters: | original_file_dict – Dict of lists of file contents before changes modified_file_dict – Dict of lists of file contents after changes
  Returns: | Return a dictionary of renamed files.

`coalib.results.ResultFilter.` `filter_results`(original_file_dict, modified_file_dict, original_results, modified_results)

  Filters results for such ones that are unique across file changes

  Parameters: | original_file_dict – Dict of lists of file contents before changes modified_file_dict – Dict of lists of file contents after changes original_results – List of results of the old files modified_results – List of results of the new files
  Returns: | List of results from new files that are unique from all those that existed in the old changes

`coalib.results.ResultFilter.` `remove_range`(file_contents, source_range)

  removes the chars covered by the sourceRange from the file

  Parameters: | file_contents – list of lines in the file source_range – Source Range
  Returns: | list of file contents without specified chars removed

`coalib.results.ResultFilter.` `remove_result_ranges_diffs`(result_list, file_dict)

  Calculates the diffs to all files in file_dict that describe the removal of each respective result’s affected code.

  Parameters: | result_list – list of results file_dict – dict of file contents
  Returns: | returnvalue[result][file] is a diff of the changes the removal of this result’s affected code would cause for the file.

`coalib.results.ResultFilter.` `source_ranges_match`(original_file_dict, diff_dict, original_result_diff_dict, modified_result_diff_dict, renamed_files)

  Checks whether the SourceRanges of two results match

  Parameters: | original_file_dict – Dict of lists of file contents before changes diff_dict – Dict of diffs describing the changes per file original_result_diff_dict – diff for each file for this result modified_result_diff_dict – guess renamed_files – A dictionary containing file renamings across runs
  Returns: | Boolean value whether the SourceRanges match

## coalib.results.SourcePosition module

class `coalib.results.SourcePosition.` `SourcePosition`(file: str, line=None, column=None)

  Bases: `coalib.results.TextPosition.TextPosition`

  `file`

## coalib.results.SourceRange module

class `coalib.results.SourceRange.` `SourceRange`(start: coalib.results.SourcePosition.SourcePosition, end: (<class 'coalib.results.SourcePosition.SourcePosition'>, None) = None)

  Bases: `coalib.results.TextRange.TextRange`

  `affected_source`(file_dict: dict)

    Tells which lines are affected in a specified file within a given range.

        >>> from os.path import abspath
        >>> sr = SourceRange.from_values('file_name', start_line=2, end_line=2)
        >>> sr.affected_source({
        ...     abspath('file_name'): ('def fun():\n', '    x = 2  \n')
        ... })
        ('    x = 2  \n',)

    If more than one line is affected.

        >>> sr = SourceRange.from_values('file_name', start_line=2, end_line=3)
        >>> sr.affected_source({
        ...     abspath('file_name'): ('def fun():\n',
        ...                            '    x = 2  \n', '    print(x)  \n')
        ... })
        ('    x = 2  \n', '    print(x)  \n')

    If the file indicated at the source range is not in the file_dict or the lines are not given, this will return None:

        >>> sr = SourceRange.from_values('file_name_not_present',
        ...     start_line=2, end_line=2)
        >>> sr.affected_source({abspath('file_name'):
        ...     ('def fun():\n', '    x = 2  \n')})

    Parameters: | file_dict – It is a dictionary where the file names are the keys and the contents of the files are the values(which is of type tuple).
    Returns: | A tuple of affected lines in the specified file. If the file is not affected or the file is not present in `file_dict` return `None`.

  `expand`(file_contents)

    Passes a new SourceRange that covers the same area of a file as this one would. All values of None get replaced with absolute values.

    values of None will be interpreted as follows: self.start.line is None: -> 1 self.start.column is None: -> 1 self.end.line is None: -> last line of file self.end.column is None: -> last column of self.end.line

    Parameters: | file_contents – File contents of the applicable file
    Returns: | TextRange with absolute values

  `file`
  classmethod `from_absolute_position`(file: str, position_start: coalib.results.AbsolutePosition.AbsolutePosition, position_end: (<class 'coalib.results.AbsolutePosition.AbsolutePosition'>, None) = None)

    Creates a SourceRange from a start and end positions.

    Parameters: | file – Name of the file. position_start – Start of range given by AbsolutePosition. position_end – End of range given by AbsolutePosition or None.

  classmethod `from_clang_range`(range)

    Creates a SourceRange from a clang SourceRange object.

    Parameters: | range – A cindex.SourceRange object.

  classmethod `from_values`(file, start_line=None, start_column=None, end_line=None, end_column=None)
  `overlaps`(other)
  `renamed_file`(file_diff_dict: dict)

    Retrieves the filename this source range refers to while taking the possible file renamings in the given file_diff_dict into account:

    Parameters: | file_diff_dict – A dictionary with filenames as key and their associated Diff objects as values.

## coalib.results.TextPosition module

class `coalib.results.TextPosition.` `TextPosition`(line: (<class 'int'>, None) = None, column: (<class 'int'>, None) = None)

  Bases: `object`

  `column`
  `line`

## coalib.results.TextRange module

class `coalib.results.TextRange.` `TextRange`(start: coalib.results.TextPosition.TextPosition, end: (<class 'coalib.results.TextPosition.TextPosition'>, None) = None)

  Bases: `object`

  `end`
  `expand`(text_lines)

    Passes a new TextRange that covers the same area of a file as this one would. All values of None get replaced with absolute values.

    values of None will be interpreted as follows: self.start.line is None: -> 1 self.start.column is None: -> 1 self.end.line is None: -> last line of file self.end.column is None: -> last column of self.end.line

    Parameters: | text_lines – File contents of the applicable file
    Returns: | TextRange with absolute values

  classmethod `from_values`(start_line=None, start_column=None, end_line=None, end_column=None)

    Creates a new TextRange.

    Parameters: | start_line – The line number of the start position. The first line is 1. start_column – The column number of the start position. The first column is 1. end_line – The line number of the end position. If this parameter is `None`, then the end position is set the same like start position and end_column gets ignored. end_column – The column number of the end position.
    Returns: | A TextRange.

  classmethod `join`(a, b)

    Creates a new TextRange that covers the area of two overlapping ones

    Parameters: | a – TextRange (needs to overlap b) b – TextRange (needs to overlap a)
    Returns: | A new TextRange covering the union of the Area of a and b

  `overlaps`(other)
  `start`

## Module contents