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, thenExtendwould be the frosting. Extendis exactly likeBasicbut let’s you delegate anything to another node. So most ofBasic'sdocumentation 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()