Hi guys,
as you know I'm doing this extension of Network Editor and David suggested me
to let you know how it's going.
We started to create the API by developing Python modules that work with dummy
data. Once we finish this stage we will wrap this structures under an object
with
the same interface as the C++ module that will call CLAM functions.
So far, we have developed the Processing part of the API in Python. I'll attach
the
files here for those of you that want to try it. To see a preview of things to
come, download
all the files in the same directory, launch ipython and from there do:
from Processing import Processing
p = Processing("AudioSource")
and then you have a processing created. If you type p.<tab> ipython will list
for you all
the attributes that you can see or modify.
This are the functions supported:
p = Processing("ProcessingType") #For now, only accepted parameter is
AudioSource
ports = proc._outports # connections is an iterable
ports = proc._inports # connections is an iterable
controls = proc._outcontrols # connections is an iterable
controls = proc._incontrols # connections is an iterable
proc.ConfigField = newvalue
proc["ConfigField"] = newvalue
proc._config["ConfigField"] = newvalue
proc._config.ConfigField = newvalue
proc.Output
proc['Output']
proc._outports['Output']
proc._outports.Output
proc._outports[4] # Zero based to be consistent with python indexing
proc._outports[1:4] #To get outport from 1 to 4 excluded
proc.Output.type # Returns a string
proc.Output.name
proc.Output.index
import operator
import unittest
processingDB = dict(
AudioSource = (
dict(
ConfigParam1 = "default1",
ConfigParam2 = "default2",
),
[
["Inport1", "type1"],
["Inport2", "type1"]
],
[
["Outport1", "type1"],
["Outport2", "type1"]
],
[
["Incontrol1", "type2"],
["Incontrol2", "type2"]
],
[
["Outcontrol1", "type2"],
["Outcontrol2", "type2"]
],
)
)
class Configuration(object):
def __init__(self, type):
object.__setattr__(self, "_dict", processingDB[type][0].copy())
def __getitem__(self, name):
return self._dict[name]
def __setitem__(self, name, value):
if not name in self._dict.keys():
raise KeyError(name)
item = object.__getattribute__(self, "_dict")
item[name] = value
def __getattr__(self, name):
if not name in self._dict.keys():
raise AttributeError(name)
return self.__getitem__(name)
def __setattr__(self, name, value):
if not name in self._dict.keys():
raise AttributeError(name)
self.__setitem__(name, value)
def __dir__(self):
return self._dict.keys()
class TestConfigurationFunctions(unittest.TestCase):
def setUp(self):
pass
def test_configGettingAsDictionary(self):
c = Configuration("AudioSource")
self.assertEqual(c["ConfigParam1"], "default1")
self.assertEqual(c["ConfigParam2"], "default2")
def test_configSettingAndGettingAsDictionary(self):
c = Configuration("AudioSource")
c["ConfigParam1"] = 'newvalue'
self.assertEqual(c["ConfigParam1"], "newvalue")
def test_configGettingAsAttribute(self):
c = Configuration("AudioSource")
self.assertEqual(c.ConfigParam1, "default1")
self.assertEqual(c.ConfigParam2, "default2")
def test_configSettingAndGettingAsAttribute(self):
c = Configuration("AudioSource")
c.ConfigParam1 = 'newvalue'
self.assertEqual(c.ConfigParam1, "newvalue")
def test_configSettingAsAttributeAndGettingAsDictionary(self):
c = Configuration("AudioSource")
c.ConfigParam1 = 'newvalue1'
c.ConfigParam2 = 'newvalue2'
self.assertEqual(c["ConfigParam1"], "newvalue1")
self.assertEqual(c["ConfigParam2"], "newvalue2")
def test_ValuesAsAttributesSettingAndFailing(self):
c = Configuration("AudioSource")
self.assertRaises(AttributeError, setattr, c, "ConfigParam3", "newvalue")
def test_ValuesAsAttributesGettingAndFailing(self):
c = Configuration("AudioSource")
self.assertRaises(AttributeError, getattr, c, "ConfigParam3")
def test_ValuesAsDictionarySettingAndFailing(self):
c = Configuration("AudioSource")
self.assertRaises(KeyError, operator.setitem, c, "ConfigParam3", "newvalue")
def test_ValuesAsDictionaryGettingAndFailing(self):
c = Configuration("AudioSource")
self.assertRaises(KeyError, operator.getitem, c, "ConfigParam3")
def test_dirFunction(self):
c = Configuration("AudioSource")
self.assertEquals(["ConfigParam1", "ConfigParam2"], dir(c))
if __name__ == '__main__':
unittest.main()
import unittest
class Connector(object):
Port = "Port"
Control = "Control"
In = "In"
Out = "Out"
def __init__(self, type, name = "inport1", kind=Port, direction=In, index=1):
self.__dict__["name"] = name
self.__dict__["kind"] = kind
self.__dict__["direction"] = direction
self.__dict__["index"] = index
self.__dict__["type"] = type
@property
def name(self):
"""The name of the port"""
return self.__dict__["name"]
@property
def kind(self):
"""The kind of the port"""
return self.__dict__["kind"]
@property
def direction(self):
"""The direction of the port"""
return self.__dict__["direction"]
@property
def index(self):
"""The index of the port"""
return self.__dict__["index"]
@property
def type(self):
"""The type of the port"""
return self.__dict__["type"]
class TestConnectorFunctions(unittest.TestCase):
def setUp(self):
pass
def test_gettingName(self):
port = Connector(
name="inport1",
kind=Connector.Port,
direction=Connector.In,
index=2,
type="tipus1"
)
self.assertEqual(port.name, "inport1")
def test_settingNameAndFailing(self):
port = Connector(
name="inport1",
kind=Connector.Port,
direction=Connector.In,
index=2,
type="tipus1"
)
self.assertRaises(AttributeError, setattr, port, "name", 'inport2')
def test_gettingKindPort(self):
port = Connector(name="inport1", kind=Connector.Port, direction=Connector.In, index=2, type="tipus1")
self.assertEqual(port.kind, "Port")
def test_gettingKindControl(self):
port = Connector(name="inport1", kind=Connector.Control, direction=Connector.In, index=2, type="tipus1")
self.assertEqual(port.kind, "Control")
def test_settingKindAndFailing(self):
port = Connector(name="inport1", kind=Connector.Port, direction=Connector.In, index=2, type="tipus1")
self.assertRaises(AttributeError, setattr, port, "kind", Connector.Control)
def test_gettingDirectionIn(self):
port = Connector(name="inport1", kind=Connector.Port, direction=Connector.In, index=2, type="tipus1")
self.assertEqual(port.direction, "In")
def test_gettingDirectionOut(self):
port = Connector(name="inport1", kind=Connector.Port, direction=Connector.Out, index=2, type="tipus1")
self.assertEqual(port.direction, "Out")
def test_settingDirectionAndFailing(self):
port = Connector(name="inport1", kind=Connector.Port, direction=Connector.In, index=2, type="tipus1")
self.assertRaises(AttributeError, setattr, port, "direction", Connector.Out)
def test_gettingIndex(self):
port = Connector(name="inport1", kind=Connector.Port, direction=Connector.In, index=1, type="tipus1")
self.assertEqual(port.index, 1)
def test_settingIndexAndFailing(self):
port = Connector(name="inport1", kind=Connector.Port, direction=Connector.In, index=1, type="tipus1")
self.assertRaises(AttributeError, setattr, port, "index", 2)
def test_gettingType(self):
port = Connector(name="inport1", kind=Connector.Port, direction=Connector.In, index=1, type="tipus1")
self.assertEqual(port.type, "tipus1")
def test_settingTypeAndFailing(self):
port = Connector(name="inport1", kind=Connector.Port, direction=Connector.In, index=1, type="tipus1")
self.assertRaises(AttributeError, setattr, port, "type", "tipus2")
if __name__ == '__main__':
unittest.main()
import unittest
from Connector import Connector
class Connectors(object):
def __init__(self, kind, direction, portNames):
self._dict = dict()
self._list = list()
for i, port in enumerate(portNames):
connector = Connector(name=port[0], kind=kind, direction=direction, index=i+1, type=port[1])
self._list.append(connector)
self._dict[connector.name] = connector
def __iter__(self):
for connector in self._list:
yield connector
def __getitem__(self, index):
if type(index) is int:
return self._list[index]
if type(index) is str:
return self._dict[index]
if type(index) is slice:
return self._list[index]
def __getattr__(self, name):
if not name in self._dict.keys():
raise AttributeError(name)
return self._dict[name]
def __len__(self):
return len(self._list)
def __dir__(self):
return self._dict.keys()
class TestConnectorsFunctions(unittest.TestCase):
def setUp(self):
pass
def test_iterable(self):
portNames = [['inport1', 'type1'], ['inport2', 'type1'], ['inport3', 'type1']]
ports = Connectors(Connector.Port, Connector.In, portNames)
listNames = [ connector.name for connector in ports ]
self.assertEqual(listNames, ['inport1', 'inport2', 'inport3'])
def test_indexable(self):
portNames = [['inport1', 'type1'], ['inport2', 'type1'], ['inport3', 'type1']]
ports = Connectors(Connector.Port, Connector.In, portNames)
self.assertEqual(ports[0].name, 'inport1')
def test_lenImplementation(self):
portNames = [['inport1', 'type1'], ['inport2', 'type1'], ['inport3', 'type1']]
ports = Connectors(Connector.Port, Connector.In, portNames)
self.assertEqual(len(ports), len(portNames))
def test_getConnectorByNameAsDicionary(self):
portNames = [['inport1', 'type1'], ['inport2', 'type1'], ['inport3', 'type1']]
ports = Connectors(Connector.Port, Connector.In, portNames)
self.assertEqual(ports['inport1'].name, 'inport1')
def test_getConnectorByNameAsAttribute(self):
portNames = [['inport1', 'type1'], ['inport2', 'type1'], ['inport3', 'type1']]
ports = Connectors(Connector.Port, Connector.In, portNames)
self.assertEqual(ports.inport1.kind, Connector.Port)
def test_dirFunction(self):
portNames = [['inport1', 'type1'], ['inport2', 'type1'], ['inport3', 'type1']]
ports = Connectors(Connector.Port, Connector.In, portNames)
self.assertEquals(['inport1', 'inport2', 'inport3'], dir(ports))
def test_sliceable(self):
portNames = [['inport1', 'type1'], ['inport2', 'type1'], ['inport3', 'type1'], ['inport4', 'type1']]
ports = Connectors(Connector.Port, Connector.In, portNames)
portsSliced = ports[1:4]
self.assertEqual(portsSliced[0].name, 'inport2')
self.assertEqual(portsSliced[1].name, 'inport3')
self.assertEqual(portsSliced[2].name, 'inport4')
if __name__ == '__main__':
unittest.main()
import unittest
from Configuration import Configuration
from Configuration import processingDB
from Connector import Connector
from Connectors import Connectors
class Processing(object):
def __init__(self, type):
self.__dict__["_config"] = Configuration(type)
self.__dict__["_inports"] = Connectors(Connector.Port, Connector.In, processingDB[type][1])
self.__dict__["_outports"] = Connectors(Connector.Port, Connector.Out, processingDB[type][2])
self.__dict__["_incontrols"] = Connectors(Connector.Control, Connector.In, processingDB[type][3])
self.__dict__["_outcontrols"] = Connectors(Connector.Control, Connector.Out, processingDB[type][4])
def __getitem__(self, name):
if name in dir(self._config):
return self._config[name]
if name in dir(self._inports):
return self._inports[name]
if name in dir(self._outports):
return self._outports[name]
if name in dir(self._incontrols):
return self._incontrols[name]
if name in dir(self._outcontrols):
return self._outcontrols[name]
raise KeyError(name)
def __setitem__(self, name, value):
self._config[name] = value
def __getattr__(self, name):
try:
return self.__getitem__(name)
except KeyError:
raise AttributeError(name)
def __setattr__(self, name, value):
self.__setitem__(name, value)
def __dir__(self):
return dir(self._config) + dir(self._inports) + dir(self._outports) + dir(self._incontrols) + dir(self._outcontrols) + ["_config", "_inports", "_outports", "_incontrols", "_outcontrols"]
class TestProcessingFunctions(unittest.TestCase):
def setUp(self):
pass
def test_ConfigGettingAsDictionary(self):
p = Processing("AudioSource")
self.assertEqual(p["ConfigParam1"], "default1")
def test_ConfigSettingAndGettingAsDictionary(self):
p = Processing("AudioSource")
p["ConfigParam1"] = 'newvalue'
self.assertEqual(p["ConfigParam1"], "newvalue")
def test_configGettingAsAttribute(self):
p = Processing("AudioSource")
self.assertEqual(p.ConfigParam1, "default1")
def test_configSettingAndGettingAsAttribute(self):
p = Processing("AudioSource")
p.ConfigParam1 = 'newvalue'
self.assertEqual(p.ConfigParam1, "newvalue")
def test_ConfigGettersBy_configInterface(self):
p = Processing("AudioSource")
self.assertEqual(p._config.ConfigParam1, "default1")
self.assertEqual(p._config["ConfigParam2"], "default2")
def test_ConfigSettersBy_configInterface(self):
p = Processing("AudioSource")
p._config.ConfigParam1 = "newvalue1"
p._config["ConfigParam2"] = "newvalue2"
self.assertEqual(p._config.ConfigParam1, "newvalue1")
self.assertEqual(p._config["ConfigParam2"], "newvalue2")
def test_InportsGettingByNameAsDictionary(self):
p = Processing("AudioSource")
self.assertEqual(p["Inport1"].name, "Inport1")
self.assertEqual(p["Inport1"].kind, "Port")
self.assertEqual(p["Inport1"].direction, "In")
def test_InportsGettingByNameAsAttribute(self):
p = Processing("AudioSource")
self.assertEqual(p.Inport2.name, "Inport2")
self.assertEqual(p.Inport2.kind, "Port")
self.assertEqual(p.Inport2.direction, "In")
def test_OutportsGettingByNameAsDictionary(self):
p = Processing("AudioSource")
self.assertEqual(p["Outport1"].name, "Outport1")
self.assertEqual(p["Outport1"].kind, "Port")
self.assertEqual(p["Outport1"].direction, "Out")
def test_OutportsGettingByNameAsAttribute(self):
p = Processing("AudioSource")
self.assertEqual(p.Outport2.name, "Outport2")
self.assertEqual(p.Outport2.kind, "Port")
self.assertEqual(p.Outport2.direction, "Out")
def test_IncontrolsGettingByNameAsDictionary(self):
p = Processing("AudioSource")
self.assertEqual(p["Incontrol1"].name, "Incontrol1")
self.assertEqual(p["Incontrol1"].kind, "Control")
self.assertEqual(p["Incontrol1"].direction, "In")
def test_IncontrolsGettingByNameAsAttribute(self):
p = Processing("AudioSource")
self.assertEqual(p.Incontrol2.name, "Incontrol2")
self.assertEqual(p.Incontrol2.kind, "Control")
self.assertEqual(p.Incontrol2.direction, "In")
def test_OutcontrolsGettingByNameAsDictionary(self):
p = Processing("AudioSource")
self.assertEqual(p["Outcontrol1"].name, "Outcontrol1")
self.assertEqual(p["Outcontrol1"].kind, "Control")
self.assertEqual(p["Outcontrol1"].direction, "Out")
def test_OutcontrolsGettingByNameAsAttribute(self):
p = Processing("AudioSource")
self.assertEqual(p.Outcontrol2.name, "Outcontrol2")
self.assertEqual(p.Outcontrol2.kind, "Control")
self.assertEqual(p.Outcontrol2.direction, "Out")
def test_dirFunction(self):
p = Processing("AudioSource")
self.assertEquals(sorted(
['ConfigParam1', 'ConfigParam2',
'Inport1', 'Inport2',
'Outport1', 'Outport2',
'Incontrol1', 'Incontrol2',
'Outcontrol1', 'Outcontrol2',
'_config', '_inports', '_outports', '_incontrols', '_outcontrols']), dir(p))
if __name__ == '__main__':
unittest.main()
#!/usr/bin/python
import unittest
from Connector import *
from Connectors import *
from Configuration import *
from Processing import *
if __name__ == '__main__':
unittest.main()
On Nov 3, 2010, at 7:22 PM, David García Garzón wrote:
> On Monday 25 October 2010 00:01:23 Xavier Serra wrote:
>> Hi guys,
>> the next part of my project is to integrate a console in Network Editor
>> that will allow manipulation (and creation) of networks interactively
>> through commands. Before starting to code the console I need to decide how
>> will the API be so I'm sending here a first proposal to see what you guys
>> think (this is mostly for David, but anyone is welcome to say his thing)
>>
>> Another cool thing we talked about was tab completion, like bash and
>> ipython. I tried to show how this function worked in the API example but
>> it complicated the whole thing, so I removed it.
>>
>> Bye!
>
> Follows the resulting python interface after a meeting with Xavi, Natanael
> and
> me. I included last minute not agreed changes for discusion, namely:
> port/control.peers, proc.configured flag, the '>' connection among
> processings, and the interfaces with "implicit network??".
>
> - General controls
> # with an implicit network would be free functions.
> network.load("filename.clamnetwork")
> network.import("<Network> .... </Network>")
> network.save()
> network.save("filename")
>
> - Transport
> # with an implicit network would be free functions.
> network.play()
> network.stop()
> network.pause()
> network.isStopped()
> network.isPlaying()
> network.isReady()
> network.whyIsNotReady # TOREVIEW
>
> - Processings
> proc = network.add("ProcessingType")
> proc = network.add("name", "ProcessingType")
> proc = add("ProcessingType") # implicit network
> proc = add("name", "ProcessingType") # implicit network
> network.remove("name")
> remove(proc) # implicit network alternative
> proc.remove() # alternative
> ports = proc._outports # connections is an iterable
> ports = proc._inports # connections is an iterable
> controls = proc._outcontrols # connections is an iterable
> controls = proc._incontrols # connections is an iterable
> proc.rename("newname")
> proc2 = proc.clone()
> proc2 = proc.clone("name2")
>
> - Processing Configuration
> # Changes on proc._config has no effect on the processing
> # until 'reconfigure' is called
> config = Config("ProcessingType")
> proc.ConfigField = newvalue
> proc["ConfigField"] = newvalue
> proc._config["ConfigField"] = newvalue
> proc._config.ConfigField = newvalue
> # analog for getters
> proc.updateConfig(
> ConfigField = value1,
> ConfigField2 = value2,
> )
> proc.config=config
> proc.reconfigure()
> proc.configured
>
> - Obtaining ports/controls
> proc.Output
> proc['Output']
> proc._outports['Output']
> proc._outports.Output
> proc._outports[4] # Zero based to be consistent with python indexing
> proc.Output.type # not sure what to return
> proc.Output.name
> proc.Output.index
> proc.Output.peers # returns a list of connected peers
>
> - Connecting
> proc._outports.connect(proc2) # Connects all feasible ports
> proc._outcontrols.connect(proc2) # Connects all feasible controls
> proc > proc2 # shorthand for ._outports.connect
> proc.Output.connect(proc2.Input)
> proc.Output > proc2.Input # shorthand for .connect
>
> - Disconnect controls/ports
> proc.Output.disconnect(proc2.Input)
> proc.Output.disconnect() # any connected
> proc.Input.disconnect() # any connected
> for port in proc._inports : port.disconnect()
>
> _______________________________________________
> clam-devel mailing list
> clam-devel@lists.clam-project.org
> http://lists.clam-project.org/listinfo.cgi/clam-devel-clam-project.org
_______________________________________________
clam-devel mailing list
clam-devel@lists.clam-project.org
http://lists.clam-project.org/listinfo.cgi/clam-devel-clam-project.org