Package svnmailer :: Module differ
[hide private]

Source Code for Module svnmailer.differ

  1  # -*- coding: utf-8 -*- 
  2  # 
  3  # Copyright 2004-2006 André Malo or his licensors, as applicable 
  4  # 
  5  # Licensed under the Apache License, Version 2.0 (the "License"); 
  6  # you may not use this file except in compliance with the License. 
  7  # You may obtain a copy of the License at 
  8  # 
  9  #     http://www.apache.org/licenses/LICENSE-2.0 
 10  # 
 11  # Unless required by applicable law or agreed to in writing, software 
 12  # distributed under the License is distributed on an "AS IS" BASIS, 
 13  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 14  # See the License for the specific language governing permissions and 
 15  # limitations under the License. 
 16  """ 
 17  Differ classes 
 18  """ 
 19  __author__    = "André Malo" 
 20  __docformat__ = "epytext en" 
 21  __all__       = ["InternalDiffer", "ExternalDiffer"] 
 22   
 23   
24 -class InternalDiffer(object):
25 """ Differ without an external program call (uses difflib) """ 26
27 - def __init__(self):
28 """ Initialization """ 29 pass
30 31
32 - def getStringDiff(self, string1, string2, label1, label2 = None, 33 date1 = "", date2 = ""):
34 """ creates a diff of two line based strings 35 36 If a string is C{None}, it's treated as "" 37 38 @param string1: First string 39 @type string1: C{str} 40 41 @param string2: Second string 42 @type string2: C{str} 43 44 @param label1: Label for first data 45 @type label1: C{str} 46 47 @param label2: Label for second data 48 @type label2: C{str} 49 50 @param date1: Date description for first data 51 @type date1: C{str} 52 53 @param date2: Date description for second data 54 @type date2: C{str} 55 56 @return: unified diff lines (maybe a generator) 57 @rtype: iterable 58 """ 59 import difflib 60 61 list1 = (string1 or "").splitlines(True) 62 list2 = (string2 or "").splitlines(True) 63 if not (list1 or list2): 64 list1 = list2 = [""] 65 66 return difflib.unified_diff( 67 list1, list2, label1, label2 or label1, date1, date2, 68 )
69 70
71 - def getFileDiff(self, name1, name2, label1, label2 = None, 72 date1 = "", date2 = ""):
73 """ creates a diff of two line based files 74 75 @param name1: First file name 76 @type name1: C{str} 77 78 @param name2: Second file name 79 @type name2: C{str} 80 81 @param label1: Label for first data 82 @type label1: C{str} 83 84 @param label2: Label for second data 85 @type label2: C{str} 86 87 @param date1: Date description for first data 88 @type date1: C{str} 89 90 @param date2: Date description for second data 91 @type date2: C{str} 92 93 @return: unified diff lines (maybe a generator) 94 @rtype: iterable 95 """ 96 import difflib 97 98 list1 = file(name1, "rb").readlines() 99 list2 = file(name2, "rb").readlines() 100 if not (list1 or list2): 101 list1 = list2 = [""] 102 103 return difflib.unified_diff( 104 list1, list2, label1, label2 or label1, date1, date2, 105 )
106 107
108 -class ExternalDiffer(object):
109 """ Differ which calls an external program (e.g. diff) 110 111 @ivar _diff_command: The diff command line 112 @type _diff_command: C{list} 113 114 @ivar _tempdir: The tempdir to use for string diffs 115 @type _tempdir: C{str} 116 """ 117
118 - def __init__(self, diff_command, tempdir = None):
119 """ Initialization 120 121 @param diff_command: The diff command to call 122 @type diff_command: C{list} 123 124 @param tempdir: The tempdir to use for string diffs 125 @type tempdir: C{str} 126 """ 127 self._diff_command = diff_command 128 self._tempdir = tempdir
129 130
131 - def getStringDiff(self, string1, string2, label1, label2 = None, 132 date1 = "", date2 = ""):
133 """ creates a diff of two line based strings 134 135 If a string is C{None}, it's treated as "" 136 137 @param string1: First string 138 @type string1: C{str} 139 140 @param string2: Second string 141 @type string2: C{str} 142 143 @param label1: Label for first data 144 @type label1: C{str} 145 146 @param label2: Label for second data 147 @type label2: C{str} 148 149 @param date1: Date description for first data 150 @type date1: C{str} 151 152 @param date2: Date description for second data 153 @type date2: C{str} 154 155 @return: unified diff lines (maybe a generator) 156 @rtype: iterable 157 """ 158 from svnmailer import util 159 160 string1 = string1 or "" 161 string2 = string2 or "" 162 163 file1 = util.TempFile(self._tempdir) 164 file1.fp.write(string1) 165 file1.close() 166 167 file2 = util.TempFile(self._tempdir) 168 file2.fp.write(string2) 169 file2.close() 170 171 pipe = self._getPipe( 172 file1.name, file2.name, label1, label2, date1, date2 173 ) 174 175 # yield line by line 176 line = pipe.fromchild.readline() 177 while line: 178 yield line 179 line = pipe.fromchild.readline() 180 181 pipe.fromchild.close() 182 pipe.wait()
183 184
185 - def getFileDiff(self, name1, name2, label1, label2 = None, 186 date1 = "", date2 = ""):
187 """ creates a diff of two line based files 188 189 @param name1: First file name 190 @type name1: C{str} 191 192 @param name2: Second file name 193 @type name2: C{str} 194 195 @param label1: Label for first data 196 @type label1: C{str} 197 198 @param label2: Label for second data 199 @type label2: C{str} 200 201 @param date1: Date description for first data 202 @type date1: C{str} 203 204 @param date2: Date description for second data 205 @type date2: C{str} 206 207 @return: unified diff lines (maybe a generator) 208 @rtype: iterable 209 """ 210 pipe = self._getPipe(name1, name2, label1, label2, date1, date2) 211 212 # yield line by line 213 line = pipe.fromchild.readline() 214 while line: 215 yield line 216 line = pipe.fromchild.readline() 217 218 pipe.fromchild.close() 219 pipe.wait()
220 221
222 - def _getPipe(self, name1, name2, label1, label2, date1, date2):
223 """ Returns a pipe from the diff program 224 225 @param name1: First file name 226 @type name1: C{str} 227 228 @param name2: Second file name 229 @type name2: C{str} 230 231 @param label1: Label for first data 232 @type label1: C{str} 233 234 @param label2: Label for second data 235 @type label2: C{str} 236 237 @param date1: Date description for first data 238 @type date1: C{str} 239 240 @param date2: Date description for second data 241 @type date2: C{str} 242 243 @return: The pipe object 244 @rtype: see: C{util.getPipe4} 245 """ 246 from svnmailer import util 247 248 params = { 249 "label_from": "%s %s" % (label1, date1 or ""), 250 "label_to" : "%s %s" % (label2 or label1, date2 or ""), 251 "from" : name1, 252 "to" : name2, 253 } 254 255 # check for sanity 256 for key, value in params.items(): 257 if isinstance(value, unicode): 258 params[key] = value.encode("utf-8") 259 260 cmd = list(self._diff_command) 261 cmd[1:] = [(isinstance(arg, unicode) and 262 [arg.encode("utf-8")] or [arg])[0] % params for arg in cmd[1:] 263 ] 264 265 pipe = util.getPipe4(cmd) 266 pipe.tochild.close() 267 268 return pipe
269