Coverage for hdl_registers/generator/python/pickle.py: 96%

27 statements  

« prev     ^ index     » next       coverage.py v7.6.1, created at 2024-09-07 20:51 +0000

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

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

3# 

4# This file is part of the hdl-registers project, an HDL register generator fast enough to run 

5# in real time. 

6# https://hdl-registers.com 

7# https://github.com/hdl-registers/hdl-registers 

8# -------------------------------------------------------------------------------------------------- 

9 

10# Standard libraries 

11import pickle 

12from pathlib import Path 

13from typing import Any 

14 

15# Third party libraries 

16from tsfpga.system_utils import create_directory 

17 

18# First party libraries 

19from hdl_registers.generator.register_code_generator import RegisterCodeGenerator 

20from hdl_registers.register_list import RegisterList 

21 

22 

23class PythonPickleGenerator(RegisterCodeGenerator): 

24 """ 

25 Generate a Python pickle of the :class:`.RegisterList` object, along with a Python 

26 module to re-create the pickle in a simple way. 

27 

28 See the :ref:`generator_python` article for usage details. 

29 """ 

30 

31 __version__ = "1.0.0" 

32 

33 SHORT_DESCRIPTION = "Python pickle" 

34 

35 COMMENT_START = "#" 

36 

37 @property 

38 def output_file(self) -> Path: 

39 """ 

40 Result will be placed in this file. 

41 """ 

42 return self.output_folder / f"{self.name}.py" 

43 

44 def __init__(self, register_list: RegisterList, output_folder: Path): 

45 super().__init__(register_list=register_list, output_folder=output_folder) 

46 

47 self.pickle_file = self.output_folder / f"{self.name}.pickle" 

48 

49 def create(self, **kwargs: Any) -> Path: 

50 """ 

51 Create the binary pickle also, apart from the class file. 

52 

53 Note that this is a little bit hacky, preferably each generator should produce only 

54 one file. 

55 """ 

56 # Create directory if it does not exist, but do not delete anything if it does. 

57 create_directory(self.output_folder, empty=False) 

58 

59 with self.pickle_file.open("wb") as file_handle: 

60 pickle.dump(self.register_list, file_handle) 

61 

62 return super().create(**kwargs) 

63 

64 def get_code(self, **kwargs: Any) -> str: 

65 """ 

66 Save register list object to binary file (pickle) and create a python class 

67 that recreates it. 

68 """ 

69 class_name = self.to_pascal_case(self.name) 

70 

71 return f'''\ 

72{self.header} 

73# Standard libraries 

74import pickle 

75from pathlib import Path 

76from typing import TYPE_CHECKING 

77 

78if TYPE_CHECKING: 

79 # Third party libraries 

80 from hdl_registers.register_list import RegisterList 

81 

82THIS_DIR = Path(__file__).parent 

83PICKLE_FILE = THIS_DIR / "{self.pickle_file.name}" 

84 

85 

86class {class_name}: 

87 """ 

88 Instantiate this class to get the ``RegisterList`` object for the 

89 ``{self.name}`` register list. 

90 """ 

91 

92 def __new__(cls): 

93 """ 

94 Recreate the ``RegisterList`` object from binary pickle. 

95 """ 

96 with PICKLE_FILE.open("rb") as file_handle: 

97 return pickle.load(file_handle) 

98 

99 

100def get_register_list() -> "RegisterList": 

101 """ 

102 Return a ``RegisterList`` object with the registers/constants from the 

103 ``{self.name}`` register list. 

104 Recreated from a Python pickle file. 

105 """ 

106 with PICKLE_FILE.open("rb") as file_handle: 

107 return pickle.load(file_handle) 

108''' 

109 

110 @property 

111 def should_create(self) -> bool: 

112 """ 

113 Since this generator creates two files, where one is binary, it is impossible to do the 

114 version/hash check. 

115 Hence, set it to "always create". 

116 The mechanism "create if needed" should not be used for this generator anyway, since 

117 this generator is not designed to run in real-time like e.g. the VHDL generator. 

118 """ 

119 return True