Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-mizani for openSUSE:Factory 
checked in at 2026-10-26 10:01:20
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-mizani (Old)
 and      /work/SRC/openSUSE:Factory/.python-mizani.new.2252680 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-mizani"

Mon Oct 26 10:01:20 2026 rev:12 rq:1392485 version:0.14.6

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-mizani/python-mizani.changes      
2026-03-16 14:20:16.588627045 +0100
+++ /work/SRC/openSUSE:Factory/.python-mizani.new.2252680/python-mizani.changes 
2026-10-26 10:02:51.029880739 +0100
@@ -1,0 +2,15 @@
+Sun Oct 25 16:32:09 UTC 2026 - Dirk Müller <[email protected]>
+
+- update to 0.14.6:
+  * :class:`~mizani.breaks.breaks_extended` accepts a pair for
+    only_inside, one flag per end, so a break sequence can be
+    held inside the limits at one end and allowed past them at
+    the other.
+  * :func:`~mizani.palettes.brewer_pal` now resolves a named
+    palette to its own type, so the name no longer has to match
+    the type argument. brewer_pal(palette="Set2") now works even
+    though type defaults to sequential and Set2 is qualitative.
+    An unknown name raises a ValueError listing the valid names.
+    This resolves (plotnine #1048).
+
+-------------------------------------------------------------------

Old:
----
  mizani-0.14.4.tar.gz

New:
----
  mizani-0.14.6.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-mizani.spec ++++++
--- /var/tmp/diff_new_pack.NTBSG2/_old  2026-10-26 10:02:52.330935301 +0100
+++ /var/tmp/diff_new_pack.NTBSG2/_new  2026-10-26 10:02:52.334935469 +0100
@@ -17,7 +17,7 @@
 
 
 Name:           python-mizani
-Version:        0.14.4
+Version:        0.14.6
 Release:        0
 Summary:        Scales for Python
 License:        BSD-3-Clause

++++++ mizani-0.14.4.tar.gz -> mizani-0.14.6.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mizani-0.14.4/.gitignore new/mizani-0.14.6/.gitignore
--- old/mizani-0.14.4/.gitignore        2026-01-28 15:41:52.000000000 +0100
+++ new/mizani-0.14.6/.gitignore        2026-09-07 18:14:10.312042500 +0200
@@ -23,6 +23,14 @@
 *.egg-info/
 .installed.cfg
 *.egg
+__pypackages__/
+node_modules/
+
+# Environments
+.direnv
+.venv
+venv
+uv.lock
 
 # PyInstaller
 #  Usually these files are written by a python script from a template
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mizani-0.14.4/.pre-commit-config.yaml 
new/mizani-0.14.6/.pre-commit-config.yaml
--- old/mizani-0.14.4/.pre-commit-config.yaml   2026-01-28 15:41:52.000000000 
+0100
+++ new/mizani-0.14.6/.pre-commit-config.yaml   2026-09-07 18:14:10.312042500 
+0200
@@ -1,6 +1,6 @@
 repos:
   - repo: https://github.com/astral-sh/ruff-pre-commit
-    rev: v0.14.14
+    rev: v0.16.6
     hooks:
       - id: ruff
         args: [--select=I001, --fix]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mizani-0.14.4/PKG-INFO new/mizani-0.14.6/PKG-INFO
--- old/mizani-0.14.4/PKG-INFO  2026-01-28 15:42:01.085750600 +0100
+++ new/mizani-0.14.6/PKG-INFO  2026-09-07 18:14:20.825758200 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.4
 Name: mizani
-Version: 0.14.4
+Version: 0.14.6
 Summary: Scales for Python
 Author-email: Hassan Kibirige <[email protected]>
 License: Copyright (c) 2016, Hassan Kibirige
@@ -73,7 +73,7 @@
 Requires-Dist: pre-commit; extra == "dev"
 Requires-Dist: mizani[typing]; extra == "dev"
 Provides-Extra: typing
-Requires-Dist: pyright==1.1.408; extra == "typing"
+Requires-Dist: pyright==1.1.411; extra == "typing"
 Requires-Dist: pandas-stubs; extra == "typing"
 Dynamic: license-file
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mizani-0.14.4/doc/changelog.rst 
new/mizani-0.14.6/doc/changelog.rst
--- old/mizani-0.14.4/doc/changelog.rst 2026-01-28 15:41:52.000000000 +0100
+++ new/mizani-0.14.6/doc/changelog.rst 2026-09-07 18:14:10.312504800 +0200
@@ -1,6 +1,35 @@
 Changelog
 =========
 
+v0.14.6
+-------
+
+2026-09-07
+
+Enhancements
+************
+
+- :class:`~mizani.breaks.breaks_extended` accepts a pair for
+  ``only_inside``, one flag per end, so a break sequence can be held
+  inside the limits at one end and allowed past them at the other.
+
+
+v0.14.5
+-------
+
+2026-09-04
+
+Bug Fixes
+*********
+
+- :func:`~mizani.palettes.brewer_pal` now resolves a named palette to its own
+  type, so the name no longer has to match the ``type`` argument.
+  ``brewer_pal(palette="Set2")`` now works even though ``type`` defaults to
+  sequential and ``Set2`` is qualitative. An unknown name raises a
+  ``ValueError`` listing the valid names. This resolves `(plotnine #1048)
+  <https://github.com/has2k1/plotnine/issues/1048>`_.
+
+
 v0.14.4
 -------
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/mizani-0.14.4/mizani/_colors/_palettes/brewer/__init__.py 
new/mizani-0.14.6/mizani/_colors/_palettes/brewer/__init__.py
--- old/mizani-0.14.4/mizani/_colors/_palettes/brewer/__init__.py       
2026-01-28 15:41:52.000000000 +0100
+++ new/mizani-0.14.6/mizani/_colors/_palettes/brewer/__init__.py       
2026-09-07 18:14:10.316721700 +0200
@@ -1,5 +1,6 @@
 from __future__ import annotations
 
+from functools import cache
 from typing import TYPE_CHECKING
 
 if TYPE_CHECKING:
@@ -36,7 +37,42 @@
 
         return diverging
     else:
-        raise ValueError(f"Unknown type of brewer palette: {type}")
+        raise ValueError(f"Unknown type of brewer palette: {scheme}")
+
+
+@cache
+def _palette_schemes() -> dict[str, ColorScheme]:
+    """
+    Return every brewer palette's scheme, keyed by palette name
+
+    Palette names are unique across schemes, so each name identifies one
+    scheme.
+    """
+    schemes: tuple[ColorScheme, ...] = (
+        "sequential",
+        "qualitative",
+        "diverging",
+    )
+    return {
+        name: scheme
+        for scheme in schemes
+        for name in get_palette_names(scheme)
+    }
+
+
+def get_palette_scheme(name: str) -> ColorScheme:
+    """
+    Return the scheme for a named palette
+
+    Raise a `ValueError` if the name is not a brewer palette.
+    """
+    lookup = _palette_schemes()
+    if name not in lookup:
+        raise ValueError(
+            f"Unknown brewer palette: '{name}'. The valid names are "
+            f"{sorted(lookup)}."
+        )
+    return lookup[name]
 
 
 def number_to_name(scheme: ColorScheme | ColorSchemeShort, n: int) -> str:
@@ -49,7 +85,7 @@
     names = mod.__all__
     if n > len(names):
         raise ValueError(
-            f"There are only '{n}' palettes of type {scheme}. "
+            f"There are only '{len(names)}' palettes of type {scheme}. "
             f"You requested palette no. {n}"
         )
     return names[n - 1]
@@ -60,8 +96,13 @@
 ) -> ColorPalette:
     """
     Return color palette from a given scheme
+
+    The scheme selects a palette given by number. A palette given by name
+    belongs to one scheme only, so the name overrides `scheme`.
     """
     if isinstance(palette, int):
         palette = number_to_name(scheme, palette)
+    else:
+        scheme = get_palette_scheme(palette)
     mod = get_palette_module(scheme)
     return getattr(mod, palette)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mizani-0.14.4/mizani/_datetime/utils.py 
new/mizani-0.14.6/mizani/_datetime/utils.py
--- old/mizani-0.14.4/mizani/_datetime/utils.py 2026-01-28 15:41:52.000000000 
+0100
+++ new/mizani-0.14.6/mizani/_datetime/utils.py 2026-09-07 18:14:10.317370200 
+0200
@@ -29,7 +29,6 @@
 SECONDS_PER_DAY = 24 * 60 * 60
 MICROSECONDS_PER_DAY = SECONDS_PER_DAY * (10**6)
 
-NaT_int = np.datetime64("NaT").astype(np.int64)
 MIN_DATETIME64 = np.datetime64("0001-01-01")
 MAX_DATETIME64 = np.datetime64("10000-01-01")
 UTC = ZoneInfo("UTC")
@@ -162,8 +161,7 @@
         + diff_ns.astype(np.float64) / 1.0e9
     ) / SECONDS_PER_DAY
 
-    x_int = x.astype(np.int64)
-    res[x_int == NaT_int] = np.nan
+    res[np.isnat(x)] = np.nan
     return res
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mizani-0.14.4/mizani/breaks.py 
new/mizani-0.14.6/mizani/breaks.py
--- old/mizani-0.14.4/mizani/breaks.py  2026-01-28 15:41:52.000000000 +0100
+++ new/mizani-0.14.6/mizani/breaks.py  2026-09-07 18:14:10.317621000 +0200
@@ -193,13 +193,13 @@
                 lower_end = np.max(
                     [
                         np.min(np.where(limits[0] <= breaks)) - 1,
-                        0,  # type: ignore
+                        0,
                     ]
                 )
                 upper_end = np.min(
                     [
                         np.max(np.where(breaks <= limits[1])) + 1,
-                        len(breaks),  # type: ignore
+                        len(breaks),
                     ]
                 )
                 return breaks[lower_end : upper_end + 1]
@@ -655,9 +655,14 @@
         Desired number of breaks
     Q : list
         List of nice numbers
-    only_inside : bool
+    only_inside : bool | tuple[bool, bool]
         If ``True``, then all the breaks will be within the given
-        range.
+        range. A pair ``(lower, upper)`` constrains each end on its
+        own, so ``(True, False)`` keeps the first break at or above
+        the lower limit while the last break may lie beyond the
+        upper limit. The coverage score treats the two ends
+        separately (Talbot et al., 2010), so the search is unchanged;
+        only the candidates it admits are.
     w : list
         Weights applied to the four optimization components
         (simplicity, coverage, density, and legibility). They
@@ -670,6 +675,8 @@
     array([  0. ,   2.5,   5. ,   7.5,  10. ])
     >>> breaks_extended(n=6)(limits)
     array([  0.,   2.,   4.,   6.,   8.,  10.])
+    >>> breaks_extended(n=3, only_inside=(True, False))((-7.7, 196.9))
+    array([  0., 100., 200.])
 
     References
     ----------
@@ -683,12 +690,16 @@
 
     n: int = 5
     Q: Sequence[float] = (1, 5, 2, 2.5, 4, 3)
-    only_inside: bool = False
+    only_inside: bool | tuple[bool, bool] = False
     w: Sequence[float] = (0.25, 0.2, 0.5, 0.05)
 
     def __post_init__(self):
         # Used for lookups during the computations
         self.Q_index = {q: i for i, q in enumerate(self.Q)}
+        if isinstance(self.only_inside, bool):
+            self._inside = (self.only_inside, self.only_inside)
+        else:
+            self._inside = tuple(self.only_inside)
 
     def coverage(
         self, dmin: float, dmax: float, lmin: float, lmax: float
@@ -764,7 +775,7 @@
         """
         Q = self.Q
         w = self.w
-        only_inside = self.only_inside
+        inside_lower, inside_upper = self._inside
         simplicity_max = self.simplicity_max
         density_max = self.density_max
         coverage_max = self.coverage_max
@@ -835,9 +846,10 @@
 
                             score = w[0] * s + w[1] * c + w[2] * d + w[3] * l
 
-                            if score > best_score and (
-                                not only_inside
-                                or (lmin >= dmin and lmax <= dmax)
+                            if (
+                                score > best_score
+                                and (not inside_lower or lmin >= dmin)
+                                and (not inside_upper or lmax <= dmax)
                             ):
                                 best_score = score
                                 best = (lmin, lmax, lstep, q, k)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mizani-0.14.4/mizani/palettes.py 
new/mizani-0.14.6/mizani/palettes.py
--- old/mizani-0.14.4/mizani/palettes.py        2026-01-28 15:41:52.000000000 
+0100
+++ new/mizani-0.14.6/mizani/palettes.py        2026-09-07 18:14:10.317621000 
+0200
@@ -18,7 +18,7 @@
 
 import colorsys
 from dataclasses import dataclass
-from typing import TYPE_CHECKING, Protocol
+from typing import TYPE_CHECKING, Protocol, cast
 from warnings import warn
 
 import numpy as np
@@ -477,15 +477,14 @@
     Parameters
     ----------
     type : 'sequential' | 'qualitative' | 'diverging'
-        Type of palette. Sequential, Qualitative or
-        Diverging. The following abbreviations may
-        be used, ``seq``, ``qual`` or ``div``.
+        Type from which to choose a numeric `palette`. The abbreviations
+        `seq`, `qual`, and `div` are supported. A named palette selects its
+        own type, and `type` becomes its long form, such as `'qualitative'`.
     palette : int | str
-        Which palette to choose from. If is an integer,
-        it must be in the range ``[0, m]``, where ``m``
-        depends on the number sequential, qualitative or
-        diverging palettes. If it is a string, then it
-        is the name of the palette.
+        Palette to choose. An integer must be in the range `[0, m]`, where
+        `m` depends on the number of sequential, qualitative, or diverging
+        palettes. A string must be a palette name; an unknown name raises a
+        `ValueError`.
     direction : int
         The order of colours in the scale. If -1 the order
         of colors is reversed. The default is 1.
@@ -509,10 +508,18 @@
     >>> brewer_pal('seq', 'PuBuGn')(5)
     ['#F6EFF7', '#BDC9E1', '#67A9CF', '#1C9099', '#016C59']
 
+    A named palette does not need a matching `type`.
+
+    >>> pal = brewer_pal(palette='Set2')
+    >>> pal(3)
+    ['#66C2A5', '#FC8D62', '#8DA0CB']
+    >>> pal.type
+    'qualitative'
+
     The available color names for each palette type can be
     obtained using the following code::
 
-        from mizani._colors.brewer import get_palette_names
+        from mizani._colors._palettes.brewer import get_palette_names
 
         print(get_palette_names("sequential"))
         print(get_palette_names("qualitative"))
@@ -530,6 +537,7 @@
             raise ValueError("direction should be 1 or -1.")
 
         self.bpal = get_brewer_palette(self.type, self.palette)
+        self.type = cast("ColorScheme", self.bpal.kind.value)
 
     def __call__(self, n: int) -> Sequence[RGBHexColor | None]:
         # Only draw the maximum allowable colors from the palette
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mizani-0.14.4/mizani/scale.py 
new/mizani-0.14.6/mizani/scale.py
--- old/mizani-0.14.4/mizani/scale.py   2026-01-28 15:41:52.000000000 +0100
+++ new/mizani-0.14.6/mizani/scale.py   2026-09-07 18:14:10.317621000 +0200
@@ -54,6 +54,7 @@
         ContinuousPalette,
         DiscretePalette,
         FloatArrayLike,
+        NDArrayAny,
         NDArrayFloat,
         Trans,
     )
@@ -76,7 +77,7 @@
         palette: ContinuousPalette,
         na_value: Any = None,
         trans: Trans | None = None,
-    ) -> NDArrayFloat:
+    ) -> NDArrayAny:
         """
         Scale data continuously
 
@@ -144,7 +145,7 @@
         limits: tuple[float, float],
         na_value: Any = None,
         oob: Callable[[TVector], TVector] = censor,
-    ) -> NDArrayFloat:
+    ) -> NDArrayAny:
         """
         Map values to a continuous palette
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mizani-0.14.4/mizani/typing.py 
new/mizani-0.14.6/mizani/typing.py
--- old/mizani-0.14.4/mizani/typing.py  2026-01-28 15:41:52.000000000 +0100
+++ new/mizani-0.14.6/mizani/typing.py  2026-09-07 18:14:10.317706300 +0200
@@ -163,7 +163,9 @@
     )
     TimedeltaOffset: TypeAlias = timedelta | str | Sequence[str] | None
 
-    ContinuousPalette: TypeAlias = Callable[[FloatArrayLike], Sequence[Any]]
+    ContinuousPalette: TypeAlias = Callable[
+        [FloatArrayLike], NDArrayAny | Sequence[Any]
+    ]
     DiscretePalette: TypeAlias = Callable[[int], NDArrayAny | AnySeries]
 
     # Mizani
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mizani-0.14.4/mizani.egg-info/PKG-INFO 
new/mizani-0.14.6/mizani.egg-info/PKG-INFO
--- old/mizani-0.14.4/mizani.egg-info/PKG-INFO  2026-01-28 15:42:01.000000000 
+0100
+++ new/mizani-0.14.6/mizani.egg-info/PKG-INFO  2026-09-07 18:14:20.781757800 
+0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.4
 Name: mizani
-Version: 0.14.4
+Version: 0.14.6
 Summary: Scales for Python
 Author-email: Hassan Kibirige <[email protected]>
 License: Copyright (c) 2016, Hassan Kibirige
@@ -73,7 +73,7 @@
 Requires-Dist: pre-commit; extra == "dev"
 Requires-Dist: mizani[typing]; extra == "dev"
 Provides-Extra: typing
-Requires-Dist: pyright==1.1.408; extra == "typing"
+Requires-Dist: pyright==1.1.411; extra == "typing"
 Requires-Dist: pandas-stubs; extra == "typing"
 Dynamic: license-file
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mizani-0.14.4/mizani.egg-info/SOURCES.txt 
new/mizani-0.14.6/mizani.egg-info/SOURCES.txt
--- old/mizani-0.14.4/mizani.egg-info/SOURCES.txt       2026-01-28 
15:42:01.000000000 +0100
+++ new/mizani-0.14.6/mizani.egg-info/SOURCES.txt       2026-09-07 
18:14:20.800408000 +0200
@@ -63,6 +63,8 @@
 mizani.egg-info/SOURCES.txt
 mizani.egg-info/dependency_links.txt
 mizani.egg-info/requires.txt
+mizani.egg-info/scm_file_list.json
+mizani.egg-info/scm_version.json
 mizani.egg-info/top_level.txt
 mizani/_colors/__init__.py
 mizani/_colors/_named_color_values.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mizani-0.14.4/mizani.egg-info/requires.txt 
new/mizani-0.14.6/mizani.egg-info/requires.txt
--- old/mizani-0.14.4/mizani.egg-info/requires.txt      2026-01-28 
15:42:01.000000000 +0100
+++ new/mizani-0.14.6/mizani.egg-info/requires.txt      2026-09-07 
18:14:20.784434800 +0200
@@ -36,5 +36,5 @@
 pytest-cov>=4.0.0
 
 [typing]
-pyright==1.1.408
+pyright==1.1.411
 pandas-stubs
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mizani-0.14.4/mizani.egg-info/scm_file_list.json 
new/mizani-0.14.6/mizani.egg-info/scm_file_list.json
--- old/mizani-0.14.4/mizani.egg-info/scm_file_list.json        1970-01-01 
01:00:00.000000000 +0100
+++ new/mizani-0.14.6/mizani.egg-info/scm_file_list.json        2026-09-07 
18:14:20.780415800 +0200
@@ -0,0 +1,130 @@
+{
+  "files": [
+    ".gitattributes",
+    ".github/workflows/release.yml",
+    ".github/workflows/testing.yml",
+    ".gitignore",
+    ".pre-commit-config.yaml",
+    ".readthedocs.yaml",
+    "LICENSE",
+    "Makefile",
+    "README.md",
+    "codecov.yml",
+    "doc/Makefile",
+    "doc/_static/copybutton.js",
+    "doc/_static/custom.css",
+    "doc/bounds.rst",
+    "doc/breaks.rst",
+    "doc/changelog.rst",
+    "doc/conf.py",
+    "doc/docutils.conf",
+    "doc/index.rst",
+    "doc/installation.rst",
+    "doc/labels.rst",
+    "doc/palettes.rst",
+    "doc/scale.rst",
+    "doc/sphinxext/__init__.py",
+    "doc/sphinxext/inline_code_highlight.py",
+    "doc/theme/globaltoc.html",
+    "doc/theme/layout.html",
+    "doc/theme/localtoc.html",
+    "doc/theme/navbar-2.html",
+    "doc/theme/navbar.html",
+    "doc/theme/navbarsearchbox.html",
+    "doc/theme/navbartoc.html",
+    "doc/theme/relations.html",
+    "doc/theme/search.html",
+    "doc/theme/searchbox.html",
+    "doc/theme/searchresults.html",
+    "doc/theme/sourcelink.html",
+    "doc/theme/static/bootstrap-3.4.1/css/bootstrap.min.css",
+    "doc/theme/static/bootstrap-3.4.1/js/bootstrap.min.js",
+    "doc/theme/static/bootstrap-sphinx.css_t",
+    "doc/theme/static/bootstrap-sphinx.js_t",
+    "doc/theme/static/js/jquery-1.12.4.min.js",
+    "doc/theme/static/js/jquery-fix.js",
+    "doc/theme/theme.conf",
+    "doc/transforms.rst",
+    "licences/HUSL_LICENSE",
+    "licences/SCALES_LICENSE",
+    "licences/SEABORN_LICENSE",
+    "licences/SIX_LICENSE",
+    "mizani/__init__.py",
+    "mizani/_colors/__init__.py",
+    "mizani/_colors/_colormaps/__init__.py",
+    "mizani/_colors/_colormaps/_colormap.py",
+    "mizani/_colors/_colormaps/_cubehelix.py",
+    "mizani/_colors/_colormaps/_interpolated.py",
+    "mizani/_colors/_colormaps/_listed.py",
+    "mizani/_colors/_colormaps/_maps/__init__.py",
+    "mizani/_colors/_colormaps/_maps/_interpolated.py",
+    "mizani/_colors/_colormaps/_maps/_listed.py",
+    "mizani/_colors/_colormaps/_maps/_palette_interpolated.py",
+    "mizani/_colors/_colormaps/_maps/_segment_function.py",
+    "mizani/_colors/_colormaps/_maps/_segment_interpolated.py",
+    "mizani/_colors/_colormaps/_palette_interpolated.py",
+    "mizani/_colors/_colormaps/_segment_function.py",
+    "mizani/_colors/_colormaps/_segment_interpolated.py",
+    "mizani/_colors/_named_color_values.py",
+    "mizani/_colors/_palettes/__init__.py",
+    "mizani/_colors/_palettes/_palette.py",
+    "mizani/_colors/_palettes/brewer/__init__.py",
+    "mizani/_colors/_palettes/brewer/diverging.py",
+    "mizani/_colors/_palettes/brewer/qualitative.py",
+    "mizani/_colors/_palettes/brewer/sequential.py",
+    "mizani/_colors/_palettes/other/__init__.py",
+    "mizani/_colors/_palettes/other/qualitative.py",
+    "mizani/_colors/hsluv.py",
+    "mizani/_colors/named_colors.py",
+    "mizani/_colors/utils.py",
+    "mizani/_datetime/__init__.py",
+    "mizani/_datetime/breaks.py",
+    "mizani/_datetime/rounding.py",
+    "mizani/_datetime/types.py",
+    "mizani/_datetime/utils.py",
+    "mizani/_timedelta/__init__.py",
+    "mizani/_timedelta/breaks.py",
+    "mizani/_timedelta/utils.py",
+    "mizani/bounds.py",
+    "mizani/breaks.py",
+    "mizani/formatters.py",
+    "mizani/labels.py",
+    "mizani/palettes.py",
+    "mizani/py.typed",
+    "mizani/scale.py",
+    "mizani/transforms.py",
+    "mizani/typing.py",
+    "mizani/utils.py",
+    "pyproject.toml",
+    "tests/__init__.py",
+    "tests/colors/__init__.py",
+    "tests/colors/data/hsluv-snapshot-rev4.json",
+    "tests/colors/test_cubehelix.py",
+    "tests/colors/test_hsluv.py",
+    "tests/colors/test_interpolated.py",
+    "tests/colors/test_listed.py",
+    "tests/colors/test_named_colors.py",
+    "tests/colors/test_segment_function.py",
+    "tests/colors/test_utils.py",
+    "tests/conftest.py",
+    "tests/datetime/__init__.py",
+    "tests/datetime/test_breaks.py",
+    "tests/datetime/test_rounding.py",
+    "tests/datetime/test_utils.py",
+    "tests/test_bounds.py",
+    "tests/test_breaks.py",
+    "tests/test_labels.py",
+    "tests/test_palettes.py",
+    "tests/test_scale.py",
+    "tests/test_transforms.py",
+    "tests/test_utils.py",
+    "tests/timedelta/__init__.py",
+    "tests/timedelta/test_breaks.py",
+    "tests/timedelta/test_utils.py",
+    "tools/build_theme.sh",
+    "tools/gha_check_semver.py",
+    "tools/release-checklist-tpl.md",
+    "tools/release-checklist.py",
+    "tools/term.py"
+  ]
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mizani-0.14.4/mizani.egg-info/scm_version.json 
new/mizani-0.14.6/mizani.egg-info/scm_version.json
--- old/mizani-0.14.4/mizani.egg-info/scm_version.json  1970-01-01 
01:00:00.000000000 +0100
+++ new/mizani-0.14.6/mizani.egg-info/scm_version.json  2026-09-07 
18:14:20.768881300 +0200
@@ -0,0 +1,8 @@
+{
+  "tag": "0.14.6",
+  "distance": 0,
+  "node": "ga056fe2c8649a2c8ffd09430952e69137f5ae3b5",
+  "dirty": false,
+  "branch": "HEAD",
+  "node_date": "2026-09-07"
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mizani-0.14.4/pyproject.toml 
new/mizani-0.14.6/pyproject.toml
--- old/mizani-0.14.4/pyproject.toml    2026-01-28 15:41:52.000000000 +0100
+++ new/mizani-0.14.6/pyproject.toml    2026-09-07 18:14:10.317706300 +0200
@@ -65,7 +65,7 @@
 ]
 
 typing = [
-    "pyright==1.1.408",
+    "pyright==1.1.411",
     "pandas-stubs",
 ]
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mizani-0.14.4/tests/datetime/test_utils.py 
new/mizani-0.14.6/tests/datetime/test_utils.py
--- old/mizani-0.14.4/tests/datetime/test_utils.py      2026-01-28 
15:41:52.000000000 +0100
+++ new/mizani-0.14.6/tests/datetime/test_utils.py      2026-09-07 
18:14:10.325093500 +0200
@@ -27,6 +27,13 @@
     assert len(datetime_to_num([])) == 0
 
 
+def test_datetime_to_num_handles_nat():
+    result = datetime_to_num(
+        np.array(["2020-01-01", "NaT"], dtype="datetime64[ns]")
+    )
+    assert np.isnan(result[1])
+
+
 def test_num_to_datetime():
     limits = num_to_datetime((25552, 27743))
     assert limits[0] == datetime(2039, 12, 17, tzinfo=ZoneInfo("UTC"))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mizani-0.14.4/tests/test_breaks.py 
new/mizani-0.14.6/tests/test_breaks.py
--- old/mizani-0.14.4/tests/test_breaks.py      2026-01-28 15:41:52.000000000 
+0100
+++ new/mizani-0.14.6/tests/test_breaks.py      2026-09-07 18:14:10.325093500 
+0200
@@ -438,3 +438,32 @@
     limits = [np.pi, np.pi]
     assert len(breaks(limits)) == 1
     assert breaks(limits)[0] == limits[1]
+
+
+def test_breaks_extended_only_inside_per_end():
+    limits = (-7.7, 196.9)
+
+    # A pair of equal flags is the same as the single flag
+    for flag in (True, False):
+        npt.assert_array_equal(
+            breaks_extended(n=3, only_inside=(flag, flag))(limits),
+            breaks_extended(n=3, only_inside=flag)(limits),
+        )
+
+    # Each end honours its own flag: the constrained end stays inside,
+    # the free end may go past its limit
+    breaks = breaks_extended(n=3, only_inside=(True, False))(limits)
+    npt.assert_array_equal(breaks, [0, 100, 200])
+    breaks = breaks_extended(n=3, only_inside=(False, True))((3.1, 207.7))
+    npt.assert_array_equal(breaks, [0, 100, 200])
+
+    # Over many ranges the constrained end never crosses its limit
+    rng = np.random.default_rng(0)
+    for _ in range(200):
+        lo = rng.uniform(-50, 50)
+        hi = lo + 10 ** rng.uniform(-1, 3)
+        n = int(rng.integers(2, 9))
+        breaks = breaks_extended(n=n, only_inside=(True, False))((lo, hi))
+        assert breaks[0] >= lo
+        breaks = breaks_extended(n=n, only_inside=(False, True))((lo, hi))
+        assert breaks[-1] <= hi
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mizani-0.14.4/tests/test_palettes.py 
new/mizani-0.14.6/tests/test_palettes.py
--- old/mizani-0.14.4/tests/test_palettes.py    2026-01-28 15:41:52.000000000 
+0100
+++ new/mizani-0.14.6/tests/test_palettes.py    2026-09-07 18:14:10.325093500 
+0200
@@ -135,6 +135,28 @@
         brewer_pal(direction=-2)(100)
 
 
+def test_brewer_pal_named_palette_selects_its_type():
+    # A unique name identifies the palette type and overrides the default or
+    # explicitly supplied type.
+    result = brewer_pal(palette="Set2")(3)
+    assert all(s[0] == "#" and len(s) == 7 for s in result)
+
+    result = brewer_pal("div", "Blues")(3)
+    assert all(s[0] == "#" and len(s) == 7 for s in result)
+
+    assert brewer_pal(palette="Set2").type == "qualitative"
+    assert brewer_pal("div", "Blues").type == "sequential"
+
+    with pytest.raises(ValueError, match="Nonesuch"):
+        brewer_pal(palette="Nonesuch")
+
+
+def test_brewer_pal_number_out_of_range():
+    # Report the number of available palettes, not the requested number.
+    with pytest.raises(ValueError, match="only '8' palettes of type qual"):
+        brewer_pal("qual", 20)
+
+
 def test_brewer_palette_names():
     from mizani._colors._palettes.brewer import get_palette_names
 

Reply via email to