Skip to content

Commit ddd3d0f

Browse files
authored
fix: improper wrapping of short anonymous hyperlnks (#213)
* fix: improper wrapping of anonymous hyperlinks * test: add test for improper wrapping of anonymous hyperlinks
1 parent 1cef4e9 commit ddd3d0f

3 files changed

Lines changed: 54 additions & 15 deletions

File tree

.github/workflows/do-prioritize-issues.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# This workflow runs daily at 1pm.
1+
# This workflow runs when labels are applied to issues.
22
#
33
# - Get list of labels.
44
# - Determine issue priority based on labels:
@@ -24,19 +24,19 @@ jobs:
2424
uses: weibullguy/get-labels-action@main
2525

2626
- name: Add High Urgency Labels
27-
if: (endsWith(steps.getlabels.outputs.labels, ' convention ') && endsWith(steps.getlabels.outputs.labels, ' bug '))
27+
if: (endsWith(steps.getlabels.outputs.labels, 'convention') && endsWith(steps.getlabels.outputs.labels, 'bug'))
2828
uses: andymckay/labeler@master
2929
with:
3030
add-labels: "U: high"
3131

3232
- name: Add Medium Urgency Labels
33-
if: (endsWith(steps.getlabels.outputs.labels, ' style ') && endsWith(steps.getlabels.outputs.labels, ' bug ')) || (endsWith(steps.getlabels.outputs.labels, ' stakeholder ') && endsWith(steps.getlabels.outputs.labels, ' bug ')) || (endsWith(steps.getlabels.outputs.labels, ' convenction ') && endsWith(steps.getlabels.outputs.labels, ' enhancement '))
33+
if: (endsWith(steps.getlabels.outputs.labels, 'style') && endsWith(steps.getlabels.outputs.labels, 'bug')) || (endsWith(steps.getlabels.outputs.labels, 'stakeholder') && endsWith(steps.getlabels.outputs.labels, 'bug')) || (endsWith(steps.getlabels.outputs.labels, 'convention') && endsWith(steps.getlabels.outputs.labels, 'enhancement'))
3434
uses: andymckay/labeler@master
3535
with:
3636
add-labels: "U: medium"
3737

3838
- name: Add Low Urgency Labels
39-
if: (endsWith(steps.getlabels.outputs.labels, ' style ') && endsWith(steps.getlabels.outputs.labels, ' enhancement ')) || (endsWith(steps.getlabels.outputs.labels, ' stakeholder ') && endsWith(steps.getlabels.outputs.labels, ' enhancement ')) || endsWith(steps.getlabels.outputs.labels, ' doc ') || contains(steps.getlabels.outputs.labels, ' chore ')
39+
if: (endsWith(steps.getlabels.outputs.labels, 'style') && endsWith(steps.getlabels.outputs.labels, 'enhancement')) || (endsWith(steps.getlabels.outputs.labels, 'stakeholder') && endsWith(steps.getlabels.outputs.labels, 'enhancement')) || contains(steps.getlabels.outputs.labels, 'doc') || contains(steps.getlabels.outputs.labels, 'chore')
4040
uses: andymckay/labeler@master
4141
with:
4242
add-labels: "U: low"

src/docformatter/syntax.py

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -110,13 +110,16 @@
110110

111111
# This is the regex used to find URL links:
112112
#
113-
# (`{{2}}|`\w[\w. :\n]*|\.\. _?[\w. :]+|')? is used to find in-line links that
113+
# (__ |`{{2}}|`\w[\w. :\n]*|\.\. _?[\w. :]+|')? is used to find in-line links that
114114
# should remain on a single line even if it exceeds the wrap length.
115+
# __ is used to find to underscores followed by a single space.
116+
# This finds patterns like: __ https://sw.kovidgoyal.net/kitty/graphics-protocol/
117+
#
115118
# `{{2}} is used to find two back-tick characters.
116119
# This finds patterns like: ``http://www.example.com``
117120
#
118-
# `\w[\w. :#\n]* matches the back-tick character immediately followed by one
119-
# letter, then followed by any number of letters, periods, spaces, colons,
121+
# `\w[a-zA-Z0-9. :#\n]* matches the back-tick character immediately followed by one
122+
# letter, then followed by any number of letters, numbers, periods, spaces, colons,
120123
# hash marks or newlines.
121124
# This finds patterns like: `Link text <https://domain.invalid/>`_
122125
#
@@ -137,8 +140,10 @@
137140
# (//)? matches two forward slashes zero or one time.
138141
# (\S*) matches any non-whitespace character between zero and infinity times.
139142
# >? matches the character > between zero and one times.
140-
URL_REGEX = rf"(`{{2}}|`\w[\w. :#\n]*|\.\. _?[\w. :]+|')?<?({URL_PATTERNS}):(\
141-
//)?(\S*)>?"
143+
URL_REGEX = (
144+
rf"(__ |`{{2}}|`\w[\w :#\n]*[.|\.\. _?[\w. :]+|')?<?"
145+
rf"({URL_PATTERNS}):(\//)?(\S*)>?"
146+
)
142147

143148
URL_SKIP_REGEX = rf"({URL_PATTERNS}):(/){{0,2}}(``|')"
144149
"""The regex used to ignore found hyperlinks.
@@ -195,9 +200,11 @@ def description_to_list(
195200
initial_indent=indentation,
196201
subsequent_indent=indentation,
197202
)
203+
198204
if _text:
199205
_lines.extend(_text)
200206
_lines.append("")
207+
201208
with contextlib.suppress(IndexError):
202209
if not _lines[-1] and not _lines[-2]:
203210
_lines.pop(-1)
@@ -530,9 +537,8 @@ def do_wrap_urls(
530537
wrap_length,
531538
)
532539
)
533-
534540
with contextlib.suppress(IndexError):
535-
if not _lines[-1]:
541+
if not text[_url[0] - len(indentation) - 2] == "\n" and not _lines[-1]:
536542
_lines.pop(-1)
537543

538544
# Add the URL.

tests/test_format_docstring.py

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1391,12 +1391,12 @@ def test_format_docstring_with_only_link_in_description(
13911391
]
13921392
],
13931393
)
1394-
def test_format_docstring_link_only_one_newline_after_link(
1394+
def test_format_docstring_link_no_newline_after_link(
13951395
self,
13961396
test_args,
13971397
args,
13981398
):
1399-
"""Links should have no newline before them and only one after.
1399+
"""Links should have no newline before or after them.
14001400
14011401
See issue #180.
14021402
"""
@@ -1413,11 +1413,9 @@ def test_format_docstring_link_only_one_newline_after_link(
14131413
Generated by 'django-admin startproject' using Django 4.1.1.
14141414
14151415
For more information on this file, see
1416-
14171416
https://docs.djangoproject.com/en/4.1/topics/settings/
14181417
14191418
For the full list of settings and their values, see
1420-
14211419
https://docs.djangoproject.com/en/4.1/ref/settings/
14221420
"""\
14231421
'''
@@ -1437,6 +1435,41 @@ def test_format_docstring_link_only_one_newline_after_link(
14371435
INDENTATION, docstring.strip()
14381436
)
14391437

1438+
@pytest.mark.unit
1439+
@pytest.mark.parametrize("args", [[""]])
1440+
def test_format_docstring_with_short_anonymous_link(self, test_args, args):
1441+
"""Anonymous link references should not be wrapped into the link.
1442+
1443+
See issue #210.
1444+
"""
1445+
uut = Formatter(
1446+
test_args,
1447+
sys.stderr,
1448+
sys.stdin,
1449+
sys.stdout,
1450+
)
1451+
1452+
docstring = '''\
1453+
"""Short description.
1454+
1455+
This graphics format generates terminal escape codes that transfer PNG
1456+
data to a TTY using the `kitty graphics protocol`__.
1457+
1458+
__ https://sw.kovidgoyal.net/kitty/graphics-protocol/
1459+
"""
1460+
'''
1461+
assert docstring == uut._do_format_code(
1462+
'''\
1463+
"""Short description.
1464+
1465+
This graphics format generates terminal escape codes that transfer
1466+
PNG data to a TTY using the `kitty graphics protocol`__.
1467+
1468+
__ https://sw.kovidgoyal.net/kitty/graphics-protocol/
1469+
"""
1470+
'''
1471+
)
1472+
14401473
@pytest.mark.unit
14411474
@pytest.mark.parametrize("args", [[""]])
14421475
def test_format_docstring_with_class_attributes(self, test_args, args):

0 commit comments

Comments
 (0)