Repository: matplotlib/matplotlib
Pull request: Add a new `orientation` parameter to Violinplot and deprecate `vert`
<!--
Thank you so much for your PR!  To help us review your contribution, please check
out the development guide https://matplotlib.org/devdocs/devel/index.html
-->

## PR summary
<!-- Please provide at least 1-2 sentences describing the pull request in detail
(Why is this change required?  What problem does it solve?) and link to relevant
issues and PRs.

Also please summarize the changes in the title, for example "Raise ValueError on
non-numeric input to set_xlim" and avoid non-descriptive titles such as "Addresses
issue #8576".
-->
Partially closes #13435. Replace the `vert: bool` parameter with `orientation : {'vertical', 'horizontal'}`.
Also changed the Violin plot basics gallery example to reflect the changes.

The other half of issue #13435 is to do the same to boxplots 

## PR checklist
<!-- Please mark any checkboxes that do not apply to this PR as [N/A].-->

- [x] "closes #0000" is in the body of the PR description to [link the related issue](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue)
- [x] new and changed code is [tested](https://matplotlib.org/devdocs/devel/testing.html)
- [x] *Plotting related* features are demonstrated in an [example](https://matplotlib.org/devdocs/devel/document.html#write-examples-and-tutorials)
- [x] *New Features* and *API Changes* are noted with a [directive and release note](https://matplotlib.org/devdocs/devel/api_changes.html#announce-changes-deprecations-and-new-features)
- [x] Documentation complies with [general](https://matplotlib.org/devdocs/devel/document.html#write-rest-pages) and [docstring](https://matplotlib.org/devdocs/devel/document.html#write-docstrings) guidelines

<!--We understand that PRs can sometimes be overwhelming, especially as the
reviews start coming in.  Please let us know if the reviews are unclear or
the recommended next step seems overly demanding, if you would like help in
addressing a reviewer's comments, or if you have been waiting too long to hear
back on your PR.-->


Problem statement:
boxplot/violinplot orientation-setting API
<!--To help us understand and resolve your issue, please fill out the form to the best of your ability.-->
<!--You can feel free to delete the sections that do not apply.-->

### Bug report

**Bug summary**

Currently, boxplot(), bxp(), violin(), and violinplot() take a `vert: bool` argument to switch between vertical and horizontal; this is inconsistent with colorbar(), hist(), eventplot(), and Slider(), which take an `orientation: {"vertical", "horizontal"}` argument.

For consistency, I'd suggest adding support for `orientation` (both because I think colorbar() and hist(), in particular, are probably the most used among all these, and because I like the API better :-)), and later deprecate `vert`.  Thoughts?

attn @phobson who has been involved in boxplots, IIRC.

Hints from issue discussion:
I think this is a good idea.

Should be easy enough to capture `vert`, emit and deprecation warning, and then set `orientation` accordingly.
(and while we're at it, the manage_xticks arg should be renamed to manage_ticks, as it covers both orientations)
just throwing this out there: what would you say to `manage_labels`?
well technically it's managing ticks, tick labels, *and axis limits* so I think manage_labels is worse than manage_ticks, and perhaps manage_axis is better?
I also wonder whether it really needs to manage axis limits -- can't the standard margins system do that just as well?  (needs to be investigated)
good points all around.

just noticed a wrinkle: `boxplot.vert` is an rcParam
We know how to handle deprecation/renaming of rcParams too, but thanks for pointing that out.
This issue has been marked "inactive" because it has been 365 days since the last comment. If this issue is still present in recent Matplotlib releases, or the feature request is still wanted, please leave a comment and this label will be removed. If there are no updates in another 30 days, this issue will be automatically closed, but you are free to re-open or create a new issue if needed. We value issue reports, and this procedure is meant to help us resurface and prioritize issues that have not been addressed yet, not make them disappear.  Thanks for your help!
At least adding orientation should hopefully be uncontroversial.
Would you want separate PRs for `boxplot` and `violinplot` to keep it simple? The review process for the `boxplot` section will probably take a bit longer because it involves the deprecation of an rcParam which Ive never done before.
Should we simply deprecate the `boxplot.vert` rcParams without replacement? This is more of a plot-type setting rather than style. It’s not useful as a global config or style parameter. The only use case would be a local context (e.g. via a context manager) if somebody wants to make multiple horizontal plots. But for that rare case using the parameter explicitly may be good enough and is more clear for the reader.

I believe, we also don’t have that config for `bar()` or `hist()`.

Commit message: fix broken tests

Patch to review:
diff --git a/doc/api/next_api_changes/deprecations/27998-TS.rst b/doc/api/next_api_changes/deprecations/27998-TS.rst
new file mode 100644
index 000000000000..ab69b87f0989
--- /dev/null
+++ b/doc/api/next_api_changes/deprecations/27998-TS.rst
@@ -0,0 +1,7 @@
+``violinplot`` and ``violin`` *vert* parameter
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The parameter *vert: bool* has been deprecated on `~.Axes.violinplot` and
+`~.Axes.violin`.
+It will be replaced by *orientation: {"vertical", "horizontal"}* for API
+consistency.
diff --git a/doc/users/next_whats_new/violinplot_orientation.rst b/doc/users/next_whats_new/violinplot_orientation.rst
new file mode 100644
index 000000000000..23d81446ad35
--- /dev/null
+++ b/doc/users/next_whats_new/violinplot_orientation.rst
@@ -0,0 +1,21 @@
+``violinplot`` and ``violin`` orientation parameter
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Violinplots have a new parameter *orientation: {"vertical", "horizontal"}*
+to change the orientation of the plot. This will replace the deprecated
+*vert: bool* parameter.
+
+
+.. plot::
+    :include-source: true
+    :alt: Example of creating 4 horizontal violinplots.
+
+    import matplotlib.pyplot as plt
+    import numpy as np
+
+    fig, ax = plt.subplots()
+    np.random.seed(19680801)
+    all_data = [np.random.normal(0, std, 100) for std in range(6, 10)]
+
+    ax.violinplot(all_data, orientation='horizontal')
+    plt.show()
diff --git a/galleries/examples/statistics/violinplot.py b/galleries/examples/statistics/violinplot.py
index afcc1c977034..5d1701d865c3 100644
--- a/galleries/examples/statistics/violinplot.py
+++ b/galleries/examples/statistics/violinplot.py
@@ -62,37 +62,37 @@
                      quantiles=[0.05, 0.1, 0.8, 0.9], bw_method=0.5, side='high')
 axs[0, 5].set_title('Custom violin 6', fontsize=fs)
 
-axs[1, 0].violinplot(data, pos, points=80, vert=False, widths=0.7,
+axs[1, 0].violinplot(data, pos, points=80, orientation='horizontal', widths=0.7,
                      showmeans=True, showextrema=True, showmedians=True)
 axs[1, 0].set_title('Custom violin 7', fontsize=fs)
 
-axs[1, 1].violinplot(data, pos, points=100, vert=False, widths=0.9,
+axs[1, 1].violinplot(data, pos, points=100, orientation='horizontal', widths=0.9,
                      showmeans=True, showextrema=True, showmedians=True,
                      bw_method='silverman')
 axs[1, 1].set_title('Custom violin 8', fontsize=fs)
 
-axs[1, 2].violinplot(data, pos, points=200, vert=False, widths=1.1,
+axs[1, 2].violinplot(data, pos, points=200, orientation='horizontal', widths=1.1,
                      showmeans=True, showextrema=True, showmedians=True,
                      bw_method=0.5)
 axs[1, 2].set_title('Custom violin 9', fontsize=fs)
 
-axs[1, 3].violinplot(data, pos, points=200, vert=False, widths=1.1,
+axs[1, 3].violinplot(data, pos, points=200, orientation='horizontal', widths=1.1,
                      showmeans=True, showextrema=True, showmedians=True,
                      quantiles=[[0.1], [], [], [0.175, 0.954], [0.75], [0.25]],
                      bw_method=0.5)
 axs[1, 3].set_title('Custom violin 10', fontsize=fs)
 
-axs[1, 4].violinplot(data[-1:], pos[-1:], points=200, vert=False, widths=1.1,
-                     showmeans=True, showextrema=True, showmedians=True,
+axs[1, 4].violinplot(data[-1:], pos[-1:], points=200, orientation='horizontal',
+                     widths=1.1, showmeans=True, showextrema=True, showmedians=True,
                      quantiles=[0.05, 0.1, 0.8, 0.9], bw_method=0.5)
 axs[1, 4].set_title('Custom violin 11', fontsize=fs)
 
-axs[1, 5].violinplot(data[-1:], pos[-1:], points=200, vert=False, widths=1.1,
-                     showmeans=True, showextrema=True, showmedians=True,
+axs[1, 5].violinplot(data[-1:], pos[-1:], points=200, orientation='horizontal',
+                     widths=1.1, showmeans=True, showextrema=True, showmedians=True,
                      quantiles=[0.05, 0.1, 0.8, 0.9], bw_method=0.5, side='low')
 
-axs[1, 5].violinplot(data[-1:], pos[-1:], points=200, vert=False, widths=1.1,
-                     showmeans=True, showextrema=True, showmedians=True,
+axs[1, 5].violinplot(data[-1:], pos[-1:], points=200, orientation='horizontal',
+                     widths=1.1, showmeans=True, showextrema=True, showmedians=True,
                      quantiles=[0.05, 0.1, 0.8, 0.9], bw_method=0.5, side='high')
 axs[1, 5].set_title('Custom violin 12', fontsize=fs)
 
diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py
index 26a3a580ba3e..9620d009888c 100644
--- a/lib/matplotlib/axes/_axes.py
+++ b/lib/matplotlib/axes/_axes.py
@@ -8350,9 +8350,10 @@ def matshow(self, Z, **kwargs):
 
     @_api.make_keyword_only("3.9", "vert")
     @_preprocess_data(replace_names=["dataset"])
-    def violinplot(self, dataset, positions=None, vert=True, widths=0.5,
+    def violinplot(self, dataset, positions=None, vert=None, widths=0.5,
                    showmeans=False, showextrema=True, showmedians=False,
-                   quantiles=None, points=100, bw_method=None, side='both'):
+                   quantiles=None, points=100, bw_method=None, side='both',
+                   orientation=None):
         """
         Make a violin plot.
 
@@ -8371,8 +8372,14 @@ def violinplot(self, dataset, positions=None, vert=True, widths=0.5,
             vertical violins (or y-axis for horizontal violins).
 
         vert : bool, default: True.
-            If true, creates a vertical violin plot.
-            Otherwise, creates a horizontal violin plot.
+            .. deprecated:: 3.10
+                Use *orientation* instead.
+
+                If this is given during the deprecation period, it overrides
+                the *orientation* parameter.
+
+            If True, plots the violins vertically.
+            If False, plots the violins horizontally.
 
         widths : float or array-like, default: 0.5
             The maximum width of each violin in units of the *positions* axis.
@@ -8407,6 +8414,12 @@ def violinplot(self, dataset, positions=None, vert=True, widths=0.5,
             'both' plots standard violins. 'low'/'high' only
             plots the side below/above the positions value.
 
+        orientation : {'vertical', 'horizontal'}, default: 'vertical'
+            If 'horizontal', plots the violins horizontally.
+            Otherwise, plots the violins vertically.
+
+            .. versionadded:: 3.10
+
         data : indexable object, optional
             DATA_PARAMETER_PLACEHOLDER
 
@@ -8457,12 +8470,14 @@ def _kde_method(X, coords):
         vpstats = cbook.violin_stats(dataset, _kde_method, points=points,
                                      quantiles=quantiles)
         return self.violin(vpstats, positions=positions, vert=vert,
-                           widths=widths, showmeans=showmeans,
-                           showextrema=showextrema, showmedians=showmedians, side=side)
+                           orientation=orientation, widths=widths,
+                           showmeans=showmeans, showextrema=showextrema,
+                           showmedians=showmedians, side=side)
 
     @_api.make_keyword_only("3.9", "vert")
-    def violin(self, vpstats, positions=None, vert=True, widths=0.5,
-               showmeans=False, showextrema=True, showmedians=False, side='both'):
+    def violin(self, vpstats, positions=None, vert=None, widths=0.5,
+               showmeans=False, showextrema=True, showmedians=False, side='both',
+               orientation=None):
         """
         Draw a violin plot from pre-computed statistics.
 
@@ -8501,8 +8516,14 @@ def violin(self, vpstats, positions=None, vert=True, widths=0.5,
             vertical violins (or y-axis for horizontal violins).
 
         vert : bool, default: True.
-            If true, plots the violins vertically.
-            Otherwise, plots the violins horizontally.
+            .. deprecated:: 3.10
+                Use *orientation* instead.
+
+                If this is given during the deprecation period, it overrides
+                the *orientation* parameter.
+
+            If True, plots the violins vertically.
+            If False, plots the violins horizontally.
 
         widths : float or array-like, default: 0.5
             The maximum width of each violin in units of the *positions* axis.
@@ -8522,6 +8543,12 @@ def violin(self, vpstats, positions=None, vert=True, widths=0.5,
             'both' plots standard violins. 'low'/'high' only
             plots the side below/above the positions value.
 
+        orientation : {'vertical', 'horizontal'}, default: 'vertical'
+            If 'horizontal', plots the violins horizontally.
+            Otherwise, plots the violins vertically.
+
+            .. versionadded:: 3.10
+
         Returns
         -------
         dict
@@ -8572,6 +8599,24 @@ def violin(self, vpstats, positions=None, vert=True, widths=0.5,
         datashape_message = ("List of violinplot statistics and `{0}` "
                              "values must have the same length")
 
+        if vert is not None:
+            _api.warn_deprecated(
+                "3.10",
+                name="vert: bool",
+                alternative="orientation: {'vertical', 'horizontal'}"
+            )
+
+        # vert and orientation parameters are linked until vert's
+        # deprecation period expires. If both are selected,
+        # vert takes precedence.
+        if vert or vert is None and orientation is None:
+            orientation = 'vertical'
+        elif vert is False:
+            orientation = 'horizontal'
+
+        if orientation is not None:
+            _api.check_in_list(['horizontal', 'vertical'], orientation=orientation)
+
         # Validate positions
         if positions is None:
             positions = range(1, N + 1)
@@ -8600,7 +8645,7 @@ def violin(self, vpstats, positions=None, vert=True, widths=0.5,
             fillcolor = linecolor = self._get_lines.get_next_color()
 
         # Check whether we are rendering vertically or horizontally
-        if vert:
+        if orientation == 'vertical':
             fill = self.fill_betweenx
             if side in ['low', 'high']:
                 perp_lines = functools.partial(self.hlines, colors=linecolor,
diff --git a/lib/matplotlib/axes/_axes.pyi b/lib/matplotlib/axes/_axes.pyi
index be0a0e48d662..0aa7d05acddc 100644
--- a/lib/matplotlib/axes/_axes.pyi
+++ b/lib/matplotlib/axes/_axes.pyi
@@ -739,7 +739,7 @@ class Axes(_AxesBase):
         dataset: ArrayLike | Sequence[ArrayLike],
         positions: ArrayLike | None = ...,
         *,
-        vert: bool = ...,
+        vert: bool | None = ...,
         widths: float | ArrayLike = ...,
         showmeans: bool = ...,
         showextrema: bool = ...,
@@ -751,6 +751,7 @@ class Axes(_AxesBase):
         | Callable[[GaussianKDE], float]
         | None = ...,
         side: Literal["both", "low", "high"] = ...,
+        orientation: Literal["vertical", "horizontal"] | None = ...,
         data=...,
     ) -> dict[str, Collection]: ...
     def violin(
@@ -758,12 +759,13 @@ class Axes(_AxesBase):
         vpstats: Sequence[dict[str, Any]],
         positions: ArrayLike | None = ...,
         *,
-        vert: bool = ...,
+        vert: bool | None = ...,
         widths: float | ArrayLike = ...,
         showmeans: bool = ...,
         showextrema: bool = ...,
         showmedians: bool = ...,
         side: Literal["both", "low", "high"] = ...,
+        orientation: Literal["vertical", "horizontal"] | None = ...,
     ) -> dict[str, Collection]: ...
 
     table = mtable.table
diff --git a/lib/matplotlib/pyplot.py b/lib/matplotlib/pyplot.py
index 2376c6243929..1498f777bf20 100644
--- a/lib/matplotlib/pyplot.py
+++ b/lib/matplotlib/pyplot.py
@@ -4142,7 +4142,7 @@ def triplot(*args, **kwargs):
 def violinplot(
     dataset: ArrayLike | Sequence[ArrayLike],
     positions: ArrayLike | None = None,
-    vert: bool = True,
+    vert: bool | None = None,
     widths: float | ArrayLike = 0.5,
     showmeans: bool = False,
     showextrema: bool = True,
@@ -4154,6 +4154,7 @@ def violinplot(
     | Callable[[GaussianKDE], float]
     | None = None,
     side: Literal["both", "low", "high"] = "both",
+    orientation: Literal["vertical", "horizontal"] | None = None,
     *,
     data=None,
 ) -> dict[str, Collection]:
@@ -4169,6 +4170,7 @@ def violinplot(
         points=points,
         bw_method=bw_method,
         side=side,
+        orientation=orientation,
         **({"data": data} if data is not None else {}),
     )
 
diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py
index 3644f0861d1b..2c2b354cd71c 100644
--- a/lib/matplotlib/tests/test_axes.py
+++ b/lib/matplotlib/tests/test_axes.py
@@ -3747,7 +3747,7 @@ def test_horiz_violinplot_baseline():
     # First 9 digits of frac(sqrt(19))
     np.random.seed(358898943)
     data = [np.random.normal(size=100) for _ in range(4)]
-    ax.violinplot(data, positions=range(4), vert=False, showmeans=False,
+    ax.violinplot(data, positions=range(4), orientation='horizontal', showmeans=False,
                   showextrema=False, showmedians=False)
 
 
@@ -3757,7 +3757,7 @@ def test_horiz_violinplot_showmedians():
     # First 9 digits of frac(sqrt(23))
     np.random.seed(795831523)
     data = [np.random.normal(size=100) for _ in range(4)]
-    ax.violinplot(data, positions=range(4), vert=False, showmeans=False,
+    ax.violinplot(data, positions=range(4), orientation='horizontal', showmeans=False,
                   showextrema=False, showmedians=True)
 
 
@@ -3767,7 +3767,7 @@ def test_horiz_violinplot_showmeans():
     # First 9 digits of frac(sqrt(29))
     np.random.seed(385164807)
     data = [np.random.normal(size=100) for _ in range(4)]
-    ax.violinplot(data, positions=range(4), vert=False, showmeans=True,
+    ax.violinplot(data, positions=range(4), orientation='horizontal', showmeans=True,
                   showextrema=False, showmedians=False)
 
 
@@ -3777,7 +3777,7 @@ def test_horiz_violinplot_showextrema():
     # First 9 digits of frac(sqrt(31))
     np.random.seed(567764362)
     data = [np.random.normal(size=100) for _ in range(4)]
-    ax.violinplot(data, positions=range(4), vert=False, showmeans=False,
+    ax.violinplot(data, positions=range(4), orientation='horizontal', showmeans=False,
                   showextrema=True, showmedians=False)
 
 
@@ -3787,7 +3787,7 @@ def test_horiz_violinplot_showall():
     # First 9 digits of frac(sqrt(37))
     np.random.seed(82762530)
     data = [np.random.normal(size=100) for _ in range(4)]
-    ax.violinplot(data, positions=range(4), vert=False, showmeans=True,
+    ax.violinplot(data, positions=range(4), orientation='horizontal', showmeans=True,
                   showextrema=True, showmedians=True,
                   quantiles=[[0.1, 0.9], [0.2, 0.8], [0.3, 0.7], [0.4, 0.6]])
 
@@ -3798,7 +3798,7 @@ def test_horiz_violinplot_custompoints_10():
     # First 9 digits of frac(sqrt(41))
     np.random.seed(403124237)
     data = [np.random.normal(size=100) for _ in range(4)]
-    ax.violinplot(data, positions=range(4), vert=False, showmeans=False,
+    ax.violinplot(data, positions=range(4), orientation='horizontal', showmeans=False,
                   showextrema=False, showmedians=False, points=10)
 
 
@@ -3808,7 +3808,7 @@ def test_horiz_violinplot_custompoints_200():
     # First 9 digits of frac(sqrt(43))
     np.random.seed(557438524)
     data = [np.random.normal(size=100) for _ in range(4)]
-    ax.violinplot(data, positions=range(4), vert=False, showmeans=False,
+    ax.violinplot(data, positions=range(4), orientation='horizontal', showmeans=False,
                   showextrema=False, showmedians=False, points=200)
 
 
@@ -3819,11 +3819,11 @@ def test_violinplot_sides():
     data = [np.random.normal(size=100)]
     # Check horizontal violinplot
     for pos, side in zip([0, -0.5, 0.5], ['both', 'low', 'high']):
-        ax.violinplot(data, positions=[pos], vert=False, showmeans=False,
+        ax.violinplot(data, positions=[pos], orientation='horizontal', showmeans=False,
                       showextrema=True, showmedians=True, side=side)
     # Check vertical violinplot
     for pos, side in zip([4, 3.5, 4.5], ['both', 'low', 'high']):
-        ax.violinplot(data, positions=[pos], vert=True, showmeans=False,
+        ax.violinplot(data, positions=[pos], orientation='vertical', showmeans=False,
                       showextrema=True, showmedians=True, side=side)
 
 
@@ -9034,3 +9034,40 @@ def test_latex_pie_percent(fig_test, fig_ref):
 
     ax1 = fig_ref.subplots()
     ax1.pie(data, autopct=r"%1.0f\%%", textprops={'usetex': True})
+
+
+@check_figures_equal(extensions=['png'])
+def test_violinplot_orientation(fig_test, fig_ref):
+    # Test the `orientation : {'vertical', 'horizontal'}`
+    # parameter and deprecation of `vert: bool`.
+    fig, axs = plt.subplots(nrows=1, ncols=3)
+    np.random.seed(19680801)
+    all_data = [np.random.normal(0, std, 100) for std in range(6, 10)]
+
+    axs[0].violinplot(all_data)  # Default vertical plot.
+    # xticks and yticks should be at their default position.
+    assert all(axs[0].get_xticks() == np.array(
+        [0.5, 1., 1.5, 2., 2.5, 3., 3.5, 4., 4.5]))
+    assert all(axs[0].get_yticks() == np.array(
+        [-30., -20., -10., 0., 10., 20., 30.]))
+
+    # Horizontal plot using new `orientation` keyword.
+    axs[1].violinplot(all_data, orientation='horizontal')
+    # xticks and yticks should be swapped.
+    assert all(axs[1].get_xticks() == np.array(
+        [-30., -20., -10., 0., 10., 20., 30.]))
+    assert all(axs[1].get_yticks() == np.array(
+        [0.5, 1., 1.5, 2., 2.5, 3., 3.5, 4., 4.5]))
+
+    plt.close()
+
+    # Deprecation of `vert: bool` keyword
+    with pytest.warns(mpl.MatplotlibDeprecationWarning,
+                      match='vert: bool was deprecated in Matplotlib 3.10'):
+        # Compare images between a figure that
+        # uses vert and one that uses orientation.
+        ax_ref = fig_ref.subplots()
+        ax_ref.violinplot(all_data, vert=False)
+
+        ax_test = fig_test.subplots()
+        ax_test.violinplot(all_data, orientation='horizontal')


Code review comments:
diff_hunk: @@ -8572,6 +8599,24 @@ def violin(self, vpstats, positions=None, vert=True, widths=0.5,
         datashape_message = ("List of violinplot statistics and `{0}` "
                              "values must have the same length")
 
+        if vert is not None:
+            _api.warn_deprecated(
+                "3.10",
+                name="vert: bool",
+                alternative="orientation: {'vertical', 'horizontal'}"
+            )
+
+        # vert and orientation parameters are linked until vert's
+        # deprecation period expires. If both are selected,
+        # vert takes precedence.
+        if vert or vert is None and orientation is None:
+            orientation = 'vertical'
+        elif vert is False:
+            orientation = 'horizontal'
+
+        if orientation is not None:
+            _api.check_in_list(['horizontal', 'vertical'], orientation=orientation)
path: lib/matplotlib/axes/_axes.py
text: @user1:
I'm not following the logic here completely. After whatever mangling vert and orientation, shouldn't we have a normalized `orientation` that must be 'horizontal' or 'vertical'? In other words

- Why do we allow orientation to be None in 8617 and would that even work for the following code?

Can't we simply
```
if vert is not None:
    _api.warn_deprecated(...)
    orientation = 'vertical' if vert else 'horizontal'
_api.check_in_list(['horizontal', 'vertical'], orientation=orientation)
```
and default `orientation='vertical'` instead of defaulting it to None?

@author:
Yes it should default to vertical instead of None (it even says so in the docstring) so there was no reason for it other than making it more convoluted. That code change is great, I'll add it to the next commit