1 """This module provides classes to deal with
2 unimportant difference in diff result.
12 Configuration defining unimportant difference
16 def load(cls, filename):
17 "Load config from file"
18 with open(filename) as reader:
20 txt.replace(os.linesep, '')
21 data = json.loads(txt)
29 def __init__(self, conf):
30 self._rules = self._compile(conf)
32 def check_and_mark(self, item):
33 """Check if there are unimportant differences in item.
36 for matcher, rule in self._rules:
37 if matcher(item['filename']):
43 """Compile config item to matching rules
45 def new_matcher(pattern):
46 """Supported file name pattern like:
53 if pattern.endswith(os.path.sep): # direcotry name
54 pattern = pattern + '*'
56 bname = os.path.basename(pattern)
57 if bname == pattern: # only basename, ignore dirname
58 def matcher(filename):
60 return fnmatch.fnmatch(os.path.basename(filename), pattern)
62 def matcher(filename):
64 return fnmatch.fnmatch(filename, pattern)
66 matcher.__docstring__ = 'Match filename with pattern %s' % pattern
70 for pat in conf.get('ignoreFiles', []):
71 matcher = new_matcher(pat)
72 rules.append((matcher, ignore_file))
74 for entry in conf.get('ignoreLines', []):
75 files = entry['Files']
76 lines = entry['Lines']
77 if isinstance(files, basestring):
79 if isinstance(lines, basestring):
81 ignore = IgnoreLines(lines)
83 matcher = new_matcher(pat)
84 rules.append((matcher, ignore))
89 def ignore_file(onefile):
90 """Mark whole file as trivial difference
92 onefile['ignore'] = True
95 class IgnoreLines(object):
96 """Mark certain lines in a file as trivial
97 differences according to given patterns
99 def __init__(self, patterns):
100 self.patterns = [re.compile(p) for p in patterns]
102 def is_unimportant(self, line):
103 "Is this line trivial"
104 for pat in self.patterns:
105 if pat.match(line['text']):
108 def __call__(self, onefile):
109 "Mark lines as trivial"
110 if onefile['type'] != 'onefilediff':
113 def should_ignore(line):
114 "Is this line trivial"
115 if line['type'] in ('insert', 'delete'):
116 return self.is_unimportant(line)
117 # else: context, no_newline_at_eof
121 for section in onefile['sections']:
122 for line in section['hunks']:
123 line['ignore'] = should_ignore(line)
124 all_ignored = all_ignored and line['ignore']
126 # if all lines are unimportant then the whole file is unimportant
128 onefile['ignore'] = True