comparison shasum.py @ 21:f2d634270e1c

Refactor: parse a line of a digest file within a dedicated funcion
author Franz Glasner <fzglas.hg@dom66.de>
date Sat, 05 Dec 2020 13:32:00 +0100
parents 8f0241ed4a00
children 6bdfc5ad4656
comparison
equal deleted inserted replaced
20:8f0241ed4a00 21:f2d634270e1c
136 :return: a tuple with static "ok", "missing", or "failed", the filename and 136 :return: a tuple with static "ok", "missing", or "failed", the filename and
137 the digest used 137 the digest used
138 :rtype: tuple(str, str, str) 138 :rtype: tuple(str, str, str)
139 139
140 """ 140 """
141 # determine checkfile format (BSD or coreutils) 141 parts = parse_digest_line(opts, line)
142 # BSD? 142 if not parts:
143 mo = re.search(r"\A(\S+)\s*\((.*)\)\s*=\s*(.+)\n?\Z", line) 143 raise ValueError(
144 if mo: 144 "improperly formatted digest line: {}".format(line))
145 tag = mo.group(1) 145 tag, algo, fn, digest = parts
146 algo = algotag2algotype(tag)
147 fn = mo.group(2)
148 digest = mo.group(3)
149 else:
150 mo = re.search(r"([^\ ]+) [\*\ ]?(.+)\n?\Z", line)
151 if mo:
152 tag = opts.algorithm[1]
153 algo = opts.algorithm[0]
154 fn = mo.group(2)
155 digest = mo.group(1)
156 else:
157 raise ValueError(
158 "improperly formatted digest line: {}".format(line))
159 try: 146 try:
160 with open(fn, "rb") as input: 147 with open(fn, "rb") as input:
161 d = compute_digest(algo, input) 148 d = compute_digest(algo, input)
162 if d.lower() == digest.lower(): 149 if d.lower() == digest.lower():
163 return ("ok", fn, tag) 150 return ("ok", fn, tag)
164 else: 151 else:
165 return ("failed", fn, tag) 152 return ("failed", fn, tag)
166 except EnvironmentError: 153 except EnvironmentError:
167 return ("missing", fn, tag) 154 return ("missing", fn, tag)
155
156
157 def parse_digest_line(opts, line):
158 """Parse a `line` of a digest file and return its parts.
159
160 :return: a tuple of the normalized algorithm tag, the algorithm
161 constructor, the filename and the hex digest;
162 if `line` cannot be parsed successfully `None` is returned
163 :rtype: tuple(str, obj, str, str) or None
164
165 Handles coreutils and BSD-style file formats.
166
167 """
168 # determine checkfile format (BSD or coreutils)
169 # BSD?
170 mo = re.search(r"\A(\S+)\s*\((.*)\)\s*=\s*(.+)\n?\Z", line)
171 if mo:
172 # (tag, algorithm, filename, digest)
173 return (mo.group(1),
174 algotag2algotype(mo.group(1)),
175 mo.group(2),
176 mo.group(3))
177 else:
178 # coreutils?
179 mo = re.search(r"([^\ ]+) [\*\ ]?(.+)\n?\Z", line)
180 if mo:
181 # (tag, algorithm, filename, digest)
182 return (opts.algorithm[1],
183 opts.algorithm[0],
184 mo.group(2),
185 mo.group(1))
186 else:
187 return None
168 188
169 189
170 def argv2algo(s): 190 def argv2algo(s):
171 """Convert a commane line algorithm specifier into a tuple with the 191 """Convert a commane line algorithm specifier into a tuple with the
172 type/factory of the digest and the algorithms tag for output purposes. 192 type/factory of the digest and the algorithms tag for output purposes.