ivoflipse / Pawlabeling

Tool for processing and analyzing pressure measurements
Other
18 stars 1 forks source link

Deleting the last item from subjects, sessions or measurements is broken #113

Closed ivoflipse closed 10 years ago

ivoflipse commented 11 years ago

Sometimes I try to delete a subject, session or measurement, but because its the only one or the last one. I suddenly get an error (sorry I don't have a trace).

Figure out what's happening and if it happens again, work around it and delete it anyway.

ivoflipse commented 10 years ago

Here's the specific error message:

NotImplementedError: You are trying to delete all the rows in table "/subjects". This is not supported right now due to limitations on the underlying HDF5 library. Sorry!

ivoflipse commented 10 years ago

Looking through old mailing lists, this problem should have been fixed in HDF5 1.8, but when I looked at Github, the code was still there. So I'm not really sure what I can do here.

One workaround would be to drop the whole table, that I'm trying to delete from, which should be safe given that I'm deleting the last item anyway.

ivoflipse commented 10 years ago

I've resorted to manually dropping the table and recreating it. In some cases it would complain about the group still being there, so I made an even worse hack and changed create_group, such that it tries to create the group, if that fails, it tries to remove the node and tries again.

Feels really bad though and its currently only implemented on contactmodel

ivoflipse commented 10 years ago

I just ran into this problem again. I should check out whether this still isn't solved.

Traceback (most recent call last):
  File "C:\Dropbox\Development\Pawlabeling\pawlabeling\widgets\database\sessionwidget.py", line 92, in delete_session
    self.model.delete_session(session=session)
  File "C:\Dropbox\Development\Pawlabeling\pawlabeling\models\model.py", line 237, in delete_session
    self.session_model.delete_session(session)
  File "C:\Dropbox\Development\Pawlabeling\pawlabeling\models\sessionmodel.py", line 34, in delete_session
    item_id=session.session_id)
  File "C:\Dropbox\Development\Pawlabeling\pawlabeling\models\table.py", line 95, in remove_row
    table.removeRows(start=index, stop=index+1)
  File "C:\Anaconda64\lib\site-packages\tables\_past.py", line 35, in oldfunc
    return obj(*args, **kwargs)
  File "C:\Anaconda64\lib\site-packages\tables\table.py", line 2670, in remove_rows
    self._v_pathname)
NotImplementedError: You are trying to delete all the rows in table "/subject_3/sessions". This is not supported right now due to limitations on the underlying HDF5 library. Sorry!
ivoflipse commented 10 years ago

I thought I'd wrap the table.remove_rows in a try/except clause and if it raises a NotImplementedError just remove the entire table.

However, delete_session (for example) removes both a row and a group:

    def delete_session(self, session):
        # Delete both the row and the group
        self.sessions_table.remove_row(table=self.sessions_table.sessions_table,
                                       name_id="session_id",
                                       item_id=session.session_id)
        self.sessions_table.remove_group(where="/{}".format(self.subject_id),
                                         name=session.session_id)

So now remove_row doesn't get executed, but remove_group does. Which creates problems down the road. So either both actions have to succeed or neither.

Perhaps table.flush() shouldn't be called until we're sure both actions succeeded.

ivoflipse commented 10 years ago
Traceback (most recent call last):
  File "C:\Dropbox\Development\Pawlabeling\pawlabeling\widgets\database\subjectwidget.py", line 156, in put_subject
    self.model.put_subject(subject=subject)
  File "C:\Dropbox\Development\Pawlabeling\pawlabeling\models\model.py", line 146, in put_subject
    self.get_sessions()
  File "C:\Dropbox\Development\Pawlabeling\pawlabeling\models\model.py", line 102, in get_sessions
    pub.sendMessage("get_sessions")
  File "C:\Anaconda64\lib\site-packages\pypubsub-3.3.0dev1-py2.7.egg\pubsub\core\kwargs\publisher.py", line 27, in sendMessage
    topicObj.publish(**kwargs)
  File "C:\Anaconda64\lib\site-packages\pypubsub-3.3.0dev1-py2.7.egg\pubsub\core\kwargs\publishermixin.py", line 24, in publish
    self._publish(msgKwargs)
  File "C:\Anaconda64\lib\site-packages\pypubsub-3.3.0dev1-py2.7.egg\pubsub\core\topicobj.py", line 370, in _publish
    self.__sendMessage(data, self, iterState)
  File "C:\Anaconda64\lib\site-packages\pypubsub-3.3.0dev1-py2.7.egg\pubsub\core\topicobj.py", line 389, in __sendMessage
    self._mix_callListener(listener, data, iterState)
  File "C:\Anaconda64\lib\site-packages\pypubsub-3.3.0dev1-py2.7.egg\pubsub\core\kwargs\publishermixin.py", line 64, in _mix_callListener
    listener(iterState.filteredArgs, self, msgKwargs)
  File "C:\Anaconda64\lib\site-packages\pypubsub-3.3.0dev1-py2.7.egg\pubsub\core\kwargs\listenerimpl.py", line 43, in __call__
    cb(**kwargs)
  File "C:\Dropbox\Development\Pawlabeling\pawlabeling\widgets\database\sessionwidget.py", line 128, in update_sessions_tree
    self.put_session()
  File "C:\Dropbox\Development\Pawlabeling\pawlabeling\widgets\database\sessionwidget.py", line 109, in put_session
    self.model.put_session(session=session)
  File "C:\Dropbox\Development\Pawlabeling\pawlabeling\models\model.py", line 157, in put_session
    session_id=self.session_id)
  File "C:\Dropbox\Development\Pawlabeling\pawlabeling\models\table.py", line 261, in __init__
    self.session_group = self.table.root.__getattr__(self.subject_id).__getattr__(self.session_id)
  File "C:\Anaconda64\lib\site-packages\tables\group.py", line 811, in __getattr__
    return self._f_get_child(name)
  File "C:\Anaconda64\lib\site-packages\tables\group.py", line 681, in _f_get_child
    self._g_check_has_child(childname)
  File "C:\Anaconda64\lib\site-packages\tables\group.py", line 405, in _g_check_has_child
    % (self._v_pathname, name))
tables.exceptions.NoSuchNodeError: group ``/subject_4`` does not have a child named ``session_1``

Here you see what goes wrong. When selecting a subject it propagates events, it gets the sessions, selects the first one, gets the measurements, selects the first one. But then it fails, because the session_group session_1 no longer exists.

So I should really make sure there's no session table left, but then also make sure that the model no longer maintains the old state.

ivoflipse commented 10 years ago

Ok, removing the node as is, doesn't work as intended:

Traceback (most recent call last):
  File "C:\Dropbox\Development\Pawlabeling\pawlabeling\widgets\database\sessionwidget.py", line 94, in delete_session
    self.model.delete_session(session=session)
  File "C:\Dropbox\Development\Pawlabeling\pawlabeling\models\model.py", line 239, in delete_session
    self.get_sessions()
  File "C:\Dropbox\Development\Pawlabeling\pawlabeling\models\model.py", line 101, in get_sessions
    self.sessions = self.session_model.get_sessions()
  File "C:\Dropbox\Development\Pawlabeling\pawlabeling\models\sessionmodel.py", line 40, in get_sessions
    for session in self.sessions_table.get_sessions():
  File "C:\Dropbox\Development\Pawlabeling\pawlabeling\models\table.py", line 230, in get_sessions
    session_list = self.sessions_table.read()
  File "C:\Anaconda64\lib\site-packages\tables\table.py", line 1961, in read
    self._g_check_open()
  File "C:\Anaconda64\lib\site-packages\tables\node.py", line 349, in _g_check_open
    raise ClosedNodeError("the node object is closed")
tables.exceptions.ClosedNodeError: the node object is closed

But I think that's because none of the other functions are notified that its now actually gone. So I guess its good practice to shield those functions from accessing it without checking and failing early.

ivoflipse commented 10 years ago

It seems to be working now, quite smoothly I must say. But when deleting the last subject, it doesn't refresh the session and measurement widget, which is rather fishy.