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

Add full violations codes to docs #2409

Merged
merged 15 commits into from
Apr 30, 2022
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ Semantic versioning in our case means:
change the client facing API, change code conventions significantly, etc.


## 0.16.2

### Misc
- Adds full violation codes to docs and `BaseViolation.full_code` #2409

## 0.16.1

### Bugfixes
Expand Down
6 changes: 6 additions & 0 deletions tests/test_violations/test_docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,9 @@ def test_configuration(all_violations):

for option_item, is_listed in option_listed.items():
assert is_listed, option_item


def test_all_violations_doc_start_with_full_code(all_violations):
"""Ensures that all violations have `versionadded` tag."""
for violation in all_violations:
assert violation.__doc__.lstrip().startswith(violation.full_code)
28 changes: 25 additions & 3 deletions wemake_python_styleguide/violations/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ class SomeViolation(ASTViolation):
#: We use this type to define helper classes with callbacks to add violations.
ErrorCallback = Callable[['BaseViolation'], None]

def _prepend_skipping_whitespaces(prefix: str, text: str) -> str:
Bobronium marked this conversation as resolved.
Show resolved Hide resolved
lstripped_text = text.lstrip()
leading_whitespaces = text[:len(text) - len(lstripped_text)]
return f'{leading_whitespaces}{prefix}{lstripped_text}'
Bobronium marked this conversation as resolved.
Show resolved Hide resolved


@enum.unique
class ViolationPostfixes(enum.Enum):
Expand Down Expand Up @@ -98,12 +103,28 @@ class BaseViolation(object, metaclass=abc.ABCMeta):
code: ClassVar[int]
previous_codes: ClassVar[Set[int]]
deprecated: ClassVar[bool] = False

# assigned in __init_subclass__
full_code: ClassVar[str]
summary: ClassVar[str]

# We use this code to show base metrics and thresholds mostly:
postfix_template: ClassVar[ViolationPostfixes] = (
ViolationPostfixes.bigger_than
)

def __init_subclass__(cls) -> None:
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This causes WPS338 error. Considering that #2411 is in place, what should be our course of action?

I see the following options:

  1. Suppress the error until Add __init_subclass__ to the methods order #2411 gets released
  2. Obey current rules of ordering, refactor once Add __init_subclass__ to the methods order #2411 gets released
  3. Do nothing, wait until Add __init_subclass__ to the methods order #2411 gets released

"""
Bobronium marked this conversation as resolved.
Show resolved Hide resolved
Derives and sets additional values for subclasses
"""
if hasattr(cls, 'code'):
Bobronium marked this conversation as resolved.
Show resolved Hide resolved
# this is mostly done for docs to display the full code,
# allowing its indexing in search engines and better discoverability
cls.full_code = cls._full_code()
cls.summary = cls.__doc__.lstrip().split('\n', maxsplit=1)[0]
# this hack adds full code to summary table in the docs
cls.__doc__ = _prepend_skipping_whitespaces(f'{cls.full_code} — ', cls.__doc__)
Bobronium marked this conversation as resolved.
Show resolved Hide resolved

def __init__(
self,
node: ErrorNode,
Expand Down Expand Up @@ -131,7 +152,7 @@ def message(self) -> str:
Conditionally formats the ``error_template`` if it is required.
"""
return '{0} {1}{2}'.format(
self._full_code(),
self.full_code,
self.error_template.format(self._text),
self._postfix_information(),
)
Expand All @@ -142,14 +163,15 @@ def node_items(self) -> Tuple[int, int, str]:
return (*self._location(), self.message())

@final
def _full_code(self) -> str:
@classmethod
def _full_code(cls) -> str:
"""
Returns fully formatted code.

Adds violation letter to the numbers.
Also ensures that codes like ``3`` will be represented as ``WPS003``.
"""
return 'WPS{0}'.format(str(self.code).zfill(3))
return 'WPS{0}'.format(str(cls.code).zfill(3))

@final
def _postfix_information(self) -> str:
Expand Down