Node/Extend
When you want to make adjustments to an existing node’s implementation
Use cases:
- Few isolated changes to an existing node
- Wrap a CRUD node but customize editing operations, actions or notifications
Special notes
- If [
Reflect
]({ { < relref “reflect” > } } ) was a cake and [Basic
]({ { < relref “basic” > } } ) was the plate under the cake, thenExtend
would be the frosting. Extend
is exactly likeBasic
but let’s you delegate anything to another node. So most ofBasic's
documentation also applies here.
Reflect
with one exception
package demo
import "fmt"
type Bird struct {
Name string
X int
Y int
}
func (b *Bird) GetCoordinates() string {
return fmt.Sprintf("%d,%d", b.X, b.Y)
}
class Bird():
def __init__(self, name, x, y):
self.name = name
self.x = x
self.y = y
def coordinates(self):
return f'{self.x},{self.y}'
module bird {
namespace "freeconf.org";
prefix "b";
leaf name {
type string;
}
leaf location {
config false;
type string {
pattern "[0-9.]+,[0-9.]+";
}
}
}
package demo
import (
"github.com/freeconf/yang/node"
"github.com/freeconf/yang/nodeutil"
"github.com/freeconf/yang/val"
)
func manage(b *Bird) node.Node {
return &nodeutil.Extend{
Base: nodeutil.ReflectChild(b), // handles Name
OnField: func(p node.Node, r node.FieldRequest, hnd *node.ValueHandle) error {
switch r.Meta.Ident() {
case "location":
hnd.Val = val.String(b.GetCoordinates())
default:
// delegates to ReflectChild for name
return p.Field(r, hnd)
}
return nil
},
}
}
from freeconf import nodeutil, val
def manage_bird(bird):
base = nodeutil.Node(bird)
def on_field(parent, req, write_val):
if req.meta.ident == "location":
return val.Val(bird.coordinates())
return parent.field(req, write_val)
return nodeutil.Extend(base, on_field=on_field)
Addition Files
file: manage_test.go
package demo
import (
"testing"
"github.com/freeconf/yang/fc"
"github.com/freeconf/yang/node"
"github.com/freeconf/yang/nodeutil"
"github.com/freeconf/yang/parser"
"github.com/freeconf/yang/source"
)
func TestManage(t *testing.T) {
b := &Bird{Name: "sparrow", X: 99, Y: 1000}
ypath := source.Dir(".")
m := parser.RequireModule(ypath, "bird")
bwsr := node.NewBrowser(m, manage(b))
root := bwsr.Root()
defer root.Release()
actual, err := nodeutil.WriteJSON(root)
fc.AssertEqual(t, nil, err)
fc.AssertEqual(t, `{"name":"sparrow","location":"99,1000"}`, actual)
}
file: test_manage.py
#!/usr/bin/env python3
import unittest
from freeconf import parser, nodeutil, source, node
from manage import manage_bird
from bird import Bird
class TestManage(unittest.TestCase):
def test_manage(self):
app = Bird("sparrow", 99, 1000)
ypath = source.path('..')
m = parser.load_module_file(ypath, 'bird')
mgmt = manage_bird(app)
bwsr = node.Browser(m, mgmt)
root = bwsr.root()
try:
actual = nodeutil.json_write_str(root)
self.assertEqual('{"name":"sparrow","location":"99,1000"}', actual)
finally:
root.release()
if __name__ == '__main__':
unittest.main()