pazz / alot

Terminal-based Mail User Agent
GNU General Public License v3.0
683 stars 163 forks source link

[master/cffi] AttributeError: 'Thread' object has no attribute 'get_toplevel_messages' #1590

Closed kbingham closed 2 years ago

kbingham commented 2 years ago

Before you submit a bug report, please make sure that the issue still exists on the master branch!

Describe the bug

Attempting to run alot with the latest master branch fails with "AttributeError: 'Thread' object has no attribute 'get_toplevel_messages'" (python trace below).

git bisect brings it to:

de51016548aa8c48726d8d1b1e0e2cd900291780 is the first bad commit alot: Import the notmuch2 bindings

However, the resulting error is actually different at that point and fails with: AttributeError: 'Database' object has no attribute 'create_query'

But I can not run any commit beyond "import the notmuch2" commit.

Software Versions

To Reproduce Steps to reproduce the behaviour:

check out sources at relevant point python3 -m alot

However, some investigations makes it look like this might be specific to a config option I have set:

 # Set thread subjects to the first (oldest) message
 thread_subject = oldest

So perhaps others don't hit this if they don't have that set. (I thought that was the obvious choice to set it to though ... )

Error Log

python3 -m alot
Traceback (most recent call last):
  File "/usr/lib/python3.9/runpy.py", line 197, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/usr/lib/python3.9/runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "/home/kbingham/iob/alot/alot/__main__.py", line 146, in <module>
    main()
  File "/home/kbingham/iob/alot/alot/__main__.py", line 137, in main
    UI(dbman, cmdstring)
  File "/home/kbingham/iob/alot/alot/ui.py", line 146, in __init__
    self.mainloop.run()
  File "/usr/lib/python3/dist-packages/urwid/main_loop.py", line 287, in run
    self._run()
  File "/usr/lib/python3/dist-packages/urwid/main_loop.py", line 385, in _run
    self.event_loop.run()
  File "/usr/lib/python3/dist-packages/urwid/main_loop.py", line 1346, in run
    reraise(*exc_info)
  File "/usr/lib/python3/dist-packages/urwid/compat.py", line 58, in reraise
    raise value
  File "/usr/lib/python3/dist-packages/urwid/main_loop.py", line 1360, in wrapper
    rval = f(*args,**kargs)
  File "/usr/lib/python3/dist-packages/urwid/main_loop.py", line 1319, in _twisted_idle_callback
    callback()
  File "/usr/lib/python3/dist-packages/urwid/main_loop.py", line 574, in entering_idle
    self.draw_screen()
  File "/usr/lib/python3/dist-packages/urwid/main_loop.py", line 588, in draw_screen
    canvas = self._topmost_widget.render(self.screen_size, focus=True)
  File "/usr/lib/python3/dist-packages/urwid/widget.py", line 145, in cached_render
    canv = fn(self, size, focus=focus)
  File "/usr/lib/python3/dist-packages/urwid/decoration.py", line 226, in render
    canv = self._original_widget.render(size, focus=focus)
  File "/usr/lib/python3/dist-packages/urwid/widget.py", line 145, in cached_render
    canv = fn(self, size, focus=focus)
  File "/usr/lib/python3/dist-packages/urwid/container.py", line 1089, in render
    body = self.body.render((maxcol, maxrow-ftrim-htrim),
  File "/home/kbingham/iob/alot/alot/buffers/buffer.py", line 19, in render
    return self.body.render(size, focus)
  File "/usr/lib/python3/dist-packages/urwid/widget.py", line 145, in cached_render
    canv = fn(self, size, focus=focus)
  File "/usr/lib/python3/dist-packages/urwid/listbox.py", line 439, in render
    middle, top, bottom = self.calculate_visible(
  File "/usr/lib/python3/dist-packages/urwid/listbox.py", line 325, in calculate_visible
    focus_widget, focus_pos = self._body.get_focus()
  File "/home/kbingham/iob/alot/alot/walker.py", line 39, in get_focus
    return self._get_at_pos(self.focus)
  File "/home/kbingham/iob/alot/alot/walker.py", line 72, in _get_at_pos
    widget = self._get_next_item()
  File "/home/kbingham/iob/alot/alot/walker.py", line 85, in _get_next_item
    next_widget = self.containerclass(next_obj, **self.kwargs)
  File "/home/kbingham/iob/alot/alot/widgets/search.py", line 26, in __init__
    self.rebuild()
  File "/home/kbingham/iob/alot/alot/widgets/search.py", line 32, in rebuild
    self.thread = self.dbman.get_thread(self.tid)
  File "/home/kbingham/iob/alot/alot/db/manager.py", line 287, in get_thread
    return Thread(self, thread)
  File "/home/kbingham/iob/alot/alot/db/thread.py", line 31, in __init__
    self.refresh(thread)
  File "/home/kbingham/iob/alot/alot/db/thread.py", line 39, in refresh
    self._refresh(thread)
  File "/home/kbingham/iob/alot/alot/db/thread.py", line 50, in _refresh
    first_msg = list(thread.get_toplevel_messages())[0]
AttributeError: 'Thread' object has no attribute 'get_toplevel_messages'
make: *** [Makefile:2: run] Error 1
kbingham commented 2 years ago
(Pdb) list
 48             elif subject_type == 'oldest':
 49                 try:
 50  >>                 first_msg = list(thread.get_toplevel_messages())[0]
 51                     subject = first_msg.get_header('subject')
 52                 except IndexError:
 53  ->                 subject = ''
 54             self._subject = subject
 55     
 56             self._authors = None
 57             ts = thread.first
 58     

As far as I can tell the first_msg = list(thread.get_toplevel_messages())[0] may be a left over that hasn't yet been ported to the new notmuch2 bindings. I tried making it call self.get_toplevel_messages() - but that fails.

More investigation needed.

mmartin commented 2 years ago

This seems to fix it:

--- a/alot/db/thread.py
+++ b/alot/db/thread.py
@@ -47,8 +47,8 @@ class Thread:
             subject = thread.subject
         elif subject_type == 'oldest':
             try:
-                first_msg = list(thread.get_toplevel_messages())[0]
-                subject = first_msg.get_header('subject')
+                first_msg = list(thread.toplevel())[0]
+                subject = first_msg.header('subject')
             except IndexError:
                 subject = ''
         self._subject = subject
kbingham commented 2 years ago

Awesome thanks for the guidance. Is there documentation for the notmuch2 bindings? I could only see that they were from cffi so auto-generated ...

kbingham commented 2 years ago

Thanks - that's confirmed working here. Now spotted more behaviour changes on master but those are certainly separate.

@mmartin Will you submit that as PR/Patch? or would you prefer I do it, and if so - how would you like your 'Suggested-by: <>' tag to appear for credit if I do it...

mmartin commented 2 years ago

@kbingham Go ahead and you do it, no need for “Suggested-by” tag.

kbingham commented 2 years ago

Aha - the notmuch2 bindings are documented as the notmuch bindings ;-) That's why I couldn't find them. I was looking for something specific as 'notmuch2' but they're now just the expected notmuch python bindings!

https://notmuchmail.org/doc/latest/python-bindings.html

So we have

PR submitted at https://github.com/pazz/alot/pull/1591

kbingham commented 2 years ago

Fixed with #1591