From 35faf3c7f781c6091987c6f0d2427d729ccb0f4e Mon Sep 17 00:00:00 2001 From: Chakradhar Palaparthi Date: Sun, 4 Oct 2020 12:17:32 +0530 Subject: [PATCH 1/7] Create file_utils.py Utility file helpful for file I/O in python3. Helps for plain text IO and JSON load and dump. --- other/file_utils.py | 129 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 other/file_utils.py diff --git a/other/file_utils.py b/other/file_utils.py new file mode 100644 index 000000000000..10ee76afca76 --- /dev/null +++ b/other/file_utils.py @@ -0,0 +1,129 @@ +import json +import sys + + +def touch_file(file_name): + try: + with open(file_name): + pass + except FileNotFoundError: + try: + with open(file_name, 'w'): + pass + except IOError as ioe: + print(ioe) + sys.stdout.flush() + print('Unable to create file {}'.format(file_name)) + sys.stdout.flush() + except IOError as ioe: + print(ioe) + sys.stdout.flush() + print('Unable to read file {}'.format(file_name)) + sys.stdout.flush() + + +def clear_file(file_name): + try: + with open(file_name, 'w'): + pass + except IOError as ioe: + print(ioe) + sys.stdout.flush() + print('Unable to create file {}'.format(file_name)) + sys.stdout.flush() + + +def dump_json_to_file(data, file_name): + touch_file(file_name) + with open(file_name, 'w') as write_file: + write_file.write(json.dumps(data, indent=4)) + write_file.write('\n') + + +def load_json_from_file(file_name): + touch_file(file_name) + with open(file_name) as readfile: + content = readfile.read() + if content == '': + content = str(dict()) + content = json.loads(content) + return content + + +def read_lines_strip_return(file_name, split=None, index=None): + try: + with open(file_name) as readfile: + lines = readfile.readlines() + res = list() + for line in lines: + line = line.strip() + if line != '': + if split is not None: + line = line.split(split) + if index is None: + res.append(line) + else: + res.append(line[index]) + else: + res.append(line) + return res + except FileNotFoundError: + return "FileNotFoundError: {0}".format(file_name) + except IOError as ioe: + print(ioe) + sys.stdout.flush() + print('Unable to read file {}'.format(file_name)) + sys.stdout.flush() + + +def read_file(file_name): + try: + with open(file_name) as readfile: + return readfile.read().strip() + except FileNotFoundError: + return "FileNotFoundError: {0}".format(file_name) + except IOError as ioe: + print(ioe) + sys.stdout.flush() + print('Unable to read file {}'.format(file_name)) + sys.stdout.flush() + + +def append_line_to_file(file_name, content): + touch_file(file_name) + with open(file_name, 'a') as append_file: + append_file.write(content + '\n') + + +def append_line_to_file_if_doesnt_exist(file_name, content): + touch_file(file_name) + lines = read_lines_strip_return(file_name) + if content not in lines: + with open(file_name, 'a') as append_file: + append_file.write(content + '\n') + + +def check_file_exists(file_name): + try: + with open(file_name): + pass + return True + except FileNotFoundError: + return False + except IOError as ioe: + print(ioe) + sys.stdout.flush() + print('Unable to read file {}'.format(file_name)) + sys.stdout.flush() + return False + + +def convert_int_to_dotted_str(number): + res = list() + for digit in str(number): + res.append(digit) + return '.'.join(res) + + +def convert_dotted_str_to_int(dotted_str): + return int(''.join(dotted_str.split('.'))) From 5d9f968ba4e09bd29a6fe50b7dcb0c61dc41ec70 Mon Sep 17 00:00:00 2001 From: Chakradhar Palaparthi Date: Sun, 4 Oct 2020 12:38:03 +0530 Subject: [PATCH 2/7] Update file_utils.py Updated to make it compatible with black --- other/file_utils.py | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/other/file_utils.py b/other/file_utils.py index 10ee76afca76..e774129c8eb9 100644 --- a/other/file_utils.py +++ b/other/file_utils.py @@ -8,43 +8,43 @@ def touch_file(file_name): pass except FileNotFoundError: try: - with open(file_name, 'w'): + with open(file_name, "w"): pass except IOError as ioe: print(ioe) sys.stdout.flush() - print('Unable to create file {}'.format(file_name)) + print("Unable to create file {}".format(file_name)) sys.stdout.flush() except IOError as ioe: print(ioe) sys.stdout.flush() - print('Unable to read file {}'.format(file_name)) + print("Unable to read file {}".format(file_name)) sys.stdout.flush() def clear_file(file_name): try: - with open(file_name, 'w'): + with open(file_name, "w"): pass except IOError as ioe: print(ioe) sys.stdout.flush() - print('Unable to create file {}'.format(file_name)) + print("Unable to create file {}".format(file_name)) sys.stdout.flush() def dump_json_to_file(data, file_name): touch_file(file_name) - with open(file_name, 'w') as write_file: + with open(file_name, "w") as write_file: write_file.write(json.dumps(data, indent=4)) - write_file.write('\n') + write_file.write("\n") def load_json_from_file(file_name): touch_file(file_name) with open(file_name) as readfile: content = readfile.read() - if content == '': + if content == "": content = str(dict()) content = json.loads(content) return content @@ -57,7 +57,7 @@ def read_lines_strip_return(file_name, split=None, index=None): res = list() for line in lines: line = line.strip() - if line != '': + if line != "": if split is not None: line = line.split(split) if index is None: @@ -72,7 +72,7 @@ def read_lines_strip_return(file_name, split=None, index=None): except IOError as ioe: print(ioe) sys.stdout.flush() - print('Unable to read file {}'.format(file_name)) + print("Unable to read file {}".format(file_name)) sys.stdout.flush() @@ -85,22 +85,22 @@ def read_file(file_name): except IOError as ioe: print(ioe) sys.stdout.flush() - print('Unable to read file {}'.format(file_name)) + print("Unable to read file {}".format(file_name)) sys.stdout.flush() def append_line_to_file(file_name, content): touch_file(file_name) - with open(file_name, 'a') as append_file: - append_file.write(content + '\n') + with open(file_name, "a") as append_file: + append_file.write(content + "\n") def append_line_to_file_if_doesnt_exist(file_name, content): touch_file(file_name) lines = read_lines_strip_return(file_name) if content not in lines: - with open(file_name, 'a') as append_file: - append_file.write(content + '\n') + with open(file_name, "a") as append_file: + append_file.write(content + "\n") def check_file_exists(file_name): @@ -113,7 +113,7 @@ def check_file_exists(file_name): except IOError as ioe: print(ioe) sys.stdout.flush() - print('Unable to read file {}'.format(file_name)) + print("Unable to read file {}".format(file_name)) sys.stdout.flush() return False @@ -122,8 +122,8 @@ def convert_int_to_dotted_str(number): res = list() for digit in str(number): res.append(digit) - return '.'.join(res) + return ".".join(res) def convert_dotted_str_to_int(dotted_str): - return int(''.join(dotted_str.split('.'))) + return int("".join(dotted_str.split("."))) From d15d4af00b3e254e2dd716790f8a2922409f0840 Mon Sep 17 00:00:00 2001 From: Chakradhar Palaparthi Date: Sun, 4 Oct 2020 12:58:37 +0530 Subject: [PATCH 3/7] Update other/file_utils.py Co-authored-by: Christian Clauss --- other/file_utils.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/other/file_utils.py b/other/file_utils.py index e774129c8eb9..55733c34929c 100644 --- a/other/file_utils.py +++ b/other/file_utils.py @@ -36,8 +36,7 @@ def clear_file(file_name): def dump_json_to_file(data, file_name): touch_file(file_name) with open(file_name, "w") as write_file: - write_file.write(json.dumps(data, indent=4)) - write_file.write("\n") + write_file.write(json.dumps(data, indent=4) + "\n") def load_json_from_file(file_name): From dc47da288b41f3fe66b8420eda6231c503c51712 Mon Sep 17 00:00:00 2001 From: Chakradhar Palaparthi Date: Sun, 4 Oct 2020 13:00:10 +0530 Subject: [PATCH 4/7] Update other/file_utils.py Co-authored-by: Christian Clauss --- other/file_utils.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/other/file_utils.py b/other/file_utils.py index 55733c34929c..cda65b02768d 100644 --- a/other/file_utils.py +++ b/other/file_utils.py @@ -42,11 +42,7 @@ def dump_json_to_file(data, file_name): def load_json_from_file(file_name): touch_file(file_name) with open(file_name) as readfile: - content = readfile.read() - if content == "": - content = str(dict()) - content = json.loads(content) - return content + return readfile.read() or str({}) def read_lines_strip_return(file_name, split=None, index=None): From 4078ae2c538a66b50293d5346676c672fadb3259 Mon Sep 17 00:00:00 2001 From: Chakradhar Palaparthi Date: Sun, 4 Oct 2020 13:39:30 +0530 Subject: [PATCH 5/7] Added type hints, docstrings and removed prints --- other/file_utils.py | 129 +++++++++++++++++++++++++++++--------------- 1 file changed, 86 insertions(+), 43 deletions(-) diff --git a/other/file_utils.py b/other/file_utils.py index cda65b02768d..76f59b6a39fd 100644 --- a/other/file_utils.py +++ b/other/file_utils.py @@ -2,7 +2,14 @@ import sys -def touch_file(file_name): +# A utility file for all basic plain text and JSON file IO + +def touch_file(file_name: str) -> None: + """ + Touch file: + Checks if the file file_name exist else tries to create it. + Similar to touch command on linux. + """ try: with open(file_name): pass @@ -11,41 +18,56 @@ def touch_file(file_name): with open(file_name, "w"): pass except IOError as ioe: - print(ioe) - sys.stdout.flush() - print("Unable to create file {}".format(file_name)) - sys.stdout.flush() + sys.exit("{}: Unable to create {}".format(ioe, file_name)) except IOError as ioe: - print(ioe) - sys.stdout.flush() - print("Unable to read file {}".format(file_name)) - sys.stdout.flush() + sys.exit("{}: Unable to read file {}".format(ioe, file_name)) -def clear_file(file_name): +def clear_file(file_name: str) -> None: + """ + Clear file: + A utility function to clear the contents of the file file_name + """ try: with open(file_name, "w"): pass except IOError as ioe: - print(ioe) - sys.stdout.flush() - print("Unable to create file {}".format(file_name)) - sys.stdout.flush() + sys.exit("{}: Unable to create file {}".format(ioe, file_name)) -def dump_json_to_file(data, file_name): +def dump_json_to_file(data: object, file_name: str) -> None: + """ + Dump JSON to file: + - Creates the file file_name if it doesn't exist already. + - Clears the content of the file file_name. + - Converts the data object into JSON format and dumps it into the file file_name. + """ touch_file(file_name) with open(file_name, "w") as write_file: write_file.write(json.dumps(data, indent=4) + "\n") -def load_json_from_file(file_name): +def load_json_from_file(file_name: str) -> str: + """ + Load JSON from file: + - Creates the file file_name if it doesn't exist already. + - Read the content of the file file_name. + - Converts the data inside the file_name into JSON format and returns it. + - Returns str representation of an empty dict if the file is empty. + """ touch_file(file_name) with open(file_name) as readfile: return readfile.read() or str({}) -def read_lines_strip_return(file_name, split=None, index=None): +def read_lines_strip_return(file_name: str, split: str = None, index: int = None) -> list: + """ + Read Lines from file: + - Read the content of the file file_name using readlines. + - If the parameter split is specified then each line is split using it. + - If the index is specified then after splitting the line corresponding index from the line is returned + - Returns list of lines from the file file_name matching the split and index conditions + """ try: with open(file_name) as readfile: lines = readfile.readlines() @@ -62,63 +84,84 @@ def read_lines_strip_return(file_name, split=None, index=None): else: res.append(line) return res - except FileNotFoundError: - return "FileNotFoundError: {0}".format(file_name) + except FileNotFoundError as fn_fe: + sys.exit("{}: {}".format(fn_fe, file_name)) except IOError as ioe: - print(ioe) - sys.stdout.flush() - print("Unable to read file {}".format(file_name)) - sys.stdout.flush() + sys.exit("{}: Unable to read file {}".format(ioe, file_name)) -def read_file(file_name): +def read_file(file_name: str) -> str: + """ + Read file: + - Read the content of the file file_name using read and returns it. + """ try: with open(file_name) as readfile: return readfile.read().strip() - except FileNotFoundError: - return "FileNotFoundError: {0}".format(file_name) + except FileNotFoundError as fn_fe: + sys.exit("{}: {}".format(fn_fe, file_name)) except IOError as ioe: - print(ioe) - sys.stdout.flush() - print("Unable to read file {}".format(file_name)) - sys.stdout.flush() + sys.exit("{}: Unable to read file {}".format(ioe, file_name)) -def append_line_to_file(file_name, content): +def append_line_to_file(file_name: str, line: str) -> None: + """ + Append Line to file: + - Checks if the file exists and creates if not. + - Opens the file in append mode and appends the line at the ending of file file_name. + """ touch_file(file_name) with open(file_name, "a") as append_file: - append_file.write(content + "\n") + append_file.write(line + "\n") -def append_line_to_file_if_doesnt_exist(file_name, content): +def append_line_to_file_if_doesnt_exist(file_name: str, line: str) -> None: + """ + Append Line to file only if not exists: + - Checks if the file exists and creates if not. + - Checks if the line already exists in the file file_name. + - Only appends the line if nor already present in file_name. + """ touch_file(file_name) lines = read_lines_strip_return(file_name) - if content not in lines: + if line not in lines: with open(file_name, "a") as append_file: - append_file.write(content + "\n") + append_file.write(line + "\n") -def check_file_exists(file_name): +def check_file_exists(file_name: str) -> bool: + """ + Check if file exists: + - Checks whether the file file_name exists or not. + """ try: with open(file_name): pass return True except FileNotFoundError: return False - except IOError as ioe: - print(ioe) - sys.stdout.flush() - print("Unable to read file {}".format(file_name)) - sys.stdout.flush() + except IOError: return False -def convert_int_to_dotted_str(number): +def convert_int_to_dotted_str(number: int) -> str: + """ + Convert int into dotted str: + - This function takes an integer and converts it into a dotted str + - Useful in converting a number into version + - Eg: 123 -> "1.2.3" + """ res = list() for digit in str(number): res.append(digit) return ".".join(res) -def convert_dotted_str_to_int(dotted_str): +def convert_dotted_str_to_int(dotted_str: str) -> int: + """ + Convert dotted str into int: + - This function takes a dotted str and converts into an int + - Useful in converting version into a number + - Eg: "1.2.3" -> 123 + """ return int("".join(dotted_str.split("."))) From fd07da2b762abd995b2e2465c38e2be3d20ac0c0 Mon Sep 17 00:00:00 2001 From: Chakradhar Palaparthi Date: Sun, 4 Oct 2020 13:55:54 +0530 Subject: [PATCH 6/7] Update file_utils.py Correcting black and flake8 changes --- other/file_utils.py | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/other/file_utils.py b/other/file_utils.py index 76f59b6a39fd..e6fdfc70e5d5 100644 --- a/other/file_utils.py +++ b/other/file_utils.py @@ -1,9 +1,9 @@ import json import sys - # A utility file for all basic plain text and JSON file IO + def touch_file(file_name: str) -> None: """ Touch file: @@ -26,7 +26,7 @@ def touch_file(file_name: str) -> None: def clear_file(file_name: str) -> None: """ Clear file: - A utility function to clear the contents of the file file_name + A utility function to clear the contents of the file file_name. """ try: with open(file_name, "w"): @@ -60,13 +60,15 @@ def load_json_from_file(file_name: str) -> str: return readfile.read() or str({}) -def read_lines_strip_return(file_name: str, split: str = None, index: int = None) -> list: +def read_lines_strip_return( + file_name: str, split: str = None, index: int = None +) -> list: """ Read Lines from file: - Read the content of the file file_name using readlines. - If the parameter split is specified then each line is split using it. - - If the index is specified then after splitting the line corresponding index from the line is returned - - Returns list of lines from the file file_name matching the split and index conditions + - If the index is specified, index from the above split line is returned. + - Returns list of lines from file_name matching the split and index conditions. """ try: with open(file_name) as readfile: @@ -108,8 +110,8 @@ def append_line_to_file(file_name: str, line: str) -> None: """ Append Line to file: - Checks if the file exists and creates if not. - - Opens the file in append mode and appends the line at the ending of file file_name. - """ + - Opens the file in append mode and appends the line at the ending of file_name. + """ touch_file(file_name) with open(file_name, "a") as append_file: append_file.write(line + "\n") @@ -121,7 +123,7 @@ def append_line_to_file_if_doesnt_exist(file_name: str, line: str) -> None: - Checks if the file exists and creates if not. - Checks if the line already exists in the file file_name. - Only appends the line if nor already present in file_name. - """ + """ touch_file(file_name) lines = read_lines_strip_return(file_name) if line not in lines: @@ -147,8 +149,8 @@ def check_file_exists(file_name: str) -> bool: def convert_int_to_dotted_str(number: int) -> str: """ Convert int into dotted str: - - This function takes an integer and converts it into a dotted str - - Useful in converting a number into version + - This function takes an integer and converts it into a dotted str. + - Useful in converting a number into version. - Eg: 123 -> "1.2.3" """ res = list() @@ -160,8 +162,8 @@ def convert_int_to_dotted_str(number: int) -> str: def convert_dotted_str_to_int(dotted_str: str) -> int: """ Convert dotted str into int: - - This function takes a dotted str and converts into an int - - Useful in converting version into a number + - This function takes a dotted str and converts into an int. + - Useful in converting version into a number. - Eg: "1.2.3" -> 123 """ return int("".join(dotted_str.split("."))) From 9398b70a6ce133f50a19bcb2868a3364be85e0a4 Mon Sep 17 00:00:00 2001 From: Chakradhar Palaparthi Date: Sun, 4 Oct 2020 13:58:37 +0530 Subject: [PATCH 7/7] Update file_utils.py black: Single space after file_name --- other/file_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/other/file_utils.py b/other/file_utils.py index e6fdfc70e5d5..92ad1941f3bb 100644 --- a/other/file_utils.py +++ b/other/file_utils.py @@ -61,7 +61,7 @@ def load_json_from_file(file_name: str) -> str: def read_lines_strip_return( - file_name: str, split: str = None, index: int = None + file_name: str, split: str = None, index: int = None ) -> list: """ Read Lines from file: