From fd632eb911878a9c535ea847990338355eb375ca Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Fri, 4 Aug 2023 13:01:34 +0200 Subject: [PATCH 1/7] gh-104683: Argument Clinic: refactor format_docstring() Extract helper methods for formatting the signature and parameter sections, and clean up the remaining function body. --- Tools/clinic/clinic.py | 84 +++++++++++++++++++----------------------- 1 file changed, 38 insertions(+), 46 deletions(-) diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py index 7525c1ca524003..a8be0f03039e1d 100755 --- a/Tools/clinic/clinic.py +++ b/Tools/clinic/clinic.py @@ -5308,23 +5308,13 @@ def state_function_docstring(self, line: str) -> None: self.docstring_append(self.function, line) - def format_docstring(self) -> str: - f = self.function - assert f is not None - - new_or_init = f.kind.new_or_init - if new_or_init and not f.docstring: - # don't render a docstring at all, no signature, nothing. - return f.docstring - + @staticmethod + def format_docstring_signature( + f: Function, + parameters: list[Parameter] + ) -> str: text, add, output = _text_accumulator() - parameters = f.render_parameters - - ## - ## docstring first line - ## - - if new_or_init: + if f.kind.new_or_init: # classes get *just* the name of the class # not __new__, not __init__, and not module.classname assert f.cls @@ -5484,35 +5474,39 @@ def add_parameter(text: str) -> None: if not f.docstring_only: add("\n" + sig_end_marker + "\n") - docstring_first_line = output() + signature_line = output() # now fix up the places where the brackets look wrong - docstring_first_line = docstring_first_line.replace(', ]', ',] ') + return signature_line.replace(', ]', ',] ') - # okay. now we're officially building the "parameters" section. - # create substitution text for {parameters} + @staticmethod + def format_docstring_parameters(params: list[Parameter]) -> str: + """Create substitution text for {parameters}""" + text, add, output = _text_accumulator() spacer_line = False - for p in parameters: - if not p.docstring.strip(): + for param in params: + docstring = param.docstring.strip() + if not docstring: continue if spacer_line: add('\n') else: spacer_line = True add(" ") - add(p.name) + add(param.name) add('\n') - add(textwrap.indent(rstrip_lines(p.docstring.rstrip()), " ")) - parameters_output = output() - if parameters_output: - parameters_output += '\n' - - ## - ## docstring body - ## + stripped = rstrip_lines(docstring.rstrip()) + add(textwrap.indent(stripped, " ")) + if text: + add('\n') + return output() - docstring = f.docstring.rstrip() - lines = [line.rstrip() for line in docstring.split('\n')] + def format_docstring(self) -> str: + assert self.function is not None + f = self.function + if f.kind.new_or_init and not f.docstring: + # don't render a docstring at all, no signature, nothing. + return f.docstring # Enforce the summary line! # The first line of a docstring should be a summary of the function. @@ -5526,6 +5520,7 @@ def add_parameter(text: str) -> None: # Guido said Clinic should enforce this: # http://mail.python.org/pipermail/python-dev/2013-June/127110.html + lines = [line for line in f.docstring.split('\n')] if len(lines) >= 2: if lines[1]: fail("Docstring for " + f.full_name + " does not have a summary line!\n" + @@ -5537,26 +5532,23 @@ def add_parameter(text: str) -> None: # between it and the {parameters} we're about to add. lines.append('') - parameters_marker_count = len(docstring.split('{parameters}')) - 1 + parameters_marker_count = len(f.docstring.split('{parameters}')) - 1 if parameters_marker_count > 1: fail('You may not specify {parameters} more than once in a docstring!') + # insert signature at front and params after the summary line if not parameters_marker_count: - # insert after summary line lines.insert(2, '{parameters}') + lines.insert(0, '{signature}') - # insert at front of docstring - lines.insert(0, docstring_first_line) - + # finalize docstring + params = f.render_parameters + parameters = self.format_docstring_parameters(params) + signature = self.format_docstring_signature(f, params) docstring = "\n".join(lines) - - add(docstring) - docstring = output() - - docstring = linear_format(docstring, parameters=parameters_output) - docstring = docstring.rstrip() - - return docstring + return linear_format(docstring, + signature=signature, + parameters=parameters).rstrip() def do_post_block_processing_cleanup(self) -> None: """ From 1d244dc64220ff1f69677827149197a918d5bc5b Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Fri, 4 Aug 2023 14:00:34 +0200 Subject: [PATCH 2/7] Use splitlines() iso. comprehension Co-authored-by: Alex Waygood --- Tools/clinic/clinic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py index a8be0f03039e1d..2c5e7ae9db73d3 100755 --- a/Tools/clinic/clinic.py +++ b/Tools/clinic/clinic.py @@ -5520,7 +5520,7 @@ def format_docstring(self) -> str: # Guido said Clinic should enforce this: # http://mail.python.org/pipermail/python-dev/2013-June/127110.html - lines = [line for line in f.docstring.split('\n')] + lines = f.docstring.splitlines() if len(lines) >= 2: if lines[1]: fail("Docstring for " + f.full_name + " does not have a summary line!\n" + From 9d3ed09e64b23885c5f774610384929fa15bf8a8 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Fri, 4 Aug 2023 14:25:46 +0200 Subject: [PATCH 3/7] Revert "Use splitlines() iso. comprehension" This reverts commit 1d244dc64220ff1f69677827149197a918d5bc5b. --- Tools/clinic/clinic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py index 2c5e7ae9db73d3..a8be0f03039e1d 100755 --- a/Tools/clinic/clinic.py +++ b/Tools/clinic/clinic.py @@ -5520,7 +5520,7 @@ def format_docstring(self) -> str: # Guido said Clinic should enforce this: # http://mail.python.org/pipermail/python-dev/2013-June/127110.html - lines = f.docstring.splitlines() + lines = [line for line in f.docstring.split('\n')] if len(lines) >= 2: if lines[1]: fail("Docstring for " + f.full_name + " does not have a summary line!\n" + From 0902130a75a02d0deffd4643486d4304fd1e96e0 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Fri, 4 Aug 2023 14:28:33 +0200 Subject: [PATCH 4/7] Split, not splitlines Co-authored-by: Alex Waygood --- Tools/clinic/clinic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py index a8be0f03039e1d..c95b0f84e99963 100755 --- a/Tools/clinic/clinic.py +++ b/Tools/clinic/clinic.py @@ -5520,7 +5520,7 @@ def format_docstring(self) -> str: # Guido said Clinic should enforce this: # http://mail.python.org/pipermail/python-dev/2013-June/127110.html - lines = [line for line in f.docstring.split('\n')] + lines = f.docstring.split('\n') if len(lines) >= 2: if lines[1]: fail("Docstring for " + f.full_name + " does not have a summary line!\n" + From e3ff673ac179a0b0d0b5761c1cdbf10224529942 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 8 Aug 2023 08:52:50 +0200 Subject: [PATCH 5/7] Style Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com> --- Tools/clinic/clinic.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py index c95b0f84e99963..f85bed7bb14762 100755 --- a/Tools/clinic/clinic.py +++ b/Tools/clinic/clinic.py @@ -5310,8 +5310,8 @@ def state_function_docstring(self, line: str) -> None: @staticmethod def format_docstring_signature( - f: Function, - parameters: list[Parameter] + f: Function, + parameters: list[Parameter] ) -> str: text, add, output = _text_accumulator() if f.kind.new_or_init: From 34729c2a7821700e83ad49d8b79819a4e454e06d Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 8 Aug 2023 08:57:30 +0200 Subject: [PATCH 6/7] Fix mypy --- Tools/clinic/clinic.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py index 977ed3202a4a8b..dde7b0b7466c8d 100755 --- a/Tools/clinic/clinic.py +++ b/Tools/clinic/clinic.py @@ -5504,10 +5504,8 @@ def state_function_docstring(self, line: str) -> None: self.docstring_append(self.function, line) - @staticmethod def format_docstring_signature( - f: Function, - parameters: list[Parameter] + self, f: Function, parameters: list[Parameter] ) -> str: text, add, output = _text_accumulator() if f.kind.new_or_init: From 4b0c7ec8b9c639b61f5e982a8911cfadc9093556 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 8 Aug 2023 22:41:45 +0200 Subject: [PATCH 7/7] Remove one more unneeded rstrip --- Tools/clinic/clinic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py index 7c3cbc51714a2e..05f7ad07fd3dba 100755 --- a/Tools/clinic/clinic.py +++ b/Tools/clinic/clinic.py @@ -5694,7 +5694,7 @@ def format_docstring_parameters(params: list[Parameter]) -> str: add(" ") add(param.name) add('\n') - stripped = rstrip_lines(docstring.rstrip()) + stripped = rstrip_lines(docstring) add(textwrap.indent(stripped, " ")) if text: add('\n')