visidata icon indicating copy to clipboard operation
visidata copied to clipboard

[bug Python3.9] "AttributeError: 'LazyChainMap' object has no attribute 'get'" when entering pdb++ breakpoint.

Open jasonwirth opened this issue 2 years ago • 7 comments

Small description Entering a breakpoint (space breakpoint) throws AttributeError: 'LazyChainMap' object has no attribute 'get'.

Expected result Enter the debugger / pdb.

Actual result with screenshot Screen Shot 2022-03-06 at 9 53 52 PM

error_LazyChainMap_has_no_attribute_get.txt

Traceback (most recent call last):
  File "/Users/jasonwirth/code/visidata/visidata/basesheet.py", line 170, in execCommand
    escaped = super().execCommand2(cmd, vdglobals=vdglobals)
  File "/Users/jasonwirth/code/visidata/visidata/basesheet.py", line 72, in execCommand2
    exec(code, vdglobals, LazyChainMap(vd, self))
  File "breakpoint", line 1, in <module>
  File "/Users/jasonwirth/code/visidata/visidata/editor.py", line 88, in _breakpoint
    VisiDataPdb(nosigint=True).set_trace()
  File "/Users/jasonwirth/miniconda3/envs/visidata/lib/python3.9/bdb.py", line 92, in trace_dispatch
    return self.dispatch_return(frame, arg)
  File "/Users/jasonwirth/miniconda3/envs/visidata/lib/python3.9/bdb.py", line 151, in dispatch_return
    self.user_return(frame, arg)
  File "/Users/jasonwirth/miniconda3/envs/visidata/lib/python3.9/pdb.py", line 294, in user_return
    self.interaction(frame, None)
  File "/Users/jasonwirth/miniconda3/envs/visidata/lib/python3.9/site-packages/pdb.py", line 216, in interaction
    ret = self.setup(frame, traceback)
  File "/Users/jasonwirth/miniconda3/envs/visidata/lib/python3.9/site-packages/pdb.py", line 259, in setup
    ret = super(Pdb, self).setup(frame, tb)
  File "/Users/jasonwirth/miniconda3/envs/visidata/lib/python3.9/pdb.py", line 209, in setup
    self.stack, self.curindex = self.get_stack(f, tb)
  File "/Users/jasonwirth/miniconda3/envs/visidata/lib/python3.9/site-packages/pdb.py", line 290, in get_stack
    return self.compute_stack(fullstack, idx)
  File "/Users/jasonwirth/miniconda3/envs/visidata/lib/python3.9/site-packages/pdb.py", line 301, in compute_stack
    if self._is_hidden(frame):
  File "/Users/jasonwirth/miniconda3/envs/visidata/lib/python3.9/site-packages/pdb.py", line 282, in _is_hidden
    if frame.f_locals.get('__tracebackhide__') \
AttributeError: 'LazyChainMap' object has no attribute 'get'

Steps to reproduce with sample data and a . enter-breakpoint.vd.txt vd

sheet	col	row	longname	input	keystrokes	comment
			open-file	sample_data/countries	o	
countries		0	breakpoint			drop into pdb

Additional context

saul.pw/VisiData v2.9dev

jasonwirth avatar Mar 07 '22 04:03 jasonwirth

The fix seems somewhat trivial, add LazyChainMap.get method.

    def get(self, key, default=None, /):
        return self.objs.get(key, default=default)

However the object also maintains a locals dictionary. I'm not sure if there is a particular order, e.g. check objs first then check locals?

    def get(self, key, default=None, /):
        if key in self.objs:
            return self.objs[key]
        return self.locals.get(key, default=default)

jasonwirth avatar Mar 07 '22 04:03 jasonwirth

@jasonwirth, I actually cannot reproduce this on the develop branch. Are you able to enter the debugger at all? Do you type something into it that triggers this exception?

anjakefala avatar Mar 08 '22 05:03 anjakefala

Oh, this might be a Python version thing! I see you are using Python 3.9, which I am not!

anjakefala avatar Mar 08 '22 05:03 anjakefala

Update I still cannot reproduce this with Python3.9. Waiting on more information or until I take the time to ensure my 3.9 environment is isolated.

anjakefala avatar Mar 08 '22 05:03 anjakefala

I ran into this a while back too. It depended on my config and/or what I was doing in though debugger though - one reliable way to reproduce it was pip installing pdb++ and then triggering a breakpoint(). pdb++ checked local variables right away where pdb on its own didn't.

I started working on a fix in #589 but it was wrong in a few ways (handy comments from @saulpw in there!). It was fairly low priority for me and didn't seem to affect anyone else so I kinda left it hanging :grimacing: . @jasonwirth's approach sounds simpler though - fix the immediate ouch :).

ajkerrigan avatar Mar 08 '22 05:03 ajkerrigan

I did some quick adhoc testing using py3.8. I think the bug is in pdb++, as @ajkerrigan suggested. Dropping into a regular pdb debugger works, but pdb++ gets the error with both 3.8 and 3.9.

Edit: I've tried a variety of things, manually setting breakpoints, using VS Code debugger, etc. I came across this #558 issue on how to debug VD which links to @ajkerrigan page on debugging. Those docs and and CTRL+E to get the stacktrace has been very helpful.

jasonwirth avatar Mar 09 '22 16:03 jasonwirth

Thanks everyone for investigating this! @jasonwirth's solution is good, though I think the locals should be used before objs, if the key is available, because any locals in e.g. a generator expression should be "more local" than the column values. Can you put together a PR?

saulpw avatar Mar 16 '22 04:03 saulpw