Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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
19 changes: 19 additions & 0 deletions docs/checking_class_attributes.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ ______________________________________________________________________
- [1. Numpy style](#1-numpy-style)
- [2. Google style](#2-google-style)
- [3. Sphinx style](#3-sphinx-style)
- [4. Inline docstrings](#4-inline-docstrings)

______________________________________________________________________

Expand Down Expand Up @@ -186,3 +187,21 @@ class MyPet:
def __init__(self, airtag_id: int) -> None:
self.airtag_id = airtag_id
```

## 4. Inline docstrings

PEP-257 indicates that string literals located directly after an assign
Comment thread
mpyuglgwkxcmodyrpo marked this conversation as resolved.
Outdated
statement may be treated as attribute documentation. As such, we also
optionally support inline docstrings for class attributes with the
`allow-inline-classvar-docs` option set to True (it is False by default).
Comment thread
mpyuglgwkxcmodyrpo marked this conversation as resolved.
Outdated

Attribute type documentation may be specified as the first thing in the
docstring followed by a colon. For example:

```python
class MyClass:
"""My class that does things."""

field1 = 5
"""int: My first field"""
```
61 changes: 41 additions & 20 deletions docs/config_options.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,17 @@ ______________________________________________________________________
- [16. `--should-document-private-class-attributes` (shortform: `-sdpca`, default: `False`)](#16---should-document-private-class-attributes-shortform--sdpca-default-false)
- [17. `--treat-property-methods-as-class-attributes` (shortform: `-tpmaca`, default: `False`)](#17---treat-property-methods-as-class-attributes-shortform--tpmaca-default-false)
- [18. `--only-attrs-with-ClassVar-are-treated-as-class-attrs` (shortform: `-oawcv`, default: `False`)](#18---only-attrs-with-classvar-are-treated-as-class-attrs-shortform--oawcv-default-false)
- [19. `--should-document-star-arguments` (shortform: `-sdsa`, default: `True`)](#19---should-document-star-arguments-shortform--sdsa-default-true)
- [20. `--omit-stars-when-documenting-varargs` (shortform: `-oswdv`, default: `False`)](#20---omit-stars-when-documenting-varargs-shortform--oswdv-default-false)
- [21. `--check-style-mismatch` (shortform: `-csm`, default: `False`)](#21---check-style-mismatch-shortform--csm-default-false)
- [22. `--check-arg-defaults` (shortform: `-cad`, default: `False`)](#22---check-arg-defaults-shortform--cad-default-false)
- [23. `--baseline`](#23---baseline)
- [24. `--generate-baseline` (default: `False`)](#24---generate-baseline-default-false)
- [25. `--auto-regenerate-baseline` (shortform: `-arb`, default: `True`)](#25---auto-regenerate-baseline-shortform--arb-default-true)
- [26. `--show-filenames-in-every-violation-message` (shortform: `-sfn`, default: `False`)](#26---show-filenames-in-every-violation-message-shortform--sfn-default-false)
- [27. `--native-mode-noqa-location` (shortform: `-nmnl`, default: `docstring`)](#27---native-mode-noqa-location-shortform--nmnl-default-docstring)
- [28. `--config` (default: `pyproject.toml`)](#28---config-default-pyprojecttoml)
- [19. `--allow-inline-classvar-docs` (shortform: `-aicvd`, default: `False`)](#19---allow-inline-classvar-docs-shortform--aicvd-default-false)
- [20. `--should-document-star-arguments` (shortform: `-sdsa`, default: `True`)](#20---should-document-star-arguments-shortform--sdsa-default-true)
- [21. `--omit-stars-when-documenting-varargs` (shortform: `-oswdv`, default: `False`)](#21---omit-stars-when-documenting-varargs-shortform--oswdv-default-false)
- [22. `--check-style-mismatch` (shortform: `-csm`, default: `False`)](#22---check-style-mismatch-shortform--csm-default-false)
- [23. `--check-arg-defaults` (shortform: `-cad`, default: `False`)](#23---check-arg-defaults-shortform--cad-default-false)
- [24. `--baseline`](#24---baseline)
- [25. `--generate-baseline` (default: `False`)](#25---generate-baseline-default-false)
- [26. `--auto-regenerate-baseline` (shortform: `-arb`, default: `True`)](#26---auto-regenerate-baseline-shortform--arb-default-true)
- [27. `--show-filenames-in-every-violation-message` (shortform: `-sfn`, default: `False`)](#27---show-filenames-in-every-violation-message-shortform--sfn-default-false)
- [28. `--native-mode-noqa-location` (shortform: `-nmnl`, default: `docstring`)](#28---native-mode-noqa-location-shortform--nmnl-default-docstring)
- [29. `--config` (default: `pyproject.toml`)](#29---config-default-pyprojecttoml)

______________________________________________________________________

Expand Down Expand Up @@ -229,20 +230,40 @@ If True, only the attributes whose type annotations are wrapped within
`ClassVar` (where `ClassVar` is imported from `typing`) are treated as class
attributes, and all other attributes are treated as instance attributes.

## 19. `--should-document-star-arguments` (shortform: `-sdsa`, default: `True`)
## 19. `--allow-inline-classvar-docs` (shortform: `-aicvd`, default: `False`)

If True, allow class attributes to have inline documentation. For example:

```python
class MyClass:
"""My class."""

field1: int = 5
"""int: Field 1 documentation."""
```

If False, pydoclint will not parse inline class attribute docstrings.

Inline documentation will not supersede class-level documentation, meaning that
if you declare an attribute at the class level **and** an inline docstring,
pydoclint will take the class-level documentation and not the inline docstring.
Comment thread
mpyuglgwkxcmodyrpo marked this conversation as resolved.
Outdated
Inline docstrings may specify the attribute type as the first token in the
docstring followed by a `:`.

## 20. `--should-document-star-arguments` (shortform: `-sdsa`, default: `True`)

If True, "star arguments" (such as `*args`, `**kwargs`, `**props`, etc.) in the
function signature should be documented in the docstring. If False, they should
not appear in the docstring.

## 20. `--omit-stars-when-documenting-varargs` (shortform: `-oswdv`, default: `False`)
## 21. `--omit-stars-when-documenting-varargs` (shortform: `-oswdv`, default: `False`)

If True, docstring argument entries describing `*args` or `**kwargs` may omit
the leading `*`, and pydoclint will still match them against the function
signature. Leave this disabled to require docstrings to include the leading `*`
characters for varargs.

## 21. `--check-style-mismatch` (shortform: `-csm`, default: `False`)
## 22. `--check-style-mismatch` (shortform: `-csm`, default: `False`)

If True, check that style specified in --style matches the detected style of
the docstring. If there is a mismatch, `DOC003` will be reported. Setting this
Expand All @@ -251,13 +272,13 @@ to False will silence all `DOC003` violations.
Read more about this config option and `DOC003` at
[https://jsh9.github.io/pydoclint/style_mismatch.html](https://jsh9.github.io/pydoclint/style_mismatch.html).

## 22. `--check-arg-defaults` (shortform: `-cad`, default: `False`)
## 23. `--check-arg-defaults` (shortform: `-cad`, default: `False`)

If True, docstring type hints should contain default values consistent with the
function signature. If False, docstring type hints should not contain default
values. (Only applies to numpy style for now.)

## 23. `--baseline`
## 24. `--baseline`

Baseline allows you to remember the current project state and then show only
new violations, ignoring old ones. This can be very useful when you'd like to
Expand All @@ -279,20 +300,20 @@ If `--generate-baseline` is not passed to _pydoclint_ (the default is `False`),
_pydoclint_ will read your baseline file, and ignore all violations specified
in that file.

## 24. `--generate-baseline` (default: `False`)
## 25. `--generate-baseline` (default: `False`)

Required to use with `--baseline` option. If `True`, generate the baseline file
that contains all current violations.

## 25. `--auto-regenerate-baseline` (shortform: `-arb`, default: `True`)
## 26. `--auto-regenerate-baseline` (shortform: `-arb`, default: `True`)

If it's set to True, _pydoclint_ will automatically regenerate the baseline
file every time you fix violations in the baseline and rerun _pydoclint_.

This saves you from having to manually regenerate the baseline file by setting
`--generate-baseline=True` and run _pydoclint_.

## 26. `--show-filenames-in-every-violation-message` (shortform: `-sfn`, default: `False`)
## 27. `--show-filenames-in-every-violation-message` (shortform: `-sfn`, default: `False`)

If False, in the terminal the violation messages are grouped by file names:

Expand Down Expand Up @@ -326,7 +347,7 @@ This can be convenient if you would like to click on each violation message and
go to the corresponding line in your IDE. (Note: not all terminal app offers
this functionality.)

## 27. `--native-mode-noqa-location` (shortform: `-nmnl`, default: `docstring`)
## 28. `--native-mode-noqa-location` (shortform: `-nmnl`, default: `docstring`)

This option controls where _pydoclint_ looks for inline `# noqa: DOCxxx`
comments when running in native mode (i.e., outside of Flake8). Two values are
Expand All @@ -341,7 +362,7 @@ Only DOC-prefixed violation codes are honored; other codes are ignored by the
native parser. This setting has no effect in Flake8 mode, which is controlled
by Flake8's own `noqa` handling.

## 28. `--config` (default: `pyproject.toml`)
## 29. `--config` (default: `pyproject.toml`)

The full path of the .toml config file that contains the config options. Note
that the command line options take precedence over the .toml file. Look at this
Expand Down
1 change: 1 addition & 0 deletions muff.toml
Original file line number Diff line number Diff line change
Expand Up @@ -139,5 +139,6 @@ max-bool-expr = 10
max-branches = 100
max-locals = 1000
max-nested-blocks = 10
max-public-methods = 30
max-returns = 30
max-statements = 50
14 changes: 14 additions & 0 deletions pydoclint/flake8_entry.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,14 @@ def add_options(cls, parser: Any) -> None: # noqa: D102
' attributes are treated as instance attributes.'
),
)
parser.add_option(
'-aicvd',
'--allow-inline-class-var-docs',
action='store',
default='False',
parse_from_config=True,
help='If True, allow inline documentation for class attributes.',
)
parser.add_option(
'-sdsa',
'--should-document-star-arguments',
Expand Down Expand Up @@ -347,6 +355,7 @@ def parse_options(cls, options: Any) -> None: # noqa: D102
cls.only_attrs_with_ClassVar_are_treated_as_class_attrs = (
options.only_attrs_with_ClassVar_are_treated_as_class_attrs
)
cls.allow_inline_class_var_docs = options.allow_inline_class_var_docs
cls.should_document_star_arguments = (
options.should_document_star_arguments
)
Expand Down Expand Up @@ -440,6 +449,10 @@ def run(self) -> Generator[tuple[int, int, str, Any], None, None]:
'--only-attrs-with-ClassVar-are-treated-as-class-attrs',
self.only_attrs_with_ClassVar_are_treated_as_class_attrs,
)
allowInlineClassVarDocs = self._bool(
'--allow-inline-class-var-docs',
self.allow_inline_class_var_docs,
)
shouldDocumentStarArguments = self._bool(
'--should-document-star-arguments',
self.should_document_star_arguments,
Expand Down Expand Up @@ -490,6 +503,7 @@ def run(self) -> Generator[tuple[int, int, str, Any], None, None]:
onlyAttrsWithClassVarAreTreatedAsClassAttrs=(
onlyAttrsWithClassVarAreTreatedAsClassAttrs
),
allowInlineClassVarDocs=allowInlineClassVarDocs,
shouldDocumentStarArguments=shouldDocumentStarArguments,
omitStarsWhenDocumentingVarargs=omitStarsWhenDocumentingVarargs,
checkStyleMismatch=checkStyleMismatch,
Expand Down
14 changes: 14 additions & 0 deletions pydoclint/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,14 @@ def validateNativeModeNoqaLocation(
' treated as instance attributes.'
),
)
@click.option(
'-aicvd',
'--allow-inline-classvar-docs',
type=bool,
show_default=True,
default=False,
help='If True, allow inline documentation of class attributes.',
)
@click.option(
'-sdsa',
'--should-document-star-arguments',
Expand Down Expand Up @@ -469,6 +477,7 @@ def main( # noqa: C901, PLR0915
require_return_section_when_returning_nothing: bool,
require_yield_section_when_yielding_nothing: bool,
only_attrs_with_classvar_are_treated_as_class_attrs: bool,
allow_inline_classvar_docs: bool,
should_document_star_arguments: bool,
omit_stars_when_documenting_varargs: bool,
should_declare_assert_error_if_assert_statement_exists: bool,
Expand Down Expand Up @@ -580,6 +589,7 @@ def main( # noqa: C901, PLR0915
onlyAttrsWithClassVarAreTreatedAsClassAttrs=(
only_attrs_with_classvar_are_treated_as_class_attrs
),
allowInlineClassVarDocs=allow_inline_classvar_docs,
requireReturnSectionWhenReturningNothing=(
require_return_section_when_returning_nothing
),
Expand Down Expand Up @@ -736,6 +746,7 @@ def _checkPaths(
shouldDocumentPrivateClassAttributes: bool = False,
treatPropertyMethodsAsClassAttributes: bool = False,
onlyAttrsWithClassVarAreTreatedAsClassAttrs: bool = False,
allowInlineClassVarDocs: bool = False,
requireReturnSectionWhenReturningNothing: bool = False,
requireYieldSectionWhenYieldingNothing: bool = False,
shouldDocumentStarArguments: bool = True,
Expand Down Expand Up @@ -798,6 +809,7 @@ def _checkPaths(
onlyAttrsWithClassVarAreTreatedAsClassAttrs=(
onlyAttrsWithClassVarAreTreatedAsClassAttrs
),
allowInlineClassVarDocs=allowInlineClassVarDocs,
requireReturnSectionWhenReturningNothing=(
requireReturnSectionWhenReturningNothing
),
Expand Down Expand Up @@ -836,6 +848,7 @@ def _checkFile(
shouldDocumentPrivateClassAttributes: bool = False,
treatPropertyMethodsAsClassAttributes: bool = False,
onlyAttrsWithClassVarAreTreatedAsClassAttrs: bool = False,
allowInlineClassVarDocs: bool = False,
requireReturnSectionWhenReturningNothing: bool = False,
requireYieldSectionWhenYieldingNothing: bool = False,
shouldDocumentStarArguments: bool = True,
Expand Down Expand Up @@ -893,6 +906,7 @@ def _checkFile(
onlyAttrsWithClassVarAreTreatedAsClassAttrs=(
onlyAttrsWithClassVarAreTreatedAsClassAttrs
),
allowInlineClassVarDocs=allowInlineClassVarDocs,
requireReturnSectionWhenReturningNothing=(
requireReturnSectionWhenReturningNothing
),
Expand Down
9 changes: 9 additions & 0 deletions pydoclint/utils/arg.py
Original file line number Diff line number Diff line change
Expand Up @@ -431,3 +431,12 @@ def hasTypeHintInAllArgs(self) -> bool:
they don't need to have type hints.
"""
return all(_.hasTypeHint() for _ in self.infoList if _.notStarArg())

def insertAt(
self,
index: int,
arg: Arg,
) -> None:
"""Insert an Arg at a specific index."""
self.infoList.insert(index, arg)
self.lookup[arg.name] = arg.typeHint
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there any safeguards when arg already exists in self.infoList and self.lookup?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a check and exception. Thoughts? It should be an edge case.

Loading