def get_file_dict(filename_list, log_printer, allow_raw_files=False): """ Reads all files into a dictionary. :param filename_list: List of names of paths to files to get contents of. :param log_printer: The logger which logs errors. :param allow_raw_files: Allow the usage of raw files (non text files), disabled by default :return: Reads the content of each file into a dictionary with filenames as keys. """ file_dict = {} for filename in filename_list: try: with open(filename, 'r', encoding=detect_encoding(filename)) as _file: file_dict[filename] = tuple(_file.readlines()) except UnicodeDecodeError: if allow_raw_files: file_dict[filename] = None continue log_printer.warn("Failed to read file '{}'. It seems to contain " 'non-unicode characters. Leaving it ' 'out.'.format(filename)) except OSError as exception: log_printer.log_exception("Failed to read file '{}' because of " 'an unknown error. Leaving it ' 'out.'.format(filename), exception, log_level=LOG_LEVEL.WARNING) log_printer.debug('Files that will be checked:\n' + '\n'.join(file_dict.keys())) return file_dict
def get_disk_contents(self): """ :return: Returns the contents of a copy of the file on the disk. It might not be in sync with the editor version of the file. """ with open(self.filename, 'r', encoding=detect_encoding(self.filename)) as disk: return disk.read()
def apply(self, result, original_file_dict, file_diff_dict, editor: str): """ (O)pen file :param editor: The editor to open the file with. """ try: editor_info = KNOWN_EDITORS[editor.strip()] except KeyError: # If the editor is unknown fall back to just passing # the filenames and emit a warning logging.warning( 'The editor "{editor}" is unknown to coala. Files won\'t be' ' opened at the correct positions and other quirks might' ' occur. Consider opening an issue at' ' https://github.com/coala/coala/issues so we' ' can add support for this editor.' ' Supported editors are: {supported}'.format( editor=editor, supported=', '.join( sorted(KNOWN_EDITORS.keys()) ) ) ) editor_info = { 'file_arg_template': '{filename}', 'gui': False } # Use dict to remove duplicates filenames = { src.file: { 'filename': src.renamed_file(file_diff_dict), 'line': src.start.line or 1, 'column': src.start.column or 1 } for src in result.affected_code } call_args = self.build_editor_call_args(editor, editor_info, filenames) if editor_info.get('gui', True): subprocess.call(call_args, stdout=subprocess.PIPE) else: subprocess.call(call_args) for original_name, file_info in filenames.items(): filename = file_info['filename'] with open(filename, encoding=detect_encoding(filename)) as file: file_diff_dict[original_name] = Diff.from_string_arrays( original_file_dict[original_name], file.readlines(), rename=False if original_name == filename else filename) return file_diff_dict
def apply(self, result, original_file_dict, file_diff_dict, no_orig: bool = False): """ (A)pply patch :param no_orig: Whether or not to create .orig backup files """ for filename in result.diffs: pre_patch_filename = filename if filename in file_diff_dict: diff = file_diff_dict[filename] pre_patch_filename = (diff.rename if diff.rename is not False else filename) file_diff_dict[filename] += result.diffs[filename] else: file_diff_dict[filename] = result.diffs[filename] # Backup original file, only if there was no previous patch # from this run though! if not no_orig and isfile(pre_patch_filename): shutil.copy2(pre_patch_filename, pre_patch_filename + '.orig') diff = file_diff_dict[filename] if not diff.delete: new_filename = (diff.rename if diff.rename is not False else filename) with open(new_filename, mode='w', encoding=detect_encoding(pre_patch_filename)) as file: file.writelines(diff.modified) if diff.delete or diff.rename: if diff.rename != pre_patch_filename and isfile( pre_patch_filename): remove(pre_patch_filename) return file_diff_dict
def apply(self, result, original_file_dict, file_diff_dict, no_orig: bool=False): """ (A)pply patch :param no_orig: Whether or not to create .orig backup files """ for filename in result.diffs: pre_patch_filename = filename if filename in file_diff_dict: diff = file_diff_dict[filename] pre_patch_filename = (diff.rename if diff.rename is not False else filename) file_diff_dict[filename] += result.diffs[filename] else: file_diff_dict[filename] = result.diffs[filename] # Backup original file, only if there was no previous patch # from this run though! if not no_orig and isfile(pre_patch_filename): shutil.copy2(pre_patch_filename, pre_patch_filename + '.orig') diff = file_diff_dict[filename] if not diff.delete: new_filename = (diff.rename if diff.rename is not False else filename) with open(new_filename, mode='w', encoding=detect_encoding(pre_patch_filename)) as file: file.writelines(diff.modified) if diff.delete or diff.rename: if diff.rename != pre_patch_filename and isfile( pre_patch_filename): remove(pre_patch_filename) return file_diff_dict
def apply(self, result, original_file_dict, file_diff_dict, language: str, no_orig: bool = False): """ Add (I)gnore comment """ ignore_comment = self.get_ignore_comment(result.origin, language) if not ignore_comment: return file_diff_dict source_range = next( filter(lambda sr: exists(sr.file), result.affected_code)) filename = source_range.file ignore_diff = Diff(original_file_dict[filename]) ignore_diff.change_line( source_range.start.line, original_file_dict[filename][source_range.start.line - 1], original_file_dict[filename][source_range.start.line - 1].rstrip() + ' ' + ignore_comment) if filename in file_diff_dict: ignore_diff = file_diff_dict[filename] + ignore_diff else: if not no_orig and isfile(filename): shutil.copy2(filename, filename + '.orig') file_diff_dict[filename] = ignore_diff new_filename = ignore_diff.rename if ignore_diff.rename else filename with open(new_filename, mode='w', encoding=detect_encoding(new_filename)) as file: file.writelines(ignore_diff.modified) return file_diff_dict
def from_file(cls, filename, workspace, binary=False): """ Construct a FileProxy instance from an existing file on the drive. :param filename: The name of the file to be represented by the proxy instance. :param workspace: The workspace the file belongs to. This can be none representing that the the directory server is currently serving from is the workspace. :return: Returns a FileProxy instance of the file with the content synced from a disk copy. """ if not binary: with open(filename, 'r', encoding=detect_encoding(filename)) as reader: return cls(filename, workspace, reader.read()) else: with open(filename, 'rb') as reader: return cls(filename, workspace, reader.read())
def apply(self, result, original_file_dict, file_diff_dict, language: str, no_orig: bool=False): """ Add (I)gnore comment """ ignore_comment = self.get_ignore_comment(result.origin, language) if not ignore_comment: return file_diff_dict source_range = next(filter(lambda sr: exists(sr.file), result.affected_code)) filename = source_range.file ignore_diff = Diff(original_file_dict[filename]) ignore_diff.change_line( source_range.start.line, original_file_dict[filename][source_range.start.line-1], original_file_dict[filename][source_range.start.line-1].rstrip() + ' ' + ignore_comment) if filename in file_diff_dict: ignore_diff = file_diff_dict[filename] + ignore_diff else: if not no_orig and isfile(filename): shutil.copy2(filename, filename + '.orig') file_diff_dict[filename] = ignore_diff new_filename = ignore_diff.rename if ignore_diff.rename else filename with open(new_filename, mode='w', encoding=detect_encoding(new_filename)) as file: file.writelines(ignore_diff.modified) return file_diff_dict