Reputation: 43097
I am building a python automation API around a device configuration that looks like this...
root@EX4200-24T# show interfaces ge-0/0/6
mtu 9216;
unit 0 {
family ethernet-switching {
port-mode trunk;
vlan {
members [ v100 v101 v102 ];
}
}
}
root@EX4200-24T#
I am defining python classes for certain actions (like SET), as well as classes for the keywords for the action... The idea is that SET would iterate through the keyword classes and attach the class objects to the interfaces.
The problem is that the configuration of this device is quite hierarchical... for instance if there are many ethernet-switching
instances, I don't want API users to have to use:
# Note that each keyword corresponds to a python class that is appended
# to an InterfaceList object behind the scenes...
SET(Interface='ge-0/0/6.0', Family='ethernet-switching', PortMode='trunk',
Vlan=['v100', 'v101', 'v102'])
SET(Interface='ge-0/0/7.0', Family='ethernet-switching', PortMode='trunk',
Vlan=['v100', 'v101', 'v102'])
SET(Interface='ge-0/0/8.0', Family='ethernet-switching', PortMode='trunk',
Vlan=['v100', 'v101', 'v102'])
Instead I would like to be able to use:
Family('ethernet-switching')
SET(Interface='ge-0/0/6.0', PortMode='trunk', Vlan=['v100', 'v101', 'v102'])
SET(Interface='ge-0/0/7.0', PortMode='trunk', Vlan=['v100', 'v101', 'v102'])
SET(Interface='ge-0/0/8.0', PortMode='trunk', Vlan=['v100', 'v101', 'v102'])
Family(None)
# API usage continues...
However, I can't figure out a way to code this in python without resorting to something like this...
f = Family('ethernet-switching')
f.SET(Interface='ge-0/0/6.0', PortMode='trunk',
Vlan=['v100', 'v101', 'v102'])
f.SET(Interface='ge-0/0/7.0', PortMode='trunk',
Vlan=['v100', 'v101', 'v102'])
f.SET(Interface='ge-0/0/8.0', PortMode='trunk',
Vlan=['v100', 'v101', 'v102'])
Which is not so bad until I need SET()
to inherit from multiple classes... such as...
PREFERRED API
# Note: there could be many combinations of classes to inherit from
Family('ethernet-switching')
PortMode('trunk')
SET(Interface='ge-0/0/6.0', Vlan=['v100', 'v101', 'v102'])
SET(Interface='ge-0/0/7.0', Vlan=['v100', 'v101', 'v102'])
PortMode('access')
SET(Interface='ge-0/0/8.0', Vlan=['v100'])
SET(Interface='ge-0/0/9.0', Vlan=['v100'])
Family(None)
PortMode(None)
Is there a pythonic way to achieve the last API example I have? If not, can you share some ideas for how to code the hierarchy of classes?
Upvotes: 5
Views: 552
Reputation: 41546
gnibbler's use of functools.partial
is indeed an elegant approach, but if you want to look at a true implicit context based approach, I suggested exploring the implementation details underlying decimal.getcontext()
, decimal.setcontext()
and decimal.localcontext()
.
Documentation is at: http://docs.python.org/py3k/library/decimal Source code is at: http://hg.python.org/cpython/file/default/Lib/decimal.py#l435
Upvotes: 2
Reputation: 304413
Does something like this help you?
from functools import partial
S=partial(SET, Family='ethernet-switching', PortMode='trunk')
S(Interface='ge-0/0/6.0', Vlan=['v100', 'v101', 'v102'])
S(Interface='ge-0/0/7.0', Vlan=['v100', 'v101', 'v102'])
S(Interface='ge-0/0/8.0', Vlan=['v100', 'v101', 'v102'])
Upvotes: 10
Reputation: 9091
Well this resembles jQuery
selection & filtering API, where they make use of function chaining:
some_set_of_data
.filter(first_criteria)
.filter(second_criteria)
They also introduced end()
method that allows you to do things like that:
some_set_of_data
.filter(first_criteria)
.filter(second_criteria)
.do_something()
.end()
.do_something_else()
Note that in this example do_something()
is called on data filtered by both first_criteria
and second_criteria
, wheras do_something_else()
is called on the data only filtered by the first_criteria
.
It should be fairly easy to copy this kind of approach in Python that has a lot in common with JavaScript.
Upvotes: 1