|
1 | 1 | from __future__ import annotations
|
2 | 2 |
|
3 |
| -from typing import cast |
4 |
| -from typing import List |
| 3 | +import re |
| 4 | +from dataclasses import dataclass |
| 5 | +from typing import Any |
5 | 6 | from typing import Pattern
|
6 | 7 | from typing import Sequence
|
7 |
| -from typing import Tuple |
8 |
| -from typing import Union |
9 | 8 |
|
10 |
| -from django.conf import settings |
| 9 | +from django.conf import settings as _django_settings |
11 | 10 |
|
12 | 11 | from corsheaders.defaults import default_headers
|
13 | 12 | from corsheaders.defaults import default_methods
|
14 | 13 |
|
15 | 14 | # Kept here for backwards compatibility
|
16 | 15 |
|
17 | 16 |
|
| 17 | +@dataclass |
18 | 18 | 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): |
19 | 40 | """
|
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. |
38 | 42 |
|
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 | + """ |
71 | 46 |
|
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) |
75 | 55 |
|
76 | 56 |
|
77 |
| -conf = Settings() |
| 57 | +conf = DjangoConfig() |
0 commit comments