diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4f4fdd167b2d105b52f860fdec88de10baa954a4..3cf2f97327ea1ce0e8a7dd40bd63d8116361d6cd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -106,6 +106,7 @@ INSTALL(TARGETS ${PYTHON_MODULE} SET (PYTHON_SOURCES dynamic_graph/__init__.py + dynamic_graph/attrpath.py dynamic_graph/entity.py dynamic_graph/signal_base.py dynamic_graph/matlab.py diff --git a/src/dynamic_graph/attrpath.py b/src/dynamic_graph/attrpath.py new file mode 100644 index 0000000000000000000000000000000000000000..ba1713ec677a619bee5926d8b4a267cb2c0bfa8e --- /dev/null +++ b/src/dynamic_graph/attrpath.py @@ -0,0 +1,110 @@ +# This module define the three functions: +# - getattrpath +# - setattrpath +# - existattrpath +# that work similarly as the get/setattr, but given path ("a.b.c.d") +# in input. Consider the following example: +# >>> setattrpath( e.__class__,"a.b.c.d",fun) +# with fun a function (self,*arg). Then, it is next possible to launch +# >>> e.a.b.c.d( ...) +# as if it was a classical member function of e. + + +class CommandPath(object): + """ + This class is only defined to implement a path of attribute + to store entity commands. It has no members except those automatically + defined at run time (which should be CommandPath or functions). + """ + mother=None + def __getattr__(self,name): + privateName=name+'_obj' + if privateName in self.__dict__: + obj=getattr(self,privateName) + obj.mother=self.mother + return obj + return object.__getattr__(self,name) + +def createCommandModule( target,name ): + def createGetter( name ): + def __( self ): + obj = getattr(self,name) + obj.mother=self + return obj + return __ + + privateName = name+'_obj' + setattr( target,privateName, CommandPath() ) + module = getattr( target,privateName ) + + if not isinstance(target,CommandPath) : + setattr( target,name, property(createGetter(privateName)) ) + +class CommandLauncher(object): + """ + """ + mother=None + fun=None + def __init__(self,fun): self.fun=fun + def __call__(self,*arg): + self.fun(self.mother,*arg) + +def createCommandLauncher( target,name,fun ): + if isinstance(target,CommandPath) : + privateName = name+'_obj' + setattr( target,privateName, CommandLauncher(fun) ) + else: + setattr( target,name,fun ) + + +def setattrpath( target,path,attribute ): + """ + Create in target an new attribute with value path (available at + target.path1. ... .pathn). + """ + pathk=target + read=True + if type(path)==type(str()): path=path.split('.') + for tokenk in path[0:-1]: + if (not read) | (tokenk not in pathk.__dict__): + read=False + createCommandModule(pathk,tokenk) + pathk = getattr(pathk,tokenk+"_obj") + if callable(attribute): + createCommandLauncher( pathk,path[-1],attribute ) + else: + print "Should not happen" + setattr(pathk,path[-1],attribute ) + +def getattrpath( target,path ): + """ + Get in target the value located at path (available at + target.path1. ... .pathn). + """ + pathk=target + if type(path)==type(str()): path=path.split('.') + for tokenk in path: + privateName=tokenk+"_obj" + if (privateName in pathk.__dict__): pathk = getattr(pathk,privateName) + else: + if ( tokenk in pathk.__dict__): pathk = getattr(pathk,tokenk) + else: + raise Exception('Path does not exist -- while accessing "'+tokenk+'" in '+'.'.join(path)) + return pathk + +def existattrpath( target,path ): + """ + Check for the existence in target of a value located at path (available at + target.path1. ... .pathn). + """ + pathk=target + if type(path)==type(str()): path=path.split('.') + for tokenk in path[0:-1]: + print 'check ',tokenk + privateName=tokenk+"_obj" + if (privateName not in pathk.__dict__): + return False + pathk = getattr(pathk,privateName) + name=path[-1] + privateName=name+"_obj" + return (name in pathk.__dict__)|(privateName in pathk.__dict__) diff --git a/src/dynamic_graph/entity.py b/src/dynamic_graph/entity.py index 7019ad152f7c0cec23e97c80666c568c9e3dc477..4da11ff17ba7451df1da7e3240467e9152e7b3e0 100644 --- a/src/dynamic_graph/entity.py +++ b/src/dynamic_graph/entity.py @@ -4,13 +4,13 @@ Author: Florent Lamiraux """ import wrap, signal_base, new +from attrpath import setattrpath entityClassNameList = [] if 'display' not in globals().keys(): def display(s): print(s) - def commandMethod(name, docstring) : def method(self, *arg): return wrap.entity_execute_command(self.obj, name, arg) @@ -28,7 +28,7 @@ def initEntity(self, name): # for each command, add a method with the name of the command for command in commands: docstring = wrap.entity_get_command_docstring(self.obj, command) - setattr(self.__class__, command, commandMethod(command, docstring)) + setattrpath(self.__class__, command, commandMethod(command, docstring)) self.__class__.commandCreated = True @@ -158,6 +158,7 @@ class Entity (object) : print "Warning: command ",cmdName," will overwrite an object attribute." docstring = wrap.entity_get_command_docstring(self.obj, cmdName) cmd = commandMethod(cmdName,docstring) + # Limitation (todo): does not handle for path attribute name (see setattrpath). setattr(self,cmdName,new.instancemethod( cmd, self,self.__class__)) def boundAllNewCommands(self):