Repository: holoviz/panel

Issue:
UnsetValueError when setting the DatePicker value
Starting from a `DatePicker` which doesn't have a defined `value`, then setting its `value` to an actual date (click on the button in the example) raises a Bokeh `UnsetValueError`.

```python
import datetime
import panel as pn

pn.extension()

today = datetime.date.today()

w = pn.widgets.DatePicker()

def cb(e):
    w.value = today

b = pn.widgets.Button(name='set')
b.on_click(cb)

pn.Column(b, w).servable()
```

Traceback:
```
2022-05-12 20:19:23,572 error handling message
 message: Message 'PATCH-DOC' content: {'events': [{'kind': 'MessageSent', 'msg_type': 'bokeh_event', 'msg_data': {'event_name': 'button_click', 'event_values': {}}}], 'references': []} 
 error: UnsetValueError("DatePicker(id='1025', ...).value doesn't have a value set")
Traceback (most recent call last):
  File "/Users/mliquet/miniconda3/envs/panel-dev38/lib/python3.8/site-packages/bokeh/server/protocol_handler.py", line 97, in handle
    work = await handler(message, connection)
  File "/Users/mliquet/miniconda3/envs/panel-dev38/lib/python3.8/site-packages/bokeh/server/session.py", line 93, in _needs_document_lock_wrapper
    result = func(self, *args, **kwargs)
  File "/Users/mliquet/miniconda3/envs/panel-dev38/lib/python3.8/site-packages/bokeh/server/session.py", line 287, in _handle_patch
    message.apply_to_document(self.document, self)
  File "/Users/mliquet/miniconda3/envs/panel-dev38/lib/python3.8/site-packages/bokeh/protocol/messages/patch_doc.py", line 115, in apply_to_document
    invoke_with_curdoc(doc, lambda: doc.apply_json_patch(self.content, setter))
  File "/Users/mliquet/miniconda3/envs/panel-dev38/lib/python3.8/site-packages/bokeh/document/callbacks.py", line 408, in invoke_with_curdoc
    return f()
  File "/Users/mliquet/miniconda3/envs/panel-dev38/lib/python3.8/site-packages/bokeh/protocol/messages/patch_doc.py", line 115, in <lambda>
    invoke_with_curdoc(doc, lambda: doc.apply_json_patch(self.content, setter))
  File "/Users/mliquet/miniconda3/envs/panel-dev38/lib/python3.8/site-packages/bokeh/document/document.py", line 391, in apply_json_patch
    DocumentPatchedEvent.handle_json(self, event_json, references, setter)
  File "/Users/mliquet/miniconda3/envs/panel-dev38/lib/python3.8/site-packages/bokeh/document/events.py", line 259, in handle_json
    handler(doc, event_json, references, setter)
  File "/Users/mliquet/miniconda3/envs/panel-dev38/lib/python3.8/site-packages/bokeh/document/events.py", line 300, in _handle_json
    cb(event_json["msg_data"])
  File "/Users/mliquet/miniconda3/envs/panel-dev38/lib/python3.8/site-packages/bokeh/document/callbacks.py", line 355, in trigger_json_event
    model._trigger_event(event)
  File "/Users/mliquet/miniconda3/envs/panel-dev38/lib/python3.8/site-packages/bokeh/util/callback_manager.py", line 119, in _trigger_event
    self.document.callbacks.notify_event(cast(Model, self), event, invoke)
  File "/Users/mliquet/miniconda3/envs/panel-dev38/lib/python3.8/site-packages/bokeh/document/callbacks.py", line 247, in notify_event
    invoke_with_curdoc(doc, callback_invoker)
  File "/Users/mliquet/miniconda3/envs/panel-dev38/lib/python3.8/site-packages/bokeh/document/callbacks.py", line 408, in invoke_with_curdoc
    return f()
  File "/Users/mliquet/miniconda3/envs/panel-dev38/lib/python3.8/site-packages/bokeh/util/callback_manager.py", line 115, in invoke
    cast(EventCallbackWithEvent, callback)(event)
  File "/Users/mliquet/work/dev/panel/panel/reactive.py", line 399, in _server_event
    self._comm_event(event)
  File "/Users/mliquet/work/dev/panel/panel/reactive.py", line 391, in _comm_event
    self._process_bokeh_event(event)
  File "/Users/mliquet/work/dev/panel/panel/reactive.py", line 338, in _process_bokeh_event
    self._process_event(event)
  File "/Users/mliquet/work/dev/panel/panel/widgets/button.py", line 136, in _process_event
    self.clicks += 1
  File "/Users/mliquet/miniconda3/envs/panel-dev38/lib/python3.8/site-packages/param/parameterized.py", line 354, in _f
    instance_param.__set__(obj, val)
  File "/Users/mliquet/miniconda3/envs/panel-dev38/lib/python3.8/site-packages/param/parameterized.py", line 356, in _f
    return f(self, obj, val)
  File "/Users/mliquet/miniconda3/envs/panel-dev38/lib/python3.8/site-packages/param/__init__.py", line 621, in __set__
    super(Dynamic,self).__set__(obj,val)
  File "/Users/mliquet/miniconda3/envs/panel-dev38/lib/python3.8/site-packages/param/parameterized.py", line 356, in _f
    return f(self, obj, val)
  File "/Users/mliquet/miniconda3/envs/panel-dev38/lib/python3.8/site-packages/param/parameterized.py", line 1231, in __set__
    obj.param._call_watcher(watcher, event)
  File "/Users/mliquet/miniconda3/envs/panel-dev38/lib/python3.8/site-packages/param/parameterized.py", line 2021, in _call_watcher
    self_._execute_watcher(watcher, (event,))
  File "/Users/mliquet/miniconda3/envs/panel-dev38/lib/python3.8/site-packages/param/parameterized.py", line 2003, in _execute_watcher
    watcher.fn(*args, **kwargs)
  File "/Users/mliquet/work/dev/panel/mltmess/issue_link_calendardate.py", line 11, in cb
    w.value = today
  File "/Users/mliquet/miniconda3/envs/panel-dev38/lib/python3.8/site-packages/param/parameterized.py", line 356, in _f
    return f(self, obj, val)
  File "/Users/mliquet/miniconda3/envs/panel-dev38/lib/python3.8/site-packages/param/__init__.py", line 621, in __set__
    super(Dynamic,self).__set__(obj,val)
  File "/Users/mliquet/miniconda3/envs/panel-dev38/lib/python3.8/site-packages/param/parameterized.py", line 356, in _f
    return f(self, obj, val)
  File "/Users/mliquet/miniconda3/envs/panel-dev38/lib/python3.8/site-packages/param/parameterized.py", line 1231, in __set__
    obj.param._call_watcher(watcher, event)
  File "/Users/mliquet/miniconda3/envs/panel-dev38/lib/python3.8/site-packages/param/parameterized.py", line 2021, in _call_watcher
    self_._execute_watcher(watcher, (event,))
  File "/Users/mliquet/miniconda3/envs/panel-dev38/lib/python3.8/site-packages/param/parameterized.py", line 2003, in _execute_watcher
    watcher.fn(*args, **kwargs)
  File "/Users/mliquet/work/dev/panel/panel/reactive.py", line 297, in _param_change
    self._apply_update(named_events, msg, model, ref)
  File "/Users/mliquet/work/dev/panel/panel/reactive.py", line 238, in _apply_update
    self._update_model(events, msg, root, model, doc, comm)
  File "/Users/mliquet/work/dev/panel/panel/reactive.py", line 250, in _update_model
    self._changing[ref] = attrs = [
  File "/Users/mliquet/work/dev/panel/panel/reactive.py", line 252, in <listcomp>
    if not model.lookup(attr).property.matches(getattr(model, attr), value)
  File "/Users/mliquet/miniconda3/envs/panel-dev38/lib/python3.8/site-packages/bokeh/core/property/descriptors.py", line 234, in __get__
    raise UnsetValueError(f"{obj}.{self.name} doesn't have a value set")
bokeh.core.property.descriptors.UnsetValueError: DatePicker(id='1025', ...).value doesn't have a value set
```


Discussion:

Resolving patch:
diff --git a/panel/reactive.py b/panel/reactive.py
--- a/panel/reactive.py
+++ b/panel/reactive.py
@@ -24,6 +24,7 @@
 import numpy as np
 import param # type: ignore
 
+from bokeh.core.property.descriptors import UnsetValueError
 from bokeh.model import DataModel
 from param.parameterized import ParameterizedMetaclass, Watcher
 
@@ -247,10 +248,16 @@ def _update_model(
         doc: 'Document', comm: Optional['Comm']
     ) -> None:
         ref = root.ref['id']
-        self._changing[ref] = attrs = [
-            attr for attr, value in msg.items()
-            if not model.lookup(attr).property.matches(getattr(model, attr), value)
-        ]
+        self._changing[ref] = attrs = []
+        for attr, value in msg.items():
+            # Bokeh raises UnsetValueError if the value is Undefined.
+            try:
+                model_val = getattr(model, attr)
+            except UnsetValueError:
+                attrs.append(attr)
+                continue
+            if not model.lookup(attr).property.matches(model_val, value):
+                attrs.append(attr)
         try:
             model.update(**msg)
         finally:


Test patch: