Coverage for hdl_registers/generator/python/pickle.py: 96%
27 statements
« prev ^ index » next coverage.py v7.9.2, created at 2025-07-04 20:52 +0000
« prev ^ index » next coverage.py v7.9.2, created at 2025-07-04 20:52 +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# --------------------------------------------------------------------------------------------------
10import pickle
11from pathlib import Path
12from typing import Any
14from tsfpga.system_utils import create_directory
16from hdl_registers.generator.register_code_generator import RegisterCodeGenerator
17from hdl_registers.register_list import RegisterList
20class PythonPickleGenerator(RegisterCodeGenerator):
21 """
22 Generate a Python pickle of the :class:`.RegisterList` object, along with a Python
23 module to re-create the pickle in a simple way.
25 See the :ref:`generator_python` article for usage details.
26 """
28 __version__ = "1.0.0"
30 SHORT_DESCRIPTION = "Python pickle"
32 COMMENT_START = "#"
34 @property
35 def output_file(self) -> Path:
36 """
37 Result will be placed in this file.
38 """
39 return self.output_folder / f"{self.name}.py"
41 def __init__(self, register_list: RegisterList, output_folder: Path) -> None:
42 super().__init__(register_list=register_list, output_folder=output_folder)
44 self.pickle_file = self.output_folder / f"{self.name}.pickle"
46 def create(
47 self,
48 **kwargs: Any, # noqa: ANN401
49 ) -> Path:
50 """
51 Create the binary pickle also, apart from the class file.
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)
59 with self.pickle_file.open("wb") as file_handle:
60 pickle.dump(self.register_list, file_handle)
62 return super().create(**kwargs)
64 def get_code(
65 self,
66 **kwargs: Any, # noqa: ANN401, ARG002
67 ) -> str:
68 """
69 Save register list object to binary file (pickle) and create a python class
70 that recreates it.
71 """
72 class_name = self.to_pascal_case(self.name)
74 return f'''\
75import pickle
76from pathlib import Path
77from typing import TYPE_CHECKING
79if TYPE_CHECKING:
80 from hdl_registers.register_list import RegisterList
82THIS_DIR = Path(__file__).parent
83PICKLE_FILE = THIS_DIR / "{self.pickle_file.name}"
86class {class_name}:
87 """
88 Instantiate this class to get the ``RegisterList`` object for the
89 ``{self.name}`` register list.
90 """
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)
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'''
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