From 1af103b43a1e6ac8909ebc1adeb4759884421635 Mon Sep 17 00:00:00 2001 From: jsh9 <25124332+jsh9@users.noreply.github.com> Date: Fri, 20 Oct 2023 13:29:38 -0400 Subject: [PATCH 1/4] Fix prepended escape char handling --- pydoclint/utils/arg.py | 20 +++++--------- .../data/edge_cases/05_escape_char/google.py | 8 ++++++ tests/data/edge_cases/05_escape_char/numpy.py | 10 +++++++ .../data/edge_cases/05_escape_char/sphinx.py | 10 +++++++ tests/utils/test_arg.py | 27 ++++++++++++++++++- 5 files changed, 61 insertions(+), 14 deletions(-) diff --git a/pydoclint/utils/arg.py b/pydoclint/utils/arg.py index 4627c8b..7ce6b40 100644 --- a/pydoclint/utils/arg.py +++ b/pydoclint/utils/arg.py @@ -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: @@ -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 @@ -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('\\', '') diff --git a/tests/data/edge_cases/05_escape_char/google.py b/tests/data/edge_cases/05_escape_char/google.py index 7b545ef..935f110 100644 --- a/tests/data/edge_cases/05_escape_char/google.py +++ b/tests/data/edge_cases/05_escape_char/google.py @@ -1,3 +1,7 @@ +# From these issues: +# https://github.com/jsh9/pydoclint/issues/73 +# https://github.com/jsh9/pydoclint/issues/92 + def myFunc( arg1_: int, arg2__: int, @@ -8,6 +12,8 @@ def myFunc( some_thing_3___: int, some_thing_4____: int, some_thing_5_____: str, + *args: Any, + **kwargs: Any, ) -> None: r""" Do something. @@ -22,6 +28,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 diff --git a/tests/data/edge_cases/05_escape_char/numpy.py b/tests/data/edge_cases/05_escape_char/numpy.py index 22ecbe1..8e3cc16 100644 --- a/tests/data/edge_cases/05_escape_char/numpy.py +++ b/tests/data/edge_cases/05_escape_char/numpy.py @@ -1,3 +1,7 @@ +# From these issues: +# https://github.com/jsh9/pydoclint/issues/73 +# https://github.com/jsh9/pydoclint/issues/92 + def myFunc( arg1_: int, arg2__: int, @@ -8,6 +12,8 @@ def myFunc( some_thing_3___: int, some_thing_4____: int, some_thing_5_____: str, + *args: Any, + **kwargs: Any, ) -> None: r""" Do something. @@ -32,6 +38,10 @@ def myFunc( Arg some_thing_5_____ : str Arg + *args : Any + Args + **kwargs : Any + Keyword args Returns ------- diff --git a/tests/data/edge_cases/05_escape_char/sphinx.py b/tests/data/edge_cases/05_escape_char/sphinx.py index ab8fc97..b10c5a6 100644 --- a/tests/data/edge_cases/05_escape_char/sphinx.py +++ b/tests/data/edge_cases/05_escape_char/sphinx.py @@ -1,3 +1,7 @@ +# From these issues: +# https://github.com/jsh9/pydoclint/issues/73 +# https://github.com/jsh9/pydoclint/issues/92 + def myFunc( arg1_: int, arg2__: int, @@ -8,6 +12,8 @@ def myFunc( some_thing_3___: int, some_thing_4____: int, some_thing_5_____: str, + *args: Any, + **kwargs: Any, ) -> None: r""" Do something. @@ -30,6 +36,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 """ diff --git a/tests/utils/test_arg.py b/tests/utils/test_arg.py index 8cc07d5..0a2c2d8 100644 --- a/tests/utils/test_arg.py +++ b/tests/utils/test_arg.py @@ -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'), + (Arg(name='**kwargs', typeHint='Any'), '**kwargs: Any'), + (Arg(name='\\**kwargs', typeHint='Any'), '**kwargs: Any'), ], ) def testArg_str(arg: Arg, string_repr: str) -> None: @@ -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: @@ -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 @@ -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')]), + ArgList([Arg('arg1_', '1'), Arg('arg2\_\_', '2')]), + ), ], ) def testArgList_equality(list1: ArgList, list2: ArgList) -> None: @@ -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')]), + ArgList([Arg('arg2\_\_', '2')]), + {Arg('arg1_', '1')}, + ), ], ) def testArgList_subtract( From 87f82e6b1f1bcbda1d42e7aee082a3eac54e145a Mon Sep 17 00:00:00 2001 From: jsh9 <25124332+jsh9@users.noreply.github.com> Date: Fri, 20 Oct 2023 13:30:24 -0400 Subject: [PATCH 2/4] Auto-format --- tests/data/edge_cases/05_escape_char/google.py | 1 + tests/data/edge_cases/05_escape_char/numpy.py | 1 + tests/data/edge_cases/05_escape_char/sphinx.py | 1 + 3 files changed, 3 insertions(+) diff --git a/tests/data/edge_cases/05_escape_char/google.py b/tests/data/edge_cases/05_escape_char/google.py index 935f110..d60e7e5 100644 --- a/tests/data/edge_cases/05_escape_char/google.py +++ b/tests/data/edge_cases/05_escape_char/google.py @@ -2,6 +2,7 @@ # https://github.com/jsh9/pydoclint/issues/73 # https://github.com/jsh9/pydoclint/issues/92 + def myFunc( arg1_: int, arg2__: int, diff --git a/tests/data/edge_cases/05_escape_char/numpy.py b/tests/data/edge_cases/05_escape_char/numpy.py index 8e3cc16..02fa8c1 100644 --- a/tests/data/edge_cases/05_escape_char/numpy.py +++ b/tests/data/edge_cases/05_escape_char/numpy.py @@ -2,6 +2,7 @@ # https://github.com/jsh9/pydoclint/issues/73 # https://github.com/jsh9/pydoclint/issues/92 + def myFunc( arg1_: int, arg2__: int, diff --git a/tests/data/edge_cases/05_escape_char/sphinx.py b/tests/data/edge_cases/05_escape_char/sphinx.py index b10c5a6..4383a57 100644 --- a/tests/data/edge_cases/05_escape_char/sphinx.py +++ b/tests/data/edge_cases/05_escape_char/sphinx.py @@ -2,6 +2,7 @@ # https://github.com/jsh9/pydoclint/issues/73 # https://github.com/jsh9/pydoclint/issues/92 + def myFunc( arg1_: int, arg2__: int, From 652e3ab6f5807f22bcb949410c77f7d8ac1ba32b Mon Sep 17 00:00:00 2001 From: jsh9 <25124332+jsh9@users.noreply.github.com> Date: Fri, 20 Oct 2023 13:32:56 -0400 Subject: [PATCH 3/4] Fix flake8 --- tests/utils/test_arg.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/utils/test_arg.py b/tests/utils/test_arg.py index 0a2c2d8..6249569 100644 --- a/tests/utils/test_arg.py +++ b/tests/utils/test_arg.py @@ -16,7 +16,7 @@ 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'), + (Arg(name='arg1\_\_', typeHint='Any'), 'arg1__: Any'), # noqa: W605 (Arg(name='**kwargs', typeHint='Any'), '**kwargs: Any'), (Arg(name='\\**kwargs', typeHint='Any'), '**kwargs: Any'), ], @@ -205,8 +205,8 @@ def testArgList_length(input_: ArgList, expected: int) -> None: ArgList([Arg('\\*args', '1'), Arg('**kwargs', '2')]), ), ( - ArgList([Arg('arg1\_', '1'), Arg('arg2__', '2')]), - ArgList([Arg('arg1_', '1'), Arg('arg2\_\_', '2')]), + ArgList([Arg('arg1\_', '1'), Arg('arg2__', '2')]), # noqa: W605 + ArgList([Arg('arg1_', '1'), Arg('arg2\_\_', '2')]), # noqa: W605 ), ], ) @@ -319,8 +319,8 @@ def testArgList_contains( {Arg('**kwargs', '2')}, ), ( - ArgList([Arg('arg1\_', '1'), Arg('arg2__', '2')]), - ArgList([Arg('arg2\_\_', '2')]), + ArgList([Arg('arg1\_', '1'), Arg('arg2__', '2')]), # noqa: W605 + ArgList([Arg('arg2\_\_', '2')]), # noqa: W605 {Arg('arg1_', '1')}, ), ], From 632cbf1c666f2b5e497a2d360a251469bac95c3b Mon Sep 17 00:00:00 2001 From: jsh9 <25124332+jsh9@users.noreply.github.com> Date: Fri, 20 Oct 2023 13:34:24 -0400 Subject: [PATCH 4/4] Bump version and update changelog --- CHANGELOG.md | 9 +++++++++ setup.cfg | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d9bf83f..22f9daa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/setup.cfg b/setup.cfg index e4e32f1..6e4dcd2 100644 --- a/setup.cfg +++ b/setup.cfg @@ -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