Coverage for tests/helpers.py: 38%

58 statements  

« prev     ^ index     » next       coverage.py v7.8.2, created at 2025-06-06 13:57 +0200

1from __future__ import annotations 

2 

3import os 

4import textwrap 

5from pathlib import Path 

6 

7 

8def create_empty_file(filename: str | Path, create_folder: bool = False): 

9 """ 

10 A function and context manager to create an empty file with the given 

11 filename. When used as a function, the file needs to be removed explicitly 

12 with a call to `filename.unlink()` or `os.unlink(filename)`. 

13 

14 This function can be called as a context manager in which case the file will 

15 be removed when the context ends. 

16 

17 Returns: 

18 The filename as a Path. 

19 """ 

20 

21 class _ContextManager: 

22 def __init__(self, filename: str | Path, create_folder: bool): 

23 self.filename = Path(filename) 

24 

25 if self.filename.exists(): 

26 raise FileExistsError(f"The empty file you wanted to create already exists: {filename}") 

27 

28 if create_folder and not self.filename.parent.exists(): 

29 self.filename.parent.mkdir(parents=True) 

30 

31 with self.filename.open(mode="w"): 

32 pass 

33 

34 def __enter__(self): 

35 return self.filename 

36 

37 def __exit__(self, exc_type, exc_val, exc_tb): 

38 self.filename.unlink() 

39 

40 return _ContextManager(filename, create_folder) 

41 

42 

43def create_text_file(filename: str | Path, content: str, create_folder: bool = False): 

44 """ 

45 A function and context manager to create a text file with the given string 

46 as content. When used as a function, the file needs to be removed explicitly 

47 with a call to `filename.unlink()` or `os.unlink(filename)`. 

48 

49 This function can be called as a context manager in which case the file will 

50 be removed when the context ends. 

51 

52 >> with create_text_file("samples.txt", "A,B,C\n1,2,3\n4,5,6\n"): 

53 .. # do something with the file or its content 

54 

55 Returns: 

56 The filename as a Path. 

57 """ 

58 

59 class _ContextManager: 

60 def __init__(self, filename: str | Path, create_folder: bool): 

61 self.filename = Path(filename) 

62 

63 if self.filename.exists(): 63 ↛ 64line 63 didn't jump to line 64 because the condition on line 63 was never true

64 raise FileExistsError(f"The text file you wanted to create already exists: {filename}") 

65 

66 if create_folder and not self.filename.parent.exists(): 66 ↛ 67line 66 didn't jump to line 67 because the condition on line 66 was never true

67 self.filename.parent.mkdir(parents=True) 

68 

69 with self.filename.open(mode="w") as fd: 

70 fd.write(content) 

71 

72 def __enter__(self): 

73 return self.filename 

74 

75 def __exit__(self, exc_type, exc_val, exc_tb): 

76 self.filename.unlink() 

77 

78 return _ContextManager(filename, create_folder) 

79 

80 

81CSV_TEST_DATA = """\ 

82employee_id,first_name,last_name,department,position,salary,hire_date,is_active,email 

83# a comment line 

841001,John,Smith,Engineering,Software Engineer,75000,2022-03-15,TRUE,john.smith@company.com 

851002,Sarah,Johnson,Marketing,Marketing Manager,68000,2021-07-22,TRUE,sarah.johnson@company.com 

861003,Michael,Brown,Sales,Sales Representative,55000,2023-01-10,TRUE,michael.brown@company.com 

871004,Emily,Davis,Engineering,Senior Developer,85000,2020-11-05,TRUE,emily.davis@company.com 

881005,David,Wilson,HR,HR Specialist,62000,2022-09-18,TRUE,david.wilson@company.com 

891006,Lisa,Anderson,Finance,Financial Analyst,70000,2021-04-12,TRUE,lisa.anderson@company.com 

901007,Robert,Taylor,Engineering,DevOps Engineer,78000,2022-12-03,TRUE,robert.taylor@company.com 

911008,Jennifer,Thomas,Marketing,Content Creator,52000,2023-05-20,TRUE,jennifer.thomas@company.com 

921009,William,Jackson,Sales,Sales Manager,72000,2020-08-14,TRUE,william.jackson@company.com 

931010,Jessica,White,IT,System Administrator,65000,2021-10-30,FALSE,jessica.white@company.com 

941011,Christopher,Harris,Engineering,Junior Developer,58000,2023-08-07,TRUE,christopher.harris@company.com 

951012,Amanda,Martin,Finance,Accountant,61000,2022-02-28,TRUE,amanda.martin@company.com 

961013,James,Thompson,Sales,Sales Representative,54000,2023-03-16,TRUE,james.thompson@company.com 

971014,Michelle,Garcia,HR,Recruiter,59000,2021-12-08,TRUE,michelle.garcia@company.com 

981015,Daniel,Rodriguez,IT,Network Engineer,73000,2020-06-25,TRUE,daniel.rodriguez@company.com 

99""" 

100 

101 

102def create_test_csv_file(filename: str | Path, create_folder: bool = False): 

103 """ 

104 This file includes 15 employees with various data types that are useful for testing: 

105 

106 - Employee IDs (integers) 

107 - Names (text strings) 

108 - Departments (Engineering, Marketing, Sales, HR, Finance, IT) 

109 - Salaries (numeric values) 

110 - Hire dates (date format) 

111 - Active status (boolean TRUE/FALSE) 

112 - Email addresses (text with special characters) 

113 

114 The data includes different scenarios like active/inactive employees, various salary ranges, 

115 and different departments, making it great for testing data filtering, sorting, analysis, 

116 and visualization. 

117 

118 """ 

119 return create_text_file(filename, CSV_TEST_DATA, create_folder) 

120 

121 

122# Test the helper functions 

123 

124 

125def main(): 

126 print(f"cwd = {os.getcwd()}") 

127 

128 fn = Path("xxx.txt") 

129 

130 with create_empty_file(fn): 

131 assert fn.exists() 

132 assert not fn.exists() 

133 

134 create_empty_file(fn) 

135 assert fn.exists() 

136 fn.unlink() 

137 assert not fn.exists() 

138 

139 # Test the create_a_text_file() helper function 

140 

141 with create_text_file( 

142 fn, 

143 textwrap.dedent( 

144 """\ 

145 A,B,C,D 

146 1,2,3,4 

147 5,6,7,8 

148 """ 

149 ), 

150 ) as filename: 

151 assert fn.exists() 

152 assert filename == fn 

153 

154 print(fn.read_text()) 

155 

156 assert not fn.exists() 

157 

158 fn = Path("data/xxx.txt") 

159 

160 with create_empty_file(fn, create_folder=True): 

161 assert fn.exists() 

162 

163 assert not fn.exists() 

164 

165 

166if __name__ == "__main__": 166 ↛ 167line 166 didn't jump to line 167 because the condition on line 166 was never true

167 main()