diff --git a/CHANGELOG-unreleased.md b/CHANGELOG-unreleased.md index 380a8b3c4..e453c5a2c 100644 --- a/CHANGELOG-unreleased.md +++ b/CHANGELOG-unreleased.md @@ -13,4 +13,5 @@ the released changes. ### Fixed - Fixed RTD by specifying theme explicitly. - `.value()` now works for pairParameters +- Setting `model.PARAM1 = model.PARAM2` no longer overrides the name of `PARAM1` ### Removed diff --git a/src/pint/models/timing_model.py b/src/pint/models/timing_model.py index aa73ca579..65a013d54 100644 --- a/src/pint/models/timing_model.py +++ b/src/pint/models/timing_model.py @@ -498,6 +498,16 @@ def __getattr__(self, name): f"Attribute {name} not found in TimingModel or any Component" ) + def __setattr__(self, name, value): + """Mostly this just sets ``self.name = value``. But in the case where they are both :class:`Parameter` instances + with different names, this copies the ``quantity``, ``uncertainty``, ``frozen`` attributes only. + """ + if isinstance(value, (Parameter, prefixParameter)) and name != value.name: + for p in ["quantity", "uncertainty", "frozen"]: + setattr(getattr(self, name), p, getattr(value, p)) + else: + super().__setattr__(name, value) + @property_exists def params_ordered(self): """List of all parameter names in this model and all its components. diff --git a/tests/test_parameters.py b/tests/test_parameters.py index 3a6a7b832..460bd1ca8 100644 --- a/tests/test_parameters.py +++ b/tests/test_parameters.py @@ -605,3 +605,45 @@ def test_correct_number_of_params_and_FD_terms_after_add_or_remove_param(): m.remove_param("FD4") assert len(m.components["FD"].params) == 3 assert len(m.get_prefix_mapping("FD")) == 3 + + +def test_parameter_retains_name_on_set(): + basic_par_str = """ + PSR B1937+21 + LAMBDA 301.9732445337270 + BETA 42.2967523367957 + PMLAMBDA -0.0175 + PMBETA -0.3971 + PX 0.1515 + POSEPOCH 55321.0000 + F0 641.9282333345536244 1 0.0000000000000132 + F1 -4.330899370129D-14 1 2.149749089617D-22 + PEPOCH 55321.000000 + DM 71.016633 + UNITS TDB + """ + + m = get_model(io.StringIO(basic_par_str)) + m.POSEPOCH = m.PEPOCH + assert m.POSEPOCH.name == "POSEPOCH" + + +def test_parameter_set_incompatible_fails(): + basic_par_str = """ + PSR B1937+21 + LAMBDA 301.9732445337270 + BETA 42.2967523367957 + PMLAMBDA -0.0175 + PMBETA -0.3971 + PX 0.1515 + POSEPOCH 55321.0000 + F0 641.9282333345536244 1 0.0000000000000132 + F1 -4.330899370129D-14 1 2.149749089617D-22 + PEPOCH 55321.000000 + DM 71.016633 + UNITS TDB + """ + + m = get_model(io.StringIO(basic_par_str)) + with pytest.raises(u.core.UnitConversionError): + m.F0 = m.F1