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