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