ipython / ipython/traitlets

Notifying a trait with a DataFrame instance throws Value Error

Abierto
#756 3 comentarios 2 reacciones 0 asignados Ver en GitHub
Lenguaje dominante
Python
Estrellas
653
Forks
217
Merge medio
2 d 21 h
PR fusionados (30 d)
2

Descripción

Hey there,

At first, thank you for this amazing library!

I noticed that there are problems when linking multiple objects using the link function, if the value of a trait is a dataframe.
To me it looks like the compare logic overridden by pandas is causing the problem.
Here is an example:

```python
import traitlets
from traitlets import link, directional_link
import pandas as pd

class SomeClass(traitlets.HasTraits):
df = traitlets.Instance(klass=pd.DataFrame, allow_none=True)

foo = SomeClass()
baz = SomeClass()
bar = SomeClass()

# Will not work
link((foo, "df"), (baz, "df"))
foo.df = pd.DataFrame() # Throws ValueError
```

Stacktrace:

```python
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
traitlets_dataframe.ipynb Cell 4' in ()
2 link((foo, "df"), (baz, "df"))
4 # Throws ValueError
----> 5 foo.df = pd.DataFrame()

File .\lib\site-packages\traitlets\traitlets.py:712, in TraitType.__set__(self, obj, value)
710 raise TraitError('The "%s" trait is read-only.' % self.name)
711 else:
--> 712 self.set(obj, value)

File .\lib\site-packages\traitlets\traitlets.py:701, in TraitType.set(self, obj, value)
697 silent = False
698 if silent is not True:
699 # we explicitly compare silent to True just in case the equality
700 # comparison above returns something other than True/False
--> 701 obj._notify_trait(self.name, old_value, new_value)

File .\lib\site-packages\traitlets\traitlets.py:1371, in HasTraits._notify_trait(self, name, old_value, new_value)
1370 def _notify_trait(self, name, old_value, new_value):
-> 1371 self.notify_change(
1372 Bunch(
1373 name=name,
1374 old=old_value,
1375 new=new_value,
1376 owner=self,
1377 type="change",
1378 )
1379 )

File .\lib\site-packages\traitlets\traitlets.py:1383, in HasTraits.notify_change(self, change)
1381 def notify_change(self, change):
1382 """Notify observers of a change event"""
-> 1383 return self._notify_observers(change)

File .\lib\site-packages\traitlets\traitlets.py:1428, in HasTraits._notify_observers(self, event)
1425 elif isinstance(c, EventHandler) and c.name is not None:
1426 c = getattr(self, c.name)
-> 1428 c(event)

File .\lib\site-packages\traitlets\traitlets.py:366, in link._update_target(self, change)
364 with self._busy_updating():
365 setattr(self.target[0], self.target[1], self._transform(change.new))
--> 366 if getattr(self.source[0], self.source[1]) != change.new:
367 raise TraitError(
368 "Broken link {}: the source value changed while updating "
369 "the target.".format(self)
370 )

File .\lib\site-packages\pandas\core\generic.py:1527, in NDFrame.__nonzero__(self)
1525 @final
1526 def __nonzero__(self):
-> 1527 raise ValueError(
1528 f"The truth value of a {type(self).__name__} is ambiguous. "
1529 "Use a.empty, a.bool(), a.item(), a.any() or a.all()."
1530 )

ValueError: The truth value of a DataFrame is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
```

As you can see, hhe problem is in `traitlets.py: 366`, because `getattr(self.source[0], self.source[1]) != change.new` does not return a bool value in the case of a DataFrame.

Would it be possible to make this function compatible with pandas, or possibly define a custom function for comparison?

Thank you in advance!

Guía de contribución

Abrir la guía de contribución

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.