182 return bool(b) |
180 return bool(b) |
183 |
181 |
184 |
182 |
185 def join_regex(regexes): |
183 def join_regex(regexes): |
186 """Combine a list of regexes into one that matches any of them.""" |
184 """Combine a list of regexes into one that matches any of them.""" |
187 return "|".join("(?:%s)" % r for r in regexes) |
185 return "|".join(f"(?:{r})" for r in regexes) |
188 |
186 |
189 |
187 |
190 def file_be_gone(path): |
188 def file_be_gone(path): |
191 """Remove a file, and don't get annoyed if it doesn't exist.""" |
189 """Remove a file, and don't get annoyed if it doesn't exist.""" |
192 try: |
190 try: |
218 getattr(outfile, "encoding", None) or |
216 getattr(outfile, "encoding", None) or |
219 getattr(sys.__stdout__, "encoding", None) or |
217 getattr(sys.__stdout__, "encoding", None) or |
220 locale.getpreferredencoding() |
218 locale.getpreferredencoding() |
221 ) |
219 ) |
222 return encoding |
220 return encoding |
223 |
|
224 |
|
225 def filename_suffix(suffix): |
|
226 """Compute a filename suffix for a data file. |
|
227 |
|
228 If `suffix` is a string or None, simply return it. If `suffix` is True, |
|
229 then build a suffix incorporating the hostname, process id, and a random |
|
230 number. |
|
231 |
|
232 Returns a string or None. |
|
233 |
|
234 """ |
|
235 if suffix is True: |
|
236 # If data_suffix was a simple true value, then make a suffix with |
|
237 # plenty of distinguishing information. We do this here in |
|
238 # `save()` at the last minute so that the pid will be correct even |
|
239 # if the process forks. |
|
240 dice = random.Random(os.urandom(8)).randint(0, 999999) |
|
241 suffix = "%s.%s.%06d" % (socket.gethostname(), os.getpid(), dice) |
|
242 return suffix |
|
243 |
221 |
244 |
222 |
245 class Hasher: |
223 class Hasher: |
246 """Hashes Python data for fingerprinting.""" |
224 """Hashes Python data for fingerprinting.""" |
247 def __init__(self): |
225 def __init__(self): |
413 """Sort the (string, value) items the way humans expect. |
391 """Sort the (string, value) items the way humans expect. |
414 |
392 |
415 Returns the sorted list of items. |
393 Returns the sorted list of items. |
416 """ |
394 """ |
417 return sorted(items, key=lambda pair: (human_key(pair[0]), pair[1]), reverse=reverse) |
395 return sorted(items, key=lambda pair: (human_key(pair[0]), pair[1]), reverse=reverse) |
|
396 |
|
397 |
|
398 def plural(n, thing="", things=""): |
|
399 """Pluralize a word. |
|
400 |
|
401 If n is 1, return thing. Otherwise return things, or thing+s. |
|
402 """ |
|
403 if n == 1: |
|
404 return thing |
|
405 else: |
|
406 return things or (thing + "s") |