From 230f78375baee73aca696e6bec3d5623b4b7422a Mon Sep 17 00:00:00 2001 From: Tom Donoghue Date: Tue, 9 Jun 2026 00:06:32 +0100 Subject: [PATCH 1/4] refactor copy_doc_func_to_method & split in 2 --- specparam/modutils/docs.py | 27 +++++++++++++++++++++++++-- specparam/tests/modutils/test_docs.py | 17 +++++++++++++++-- 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/specparam/modutils/docs.py b/specparam/modutils/docs.py index af97b7398..38b800275 100644 --- a/specparam/modutils/docs.py +++ b/specparam/modutils/docs.py @@ -224,8 +224,31 @@ def docs_add_section(docstring, section): return new_docstring -def copy_doc_func_to_method(source): - """Decorator that copies method docstring from function, dropping first parameter. +def copy_func_docstring(source): + """Decorator that copies docstring from source. + + Parameters + ---------- + source : function + Source function to copy docstring from. + + Returns + ------- + wrapper : function + The decorated function, with updated docs. + """ + + def wrapper(func): + + func.__doc__ = deepcopy(source.__doc__) + + return func + + return wrapper + + +def copy_func_docstring_drop_first(source): + """Decorator that copies docstring from source, dropping first parameter. Parameters ---------- diff --git a/specparam/tests/modutils/test_docs.py b/specparam/tests/modutils/test_docs.py index 32df309ce..42ba5e5cb 100644 --- a/specparam/tests/modutils/test_docs.py +++ b/specparam/tests/modutils/test_docs.py @@ -80,7 +80,21 @@ def test_docs_add_section(tdocstring): assert '%' not in new_docstring assert 'new note' in new_docstring -def test_copy_doc_func_to_method(tdocstring): +def test_copy_func_docstring(tdocstring): + + def tfunc(): pass + tfunc.__doc__ = tdocstring + + @copy_doc_func_to_method(tfunc) + def tfunc_out(): + pass + + assert tfunc_out.__doc__ + + for el in ['first', 'second']: + assert el in tfunc_out.__doc__ + +def test_copy_func_docstring_drop_first(tdocstring): def tfunc(): pass tfunc.__doc__ = tdocstring @@ -95,7 +109,6 @@ def tmethod(): assert 'first' not in tobj.tmethod.__doc__ assert 'second' in tobj.tmethod.__doc__ - def test_copy_doc_class(tdocstring): class tobj1(): From 5eb71559fbe0a226c61f9b8b1e54bf52a5fe4d61 Mon Sep 17 00:00:00 2001 From: Tom Donoghue Date: Tue, 9 Jun 2026 00:08:13 +0100 Subject: [PATCH 2/4] fix tests for new docstr copy funcs --- specparam/tests/modutils/test_docs.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/specparam/tests/modutils/test_docs.py b/specparam/tests/modutils/test_docs.py index 42ba5e5cb..50424797e 100644 --- a/specparam/tests/modutils/test_docs.py +++ b/specparam/tests/modutils/test_docs.py @@ -85,7 +85,7 @@ def test_copy_func_docstring(tdocstring): def tfunc(): pass tfunc.__doc__ = tdocstring - @copy_doc_func_to_method(tfunc) + @copy_func_docstring(tfunc) def tfunc_out(): pass @@ -101,7 +101,7 @@ def tfunc(): pass class tobj(): - @copy_doc_func_to_method(tfunc) + @copy_func_docstring_drop_first(tfunc) def tmethod(): pass From 36d8bff84b9f4462ae7732e11fb2cf0cabf045a9 Mon Sep 17 00:00:00 2001 From: Tom Donoghue Date: Tue, 9 Jun 2026 00:12:29 +0100 Subject: [PATCH 3/4] update docst decs for drop first cases --- specparam/models/event.py | 8 ++++---- specparam/models/group.py | 10 +++++----- specparam/models/model.py | 10 +++++----- specparam/models/time.py | 8 ++++---- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/specparam/models/event.py b/specparam/models/event.py index 1bafefe9b..41877bef5 100644 --- a/specparam/models/event.py +++ b/specparam/models/event.py @@ -8,7 +8,7 @@ from specparam.data.data import Data3D from specparam.data.conversions import event_group_to_dataframe, dict_to_df from specparam.data.utils import flatten_results_dict -from specparam.modutils.docs import (copy_doc_func_to_method, docs_get_section, +from specparam.modutils.docs import (copy_func_docstring_drop_first, docs_get_section, replace_docstring_sections) from specparam.reports.save import save_event_report from specparam.reports.strings import gen_event_results_str @@ -205,20 +205,20 @@ def print(self, info='results', concise=False): super().print(info, concise=concise) - @copy_doc_func_to_method(plot_event_model) + @copy_func_docstring_drop_first(plot_event_model) def plot(self, save_fig=False, file_name=None, file_path=None, **plot_kwargs): plot_event_model(self, save_fig=save_fig, file_name=file_name, file_path=file_path, **plot_kwargs) - @copy_doc_func_to_method(save_event_report) + @copy_func_docstring_drop_first(save_event_report) def save_report(self, file_name, file_path=None, add_settings=True): save_event_report(self, file_name, file_path, add_settings) - @copy_doc_func_to_method(save_event) + @copy_func_docstring_drop_first(save_event) def save(self, file_name, file_path=None, append=False, save_results=False, save_settings=False, save_data=False): diff --git a/specparam/models/group.py b/specparam/models/group.py index 6a0b909d5..8415368cd 100644 --- a/specparam/models/group.py +++ b/specparam/models/group.py @@ -17,8 +17,8 @@ from specparam.io.files import load_jsonlines from specparam.reports.save import save_group_report from specparam.reports.strings import gen_group_results_str -from specparam.modutils.docs import (copy_doc_func_to_method, - docs_get_section, replace_docstring_sections) +from specparam.modutils.docs import (copy_func_docstring_drop_first, docs_get_section, + replace_docstring_sections) from specparam.utils.checks import check_inds ################################################################################################### @@ -186,13 +186,13 @@ def report(self, freqs=None, power_spectra=None, freq_range=None, n_jobs=1, self.print('results') - @copy_doc_func_to_method(plot_group_model) + @copy_func_docstring_drop_first(plot_group_model) def plot(self, **plot_kwargs): plot_group_model(self, **plot_kwargs) - @copy_doc_func_to_method(save_group) + @copy_func_docstring_drop_first(save_group) def save(self, file_name, file_path=None, append=False, save_results=False, save_settings=False, save_data=False): @@ -326,7 +326,7 @@ def get_group(self, inds): return group - @copy_doc_func_to_method(save_group_report) + @copy_func_docstring_drop_first(save_group_report) def save_report(self, file_name, file_path=None, add_settings=True): save_group_report(self, file_name, file_path, add_settings) diff --git a/specparam/models/model.py b/specparam/models/model.py index 04d5d2458..d7eb6f2a9 100644 --- a/specparam/models/model.py +++ b/specparam/models/model.py @@ -21,8 +21,8 @@ from specparam.reports.save import save_model_report from specparam.reports.strings import gen_model_results_str from specparam.modutils.errors import NoDataError, FitError -from specparam.modutils.docs import (copy_doc_func_to_method, replace_docstring_sections, - docs_get_section) +from specparam.modutils.docs import (copy_func_docstring_drop_first, docs_get_section, + replace_docstring_sections) from specparam.utils.checks import check_all_none from specparam.io.files import load_json from specparam.io.models import save_model @@ -234,7 +234,7 @@ def print(self, info='results', concise=False): super().print(info, concise=concise) - @copy_doc_func_to_method(plot_model) + @copy_func_docstring_drop_first(plot_model) def plot(self, plot_peaks=None, plot_aperiodic=True, freqs=None, power_spectrum=None, freq_range=None, plt_log=False, add_legend=True, ax=None, data_kwargs=None, model_kwargs=None, aperiodic_kwargs=None, peak_kwargs=None, **plot_kwargs): @@ -245,7 +245,7 @@ def plot(self, plot_peaks=None, plot_aperiodic=True, freqs=None, power_spectrum= aperiodic_kwargs=aperiodic_kwargs, peak_kwargs=peak_kwargs, **plot_kwargs) - @copy_doc_func_to_method(save_model) + @copy_func_docstring_drop_first(save_model) def save(self, file_name, file_path=None, append=False, save_results=False, save_settings=False, save_data=False): @@ -298,7 +298,7 @@ def get_metrics(self, category, measure=None): return self.results.get_metrics(category, measure) - @copy_doc_func_to_method(save_model_report) + @copy_func_docstring_drop_first(save_model_report) def save_report(self, file_name, file_path=None, add_settings=True, **plot_kwargs): save_model_report(self, file_name, file_path, add_settings, **plot_kwargs) diff --git a/specparam/models/time.py b/specparam/models/time.py index 55cfdd2f1..f205f7691 100644 --- a/specparam/models/time.py +++ b/specparam/models/time.py @@ -9,7 +9,7 @@ from specparam.plts.time import plot_time_model from specparam.reports.save import save_time_report from specparam.reports.strings import gen_time_results_str -from specparam.modutils.docs import (copy_doc_func_to_method, docs_get_section, +from specparam.modutils.docs import (copy_func_docstring_drop_first, docs_get_section, replace_docstring_sections) from specparam.utils.checks import check_inds @@ -157,7 +157,7 @@ def print(self, info='results', concise=False, report_type='time'): super().print(info, concise=concise) - @copy_doc_func_to_method(plot_time_model) + @copy_func_docstring_drop_first(plot_time_model) def plot(self, plot_type='time', save_fig=False, file_name=None, file_path=None, **plot_kwargs): if plot_type == 'time': @@ -167,14 +167,14 @@ def plot(self, plot_type='time', save_fig=False, file_name=None, file_path=None, super().plot(save_fig=save_fig, file_name=file_name, file_path=file_path, **plot_kwargs) - @copy_doc_func_to_method(save_time) + @copy_func_docstring_drop_first(save_time) def save(self, file_name, file_path=None, append=False, save_results=False, save_settings=False, save_data=False): save_time(self, file_name, file_path, append, save_results, save_settings, save_data) - @copy_doc_func_to_method(save_time_report) + @copy_func_docstring_drop_first(save_time_report) def save_report(self, file_name, file_path=None, add_settings=True): save_time_report(self, file_name, file_path, add_settings) From d56b74aa2844c7fce2145dccbd1bd22b1b064693 Mon Sep 17 00:00:00 2001 From: Tom Donoghue Date: Tue, 9 Jun 2026 00:14:33 +0100 Subject: [PATCH 4/4] update docst decs for non drop first cases --- specparam/models/group.py | 8 ++++---- specparam/models/model.py | 8 ++++---- specparam/results/results.py | 6 +++--- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/specparam/models/group.py b/specparam/models/group.py index 8415368cd..b5a39edf1 100644 --- a/specparam/models/group.py +++ b/specparam/models/group.py @@ -17,8 +17,8 @@ from specparam.io.files import load_jsonlines from specparam.reports.save import save_group_report from specparam.reports.strings import gen_group_results_str -from specparam.modutils.docs import (copy_func_docstring_drop_first, docs_get_section, - replace_docstring_sections) +from specparam.modutils.docs import (copy_func_docstring, copy_func_docstring_drop_first, + docs_get_section, replace_docstring_sections) from specparam.utils.checks import check_inds ################################################################################################### @@ -243,13 +243,13 @@ def load(self, file_name, file_path=None): self._reset_data_results(clear_spectrum=True, clear_results=True) - @copy_doc_func_to_method(Results2D.get_params) + @copy_func_docstring(Results2D.get_params) def get_params(self, component, field=None): return self.results.get_params(component, field) - @copy_doc_func_to_method(Results2D.get_metrics) + @copy_func_docstring(Results2D.get_metrics) def get_metrics(self, category, measure=None): return self.results.get_metrics(category, measure) diff --git a/specparam/models/model.py b/specparam/models/model.py index d7eb6f2a9..04c8154b8 100644 --- a/specparam/models/model.py +++ b/specparam/models/model.py @@ -21,8 +21,8 @@ from specparam.reports.save import save_model_report from specparam.reports.strings import gen_model_results_str from specparam.modutils.errors import NoDataError, FitError -from specparam.modutils.docs import (copy_func_docstring_drop_first, docs_get_section, - replace_docstring_sections) +from specparam.modutils.docs import (copy_func_docstring, copy_func_docstring_drop_first, + docs_get_section, replace_docstring_sections) from specparam.utils.checks import check_all_none from specparam.io.files import load_json from specparam.io.models import save_model @@ -286,13 +286,13 @@ def load(self, file_name, file_path=None, regenerate=True): self.results._regenerate_model(self.data.freqs) - @copy_doc_func_to_method(Results.get_params) + @copy_func_docstring(Results.get_params) def get_params(self, component, field=None): return self.results.get_params(component, field) - @copy_doc_func_to_method(Results.get_metrics) + @copy_func_docstring(Results.get_metrics) def get_metrics(self, category, measure=None): return self.results.get_metrics(category, measure) diff --git a/specparam/results/results.py b/specparam/results/results.py index da5042294..27fe49512 100644 --- a/specparam/results/results.py +++ b/specparam/results/results.py @@ -12,7 +12,7 @@ from specparam.metrics.metrics import Metrics from specparam.utils.checks import check_inds from specparam.modutils.errors import NoModelError -from specparam.modutils.docs import (copy_doc_func_to_method, docs_get_section, +from specparam.modutils.docs import (copy_func_docstring, docs_get_section, replace_docstring_sections) from specparam.data.stores import FitResults from specparam.data.conversions import group_to_dict, event_group_to_dict @@ -210,7 +210,7 @@ def get_params(self, component, field=None, version=None): return getattr(self.params, component).get_params(version, field) - @copy_doc_func_to_method(Metrics.get_metrics) + @copy_func_docstring(Metrics.get_metrics) def get_metrics(self, category, measure=None): return self.metrics.get_metrics(category, measure) @@ -419,7 +419,7 @@ def get_params(self, component, field=None): return get_group_params(self.group_results, self.modes, component, field) - @copy_doc_func_to_method(Metrics.get_metrics) + @copy_func_docstring(Metrics.get_metrics) def get_metrics(self, category, measure=None): return get_group_metrics(self.group_results, category, measure)