1313args = parser .parse_args ();
1414
1515# cat returns different error messages depending on the reason the path could be read
16- def cat_file (path ):
16+ def read_file (path ):
17+ """Returns (content, error_message). error_message is None on success"""
1718 try :
1819 with open (path , "r" ,) as f :
19- content = f .read ()
20+ return f .read (), None
2021 except FileNotFoundError :
21- print (f"cat: { path } : No such file or directory" , file = sys .stderr )
22- return False
22+ return None , f"cat: { path } : No such file or directory"
2323 except IsADirectoryError :
24- print (f"cat: { path } : Is a directory" , file = sys .stderr )
25- return False
24+ return None , f"cat: { path } : Is a directory"
2625 except PermissionError :
27- print (f"cat: { path } : Permission denied" , file = sys .stderr )
28- return False
26+ return None , f"cat: { path } : Permission denied"
2927
30- print (content )
3128
29+ # -b (number the non-empty lines) takes priority over -n (number all lines)
30+ # if both are present
31+ def format_lines (lines , number_all = False , number_non_empty = False ):
32+ """Returns a list of formatted output lines"""
33+ output = []
34+
35+ if number_non_empty :
36+ line_num = 0
37+ for line in lines :
38+ if line == "" :
39+ output .append ("" )
40+ else :
41+ line_num += 1
42+ # {line_num:6} right justied number, length of at least 6
43+ # {some_str:6} left justifed string, length fo at least 6
44+ output .append (f"{ line_num :6} \t { line } " )
45+ elif number_all :
46+ for i , line in enumerate (lines , start = 1 ):
47+ output .append (f"{ i :6} \t { line } " )
48+ else :
49+ output = lines
3250
3351
34- # cat exits with error code 1 if any file read fails
35- file_error = False
52+ # TODO: runner function to call read_file, and feed it into formatLines, then print
3653
37- for path in args . paths :
38- line_num = 1
39- is_success = cat_file ( path )
54+ def main () :
55+ # cat exits with error code 1 if any file read fails
56+ file_error = False
4057
41- if not is_success :
42- file_error = True
58+ for path in args .paths :
59+ line_num = 1
60+ is_success = cat_file (path )
4361
44- # if at any point, file reading failed file error is set to True,
45- # and program exist with code 1 after all tasks completed
46- sys .exit (1 if file_error else 0 )
62+ if not is_success :
63+ file_error = True
64+
65+ # if at any point, file reading failed file error is set to True,
66+ # and program exist with code 1 after all tasks completed
67+ sys .exit (1 if file_error else 0 )
68+
69+ # ensures that main only runs when this file/module is directly executed
70+ # not when it is imported, for example, for automated tests
71+ if __name__ == "__main__" :
72+ main ()
0 commit comments