format-docstring 0.1.0__tar.gz → 0.1.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. format_docstring-0.1.2/CHANGELOG.md +37 -0
  2. {format_docstring-0.1.0 → format_docstring-0.1.2}/PKG-INFO +4 -4
  3. {format_docstring-0.1.0 → format_docstring-0.1.2}/README.md +3 -3
  4. {format_docstring-0.1.0 → format_docstring-0.1.2}/format_docstring/docstring_rewriter.py +2 -2
  5. {format_docstring-0.1.0 → format_docstring-0.1.2}/format_docstring/line_wrap_numpy.py +15 -2
  6. {format_docstring-0.1.0 → format_docstring-0.1.2}/format_docstring/line_wrap_utils.py +92 -3
  7. {format_docstring-0.1.0 → format_docstring-0.1.2}/format_docstring.egg-info/PKG-INFO +4 -4
  8. {format_docstring-0.1.0 → format_docstring-0.1.2}/pyproject.toml +1 -1
  9. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/end_to_end/numpy/contents_that_are_not_wrapped.txt +2 -0
  10. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/end_to_end/numpy/new_lines_before_and_after.txt +15 -0
  11. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/line_wrap/numpy/contents_that_are_not_wrapped.txt +2 -0
  12. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_line_wrap_numpy.py +1 -1
  13. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_line_wrap_utils.py +106 -4
  14. format_docstring-0.1.0/CHANGELOG.md +0 -14
  15. {format_docstring-0.1.0 → format_docstring-0.1.2}/.github/workflows/python-package.yml +0 -0
  16. {format_docstring-0.1.0 → format_docstring-0.1.2}/.github/workflows/python-publish.yml +0 -0
  17. {format_docstring-0.1.0 → format_docstring-0.1.2}/.gitignore +0 -0
  18. {format_docstring-0.1.0 → format_docstring-0.1.2}/.pre-commit-config.yaml +0 -0
  19. {format_docstring-0.1.0 → format_docstring-0.1.2}/.pre-commit-hooks.yaml +0 -0
  20. {format_docstring-0.1.0 → format_docstring-0.1.2}/CLAUDE.md +0 -0
  21. {format_docstring-0.1.0 → format_docstring-0.1.2}/LICENSE +0 -0
  22. {format_docstring-0.1.0 → format_docstring-0.1.2}/format_docstring/__init__.py +0 -0
  23. {format_docstring-0.1.0 → format_docstring-0.1.2}/format_docstring/base_fixer.py +0 -0
  24. {format_docstring-0.1.0 → format_docstring-0.1.2}/format_docstring/config.py +0 -0
  25. {format_docstring-0.1.0 → format_docstring-0.1.2}/format_docstring/line_wrap_google.py +0 -0
  26. {format_docstring-0.1.0 → format_docstring-0.1.2}/format_docstring/main_jupyter.py +0 -0
  27. {format_docstring-0.1.0 → format_docstring-0.1.2}/format_docstring/main_py.py +0 -0
  28. {format_docstring-0.1.0 → format_docstring-0.1.2}/format_docstring.egg-info/SOURCES.txt +0 -0
  29. {format_docstring-0.1.0 → format_docstring-0.1.2}/format_docstring.egg-info/dependency_links.txt +0 -0
  30. {format_docstring-0.1.0 → format_docstring-0.1.2}/format_docstring.egg-info/entry_points.txt +0 -0
  31. {format_docstring-0.1.0 → format_docstring-0.1.2}/format_docstring.egg-info/requires.txt +0 -0
  32. {format_docstring-0.1.0 → format_docstring-0.1.2}/format_docstring.egg-info/top_level.txt +0 -0
  33. {format_docstring-0.1.0 → format_docstring-0.1.2}/muff.toml +0 -0
  34. {format_docstring-0.1.0 → format_docstring-0.1.2}/requirements.dev +0 -0
  35. {format_docstring-0.1.0 → format_docstring-0.1.2}/setup.cfg +0 -0
  36. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/__init__.py +0 -0
  37. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/helpers.py +0 -0
  38. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_config.py +0 -0
  39. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/end_to_end/numpy/README.md +0 -0
  40. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/end_to_end/numpy/colon_spacing_fix.txt +0 -0
  41. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/end_to_end/numpy/default_value_standardization.txt +0 -0
  42. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/end_to_end/numpy/empty_lines_are_respected.txt +0 -0
  43. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/end_to_end/numpy/existing_linebreaks_should_not_be_respected.txt +0 -0
  44. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/end_to_end/numpy/four_level_nested_classes.txt +0 -0
  45. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/end_to_end/numpy/indent_four_levels_16_spaces_width_10.txt +0 -0
  46. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/end_to_end/numpy/indent_misaligned_all.txt +0 -0
  47. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/end_to_end/numpy/indent_two_levels_8_spaces.txt +0 -0
  48. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/end_to_end/numpy/line_length_2.txt +0 -0
  49. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/end_to_end/numpy/mismatched_underlines.txt +0 -0
  50. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/end_to_end/numpy/mismatched_underlines_one_dash.txt +0 -0
  51. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/end_to_end/numpy/mismatched_underlines_two_dashes.txt +0 -0
  52. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/end_to_end/numpy/module_level_docstring.txt +0 -0
  53. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/end_to_end/numpy/param_signature_without_type.txt +0 -0
  54. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/end_to_end/numpy/parameters_returns_raises_wrapping.txt +0 -0
  55. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/end_to_end/numpy/returns_signature_and_description.txt +0 -0
  56. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/end_to_end/numpy/section_title_fixed.txt +0 -0
  57. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/end_to_end/numpy/sections_notes_examples.txt +0 -0
  58. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/end_to_end/numpy/signature_line_is_not_wrapped.txt +0 -0
  59. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/end_to_end/numpy/single_line_docstring.txt +0 -0
  60. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/end_to_end/numpy/texts_are_rewrapped.txt +0 -0
  61. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/end_to_end/numpy/very_long_unbreakable_word.txt +0 -0
  62. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/integration_test/numpy/after.ipynb +0 -0
  63. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/integration_test/numpy/after.py +0 -0
  64. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/integration_test/numpy/after_50.ipynb +0 -0
  65. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/integration_test/numpy/after_50.py +0 -0
  66. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/integration_test/numpy/before.ipynb +0 -0
  67. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/integration_test/numpy/before.py +0 -0
  68. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/line_wrap/numpy/README.md +0 -0
  69. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/line_wrap/numpy/colon_spacing_fix.txt +0 -0
  70. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/line_wrap/numpy/default_value_standardization.txt +0 -0
  71. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/line_wrap/numpy/empty_lines_are_respected.txt +0 -0
  72. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/line_wrap/numpy/existing_linebreaks_should_not_be_respected.txt +0 -0
  73. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/line_wrap/numpy/indent_four_levels_16_spaces_width_10.txt +0 -0
  74. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/line_wrap/numpy/indent_two_levels_8_spaces.txt +0 -0
  75. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/line_wrap/numpy/line_length_2.txt +0 -0
  76. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/line_wrap/numpy/mismatched_underlines.txt +0 -0
  77. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/line_wrap/numpy/mismatched_underlines_one_dash.txt +0 -0
  78. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/line_wrap/numpy/mismatched_underlines_two_dashes.txt +0 -0
  79. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/line_wrap/numpy/module_level_docstring.txt +0 -0
  80. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/line_wrap/numpy/param_signature_without_type.txt +0 -0
  81. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/line_wrap/numpy/parameters_returns_raises_wrapping.txt +0 -0
  82. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/line_wrap/numpy/returns_signature_and_description.txt +0 -0
  83. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/line_wrap/numpy/section_title_fixed.txt +0 -0
  84. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/line_wrap/numpy/sections_notes_examples.txt +0 -0
  85. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/line_wrap/numpy/signature_line_is_not_wrapped.txt +0 -0
  86. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/line_wrap/numpy/texts_are_rewrapped.txt +0 -0
  87. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/line_wrap/numpy/very_long_unbreakable_word.txt +0 -0
  88. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_data/playground.py +0 -0
  89. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_docstring_rewriter.py +0 -0
  90. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_line_wrap_google.py +0 -0
  91. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_main_jupyter.py +0 -0
  92. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_main_py.py +0 -0
  93. {format_docstring-0.1.0 → format_docstring-0.1.2}/tests/test_playground.py +0 -0
  94. {format_docstring-0.1.0 → format_docstring-0.1.2}/tox.ini +0 -0
@@ -0,0 +1,37 @@
1
+ # Change Log
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on
6
+ [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project
7
+ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
8
+
9
+ ## [0.1.2] - 2025-10-08
10
+
11
+ - Added
12
+ - Support for 1 blank line after `::`
13
+ - Full diff
14
+ - https://github.com/jsh9/format-docstring/compare/0.1.1...0.1.2
15
+
16
+ ## [0.1.1] - 2025-10-06
17
+
18
+ - Fixed
19
+ - A bug where single-line docstrings exceeding length limit aren't handled
20
+ - Full diff
21
+ - https://github.com/jsh9/format-docstring/compare/0.1.0...0.1.1
22
+
23
+ ## [0.1.0] - 2025-10-06
24
+
25
+ - Added
26
+ - Initial release of format-docstring
27
+ - Support for NumPy-style docstring formatting
28
+ - Limited support for Google-style docstrings
29
+ - CLI tools: `format-docstring` and `format-docstring-jupyter`
30
+ - Configuration via `pyproject.toml` with `[tool.format_docstring]` section
31
+ - Options for line length, docstring style, and file exclusion patterns
32
+ - Pre-commit hooks for Python files and Jupyter notebooks
33
+ - Comprehensive test suite with pytest
34
+ - Type checking with mypy
35
+ - Support for Python 3.10-3.12
36
+ - Full diff
37
+ - N/A
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: format-docstring
3
- Version: 0.1.0
3
+ Version: 0.1.2
4
4
  Summary: A Python formatter to wrap/adjust docstring lines
5
5
  Author-email: jsh9 <25124332+jsh9@users.noreply.github.com>
6
6
  Maintainer-email: jsh9 <25124332+jsh9@users.noreply.github.com>
@@ -126,9 +126,9 @@ def example_function(param1, param2, option='default'):
126
126
 
127
127
  Content following double colons (::) is preserved::
128
128
 
129
- - This indented block after :: is not wrapped
130
- - Even if lines are very long they stay intact
131
- - Useful for code blocks or literal content
129
+ P(B|A) P(A)
130
+ P(A|B) = ---------------
131
+ P(B)
132
132
 
133
133
  Regular bullet lists are also preserved:
134
134
 
@@ -93,9 +93,9 @@ def example_function(param1, param2, option='default'):
93
93
 
94
94
  Content following double colons (::) is preserved::
95
95
 
96
- - This indented block after :: is not wrapped
97
- - Even if lines are very long they stay intact
98
- - Useful for code blocks or literal content
96
+ P(B|A) P(A)
97
+ P(A|B) = ---------------
98
+ P(B)
99
99
 
100
100
  Regular bullet lists are also preserved:
101
101
 
@@ -4,7 +4,7 @@ import ast
4
4
 
5
5
  from format_docstring.line_wrap_google import wrap_docstring_google
6
6
  from format_docstring.line_wrap_numpy import (
7
- handle_single_line_docstring_that_is_a_bit_too_long,
7
+ handle_single_line_docstring,
8
8
  wrap_docstring_numpy,
9
9
  )
10
10
 
@@ -168,7 +168,7 @@ def build_replacement_docstring(
168
168
 
169
169
  new_literal: str | None = rebuild_literal(original_literal, wrapped)
170
170
 
171
- new_literal = handle_single_line_docstring_that_is_a_bit_too_long(
171
+ new_literal = handle_single_line_docstring(
172
172
  whole_docstring_literal=new_literal,
173
173
  docstring_content=wrapped,
174
174
  docstring_starting_col=val.col_offset,
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import re
4
+ import textwrap
4
5
 
5
6
  from format_docstring.line_wrap_utils import (
6
7
  add_leading_indent,
@@ -358,7 +359,7 @@ def _standardize_default_value(line: str) -> str:
358
359
  return line
359
360
 
360
361
 
361
- def handle_single_line_docstring_that_is_a_bit_too_long(
362
+ def handle_single_line_docstring(
362
363
  whole_docstring_literal: str | None,
363
364
  docstring_content: str,
364
365
  docstring_starting_col: int,
@@ -382,6 +383,18 @@ def handle_single_line_docstring_that_is_a_bit_too_long(
382
383
  prefix: str = parts[0]
383
384
  postfix: str = parts[-1]
384
385
  indent: str = ' ' * num_leading_indent
385
- return f'{prefix}\n{indent}{docstring_content}\n{indent}{postfix}'
386
+
387
+ # We need to wrap `docstring_content` here because single-line
388
+ # docstrings don't get wrapped anywhere else.
389
+ tw: textwrap.TextWrapper = textwrap.TextWrapper(
390
+ width=line_length - num_leading_indent,
391
+ break_long_words=False,
392
+ break_on_hyphens=False,
393
+ replace_whitespace=False,
394
+ drop_whitespace=True,
395
+ )
396
+ wrapped_list: list[str] = tw.wrap(docstring_content)
397
+ wrapped: str = textwrap.indent('\n'.join(wrapped_list), indent)
398
+ return f'{prefix}\n{wrapped}\n{indent}{postfix}'
386
399
 
387
400
  return whole_docstring_literal
@@ -66,14 +66,79 @@ def process_temp_output(
66
66
  temp_out: list[str | list[str]],
67
67
  width: int,
68
68
  ) -> list[str]:
69
- """Wrap the `list[str]` elements in `temp_out`."""
69
+ """
70
+ Wrap the `list[str]` elements in `temp_out`.
71
+
72
+ To preserve literal blocks indicated by ``::``, the function first scans
73
+ ``temp_out`` for the pattern ``<line ending with '::'>``, followed by
74
+ ``''`` (exactly 1 empty line), followed by non-empty content. When found,
75
+ those three entries are merged into
76
+ a single ``list[str]`` so the literal block (including the separating blank
77
+ line) is wrapped as one unit.
78
+ """
79
+
80
+ def _to_list(element: str | list[str]) -> list[str]:
81
+ return [element] if isinstance(element, str) else list(element)
82
+
83
+ def _ends_with_literal_block_marker(element: str | list[str]) -> bool:
84
+ if isinstance(element, str):
85
+ return element.endswith('::')
86
+
87
+ if not element:
88
+ return False
89
+
90
+ return element[-1].endswith('::')
91
+
92
+ def _is_empty_string(element: str | list[str]) -> bool:
93
+ return isinstance(element, str) and element == ''
94
+
95
+ def _has_content(element: str | list[str]) -> bool:
96
+ if isinstance(element, str):
97
+ return element != ''
98
+
99
+ return any(line != '' for line in element)
100
+
101
+ merged_temp_out: list[str | list[str]] = []
102
+ idx = 0
103
+ while idx < len(temp_out):
104
+ current = temp_out[idx]
105
+ next_idx = idx + 1
106
+ next_next_idx = idx + 2
107
+
108
+ if (
109
+ _ends_with_literal_block_marker(current)
110
+ and next_next_idx < len(temp_out)
111
+ and _is_empty_string(temp_out[next_idx])
112
+ and _has_content(temp_out[next_next_idx])
113
+ ):
114
+ merged_element: list[str] = []
115
+ merged_element.extend(_to_list(current))
116
+ merged_element.extend(_to_list(temp_out[next_idx]))
117
+ merged_element.extend(_to_list(temp_out[next_next_idx]))
118
+ merged_temp_out.append(merged_element)
119
+ idx += 3
120
+ continue
121
+
122
+ merged_temp_out.append(current)
123
+ idx += 1
124
+
70
125
  out: list[str] = []
71
126
 
72
- for element in temp_out:
127
+ for element in merged_temp_out:
73
128
  if isinstance(element, str):
74
129
  out.append(element)
75
130
  elif isinstance(element, list):
76
131
  wrapped: list[str] = wrap_preserving_indent(element, width)
132
+ if (
133
+ '' in element
134
+ and '' not in wrapped
135
+ and element.index('') < len(element) - 1
136
+ ):
137
+ insertion_idx = min(element.index(''), len(wrapped))
138
+ wrapped = (
139
+ wrapped[:insertion_idx] + [''] + wrapped[insertion_idx:]
140
+ )
141
+
77
142
  out.extend(wrapped)
78
143
  else:
79
144
  raise RuntimeError("Something's wrong. Please contact the author.")
@@ -185,7 +250,31 @@ def _wrap_text_segment(lines: list[str], width: int) -> list[str]:
185
250
  if result and result[-1] == '':
186
251
  result.pop()
187
252
 
188
- return result if result else lines
253
+ result_: list[str] = result if result else lines
254
+
255
+ return _add_back_leading_or_trailing_newline(
256
+ original_lines=lines,
257
+ wrapped_lines=result_,
258
+ )
259
+
260
+
261
+ def _add_back_leading_or_trailing_newline(
262
+ original_lines: list[str],
263
+ wrapped_lines: list[str],
264
+ ) -> list[str]:
265
+ if len(original_lines) == 0 or len(wrapped_lines) == 0:
266
+ return wrapped_lines
267
+
268
+ new_result: list[str] = []
269
+ if original_lines[0] == '':
270
+ new_result = [''] + wrapped_lines
271
+ else:
272
+ new_result = wrapped_lines
273
+
274
+ if original_lines[-1] == '':
275
+ return new_result + ['']
276
+
277
+ return new_result
189
278
 
190
279
 
191
280
  def merge_lines_and_strip(text: str) -> str:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: format-docstring
3
- Version: 0.1.0
3
+ Version: 0.1.2
4
4
  Summary: A Python formatter to wrap/adjust docstring lines
5
5
  Author-email: jsh9 <25124332+jsh9@users.noreply.github.com>
6
6
  Maintainer-email: jsh9 <25124332+jsh9@users.noreply.github.com>
@@ -126,9 +126,9 @@ def example_function(param1, param2, option='default'):
126
126
 
127
127
  Content following double colons (::) is preserved::
128
128
 
129
- - This indented block after :: is not wrapped
130
- - Even if lines are very long they stay intact
131
- - Useful for code blocks or literal content
129
+ P(B|A) P(A)
130
+ P(A|B) = ---------------
131
+ P(B)
132
132
 
133
133
  Regular bullet lists are also preserved:
134
134
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "format-docstring"
7
- version = "0.1.0"
7
+ version = "0.1.2"
8
8
  description = "A Python formatter to wrap/adjust docstring lines"
9
9
  readme = "README.md"
10
10
  license = {text = "MIT"}
@@ -7,6 +7,7 @@ def func1():
7
7
  def func3():
8
8
  """
9
9
  Below is a formula that should not be wrapped. Here are some more contents that are arbitrary just to make the line length quite long so that we can test how it can be wrapped. This paragraph would end with two colons to signal that the contents below should not be wrapped::
10
+
10
11
  x^alpha * beta
11
12
  y(x) = --------------------------------
12
13
  1 gamma^a * tau
@@ -59,6 +60,7 @@ def func1():
59
60
  so that we can test how it can be wrapped. This paragraph would end
60
61
  with two colons to signal that the contents below should not be
61
62
  wrapped::
63
+
62
64
  x^alpha * beta
63
65
  y(x) = --------------------------------
64
66
  1 gamma^a * tau
@@ -61,6 +61,12 @@ def func8():
61
61
  nf of pf qf rf sf tf uf vf wf xf yf zf 1f 2f 3f 4f 5f 6f 7f 8f 9f 0f af bf cf df ef ff gf hf if jf kf lf mf"""
62
62
  pass
63
63
 
64
+
65
+ def func9():
66
+ def get_scores(self) -> np.ndarray:
67
+ """Return entire score array, with 'None' for scores that haven't been calculated."""
68
+ return self.scores
69
+
64
70
  **********
65
71
 
66
72
  def func1():
@@ -133,3 +139,12 @@ def func8():
133
139
  df ef ff gf hf if jf kf lf mf
134
140
  """
135
141
  pass
142
+
143
+
144
+ def func9():
145
+ def get_scores(self) -> np.ndarray:
146
+ """
147
+ Return entire score array, with 'None' for scores that haven't been
148
+ calculated.
149
+ """
150
+ return self.scores
@@ -3,6 +3,7 @@ LINE_LENGTH: 79
3
3
  **********
4
4
 
5
5
  Below is a formula that should not be wrapped. Here are some more contents that are arbitrary just to make the line length quite long so that we can test how it can be wrapped. This paragraph would end with two colons to signal that the contents below should not be wrapped::
6
+
6
7
  x^alpha * beta
7
8
  y(x) = --------------------------------
8
9
  1 gamma^a * tau
@@ -48,6 +49,7 @@ Below is a formula that should not be wrapped. Here are some more contents that
48
49
  are arbitrary just to make the line length quite long so that we can test how
49
50
  it can be wrapped. This paragraph would end with two colons to signal that the
50
51
  contents below should not be wrapped::
52
+
51
53
  x^alpha * beta
52
54
  y(x) = --------------------------------
53
55
  1 gamma^a * tau
@@ -35,7 +35,7 @@ def test_wrap_docstring_single_case() -> None:
35
35
  the test case file that's producing errors.
36
36
  """
37
37
  filename, length, before, after = load_case_from_file(
38
- DATA_DIR / 'mismatched_underlines_two_dashes.txt'
38
+ DATA_DIR / 'contents_that_are_not_wrapped.txt'
39
39
  )
40
40
  out = wrap_docstring(before, line_length=length, docstring_style='numpy')
41
41
  assert out.strip('\n') == after.strip('\n')
@@ -9,6 +9,7 @@ from format_docstring.line_wrap_utils import (
9
9
  is_bulleted_list,
10
10
  is_rST_table,
11
11
  merge_lines_and_strip,
12
+ process_temp_output,
12
13
  segment_lines_by_wrappability,
13
14
  wrap_preserving_indent,
14
15
  )
@@ -125,7 +126,7 @@ from format_docstring.line_wrap_utils import (
125
126
  # Test with rST table (should be preserved)
126
127
  (
127
128
  [
128
- 'Here is some text that should wrap.',
129
+ 'Here is some text that should wrap. 1.',
129
130
  '',
130
131
  '+------+-----+',
131
132
  '| Name | Age |',
@@ -138,12 +139,14 @@ from format_docstring.line_wrap_utils import (
138
139
  20,
139
140
  [
140
141
  'Here is some text',
141
- 'that should wrap.',
142
+ 'that should wrap. 1.',
143
+ '',
142
144
  '+------+-----+',
143
145
  '| Name | Age |',
144
146
  '+------+-----+',
145
147
  '| John | 25 |',
146
148
  '+------+-----+',
149
+ '',
147
150
  'More text that',
148
151
  'should wrap.',
149
152
  ],
@@ -151,7 +154,7 @@ from format_docstring.line_wrap_utils import (
151
154
  # Test with bulleted list (should be preserved)
152
155
  (
153
156
  [
154
- 'This is a very long line of text that should be wrapped.',
157
+ 'This is a very long line of text that should be wrapped. 2',
155
158
  '',
156
159
  '- First list item that is quite long',
157
160
  '- Second list item that is also long',
@@ -162,9 +165,11 @@ from format_docstring.line_wrap_utils import (
162
165
  [
163
166
  'This is a very long line',
164
167
  'of text that should be',
165
- 'wrapped.',
168
+ 'wrapped. 2',
169
+ '',
166
170
  '- First list item that is quite long',
167
171
  '- Second list item that is also long',
172
+ '',
168
173
  'Another long line that',
169
174
  'should be wrapped.',
170
175
  ],
@@ -218,6 +223,103 @@ def test_finalize_lines(
218
223
  assert finalize_lines(lines, leading_indent) == expected
219
224
 
220
225
 
226
+ @pytest.mark.parametrize(
227
+ 'temp_out,width,expected',
228
+ [
229
+ (
230
+ [
231
+ 'Examples::',
232
+ '',
233
+ [' code line 1', ' code line 2'],
234
+ ],
235
+ 20,
236
+ [
237
+ 'Examples::',
238
+ '',
239
+ ' code line 1',
240
+ ' code line 2',
241
+ ],
242
+ ),
243
+ (
244
+ [
245
+ 'Examples::',
246
+ '',
247
+ [
248
+ ' literal block with long text that should remain'
249
+ ' on one line even though width is short'
250
+ ],
251
+ ],
252
+ 30,
253
+ [
254
+ 'Examples::',
255
+ '',
256
+ (
257
+ ' literal block with long text that should remain'
258
+ ' on one line even though width is short'
259
+ ),
260
+ ],
261
+ ),
262
+ (
263
+ [
264
+ 'Examples::',
265
+ '',
266
+ '', # 2 empty lines: not protected by `::` above -> will wrap
267
+ [
268
+ (
269
+ ' literal block with long text that should remain'
270
+ ' on one line even though width is short'
271
+ )
272
+ ],
273
+ ],
274
+ 30,
275
+ [
276
+ 'Examples::',
277
+ '',
278
+ '',
279
+ ' literal block with long',
280
+ ' text that should remain on',
281
+ ' one line even though width',
282
+ ' is short',
283
+ ],
284
+ ),
285
+ (
286
+ [
287
+ 'Examples::',
288
+ 'no blank separator',
289
+ [' code line 1', ' code line 2'],
290
+ ],
291
+ 40,
292
+ [
293
+ 'Examples::',
294
+ 'no blank separator',
295
+ ' code line 1 code line 2',
296
+ ],
297
+ ),
298
+ (
299
+ [
300
+ 'Examples::',
301
+ '',
302
+ '',
303
+ 'Trailing text',
304
+ ],
305
+ 25,
306
+ [
307
+ 'Examples::',
308
+ '',
309
+ '',
310
+ 'Trailing text',
311
+ ],
312
+ ),
313
+ ],
314
+ )
315
+ def test_process_temp_output_merges_literal_block(
316
+ temp_out: list[str | list[str]],
317
+ width: int,
318
+ expected: list[str],
319
+ ) -> None:
320
+ assert process_temp_output(temp_out, width) == expected
321
+
322
+
221
323
  @pytest.mark.parametrize(
222
324
  'text,expected',
223
325
  [
@@ -1,14 +0,0 @@
1
- # Change Log
2
-
3
- All notable changes to this project will be documented in this file.
4
-
5
- The format is based on
6
- [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project
7
- adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
8
-
9
- ## [0.1.0] - 2025-09-07
10
-
11
- - Added
12
- - Initial release
13
- - Full diff
14
- - N/A