Skip to content

Commit ea09a9d

Browse files
jtdubclaude
andcommitted
Rename inconsistent public APIs (#216)
- tags_add()/tags_remove() → add_tags()/remove_tags() - cisco_style_text() → indented_text() - dump_simple() → to_lines() - config_to_get_to() → remediation() - depth() method → depth property - Rename private helpers _config_to_get_to/_left/_right accordingly Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 5307e78 commit ea09a9d

34 files changed

Lines changed: 278 additions & 273 deletions

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2020

2121
- Renamed `load_hconfig_v2_options` to `load_driver_rules` (#221).
2222
- Renamed `load_hconfig_v2_tags` to `load_tag_rules` (#221).
23+
- Renamed `tags_add()`/`tags_remove()` to `add_tags()`/`remove_tags()` (#216).
24+
- Renamed `cisco_style_text()` to `indented_text()` (#216).
25+
- Renamed `dump_simple()` to `to_lines()` (#216).
26+
- Renamed `config_to_get_to()` to `remediation()` (#216).
27+
- Converted `depth()` method to `depth` property (#216).
2328

2429
### Removed
2530

CLAUDE.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,9 @@ Three-layer design: **Tree** (parse/represent config), **Driver** (platform-spec
6363

6464
### Tree Layer
6565

66-
- `HConfig` (root.py) — root node, owns the driver reference. Key methods: `config_to_get_to()`, `future()`, `difference()`, `dump_simple()`.
66+
- `HConfig` (root.py) — root node, owns the driver reference. Key methods: `remediation()`, `future()`, `difference()`, `to_lines()`.
6767
- `HConfigChild` (child.py) — tree node with `text`, `parent`, `children`, `tags`, `comments`. Provides `is_lineage_match()` for rule evaluation and `negate()` for negation logic.
68-
- `HConfigBase` (base.py) — abstract base shared by both. Provides `add_child()`, `get_children_deep()`, `_config_to_get_to()` (left pass = negate missing, right pass = add new).
68+
- `HConfigBase` (base.py) — abstract base shared by both. Provides `add_child()`, `get_children_deep()`, `_remediation()` (left pass = negate missing, right pass = add new).
6969
- `HConfigChildren` (children.py) — ordered collection with O(1) dict lookup by text.
7070

7171
### Driver Layer (`platforms/`)

docs/architecture.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ The tree layer lives in `hier_config/base.py`, `hier_config/root.py`, `hier_conf
2626

2727
- A reference to the **driver** for the platform.
2828
- An `HConfigChildren` collection of top-level `HConfigChild` nodes.
29-
- High-level operations: `future()`, `config_to_get_to()`, `merge()`, `difference()`, `dump()`.
29+
- High-level operations: `future()`, `remediation()`, `merge()`, `difference()`, `dump()`.
3030

3131
Create an `HConfig` object via the constructor function:
3232

@@ -62,7 +62,7 @@ Both `HConfig` and `HConfigChild` inherit from `HConfigBase`, which provides:
6262

6363
- Child manipulation: `add_child`, `add_children`, `add_deep_copy_of`, `add_shallow_copy_of`.
6464
- Searching: `get_child`, `get_children`, `get_child_deep`, `get_children_deep`.
65-
- Diffing: `unified_diff`, `_config_to_get_to`, `_difference`.
65+
- Diffing: `unified_diff`, `_remediation`, `_difference`.
6666
- Future prediction: `_future`, `_future_pre`.
6767

6868
---
@@ -129,9 +129,9 @@ remediation = workflow.remediation_config # what to apply
129129
rollback = workflow.rollback_config # how to revert
130130
```
131131

132-
Internally it calls `running_config.config_to_get_to(generated_config)` which traverses the tree and calls `_config_to_get_to_left` (what to negate) and `_config_to_get_to_right` (what to add).
132+
Internally it calls `running_config.remediation(generated_config)` which traverses the tree and calls `_remediation_left` (what to negate) and `_remediation_right` (what to add).
133133

134-
### `config_to_get_to()`
134+
### `remediation()`
135135

136136
This method computes the **minimal delta** between two configs:
137137

@@ -204,7 +204,7 @@ HConfig tree (HConfigBase / HConfigChild nodes)
204204
205205
├──► HConfig.future() → predicted post-change HConfig
206206
207-
├──► HConfig.config_to_get_to()
207+
├──► HConfig.remediation()
208208
│ │
209209
│ ▼
210210
│ delta HConfig (remediation commands)

docs/drivers.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ intended = get_hconfig(Platform.HP_PROCURVE, intended_text)
210210
workflow = WorkflowRemediation(running, intended)
211211

212212
for line in workflow.remediation_config.all_children_sorted():
213-
print(line.cisco_style_text())
213+
print(line.indented_text())
214214
```
215215

216216
---
@@ -239,7 +239,7 @@ intended = get_hconfig(Platform.HP_COMWARE5, intended_text)
239239
workflow = WorkflowRemediation(running, intended)
240240

241241
for line in workflow.remediation_config.all_children_sorted():
242-
print(line.cisco_style_text())
242+
print(line.indented_text())
243243
```
244244

245245
---

docs/future-config.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ This feature is useful in scenarios where you need to determine the anticipated
77
- Verifying that a configuration change was successfully applied to a device
88
- For example, checking if the post-change configuration matches the predicted future configuration
99
- Generating a future-state configuration that can be analyzed by tools like Batfish to assess the potential impact of a change
10-
- Building rollback configurations: once the future configuration state is known, a rollback configuration can be generated by simply creating the remediation in reverse `(rollback = future.config_to_get_to(running))`.
10+
- Building rollback configurations: once the future configuration state is known, a rollback configuration can be generated by simply creating the remediation in reverse `(rollback = future.remediation(running))`.
1111
- When building rollbacks for a series of configuration changes, you can use the future configuration from each change as input for the subsequent change. For example, use the future configuration after Change 1 as the input for determining the future configuration after Change 2, and so on.
1212

1313
## `merge()` versus `future()`
@@ -21,9 +21,9 @@ If you receive a `DuplicateChildError` while calling `merge()`, consider whether
2121

2222
```python
2323
post_change_1_config = running_config.future(change_1_config)
24-
change_1_rollback_config = post_change_1_config.config_to_get_to(running_config)
24+
change_1_rollback_config = post_change_1_config.remediation(running_config)
2525
post_change_2_config = post_change_1_config.future(change_2_config)
26-
change_2_rollback_config = post_change_2_config.config_to_get_to(post_change_1_config)
26+
change_2_rollback_config = post_change_2_config.remediation(post_change_1_config)
2727
```
2828

2929

@@ -53,7 +53,7 @@ The `future()` algorithm is a best-effort simulation. The following cases are n
5353

5454
5. **ACL idempotency check.**
5555
The extended ACL idempotency logic (sequence-number based matching) that drives
56-
`config_to_get_to()` is not replicated in `future()`.
56+
`remediation()` is not replicated in `future()`.
5757

5858
6. **And likely others.**
5959
Complex platform-specific interactions (e.g. VRF-aware BGP sections, route-policy
@@ -93,7 +93,7 @@ configuration because their identities differ within the `neighbor` hierarchy.
9393
>>> print("Running Config")
9494
Running Config
9595
>>> for line in running_config.all_children():
96-
... print(line.cisco_style_text())
96+
... print(line.indented_text())
9797
...
9898
hostname aggr-example.rtr
9999
ip access-list extended TEST
@@ -116,7 +116,7 @@ interface Vlan3
116116
>>> print("Remediation Config")
117117
Remediation Config
118118
>>> for line in remediation_config.all_children():
119-
... print(line.cisco_style_text())
119+
... print(line.indented_text())
120120
...
121121
vlan 3
122122
name switch_mgmt_10.0.3.0/24
@@ -139,7 +139,7 @@ interface Vlan4
139139
>>> print("Future Config")
140140
Future Config
141141
>>> for line in running_config.future(remediation_config).all_children():
142-
... print(line.cisco_style_text())
142+
... print(line.indented_text())
143143
...
144144
vlan 3
145145
name switch_mgmt_10.0.3.0/24

docs/getting-started.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ The `remediation_config` attribute generates the configuration needed to apply t
4848
>>> print("Remediation configuration:")
4949
Remediation configuration:
5050
>>> for line in workflow.remediation_config.all_children_sorted():
51-
... print(line.cisco_style_text())
51+
... print(line.indented_text())
5252
...
5353
vlan 3
5454
name switch_mgmt_10.0.3.0/24
@@ -79,7 +79,7 @@ Similarly, the `rollback_config` attribute generates a configuration that can re
7979
>>> print("Rollback configuration:")
8080
Rollback configuration:
8181
>>> for line in workflow.rollback_config.all_children_sorted():
82-
... print(line.cisco_style_text())
82+
... print(line.indented_text())
8383
...
8484
no vlan 4
8585
no interface Vlan4

docs/glossary.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ A Python class that encodes all operating-system-specific behaviour for one netw
2424

2525
A configuration command where only the *last* value applied takes effect — applying the same command twice with different values results in only the second value being active. Typical examples: `hostname`, `ip address`, `description`.
2626

27-
hier_config uses `IdempotentCommandsRule` to identify these commands. During `config_to_get_to()`, when both the running and intended configs contain a command that matches an idempotency rule, the running value is **not** negated before the new value is applied (the new value simply overwrites it).
27+
hier_config uses `IdempotentCommandsRule` to identify these commands. During `remediation()`, when both the running and intended configs contain a command that matches an idempotency rule, the running value is **not** negated before the new value is applied (the new value simply overwrites it).
2828

2929
**Example rule:**
3030

@@ -126,7 +126,7 @@ A `SectionalExitingRule` that instructs hier_config to emit a closing token at t
126126

127127
## Sectional overwrite
128128

129-
A `SectionalOverwriteRule` that tells `config_to_get_to()` to **negate the entire section** and then re-create it from the intended config rather than performing a line-by-line diff. Appropriate for configuration blocks where the order of entries matters globally or where partial changes are not supported by the OS.
129+
A `SectionalOverwriteRule` that tells `remediation()` to **negate the entire section** and then re-create it from the intended config rather than performing a line-by-line diff. Appropriate for configuration blocks where the order of entries matters globally or where partial changes are not supported by the OS.
130130

131131
---
132132

docs/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ intended = get_hconfig(Platform.CISCO_IOS, intended_config_text)
4444
workflow = WorkflowRemediation(running, intended)
4545

4646
for line in workflow.remediation_config.all_children_sorted():
47-
print(line.cisco_style_text())
47+
print(line.indented_text())
4848
```
4949

5050
---

hier_config/base.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ class HConfigBase(ABC): # noqa: PLR0904
2626
2727
Both `HConfig` (the root) and `HConfigChild` (individual nodes) inherit from
2828
this class. It provides the shared tree-manipulation API: adding, searching,
29-
and diffing children, as well as the `_future` / `_config_to_get_to` algorithms
29+
and diffing children, as well as the `_future` / `_remediation` algorithms
3030
that power `WorkflowRemediation`.
3131
"""
3232

@@ -62,6 +62,7 @@ def driver(self) -> HConfigDriverBase:
6262
def lineage(self) -> Iterator[HConfigChild]:
6363
pass
6464

65+
@property
6566
@abstractmethod
6667
def depth(self) -> int:
6768
pass
@@ -231,7 +232,7 @@ def add_shallow_copy_of(
231232
new_child.comments.update(child_to_add.comments)
232233
new_child.order_weight = child_to_add.order_weight
233234
if child_to_add.is_leaf:
234-
new_child.tags_add(child_to_add.tags)
235+
new_child.add_tags(child_to_add.tags)
235236

236237
return new_child
237238

@@ -372,7 +373,7 @@ def _with_tags(
372373

373374
return new_instance
374375

375-
def _config_to_get_to(
376+
def _remediation(
376377
self,
377378
target: _HConfigRootOrChildT,
378379
delta: _HConfigRootOrChildT,
@@ -382,8 +383,8 @@ def _config_to_get_to(
382383
target is the destination(i.e. generated_config).
383384
384385
"""
385-
self._config_to_get_to_left(target, delta)
386-
self._config_to_get_to_right(target, delta)
386+
self._remediation_left(target, delta)
387+
self._remediation_right(target, delta)
387388

388389
return delta
389390

@@ -441,7 +442,7 @@ def _difference(
441442

442443
return delta
443444

444-
def _config_to_get_to_left(
445+
def _remediation_left(
445446
self,
446447
target: HConfig | HConfigChild,
447448
delta: HConfig | HConfigChild,
@@ -462,7 +463,7 @@ def _config_to_get_to_left(
462463
if self_child.children:
463464
negated.comments.add(f"removes {len(self_child.children) + 1} lines")
464465

465-
def _config_to_get_to_right(
466+
def _remediation_right(
466467
self,
467468
target: HConfig | HConfigChild,
468469
delta: HConfig | HConfigChild,
@@ -481,7 +482,7 @@ def _config_to_get_to_right(
481482
# This creates a new HConfigChild object just in case there are some delta children.
482483
# This is not very efficient, think of a way to not do this.
483484
subtree = delta.instantiate_child(target_child.text)
484-
self_child._config_to_get_to(target_child, subtree) # noqa: SLF001
485+
self_child._remediation(target_child, subtree) # noqa: SLF001
485486
if subtree.children:
486487
delta.children.append(subtree)
487488
# The child is absent, add it.

hier_config/child.py

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -114,15 +114,13 @@ def root(self) -> HConfig:
114114
return self.parent.root
115115

116116
def lines(self, *, sectional_exiting: bool = False) -> Iterable[str]:
117-
yield self.cisco_style_text()
117+
yield self.indented_text()
118118
for child in sorted(self.children):
119119
yield from child.lines(sectional_exiting=sectional_exiting)
120120

121121
if sectional_exiting and (exit_text := self.sectional_exit):
122122
depth = (
123-
self.depth() - 1
124-
if self.sectional_exit_text_parent_level
125-
else self.depth()
123+
self.depth - 1 if self.sectional_exit_text_parent_level else self.depth
126124
)
127125
yield " " * self.driver.rules.indentation * depth + exit_text
128126

@@ -147,9 +145,10 @@ def delete_sectional_exit(self) -> None:
147145
if (exit_text := self.sectional_exit) and exit_text == potential_exit.text:
148146
potential_exit.delete()
149147

148+
@property
150149
def depth(self) -> int:
151150
"""Returns the distance to the root HConfig object i.e. indent level."""
152-
return self.parent.depth() + 1
151+
return self.parent.depth + 1
153152

154153
def move(self, new_parent: HConfig | HConfigChild) -> None:
155154
"""Move one HConfigChild object to different HConfig parent object.
@@ -179,12 +178,12 @@ def path(self) -> Iterator[str]:
179178
for child in self.lineage():
180179
yield child.text
181180

182-
def cisco_style_text(
181+
def indented_text(
183182
self,
184183
style: str = "without_comments",
185184
tag: str | None = None,
186185
) -> str:
187-
"""Return a Cisco style formated line i.e. indentation_level + text ! comments."""
186+
"""Return an indented text line i.e. indentation_level + text ! comments."""
188187
comments: list[str] = []
189188
if style == "without_comments":
190189
pass
@@ -210,27 +209,27 @@ def cisco_style_text(
210209

211210
@property
212211
def indentation(self) -> str:
213-
return " " * self.driver.rules.indentation * (self.depth() - 1)
212+
return " " * self.driver.rules.indentation * (self.depth - 1)
214213

215214
def delete(self) -> None:
216215
"""Delete the current object from its parent."""
217216
self.parent.children.delete(self)
218217

219-
def tags_add(self, tag: str | Iterable[str]) -> None:
218+
def add_tags(self, tag: str | Iterable[str]) -> None:
220219
"""Add a tag to self._tags on all leaf nodes."""
221220
if self.is_branch:
222221
for child in self.children:
223-
child.tags_add(tag)
222+
child.add_tags(tag)
224223
elif isinstance(tag, str):
225224
self._tags.add(tag)
226225
else:
227226
self._tags.update(tag)
228227

229-
def tags_remove(self, tag: str | Iterable[str]) -> None:
228+
def remove_tags(self, tag: str | Iterable[str]) -> None:
230229
"""Remove a tag from self._tags on all leaf nodes."""
231230
if self.is_branch:
232231
for child in self.children:
233-
child.tags_remove(tag)
232+
child.remove_tags(tag)
234233
elif isinstance(tag, str):
235234
self._tags.remove(tag)
236235
else:
@@ -348,7 +347,7 @@ def overwrite_with(
348347
comment is attached to the new entry, and a ``"dropping section"``
349348
comment is added to the negated entry when applicable.
350349
351-
Used by :meth:`_config_to_get_to_right` when a sectional-overwrite
350+
Used by :meth:`_remediation_right` when a sectional-overwrite
352351
rule is active for ``self.text``.
353352
"""
354353
if self.children != target.children:

0 commit comments

Comments
 (0)