def coverage(self):
        """
        If there is a .coverage file available, this will attempt to form a DataFrame with that information in it, which
        will contain the columns:

         * filename
         * lines_covered
         * total_lines
         * coverage

        If it can't be found or parsed, an empty DataFrame of that form will be returned.

        :return: DataFrame
        """

        if not self.has_coverage():
            return DataFrame(columns=['filename', 'lines_covered', 'total_lines', 'coverage'])

        with open(self.git_dir + os.sep + '.coverage', 'r') as f:
            blob = f.read()
            blob = blob.split('!')[2]
            cov = json.loads(blob)

        ds = []
        for filename in cov['lines'].keys():
            idx = 0
            try:
                with open(filename, 'r') as f:
                    for idx, _ in enumerate(f):
                        pass
            except FileNotFoundError as e:
                if self.verbose:
                    warnings.warn('Could not find file %s for coverage' % (filename, ))

            num_lines = idx + 1

            try:
                short_filename = filename.split(self.git_dir + os.sep)[1]
                ds.append([short_filename, len(cov['lines'][filename]), num_lines])
            except IndexError as e:
                if self.verbose:
                    warnings.warn('Could not find file %s for coverage' % (filename, ))

        df = DataFrame(ds, columns=['filename', 'lines_covered', 'total_lines'])
        df['coverage'] = df['lines_covered'] / df['total_lines']

        return df