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

1"""Utilities for cog.""" 

2 

3import contextlib 

4import functools 

5import hashlib 

6import os 

7import sys 

8 

9 

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) 

16 

17 

18class Redirectable: 

19 """An object with its own stdout and stderr files.""" 

20 

21 def __init__(self): 

22 self.stdout = sys.stdout 

23 self.stderr = sys.stderr 

24 

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 

31 

32 def prout(self, s, end="\n"): 

33 print(s, file=self.stdout, end=end) 

34 

35 def prerr(self, s, end="\n"): 

36 print(s, file=self.stderr, end=end) 

37 

38 

39class NumberedFileReader: 

40 """A decorator for files that counts the readline()'s called.""" 

41 

42 def __init__(self, f): 

43 self.f = f 

44 self.n = 0 

45 

46 def readline(self): 

47 line = self.f.readline() 

48 if line: 

49 self.n += 1 

50 return line 

51 

52 def linenumber(self): 

53 return self.n 

54 

55 

56@contextlib.contextmanager 

57def change_dir(new_dir): 

58 """Change directory, and then change back. 

59 

60 Use as a context manager, it will return to the original 

61 directory at the end of the block. 

62 

63 """ 

64 old_dir = os.getcwd() 

65 os.chdir(str(new_dir)) 

66 try: 

67 yield 

68 finally: 

69 os.chdir(old_dir)