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 prepended escape char handling #94

Merged
merged 4 commits into from
Oct 20, 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
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# Change Log

## [0.3.8] - 2023-10-20

- Fixed

- A bug in handling prepended escape characters in docstrings

- Full diff
- https://github.com/jsh9/pydoclint/compare/0.3.7...0.3.8

## [0.3.7] - 2023-10-19

- Changed
Expand Down
20 changes: 7 additions & 13 deletions pydoclint/utils/arg.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def __init__(self, name: str, typeHint: str) -> None:
if len(name) == 0:
raise ValueError('`name` cannot be an empty string')

self.name: str = name
self.name: str = self._removeEscapeChar(name)
self.typeHint: str = typeHint

def __repr__(self) -> str:
Expand All @@ -32,7 +32,7 @@ def __eq__(self, other: 'Arg') -> bool:
if not isinstance(other, Arg):
return False

argNamesEqual: bool = self._argNamesEq(self.name, other.name)
argNamesEqual: bool = self.name == other.name
typeHintsEqual: bool = self._typeHintsEq(self.typeHint, other.typeHint)
return argNamesEqual and typeHintsEqual

Expand Down Expand Up @@ -110,20 +110,14 @@ def _typeHintsEq(cls, hint1: str, hint2: str) -> bool:

return hint1_ == hint2_

@classmethod
def _argNamesEq(cls, name1: str, name2: str) -> bool:
return cls._removeEscapeChar(name1) == cls._removeEscapeChar(name2)

@classmethod
def _removeEscapeChar(cls, string: str) -> str:
# We need to remove `\` from the arg names before comparing them,
# because when there are 1 or 2 trailing underscores in an argument,
# people need to use `\_` or `\_\_`, otherwise Sphinx will somehow
# not render the underscores (and for some reason, 3 or more trailing
# underscores are fine).
#
# We need to remove `\` from the arg names for proper comparison.
# This is because it is often necessary to add `\` in docstrings in
# order for Sphinx to correctly render them.
# For example:
# arg1\_\_ (int): The first argument
# arg1\_\_
# \\**kwargs
return string.replace('\\', '')


Expand Down
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[metadata]
name = pydoclint
version = 0.3.7
version = 0.3.8
description = A Python docstring linter that checks arguments, returns, yields, and raises sections
long_description = file: README.md
long_description_content_type = text/markdown
Expand Down
9 changes: 9 additions & 0 deletions tests/data/edge_cases/05_escape_char/google.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
# From these issues:
# https://github.com/jsh9/pydoclint/issues/73
# https://github.com/jsh9/pydoclint/issues/92


def myFunc(
arg1_: int,
arg2__: int,
Expand All @@ -8,6 +13,8 @@ def myFunc(
some_thing_3___: int,
some_thing_4____: int,
some_thing_5_____: str,
*args: Any,
**kwargs: Any,
) -> None:
r"""
Do something.
Expand All @@ -22,6 +29,8 @@ def myFunc(
some_thing_3\_\_\_ (int): Arg
some_thing_4\_\_\_\_ (int): Arg
some_thing_5_____ (str): Arg
*args (Any): Args
**kwargs (Any): Keyword args

Returns:
None: Return value
Expand Down
11 changes: 11 additions & 0 deletions tests/data/edge_cases/05_escape_char/numpy.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
# From these issues:
# https://github.com/jsh9/pydoclint/issues/73
# https://github.com/jsh9/pydoclint/issues/92


def myFunc(
arg1_: int,
arg2__: int,
Expand All @@ -8,6 +13,8 @@ def myFunc(
some_thing_3___: int,
some_thing_4____: int,
some_thing_5_____: str,
*args: Any,
**kwargs: Any,
) -> None:
r"""
Do something.
Expand All @@ -32,6 +39,10 @@ def myFunc(
Arg
some_thing_5_____ : str
Arg
*args : Any
Args
**kwargs : Any
Keyword args

Returns
-------
Expand Down
11 changes: 11 additions & 0 deletions tests/data/edge_cases/05_escape_char/sphinx.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
# From these issues:
# https://github.com/jsh9/pydoclint/issues/73
# https://github.com/jsh9/pydoclint/issues/92


def myFunc(
arg1_: int,
arg2__: int,
Expand All @@ -8,6 +13,8 @@ def myFunc(
some_thing_3___: int,
some_thing_4____: int,
some_thing_5_____: str,
*args: Any,
**kwargs: Any,
) -> None:
r"""
Do something.
Expand All @@ -30,6 +37,10 @@ def myFunc(
:type some_thing_4\_\_\_\_: int
:param some_thing_5_____: Arg
:type some_thing_5_____: str
:param \\*args: Args
:type \\*args: Any
:param \\**kwargs: Args
:type \\**kwargs: Any
:return: Return value
:rtype: None
"""
Expand Down
27 changes: 26 additions & 1 deletion tests/utils/test_arg.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ def testArg_initializationCheck():
(Arg(name='1', typeHint='2'), '1: 2'),
(Arg(name='arg1', typeHint='str'), 'arg1: str'),
(Arg(name='obj', typeHint='int | float'), 'obj: int | float'),
(Arg(name='arg1\_\_', typeHint='Any'), 'arg1__: Any'), # noqa: W605
(Arg(name='**kwargs', typeHint='Any'), '**kwargs: Any'),
(Arg(name='\\**kwargs', typeHint='Any'), '**kwargs: Any'),
],
)
def testArg_str(arg: Arg, string_repr: str) -> None:
Expand All @@ -28,6 +31,10 @@ def testArg_str(arg: Arg, string_repr: str) -> None:
(Arg(name='1', typeHint='2'), Arg(name='1', typeHint='2')),
(Arg(name='abc', typeHint='12345'), Arg(name='abc', typeHint='12345')),
(Arg(name='aa', typeHint=''), Arg(name='aa', typeHint='')),
(Arg(name='\\**kw', typeHint=''), Arg(name='**kw', typeHint='')),
(Arg(name='**kw', typeHint=''), Arg(name='\\**kw', typeHint='')),
(Arg(name='\\*args', typeHint=''), Arg(name='*args', typeHint='')),
(Arg(name='*args', typeHint=''), Arg(name='\\*args', typeHint='')),
],
)
def testArg_equal(arg1: Arg, arg2: Arg) -> None:
Expand Down Expand Up @@ -137,7 +144,7 @@ def testArg_sorting(original: Set[Arg], after: List[Arg]) -> None:
('Literal["abc", "def"]', "Literal[\n 'abc',\n 'def',\n]", True),
],
)
def testArg_eq(str1: str, str2: str, expected: bool) -> None:
def testArg_typeHintsEq(str1: str, str2: str, expected: bool) -> None:
assert Arg._typeHintsEq(str1, str2) == expected


Expand Down Expand Up @@ -193,6 +200,14 @@ def testArgList_length(input_: ArgList, expected: int) -> None:
ArgList([Arg('1', '2'), Arg('2', '3'), Arg('3', '4')]),
ArgList([Arg('1', '2'), Arg('2', '3'), Arg('3', '4')]),
),
(
ArgList([Arg('*args', '1'), Arg('\\**kwargs', '2')]),
ArgList([Arg('\\*args', '1'), Arg('**kwargs', '2')]),
),
(
ArgList([Arg('arg1\_', '1'), Arg('arg2__', '2')]), # noqa: W605
ArgList([Arg('arg1_', '1'), Arg('arg2\_\_', '2')]), # noqa: W605
),
],
)
def testArgList_equality(list1: ArgList, list2: ArgList) -> None:
Expand Down Expand Up @@ -298,6 +313,16 @@ def testArgList_contains(
ArgList([]),
{Arg('a', '1'), Arg('b', '2'), Arg('c', '3')},
),
(
ArgList([Arg('*args', '1'), Arg('\\**kwargs', '2')]),
ArgList([Arg('\\*args', '1')]),
{Arg('**kwargs', '2')},
),
(
ArgList([Arg('arg1\_', '1'), Arg('arg2__', '2')]), # noqa: W605
ArgList([Arg('arg2\_\_', '2')]), # noqa: W605
{Arg('arg1_', '1')},
),
],
)
def testArgList_subtract(
Expand Down