|
12 | 12 | # See the License for the specific language governing permissions and |
13 | 13 | # limitations under the License. |
14 | 14 |
|
| 15 | +import logging |
15 | 16 | import unittest.mock as mock |
16 | 17 | import warnings |
17 | 18 |
|
@@ -413,3 +414,37 @@ def test_falls_back_to_pymc_for_configured_nuts_step(self, patched_sampler): |
413 | 414 | step = NUTS(potential=QuadPotentialDiag(np.ones(1))) |
414 | 415 | sample(step=step, **self._BASE_KWARGS) |
415 | 416 | patched_sampler.assert_not_called() |
| 417 | + |
| 418 | + |
| 419 | +class TestExternalSamplerLogging: |
| 420 | + """`pm.sample` should announce which external NUTS backend is running.""" |
| 421 | + |
| 422 | + _BASE_KWARGS = { |
| 423 | + "tune": 1, |
| 424 | + "draws": 1, |
| 425 | + "chains": 1, |
| 426 | + "progressbar": False, |
| 427 | + "compute_convergence_checks": False, |
| 428 | + "random_seed": 42, |
| 429 | + } |
| 430 | + |
| 431 | + @pytest.mark.parametrize("nuts_sampler", ["nutpie", "blackjax", "numpyro"]) |
| 432 | + def test_logs_external_sampler_name(self, caplog, nuts_sampler): |
| 433 | + pytest.importorskip(nuts_sampler) |
| 434 | + with Model(): |
| 435 | + Normal("x", 0, 1) |
| 436 | + HalfNormal("y", 1) |
| 437 | + with caplog.at_level(logging.INFO, logger="pymc"): |
| 438 | + sample(nuts_sampler=nuts_sampler, **self._BASE_KWARGS) |
| 439 | + |
| 440 | + assert any(r.message == f"NUTS[{nuts_sampler}]: [x, y]" for r in caplog.records) |
| 441 | + |
| 442 | + def test_quiet_suppresses_external_log(self, caplog): |
| 443 | + pytest.importorskip("nutpie") |
| 444 | + with Model(): |
| 445 | + Normal("x", 0, 1) |
| 446 | + with caplog.at_level(logging.DEBUG, logger="pymc"): |
| 447 | + sample(nuts_sampler="nutpie", quiet=True, **self._BASE_KWARGS) |
| 448 | + |
| 449 | + pymc_logs = [r for r in caplog.records if r.name.startswith("pymc")] |
| 450 | + assert pymc_logs == [] |
0 commit comments