Skip to content

Commit 4c12388

Browse files
author
Rob Hudson
committed
Show friendly error if decorator usage wasn't updated
1 parent 3040252 commit 4c12388

File tree

2 files changed

+70
-3
lines changed

2 files changed

+70
-3
lines changed

csp/decorators.py

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@
22

33

44
def csp_exempt(REPORT_ONLY=None):
5+
if callable(REPORT_ONLY):
6+
raise RuntimeError(
7+
"Incompatible `csp_exempt` decorator usage. This decorator now requires arguments, "
8+
"even if none are passed. Change bare decorator usage (@csp_exempt) to parameterized "
9+
"decorator usage (@csp_exempt()). See the django-csp 4.0 migration guide for more "
10+
"information."
11+
)
12+
513
def decorator(f):
614
@wraps(f)
715
def _wrapped(*a, **kw):
@@ -17,7 +25,17 @@ def _wrapped(*a, **kw):
1725
return decorator
1826

1927

20-
def csp_update(config, *, REPORT_ONLY=False):
28+
# Error message for deprecated decorator arguments.
29+
DECORATOR_DEPRECATION_ERROR = (
30+
"Incompatible `{fname}` decorator arguments. This decorator now takes a single dict argument. "
31+
"See the django-csp 4.0 migration guide for more information."
32+
)
33+
34+
35+
def csp_update(config=None, REPORT_ONLY=False, **kwargs):
36+
if config is None and kwargs:
37+
raise RuntimeError(DECORATOR_DEPRECATION_ERROR.format(fname="csp_update"))
38+
2139
def decorator(f):
2240
@wraps(f)
2341
def _wrapped(*a, **kw):
@@ -33,7 +51,10 @@ def _wrapped(*a, **kw):
3351
return decorator
3452

3553

36-
def csp_replace(config, *, REPORT_ONLY=False):
54+
def csp_replace(config=None, REPORT_ONLY=False, **kwargs):
55+
if config is None and kwargs:
56+
raise RuntimeError(DECORATOR_DEPRECATION_ERROR.format(fname="csp_replace"))
57+
3758
def decorator(f):
3859
@wraps(f)
3960
def _wrapped(*a, **kw):
@@ -49,7 +70,10 @@ def _wrapped(*a, **kw):
4970
return decorator
5071

5172

52-
def csp(config, *, REPORT_ONLY=False):
73+
def csp(config=None, REPORT_ONLY=False, **kwargs):
74+
if config is None and kwargs:
75+
raise RuntimeError(DECORATOR_DEPRECATION_ERROR.format(fname="csp"))
76+
5377
config = {k: [v] if isinstance(v, str) else v for k, v in config.items()}
5478

5579
def decorator(f):

csp/tests/test_decorators.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,3 +253,46 @@ def view_with_decorator(request):
253253
mw.process_response(request, response)
254254
policy_list = sorted(response[HEADER].split("; "))
255255
assert policy_list == ["font-src bar.com", "img-src foo.com"]
256+
257+
258+
# Deprecation tests
259+
260+
261+
def test_csp_exempt_error():
262+
with pytest.raises(RuntimeError) as excinfo:
263+
264+
@csp_exempt
265+
def view(request):
266+
return HttpResponse()
267+
268+
assert "Incompatible `csp_exempt` decorator usage" in str(excinfo.value)
269+
270+
271+
def test_csp_update_error():
272+
with pytest.raises(RuntimeError) as excinfo:
273+
274+
@csp_update(IMG_SRC="bar.com")
275+
def view(request):
276+
return HttpResponse()
277+
278+
assert "Incompatible `csp_update` decorator arguments" in str(excinfo.value)
279+
280+
281+
def test_csp_replace_error():
282+
with pytest.raises(RuntimeError) as excinfo:
283+
284+
@csp_replace(IMG_SRC="bar.com")
285+
def view(request):
286+
return HttpResponse()
287+
288+
assert "Incompatible `csp_replace` decorator arguments" in str(excinfo.value)
289+
290+
291+
def test_csp_error():
292+
with pytest.raises(RuntimeError) as excinfo:
293+
294+
@csp(IMG_SRC=["bar.com"])
295+
def view(request):
296+
return HttpResponse()
297+
298+
assert "Incompatible `csp` decorator arguments" in str(excinfo.value)

0 commit comments

Comments
 (0)