1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 """
17 Differ classes
18 """
19 __author__ = "André Malo"
20 __docformat__ = "epytext en"
21 __all__ = ["InternalDiffer", "ExternalDiffer"]
22
23
25 """ Differ without an external program call (uses difflib) """
26
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
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
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
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
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