Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-iminuit for openSUSE:Factory 
checked in at 2023-09-08 21:15:44
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-iminuit (Old)
 and      /work/SRC/openSUSE:Factory/.python-iminuit.new.1766 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-iminuit"

Fri Sep  8 21:15:44 2023 rev:30 rq:1109631 version:2.24.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-iminuit/python-iminuit.changes    
2023-07-03 17:41:57.608427054 +0200
+++ /work/SRC/openSUSE:Factory/.python-iminuit.new.1766/python-iminuit.changes  
2023-09-08 21:16:37.176783464 +0200
@@ -1,0 +2,10 @@
+Thu Sep  7 08:27:08 UTC 2023 - Markéta Machová <mmach...@suse.com>
+
+- Update to 2.24.0
+  * Fix CostSum.visualize bug
+  * Fix _safe_log on systems which use 32 bit floats
+  * Iteration limit in smart sampling to fix behavior for step functions 
+  * Clarify meaning of 2d contours in minuit.draw_mnmatrix
+  * Support interval type and check compatibility with pydantic 
+
+-------------------------------------------------------------------

Old:
----
  iminuit-2.22.0.tar.gz

New:
----
  iminuit-2.24.0.tar.gz

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

Other differences:
------------------
++++++ python-iminuit.spec ++++++
--- /var/tmp/diff_new_pack.y27wiE/_old  2023-09-08 21:16:38.316824208 +0200
+++ /var/tmp/diff_new_pack.y27wiE/_new  2023-09-08 21:16:38.320824351 +0200
@@ -19,7 +19,7 @@
 %define modname iminuit
 %{?sle15_python_module_pythons}
 Name:           python-%{modname}
-Version:        2.22.0
+Version:        2.24.0
 Release:        0
 Summary:        Python bindings for MINUIT2
 License:        MIT
@@ -79,12 +79,13 @@
 %python_expand %fdupes %{buildroot}%{$python_sitearch}
 
 %check
+# https://github.com/scikit-hep/iminuit/issues/940
+donttest="((test_bad_function or test_disp) and minimize)"
 # A tolerance issue on 32-bit
 %ifarch %ix86
-%pytest_arch -k 'not test_matrix'
-%else
-%pytest_arch
+donttest+=" or test_matrix"
 %endif
+%pytest_arch -k "not ($donttest)"
 
 %files %{python_files}
 %doc README.rst

++++++ iminuit-2.22.0.tar.gz -> iminuit-2.24.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iminuit-2.22.0/.github/workflows/release.yml 
new/iminuit-2.24.0/.github/workflows/release.yml
--- old/iminuit-2.22.0/.github/workflows/release.yml    2022-11-09 
13:37:21.000000000 +0100
+++ new/iminuit-2.24.0/.github/workflows/release.yml    2022-11-09 
13:37:21.000000000 +0100
@@ -63,7 +63,7 @@
       - if: ${{ matrix.arch == 'aarch64' }}
         uses: docker/setup-qemu-action@v2
 
-      - uses: pypa/cibuildwheel@v2.13.0
+      - uses: pypa/cibuildwheel@v2.14.1
         env:
           CIBW_BUILD: ${{ matrix.py }}-*
           CIBW_ARCHS: ${{ matrix.arch }}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iminuit-2.22.0/.pre-commit-config.yaml 
new/iminuit-2.24.0/.pre-commit-config.yaml
--- old/iminuit-2.22.0/.pre-commit-config.yaml  2022-11-09 13:37:21.000000000 
+0100
+++ new/iminuit-2.24.0/.pre-commit-config.yaml  2022-11-09 13:37:21.000000000 
+0100
@@ -33,14 +33,14 @@
     exclude: ^doc/_static/.*.svg
 
 # Python formatting
-- repo: https://github.com/psf/black
-  rev: 23.3.0
+- repo: https://github.com/psf/black-pre-commit-mirror
+  rev: 23.7.0
   hooks:
   - id: black
 
 # Ruff linter, replacement for flake8, pydocstyle, isort
-- repo: https://github.com/charliermarsh/ruff-pre-commit
-  rev: 'v0.0.272'
+- repo: https://github.com/astral-sh/ruff-pre-commit
+  rev: 'v0.0.284'
   hooks:
     - id: ruff
       args: [--fix, --exit-non-zero-on-fix]
@@ -62,7 +62,7 @@
 
 # Python type checking
 - repo: https://github.com/pre-commit/mirrors-mypy
-  rev: 'v1.3.0'
+  rev: 'v1.5.0'
   hooks:
   - id: mypy
     additional_dependencies: [numpy]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iminuit-2.22.0/.readthedocs.yaml 
new/iminuit-2.24.0/.readthedocs.yaml
--- old/iminuit-2.22.0/.readthedocs.yaml        2022-11-09 13:37:21.000000000 
+0100
+++ new/iminuit-2.24.0/.readthedocs.yaml        2022-11-09 13:37:21.000000000 
+0100
@@ -12,7 +12,7 @@
 build:
   os: ubuntu-22.04
   tools:
-    python: "3.10"
+    python: "3.9"
 
 python:
   install:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iminuit-2.22.0/PKG-INFO new/iminuit-2.24.0/PKG-INFO
--- old/iminuit-2.22.0/PKG-INFO 2022-11-09 13:37:21.000000000 +0100
+++ new/iminuit-2.24.0/PKG-INFO 2022-11-09 13:37:21.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: iminuit
-Version: 2.22.0
+Version: 2.24.0
 Summary: Jupyter-friendly Python frontend for MINUIT2 in C++
 Maintainer: Hans Dembinski
 Maintainer-Email: Unknown <hans.dembin...@gmail.com>
@@ -77,6 +77,8 @@
 Requires-Dist: boost_histogram; extra == "test"
 Requires-Dist: resample; extra == "test"
 Requires-Dist: unicodeitplus; extra == "test"
+Requires-Dist: pydantic; extra == "test"
+Requires-Dist: annotated_types; extra == "test"
 Requires-Dist: sphinx<7; extra == "doc"
 Requires-Dist: sphinx-rtd-theme; extra == "doc"
 Requires-Dist: nbsphinx; extra == "doc"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iminuit-2.22.0/doc/changelog.rst 
new/iminuit-2.24.0/doc/changelog.rst
--- old/iminuit-2.22.0/doc/changelog.rst        2022-11-09 13:37:21.000000000 
+0100
+++ new/iminuit-2.24.0/doc/changelog.rst        2022-11-09 13:37:21.000000000 
+0100
@@ -5,6 +5,20 @@
 Changelog
 =========
 
+2.24.0 (August 15, 2023)
+------------------------
+- Iteration limit in smart sampling to fix behavior for step functions (`#928 
<https://github.com/scikit-hep/iminuit/pull/928>`_)
+- Clarify meaning of 2d contours in minuit.draw_mnmatrix (`#927 
<https://github.com/scikit-hep/iminuit/pull/927>`_)
+- Support interval type and check compatibility with pydantic (`#922 
<https://github.com/scikit-hep/iminuit/pull/922>`_)
+
+2.23.0 (July 28, 2023)
+----------------------
+- Fix ``CostSum.visualize`` bug (`#918 
<https://github.com/scikit-hep/iminuit/pull/918>`_)
+- Fix ``_safe_log`` on systems which use 32 bit floats (`#915 
<https://github.com/scikit-hep/iminuit/pull/915>`_), (`#919 
<https://github.com/scikit-hep/iminuit/pull/919>`_)
+- Skip test_interactive and friends when ipywidgets is not installed (`#917 
<https://github.com/scikit-hep/iminuit/pull/917>`_)
+- Turn negative zero into positive zero in ``pdg_format`` (`#916 
<https://github.com/scikit-hep/iminuit/pull/916>`_)
+- Remove warning in ``test_cost.py`` by using ``pytest.warns`` instead of 
``pytest.raises`` (`#914 <https://github.com/scikit-hep/iminuit/pull/914>`_)
+
 2.22.0 (June 22, 2023)
 ----------------------
 - Hide confusing notes in docs: "not to be initialized by users." (`#906 
<https://github.com/scikit-hep/iminuit/pull/906>`_)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iminuit-2.22.0/doc/faq.rst 
new/iminuit-2.24.0/doc/faq.rst
--- old/iminuit-2.22.0/doc/faq.rst      2022-11-09 13:37:21.000000000 +0100
+++ new/iminuit-2.24.0/doc/faq.rst      2022-11-09 13:37:21.000000000 +0100
@@ -7,11 +7,12 @@
 FAQ
 ===
 
-Disclaimer: Read the excellent MINUIT2 user guide!
---------------------------------------------------
+Disclaimer: Read the excellent MINUIT user guide!
+-------------------------------------------------
 
-Many technical questions are nicely covered by the user guide of MINUIT2,
-:download:`MINUIT User's guide <mnusersguide.pdf>`. We will frequently refer 
to it here.
+Many technical questions are nicely covered by the `Minuit reference manual 
<https://cds.cern.ch/record/2296388>`_ of the original MINUIT in Fortran, on 
which MINUIT2 is based. Still relevant is chapter 5, which covers all the 
questions that one encounters when using Minuit in practice. If you have 
trouble with the fit, there is advice in sections 5.6 and 5.7 on how to fix 
common issues.
+
+Another source is the :download:`MINUIT User's guide <mnusersguide.pdf>`, 
which covers the C++ Minuit2 library on which iminuit is based. It also 
contains advice on troubleshooting, we will frequently refer to it here. 
However, the Fortran manual usually goes into more detail and is therefore 
preferred.
 
 I don't understand :meth:`Minuit.hesse`, :meth:`Minuit.minos`, 
:attr:`Minuit.errordef`; what do these do?
 
-----------------------------------------------------------------------------------------------------------
@@ -27,7 +28,7 @@
 I want to cite iminuit in my paper. Help?
 ------------------------------------------------
 
-We use the excellent Zenodo service to make each iminuit release citable. You 
can either cite iminuit as a software or you can cite the exact version that 
was used for your analysis. For more details, see :ref:`citation`.
+We use Zenodo to make each iminuit release citable. You can either cite 
iminuit as a software or you can cite the exact version that was used for your 
analysis. For more details, see :ref:`citation`.
 
 Can I have parameter limits that depend on each other (e.g. x^2 + y^2 < 3)?
 ---------------------------------------------------------------------------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iminuit-2.22.0/doc/reference.rst 
new/iminuit-2.24.0/doc/reference.rst
--- old/iminuit-2.22.0/doc/reference.rst        2022-11-09 13:37:21.000000000 
+0100
+++ new/iminuit-2.24.0/doc/reference.rst        2022-11-09 13:37:21.000000000 
+0100
@@ -27,11 +27,13 @@
     Minuit.fval
     Minuit.nfit
     Minuit.mnprofile
-    Minuit.draw_mnprofile
+    Minuit.mncontour
+    Minuit.visualize
+    Minuit.draw_mnmatrix
 
 
-Minuit
-------
+Main interface
+--------------
 
 .. autoclass:: Minuit
     :members:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iminuit-2.22.0/pyproject.toml 
new/iminuit-2.24.0/pyproject.toml
--- old/iminuit-2.22.0/pyproject.toml   2022-11-09 13:37:21.000000000 +0100
+++ new/iminuit-2.24.0/pyproject.toml   2022-11-09 13:37:21.000000000 +0100
@@ -5,7 +5,7 @@
 [project]
 name = "iminuit"
 description = "Jupyter-friendly Python frontend for MINUIT2 in C++"
-version = "2.22.0"
+version = "2.24.0"
 maintainers = [
     { name = "Hans Dembinski" },
     { email = "hans.dembin...@gmail.com" },
@@ -33,10 +33,7 @@
     "Operating System :: Unix",
     "Operating System :: MacOS",
 ]
-dependencies = [
-    "numpy >= 1.21",
-    "typing_extensions;python_version < '3.9'"
-]
+dependencies = ["numpy >= 1.21", "typing_extensions;python_version < '3.9'"]
 
 [project.urls]
 repository = "http://github.com/scikit-hep/iminuit";
@@ -49,7 +46,7 @@
     # ipywidgets 8.0.5 and 8.0.6 are broken
     # see https://github.com/jupyter-widgets/ipywidgets/issues/3731
     "ipywidgets<8.0.5",
-    "ipykernel",  # needed by ipywidgets 8.0.6
+    "ipykernel",        # needed by ipywidgets 8.0.6
     "joblib",
     "jacobi",
     "matplotlib",
@@ -61,31 +58,27 @@
     "tabulate",
     "boost_histogram",
     "resample",
-    "unicodeitplus"
+    "unicodeitplus",
+    "pydantic",
+    "annotated_types",
 ]
 doc = [
     "sphinx<7",
-    "sphinx-rtd-theme",  # needs sphinx<7
+    "sphinx-rtd-theme", # needs sphinx<7
     "nbsphinx",
     "nbconvert",
     "nbformat",
     "jupyter_client",
     "ipykernel",
-    # There are some problems with current jax versions
     "jax",
-    "jaxlib"
+    "jaxlib",
 ]
 
 [tool.scikit-build]
 minimum-version = "0.3"
 build-dir = "build/{wheel_tag}"
-sdist.exclude = [
-    "extern/root",
-]
-sdist.include = [
-    "extern/root/math/minuit2/inc",
-    "extern/root/math/minuit2/src",
-]
+sdist.exclude = ["extern/root"]
+sdist.include = ["extern/root/math/minuit2/inc", 
"extern/root/math/minuit2/src"]
 
 [tool.pytest.ini_options]
 minversion = "6.0"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iminuit-2.22.0/src/iminuit/cost.py 
new/iminuit-2.24.0/src/iminuit/cost.py
--- old/iminuit-2.22.0/src/iminuit/cost.py      2022-11-09 13:37:21.000000000 
+0100
+++ new/iminuit-2.24.0/src/iminuit/cost.py      2022-11-09 13:37:21.000000000 
+0100
@@ -113,10 +113,12 @@
 CHISQUARE = 1.0
 NEGATIVE_LOG_LIKELIHOOD = 0.5
 
+_TINY_FLOAT = np.finfo(float).tiny
+
 
 def _safe_log(x):
     # guard against x = 0
-    return np.log(x + 1e-323)
+    return np.log(np.maximum(_TINY_FLOAT, x))
 
 
 def _unbinned_nll(x):
@@ -724,8 +726,9 @@
 
         n = sum(hasattr(comp, "visualize") for comp in self)
 
-        w, h = plt.rcParams["figure.figsize"]
-        fig, ax = plt.subplots(1, n, figsize=(w, h * n))
+        fig = plt.gcf()
+        fig.set_figwidth(n * fig.get_figwidth() / 1.5)
+        _, ax = plt.subplots(1, n, num=fig.number)
 
         if component_kwargs is None:
             component_kwargs = {}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iminuit-2.22.0/src/iminuit/minuit.py 
new/iminuit-2.24.0/src/iminuit/minuit.py
--- old/iminuit-2.22.0/src/iminuit/minuit.py    2022-11-09 13:37:21.000000000 
+0100
+++ new/iminuit-2.24.0/src/iminuit/minuit.py    2022-11-09 13:37:21.000000000 
+0100
@@ -1434,13 +1434,14 @@
             Names of parameters to generate Minos errors for. If no positional
             arguments are given, Minos is run for each parameter.
         cl : float or None, optional
-            Confidence level for the confidence interval. If not set or None, a
-            standard 68.3 % confidence interval is produced. Setting this to 
another
-            value requires the scipy module to be installed. If 0 < cl < 1, 
the value
-            is interpreted as the confidence level (a probability). If cl >= 
1, it is
-            interpreted as number of standard deviations. For example, cl=3 
produces a
-            3 sigma interval. Values other than 0.68, 0.9, 0.95, 0.99, 1, 2, 
3, 4, 5
-            require the scipy module.
+            Confidence level of the interval. If not set or None, a standard 
68 %
+            interval is computed (default). If 0 < cl < 1, the value is 
interpreted as
+            the confidence level (a probability). For convenience, values cl 
>= 1 are
+            interpreted as the probability content of a central symmetric 
interval
+            covering that many standard deviations of a normal distribution. 
For
+            example, cl=1 is interpreted as 68.3 %, and cl=2 is 84.3 %, and so 
on. Using
+            values other than 0.68, 0.9, 0.95, 0.99, 1, 2, 3, 4, 5 require the 
scipy
+            module.
         ncall : int or None, optional
             Limit the number of calls made by Minos. If None, an adaptive 
internal
             heuristic of the Minuit2 library is used (Default: None).
@@ -1915,7 +1916,11 @@
         scan point. This scan produces a statistical confidence region 
according to the
         `profile likelihood method 
<https://en.wikipedia.org/wiki/Likelihood_function>`_
         with a confidence level `cl`, which is asymptotically equal to the 
coverage
-        probability of the confidence region.
+        probability of the confidence region according to `Wilks' theorem
+        <https://en.wikipedia.org/wiki/Wilks%27_theorem>`. Note that 1D 
projections of
+        the 2D confidence region are larger than 1D Minos intervals computed 
for the
+        same confidence level. This is not an error, but a consequence of 
Wilks'
+        theorem.
 
         The calculation is expensive since a numerical minimisation has to be 
performed
         at various points.
@@ -1929,9 +1934,12 @@
         cl : float or None, optional
             Confidence level of the contour. If not set or None, a standard 68 
% contour
             is computed (default). If 0 < cl < 1, the value is interpreted as 
the
-            confidence level (a probability). If cl >= 1, it is interpreted as 
number of
-            standard deviations. For example, cl=3 produces a 3 sigma contour. 
Values
-            other than 0.68, 0.9, 0.95, 0.99, 1, 2, 3, 4, 5 require the scipy 
module.
+            confidence level (a probability). For convenience, values cl >= 1 
are
+            interpreted as the probability content of a central symmetric 
interval
+            covering that many standard deviations of a normal distribution. 
For
+            example, cl=1 is interpreted as 68.3 %, and cl=2 is 84.3 %, and so 
on. Using
+            values other than 0.68, 0.9, 0.95, 0.99, 1, 2, 3, 4, 5 require the 
scipy
+            module.
         size : int, optional
             Number of points on the contour to find (default: 100). Increasing 
this
             makes the contour smoother, but requires more computation time.
@@ -2081,8 +2089,12 @@
         This draws a matrix of Minos likelihood scans, meaning that the 
likelihood is
         minimized with respect to the parameters that are not scanned over. 
The diagonal
         cells of the matrix show the 1D scan, the off-diagonal cells show 2D 
scans for
-        all unique pairs of parameters. The 2D scans show confidence regions. 
See
-        :meth:`mncontour` for details on the interpretation of these regions.
+        all unique pairs of parameters.
+
+        The projected edges of the 2D contours do not align with the 1D 
intervals,
+        because of Wilks' theorem. The levels for 2D confidence regions are 
higher. For
+        more information on the interpretation of 2D confidence regions, see
+        :meth:`mncontour`.
 
         Parameters
         ----------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iminuit-2.22.0/src/iminuit/pdg_format.py 
new/iminuit-2.24.0/src/iminuit/pdg_format.py
--- old/iminuit-2.22.0/src/iminuit/pdg_format.py        2022-11-09 
13:37:21.000000000 +0100
+++ new/iminuit-2.24.0/src/iminuit/pdg_format.py        2022-11-09 
13:37:21.000000000 +0100
@@ -180,6 +180,9 @@
         if i > 0:
             for k in mask:
                 items[k] = items[k][:-i]
+        # turn negative zero into positive zero
+        if items[0] == "-0":
+            items[0] = "0"
     return items
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iminuit-2.22.0/src/iminuit/typing.py 
new/iminuit-2.24.0/src/iminuit/typing.py
--- old/iminuit-2.22.0/src/iminuit/typing.py    2022-11-09 13:37:21.000000000 
+0100
+++ new/iminuit-2.24.0/src/iminuit/typing.py    2022-11-09 13:37:21.000000000 
+0100
@@ -71,3 +71,13 @@
     """Annotation compatible with annotated-types."""
 
     le: float
+
+
+@dataclasses.dataclass
+class Interval:
+    """Annotation compatible with annotated-types."""
+
+    gt: Optional[float] = None
+    ge: Optional[float] = None
+    lt: Optional[float] = None
+    le: Optional[float] = None
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iminuit-2.22.0/src/iminuit/util.py 
new/iminuit-2.24.0/src/iminuit/util.py
--- old/iminuit-2.22.0/src/iminuit/util.py      2022-11-09 13:37:21.000000000 
+0100
+++ new/iminuit-2.24.0/src/iminuit/util.py      2022-11-09 13:37:21.000000000 
+0100
@@ -1276,15 +1276,22 @@
                 lim[0] = c.start
             if c.stop is not None:
                 lim[1] = c.stop
-        # Minuit does not distinguish between closed and open intervals
-        elif hasattr(c, "gt"):
-            lim[0] = c.gt
-        elif hasattr(c, "ge"):
-            lim[0] = c.ge
-        elif hasattr(c, "lt"):
-            lim[1] = c.lt
-        elif hasattr(c, "le"):
-            lim[1] = c.le
+        # Minuit does not distinguish between closed and open intervals.
+        # We use a chain of ifs so that the code also works with the
+        # `Interval` class, which contains several of those attributes
+        # and which can be None.
+        gt = getattr(c, "gt", None)
+        ge = getattr(c, "ge", None)
+        lt = getattr(c, "lt", None)
+        le = getattr(c, "le", None)
+        if gt is not None:
+            lim[0] = gt
+        if ge is not None:
+            lim[0] = ge
+        if lt is not None:
+            lim[1] = lt
+        if le is not None:
+            lim[1] = le
     return tuple(lim)
 
 
@@ -1535,7 +1542,8 @@
     return segments
 
 
-def _smart_sampling(f, xmin, xmax, start=5, tol=5e-3):
+def _smart_sampling(f, xmin, xmax, start=5, tol=5e-3, maxiter=20, maxtime=10):
+    t0 = monotonic()
     x = np.linspace(xmin, xmax, start)
     ynew = f(x)
     ymin = np.min(ynew)
@@ -1543,10 +1551,23 @@
     y = {xi: yi for (xi, yi) in zip(x, ynew)}
     a = x[:-1]
     b = x[1:]
+    niter = 0
     while len(a):
-        if len(y) > 10000:
-            warnings.warn("Too many points", RuntimeWarning)  # pragma: no 
cover
-            break  # pragma: no cover
+        niter += 1
+        if niter > maxiter:
+            msg = (
+                f"Iteration limit {maxiter} in smart sampling reached, "
+                f"produced {len(y)} points"
+            )
+            warnings.warn(msg, RuntimeWarning)
+            break
+        if monotonic() - t0 > maxtime:
+            msg = (
+                f"Time limit {maxtime} in smart sampling reached, "
+                f"produced {len(y)} points"
+            )
+            warnings.warn(msg, RuntimeWarning)
+            break
         xnew = 0.5 * (a + b)
         ynew = f(xnew)
         ymin = min(ymin, np.min(ynew))
@@ -1558,10 +1579,11 @@
             + np.fromiter((y[bi] for bi in b), float)
         )
         dy = np.abs(ynew - yint)
+        dx = np.abs(b - a)
 
-        mask = dy > tol * (ymax - ymin)
-
-        # intervals which do not pass interpolation test
+        # in next iteration, handle intervals which do not
+        # pass interpolation test and are not too narrow
+        mask = (dy > tol * (ymax - ymin)) & (dx > tol * abs(xmax - xmin))
         a = a[mask]
         b = b[mask]
         xnew = xnew[mask]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iminuit-2.22.0/tests/test_cost.py 
new/iminuit-2.24.0/tests/test_cost.py
--- old/iminuit-2.22.0/tests/test_cost.py       2022-11-09 13:37:21.000000000 
+0100
+++ new/iminuit-2.24.0/tests/test_cost.py       2022-11-09 13:37:21.000000000 
+0100
@@ -237,7 +237,7 @@
     # manual spacing
     c.visualize((1, 2), model_points=np.linspace(1, 1000))
 
-    with pytest.raises(
+    with pytest.warns(
         np.VisibleDeprecationWarning, match="keyword 'nbins' is deprecated"
     ):
         c.visualize((1, 2), nbins=20)
@@ -1125,7 +1125,7 @@
 
     assert multinominal_chi2(zero, zero) == 0
     assert multinominal_chi2(zero, one) == 0
-    assert multinominal_chi2(one, zero) == pytest.approx(1487, abs=1)
+    assert multinominal_chi2(one, zero) == pytest.approx(1416, abs=1)
     n = np.array([(0.0, 0.0)])
     assert_allclose(multinominal_chi2(n, zero), 0)
     assert_allclose(multinominal_chi2(n, one), 0)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iminuit-2.22.0/tests/test_describe.py 
new/iminuit-2.24.0/tests/test_describe.py
--- old/iminuit-2.22.0/tests/test_describe.py   2022-11-09 13:37:21.000000000 
+0100
+++ new/iminuit-2.24.0/tests/test_describe.py   2022-11-09 13:37:21.000000000 
+0100
@@ -1,5 +1,5 @@
 from iminuit.util import describe, make_func_code
-from iminuit.typing import Annotated, Gt, Lt, Ge, Le
+from iminuit.typing import Annotated, Gt, Lt, Ge, Le, Interval
 from math import ldexp
 import platform
 from functools import wraps
@@ -195,6 +195,7 @@
         c: Annotated[float, 0:],
         d: Annotated[float, Ge(1)],
         e: Annotated[float, Le(2)],
+        f: Annotated[float, Interval(gt=2, lt=3)],
     ):
         ...
 
@@ -206,6 +207,7 @@
         "c": (0, np.inf),
         "d": (1, np.inf),
         "e": (-np.inf, 2),
+        "f": (2, 3),
     }
 
     class Foo:
@@ -219,6 +221,50 @@
     assert r == {"x": None, "a": (0, 1), "b": None}
 
 
+def test_with_pydantic_types():
+    tp = pytest.importorskip("pydantic.types")
+
+    def foo(
+        x: NDArray,
+        a: tp.PositiveFloat,
+        b: tp.NonNegativeFloat,
+        c: float,
+        d: Annotated[float, tp.annotated_types.Gt(1)],
+        e: Annotated[float, tp.annotated_types.Interval(gt=0, lt=1)],
+    ):
+        ...
+
+    r = describe(foo, annotations=True)
+    assert r == {
+        "x": None,
+        "a": (0, np.inf),
+        "b": (0, np.inf),
+        "c": None,
+        "d": (1, np.inf),
+        "e": (0, 1),
+    }
+
+
+def test_with_annotated_types():
+    tp = pytest.importorskip("annotated_types")
+
+    def foo(
+        x: NDArray,
+        a: float,
+        b: Annotated[float, tp.Gt(1)],
+        c: Annotated[float, tp.Interval(gt=0, lt=1)],
+    ):
+        ...
+
+    r = describe(foo, annotations=True)
+    assert r == {
+        "x": None,
+        "a": None,
+        "b": (1, np.inf),
+        "c": (0, 1),
+    }
+
+
 class Foo(float):
     pass
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iminuit-2.22.0/tests/test_draw.py 
new/iminuit-2.24.0/tests/test_draw.py
--- old/iminuit-2.22.0/tests/test_draw.py       2022-11-09 13:37:21.000000000 
+0100
+++ new/iminuit-2.24.0/tests/test_draw.py       2022-11-09 13:37:21.000000000 
+0100
@@ -137,7 +137,7 @@
 
 @pytest.mark.filterwarnings("ignore::DeprecationWarning")
 def test_interactive():
-    import ipywidgets
+    ipywidgets = pytest.importorskip("ipywidgets")
 
     def cost(a, b):
         return a**2 + b**2
@@ -223,6 +223,8 @@
 
 @pytest.mark.filterwarnings("ignore::DeprecationWarning")
 def test_interactive_raises():
+    pytest.importorskip("ipywidgets")
+
     def raiser(args):
         raise ValueError
 
@@ -237,6 +239,8 @@
 
 @pytest.mark.filterwarnings("ignore::DeprecationWarning")
 def test_interactive_with_array_func():
+    pytest.importorskip("ipywidgets")
+
     def cost(par):
         return par[0] ** 2 + (par[1] / 2) ** 2
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iminuit-2.22.0/tests/test_issue.py 
new/iminuit-2.24.0/tests/test_issue.py
--- old/iminuit-2.22.0/tests/test_issue.py      2022-11-09 13:37:21.000000000 
+0100
+++ new/iminuit-2.24.0/tests/test_issue.py      2022-11-09 13:37:21.000000000 
+0100
@@ -1,11 +1,9 @@
-from iminuit import Minuit
-from iminuit.util import IMinuitWarning
-import pickle
-import pytest
 import numpy as np
 
 
 def test_issue_424():
+    from iminuit import Minuit
+
     def fcn(x, y, z):
         return (x - 1) ** 2 + (y - 4) ** 2 / 2 + (z - 9) ** 2 / 3
 
@@ -20,6 +18,10 @@
 
 
 def test_issue_544():
+    import pytest
+    from iminuit import Minuit
+    from iminuit.util import IMinuitWarning
+
     def fcn(x, y):
         return x**2 + y**2
 
@@ -30,6 +32,8 @@
 
 
 def test_issue_648():
+    from iminuit import Minuit
+
     class F:
         first = True
 
@@ -45,6 +49,8 @@
 
 
 def test_issue_643():
+    from iminuit import Minuit
+
     def fcn(x, y, z):
         return (x - 2) ** 2 + (y - 3) ** 2 + (z - 4) ** 2
 
@@ -64,6 +70,8 @@
 
 
 def test_issue_669():
+    from iminuit import Minuit
+
     def fcn(x, y):
         return x**2 + (y / 2) ** 2
 
@@ -84,15 +92,21 @@
         assert match
 
 
+# cannot define this inside function, pickle will not allow it
 def fcn(par):
     return np.sum(par**2)
 
 
+# cannot define this inside function, pickle will not allow it
 def grad(par):
     return 2 * par
 
 
 def test_issue_687():
+    import pickle
+    import numpy as np
+    from iminuit import Minuit
+
     start = np.zeros(3)
     m = Minuit(fcn, start)
 
@@ -107,10 +121,13 @@
 
 
 def test_issue_694():
-    stats = pytest.importorskip("scipy.stats")
-
+    import pytest
+    import numpy as np
+    from iminuit import Minuit
     from iminuit.cost import ExtendedUnbinnedNLL
 
+    stats = pytest.importorskip("scipy.stats")
+
     xmus = 1.0
     xmub = 5.0
     xsigma = 1.0
@@ -142,3 +159,32 @@
             break
     else:
         assert False
+
+
+def test_issue_923():
+    from iminuit import Minuit
+    from iminuit.cost import LeastSquares
+    import numpy as np
+    import pytest
+
+    # implicitly needed by visualize
+    pytest.importorskip("matplotlib")
+
+    def model(x, c1):
+        c2 = 100
+        res = np.zeros(len(x))
+        mask = x < 47
+        res[mask] = c1
+        res[~mask] = c2
+        return res
+
+    xtest = np.linspace(0, 74)
+    ytest = xtest * 0 + 1
+    ytesterr = ytest
+
+    least_squares = LeastSquares(xtest, ytest, ytesterr, model)
+
+    m = Minuit(least_squares, c1=1)
+    m.migrad()
+    # this used to trigger an endless (?) loop
+    m.visualize()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iminuit-2.22.0/tests/test_pdg_format.py 
new/iminuit-2.24.0/tests/test_pdg_format.py
--- old/iminuit-2.22.0/tests/test_pdg_format.py 2022-11-09 13:37:21.000000000 
+0100
+++ new/iminuit-2.24.0/tests/test_pdg_format.py 2022-11-09 13:37:21.000000000 
+0100
@@ -81,6 +81,8 @@
     assert _strip(["0.11", "0.20"]) == ["0.11", "0.20"]
     assert _strip(["10.0", "20.0"]) == ["10", "20"]
     assert _strip(["1.200", "3.40"]) == ["1.20", "3.4"]
+    assert _strip(["0.000", "0.000"]) == ["0", "0"]
+    assert _strip(["-0.00", "0.00"]) == ["0", "0"]
 
 
 def test_term_format():
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iminuit-2.22.0/tests/test_repr.py 
new/iminuit-2.24.0/tests/test_repr.py
--- old/iminuit-2.22.0/tests/test_repr.py       2022-11-09 13:37:21.000000000 
+0100
+++ new/iminuit-2.24.0/tests/test_repr.py       2022-11-09 13:37:21.000000000 
+0100
@@ -1,6 +1,6 @@
-# flake8: noqa E501
+# flake8: noqa: E501
 from iminuit import Minuit
-from iminuit.util import Params, Param, Matrix, FMin, MError
+from iminuit.util import Param, Matrix, FMin, MError
 from iminuit import _repr_html, _repr_text
 import pytest
 from argparse import Namespace
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iminuit-2.22.0/tests/test_tabulate.py 
new/iminuit-2.24.0/tests/test_tabulate.py
--- old/iminuit-2.22.0/tests/test_tabulate.py   2022-11-09 13:37:21.000000000 
+0100
+++ new/iminuit-2.24.0/tests/test_tabulate.py   2022-11-09 13:37:21.000000000 
+0100
@@ -33,7 +33,7 @@
         == """
       x    y
 --  ---  ---
-x     1   -0
-y    -0    4
+x     1    0
+y     0    4
 """
     )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iminuit-2.22.0/tests/test_util.py 
new/iminuit-2.24.0/tests/test_util.py
--- old/iminuit-2.22.0/tests/test_util.py       2022-11-09 13:37:21.000000000 
+0100
+++ new/iminuit-2.24.0/tests/test_util.py       2022-11-09 13:37:21.000000000 
+0100
@@ -711,8 +711,30 @@
 
 
 def test_smart_sampling_2():
-    with pytest.warns(RuntimeWarning):
-        util._smart_sampling(np.log, 1e-10, 1, tol=1e-10)
+    # should not raise a warning
+    x, y = util._smart_sampling(np.log, 1e-10, 1, tol=1e-5)
+    assert 0 < len(x) < 1000
+
+
+def test_smart_sampling_3():
+    def step(x):
+        return np.where(x > 0.5, 0, 1)
+
+    with pytest.warns(RuntimeWarning, match="Iteration limit"):
+        x, y = util._smart_sampling(step, 0, 1, tol=0)
+    assert 0 < len(x) < 80
+
+
+def test_smart_sampling_4():
+    from time import sleep
+
+    def step(x):
+        sleep(0.1)
+        return np.where(x > 0.5, 0, 1)
+
+    with pytest.warns(RuntimeWarning, match="Time limit"):
+        x, y = util._smart_sampling(step, 0, 1, maxtime=0)
+    assert 0 < len(x) < 10
 
 
 @pytest.mark.parametrize(

Reply via email to