diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1598bab..53bb056 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -8,7 +8,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.7", "3.8", "3.9", "3.10"] + python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12"] steps: - uses: actions/checkout@v2 - name: Set up Python ${{ matrix.python-version }} diff --git a/README.rst b/README.rst index 5521bae..e043b77 100644 --- a/README.rst +++ b/README.rst @@ -238,6 +238,10 @@ suggest ignoring some of the violation codes:: # See https://github.com/peterjc/flake8-rst-docstrings/issues/17 RST201,RST203,RST301, +Using ``*arg`` or ``**kwargs`` without escaping in argument descriptions has +been special-cased to avoid triggering ``RST213`` and ``RST210`` respectively. +However, other variable names used this way will trigger as missing closing +markup for emphasis and strong, so you may have to ignore those codes as well. Version History --------------- @@ -245,6 +249,7 @@ Version History ======= ========== =========================================================== Version Released Changes ------- ---------- ----------------------------------------------------------- +v0.3.1 2023-12-22 - Ignore ``*args`` (``RST213``) & ``**kwargs`` (``RST210``) v0.3.0 2022-11-16 - Replaced ``setup.py`` with ``pyproject.toml``. v0.2.7 2022-07-15 - Fix where function signature occurred in docstring body. v0.2.6 2022-06-07 - Configuration option to define additional substitutions @@ -306,6 +311,10 @@ dependencies:: $ pip install -e .[develop] +To run the tests locally:: + + $ pytest --verbose + To make a new release once tested locally and on TravisCI:: $ git tag vX.Y.Z diff --git a/flake8_rst_docstrings.py b/flake8_rst_docstrings.py index 9d836ec..afd18db 100644 --- a/flake8_rst_docstrings.py +++ b/flake8_rst_docstrings.py @@ -25,8 +25,7 @@ re.VERBOSE, ) -__version__ = "0.3.0" - +__version__ = "0.3.1" rst_prefix = "RST" rst_fail_load = 900 @@ -123,6 +122,23 @@ def code_mapping( return default +def special_case_unescaped(docstring, variable): + """Can RST213 for ``*arg``, or RST210 for ``*kwarg`` be ignored.""" + if "\nArgs:\n" in docstring and docstring.find("\nArgs:\n") < docstring.find( + f" {variable}:" + ): + # Ignore special case used in Google docstring style + return True + elif "\nParameters\n----------\n" in docstring: + i = docstring.find("\nParameters\n----------\n") + if i < docstring.find(f"\n{variable}\n") or i < docstring.find( + f"\n{variable} :" + ): + # Ignore special case used in NumPy docstring style + return True + return False + + class reStructuredTextChecker: """Checker of Python docstrings as reStructuredText.""" @@ -257,5 +273,14 @@ def run(self): code += 100 * rst_error.level msg = "%s%03i %s" % (rst_prefix, code, msg) + # Silence special case use of *args and **kwargs + # (hopefully won't mask a true positive in same docstring) + if code == 210 and special_case_unescaped(docstring, "**kwargs"): + # Ignore special case used in Google/NumPy docstring style + continue + elif code == 213 and special_case_unescaped(docstring, "*args"): + # Ignore special case used in Google/NumPy docstring style + continue + # We don't know the column number, leaving as zero. yield start + rst_error.line, 0, msg, type(self) diff --git a/tests/test_cases/google_args_and_kwargs.py b/tests/test_cases/google_args_and_kwargs.py new file mode 100644 index 0000000..8064b2e --- /dev/null +++ b/tests/test_cases/google_args_and_kwargs.py @@ -0,0 +1,18 @@ +"""Google docstring style test case.""" + + +def module_level_function(param1, param2=None, *args, **kwargs): + """Accept keyword arguments. + + Here using the Google docstring style, notice that we have *not* escaped + the asterisk in ``*args*`` or ``**kwargs`` in the argument list. + + Args: + param1 (int): The first parameter. + param2 (str, optional): The second parameter. Defaults to None. + *args: Variable length argument list. + **kwargs: Arbitrary keyword arguments. + + ... + """ + pass diff --git a/tests/test_cases/numpy_args_and_kwargs.py b/tests/test_cases/numpy_args_and_kwargs.py new file mode 100644 index 0000000..38ec682 --- /dev/null +++ b/tests/test_cases/numpy_args_and_kwargs.py @@ -0,0 +1,23 @@ +"""Numpy style docstring example.""" + + +def module_level_function(param1, param2=None, *args, **kwargs): + """Accept keyword arguments. + + Here using the Numpy docstring style, notice that we have *not* escaped + the asterisk in ``*args*`` or ``**kwargs`` in the parameter list. + + Parameters + ---------- + param1 : int + The first parameter. + param2 : str optional + The second parameter. + *args + Variable length argument list. + **kwargs + Arbitrary keyword arguments. + + ... + """ + pass