Coverage for cogapp/utils.py: 76.74%
37 statements
« prev ^ index » next coverage.py v7.6.9, created at 2024-12-06 06:21 -0500
« prev ^ index » next coverage.py v7.6.9, created at 2024-12-06 06:21 -0500
1"""Utilities for cog."""
3import contextlib
4import functools
5import hashlib
6import os
7import sys
10# Support FIPS mode where possible (Python >= 3.9). We don't use MD5 for security.
11md5 = (
12 functools.partial(hashlib.md5, usedforsecurity=False)
13 if sys.version_info >= (3, 9)
14 else hashlib.md5
15)
18class Redirectable:
19 """An object with its own stdout and stderr files."""
21 def __init__(self):
22 self.stdout = sys.stdout
23 self.stderr = sys.stderr
25 def set_output(self, stdout=None, stderr=None):
26 """Assign new files for standard out and/or standard error."""
27 if stdout: 27 ↛ 29line 27 didn't jump to line 29 because the condition on line 27 was always true
28 self.stdout = stdout
29 if stderr: 29 ↛ 30line 29 didn't jump to line 30 because the condition on line 29 was never true
30 self.stderr = stderr
32 def prout(self, s, end="\n"):
33 print(s, file=self.stdout, end=end)
35 def prerr(self, s, end="\n"):
36 print(s, file=self.stderr, end=end)
39class NumberedFileReader:
40 """A decorator for files that counts the readline()'s called."""
42 def __init__(self, f):
43 self.f = f
44 self.n = 0
46 def readline(self):
47 line = self.f.readline()
48 if line:
49 self.n += 1
50 return line
52 def linenumber(self):
53 return self.n
56@contextlib.contextmanager
57def change_dir(new_dir):
58 """Change directory, and then change back.
60 Use as a context manager, it will return to the original
61 directory at the end of the block.
63 """
64 old_dir = os.getcwd()
65 os.chdir(str(new_dir))
66 try:
67 yield
68 finally:
69 os.chdir(old_dir)