@@ -251,6 +251,8 @@ class link(object):
251
251
----------
252
252
source : (object / attribute name) pair
253
253
target : (object / attribute name) pair
254
+ transform: iterable with two callables (optional)
255
+ Data transformation between source and target and target and source.
254
256
255
257
Examples
256
258
--------
@@ -260,15 +262,19 @@ class link(object):
260
262
"""
261
263
updating = False
262
264
263
- def __init__ (self , source , target ):
265
+ def __init__ (self , source , target , transform = None ):
264
266
_validate_link (source , target )
265
267
self .source , self .target = source , target
268
+ self ._transform , self ._transform_inv = (
269
+ transform if transform else (lambda x : x ,) * 2 )
270
+
266
271
self .link ()
267
272
268
273
def link (self ):
269
274
try :
270
275
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
+
272
278
finally :
273
279
self .source [0 ].observe (self ._update_target , names = self .source [1 ])
274
280
self .target [0 ].observe (self ._update_source , names = self .target [1 ])
@@ -285,13 +291,22 @@ def _update_target(self, change):
285
291
if self .updating :
286
292
return
287
293
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 ))
289
299
290
300
def _update_source (self , change ):
291
301
if self .updating :
292
302
return
293
303
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 ))
295
310
296
311
def unlink (self ):
297
312
self .source [0 ].unobserve (self ._update_target , names = self .source [1 ])
0 commit comments