@@ -251,6 +251,8 @@ class link(object):
251251 ----------
252252 source : (object / attribute name) pair
253253 target : (object / attribute name) pair
254+ transform: iterable with two callables (optional)
255+ Data transformation between source and target and target and source.
254256
255257 Examples
256258 --------
@@ -260,15 +262,19 @@ class link(object):
260262 """
261263 updating = False
262264
263- def __init__ (self , source , target ):
265+ def __init__ (self , source , target , transform = None ):
264266 _validate_link (source , target )
265267 self .source , self .target = source , target
268+ self ._transform , self ._transform_inv = (
269+ transform if transform else (lambda x : x ,) * 2 )
270+
266271 self .link ()
267272
268273 def link (self ):
269274 try :
270275 setattr (self .target [0 ], self .target [1 ],
271- getattr (self .source [0 ], self .source [1 ]))
276+ self ._transform (getattr (self .source [0 ], self .source [1 ])))
277+
272278 finally :
273279 self .source [0 ].observe (self ._update_target , names = self .source [1 ])
274280 self .target [0 ].observe (self ._update_source , names = self .target [1 ])
@@ -285,13 +291,22 @@ def _update_target(self, change):
285291 if self .updating :
286292 return
287293 with self ._busy_updating ():
288- setattr (self .target [0 ], self .target [1 ], change .new )
294+ setattr (self .target [0 ], self .target [1 ], self ._transform (change .new ))
295+ if getattr (self .source [0 ], self .source [1 ]) != change .new :
296+ raise TraitError (
297+ "Broken link {}: the source value changed while updating "
298+ "the target." .format (self ))
289299
290300 def _update_source (self , change ):
291301 if self .updating :
292302 return
293303 with self ._busy_updating ():
294- setattr (self .source [0 ], self .source [1 ], change .new )
304+ setattr (self .source [0 ], self .source [1 ],
305+ self ._transform_inv (change .new ))
306+ if getattr (self .target [0 ], self .target [1 ]) != change .new :
307+ raise TraitError (
308+ "Broken link {}: the target value changed while updating "
309+ "the source." .format (self ))
295310
296311 def unlink (self ):
297312 self .source [0 ].unobserve (self ._update_target , names = self .source [1 ])
0 commit comments