internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: napari/napari

Issue:
Confusing error message for `get_widget` when plugin name doesn't exist 
## Problem
The `get_widget` function raises several different errors
https://github.com/napari/napari/blob/902f5197a9e6f4752c0c673a0f4e06b01b407081/napari/plugins/_plugin_manager.py#L583

But there is no specific error if the plugin *name*  doesn't exist.
It is raise in the same case than when the widget `_dock_widget` is `null`.

https://github.com/napari/napari/blob/902f5197a9e6f4752c0c673a0f4e06b01b407081/napari/plugins/_plugin_manager.py#L637

As a result, I find the error message confusing:
https://github.com/napari/napari/blob/902f5197a9e6f4752c0c673a0f4e06b01b407081/napari/plugins/_plugin_manager.py#L619

## Step to reproduce
```python
import napari
viewer = napari.Viewer()
viewer.window.add_plugin_dock_widget(
    plugin_name="napari_bug", widget_name="Bug Report"
)
```

```python
KeyError: "Plugin 'napari_bug' does not provide any dock widgets"
```

## 📚 Documentation

I suppose there is two solutions:
- Create a specific error message when `plg_wdgs` is empty because there no
    -  dock_widget in the plugin
    - plugin
- Adapt the error message to suggest both cases




Discussion:
Thanks @ClementCaporal ! I am not sure how easy it will be to determine if the package is installed. I think your second suggestion of updating the error message to clarify that the problem is that the plugin is not installed _or_ the plugin doesn't provide a widget would be good!

Resolving patch:
diff --git a/napari/plugins/_plugin_manager.py b/napari/plugins/_plugin_manager.py
--- a/napari/plugins/_plugin_manager.py
+++ b/napari/plugins/_plugin_manager.py
@@ -606,7 +606,7 @@ def get_widget(
         Raises
         ------
         KeyError
-            If plugin `plugin_name` does not provide any widgets
+            If plugin `plugin_name` is not installed or does not provide any widgets.
         KeyError
             If plugin does not provide a widget named `widget_name`.
         ValueError
@@ -616,7 +616,7 @@ def get_widget(
         plg_wdgs = self._dock_widgets.get(plugin_name)
         if not plg_wdgs:
             msg = trans._(
-                'Plugin {plugin_name!r} does not provide any dock widgets',
+                'Plugin {plugin_name!r} is not installed or does not provide any dock widgets',
                 plugin_name=plugin_name,
                 deferred=True,
             )


Test patch:
Repository: napari/napari

Issue:
No option to select a given contribution from a plugin in 0.4.18rc2
## 🐛 Bug

In napari 0.4.18rc2 there is no option to select a specific contribution from a plugin. In our case, this is needed to load a directory one of two ways (in two coordinate systems). This was posted on zulip, and I'm raising an issue upon @Czaki's request.

## To Reproduce
In napari <= 0.4.17, I can open data using a specific reader from [brainglobe-napari-io](https://github.com/brainglobe/brainglobe-napari-io):

```python
viewer.open(file, plugin="brainglobe-napari-io.brainreg_read_dir_standard_space")
```
In napari 0.4.18rc2 this produces the error:

```bash
ValueError: There is no registered plugin named 'brainglobe-napari-io.brainreg_read_dir_standard_space'.
Names of plugins offering readers are: set()
```

## Expected behavior

For the data to be loaded with a specific reader as with previous versions. 

## Environment

<details>
  <summary>napari info</summary>
  
napari: 0.4.18rc2
Platform: Linux-5.15.0-75-generic-x86_64-with-glibc2.31
System: Ubuntu 20.04.6 LTS
Python: 3.10.11 | packaged by conda-forge | (main, May 10 2023, 18:58:44) [GCC 11.3.0]
Qt: 5.15.2
PyQt5: 5.15.9
NumPy: 1.24.3
SciPy: 1.10.1
Dask: 2023.5.1
VisPy: 0.12.2
magicgui: 0.7.2
superqt: unknown
in-n-out: 0.1.7
app-model: 0.1.4
npe2: 0.7.0

OpenGL:
- GL version: 4.6.0 NVIDIA 515.105.01
- MAX_TEXTURE_SIZE: 32768

Screens:
- screen 1: resolution 3440x1440, scale 1.0

Settings path:
- /home/adam/.config/napari/brainglobe_eaa3f9e4140a9304dcb5c8fb309cc49886dc0b64/settings.yaml
</details>

## Additional context
A workaround would be much appreciated, otherwise I think we'd need to maintain multiple plugins?



Discussion:

Resolving patch:
diff --git a/napari/plugins/_npe2.py b/napari/plugins/_npe2.py
--- a/napari/plugins/_npe2.py
+++ b/napari/plugins/_npe2.py
@@ -43,8 +43,12 @@ def read(
     """Try to return data for `path`, from reader plugins using a manifest."""
 
     # do nothing if `plugin` is not an npe2 reader
-    if plugin and plugin not in get_readers():
-        return None
+    if plugin:
+        # user might have passed 'plugin.reader_contrib' as the command
+        # so ensure we check vs. just the actual plugin name
+        plugin_name = plugin.partition('.')[0]
+        if plugin_name not in get_readers():
+            return None
 
     assert stack is not None
     # the goal here would be to make read_get_reader of npe2 aware of "stack",


Test patch:
diff --git a/napari/plugins/_tests/test_npe2.py b/napari/plugins/_tests/test_npe2.py
--- a/napari/plugins/_tests/test_npe2.py
+++ b/napari/plugins/_tests/test_npe2.py
@@ -50,6 +50,13 @@ def test_read(mock_pm: 'TestPluginManager'):
     )
     mock_pm.commands.get.assert_not_called()
 
+    mock_pm.commands.get.reset_mock()
+    _, hookimpl = _npe2.read(
+        ["some.fzzy"], stack=False, plugin='my-plugin.some_reader'
+    )
+    mock_pm.commands.get.assert_called_once_with(f'{PLUGIN_NAME}.some_reader')
+    assert hookimpl.plugin_name == PLUGIN_NAME
+
 
 @pytest.mark.skipif(
     npe2.__version__ < '0.7.0',
Repository: napari/napari

Issue:
def _show_warning(self, new_shortcut=''...) first argument is unused.
## 🧰 Task

It is a private method used only in a couple of places and this can be removed.



Discussion:

Resolving patch:
diff --git a/napari/_qt/widgets/qt_keyboard_settings.py b/napari/_qt/widgets/qt_keyboard_settings.py
--- a/napari/_qt/widgets/qt_keyboard_settings.py
+++ b/napari/_qt/widgets/qt_keyboard_settings.py
@@ -323,7 +323,7 @@ def _mark_conflicts(self, new_shortcut, row) -> bool:
                     new_shortcut=new_shortcut,
                     action_description=action.description,
                 )
-                self._show_warning(new_shortcut, action, row, message)
+                self._show_warning(row, message)
 
                 self._restore_shortcuts(row)
 
@@ -354,7 +354,7 @@ def _show_bind_shortcut_error(
             "<b>{new_shortcut}</b> is not a valid keybinding.",
             new_shortcut=new_shortcut,
         )
-        self._show_warning(new_shortcut, current_action, row, message)
+        self._show_warning(row, message)
 
         self._cleanup_warning_icons([row])
         self._restore_shortcuts(row)
@@ -473,15 +473,11 @@ def _cleanup_warning_icons(self, rows):
         for row in rows:
             self._table.setCellWidget(row, self._icon_col, QLabel(""))
 
-    def _show_warning(self, new_shortcut='', action=None, row=0, message=''):
+    def _show_warning(self, row: int, message: str) -> None:
         """Creates and displays warning message when shortcut is already assigned.
 
         Parameters
         ----------
-        new_shortcut : str
-            The new shortcut attempting to be set.
-        action : Action
-            Action that is already assigned with the shortcut.
         row : int
             Row in table where the shortcut is attempting to be set.
         message : str


Test patch:
Repository: napari/napari

Issue:
Removing comments from PR does not work
## 🐛 Bug
After merging it looks like the action for removing comments does not work. 

I will be happy to fast merge potential bugfix without the standard 24 hours as it needs to be merged to test. 



Discussion:

Resolving patch:
diff --git a/tools/remove_html_comments_from_pr.py b/tools/remove_html_comments_from_pr.py
--- a/tools/remove_html_comments_from_pr.py
+++ b/tools/remove_html_comments_from_pr.py
@@ -10,6 +10,8 @@
 
 import requests
 
+REPO = 'napari/napari'
+
 
 def remove_html_comments(text):
     # Regular expression to remove HTML comments
@@ -55,10 +57,12 @@ def edit_pull_request_description(repo, pull_request_number, access_token):
 
 
 if __name__ == "__main__":
+    print('Will inspect PR description to remove html comments.')
     # Replace with your repository and pull request number
     # get cuurrent repository name from github actions
     repository_name = environ.get("GITHUB_REPOSITORY")
-    if repository_name == "napari/napari":
+    if repository_name != REPO:
+        print('Not on main repo, aborting with success')
         sys.exit(0)
 
     # get current PR number from github actions


Test patch:
Repository: napari/napari

Issue:
Under preference-shortcuts-keybindings several keys yield -
## 🐛 Bug

<!-- A clear and concise description of what the bug is. -->
If I try to change the keybindings under preferences-shortcuts several keys lead to the same sign.
German layout: . - + lead to -
English layout: . - = lead to -

## To Reproduce

Steps to reproduce the behaviour:

1. open napari preferences shortcut menu
2. select a keybinding to change
3. type the mentioned keys

<!-- If you have a code sample, error messages, stack traces, please provide it here as well -->

## Expected behavior

<!-- A clear and concise description of what you expected to happen. -->
Get the key your pressed.

## Environment

 - Please copy and paste the information at napari info option in help menubar here:
```
napari: 0.4.18
Platform: Linux-5.14.0-1054-oem-x86_64-with-glibc2.35
System: Ubuntu 22.04.2 LTS
Python: 3.10.11 | packaged by conda-forge | (main, May 10 2023, 18:58:44) [GCC 11.3.0]
Qt: 5.15.6
PyQt5: 5.15.7
NumPy: 1.24.3
SciPy: 1.10.1
Dask: 2023.5.0
VisPy: 0.12.2
magicgui: 0.7.2
superqt: unknown
in-n-out: 0.1.7
app-model: 0.1.4
npe2: 0.7.0

OpenGL:
- GL version: 4.6 (Compatibility Profile) Mesa 22.2.5-0ubuntu0.1~22.04.3
- MAX_TEXTURE_SIZE: 16384

Screens:
- screen 1: resolution 1920x1080, scale 1.0

Settings path:
- /home/cnk/.config/napari/fim_d969ce57ebdec0a0facec3650983237d48847a92/settings.yaml
```
 - Any other relevant information:

## Additional context

<!-- Add any other context about the problem here. -->



Discussion:
I can reproduce on 0.4.18 but not on main (f8fa80a7d9c91081344dd3f9fda3c59283f4a661), so it appears to be fixed already.
I remove `probably-solved` as it needs to be fixed in 0.4.19 

Resolving patch:
diff --git a/napari/_qt/widgets/qt_keyboard_settings.py b/napari/_qt/widgets/qt_keyboard_settings.py
--- a/napari/_qt/widgets/qt_keyboard_settings.py
+++ b/napari/_qt/widgets/qt_keyboard_settings.py
@@ -612,7 +612,7 @@ def keyPressEvent(self, event):
         event_keystr = event_keyseq.toString(QKeySequence.PortableText)
 
         # Split the shortcut if it contains a symbol.
-        parsed = re.split('[-(?=.+)]', event_keystr)
+        parsed = re.split(r'[-+](?=.+)', event_keystr)
 
         keys_li = []
         # Format how the shortcut is written (ex. 'Ctrl+B' is changed to 'Control-B')


Test patch:
Repository: napari/napari

Issue:
Remove napari/qt/progress.py
## 🧰 Task

`napari/qt/progress.py` has been deprecated since 4.11 and can be removed.

It should be a good issue for a new contributor and will increate coverage %-age. 




Discussion:
would like to take it :)

Resolving patch:
diff --git a/napari/qt/progress.py b/napari/qt/progress.py
deleted file mode 100644
--- a/napari/qt/progress.py
+++ /dev/null
@@ -1,16 +0,0 @@
-import warnings
-
-from napari.utils.translations import trans
-
-warnings.warn(
-    trans._(
-        'progress has moved from qt since 0.4.11. Use `from napari.utils import progress` instead',
-        deferred=True,
-    ),
-    category=FutureWarning,
-    stacklevel=3,
-)
-
-from napari.utils import progrange, progress  # noqa
-
-__all__ = ('progress', 'progrange')


Test patch:
Repository: napari/napari

Issue:
BUG `changing` event in `EventedDict` not emitted
## 🐛 Bug

The `changing` event in [`EventedDict`](https://github.com/napari/napari/blob/8c307022cc557692409f5e8bc031f1dcde4c374a/napari/utils/events/containers/_evented_dict.py#L9) is created but not documented or emitted:

https://github.com/napari/napari/blob/8c307022cc557692409f5e8bc031f1dcde4c374a/napari/utils/events/containers/_evented_dict.py#L75-L77

It seems not to be missed, should it be added?

<!-- A clear and concise description of what the bug is. -->




Discussion:
The code part you show in Issue is the emission of the event. So only there is a lack of documentation?
It emits `changed` but not `changing`?
ah. 100% true. Why I do not notice this difference. 
I am happy to open a PR to fix this, just wanted to check that we want to add `changing` ?

Resolving patch:
diff --git a/napari/utils/events/containers/_evented_dict.py b/napari/utils/events/containers/_evented_dict.py
--- a/napari/utils/events/containers/_evented_dict.py
+++ b/napari/utils/events/containers/_evented_dict.py
@@ -22,6 +22,8 @@ class EventedDict(TypedMutableMapping[_K, _T]):
 
     Events
     ------
+    changing (key: K)
+        emitted before an item at ``key`` is changed
     changed (key: K, old_value: T, value: T)
         emitted when item at ``key`` is changed from ``old_value`` to ``value``
     adding (key: K)
@@ -75,6 +77,7 @@ def __setitem__(self, key: _K, value: _T):
             self.events.added(key=key, value=value)
             self._connect_child_emitters(value)
         else:
+            self.events.changing(key=key)
             super().__setitem__(key, value)
             self.events.changed(key=key, old_value=old, value=value)
 


Test patch:
Repository: napari/napari

Issue:
ENH Make `_open_preferences_dialog` return `PreferencesDialog`
Make [`_open_preferences_dialog`](https://github.com/napari/napari/blob/7099b18fbf9ba3fbc9a3e2d502395f8216129960/napari/_qt/qt_main_window.py#L1528) return the `PreferencesDialog`, which would be useful when we want to use it after calling `_open_preferences_dialog`.

Ref: suggested in #6230 


Discussion:

Resolving patch:
diff --git a/napari/_qt/qt_main_window.py b/napari/_qt/qt_main_window.py
--- a/napari/_qt/qt_main_window.py
+++ b/napari/_qt/qt_main_window.py
@@ -53,6 +53,7 @@
 from napari._qt._qapp_model import build_qmodel_menu
 from napari._qt._qapp_model.qactions import init_qactions
 from napari._qt.dialogs.confirm_close_dialog import ConfirmCloseDialog
+from napari._qt.dialogs.preferences_dialog import PreferencesDialog
 from napari._qt.dialogs.qt_activity_dialog import QtActivityDialog
 from napari._qt.dialogs.qt_notification import NapariQtNotification
 from napari._qt.qt_event_loop import NAPARI_ICON_PATH, get_app, quit_app
@@ -1525,10 +1526,8 @@ def close(self):
             self._qt_window.close()
             del self._qt_window
 
-    def _open_preferences_dialog(self):
+    def _open_preferences_dialog(self) -> PreferencesDialog:
         """Edit preferences from the menubar."""
-        from napari._qt.dialogs.preferences_dialog import PreferencesDialog
-
         if self._pref_dialog is None:
             win = PreferencesDialog(parent=self._qt_window)
             self._pref_dialog = win
@@ -1549,6 +1548,8 @@ def _clean_pref_dialog():
         else:
             self._pref_dialog.raise_()
 
+        return self._pref_dialog
+
     def _screenshot_dialog(self):
         """Save screenshot of current display with viewer, default .png"""
         from napari._qt.dialogs.screenshot_dialog import ScreenshotDialog
diff --git a/napari/components/_viewer_key_bindings.py b/napari/components/_viewer_key_bindings.py
--- a/napari/components/_viewer_key_bindings.py
+++ b/napari/components/_viewer_key_bindings.py
@@ -1,6 +1,6 @@
 from __future__ import annotations
 
-from typing import TYPE_CHECKING, cast
+from typing import TYPE_CHECKING
 
 from napari.components.viewer_model import ViewerModel
 from napari.utils.action_manager import action_manager
@@ -8,7 +8,6 @@
 from napari.utils.translations import trans
 
 if TYPE_CHECKING:
-    from napari._qt.dialogs.preferences_dialog import PreferencesDialog
     from napari.viewer import Viewer
 
 
@@ -165,9 +164,7 @@ def hold_for_pan_zoom(viewer: ViewerModel):
 
 @register_viewer_action(trans._("Show all key bindings"))
 def show_shortcuts(viewer: Viewer):
-    viewer.window._open_preferences_dialog()
-    pref_dialog = cast('PreferencesDialog', viewer.window._pref_dialog)
-    pref_list = pref_dialog._list
+    pref_list = viewer.window._open_preferences_dialog()._list
     for i in range(pref_list.count()):
         if pref_list.item(i).text() == "Shortcuts":
             pref_list.setCurrentRow(i)


Test patch:
Repository: napari/napari

Issue:
Bounding box of multiscale data do not properly glue to data if move bellow 0 in corrdinates
### 🐛 Bug Report


https://github.com/napari/napari/assets/3826210/e7489ad7-646e-4ff6-8e01-8da76c9a03c4

I found this bug during work on the fix of #6382

### 💡 Steps to Reproduce

Use this script and start moving layers or zoom in-out to multiscale later:

```python
import napari
from skimage import data
from skimage.transform import pyramids

im = data.astronaut()[:,:,0].astype(float)

viewer = napari.Viewer()
layer1 = viewer.add_image([im] + [pyramids.pyramid_reduce(im, downscale=s) for s in [2]], name='pyramid')
layer1.bounding_box.visible = True
layer2 = viewer.add_image(im, name='original')
layer2.bounding_box.visible = True

layer1.translate = (-600, -100)

viewer.layers["pyramid"].mode = 'transform'

#viewer.camera.zoom = 0.1
viewer.reset_view()

napari.run()
```

### 💡 Expected Behavior

It should behave like non-multiscale one 

### 🌎 Environment

current main and 0.4.19 release branch

### 💡 Additional Context

_No response_


Discussion:
cc @brisvag 

Resolving patch:
diff --git a/napari/_vispy/layers/base.py b/napari/_vispy/layers/base.py
--- a/napari/_vispy/layers/base.py
+++ b/napari/_vispy/layers/base.py
@@ -223,6 +223,19 @@ def _on_matrix_change(self):
             affine_matrix = affine_matrix @ affine_offset
         self._master_transform.matrix = affine_matrix
 
+        # Because of performance reason, for multiscale images
+        # we load only visible part of data to GPU.
+        # To place this part of data correctly we update transform,
+        # but this leads to incorrect placement of child layers.
+        # To fix this we need to update child layers transform.
+        child_matrix = np.eye(4)
+        child_matrix[-1, : len(translate)] = (
+            self.layer.translate[self.layer._slice_input.displayed][::-1]
+            - translate
+        )
+        for child in self.node.children:
+            child.transform.matrix = child_matrix
+
     def _on_experimental_clipping_planes_change(self):
         if hasattr(self.node, 'clipping_planes') and hasattr(
             self.layer, 'experimental_clipping_planes'


Test patch:
Repository: napari/napari

Issue:
#6188 introduce crash of python -m napari.
#6188crash fresh start of napari (`python -m napari`).

_Originally posted by @Czaki in https://github.com/napari/napari/issues/6188#issuecomment-1822327152_
            


Discussion:

Resolving patch:
diff --git a/napari/components/viewer_model.py b/napari/components/viewer_model.py
--- a/napari/components/viewer_model.py
+++ b/napari/components/viewer_model.py
@@ -1171,7 +1171,7 @@ def open(
         if isinstance(stack, bool) and stack:
             paths = [paths_]
         # If stack is a list and True, extend the paths with the inner lists.
-        elif isinstance(stack, list):
+        elif isinstance(stack, list) and stack:
             paths = [paths_]
             paths.extend(stack)
 


Test patch:
diff --git a/napari/components/_tests/test_add_layers.py b/napari/components/_tests/test_add_layers.py
--- a/napari/components/_tests/test_add_layers.py
+++ b/napari/components/_tests/test_add_layers.py
@@ -67,6 +67,9 @@ def test_viewer_open():
     expected_source = Source(path='mock_path.tif', reader_plugin='testimpl')
     assert all(lay.source == expected_source for lay in viewer.layers)
 
+    viewer.open([], stack=[], plugin=None)
+    assert len(viewer.layers) == 2
+
 
 def test_viewer_open_no_plugin(tmp_path):
     viewer = ViewerModel()
Repository: napari/napari

Issue:
Previous point selected on creation
### 🐛 Bug Report

When creating points in a Point layer, the newly created one doesn't get selected, but the previous (on creating the first point, nothing gets selected). This happens using either the UI or napari console.

### 💡 Steps to Reproduce

1. Create a Points layer.
2. Create some points (e.g. click the canvas in 'add' mode)
3. See the highlight.

### 💡 Expected Behavior

The newly created point should be selected.

### 🌎 Environment

napari: 0.4.19rc5
Platform: Windows-11-10.0.22635-SP0
Python: 3.12.1 (tags/v3.12.1:2305ca5, Dec 7 2023, 22:03:25) [MSC v.1937 64 bit (AMD64)]
Qt: 5.15.2
PyQt5: 5.15.10
NumPy: 1.26.3
SciPy: 1.11.4
Dask: 2024.1.0
VisPy: 0.14.1
magicgui: 0.8.1
superqt: 0.6.1
in-n-out: 0.1.9
app-model: 0.2.4
npe2: 0.7.3

OpenGL:
- GL version: 4.6.0 NVIDIA 537.13
- MAX_TEXTURE_SIZE: 32768

Screens:
- screen 1: resolution 1920x1080, scale 1.0
- screen 2: resolution 1920x1080, scale 1.0

Settings path:
- C:\Users\Tejfel\AppData\Local\napari\env312_aaf4e926625f2970653c0ce31d4b2eb5b43fe25d\settings.yaml

### 💡 Additional Context

_No response_


Discussion:
This issue has been mentioned on **Image.sc Forum**. There might be relevant details there:

https://forum.image.sc/t/request-for-testing-napari-0-4-19-release-candidate/87972/30


Resolving patch:
diff --git a/napari/layers/points/points.py b/napari/layers/points/points.py
--- a/napari/layers/points/points.py
+++ b/napari/layers/points/points.py
@@ -1867,7 +1867,7 @@ def _set_highlight(self, force=False):
             and np.array_equal(self._drag_box, self._drag_box_stored)
         ) and not force:
             return
-        self._selected_data_stored = copy(self.selected_data)
+        self._selected_data_stored = Selection(self.selected_data)
         self._value_stored = copy(self._value)
         self._drag_box_stored = copy(self._drag_box)
 


Test patch:
Repository: napari/napari

Issue:
When all layers are removed, all roll locks should be removed
> Personally, I think when the LayerList goes to zero the locks should be removed, but I won't block on this point because I expect strong pushback on this from other core devs.

This could be done easily in [`Dims.reset`](https://github.com/napari/napari/blob/f9709d8a9eed8f1ab41596d71b7b29ee4390f64e/napari/components/dims.py#L377), which is called [in `ViewerModel` when the layers change and there are none of them](https://github.com/napari/napari/blob/f9709d8a9eed8f1ab41596d71b7b29ee4390f64e/napari/components/viewer_model.py#L489).

So I don't have an issue with this side-effect because there are existing related side-effects when removing the last layer.

@Chris-N-K : we've already asked so much of you here, so this is a non-blocking request. If you feel like adding it when making the latest updates, go for it! Otherwise, @psobolewskiPhD and I can make a follow up PR.

_Originally posted by @andy-sweet in https://github.com/napari/napari/issues/5986#issuecomment-2025530604_
            


Discussion:

Resolving patch:
diff --git a/napari/components/dims.py b/napari/components/dims.py
--- a/napari/components/dims.py
+++ b/napari/components/dims.py
@@ -392,6 +392,7 @@ def reset(self):
         self.order = tuple(range(self.ndim))
         self.margin_left = (0,) * self.ndim
         self.margin_right = (0,) * self.ndim
+        self.rollable = (True,) * self.ndim
 
     def transpose(self):
         """Transpose displayed dimensions.


Test patch: