Do extra code style checks with flake8-bugbear

Flake8 Bugbear checks for some extra things that aren’t code style
errors, but are likely to introduce bugs or unexpected behaviour. A
good example is having mutable default function arguments, which get
shared between every call to the function and therefore mutating a value
in one place can unexpectedly cause it to change in another.

This commit enables all the extra warnings provided by Flake8 Bugbear,
except for:
- the line length one (because we already lint for that separately)
- B903 Data class should either be immutable or use `__slots__` because
  this seems to false-positive on some of our custom exceptions
- B902 Invalid first argument 'cls' used for instance method because
  some SQLAlchemy decorators (eg `declared_attr`) make things that
  aren’t formally class methods take a class not an instance as their
  first argument

It disables:
- _B306: BaseException.message is removed in Python 3_ because I think
  our exceptions have a custom structure that means the `.message`
  attribute is still present

Matches the work done in other repos:
- https://github.com/alphagov/notifications-admin/pull/3172/files
This commit is contained in:
Chris Hill-Scott
2020-12-22 15:46:31 +00:00
parent 7152ac7cba
commit 3b0b96834d
29 changed files with 88 additions and 68 deletions

View File

@@ -23,12 +23,12 @@ def create_secret_code():
return ''.join(map(str, [SystemRandom().randrange(10) for i in range(5)]))
def save_user_attribute(usr, update_dict={}):
db.session.query(User).filter_by(id=usr.id).update(update_dict)
def save_user_attribute(usr, update_dict=None):
db.session.query(User).filter_by(id=usr.id).update(update_dict or {})
db.session.commit()
def save_model_user(user, update_dict={}, password=None, validated_email_access=False):
def save_model_user(user, update_dict=None, password=None, validated_email_access=False):
if password:
user.password = password
user.password_changed_at = datetime.utcnow()
@@ -36,7 +36,7 @@ def save_model_user(user, update_dict={}, password=None, validated_email_access=
user.email_access_validated_at = datetime.utcnow()
if update_dict:
_remove_values_for_keys_if_present(update_dict, ['id', 'password_changed_at'])
db.session.query(User).filter_by(id=user.id).update(update_dict)
db.session.query(User).filter_by(id=user.id).update(update_dict or {})
else:
db.session.add(user)
db.session.commit()

View File

@@ -104,8 +104,9 @@ def __format_message(e):
error_path = e.path.popleft()
# no need to catch IndexError exception explicity as
# error_path is None if e.path has no items
finally:
return error_path
except Exception:
pass
return error_path
def get_error_message(e):
# e.cause is an exception (such as InvalidPhoneError). if it's not present it was a standard jsonschema error

View File

@@ -543,7 +543,7 @@ def get_detailed_services(start_date, end_date, only_active=False, include_from_
include_from_test_key=include_from_test_key,
)
results = []
for service_id, rows in itertools.groupby(stats, lambda x: x.service_id):
for _service_id, rows in itertools.groupby(stats, lambda x: x.service_id):
rows = list(rows)
s = statistics.format_statistics(rows)
results.append({

View File

@@ -34,18 +34,18 @@ class RateLimitError(InvalidRequest):
class BadRequestError(InvalidRequest):
message = "An error occurred"
def __init__(self, fields=[], message=None, status_code=400):
def __init__(self, fields=None, message=None, status_code=400):
self.status_code = status_code
self.fields = fields
self.fields = fields or []
self.message = message if message else self.message
class ValidationError(InvalidRequest):
message = "Your notification has failed validation"
def __init__(self, fields=[], message=None, status_code=400):
def __init__(self, fields=None, message=None, status_code=400):
self.status_code = status_code
self.fields = fields
self.fields = fields or []
self.message = message if message else self.message