Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1# -------------------------------------------------------------------------------------------------- 

2# Copyright (c) Lukas Vik. All rights reserved. 

3# 

4# This file is part of the tsfpga project. 

5# https://tsfpga.com 

6# https://gitlab.com/tsfpga/tsfpga 

7# -------------------------------------------------------------------------------------------------- 

8 

9import importlib.util 

10import os 

11from os.path import commonpath 

12from platform import system 

13from shutil import rmtree 

14import subprocess 

15 

16from tsfpga import DEFAULT_FILE_ENCODING 

17 

18 

19def create_file(file, contents=None): 

20 create_directory(file.parent, empty=False) 

21 

22 contents = "" if contents is None else contents 

23 with open(file, "w", encoding=DEFAULT_FILE_ENCODING) as file_handle: 

24 file_handle.write(contents) 

25 

26 return file 

27 

28 

29def read_file(file): 

30 with open(file, encoding=DEFAULT_FILE_ENCODING) as file_handle: 

31 return file_handle.read() 

32 

33 

34def read_last_lines_of_file(file, num_lines): 

35 """ 

36 Read a number of lines from the end of a file, without buffering the whole file. 

37 Similar to unix ``tail`` command. 

38 

39 Arguments: 

40 file (`pathlib.Path`): The file that shall be read. 

41 num_lines (int): The number of lines to read. 

42 

43 Return: 

44 str: The last lines of the file. 

45 """ 

46 result_lines = [] 

47 blocks_to_read = 0 

48 

49 with open(file, encoding=DEFAULT_FILE_ENCODING) as file_handle: 

50 while len(result_lines) < num_lines: 

51 # Since we do not know the line lengths, there is some guessing involved. Keep reading 

52 # larger and larger blocks until we have all the lines that are requested. 

53 blocks_to_read += 1 

54 

55 try: 

56 # Read a block from the end 

57 file_handle.seek(-blocks_to_read * 4096, os.SEEK_END) 

58 except IOError: 

59 # Tried to read more data than what is available. Read whatever we have and return 

60 # to user. 

61 file_handle.seek(0) 

62 result_lines = file_handle.readlines() 

63 break 

64 

65 result_lines = file_handle.readlines() 

66 

67 result = "".join(result_lines[-num_lines:]) 

68 return result 

69 

70 

71def delete(path): 

72 if path.exists(): 

73 if path.is_dir(): 

74 rmtree(path) 

75 else: 

76 path.unlink() 

77 return path 

78 

79 

80def create_directory(directory, empty=True): 

81 if empty: 

82 delete(directory) 

83 elif directory.exists(): 

84 return directory 

85 

86 directory.mkdir(parents=True) 

87 return directory 

88 

89 

90def file_is_in_directory(file_path, directories): 

91 """ 

92 Check if the file is in any of the directories. 

93 

94 Arguments: 

95 file_path (`pathlib.Path`): The file to be checked. 

96 directories (list(`pathlib.Path`)): The directories to be controlled. 

97 

98 Returns: 

99 bool: True if there is a comon path. 

100 """ 

101 for directory in directories: 

102 if commonpath([str(file_path), str(directory)]) == str(directory): 

103 return True 

104 return False 

105 

106 

107def run_command(cmd, cwd=None): 

108 if not isinstance(cmd, list): 

109 raise ValueError("Must be called with a list, not a string") 

110 

111 subprocess.check_call(cmd, cwd=cwd) 

112 

113 

114def load_python_module(file): 

115 python_module_name = file.stem 

116 

117 spec = importlib.util.spec_from_file_location(python_module_name, file) 

118 module = importlib.util.module_from_spec(spec) 

119 spec.loader.exec_module(module) 

120 

121 return module 

122 

123 

124def system_is_windows(): 

125 return system() == "Windows"