Coverage for birdplan/bird_config/sections/base.py: 95%
76 statements
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-23 03:27 +0000
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-23 03:27 +0000
1#
2# SPDX-License-Identifier: GPL-3.0-or-later
3#
4# Copyright (c) 2019-2024, AllWorldIT
5#
6# This program is free software: you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation, either version 3 of the License, or
9# (at your option) any later version.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with this program. If not, see <http://www.gnu.org/licenses/>.
19"""BIRD configuration section base class."""
21from typing import Dict, List, Union
23from ..globals import BirdConfigGlobals
25__all__ = ["SectionBaseConfig", "SectionBase"]
28# Types
29SectionConfigItem = Union[str, List[str], "SectionBase"]
30SectionConfigItemList = List[SectionConfigItem]
31SectionConfigItems = Dict[int, SectionConfigItemList]
34class SectionBaseConfig: # pylint: disable=too-few-public-methods
35 """Configuration contents of the section."""
37 _birdconfig_globals: BirdConfigGlobals
38 _items: SectionConfigItems
40 def __init__(self, birdconfig_globals: BirdConfigGlobals) -> None:
41 """Initialize object."""
42 self._birdconfig_globals = birdconfig_globals
43 self._items = {}
45 def add(self, item: SectionConfigItem, order: int = 10, deferred: bool = False, debug: bool = False) -> None:
46 """
47 Add configuration to the output we're going to generate.
49 Parameters
50 ----------
51 item : SectionConfigItem
52 Configuration to add, either a string, list of strings or another section.
54 order : int
55 Ordering of the item to add. Defaults to `10`.
57 deferred : bool
58 If the config item is a SectionBase, then rendering can be deferred until after configuration.
59 This is needed for instance for the constants section, which other protocols may add to.
61 debug : bool
62 The configuration provided should only be output when we are in debug mode.
64 """
65 # Sanity checks
66 if deferred and not isinstance(item, SectionBase):
67 raise RuntimeError("Only SectionBase objects can be used as deferred configuration")
69 # If we have a debug line, exclude it if we're not in debugging mode
70 if debug and not self.birdconfig_globals.debug:
71 return
73 # Make sure this ordering position is initialized
74 if order not in self.items:
75 self.items[order] = []
76 items = self.items[order]
78 # If this is an instance of a list, extend our lines by this list
79 if isinstance(item, list):
80 items.extend(item)
81 # If it is an entire section, configure it and add the lines
82 elif isinstance(item, SectionBase):
83 # Check if we're rendering now or later
84 if not deferred:
85 item.configure()
86 self.add(item.conf.lines)
87 else:
88 items.append(item)
89 # Else just add it
90 else:
91 items.append(item)
93 def append(self, item: SectionConfigItem, deferred: bool = False, debug: bool = False) -> None:
94 """
95 Add configuration to the output we're going to generate.
97 This uses an order of `50`, which is higher than add() that defaults to `10`.
99 Parameters
100 ----------
101 item : SectionConfigItem
102 Configuration to add, either a string, list of strings or another section.
103 deferred : bool
104 If the config item is a SectionBase, then rendering can be deferred until after configuration.
105 This is needed for instance for the constants section, which other protocols may add to.
106 debug : bool
107 The configuration provided should only be output when we are in debug mode.
109 """
110 self.add(item=item, order=50, deferred=deferred, debug=debug)
112 def title(self, title: str, order: int = 10) -> None:
113 """
114 Add a title block.
116 Parameters
117 ----------
118 title : str
119 Add a title block
120 order : int
121 Ordering of the item to add. Defaults to `10`.
123 """
124 self.add("#", order=order)
125 self.add(f"# {title}", order=order)
126 self.add("#", order=order)
127 self.add("", order=order)
129 def append_title(self, title: str) -> None:
130 """
131 Add a title block.
133 This uses an order of `50`, which is higher than title() that defaults to `10`.
135 Parameters
136 ----------
137 title : str
138 Add a title block
140 """
141 self.title(title=title, order=50)
143 @property
144 def items(self) -> SectionConfigItems:
145 """Return our configuration items."""
146 return self._items
148 @property
149 def lines(self) -> List[str]:
150 """Return our configuration lines."""
151 lines: List[str] = []
152 # Loop with configuration items in order
153 for _, items in sorted(self._items.items()):
154 # Loop with each list
155 for item in items:
156 # If it is a SectionBase it means it was deferred, so configure and extend
157 if isinstance(item, SectionBase):
158 item.configure()
159 lines.extend(item.conf.lines)
160 # Or its just normal strings, add them all
161 elif isinstance(item, str):
162 lines.append(item)
163 # Or something really weird happened
164 else:
165 raise RuntimeError("We should only have 'str' and 'SectionBase' items")
166 # Finally return
167 return lines
169 @property
170 def birdconfig_globals(self) -> BirdConfigGlobals:
171 """Return our BirdConfig globals."""
172 return self._birdconfig_globals
175class SectionBase:
176 """Base class for a BIRD configuration section."""
178 # Section title
179 _section: str
181 # Globals
182 _birdconfig_globals: BirdConfigGlobals
184 # Configuration lines to output
185 _config: SectionBaseConfig
187 # pylint: disable=unused-argument
188 def __init__(self, birdconfig_globals: BirdConfigGlobals) -> None:
189 """
190 Initialize the object.
192 Returns
193 -------
194 Nothing.
196 """
198 self._section = ""
200 self._birdconfig_globals = birdconfig_globals
202 self._config = SectionBaseConfig(birdconfig_globals=self.birdconfig_globals)
204 def configure(self) -> None:
205 """
206 Configure this section.
208 Returns
209 -------
210 Nothing.
212 """
213 if self.section:
214 self.conf.title(self.section)
216 @property
217 def section(self) -> str:
218 """Return the section name."""
219 return self._section
221 @property
222 def birdconfig_globals(self) -> BirdConfigGlobals:
223 """Return our BirdConfig globals."""
224 return self._birdconfig_globals
226 @property
227 def conf(self) -> SectionBaseConfig:
228 """Return the configuration object."""
229 return self._config