Replace Pylama with Prospector

Pylama is no longer maintained, and has been gradually getting slower
and slower, as well as being incompatible with Python 3.7 and newer
versions of astroid and pylint. This replaces it with Prospector, which
is being maintained by the same group as pylint and some other code
quality tools.
This commit is contained in:
Chad Birch
2018-08-29 13:20:50 -06:00
parent d1a73f4a12
commit d170962204
16 changed files with 58 additions and 83 deletions

View File

@@ -6,4 +6,4 @@ vagrant ssh -c ". activate \
&& echo 'Checking mypy type annotations...' && mypy . \
&& echo 'Checking if Black would reformat any code...' && black --check . \
&& echo -n 'Running tests: ' && pytest -q \
&& echo 'Checking code style fully (takes a while)...' && pylama"
&& echo 'Checking code style fully (takes a while)...' && prospector -M"

34
tildes/prospector.yaml Normal file
View File

@@ -0,0 +1,34 @@
strictness: none
doc-warnings: true
max-line-length: 88
ignore-paths:
- alembic
pep8:
disable:
# "multiple statements on one line" - type declarations seem to trigger sometimes
- E704
pep257:
disable:
# checks for blank lines after a function docstring, but Black will add one
# when the first code in the function is another function definition.
- D202
- D203 # blank line before class docstring
- D213 # blank line after summary line for multi-line docstring
pyflakes:
disable:
- F401 # unused imports, triggers in __init__.py and pylint can handle it otherwise
pylint:
enable: all
disable:
- bad-continuation # let Black handle line-wrapping
- comparison-with-callable # seems to have a lot of false positives
- logging-fstring-interpolation # rather use f-strings than worry about this
- no-else-return # elif after return - could refactor to enable this check
- no-self-use # schemas do this a lot, would be nice to only disable for schemas
- too-few-public-methods # plenty of classes that don't need multiple methods
- too-many-instance-attributes # models have many instance attributes

View File

@@ -1,69 +0,0 @@
[pylama]
linters = mccabe,pycodestyle,pydocstyle,pyflakes,pylint
skip = alembic/*
# ignored checks:
# - D202 - pydocstyle check for blank lines after a function docstring, but
# Black will add one when the first code in the function is another
# function definition.
# - D203 - pydocstyle has two mutually exclusive checks (D203/D211)
# for whether a class docstring should have a blank line before
# it or not. I don't want a blank line, so D203 is disabled.
# - D213 - another pair of mutually exclusive pydocstyle checks, this
# time for whether a multi-line docstring's summary line should be
# on the first or second line. I want it to be on the first line,
# so D213 needs to be disabled.
# - E203 - checks for whitespace around : in slices, but Black adds it
# in some cases.
ignore = D202,D203,D213,E203
[pylama:pycodestyle]
max_line_length = 88
[pylama:pylint]
enable = all
# disabled pylint checks:
# - bad-continuation (Black will handle wrapping lines properly)
# - missing-docstring (already reported by pydocstyle)
# - too-few-public-methods (more annoying than helpful, especially early on)
# - too-many-instance-attributes (overly-picky when models need many)
# - locally-disabled (don't need a warning about things I disable)
# - locally-enabled (or when checks are (re-)enabled)
# - suppressed-message (...a different message when I disable one?)
disable =
bad-continuation,
missing-docstring,
too-few-public-methods,
too-many-instance-attributes,
locally-disabled,
locally-enabled,
suppressed-message
# The APIv0 and venusian.AttachInfo classes need to be ignored because pylint
# can't recognize dynamically-added methods/attrs, so all of the functions in
# cornice.Service like .get(), .post(), etc. cause errors.
ignored-classes = APIv0, venusian.AttachInfo
[pylama:tildes/schemas/*]
# ignored checks for schemas specifically:
# - R0201 - method could be a function (for @pre_load-type methods)
ignore = R0201
[pylama:tildes/views/api/web/*]
# ignored checks for web API specifically:
# - C0103 - invalid function names (endpoints can have very long ones)
ignore = C0103
[pylama:tests/*]
# ignored checks for tests specifically:
# - D100 - missing module-level docstrings
# - C0103 - invalid function names (tests often have very long ones)
# - W0212 - access to protected member (useful/necessary for tests sometimes)
# - W0621 - redefining name from outer scope (that's how pytest fixtures work)
# - E1101 - <something> has no member (mocks add members this can't detect)
ignore = D100,C0103,W0212,W0621,E1101
[pylama:*/__init__.py]
# ignore "imported but unused" inside __init__.py files
ignore = W0611

View File

@@ -2,7 +2,6 @@ ago
alembic
amqpy
argon2_cffi
astroid==1.5.3 # pylama has issues with pylint 1.8.1
black
bleach
click
@@ -15,12 +14,9 @@ mypy
mypy-extensions
Pillow
prometheus-client
prospector
psycopg2
publicsuffix2
pydocstyle
pylama
pylama-pylint
pylint==1.7.5 # pylama has issues with 1.8.1
pyotp
pyramid
pyramid-debugtoolbar

View File

@@ -3,7 +3,7 @@ alembic==1.0.0
amqpy==0.13.1
appdirs==1.4.3
argon2-cffi==18.3.0
astroid==1.5.3
astroid==2.0.4
atomicwrites==1.2.0
attrs==18.1.0
backcall==0.1.0
@@ -16,6 +16,9 @@ chardet==3.0.4
click==6.7
cornice==3.4.0
decorator==4.3.0
dodgy==0.1.9
flake8==3.5.0
flake8-polyfill==1.0.2
freezegun==0.3.10
gunicorn==19.9.0
html5lib==1.0.1
@@ -36,6 +39,7 @@ mypy==0.620
mypy-extensions==0.4.1
parso==0.3.1
PasteDeploy==1.5.2
pep8-naming==0.7.0
pexpect==4.6.0
pickleshare==0.7.4
Pillow==5.2.0
@@ -44,18 +48,18 @@ plaster-pastedeploy==0.6
pluggy==0.7.1
prometheus-client==0.3.1
prompt-toolkit==1.0.15
prospector==1.1.2
psycopg2==2.7.5
ptyprocess==0.6.0
publicsuffix2==2.20160818
py==1.6.0
pycodestyle==2.4.0
pycodestyle==2.3.1
pycparser==2.18
pydocstyle==2.1.1
pyflakes==2.0.0
pyflakes==1.6.0
Pygments==2.2.0
pylama==7.4.3
pylama-pylint==3.0.1
pylint==1.7.5
pylint==2.1.1
pylint-plugin-utils==0.4
pyotp==2.2.6
pyramid==1.9.2
pyramid-debugtoolbar==4.4
@@ -74,6 +78,8 @@ qrcode==6.0
redis==2.10.6
repoze.lru==0.7
requests==2.19.1
requirements-detector==0.6
setoptconf==0.2.0
simplegeneric==0.8.1
simplejson==3.16.0
six==1.11.0

View File

@@ -1,4 +1,5 @@
"""Script for doing the initial setup of database tables."""
# pylint: disable=wrong-import-order
import os
import subprocess

View File

@@ -2,7 +2,6 @@
WELCOME_MESSAGE_SUBJECT = "Welcome to the Tildes alpha"
# pylama:ignore=E501
WELCOME_MESSAGE_TEXT = """
Hi, welcome to the Tildes alpha!

View File

@@ -32,6 +32,7 @@ class CommentNotificationQuery(ModelQuery):
def join_all_relationships(self) -> "CommentNotificationQuery":
"""Eagerly join the comment, topic, and group to the notification."""
# pylint: disable=self-cls-assignment
self = self.options(
joinedload(CommentNotification.comment)
.joinedload("topic")

View File

@@ -168,6 +168,7 @@ class CommentTree:
direct parents. All comments with any uncollapsed descendant will be collapsed
individually. Branches with no uncollapsed comments will be collapsed fully.
"""
# pylint: disable=too-many-branches
for comment in reversed(self.comments):
# as soon as we reach an old comment, we can stop
if comment.created_time <= threshold:

View File

@@ -1,4 +1,5 @@
"""Contains the Log class."""
# pylint: disable=too-many-branches,too-many-return-statements
from typing import Any, Dict, Optional
@@ -142,7 +143,6 @@ class LogTopic(DatabaseModel, BaseLog):
def __str__(self) -> str:
"""Return a string representation of the log event."""
# pylint: disable=too-many-return-statements
if self.event_type == LogEventType.TOPIC_TAG:
return self._tag_event_description()
elif self.event_type == LogEventType.TOPIC_MOVE:

View File

@@ -1,4 +1,5 @@
"""Contains the ModelQuery class, a specialized SQLAlchemy Query subclass."""
# pylint: disable=self-cls-assignment
from typing import Any, Iterator, TypeVar

View File

@@ -93,6 +93,7 @@ class PaginatedQuery(ModelQuery):
def _apply_before_or_after(self) -> "PaginatedQuery":
"""Apply the "before" or "after" restrictions if necessary."""
# pylint: disable=assignment-from-no-return
if not (self.after_id or self.before_id):
return self

View File

@@ -209,6 +209,7 @@ class Topic(DatabaseModel):
def __acl__(self) -> Sequence[Tuple[str, Any, str]]:
"""Pyramid security ACL."""
# pylint: disable=too-many-branches
acl = []
# deleted topics allow "general" viewing, but nothing else

View File

@@ -52,6 +52,7 @@ class TopicQuery(PaginatedQuery):
def _attach_visit_data(self) -> "TopicQuery":
"""Join the data related to the user's last visit to the topic(s)."""
# pylint: disable=assignment-from-no-return
if self.request.user.track_comment_visits:
query = self.outerjoin(
TopicVisit,

View File

@@ -20,6 +20,7 @@ class Enum(Field):
self, enum_class: Optional[Type] = None, *args: Any, **kwargs: Any
) -> None:
"""Initialize the field with an optional enum class."""
# pylint: disable=keyword-arg-before-vararg
super().__init__(*args, **kwargs)
self._enum_class = enum_class

View File

@@ -28,6 +28,7 @@ def _422_response_with_errors(errors: Sequence[str]) -> Response:
@ic_view_config(context=ValidationError)
def unprocessable_entity(request: Request) -> Response:
"""Exception view for 422 errors."""
# pylint: disable=too-many-branches
if isinstance(request.exception, ValidationError):
validation_error = request.exception
else: