Coverage for hdl_registers/generator/python/pickle.py: 96%
27 statements
« prev ^ index » next coverage.py v7.6.12, created at 2025-03-12 11:11 +0000
« prev ^ index » next coverage.py v7.6.12, created at 2025-03-12 11:11 +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# --------------------------------------------------------------------------------------------------
10# ruff: noqa: A005
12import pickle
13from pathlib import Path
14from typing import Any
16from tsfpga.system_utils import create_directory
18from hdl_registers.generator.register_code_generator import RegisterCodeGenerator
19from hdl_registers.register_list import RegisterList
22class PythonPickleGenerator(RegisterCodeGenerator):
23 """
24 Generate a Python pickle of the :class:`.RegisterList` object, along with a Python
25 module to re-create the pickle in a simple way.
27 See the :ref:`generator_python` article for usage details.
28 """
30 __version__ = "1.0.0"
32 SHORT_DESCRIPTION = "Python pickle"
34 COMMENT_START = "#"
36 @property
37 def output_file(self) -> Path:
38 """
39 Result will be placed in this file.
40 """
41 return self.output_folder / f"{self.name}.py"
43 def __init__(self, register_list: RegisterList, output_folder: Path) -> None:
44 super().__init__(register_list=register_list, output_folder=output_folder)
46 self.pickle_file = self.output_folder / f"{self.name}.pickle"
48 def create(
49 self,
50 **kwargs: Any, # noqa: ANN401
51 ) -> Path:
52 """
53 Create the binary pickle also, apart from the class file.
55 Note that this is a little bit hacky, preferably each generator should produce only
56 one file.
57 """
58 # Create directory if it does not exist, but do not delete anything if it does.
59 create_directory(self.output_folder, empty=False)
61 with self.pickle_file.open("wb") as file_handle:
62 pickle.dump(self.register_list, file_handle)
64 return super().create(**kwargs)
66 def get_code(
67 self,
68 **kwargs: Any, # noqa: ANN401, ARG002
69 ) -> str:
70 """
71 Save register list object to binary file (pickle) and create a python class
72 that recreates it.
73 """
74 class_name = self.to_pascal_case(self.name)
76 return f'''\
77import pickle
78from pathlib import Path
79from typing import TYPE_CHECKING
81if TYPE_CHECKING:
82 from hdl_registers.register_list import RegisterList
84THIS_DIR = Path(__file__).parent
85PICKLE_FILE = THIS_DIR / "{self.pickle_file.name}"
88class {class_name}:
89 """
90 Instantiate this class to get the ``RegisterList`` object for the
91 ``{self.name}`` register list.
92 """
94 def __new__(cls):
95 """
96 Recreate the ``RegisterList`` object from binary pickle.
97 """
98 with PICKLE_FILE.open("rb") as file_handle:
99 return pickle.load(file_handle)
102def get_register_list() -> "RegisterList":
103 """
104 Return a ``RegisterList`` object with the registers/constants from the
105 ``{self.name}`` register list.
106 Recreated from a Python pickle file.
107 """
108 with PICKLE_FILE.open("rb") as file_handle:
109 return pickle.load(file_handle)
110'''
112 @property
113 def should_create(self) -> bool:
114 """
115 Since this generator creates two files, where one is binary, it is impossible to do the
116 version/hash check.
117 Hence, set it to "always create".
118 The mechanism "create if needed" should not be used for this generator anyway, since
119 this generator is not designed to run in real-time like e.g. the VHDL generator.
120 """
121 return True