From c529904e36f86069588ab8abc7119cb82b8f4e6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Walson=20Low=20=EF=BC=88=E5=88=98=E7=BB=B4=E6=98=87?= =?UTF-8?q?=EF=BC=89?= Date: Thu, 16 Oct 2025 14:20:27 +0800 Subject: [PATCH] Add option to prepend line numbers to Line --- unidiff/patch.py | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/unidiff/patch.py b/unidiff/patch.py index bfe80e4..e5d324a 100644 --- a/unidiff/patch.py +++ b/unidiff/patch.py @@ -101,6 +101,11 @@ def is_removed(self) -> bool: def is_context(self) -> bool: return self.line_type == LINE_TYPE_CONTEXT + def prepend_line_number(self) -> str: + if self.target_line_no or self.source_line_no: + return "%d %s%s" % (self.target_line_no or self.source_line_no, self.line_type, self.value) + return str(self) + class PatchInfo(list): """Lines with extended patch info. @@ -151,13 +156,19 @@ def __repr__(self) -> str: return str(value) def __str__(self) -> str: + content = ''.join(str(line) for line in self) + return self.head + content + + @property + def head(self) -> str: # section header is optional and thus we output it only if it's present - head = "@@ -%d,%d +%d,%d @@%s\n" % ( + return "@@ -%d,%d +%d,%d @@%s\n" % ( self.source_start, self.source_length, self.target_start, self.target_length, ' ' + self.section_header if self.section_header else '') - content = ''.join(str(line) for line in self) - return head + content + + def prepend_line_number(self) -> str: + return self.head + ''.join(line.prepend_line_number() for line in self) def append(self, line: Line) -> None: """Append the line to hunk, and keep track of source/target lines.""" @@ -215,6 +226,7 @@ def __init__( source_timestamp: Optional[str] = None, target_timestamp: Optional[str] = None, is_binary_file: bool = False, + prepend_line_number: bool = False ) -> None: super(PatchedFile, self).__init__() self.patch_info = patch_info @@ -223,6 +235,7 @@ def __init__( self.target_file = target self.target_timestamp = target_timestamp self.is_binary_file = is_binary_file + self.prepend_line_number = prepend_line_number def __repr__(self) -> str: return str("") % str(self.path) @@ -239,7 +252,7 @@ def __str__(self) -> str: target = "+++ %s%s\n" % ( self.target_file, '\t' + self.target_timestamp if self.target_timestamp else '') - hunks = ''.join(str(hunk) for hunk in self) + hunks = ''.join(hunk.prepend_line_number() if self.prepend_line_number else str(hunk) for hunk in self) return info + source + target + hunks def _parse_hunk( @@ -435,7 +448,8 @@ def __init__( self, f: Union[StringIO, str], encoding: Optional[str] = None, - metadata_only: bool = False + metadata_only: bool = False, + prepend_line_number: bool = False ) -> None: super(PatchSet, self).__init__() @@ -453,6 +467,7 @@ def __init__( data, # type: ignore encoding=encoding, metadata_only=metadata_only, + prepend_line_number=prepend_line_number ) def __repr__(self) -> str: @@ -466,6 +481,7 @@ def _parse( diff: Iterator[str], encoding: Optional[str], metadata_only: bool, + prepend_line_number: bool, ) -> None: current_file = None patch_info = None @@ -484,7 +500,7 @@ def _parse( source_file = is_diff_git_header.group('source') target_file = is_diff_git_header.group('target') current_file = PatchedFile( - patch_info, source_file, target_file, None, None) + patch_info, source_file, target_file, None, None, prepend_line_number=prepend_line_number) self.append(current_file) patch_info.append(line) continue