format-docstring 0.1.6__tar.gz → 0.1.8__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.
- {format_docstring-0.1.6 → format_docstring-0.1.8}/CHANGELOG.md +31 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/PKG-INFO +1 -1
- {format_docstring-0.1.6 → format_docstring-0.1.8}/format_docstring/line_wrap_numpy.py +132 -31
- {format_docstring-0.1.6 → format_docstring-0.1.8}/format_docstring.egg-info/PKG-INFO +1 -1
- {format_docstring-0.1.6 → format_docstring-0.1.8}/pyproject.toml +1 -1
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/end_to_end/numpy/fix_rst_backticks.txt +21 -3
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/line_wrap/numpy/fix_rst_backticks.txt +26 -2
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_line_wrap_numpy.py +78 -2
- {format_docstring-0.1.6 → format_docstring-0.1.8}/.github/workflows/python-package.yml +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/.github/workflows/python-publish.yml +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/.gitignore +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/.pre-commit-config.yaml +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/.pre-commit-hooks.yaml +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/CLAUDE.md +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/LICENSE +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/README.md +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/format_docstring/__init__.py +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/format_docstring/base_fixer.py +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/format_docstring/config.py +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/format_docstring/docstring_rewriter.py +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/format_docstring/line_wrap_google.py +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/format_docstring/line_wrap_utils.py +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/format_docstring/main_jupyter.py +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/format_docstring/main_py.py +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/format_docstring.egg-info/SOURCES.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/format_docstring.egg-info/dependency_links.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/format_docstring.egg-info/entry_points.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/format_docstring.egg-info/requires.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/format_docstring.egg-info/top_level.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/muff.toml +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/requirements.dev +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/setup.cfg +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/__init__.py +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/helpers.py +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_config.py +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/end_to_end/numpy/README.md +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/end_to_end/numpy/colon_spacing_fix.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/end_to_end/numpy/contents_that_are_not_wrapped.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/end_to_end/numpy/default_value_standardization.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/end_to_end/numpy/empty_lines_are_respected.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/end_to_end/numpy/examples_section.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/end_to_end/numpy/existing_linebreaks_should_not_be_respected.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/end_to_end/numpy/four_level_nested_classes.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/end_to_end/numpy/indent_four_levels_16_spaces_width_10.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/end_to_end/numpy/indent_misaligned_all.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/end_to_end/numpy/indent_two_levels_8_spaces.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/end_to_end/numpy/line_length_2.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/end_to_end/numpy/mismatched_underlines.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/end_to_end/numpy/mismatched_underlines_one_dash.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/end_to_end/numpy/mismatched_underlines_two_dashes.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/end_to_end/numpy/module_level_docstring.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/end_to_end/numpy/new_lines_before_and_after.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/end_to_end/numpy/param_signature_without_type.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/end_to_end/numpy/parameters_returns_raises_wrapping.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/end_to_end/numpy/returns_signature_and_description.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/end_to_end/numpy/section_title_fixed.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/end_to_end/numpy/sections_notes_examples.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/end_to_end/numpy/signature_line_is_not_wrapped.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/end_to_end/numpy/single_line_docstring.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/end_to_end/numpy/texts_are_rewrapped.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/end_to_end/numpy/very_long_unbreakable_word.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/integration_test/numpy/after.ipynb +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/integration_test/numpy/after.py +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/integration_test/numpy/after_50.ipynb +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/integration_test/numpy/after_50.py +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/integration_test/numpy/before.ipynb +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/integration_test/numpy/before.py +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/line_wrap/numpy/README.md +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/line_wrap/numpy/colon_spacing_fix.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/line_wrap/numpy/contents_that_are_not_wrapped.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/line_wrap/numpy/default_value_standardization.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/line_wrap/numpy/empty_lines_are_respected.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/line_wrap/numpy/examples_section.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/line_wrap/numpy/existing_linebreaks_should_not_be_respected.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/line_wrap/numpy/indent_four_levels_16_spaces_width_10.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/line_wrap/numpy/indent_two_levels_8_spaces.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/line_wrap/numpy/line_length_2.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/line_wrap/numpy/mismatched_underlines.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/line_wrap/numpy/mismatched_underlines_one_dash.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/line_wrap/numpy/mismatched_underlines_two_dashes.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/line_wrap/numpy/module_level_docstring.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/line_wrap/numpy/param_signature_without_type.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/line_wrap/numpy/parameters_returns_raises_wrapping.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/line_wrap/numpy/returns_signature_and_description.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/line_wrap/numpy/section_title_fixed.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/line_wrap/numpy/sections_notes_examples.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/line_wrap/numpy/signature_line_is_not_wrapped.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/line_wrap/numpy/texts_are_rewrapped.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/line_wrap/numpy/very_long_unbreakable_word.txt +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/playground.py +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_docstring_rewriter.py +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_line_wrap_google.py +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_line_wrap_utils.py +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_main_jupyter.py +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_main_py.py +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_playground.py +0 -0
- {format_docstring-0.1.6 → format_docstring-0.1.8}/tox.ini +0 -0
|
@@ -6,6 +6,37 @@ The format is based on
|
|
|
6
6
|
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project
|
|
7
7
|
adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
8
8
|
|
|
9
|
+
## [0.1.8] - 2025-10-14
|
|
10
|
+
|
|
11
|
+
- Fixed
|
|
12
|
+
- Bug in `_fix_rst_backticks()` where backtick pairs spanning multiple lines
|
|
13
|
+
(e.g., multi-line external links) were incorrectly processed
|
|
14
|
+
- Added `(?!_)` lookahead to regex pattern to prevent matching trailing
|
|
15
|
+
backticks from cross-references (e.g., `` `text`_ ``)
|
|
16
|
+
- Changed
|
|
17
|
+
- Moved backtick fixing from line-by-line processing to whole-docstring
|
|
18
|
+
processing to correctly handle multi-line constructs
|
|
19
|
+
- REPL lines (starting with `>>> ` or `... `) are now protected with
|
|
20
|
+
placeholders during backtick fixing to preserve backticks in Python
|
|
21
|
+
examples
|
|
22
|
+
- Added
|
|
23
|
+
- Test cases for multi-line external links in
|
|
24
|
+
`test_fix_rst_backticks_cases()`
|
|
25
|
+
- Test cases for REPL lines with backticks in
|
|
26
|
+
`test_fix_rst_backticks_cases()`
|
|
27
|
+
- Full diff
|
|
28
|
+
- https://github.com/jsh9/format-docstring/compare/0.1.7...0.1.8
|
|
29
|
+
|
|
30
|
+
## [0.1.7] - 2025-10-14
|
|
31
|
+
|
|
32
|
+
- Fixed
|
|
33
|
+
- Backtick fixing logic to properly distinguish between inline literals and
|
|
34
|
+
external links (e.g., `` `Python <https://example.org>`_ ``)
|
|
35
|
+
- Refactored `_fix_rst_backticks()` to use pre-compiled regex pattern for
|
|
36
|
+
better performance
|
|
37
|
+
- Full diff
|
|
38
|
+
- https://github.com/jsh9/format-docstring/compare/0.1.6...0.1.7
|
|
39
|
+
|
|
9
40
|
## [0.1.6] - 2025-10-13
|
|
10
41
|
|
|
11
42
|
- Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: format-docstring
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.8
|
|
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>
|
|
@@ -37,6 +37,12 @@ def wrap_docstring_numpy(
|
|
|
37
37
|
# This helps place the closing quotes on their own indented line later.
|
|
38
38
|
docstring_: str = add_leading_indent(docstring, leading_indent)
|
|
39
39
|
|
|
40
|
+
# Apply backtick fixing to the entire docstring first, before line-by-line
|
|
41
|
+
# processing. This ensures that backtick pairs spanning multiple lines are
|
|
42
|
+
# handled correctly.
|
|
43
|
+
if fix_rst_backticks:
|
|
44
|
+
docstring_ = _fix_rst_backticks(docstring_)
|
|
45
|
+
|
|
40
46
|
lines: list[str] = docstring_.splitlines()
|
|
41
47
|
if not lines:
|
|
42
48
|
return docstring_
|
|
@@ -132,10 +138,7 @@ def wrap_docstring_numpy(
|
|
|
132
138
|
continue
|
|
133
139
|
|
|
134
140
|
# Description lines (typically indented): wrap if too long
|
|
135
|
-
|
|
136
|
-
_fix_rst_backticks(line) if fix_rst_backticks else line
|
|
137
|
-
)
|
|
138
|
-
collect_to_temp_output(temp_out, line_to_process)
|
|
141
|
+
collect_to_temp_output(temp_out, line)
|
|
139
142
|
i += 1
|
|
140
143
|
continue
|
|
141
144
|
|
|
@@ -152,18 +155,12 @@ def wrap_docstring_numpy(
|
|
|
152
155
|
i += 1
|
|
153
156
|
continue
|
|
154
157
|
|
|
155
|
-
|
|
156
|
-
_fix_rst_backticks(line) if fix_rst_backticks else line
|
|
157
|
-
)
|
|
158
|
-
collect_to_temp_output(temp_out, line_to_process)
|
|
158
|
+
collect_to_temp_output(temp_out, line)
|
|
159
159
|
i += 1
|
|
160
160
|
continue
|
|
161
161
|
|
|
162
162
|
# Examples or any other section
|
|
163
|
-
|
|
164
|
-
_fix_rst_backticks(line) if fix_rst_backticks else line
|
|
165
|
-
)
|
|
166
|
-
collect_to_temp_output(temp_out, line_to_process)
|
|
163
|
+
collect_to_temp_output(temp_out, line)
|
|
167
164
|
i += 1
|
|
168
165
|
|
|
169
166
|
out: list[str] = process_temp_output(temp_out, width=line_length)
|
|
@@ -415,15 +412,51 @@ def handle_single_line_docstring(
|
|
|
415
412
|
return whole_docstring_literal
|
|
416
413
|
|
|
417
414
|
|
|
415
|
+
# Precompiled regex for fixing RST backticks.
|
|
416
|
+
# Pattern matches inline literals while avoiding roles, cross-references, and
|
|
417
|
+
# links. See the documentation of _fix_rst_backticks() for more details.
|
|
418
|
+
# The pattern allows backticks after: start of line, whitespace, parentheses,
|
|
419
|
+
# or certain punctuation (like > and . for `>>> ` and `... ` literals)
|
|
420
|
+
# Note: We match [^`]+ (anything except backticks) and then check in the
|
|
421
|
+
# replacement function whether it's an external link (contains < followed by >)
|
|
422
|
+
# The opening backtick must not be immediately followed by _ or __ (to avoid
|
|
423
|
+
# matching the trailing backtick of cross-references like `text`_ or `text`__)
|
|
424
|
+
_RST_BACKTICK_PATTERN = re.compile(
|
|
425
|
+
r'(?:^|(?<=\s)|(?<=\()|(?<=[>.]))(?::[\w-]+:)?`(?!_)([^`]+)`(?!`)(?!__)(?!_)'
|
|
426
|
+
)
|
|
427
|
+
|
|
428
|
+
|
|
418
429
|
def _fix_rst_backticks(docstring: str) -> str:
|
|
419
430
|
"""
|
|
420
|
-
Fix single backticks to double backticks per rST syntax.
|
|
421
|
-
|
|
422
|
-
This function converts pairs of single backticks (
|
|
423
|
-
backticks (``).
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
431
|
+
Fix inline-literal single backticks to double backticks per rST syntax.
|
|
432
|
+
|
|
433
|
+
This function converts pairs of single backticks (`` `...` ``) that
|
|
434
|
+
represent inline *literals* into pairs of double backticks (`` ``...`` ``).
|
|
435
|
+
It deliberately **does not** modify other rST constructs that require
|
|
436
|
+
single backticks.
|
|
437
|
+
|
|
438
|
+
What stays untouched
|
|
439
|
+
--------------------
|
|
440
|
+
- Existing double-backtick literals: ````code````.
|
|
441
|
+
- Roles: ``:role:`text``` (e.g., ``:emphasis:`word```).
|
|
442
|
+
- Cross-references: `` `text`_ `` and anonymous refs `` `text`__ ``.
|
|
443
|
+
- Inline external links: `` `text <https://example.com>`_ ``.
|
|
444
|
+
- Explicit hyperlink targets: ``.. _`Label`: https://example.com``.
|
|
445
|
+
- REPL lines: Lines starting with ``>>> `` or ``... `` (Python examples).
|
|
446
|
+
|
|
447
|
+
How it works (regex guards)
|
|
448
|
+
---------------------------
|
|
449
|
+
The pattern only upgrades a match when **all** these are true:
|
|
450
|
+
- Opening backtick is not part of an existing ````...```` (``(?<!`)``).
|
|
451
|
+
- Opening backtick is not immediately preceded by ``:`` (to avoid roles).
|
|
452
|
+
- Opening backtick is not immediately preceded by ``_`` (to avoid
|
|
453
|
+
explicit targets like ``.. _`Label`: …``).
|
|
454
|
+
- The enclosed text contains **no** backticks and **no** ``<`` (to avoid
|
|
455
|
+
inline-link forms like `` `text <url>`_ ``).
|
|
456
|
+
- Closing backtick is not part of ````...```` (``(?!`)``).
|
|
457
|
+
- Closing backtick is not followed by ``__`` or ``_`` (to avoid
|
|
458
|
+
anonymous/named references).
|
|
459
|
+
- The line does not start with ``>>> `` or ``... `` (Python REPL).
|
|
427
460
|
|
|
428
461
|
Parameters
|
|
429
462
|
----------
|
|
@@ -433,23 +466,91 @@ def _fix_rst_backticks(docstring: str) -> str:
|
|
|
433
466
|
Returns
|
|
434
467
|
-------
|
|
435
468
|
str
|
|
436
|
-
The docstring with
|
|
469
|
+
The docstring with only inline-literal backticks fixed.
|
|
437
470
|
|
|
438
471
|
Examples
|
|
439
472
|
--------
|
|
440
473
|
>>> _fix_rst_backticks('Use `foo` to do something')
|
|
441
474
|
'Use ``foo`` to do something'
|
|
475
|
+
|
|
476
|
+
>>> _fix_rst_backticks('Edge punctuation: `x`.')
|
|
477
|
+
'Edge punctuation: ``x``.'
|
|
478
|
+
|
|
479
|
+
>>> _fix_rst_backticks(':emphasis:`word`')
|
|
480
|
+
':emphasis:`word`'
|
|
481
|
+
|
|
482
|
+
>>> _fix_rst_backticks('See `Link`_ for details')
|
|
483
|
+
'See `Link`_ for details'
|
|
484
|
+
|
|
485
|
+
>>> _fix_rst_backticks('`Python <https://www.python.org>`_')
|
|
486
|
+
'`Python <https://www.python.org>`_'
|
|
487
|
+
|
|
488
|
+
>>> _fix_rst_backticks('.. _`Special Target`: https://example.com/special')
|
|
489
|
+
'.. _`Special Target`: https://example.com/special'
|
|
490
|
+
|
|
442
491
|
>>> _fix_rst_backticks('Already has ``foo`` double backticks')
|
|
443
492
|
'Already has ``foo`` double backticks'
|
|
493
|
+
|
|
494
|
+
>>> _fix_rst_backticks('>>> `foo` in REPL')
|
|
495
|
+
'>>> `foo` in REPL'
|
|
444
496
|
"""
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
497
|
+
|
|
498
|
+
def replace_func(match: re.Match[str]) -> str:
|
|
499
|
+
# match.group(0) is the full match
|
|
500
|
+
# match.group(1) is the content between backticks
|
|
501
|
+
full_match: str = match.group(0)
|
|
502
|
+
content: str = match.group(1)
|
|
503
|
+
|
|
504
|
+
# If the match includes a role prefix (like :emphasis:), don't replace
|
|
505
|
+
if ':' in full_match and full_match.index('`') > 0:
|
|
506
|
+
# Check if there's a role prefix before the backtick
|
|
507
|
+
before_backtick = full_match[: full_match.index('`')]
|
|
508
|
+
if ':' in before_backtick:
|
|
509
|
+
return full_match # Keep original (it's a role)
|
|
510
|
+
|
|
511
|
+
# Check if this is an external link (contains <...> pattern)
|
|
512
|
+
# External links look like: `text <url>`_
|
|
513
|
+
if '<' in content and '>' in content:
|
|
514
|
+
# Check if < comes before > (basic validation)
|
|
515
|
+
if content.index('<') < content.rindex('>'):
|
|
516
|
+
return full_match # Keep original (it's an external link)
|
|
517
|
+
|
|
518
|
+
# Otherwise, replace single backticks with double
|
|
519
|
+
# Keep any leading whitespace/parenthesis/punctuation
|
|
520
|
+
prefix = match.group(0)[: match.group(0).index('`')]
|
|
521
|
+
return f'{prefix}``{content}``'
|
|
522
|
+
|
|
523
|
+
# Protect REPL lines (>>> and ...) from backtick fixing by temporarily
|
|
524
|
+
# replacing them with placeholders, then restoring after processing.
|
|
525
|
+
# This allows multi-line backtick pairs (such as external links spanning
|
|
526
|
+
# lines) to be handled correctly while still preserving backticks in REPL
|
|
527
|
+
# comments.
|
|
528
|
+
lines = docstring.splitlines(keepends=True)
|
|
529
|
+
repl_lines: dict[int, str] = {}
|
|
530
|
+
protected_lines: list[str] = []
|
|
531
|
+
|
|
532
|
+
for i, line in enumerate(lines):
|
|
533
|
+
stripped = line.lstrip()
|
|
534
|
+
# Protect REPL lines (>>> or ...) - don't fix backticks in these
|
|
535
|
+
if stripped.startswith('>>> ') or stripped.startswith('... '):
|
|
536
|
+
repl_lines[i] = line
|
|
537
|
+
# Use a placeholder that won't be matched by the regex
|
|
538
|
+
protected_lines.append(
|
|
539
|
+
'\x00REPL_LINE\x00\n'
|
|
540
|
+
if line.endswith('\n')
|
|
541
|
+
else '\x00REPL_LINE\x00'
|
|
542
|
+
)
|
|
543
|
+
else:
|
|
544
|
+
protected_lines.append(line)
|
|
545
|
+
|
|
546
|
+
# Process the entire docstring (with REPL lines protected)
|
|
547
|
+
protected_docstring = ''.join(protected_lines)
|
|
548
|
+
processed = _RST_BACKTICK_PATTERN.sub(replace_func, protected_docstring)
|
|
549
|
+
|
|
550
|
+
# Restore REPL lines
|
|
551
|
+
result_lines = processed.splitlines(keepends=True)
|
|
552
|
+
for i, original_line in repl_lines.items():
|
|
553
|
+
if i < len(result_lines):
|
|
554
|
+
result_lines[i] = original_line
|
|
555
|
+
|
|
556
|
+
return ''.join(result_lines)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: format-docstring
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.8
|
|
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>
|
|
@@ -41,6 +41,15 @@ def process_data(data, config=None):
|
|
|
41
41
|
When `mode` is set to `'advanced'`, additional processing steps are
|
|
42
42
|
applied. The `threshold` parameter controls filtering behavior.
|
|
43
43
|
|
|
44
|
+
For rST roles like :emphasis:`important` and :sup:`2`, the single backticks
|
|
45
|
+
should remain. Cross-references like `Section`_ and anonymous refs like
|
|
46
|
+
`Link`__ should not be modified. External links such as `Python
|
|
47
|
+
<https://www.python.org>`_ must stay as-is.
|
|
48
|
+
|
|
49
|
+
Here's another example where long URLs extend to the next line `Here is the
|
|
50
|
+
Link <https://www.this-is-a-url-that-is-long.com>`_ and `Another One
|
|
51
|
+
<https://www.this-is-another-url-that-is-long.com>`_.
|
|
52
|
+
|
|
44
53
|
Examples
|
|
45
54
|
--------
|
|
46
55
|
>>> data = [{'id': 1, 'value': 10}]
|
|
@@ -98,14 +107,14 @@ def process_data(data, config=None):
|
|
|
98
107
|
config : dict, optional
|
|
99
108
|
Configuration dictionary. Valid keys are ``mode``, ``threshold``, and
|
|
100
109
|
``output_format``. Default is ``None``.
|
|
101
|
-
processor :
|
|
110
|
+
processor : ``DataProcessor``
|
|
102
111
|
The ``processor`` instance to use for data transformation.
|
|
103
112
|
|
|
104
113
|
Returns
|
|
105
114
|
-------
|
|
106
115
|
dict
|
|
107
116
|
Processed data with keys ``results``, ``metadata``, and ``status``.
|
|
108
|
-
|
|
117
|
+
``ProcessedData``
|
|
109
118
|
Alternative format with ``data`` and ``errors`` fields.
|
|
110
119
|
|
|
111
120
|
Raises
|
|
@@ -123,6 +132,15 @@ def process_data(data, config=None):
|
|
|
123
132
|
When ``mode`` is set to ``'advanced'``, additional processing steps are
|
|
124
133
|
applied. The ``threshold`` parameter controls filtering behavior.
|
|
125
134
|
|
|
135
|
+
For rST roles like :emphasis:`important` and :sup:`2`, the single backticks
|
|
136
|
+
should remain. Cross-references like `Section`_ and anonymous refs like
|
|
137
|
+
`Link`__ should not be modified. External links such as `Python
|
|
138
|
+
<https://www.python.org>`_ must stay as-is.
|
|
139
|
+
|
|
140
|
+
Here's another example where long URLs extend to the next line `Here is the
|
|
141
|
+
Link <https://www.this-is-a-url-that-is-long.com>`_ and `Another One
|
|
142
|
+
<https://www.this-is-another-url-that-is-long.com>`_.
|
|
143
|
+
|
|
126
144
|
Examples
|
|
127
145
|
--------
|
|
128
146
|
>>> data = [{'id': 1, 'value': 10}]
|
|
@@ -149,7 +167,7 @@ class DataProcessor:
|
|
|
149
167
|
``'advanced'``.
|
|
150
168
|
pipelines : list
|
|
151
169
|
List of ``Pipeline`` objects to apply.
|
|
152
|
-
config :
|
|
170
|
+
config : ``ConfigDict``
|
|
153
171
|
Configuration for the ``processor`` with ``settings`` dictionary.
|
|
154
172
|
"""
|
|
155
173
|
|
|
@@ -29,6 +29,18 @@ Notes
|
|
|
29
29
|
When using `special_value`, ensure that `config` is set properly. The
|
|
30
30
|
`default_value` is `None` by default.
|
|
31
31
|
|
|
32
|
+
This section also contains rST roles like :emphasis:`word` and :strong:`bold`
|
|
33
|
+
that should remain unchanged. Cross-references like `Section`_ should not be
|
|
34
|
+
modified, nor should anonymous refs like `Docs`__. External links like `Python
|
|
35
|
+
<https://www.python.org>`_ must also stay as-is.
|
|
36
|
+
|
|
37
|
+
Explicit targets like shown in the directive ``.. _`Special Target`:
|
|
38
|
+
https://example.com/special`` should not be touched.
|
|
39
|
+
|
|
40
|
+
Here's another example where long URLs extend to the next line `Here is perhaps
|
|
41
|
+
the Link <https://www.this-is-a-url-that-is-long.com>`_ and `Another One
|
|
42
|
+
<https://www.this-is-another-url-that-is-long.com>`_.
|
|
43
|
+
|
|
32
44
|
Examples
|
|
33
45
|
--------
|
|
34
46
|
>>> data = [{'id': 1, 'value': 10}]
|
|
@@ -47,14 +59,14 @@ arg1 : str
|
|
|
47
59
|
Use ``method_name`` to access this value.
|
|
48
60
|
arg2 : int
|
|
49
61
|
The value should be between ``1`` and ``100``.
|
|
50
|
-
config :
|
|
62
|
+
config : ``ConfigType``
|
|
51
63
|
A ``Config`` object for settings.
|
|
52
64
|
|
|
53
65
|
Returns
|
|
54
66
|
-------
|
|
55
67
|
dict
|
|
56
68
|
A dictionary with keys ``result`` and ``status``.
|
|
57
|
-
|
|
69
|
+
``ResultDict``
|
|
58
70
|
An alternative return format with ``data`` field.
|
|
59
71
|
|
|
60
72
|
See Also
|
|
@@ -67,6 +79,18 @@ Notes
|
|
|
67
79
|
When using ``special_value``, ensure that ``config`` is set properly. The
|
|
68
80
|
``default_value`` is ``None`` by default.
|
|
69
81
|
|
|
82
|
+
This section also contains rST roles like :emphasis:`word` and :strong:`bold`
|
|
83
|
+
that should remain unchanged. Cross-references like `Section`_ should not be
|
|
84
|
+
modified, nor should anonymous refs like `Docs`__. External links like `Python
|
|
85
|
+
<https://www.python.org>`_ must also stay as-is.
|
|
86
|
+
|
|
87
|
+
Explicit targets like shown in the directive ``.. _`Special Target`:
|
|
88
|
+
https://example.com/special`` should not be touched.
|
|
89
|
+
|
|
90
|
+
Here's another example where long URLs extend to the next line `Here is perhaps
|
|
91
|
+
the Link <https://www.this-is-a-url-that-is-long.com>`_ and `Another One
|
|
92
|
+
<https://www.this-is-another-url-that-is-long.com>`_.
|
|
93
|
+
|
|
70
94
|
Examples
|
|
71
95
|
--------
|
|
72
96
|
>>> data = [{'id': 1, 'value': 10}]
|
|
@@ -5,6 +5,7 @@ import pytest
|
|
|
5
5
|
from format_docstring.docstring_rewriter import wrap_docstring
|
|
6
6
|
from format_docstring.line_wrap_numpy import (
|
|
7
7
|
_fix_colon_spacing,
|
|
8
|
+
_fix_rst_backticks,
|
|
8
9
|
_get_section_heading_title,
|
|
9
10
|
_is_hyphen_underline,
|
|
10
11
|
_is_param_signature,
|
|
@@ -243,6 +244,81 @@ def test_standardize_default_value(line: str, expected: str) -> None:
|
|
|
243
244
|
assert _standardize_default_value(line) == expected
|
|
244
245
|
|
|
245
246
|
|
|
247
|
+
@pytest.mark.parametrize(
|
|
248
|
+
'src, expected',
|
|
249
|
+
[
|
|
250
|
+
# --- should fix (inline literals) ---
|
|
251
|
+
('Use `foo` to do something', 'Use ``foo`` to do something'),
|
|
252
|
+
('Edge punctuation: `x`.', 'Edge punctuation: ``x``.'),
|
|
253
|
+
(
|
|
254
|
+
'Multiple inline literals: `a` and `b`.',
|
|
255
|
+
'Multiple inline literals: ``a`` and ``b``.',
|
|
256
|
+
),
|
|
257
|
+
(
|
|
258
|
+
'Underscores inside literal are fine: `foo_bar`.',
|
|
259
|
+
'Underscores inside literal are fine: ``foo_bar``.',
|
|
260
|
+
),
|
|
261
|
+
(
|
|
262
|
+
'Adjacent to parentheses: (`call_me`) and `ok`',
|
|
263
|
+
'Adjacent to parentheses: (``call_me``) and ``ok``',
|
|
264
|
+
),
|
|
265
|
+
# Edge cases: literals that contain special characters -> should fix
|
|
266
|
+
('`>>> `', '``>>> ``'),
|
|
267
|
+
('`... `', '``... ``'),
|
|
268
|
+
# --- should not fix (roles) ---
|
|
269
|
+
(':emphasis:`word`', ':emphasis:`word`'),
|
|
270
|
+
(':strong:`bold`', ':strong:`bold`'),
|
|
271
|
+
(':sup:`2`', ':sup:`2`'),
|
|
272
|
+
(
|
|
273
|
+
':title-reference:`The Great Book`',
|
|
274
|
+
':title-reference:`The Great Book`',
|
|
275
|
+
),
|
|
276
|
+
# --- should not fix (cross-references & links) ---
|
|
277
|
+
('See `Section`_ for details', 'See `Section`_ for details'),
|
|
278
|
+
(
|
|
279
|
+
'See `Docs`__ for the anonymous reference',
|
|
280
|
+
'See `Docs`__ for the anonymous reference',
|
|
281
|
+
),
|
|
282
|
+
(
|
|
283
|
+
'`Python <https://www.python.org>`_',
|
|
284
|
+
'`Python <https://www.python.org>`_',
|
|
285
|
+
),
|
|
286
|
+
# --- should not fix (already correct literals) ---
|
|
287
|
+
(
|
|
288
|
+
'Already has ``double`` backticks',
|
|
289
|
+
'Already has ``double`` backticks',
|
|
290
|
+
),
|
|
291
|
+
# --- should not fix (explicit hyperlink target) ---
|
|
292
|
+
(
|
|
293
|
+
'.. _`Special Target`: https://example.com/special',
|
|
294
|
+
'.. _`Special Target`: https://example.com/special',
|
|
295
|
+
),
|
|
296
|
+
# --- should not fix (multi-line external links) ---
|
|
297
|
+
(
|
|
298
|
+
"Here's another example where long URLs"
|
|
299
|
+
' extend to the next line `Here is perhaps\n'
|
|
300
|
+
'the Link <https://www.this-is-a-url-that-is-long.com>`_'
|
|
301
|
+
' and `Another One\n'
|
|
302
|
+
'<https://www.this-is-another-url-that-is-long.com>`_.',
|
|
303
|
+
"Here's another example where long URLs extend to"
|
|
304
|
+
' the next line `Here is perhaps\n'
|
|
305
|
+
'the Link <https://www.this-is-a-url-that-is-long.com>`_'
|
|
306
|
+
' and `Another One\n'
|
|
307
|
+
'<https://www.this-is-another-url-that-is-long.com>`_.',
|
|
308
|
+
),
|
|
309
|
+
# --- should not fix (REPL lines with backticks) ---
|
|
310
|
+
(
|
|
311
|
+
'>>> # Use `config` parameter to customize `mode`\n'
|
|
312
|
+
'... # and set the `threshold` value',
|
|
313
|
+
'>>> # Use `config` parameter to customize `mode`\n'
|
|
314
|
+
'... # and set the `threshold` value',
|
|
315
|
+
),
|
|
316
|
+
],
|
|
317
|
+
)
|
|
318
|
+
def test_fix_rst_backticks_cases(src: str, expected: str) -> None:
|
|
319
|
+
assert _fix_rst_backticks(src) == expected
|
|
320
|
+
|
|
321
|
+
|
|
246
322
|
@pytest.mark.parametrize(
|
|
247
323
|
'fix_rst_backticks, input_docstring, expected_docstring',
|
|
248
324
|
[
|
|
@@ -258,10 +334,10 @@ def test_standardize_default_value(line: str, expected: str) -> None:
|
|
|
258
334
|
),
|
|
259
335
|
],
|
|
260
336
|
)
|
|
261
|
-
def
|
|
337
|
+
def test_fix_rst_backticks_option_on_and_off(
|
|
262
338
|
fix_rst_backticks: bool, input_docstring: str, expected_docstring: str
|
|
263
339
|
) -> None:
|
|
264
|
-
"""
|
|
340
|
+
"""Verify the `fix_rst_backticks` option can be correctly turned on/off"""
|
|
265
341
|
result = wrap_docstring(
|
|
266
342
|
input_docstring,
|
|
267
343
|
line_length=79,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{format_docstring-0.1.6 → format_docstring-0.1.8}/format_docstring.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{format_docstring-0.1.6 → format_docstring-0.1.8}/format_docstring.egg-info/entry_points.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/end_to_end/numpy/README.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/end_to_end/numpy/line_length_2.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/integration_test/numpy/after.ipynb
RENAMED
|
File without changes
|
{format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/integration_test/numpy/after.py
RENAMED
|
File without changes
|
|
File without changes
|
{format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/integration_test/numpy/after_50.py
RENAMED
|
File without changes
|
|
File without changes
|
{format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/integration_test/numpy/before.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{format_docstring-0.1.6 → format_docstring-0.1.8}/tests/test_data/line_wrap/numpy/line_length_2.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|