Skip to content

Commit 3dc7093

Browse files
author
Jaap Roes
committed
Spilt settings in dataclass and Django settings proxy
1 parent fe75e30 commit 3dc7093

File tree

2 files changed

+44
-59
lines changed

2 files changed

+44
-59
lines changed

src/corsheaders/conf.py

Lines changed: 39 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,77 +1,57 @@
11
from __future__ import annotations
22

3-
from typing import cast
4-
from typing import List
3+
import re
4+
from dataclasses import dataclass
5+
from typing import Any
56
from typing import Pattern
67
from typing import Sequence
7-
from typing import Tuple
8-
from typing import Union
98

10-
from django.conf import settings
9+
from django.conf import settings as _django_settings
1110

1211
from corsheaders.defaults import default_headers
1312
from corsheaders.defaults import default_methods
1413

1514
# Kept here for backwards compatibility
1615

1716

17+
@dataclass
1818
class Settings:
19+
CORS_ALLOW_HEADERS: Sequence[str] = default_headers
20+
CORS_ALLOW_METHODS: Sequence[str] = default_methods
21+
CORS_ALLOW_CREDENTIALS: bool = False
22+
CORS_ALLOW_PRIVATE_NETWORK: bool = False
23+
CORS_PREFLIGHT_MAX_AGE: int = 86400
24+
CORS_ALLOW_ALL_ORIGINS: bool = False
25+
CORS_ALLOWED_ORIGINS: list[str] | tuple[str] = () # type: ignore
26+
CORS_ALLOWED_ORIGIN_REGEXES: Sequence[str | Pattern[str]] = ()
27+
CORS_EXPOSE_HEADERS: Sequence[str] = ()
28+
CORS_URLS_REGEX: str | Pattern[str] = re.compile(r"^.*$")
29+
30+
31+
_RENAMED_SETTINGS = {
32+
# New name -> Old name
33+
"CORS_ALLOW_ALL_ORIGINS": "CORS_ORIGIN_ALLOW_ALL",
34+
"CORS_ALLOWED_ORIGINS": "CORS_ORIGIN_WHITELIST",
35+
"CORS_ALLOWED_ORIGIN_REGEXES": "CORS_ORIGIN_REGEX_WHITELIST",
36+
}
37+
38+
39+
class DjangoConfig(Settings):
1940
"""
20-
Shadow Django's settings with a little logic
21-
"""
22-
23-
@property
24-
def CORS_ALLOW_HEADERS(self) -> Sequence[str]:
25-
return getattr(settings, "CORS_ALLOW_HEADERS", default_headers)
26-
27-
@property
28-
def CORS_ALLOW_METHODS(self) -> Sequence[str]:
29-
return getattr(settings, "CORS_ALLOW_METHODS", default_methods)
30-
31-
@property
32-
def CORS_ALLOW_CREDENTIALS(self) -> bool:
33-
return getattr(settings, "CORS_ALLOW_CREDENTIALS", False)
34-
35-
@property
36-
def CORS_ALLOW_PRIVATE_NETWORK(self) -> bool:
37-
return getattr(settings, "CORS_ALLOW_PRIVATE_NETWORK", False)
41+
A version of Settings that prefers to read from Django's settings.
3842
39-
@property
40-
def CORS_PREFLIGHT_MAX_AGE(self) -> int:
41-
return getattr(settings, "CORS_PREFLIGHT_MAX_AGE", 86400)
42-
43-
@property
44-
def CORS_ALLOW_ALL_ORIGINS(self) -> bool:
45-
return getattr(
46-
settings,
47-
"CORS_ALLOW_ALL_ORIGINS",
48-
getattr(settings, "CORS_ORIGIN_ALLOW_ALL", False),
49-
)
50-
51-
@property
52-
def CORS_ALLOWED_ORIGINS(self) -> list[str] | tuple[str]:
53-
value = getattr(
54-
settings,
55-
"CORS_ALLOWED_ORIGINS",
56-
getattr(settings, "CORS_ORIGIN_WHITELIST", ()),
57-
)
58-
return cast(Union[List[str], Tuple[str]], value)
59-
60-
@property
61-
def CORS_ALLOWED_ORIGIN_REGEXES(self) -> Sequence[str | Pattern[str]]:
62-
return getattr(
63-
settings,
64-
"CORS_ALLOWED_ORIGIN_REGEXES",
65-
getattr(settings, "CORS_ORIGIN_REGEX_WHITELIST", ()),
66-
)
67-
68-
@property
69-
def CORS_EXPOSE_HEADERS(self) -> Sequence[str]:
70-
return getattr(settings, "CORS_EXPOSE_HEADERS", ())
43+
Falls back to its own values if the setting is not configured
44+
in Django.
45+
"""
7146

72-
@property
73-
def CORS_URLS_REGEX(self) -> str | Pattern[str]:
74-
return getattr(settings, "CORS_URLS_REGEX", r"^.*$")
47+
def __getattribute__(self, name: str) -> Any:
48+
default = object.__getattribute__(self, name)
49+
if name in _RENAMED_SETTINGS:
50+
# Renamed settings are used if the new setting
51+
# is not configured in Django,
52+
old_name = _RENAMED_SETTINGS[name]
53+
default = getattr(_django_settings, old_name, default)
54+
return getattr(_django_settings, name, default)
7555

7656

77-
conf = Settings()
57+
conf = DjangoConfig()

tests/test_conf.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@
77

88

99
class ConfTests(SimpleTestCase):
10+
@override_settings(SECRET_KEY="foo")
11+
def test_other_setting(self):
12+
# Only proxy settings that are defined in the Settings class.
13+
self.assertRaises(AttributeError, getattr, conf, "SECRET_KEY")
14+
1015
@override_settings(CORS_ALLOW_HEADERS=["foo"])
1116
def test_can_override(self):
1217
assert conf.CORS_ALLOW_HEADERS == ["foo"]

0 commit comments

Comments
 (0)