Repository: holoviz/panel

Issue:
Perspective raises error when trying to filter: ValueError: too many values to unpack (expected 3)
Panel: 0.11.3

When trying to filter by dragging a field the `Perspective` Viewer raises an error.

https://user-images.githubusercontent.com/42288570/117548407-21b1fc80-b035-11eb-9c64-deb88acce924.mp4

```python
import panel as pn
import pandas as pd

pn.extension("perspective", sizing_mode="stretch_width")

data = pd.DataFrame({
    "Curve": list(range(0,1000)),
    "Other": list(range(0,1000)),
    })
pn.pane.Perspective(data).servable()
```

```bash
$ panel serve 'examples\issue_perspective.py' --auto --show
2021-05-08 19:36:33,523 Starting Bokeh server version 2.3.1 (running on Tornado 6.1)
2021-05-08 19:36:33,525 User authentication hooks NOT provided (default user enabled)
2021-05-08 19:36:33,526 Bokeh app running at: http://localhost:5006/issue_perspective
2021-05-08 19:36:33,526 Starting Bokeh server with process id: 20144
2021-05-08 19:36:35,000 WebSocket connection opened
2021-05-08 19:36:35,001 ServerConnection created
2021-05-08 19:37:24,096 Exception in callback functools.partial(<bound method IOLoop._discard_future_result of <tornado.platform.asyncio.AsyncIOMainLoop object at 0x0000015F24436130>>, <Task finished name='Task-174' coro=<_needs_document_lock.<locals>._needs_document_lock_wrapper() done, defined at c:\repos\private\panel_docker\panel\.venv\lib\site-packages\bokeh\server\session.py:51> exception=ValueError('too many values to unpack 
(expected 3)')>)
Traceback (most recent call last):
  File "c:\repos\private\panel_docker\panel\.venv\lib\site-packages\tornado\ioloop.py", line 741, in _run_callback
    ret = callback()
  File "c:\repos\private\panel_docker\panel\.venv\lib\site-packages\tornado\ioloop.py", line 765, in _discard_future_result
    future.result()
  File "c:\repos\private\panel_docker\panel\.venv\lib\site-packages\bokeh\server\session.py", line 71, in _needs_document_lock_wrapper
    result = await result
  File "c:\repos\private\panel_docker\panel\.venv\lib\site-packages\tornado\gen.py", line 216, in wrapper
    result = ctx_run(func, *args, **kwargs)
  File "c:\repos\private\panel_docker\panel\panel\reactive.py", line 257, in _change_coroutine
    self._change_event(doc)
  File "c:\repos\private\panel_docker\panel\panel\reactive.py", line 267, in _change_event
    self._process_events(events)
  File "c:\repos\private\panel_docker\panel\panel\reactive.py", line 943, in _process_events
    super(ReactiveData, self)._process_events(events)
  File "c:\repos\private\panel_docker\panel\panel\reactive.py", line 250, in _process_events
    self.param.set_param(**self._process_property_change(events))
  File "c:\repos\private\panel_docker\panel\panel\pane\perspective.py", line 396, in _process_property_change
    msg['filters'] = [[self._as_digit(col), e, val] for col, e, val in msg['filters']]
  File "c:\repos\private\panel_docker\panel\panel\pane\perspective.py", line 396, in <listcomp>
    msg['filters'] = [[self._as_digit(col), e, val] for col, e, val in msg['filters']]
ValueError: too many values to unpack (expected 3)
```


Discussion:
It's the same problem with `sort`.

Resolving patch:
diff --git a/panel/pane/perspective.py b/panel/pane/perspective.py
--- a/panel/pane/perspective.py
+++ b/panel/pane/perspective.py
@@ -391,9 +391,9 @@ def _process_property_change(self, msg):
             if msg.get(prop):
                 msg[prop] = [self._as_digit(col) for col in msg[prop]]
         if msg.get('sort'):
-            msg['sort'] = [[self._as_digit(col), d] for col, d in msg['sort']]
+            msg['sort'] = [[self._as_digit(col), *args] for col, *args in msg['sort']]
         if msg.get('filters'):
-            msg['filters'] = [[self._as_digit(col), e, val] for col, e, val in msg['filters']]
+            msg['filters'] = [[self._as_digit(col), *args] for col, *args in msg['filters']]
         if msg.get('aggregates'):
             msg['aggregates'] = {self._as_digit(col): agg for col, agg in msg['aggregates'].items()}
         return msg


Test patch:
diff --git a/panel/tests/pane/test_perspective.py b/panel/tests/pane/test_perspective.py
--- a/panel/tests/pane/test_perspective.py
+++ b/panel/tests/pane/test_perspective.py
@@ -26,7 +26,7 @@ def test_perspective_int_cols():
     assert model.sort == [['0', 'desc']]
 
     psp2 = Perspective(data)
-    
+
     psp2._process_events({
         'columns': ['0'],
         'row_pivots': ['0'],
@@ -42,3 +42,36 @@ def test_perspective_int_cols():
     assert psp2.aggregates == {0: 'mean'}
     assert psp2.sort == [[0, 'desc']]
     assert psp2.filters == [[0, '==', 'None']]
+
+def test_perspective_can_drag_to_filter():
+    # Given
+    msg = {'filters': [['Curve', '==', None, 'integer', 'sum']]}
+    # When
+    actual = Perspective()._process_property_change(msg)
+    # Then
+    assert actual == msg
+
+def test_perspective_can_filter_to_value():
+    # Given
+    msg = {'filters': [['Curve', '==', 4]]}
+    # When
+    actual = Perspective()._process_property_change(msg)
+    # Then
+    assert actual == msg
+
+def test_perspective_can_drag_to_sort():
+    # Given
+    msg = {'sort': [['Curve']]}
+    # When
+    actual = Perspective()._process_property_change(msg)
+    # Then
+    assert actual == msg
+
+def test_perspective_can_sort_desc():
+    # Given
+    msg = {'sort': [['Curve', 'desc']]}
+    # When
+    actual = Perspective()._process_property_change(msg)
+    # Then
+    assert actual == msg
+