diff --git a/bilby/core/prior/base.py b/bilby/core/prior/base.py index dc0c9f14e..28f7459be 100644 --- a/bilby/core/prior/base.py +++ b/bilby/core/prior/base.py @@ -253,7 +253,19 @@ def __repr__(self): prior_name = self.__class__.__name__ prior_module = self.__class__.__module__ instantiation_dict = self.get_instantiation_dict() - args = ', '.join([f'{key}={repr(instantiation_dict[key])}' for key in instantiation_dict]) + + def _native(value): + # Convert NumPy scalars to native Python types so that repr() is + # round-trippable by _parse_argument_string. Under NumPy 2.0, + # repr(np.float64(0.0)) is "np.float64(0.0)", which the parser would + # try to import as the module "np" and fail. + if isinstance(value, np.generic): + return value.item() + return value + + args = ', '.join( + [f'{key}={repr(_native(instantiation_dict[key]))}' for key in instantiation_dict] + ) if "bilby.core.prior" in prior_module: return f"{prior_name}({args})" else: diff --git a/test/core/prior/base_test.py b/test/core/prior/base_test.py index e61bbbf11..6f45d4b2e 100644 --- a/test/core/prior/base_test.py +++ b/test/core/prior/base_test.py @@ -54,6 +54,25 @@ def test_base_repr(self): ) self.assertTrue(sorted(expected_string) == sorted(self.prior.__repr__())) + def test_repr_round_trips_with_numpy_scalar_parameters(self): + """repr() must remain re-parseable when parameters are NumPy scalars. + + Under NumPy >= 2.0, repr() of any NumPy scalar carries the "np." prefix, + e.g. repr(np.float64(0.0)) == "np.float64(0.0)". If that goes into the + prior repr, PriorDict's parser tries to import a module "np" and fails. + """ + for minimum, maximum in [ + (np.float64(0.0), np.float64(1.0)), + (np.float32(0.0), np.float32(1.0)), + (np.int64(0), np.int64(10)), + ]: + prior = bilby.core.prior.Uniform( + minimum=minimum, maximum=maximum, name="x" + ) + self.assertNotIn("np.", repr(prior)) + reconstructed = bilby.core.prior.PriorDict({"x": repr(prior)})["x"] + self.assertEqual(prior, reconstructed) + def test_base_prob(self): self.assertTrue(np.isnan(self.prior.prob(5)))