Skip to content

Commit f1b0fa6

Browse files
authored
fix: remove blank lines after line beginning with 'def' (#171)
* chore: update copyright dates * fix: removing blank lines after variable starts with 'def' * test: add test for variable starts with 'def' * chore: remove coveralls action * fix: removing blanks lines in stub functions * test: add tests for stub function handling * doc: fix pre-commit configuration in docs
1 parent 7898b69 commit f1b0fa6

19 files changed

+271
-92
lines changed

.github/workflows/ci.yml

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -40,21 +40,3 @@ jobs:
4040
run: tox -vv --notest
4141
- name: Run tests with tox
4242
run: tox -e py --skip-pkg-install
43-
- name: Create Coveralls coverage report
44-
uses: miurahr/coveralls-python-action@patch-pyprject-toml
45-
with:
46-
base-path: .tox
47-
debug: true
48-
parallel: true
49-
50-
upload_coveralls:
51-
name: Upload Results to Coveralls
52-
needs: test
53-
runs-on: ubuntu-latest
54-
steps:
55-
- name: Upload coverage report to Coveralls
56-
uses: miurahr/coveralls-python-action@patch-pyprject-toml
57-
with:
58-
base-path: .tox
59-
debug: true
60-
parallel-finished: true

docs/source/usage.rst

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,10 @@ with the following ``.pre-commit-config.yaml`` configuration:
118118
.. code-block:: yaml
119119
120120
- repo: https://github.com/PyCQA/docformatter
121-
rev: v1.5.0
121+
rev: v1.6.1
122122
hooks:
123123
- id: docformatter
124+
additional_dependencies: [tomli]
124125
args: [--in-place --config ./pyproject.toml]
125126
126127
You will need to install ``pre-commit`` and run ``pre-commit install``.
@@ -131,6 +132,9 @@ fails because pre-commit does a diff check and fails if it detects a hook
131132
changed a file. The ``--check`` option fails because ``docformatter`` returns
132133
a non-zero exit code.
133134

135+
The ``additional_dependencies: [tomli]`` is only required if you are using
136+
``pyproject.toml`` for ``docformatter``'s configuration.
137+
134138
Use with GitHub Actions
135139
-----------------------
136140

src/docformatter/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/usr/bin/env python
22
#
3-
# Copyright (C) 2012-2022 Steven Myint
3+
# Copyright (C) 2012-2023 Steven Myint
44
#
55
# Permission is hereby granted, free of charge, to any person obtaining
66
# a copy of this software and associated documentation files (the

src/docformatter/__main__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/usr/bin/env python
22
#
3-
# Copyright (C) 2012-2022 Steven Myint
3+
# Copyright (C) 2012-2023 Steven Myint
44
#
55
# Permission is hereby granted, free of charge, to any person obtaining
66
# a copy of this software and associated documentation files (the

src/docformatter/__pkginfo__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/usr/bin/env python
22
#
3-
# Copyright (C) 2012-2022 Steven Myint
3+
# Copyright (C) 2012-2023 Steven Myint
44
#
55
# Permission is hereby granted, free of charge, to any person obtaining
66
# a copy of this software and associated documentation files (the

src/docformatter/configuration.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/usr/bin/env python
22
#
3-
# Copyright (C) 2012-2022 Steven Myint
3+
# Copyright (C) 2012-2023 Steven Myint
44
#
55
# Permission is hereby granted, free of charge, to any person obtaining
66
# a copy of this software and associated documentation files (the

src/docformatter/encode.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/usr/bin/env python
22
#
3-
# Copyright (C) 2012-2022 Steven Myint
3+
# Copyright (C) 2012-2023 Steven Myint
44
#
55
# Permission is hereby granted, free of charge, to any person obtaining
66
# a copy of this software and associated documentation files (the
@@ -28,7 +28,7 @@
2828
import io
2929
import locale
3030
import sys
31-
from typing import Dict
31+
from typing import Dict, List
3232

3333
# Third Party Imports
3434
from charset_normalizer import from_path # pylint: disable=import-error
@@ -67,7 +67,7 @@ def do_detect_encoding(self, filename: str) -> None:
6767
except (SyntaxError, LookupError, UnicodeDecodeError):
6868
self.encoding = "latin-1"
6969

70-
def do_find_newline(self, source: str) -> Dict[int, int]:
70+
def do_find_newline(self, source: List[str]) -> Dict[int, int]:
7171
"""Return type of newline used in source.
7272
7373
Parameters

src/docformatter/format.py

Lines changed: 68 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/usr/bin/env python
22
#
3-
# Copyright (C) 2012-2022 Steven Myint
3+
# Copyright (C) 2012-2023 Steven Myint
44
#
55
# Permission is hereby granted, free of charge, to any person obtaining
66
# a copy of this software and associated documentation files (the
@@ -229,13 +229,13 @@ def _do_format_code(self, source):
229229
The text from the source file.
230230
"""
231231
try:
232-
original_newline = self.encodor.do_find_newline(
232+
_original_newline = self.encodor.do_find_newline(
233233
source.splitlines(True)
234234
)
235-
code = self._format_code(source)
235+
_code = self._format_code(source)
236236

237237
return _strings.normalize_line_endings(
238-
code.splitlines(True), original_newline
238+
_code.splitlines(True), _original_newline
239239
)
240240
except (tokenize.TokenError, IndentationError):
241241
return source
@@ -310,29 +310,16 @@ def _format_code(
310310
only_comments_so_far = False
311311

312312
previous_token_type = token_type
313+
modified_tokens.append(
314+
(token_type, token_string, start, end, line)
315+
)
313316

314-
# If the current token is a newline, the previous token was a
315-
# newline or a comment, and these two sequential newlines
316-
# follow a function or method definition, ignore the blank
317-
# line before the docstring.
318-
if (
319-
len(modified_tokens) <= 2
320-
or token_type not in {tokenize.NL, tokenize.NEWLINE}
321-
or modified_tokens[-1][0]
322-
not in {tokenize.NL, tokenize.NEWLINE}
323-
or modified_tokens[-2][1] != ":"
324-
and modified_tokens[-2][0] != tokenize.COMMENT
325-
or not modified_tokens[-2][4].lstrip().startswith(("def"))
326-
):
327-
modified_tokens.append(
328-
(token_type, token_string, start, end, line)
329-
)
330-
modified_tokens = self._do_remove_blank_lines_after_method(
331-
modified_tokens
332-
)
333-
modified_tokens = self._do_remove_blank_lines_before_class(
334-
modified_tokens
335-
)
317+
modified_tokens = self._do_remove_blank_lines_after_definitions(
318+
modified_tokens
319+
)
320+
modified_tokens = self._do_remove_blank_lines_after_docstring(
321+
modified_tokens
322+
)
336323

337324
return untokenize.untokenize(modified_tokens)
338325
except tokenize.TokenError:
@@ -521,8 +508,11 @@ def _do_format_multiline_docstring(
521508
'''
522509

523510
@staticmethod
524-
def _do_remove_blank_lines_after_method(modified_tokens):
525-
"""Remove blank lines after method docstring.
511+
def _do_remove_blank_lines_after_definitions(modified_tokens):
512+
"""Remove blank lines between definitions and docstrings.
513+
514+
Blank lines between class, method, function, and variable
515+
definitions and the docstring will be removed.
526516
527517
Parameters
528518
----------
@@ -532,23 +522,37 @@ def _do_remove_blank_lines_after_method(modified_tokens):
532522
Returns
533523
-------
534524
modified_tokens: list
535-
The list of tokens with any blank lines following a method
536-
docstring removed.
525+
The list of tokens with any blank lines following a variable
526+
definition removed.
537527
"""
538-
with contextlib.suppress(IndexError):
539-
if (
540-
modified_tokens[-1][4] == "\n"
541-
and modified_tokens[-2][4].lstrip().startswith('"""')
542-
and modified_tokens[-5][4].lstrip().startswith("def")
543-
):
544-
modified_tokens.pop(-1)
528+
for _idx, _token in enumerate(modified_tokens):
529+
if _token[0] == 3:
530+
# Remove newline between variable definition and docstring.
531+
j = 1
532+
while modified_tokens[_idx - j][
533+
4
534+
] == "\n" and not modified_tokens[_idx - j - 1][
535+
4
536+
].strip().endswith(
537+
'"""'
538+
):
539+
modified_tokens.pop(_idx - j)
540+
j += 1
541+
542+
# Remove newline between class, method, and function
543+
# definitions and docstring.
544+
j = 2
545+
while modified_tokens[_idx - j][4] == "\n" and modified_tokens[
546+
_idx - j - 2
547+
][4].strip().startswith(("def", "class")):
548+
modified_tokens.pop(_idx - j)
549+
j += 1
550+
545551
return modified_tokens
546552

547553
@staticmethod
548-
def _do_remove_blank_lines_before_class(modified_tokens):
549-
"""Remove blank lines before class docstring.
550-
551-
If there is no class docstring, leave any blank lines as is.
554+
def _do_remove_blank_lines_after_docstring(modified_tokens):
555+
"""Remove blank lines between docstring and first Python statement.
552556
553557
Parameters
554558
----------
@@ -558,16 +562,30 @@ def _do_remove_blank_lines_before_class(modified_tokens):
558562
Returns
559563
-------
560564
modified_tokens: list
561-
The list of tokens with any blank lines following a method
562-
docstring removed.
565+
The list of tokens with any blank lines following a docstring
566+
removed.
563567
"""
564-
with contextlib.suppress(IndexError):
565-
if (
566-
modified_tokens[-3][4] == "\n"
567-
and modified_tokens[-2][4].lstrip().startswith('"""')
568-
and modified_tokens[-6][4].lstrip().startswith("class")
569-
):
570-
modified_tokens.pop(-3)
568+
# Remove all newlines between docstring and first Python
569+
# statement as long as it's not a stub function.
570+
for _idx, _token in enumerate(modified_tokens):
571+
with contextlib.suppress(IndexError):
572+
if (
573+
_token[0] == 1
574+
and not _token[4]
575+
.lstrip()
576+
.startswith(("class ", "def ", "@"))
577+
and not modified_tokens[_idx - 2][4]
578+
.strip()
579+
.endswith('"""')
580+
and modified_tokens[_idx - 6][4]
581+
.lstrip()
582+
.startswith(("class ", "def ", "@"))
583+
):
584+
j = 1
585+
while modified_tokens[_idx - j][4] == "\n":
586+
modified_tokens.pop(_idx - j)
587+
j += 1
588+
571589
return modified_tokens
572590

573591
def _do_strip_docstring(self, docstring: str) -> Tuple[str, str]:

src/docformatter/strings.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/usr/bin/env python
22
#
3-
# Copyright (C) 2012-2022 Steven Myint
3+
# Copyright (C) 2012-2023 Steven Myint
44
#
55
# Permission is hereby granted, free of charge, to any person obtaining
66
# a copy of this software and associated documentation files (the

src/docformatter/syntax.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -325,9 +325,7 @@ def do_split_description(
325325
# If the text including the URL is longer than the wrap length,
326326
# we need to split the description before the URL, wrap the pre-URL
327327
# text, and add the URL as a separate line.
328-
if len(text[_text_idx : _idx[1]]) > (
329-
wrap_length - len(indentation)
330-
):
328+
if len(text[_text_idx : _idx[1]]) > (wrap_length - len(indentation)):
331329
# Wrap everything in the description before the first URL.
332330
_lines.extend(
333331
description_to_list(

0 commit comments

Comments
 (0)