We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Not specifying an `on_select` callback for Table leads to a TypeError
**Describe the bug**
If you leave out a `on_select` callable on `Table` and click a row, you get a traceback in the terminal:
```python
Traceback (most recent call last):
  File "C:\\Users\\brcan\\Desktop\\snippets\\.venv\\lib\\site-packages\\toga_winforms\\widgets\\table.py", line 74, in _native_item_selection_changed
    self.interface.on_select(self.interface, row=self.interface.data[e.ItemIndex])
TypeError : 'NoneType' object is not callable
```

**To Reproduce**
Steps to reproduce the behavior:
1. Go to https://toga.readthedocs.io/en/latest/tutorial/tutorial-2.html
2. Run the example
3. Click on any row of the table
4. See error

**Expected behavior**
No error.

**Environment:**
 - Operating System: Windows 10
 - Python version: CPython 3.8.3
 - Software versions:
   - Briefcase:
   - Toga: 0.3.0dev22
   - ...


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `src/winforms/toga_winforms/widgets/table.py`
Content:
```
1 from travertino.size import at_least
2 
3 from toga_winforms.libs import WinForms
4 
5 from .base import Widget
6 
7 
8 class Table(Widget):
9     def create(self):
10         self._container = self
11         self.native = WinForms.ListView()
12         self.native.View = WinForms.View.Details
13         self._cache = []
14         self._first_item = 0
15 
16         dataColumn = []
17         for i, (heading, accessor) in enumerate(zip(
18                     self.interface.headings,
19                     self.interface._accessors
20                 )):
21             dataColumn.append(self._create_column(heading, accessor))
22 
23         self.native.FullRowSelect = True
24         self.native.MultiSelect = self.interface.multiple_select
25         self.native.DoubleBuffered = True
26         self.native.VirtualMode = True
27         self.native.Columns.AddRange(dataColumn)
28 
29         self.native.ItemSelectionChanged += self._native_item_selection_changed
30         self.native.RetrieveVirtualItem += self._native_retrieve_virtual_item
31         self.native.CacheVirtualItems += self._native_cache_virtual_items
32         self.native.VirtualItemsSelectionRangeChanged += self._native_virtual_item_selection_range_changed
33 
34     def _native_virtual_item_selection_range_changed(self, sender, e):
35         # update selection interface property
36         self.interface._selection = self._selected_rows()
37 
38         # `Shift` key or Range selection handler
39         if e.IsSelected and self.interface.multiple_select and self.interface.on_select:
40             # call on select with the last row of the multi selection
41             selected = self.interface.data[e.EndIndex]
42             self.interface.on_select(self.interface, row=selected)
43 
44     def _native_retrieve_virtual_item(self, sender, e):
45         # Because ListView is in VirtualMode, it's necessary implement
46         # VirtualItemsSelectionRangeChanged event to create ListViewItem when it's needed
47         if self._cache and e.ItemIndex >= self._first_item and \
48            e.ItemIndex < self._first_item + len(self._cache):
49             e.Item = self._cache[e.ItemIndex - self._first_item]
50         else:
51             e.Item = WinForms.ListViewItem(self.row_data(self.interface.data[e.ItemIndex]))
52 
53     def _native_cache_virtual_items(self, sender, e):
54         if self._cache and e.StartIndex >= self._first_item and \
55            e.EndIndex <= self._first_item + len(self._cache):
56             # If the newly requested cache is a subset of the old cache,
57             # no need to rebuild everything, so do nothing
58             return
59 
60         # Now we need to rebuild the cache.
61         self._first_item = e.StartIndex
62         new_length = e.EndIndex - e.StartIndex + 1
63         self._cache = []
64 
65         # Fill the cache with the appropriate ListViewItems.
66         for i in range(new_length):
67             self._cache.append(WinForms.ListViewItem(self.row_data(self.interface.data[i])))
68 
69     def _native_item_selection_changed(self, sender, e):
70         # update selection interface property
71         self.interface._selection = self._selected_rows()
72 
73         if e.IsSelected:
74             self.interface.on_select(self.interface, row=self.interface.data[e.ItemIndex])
75 
76     def _selected_rows(self):
77         if not self.native.SelectedIndices.Count:
78             return None
79 
80         if self.interface.multiple_select:
81             selected = [row for i, row in enumerate(self.interface.data) if i in self.native.SelectedIndices]
82             return selected
83         else:
84             return self.interface.data[self.native.SelectedIndices[0]]
85 
86     def _create_column(self, heading, accessor):
87         col = WinForms.ColumnHeader()
88         col.Text = heading
89         col.Name = accessor
90         return col
91 
92     def change_source(self, source):
93         self.update_data()
94 
95     def row_data(self, item):
96         # TODO: Winforms can't support icons in tree cells; so, if the data source
97         # specifies an icon, strip it when converting to row data.
98         def strip_icon(item, attr):
99             val = getattr(item, attr, self.interface.missing_value)
100 
101             if isinstance(val, tuple):
102                 return str(val[1])
103             return str(val)
104 
105         return [
106             strip_icon(item, attr)
107             for attr in self.interface._accessors
108         ]
109 
110     def update_data(self):
111         self.native.VirtualListSize = len(self.interface.data)
112         self._cache = []
113 
114     def insert(self, index, item):
115         self.update_data()
116 
117     def change(self, item):
118         self.interface.factory.not_implemented('Table.change()')
119 
120     def remove(self, item):
121         self.update_data()
122 
123     def clear(self):
124         self.update_data()
125 
126     def set_on_select(self, handler):
127         pass
128 
129     def scroll_to_row(self, row):
130         self.native.EnsureVisible(row)
131 
132     def rehint(self):
133         self.interface.intrinsic.width = at_least(self.interface.MIN_WIDTH)
134         self.interface.intrinsic.height = at_least(self.interface.MIN_HEIGHT)
135 
136     def remove_column(self, accessor):
137         self.native.Columns.RemoveByKey(accessor)
138 
139     def add_column(self, heading, accessor):
140         self.native.Columns.Add(self._create_column(heading, accessor))
141         self.update_data()
142
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/src/winforms/toga_winforms/widgets/table.py b/src/winforms/toga_winforms/widgets/table.py
--- a/src/winforms/toga_winforms/widgets/table.py
+++ b/src/winforms/toga_winforms/widgets/table.py
@@ -70,7 +70,7 @@
         # update selection interface property
         self.interface._selection = self._selected_rows()
 
-        if e.IsSelected:
+        if e.IsSelected and self.interface.on_select:
             self.interface.on_select(self.interface, row=self.interface.data[e.ItemIndex])
 
     def _selected_rows(self):

{"golden_diff": "diff --git a/src/winforms/toga_winforms/widgets/table.py b/src/winforms/toga_winforms/widgets/table.py\n--- a/src/winforms/toga_winforms/widgets/table.py\n+++ b/src/winforms/toga_winforms/widgets/table.py\n@@ -70,7 +70,7 @@\n         # update selection interface property\n         self.interface._selection = self._selected_rows()\n \n-        if e.IsSelected:\n+        if e.IsSelected and self.interface.on_select:\n             self.interface.on_select(self.interface, row=self.interface.data[e.ItemIndex])\n \n     def _selected_rows(self):\n", "issue": "Not specifying an `on_select` callback for Table leads to a TypeError\n**Describe the bug**\r\nIf you leave out a `on_select` callable on `Table` and click a row, you get a traceback in the terminal:\r\n```python\r\nTraceback (most recent call last):\r\n  File \"C:\\\\Users\\\\brcan\\\\Desktop\\\\snippets\\\\.venv\\\\lib\\\\site-packages\\\\toga_winforms\\\\widgets\\\\table.py\", line 74, in _native_item_selection_changed\r\n    self.interface.on_select(self.interface, row=self.interface.data[e.ItemIndex])\r\nTypeError : 'NoneType' object is not callable\r\n```\r\n\r\n**To Reproduce**\r\nSteps to reproduce the behavior:\r\n1. Go to https://toga.readthedocs.io/en/latest/tutorial/tutorial-2.html\r\n2. Run the example\r\n3. Click on any row of the table\r\n4. See error\r\n\r\n**Expected behavior**\r\nNo error.\r\n\r\n**Environment:**\r\n - Operating System: Windows 10\r\n - Python version: CPython 3.8.3\r\n - Software versions:\r\n   - Briefcase:\r\n   - Toga: 0.3.0dev22\r\n   - ...\r\n\n", "before_files": [{"content": "from travertino.size import at_least\n\nfrom toga_winforms.libs import WinForms\n\nfrom .base import Widget\n\n\nclass Table(Widget):\n    def create(self):\n        self._container = self\n        self.native = WinForms.ListView()\n        self.native.View = WinForms.View.Details\n        self._cache = []\n        self._first_item = 0\n\n        dataColumn = []\n        for i, (heading, accessor) in enumerate(zip(\n                    self.interface.headings,\n                    self.interface._accessors\n                )):\n            dataColumn.append(self._create_column(heading, accessor))\n\n        self.native.FullRowSelect = True\n        self.native.MultiSelect = self.interface.multiple_select\n        self.native.DoubleBuffered = True\n        self.native.VirtualMode = True\n        self.native.Columns.AddRange(dataColumn)\n\n        self.native.ItemSelectionChanged += self._native_item_selection_changed\n        self.native.RetrieveVirtualItem += self._native_retrieve_virtual_item\n        self.native.CacheVirtualItems += self._native_cache_virtual_items\n        self.native.VirtualItemsSelectionRangeChanged += self._native_virtual_item_selection_range_changed\n\n    def _native_virtual_item_selection_range_changed(self, sender, e):\n        # update selection interface property\n        self.interface._selection = self._selected_rows()\n\n        # `Shift` key or Range selection handler\n        if e.IsSelected and self.interface.multiple_select and self.interface.on_select:\n            # call on select with the last row of the multi selection\n            selected = self.interface.data[e.EndIndex]\n            self.interface.on_select(self.interface, row=selected)\n\n    def _native_retrieve_virtual_item(self, sender, e):\n        # Because ListView is in VirtualMode, it's necessary implement\n        # VirtualItemsSelectionRangeChanged event to create ListViewItem when it's needed\n        if self._cache and e.ItemIndex >= self._first_item and \\\n           e.ItemIndex < self._first_item + len(self._cache):\n            e.Item = self._cache[e.ItemIndex - self._first_item]\n        else:\n            e.Item = WinForms.ListViewItem(self.row_data(self.interface.data[e.ItemIndex]))\n\n    def _native_cache_virtual_items(self, sender, e):\n        if self._cache and e.StartIndex >= self._first_item and \\\n           e.EndIndex <= self._first_item + len(self._cache):\n            # If the newly requested cache is a subset of the old cache,\n            # no need to rebuild everything, so do nothing\n            return\n\n        # Now we need to rebuild the cache.\n        self._first_item = e.StartIndex\n        new_length = e.EndIndex - e.StartIndex + 1\n        self._cache = []\n\n        # Fill the cache with the appropriate ListViewItems.\n        for i in range(new_length):\n            self._cache.append(WinForms.ListViewItem(self.row_data(self.interface.data[i])))\n\n    def _native_item_selection_changed(self, sender, e):\n        # update selection interface property\n        self.interface._selection = self._selected_rows()\n\n        if e.IsSelected:\n            self.interface.on_select(self.interface, row=self.interface.data[e.ItemIndex])\n\n    def _selected_rows(self):\n        if not self.native.SelectedIndices.Count:\n            return None\n\n        if self.interface.multiple_select:\n            selected = [row for i, row in enumerate(self.interface.data) if i in self.native.SelectedIndices]\n            return selected\n        else:\n            return self.interface.data[self.native.SelectedIndices[0]]\n\n    def _create_column(self, heading, accessor):\n        col = WinForms.ColumnHeader()\n        col.Text = heading\n        col.Name = accessor\n        return col\n\n    def change_source(self, source):\n        self.update_data()\n\n    def row_data(self, item):\n        # TODO: Winforms can't support icons in tree cells; so, if the data source\n        # specifies an icon, strip it when converting to row data.\n        def strip_icon(item, attr):\n            val = getattr(item, attr, self.interface.missing_value)\n\n            if isinstance(val, tuple):\n                return str(val[1])\n            return str(val)\n\n        return [\n            strip_icon(item, attr)\n            for attr in self.interface._accessors\n        ]\n\n    def update_data(self):\n        self.native.VirtualListSize = len(self.interface.data)\n        self._cache = []\n\n    def insert(self, index, item):\n        self.update_data()\n\n    def change(self, item):\n        self.interface.factory.not_implemented('Table.change()')\n\n    def remove(self, item):\n        self.update_data()\n\n    def clear(self):\n        self.update_data()\n\n    def set_on_select(self, handler):\n        pass\n\n    def scroll_to_row(self, row):\n        self.native.EnsureVisible(row)\n\n    def rehint(self):\n        self.interface.intrinsic.width = at_least(self.interface.MIN_WIDTH)\n        self.interface.intrinsic.height = at_least(self.interface.MIN_HEIGHT)\n\n    def remove_column(self, accessor):\n        self.native.Columns.RemoveByKey(accessor)\n\n    def add_column(self, heading, accessor):\n        self.native.Columns.Add(self._create_column(heading, accessor))\n        self.update_data()\n", "path": "src/winforms/toga_winforms/widgets/table.py"}], "after_files": [{"content": "from travertino.size import at_least\n\nfrom toga_winforms.libs import WinForms\n\nfrom .base import Widget\n\n\nclass Table(Widget):\n    def create(self):\n        self._container = self\n        self.native = WinForms.ListView()\n        self.native.View = WinForms.View.Details\n        self._cache = []\n        self._first_item = 0\n\n        dataColumn = []\n        for i, (heading, accessor) in enumerate(zip(\n                    self.interface.headings,\n                    self.interface._accessors\n                )):\n            dataColumn.append(self._create_column(heading, accessor))\n\n        self.native.FullRowSelect = True\n        self.native.MultiSelect = self.interface.multiple_select\n        self.native.DoubleBuffered = True\n        self.native.VirtualMode = True\n        self.native.Columns.AddRange(dataColumn)\n\n        self.native.ItemSelectionChanged += self._native_item_selection_changed\n        self.native.RetrieveVirtualItem += self._native_retrieve_virtual_item\n        self.native.CacheVirtualItems += self._native_cache_virtual_items\n        self.native.VirtualItemsSelectionRangeChanged += self._native_virtual_item_selection_range_changed\n\n    def _native_virtual_item_selection_range_changed(self, sender, e):\n        # update selection interface property\n        self.interface._selection = self._selected_rows()\n\n        # `Shift` key or Range selection handler\n        if e.IsSelected and self.interface.multiple_select and self.interface.on_select:\n            # call on select with the last row of the multi selection\n            selected = self.interface.data[e.EndIndex]\n            self.interface.on_select(self.interface, row=selected)\n\n    def _native_retrieve_virtual_item(self, sender, e):\n        # Because ListView is in VirtualMode, it's necessary implement\n        # VirtualItemsSelectionRangeChanged event to create ListViewItem when it's needed\n        if self._cache and e.ItemIndex >= self._first_item and \\\n           e.ItemIndex < self._first_item + len(self._cache):\n            e.Item = self._cache[e.ItemIndex - self._first_item]\n        else:\n            e.Item = WinForms.ListViewItem(self.row_data(self.interface.data[e.ItemIndex]))\n\n    def _native_cache_virtual_items(self, sender, e):\n        if self._cache and e.StartIndex >= self._first_item and \\\n           e.EndIndex <= self._first_item + len(self._cache):\n            # If the newly requested cache is a subset of the old cache,\n            # no need to rebuild everything, so do nothing\n            return\n\n        # Now we need to rebuild the cache.\n        self._first_item = e.StartIndex\n        new_length = e.EndIndex - e.StartIndex + 1\n        self._cache = []\n\n        # Fill the cache with the appropriate ListViewItems.\n        for i in range(new_length):\n            self._cache.append(WinForms.ListViewItem(self.row_data(self.interface.data[i])))\n\n    def _native_item_selection_changed(self, sender, e):\n        # update selection interface property\n        self.interface._selection = self._selected_rows()\n\n        if e.IsSelected and self.interface.on_select:\n            self.interface.on_select(self.interface, row=self.interface.data[e.ItemIndex])\n\n    def _selected_rows(self):\n        if not self.native.SelectedIndices.Count:\n            return None\n\n        if self.interface.multiple_select:\n            selected = [row for i, row in enumerate(self.interface.data) if i in self.native.SelectedIndices]\n            return selected\n        else:\n            return self.interface.data[self.native.SelectedIndices[0]]\n\n    def _create_column(self, heading, accessor):\n        col = WinForms.ColumnHeader()\n        col.Text = heading\n        col.Name = accessor\n        return col\n\n    def change_source(self, source):\n        self.update_data()\n\n    def row_data(self, item):\n        # TODO: Winforms can't support icons in tree cells; so, if the data source\n        # specifies an icon, strip it when converting to row data.\n        def strip_icon(item, attr):\n            val = getattr(item, attr, self.interface.missing_value)\n\n            if isinstance(val, tuple):\n                return str(val[1])\n            return str(val)\n\n        return [\n            strip_icon(item, attr)\n            for attr in self.interface._accessors\n        ]\n\n    def update_data(self):\n        self.native.VirtualListSize = len(self.interface.data)\n        self._cache = []\n\n    def insert(self, index, item):\n        self.update_data()\n\n    def change(self, item):\n        self.interface.factory.not_implemented('Table.change()')\n\n    def remove(self, item):\n        self.update_data()\n\n    def clear(self):\n        self.update_data()\n\n    def set_on_select(self, handler):\n        pass\n\n    def scroll_to_row(self, row):\n        self.native.EnsureVisible(row)\n\n    def rehint(self):\n        self.interface.intrinsic.width = at_least(self.interface.MIN_WIDTH)\n        self.interface.intrinsic.height = at_least(self.interface.MIN_HEIGHT)\n\n    def remove_column(self, accessor):\n        self.native.Columns.RemoveByKey(accessor)\n\n    def add_column(self, heading, accessor):\n        self.native.Columns.Add(self._create_column(heading, accessor))\n        self.update_data()\n", "path": "src/winforms/toga_winforms/widgets/table.py"}]}