Skip to content

Commit 727e91c

Browse files
committed
Add ruff rules A,B,C4,EM,ISC,PERF,PGH,RET,RUF,S,SIM,SLF,
1 parent f5fd6fc commit 727e91c

22 files changed

+99
-90
lines changed

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@ repos:
66
- id: trailing-whitespace
77

88
- repo: https://github.com/astral-sh/ruff-pre-commit
9-
rev: v0.8.4
9+
rev: v0.9.7
1010
hooks:
1111
- id: ruff

docs/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040

4141
# General information about the project.
4242
project = 'django-waffle'
43-
copyright = '2012-2018, James Socol'
43+
copyright = '2012-2018, James Socol' # noqa: A001
4444

4545
# The version info for the project you're documenting, acts as replacement for
4646
# |version| and |release|, also used in various other places throughout the

pyproject.toml

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -71,26 +71,38 @@ target-version = "py38"
7171

7272
[tool.ruff.lint]
7373
select = [
74+
"A", # flake8-builtins
7475
"AIR", # Airflow
7576
"ASYNC", # flake8-async
77+
"B", # flake8-bugbear
7678
"BLE", # flake8-blind-except
79+
"C4", # flake8-comprehensions
7780
"C90", # McCabe cyclomatic complexity
7881
"DJ", # flake8-django
7982
"DTZ", # flake8-datetimez
8083
"E", # pycodestyle errors
84+
"EM", # flake8-errmsg
8185
"F", # Pyflakes
8286
"FIX", # flake8-fixme
8387
"FLY", # flynt
8488
"G", # flake8-logging-format
8589
"ICN", # flake8-import-conventions
8690
"INP", # flake8-no-pep420
8791
"INT", # flake8-gettext
92+
"ISC", # flake8-implicit-str-concat
8893
"NPY", # NumPy-specific rules
8994
"PD", # pandas-vet
95+
"PERF", # Perflint
96+
"PGH", # pygrep-hooks
9097
"PIE", # flake8-pie
9198
"PL", # Pylint
9299
"PYI", # flake8-pyi
100+
"RET", # flake8-return
93101
"RSE", # flake8-raise
102+
"RUF", # Ruff-specific rules
103+
"S", # flake8-bandit
104+
"SIM", # flake8-simplify
105+
"SLF", # flake8-self
94106
"SLOT", # flake8-slots
95107
"T10", # flake8-debugger
96108
"T20", # flake8-print
@@ -99,32 +111,20 @@ select = [
99111
"UP", # pyupgrade
100112
"W", # pycodestyle warnings
101113
"YTT", # flake8-2020
102-
# "A", # flake8-builtins
103114
# "ANN", # flake8-annotations
104115
# "ARG", # flake8-unused-arguments
105-
# "B", # flake8-bugbear
106-
# "C4", # flake8-comprehensions
107116
# "COM", # flake8-commas
108-
# "CPY", # flake8-copyright
117+
# "CPY", # flake8-copyright
109118
# "D", # pydocstyle
110-
# "EM", # flake8-errmsg
111119
# "ERA", # eradicate
112120
# "EXE", # flake8-executable
113121
# "FA", # flake8-future-annotations
114122
# "FBT", # flake8-boolean-trap
115123
# "I", # isort
116-
# "ISC", # flake8-implicit-str-concat
117124
# "N", # pep8-naming
118-
# "PERF", # Perflint
119-
# "PGH", # pygrep-hooks
120125
# "PT", # flake8-pytest-style
121126
# "PTH", # flake8-use-pathlib
122127
# "Q", # flake8-quotes
123-
# "RET", # flake8-return
124-
# "RUF", # Ruff-specific rules
125-
# "S", # flake8-bandit
126-
# "SIM", # flake8-simplify
127-
# "SLF", # flake8-self
128128
# "TCH", # flake8-type-checking
129129
# "TRY", # tryceratops
130130
]
@@ -135,14 +135,20 @@ exclude = [
135135
"*/migrations/*",
136136
"docs",
137137
]
138-
ignore = ["F401"]
138+
ignore = [
139+
"F401", # Imported but unused
140+
"ISC002", # Implicit string concatenation may conflict with black and ruff format
141+
"S101", # Use of assert detected
142+
]
139143

140144
[tool.ruff.lint.mccabe]
141145
max-complexity = 23
142146

143147
[tool.ruff.lint.per-file-ignores]
144148
"docs/conf.py" = ["INP001"]
145149
"test_app/models.py" = ["DJ008"] # FIXME
150+
"waffle/admin.py" = ["SLF001"] # FIXME
151+
"waffle/jinja.py" = [ "PGH003" ] # FIXME
146152
"waffle/models.py" = ["DJ012", "PYI019"] # FIXME
147153

148154
[tool.ruff.lint.pylint]

test_app/models.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ def is_active_for_user(self, user):
6060
company_ids = self._get_company_ids()
6161
if user.company_id in company_ids:
6262
return True
63+
return None
64+
return None
6365

6466
def _get_company_ids(self):
6567
cache_key = keyfmt(

test_settings.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
SITE_ID = 1
2121
USE_I18N = False
2222

23-
SECRET_KEY = 'foobar'
23+
SECRET_KEY = 'foobar' # noqa: S105
2424

2525
DATABASES = {
2626
'default': {

waffle/__init__.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,9 @@ def get_waffle_model(setting_name: str) -> (
6262

6363
try:
6464
return django_apps.get_model(flag_model_name)
65-
except ValueError:
66-
raise ImproperlyConfigured(f"WAFFLE_{setting_name} must be of the form 'app_label.model_name'")
67-
except LookupError:
68-
raise ImproperlyConfigured(
69-
f"WAFFLE_{setting_name} refers to model '{flag_model_name}' that has not been installed"
70-
)
65+
except ValueError as ve:
66+
msg = f"WAFFLE_{setting_name} must be of the form 'app_label.model_name'"
67+
raise ImproperlyConfigured(msg) from ve
68+
except LookupError as le:
69+
msg = f"WAFFLE_{setting_name} refers to model '{flag_model_name}' that has not been installed"
70+
raise ImproperlyConfigured(msg) from le

waffle/admin.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from __future__ import annotations
22

3-
from typing import Any
3+
from typing import Any, ClassVar
44

55
from django.contrib import admin
66
from django.contrib.admin.models import LogEntry, CHANGE, DELETION
@@ -84,13 +84,13 @@ def label_and_url_for_value(self, values: Any) -> tuple[str, str]:
8484
.using(self.db) \
8585
.get(**{key: value})
8686
names.append(escape(str(name)))
87-
except self.rel.model.DoesNotExist:
87+
except self.rel.model.DoesNotExist: # noqa: PERF203
8888
names.append('<missing>')
8989
return "(" + ", ".join(names) + ")", ""
9090

9191

9292
class FlagAdmin(BaseAdmin):
93-
actions = [enable_for_all, disable_for_all, delete_individually]
93+
actions: ClassVar = [enable_for_all, disable_for_all, delete_individually]
9494
list_display = ('name', 'note', 'everyone', 'percent', 'superusers',
9595
'staff', 'authenticated', 'languages')
9696
list_filter = ('everyone', 'superusers', 'staff', 'authenticated')
@@ -131,14 +131,14 @@ def disable_switches(ma, request, qs):
131131

132132

133133
class SwitchAdmin(BaseAdmin):
134-
actions = [enable_switches, disable_switches, delete_individually]
134+
actions: ClassVar = [enable_switches, disable_switches, delete_individually]
135135
list_display = ('name', 'active', 'note', 'created', 'modified')
136136
list_filter = ('active',)
137137
ordering = ('-id',)
138138

139139

140140
class SampleAdmin(BaseAdmin):
141-
actions = [delete_individually]
141+
actions: ClassVar = [delete_individually]
142142
list_display = ('name', 'percent', 'note', 'created', 'modified')
143143
ordering = ('-id',)
144144

waffle/apps.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,4 @@ class WaffleConfig(AppConfig):
77
default_auto_field = 'django.db.models.AutoField'
88

99
def ready(self) -> None:
10-
import waffle.signals # noqa: F401
10+
import waffle.signals

waffle/decorators.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,7 @@ def _wrapped_view(request, *args, **kwargs):
2525
response_to_redirect_to = get_response_to_redirect(redirect_to, *args, **kwargs)
2626
if response_to_redirect_to:
2727
return response_to_redirect_to
28-
else:
29-
raise Http404
28+
raise Http404
3029

3130
return view(request, *args, **kwargs)
3231
return _wrapped_view
@@ -48,8 +47,7 @@ def _wrapped_view(request, *args, **kwargs):
4847
response_to_redirect_to = get_response_to_redirect(redirect_to, *args, **kwargs)
4948
if response_to_redirect_to:
5049
return response_to_redirect_to
51-
else:
52-
raise Http404
50+
raise Http404
5351

5452
return view(request, *args, **kwargs)
5553
return _wrapped_view

waffle/management/commands/waffle_flag.py

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -61,14 +61,14 @@ def add_arguments(self, parser: CommandParser) -> None:
6161
parser.add_argument(
6262
'--group', '-g',
6363
action='append',
64-
default=list(),
64+
default=[],
6565
help='Turn on the flag for listed group names (use flag more '
6666
'than once for multiple groups). WARNING: This will remove '
6767
'any currently associated groups unless --append is used!')
6868
parser.add_argument(
6969
'--user', '-u',
7070
action='append',
71-
default=list(),
71+
default=[],
7272
help='Turn on the flag for listed usernames (use flag more '
7373
'than once for multiple users). WARNING: This will remove '
7474
'any currently associated users unless --append is used!')
@@ -111,7 +111,8 @@ def handle(self, *args: Any, **options: Any) -> None:
111111
flag_name = options['name']
112112

113113
if not flag_name:
114-
raise CommandError('You need to specify a flag name.')
114+
msg = 'You need to specify a flag name.'
115+
raise CommandError(msg)
115116

116117
if options['create']:
117118
flag, created = get_waffle_flag_model().objects.get_or_create(name=flag_name)
@@ -120,8 +121,9 @@ def handle(self, *args: Any, **options: Any) -> None:
120121
else:
121122
try:
122123
flag = get_waffle_flag_model().objects.get(name=flag_name)
123-
except get_waffle_flag_model().DoesNotExist:
124-
raise CommandError('This flag does not exist.')
124+
except get_waffle_flag_model().DoesNotExist as dne:
125+
msg = 'This flag does not exist.'
126+
raise CommandError(msg) from dne
125127

126128
# Group isn't an attribute on the Flag, but a related Many-to-Many
127129
# field, so we handle it a bit differently by looking up groups and
@@ -133,8 +135,9 @@ def handle(self, *args: Any, **options: Any) -> None:
133135
try:
134136
group_instance = Group.objects.get(name=group)
135137
group_hash[group_instance.name] = group_instance.id
136-
except Group.DoesNotExist:
137-
raise CommandError(f'Group {group} does not exist')
138+
except Group.DoesNotExist as dne: # noqa: PERF203
139+
msg = f'Group {group} does not exist'
140+
raise CommandError(msg) from dne
138141
# If 'append' was not passed, we clear related groups
139142
if not options_append:
140143
flag.groups.clear()
@@ -152,8 +155,9 @@ def handle(self, *args: Any, **options: Any) -> None:
152155
| Q(**{UserModel.EMAIL_FIELD: username})
153156
)
154157
user_hash.add(user_instance)
155-
except UserModel.DoesNotExist:
156-
raise CommandError(f'User {username} does not exist')
158+
except UserModel.DoesNotExist as dne: # noqa: PERF203
159+
msg = f'User {username} does not exist'
160+
raise CommandError(msg) from dne
157161
# If 'append' was not passed, we clear related users
158162
if not options_append:
159163
flag.users.clear()

waffle/management/commands/waffle_sample.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,16 +41,16 @@ def handle(self, *args: Any, **options: Any) -> None:
4141
percent = options['percent']
4242

4343
if not (sample_name and percent):
44-
raise CommandError(
45-
'You need to specify a sample name and percentage.'
46-
)
44+
msg = 'You need to specify a sample name and percentage.'
45+
raise CommandError(msg)
4746

4847
try:
4948
percent = float(percent)
5049
if not (0.0 <= percent <= 100.0):
5150
raise ValueError
52-
except ValueError:
53-
raise CommandError('You need to enter a valid percentage value.')
51+
except ValueError as ve:
52+
msg = 'You need to enter a valid percentage value.'
53+
raise CommandError(msg) from ve
5454

5555
if options['create']:
5656
sample, created = get_waffle_sample_model().objects.get_or_create(
@@ -60,8 +60,9 @@ def handle(self, *args: Any, **options: Any) -> None:
6060
else:
6161
try:
6262
sample = get_waffle_sample_model().objects.get(name=sample_name)
63-
except get_waffle_sample_model().DoesNotExist:
64-
raise CommandError('This sample does not exist.')
63+
except get_waffle_sample_model().DoesNotExist as dne:
64+
msg = 'This sample does not exist.'
65+
raise CommandError(msg) from dne
6566

6667
sample.percent = percent
6768
sample.save()

waffle/management/commands/waffle_switch.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77

88

99
def on_off_bool(string: str) -> bool:
10-
if string not in ['on', 'off']:
11-
raise ArgumentTypeError(f"invalid choice: {string!r} (choose from 'on', "
12-
"'off')")
10+
if string not in {'on', 'off'}:
11+
msg = f"invalid choice: {string!r} (choose from 'on', 'off')"
12+
raise ArgumentTypeError(msg)
1313
return string == 'on'
1414

1515

@@ -53,7 +53,8 @@ def handle(self, *args: Any, **options: Any) -> None:
5353
state = options['state']
5454

5555
if not (switch_name and state is not None):
56-
raise CommandError('You need to specify a switch name and state.')
56+
msg = 'You need to specify a switch name and state.'
57+
raise CommandError(msg)
5758

5859
if options["create"]:
5960
switch, created = get_waffle_switch_model().objects.get_or_create(
@@ -64,8 +65,9 @@ def handle(self, *args: Any, **options: Any) -> None:
6465
else:
6566
try:
6667
switch = get_waffle_switch_model().objects.get(name=switch_name)
67-
except get_waffle_switch_model().DoesNotExist:
68-
raise CommandError('This switch does not exist.')
68+
except get_waffle_switch_model().DoesNotExist as dne:
69+
msg = 'This switch does not exist.'
70+
raise CommandError(msg) from dne
6971

7072
switch.active = state
7173
switch.save()

waffle/managers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77

88
if TYPE_CHECKING:
9-
from waffle.models import _BaseModelType, AbstractBaseFlag, AbstractBaseSample, AbstractBaseSwitch # noqa: F401
9+
from waffle.models import _BaseModelType, AbstractBaseFlag, AbstractBaseSample, AbstractBaseSwitch
1010
else:
1111
_BaseModelType = TypeVar("_BaseModelType")
1212

waffle/middleware.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,8 @@ def process_response(self, request: HttpRequest, response: HttpResponse) -> Http
1414
for k in request.waffles:
1515
name = smart_str(get_setting('COOKIE') % k)
1616
active, rollout = request.waffles[k]
17-
if rollout and not active:
18-
# "Inactive" is a session cookie during rollout mode.
19-
age = None
20-
else:
21-
age = max_age
17+
# "Inactive" is a session cookie during rollout mode.
18+
age = None if rollout and not active else max_age
2219
response.set_cookie(name, value=active, max_age=age,
2320
secure=secure)
2421
if hasattr(request, 'waffle_tests'):

waffle/mixins.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,12 @@ class BaseWaffleMixin:
1111

1212
def validate_waffle(self, waffle, func):
1313
if waffle.startswith('!'):
14-
active = not func(waffle[1:])
15-
else:
16-
active = func(waffle)
17-
return active
14+
return not func(waffle[1:])
15+
return func(waffle)
1816

1917
def invalid_waffle(self):
20-
raise Http404('Inactive waffle')
18+
msg = 'Inactive waffle'
19+
raise Http404(msg)
2120

2221

2322
class WaffleFlagMixin(BaseWaffleMixin):

0 commit comments

Comments
 (0)