Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: remove blank lines after line beginning with 'def' #171

Merged
merged 7 commits into from
Apr 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 0 additions & 18 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,21 +40,3 @@ jobs:
run: tox -vv --notest
- name: Run tests with tox
run: tox -e py --skip-pkg-install
- name: Create Coveralls coverage report
uses: miurahr/coveralls-python-action@patch-pyprject-toml
with:
base-path: .tox
debug: true
parallel: true

upload_coveralls:
name: Upload Results to Coveralls
needs: test
runs-on: ubuntu-latest
steps:
- name: Upload coverage report to Coveralls
uses: miurahr/coveralls-python-action@patch-pyprject-toml
with:
base-path: .tox
debug: true
parallel-finished: true
6 changes: 5 additions & 1 deletion docs/source/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,10 @@ with the following ``.pre-commit-config.yaml`` configuration:
.. code-block:: yaml

- repo: https://github.com/PyCQA/docformatter
rev: v1.5.0
rev: v1.6.1
hooks:
- id: docformatter
additional_dependencies: [tomli]
args: [--in-place --config ./pyproject.toml]

You will need to install ``pre-commit`` and run ``pre-commit install``.
Expand All @@ -131,6 +132,9 @@ fails because pre-commit does a diff check and fails if it detects a hook
changed a file. The ``--check`` option fails because ``docformatter`` returns
a non-zero exit code.

The ``additional_dependencies: [tomli]`` is only required if you are using
``pyproject.toml`` for ``docformatter``'s configuration.

Use with GitHub Actions
-----------------------

Expand Down
2 changes: 1 addition & 1 deletion src/docformatter/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env python
#
# Copyright (C) 2012-2022 Steven Myint
# Copyright (C) 2012-2023 Steven Myint
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
Expand Down
2 changes: 1 addition & 1 deletion src/docformatter/__main__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env python
#
# Copyright (C) 2012-2022 Steven Myint
# Copyright (C) 2012-2023 Steven Myint
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
Expand Down
2 changes: 1 addition & 1 deletion src/docformatter/__pkginfo__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env python
#
# Copyright (C) 2012-2022 Steven Myint
# Copyright (C) 2012-2023 Steven Myint
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
Expand Down
2 changes: 1 addition & 1 deletion src/docformatter/configuration.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env python
#
# Copyright (C) 2012-2022 Steven Myint
# Copyright (C) 2012-2023 Steven Myint
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
Expand Down
6 changes: 3 additions & 3 deletions src/docformatter/encode.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env python
#
# Copyright (C) 2012-2022 Steven Myint
# Copyright (C) 2012-2023 Steven Myint
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
Expand Down Expand Up @@ -28,7 +28,7 @@
import io
import locale
import sys
from typing import Dict
from typing import Dict, List

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

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

Parameters
Expand Down
118 changes: 68 additions & 50 deletions src/docformatter/format.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env python
#
# Copyright (C) 2012-2022 Steven Myint
# Copyright (C) 2012-2023 Steven Myint
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
Expand Down Expand Up @@ -229,13 +229,13 @@ def _do_format_code(self, source):
The text from the source file.
"""
try:
original_newline = self.encodor.do_find_newline(
_original_newline = self.encodor.do_find_newline(
source.splitlines(True)
)
code = self._format_code(source)
_code = self._format_code(source)

return _strings.normalize_line_endings(
code.splitlines(True), original_newline
_code.splitlines(True), _original_newline
)
except (tokenize.TokenError, IndentationError):
return source
Expand Down Expand Up @@ -310,29 +310,16 @@ def _format_code(
only_comments_so_far = False

previous_token_type = token_type
modified_tokens.append(
(token_type, token_string, start, end, line)
)

# If the current token is a newline, the previous token was a
# newline or a comment, and these two sequential newlines
# follow a function or method definition, ignore the blank
# line before the docstring.
if (
len(modified_tokens) <= 2
or token_type not in {tokenize.NL, tokenize.NEWLINE}
or modified_tokens[-1][0]
not in {tokenize.NL, tokenize.NEWLINE}
or modified_tokens[-2][1] != ":"
and modified_tokens[-2][0] != tokenize.COMMENT
or not modified_tokens[-2][4].lstrip().startswith(("def"))
):
modified_tokens.append(
(token_type, token_string, start, end, line)
)
modified_tokens = self._do_remove_blank_lines_after_method(
modified_tokens
)
modified_tokens = self._do_remove_blank_lines_before_class(
modified_tokens
)
modified_tokens = self._do_remove_blank_lines_after_definitions(
modified_tokens
)
modified_tokens = self._do_remove_blank_lines_after_docstring(
modified_tokens
)

return untokenize.untokenize(modified_tokens)
except tokenize.TokenError:
Expand Down Expand Up @@ -521,8 +508,11 @@ def _do_format_multiline_docstring(
'''

@staticmethod
def _do_remove_blank_lines_after_method(modified_tokens):
"""Remove blank lines after method docstring.
def _do_remove_blank_lines_after_definitions(modified_tokens):
"""Remove blank lines between definitions and docstrings.

Blank lines between class, method, function, and variable
definitions and the docstring will be removed.

Parameters
----------
Expand All @@ -532,23 +522,37 @@ def _do_remove_blank_lines_after_method(modified_tokens):
Returns
-------
modified_tokens: list
The list of tokens with any blank lines following a method
docstring removed.
The list of tokens with any blank lines following a variable
definition removed.
"""
with contextlib.suppress(IndexError):
if (
modified_tokens[-1][4] == "\n"
and modified_tokens[-2][4].lstrip().startswith('"""')
and modified_tokens[-5][4].lstrip().startswith("def")
):
modified_tokens.pop(-1)
for _idx, _token in enumerate(modified_tokens):
if _token[0] == 3:
# Remove newline between variable definition and docstring.
j = 1
while modified_tokens[_idx - j][
4
] == "\n" and not modified_tokens[_idx - j - 1][
4
].strip().endswith(
'"""'
):
modified_tokens.pop(_idx - j)
j += 1

# Remove newline between class, method, and function
# definitions and docstring.
j = 2
while modified_tokens[_idx - j][4] == "\n" and modified_tokens[
_idx - j - 2
][4].strip().startswith(("def", "class")):
modified_tokens.pop(_idx - j)
j += 1

return modified_tokens

@staticmethod
def _do_remove_blank_lines_before_class(modified_tokens):
"""Remove blank lines before class docstring.

If there is no class docstring, leave any blank lines as is.
def _do_remove_blank_lines_after_docstring(modified_tokens):
"""Remove blank lines between docstring and first Python statement.

Parameters
----------
Expand All @@ -558,16 +562,30 @@ def _do_remove_blank_lines_before_class(modified_tokens):
Returns
-------
modified_tokens: list
The list of tokens with any blank lines following a method
docstring removed.
The list of tokens with any blank lines following a docstring
removed.
"""
with contextlib.suppress(IndexError):
if (
modified_tokens[-3][4] == "\n"
and modified_tokens[-2][4].lstrip().startswith('"""')
and modified_tokens[-6][4].lstrip().startswith("class")
):
modified_tokens.pop(-3)
# Remove all newlines between docstring and first Python
# statement as long as it's not a stub function.
for _idx, _token in enumerate(modified_tokens):
with contextlib.suppress(IndexError):
if (
_token[0] == 1
and not _token[4]
.lstrip()
.startswith(("class ", "def ", "@"))
and not modified_tokens[_idx - 2][4]
.strip()
.endswith('"""')
and modified_tokens[_idx - 6][4]
.lstrip()
.startswith(("class ", "def ", "@"))
):
j = 1
while modified_tokens[_idx - j][4] == "\n":
modified_tokens.pop(_idx - j)
j += 1

return modified_tokens

def _do_strip_docstring(self, docstring: str) -> Tuple[str, str]:
Expand Down
2 changes: 1 addition & 1 deletion src/docformatter/strings.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env python
#
# Copyright (C) 2012-2022 Steven Myint
# Copyright (C) 2012-2023 Steven Myint
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
Expand Down
4 changes: 1 addition & 3 deletions src/docformatter/syntax.py
Original file line number Diff line number Diff line change
Expand Up @@ -325,9 +325,7 @@ def do_split_description(
# If the text including the URL is longer than the wrap length,
# we need to split the description before the URL, wrap the pre-URL
# text, and add the URL as a separate line.
if len(text[_text_idx : _idx[1]]) > (
wrap_length - len(indentation)
):
if len(text[_text_idx : _idx[1]]) > (wrap_length - len(indentation)):
# Wrap everything in the description before the first URL.
_lines.extend(
description_to_list(
Expand Down
2 changes: 1 addition & 1 deletion src/docformatter/util.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env python
#
# Copyright (C) 2012-2022 Steven Myint
# Copyright (C) 2012-2023 Steven Myint
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
Expand Down
2 changes: 1 addition & 1 deletion tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#
# tests._init__.py is part of the docformatter project
#
# Copyright (C) 2012-2019 Steven Myint
# Copyright (C) 2012-2023 Steven Myint
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
Expand Down
2 changes: 1 addition & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#
# tests.conftest.py is part of the docformatter project
#
# Copyright (C) 2012-2019 Steven Myint
# Copyright (C) 2012-2023 Steven Myint
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
Expand Down
2 changes: 1 addition & 1 deletion tests/test_configuration_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# tests.test_configuration_functions.py is part of the docformatter
# project
#
# Copyright (C) 2012-2022 Steven Myint
# Copyright (C) 2012-2023 Steven Myint
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
Expand Down
2 changes: 1 addition & 1 deletion tests/test_docformatter.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#
# tests.test_docformatter.py is part of the docformatter project
#
# Copyright (C) 2012-2019 Steven Myint
# Copyright (C) 2012-2023 Steven Myint
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
Expand Down
2 changes: 1 addition & 1 deletion tests/test_encoding_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#
# tests.test_encoding_functions.py is part of the docformatter project
#
# Copyright (C) 2012-2019 Steven Myint
# Copyright (C) 2012-2023 Steven Myint
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
Expand Down
Loading