saulpw / visidata

A terminal spreadsheet multitool for discovering and arranging data
http://visidata.org
GNU General Public License v3.0
7.8k stars 276 forks source link

Unexpected behavior when unfurling an exception-value #1171

Closed jsvine closed 2 years ago

jsvine commented 2 years ago

Small description

This one's slightly arcane. If you unfurl a column that contains a exception/error, VisiData repeats the unfurled values of the previous row instead of [insert some null-like behavior]. Taking a concrete example, take the JSON file in this ZIP: test.zip

... whose Sheet representation is such:

id#| text ║
 1 | abc  ║
 2 |     ⌀║
 3 | de   ║

Then create a new column, such that it generates a cell with an error in it (because None has no .strip() method):

id#| text | list(text.strip()) ║
 1 | abc  | [3]                ║
 2 |     ⌀|                   !║
 3 | de   | [2]                ║

Now navigate to that new column and run unfurl-col ...

Expected result

I would have expected something like this (or without the id:2 row entirely if options.unfurl_empty is False):

id#| text | list(text.strip())…| list(text.strip())_value ║
 1 | abc  | 0                 #| a                        ║
 1 | abc  | 1                 #| b                        ║
 1 | abc  | 2                 #| c                        ║
 2 |     ⌀| 0                 #|                         !║
 3 | de   | 0                 #| d                        ║
 3 | de   | 1                 #| e                        ║

Actual result with screenshot

But instead, you get this:

id#| text | list(text.strip())…| list(text.strip())_value ║
 1 | abc  | 0                 #| a                        ║
 1 | abc  | 1                 #| b                        ║
 1 | abc  | 2                 #| c                        ║
 2 |     ⌀| 0                 #| a                        ║
 2 |     ⌀| 1                 #| b                        ║
 2 |     ⌀| 2                 #| c                        ║
 3 | de   | 0                 #| d                        ║
 3 | de   | 1                 #| e                        ║

... plus the following stacktrace:

Traceback (most recent call last):
  File "src/visidata/visidata/unfurl.py", line 36, in reload
    val = self.source_col.getValue(row)
  File "src/visidata/visidata/column.py", line 273, in getValue
    return self.calcValue(row)
  File "src/visidata/visidata/column.py", line 528, in calcValue
    r = self.sheet.evalExpr(self.compiledExpr, row, col=self)
  File "src/visidata/visidata/sheets.py", line 362, in evalExpr
    return eval(expr, vd.getGlobals(), contexts)
  File "Downloads/<expr>", line 1, in <module>
AttributeError: 'TypedWrapper' object has no attribute 'strip'

I think the issue may be that there's a missing continue at the end of this bit of except-block, but I might be wrong about that:

https://github.com/saulpw/visidata/blob/dc8cef4980bdef07fd3640be8c92b9e3dc8be9dc/visidata/unfurl.py#L37-L44

Steps to reproduce with sample data and a .vd

See test.vd in ZIP file above.

Additional context

visidata-2.7.dev / d655caf44295c3c95af397206a46f1f637681367

anjakefala commented 2 years ago

Thanks @jsvine! You were right about the cause. I pushed the fix to develop, and added tests. =)