• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

DemocracyClub / WhoCanIVoteFor / bdb34524-03ac-44a5-bbe5-9a049cd6b7b4

17 Feb 2025 05:02PM UTC coverage: 58.297% (-0.009%) from 58.306%
bdb34524-03ac-44a5-bbe5-9a049cd6b7b4

Pull #2169

circleci

symroe
Fixup from comments (to be cleaned up)
Pull Request #2169: Move to uv

2793 of 4791 relevant lines covered (58.3%)

0.58 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

80.7
/wcivf/settings/base.py
1
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
2
import contextlib
1✔
3
import os
1✔
4
import sys
1✔
5

6
import dc_design_system
1✔
7
import requests
1✔
8
from dc_logging_client import DCWidePostcodeLoggingClient
1✔
9
from dc_utils.settings.pipeline import *  # noqa
1✔
10
from dc_utils.settings.pipeline import get_pipeline_settings
1✔
11
from dc_utils.settings.whitenoise import whitenoise_add_middleware
1✔
12

13
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
1✔
14

15

16
def here(*x):
1✔
17
    return os.path.join(os.path.abspath(os.path.dirname(__file__)), *x)
1✔
18

19

20
PROJECT_ROOT = here("..")
1✔
21

22

23
def root(*x):
1✔
24
    return os.path.join(os.path.abspath(PROJECT_ROOT), *x)
1✔
25

26

27
def repo_root(*x):
1✔
28
    return os.path.join(os.path.abspath(here("../..")), *x)
1✔
29

30

31
# Add apps to the PYTHON PATH
32
sys.path.insert(0, root("apps"))
1✔
33

34
# Quick-start development settings - unsuitable for production
35
# See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/
36

37
# SECURITY WARNING: keep the secret key used in production secret!
38
SECRET_KEY = os.environ.get("SECRET_KEY")
1✔
39
ADMINS = (("WCIVF Developers", "developers@democracyclub.org.uk"),)
1✔
40
MANAGERS = ADMINS
1✔
41

42
# SECURITY WARNING: don't run with debug turned on in production!
43
DEBUG = False
1✔
44

45

46
def get_ec2_ip():
1✔
47
    token_req = requests.put(
×
48
        "http://169.254.169.254/latest/api/token",
49
        headers={"X-aws-ec2-metadata-token-ttl-seconds": "21600"},
50
        timeout=2,
51
    )
52
    token_req.raise_for_status()
×
53
    token_req.text
×
54
    ip_req = requests.get(
×
55
        "http://169.254.169.254/latest/meta-data/local-ipv4",
56
        headers={"X-aws-ec2-metadata-token": token_req.text},
57
        timeout=2,
58
    )
59
    ip_req.raise_for_status()
×
60
    return ip_req.text
×
61

62

63
# Hosts/domain names that are valid for this site; required if DEBUG is False
64
# See https://docs.djangoproject.com/en/1.5/ref/settings/#allowed-hosts
65
ALLOWED_HOSTS = [
1✔
66
    "localhost",
67
    "127.0.0.1",
68
]
69

70
if os.environ.get("DC_ENVIRONMENT") and os.environ.get("FQDN"):
1✔
71
    ALLOWED_HOSTS.append(os.environ.get("FQDN"))
×
72
    ALLOWED_HOSTS.append(get_ec2_ip())
×
73

74

75
CSRF_TRUSTED_ORIGINS = [
1✔
76
    f"https://{os.environ.get('FQDN')}",
77
]
78

79
SECURE_PROXY_SSL_HEADER = ("HTTP_CLOUDFRONT_FORWARDED_PROTO", "https")
1✔
80

81
SITE_ID = 1
1✔
82

83
# Application definition
84

85
INSTALLED_APPS = (
1✔
86
    "django.contrib.admin",
87
    "django.contrib.auth",
88
    "django.contrib.contenttypes",
89
    "django.contrib.sessions",
90
    "django.contrib.humanize",
91
    "django.contrib.messages",
92
    "django.contrib.staticfiles",
93
    "django.contrib.sitemaps",
94
    "django.contrib.sites",
95
    "django_filters",
96
    "dc_utils",
97
    "pipeline",
98
    "elections",
99
    "core",
100
    "people",
101
    "parties",
102
    "profiles",
103
    "feedback",
104
    "hustings",
105
    "peoplecvs",
106
    "leaflets",
107
    "django_extensions",
108
    "rest_framework",
109
    "api",
110
    "pledges",
111
    "news_mentions",
112
    "dc_design_system",
113
    "referendums",
114
    "parishes",
115
    "ppc_2024",
116
    "administrations",
117
)
118

119
MIDDLEWARE = (
1✔
120
    "django.contrib.sessions.middleware.SessionMiddleware",
121
    "django.middleware.common.CommonMiddleware",
122
    "django.middleware.csrf.CsrfViewMiddleware",
123
    "django.middleware.locale.LocaleMiddleware",
124
    "django.contrib.auth.middleware.AuthenticationMiddleware",
125
    "django.contrib.messages.middleware.MessageMiddleware",
126
    "django.middleware.clickjacking.XFrameOptionsMiddleware",
127
    "django.middleware.security.SecurityMiddleware",
128
    "core.middleware.UTMTrackerMiddleware",
129
    "dc_utils.middleware.BasicAuthMiddleware",
130
)
131

132
MIDDLEWARE = whitenoise_add_middleware(MIDDLEWARE)
1✔
133

134
# When defining a model, if no field in a model is defined with primary_key=True
135
# an implicit primary key is added. The type of this implicit primary key can
136
# now be controlled via the DEFAULT_AUTO_FIELD setting and AppConfig.default_auto_field
137
# attribute. No more needing to override primary keys in all models.
138
DEFAULT_AUTO_FIELD = "django.db.models.AutoField"
1✔
139

140
ROOT_URLCONF = "wcivf.urls"
1✔
141

142
TEMPLATES = [
1✔
143
    {
144
        "BACKEND": "django.template.backends.django.DjangoTemplates",
145
        "DIRS": [root("templates")],
146
        "APP_DIRS": True,
147
        "OPTIONS": {
148
            "context_processors": [
149
                "django.template.context_processors.debug",
150
                "django.template.context_processors.request",
151
                "django.template.context_processors.i18n",
152
                "django.contrib.auth.context_processors.auth",
153
                "django.contrib.messages.context_processors.messages",
154
                "core.context_processors.use_compress_css",
155
                "core.context_processors.postcode_form",
156
                "core.context_processors.referer_postcode",
157
                "core.context_processors.use_i18n",
158
                "hustings.context_processors.show_hustings_cta",
159
                "feedback.context_processors.feedback_form",
160
                "dc_utils.context_processors.dc_django_utils",
161
            ]
162
        },
163
    }
164
]
165

166
USE_COMPRESSED_CSS = False
1✔
167
MEDIA_ROOT = root("media")
1✔
168
MEDIA_URL = "/media/"
1✔
169

170
WSGI_APPLICATION = "wcivf.wsgi.application"
1✔
171

172
# Database
173
# https://docs.djangoproject.com/en/1.8/ref/settings/#databases
174

175
DATABASES = {
1✔
176
    "default": {
177
        "ENGINE": "django.contrib.gis.db.backends.postgis",
178
        "NAME": "wcivf",
179
        "USER": "",
180
        "PASSWORD": "",
181
    }
182
}
183
DATABASE_ROUTERS = []
1✔
184
if int(os.environ.get("FEEDBACK_DB_ENABLED", "0")):
1✔
185
    DATABASES["feedback"] = {
×
186
        "ENGINE": "django.db.backends.postgresql",
187
        "NAME": os.environ.get("FEEDBACK_DB_NAME", "wcivf_feedback_production"),
188
        "USER": "postgres",
189
        "PASSWORD": os.environ.get("FEEDBACK_DB_PASSWORD"),
190
        "HOST": os.environ.get("FEEDBACK_DB_HOST"),
191
        "PORT": "",
192
    }
193

194
    if os.environ.get("DC_ENVIRONMENT") in ["production"]:
×
195
        DATABASE_ROUTERS.append("core.db_routers.FeedbackRouter")
×
196

197
if not os.environ.get("IGNORE_ROUTERS") and os.environ.get(
1✔
198
    "RDS_DB_NAME", False
199
):
200
    DATABASE_ROUTERS.append("core.db_routers.PrincipalRDSRouter")
×
201
    DATABASES["principal"] = {
×
202
        "ENGINE": "django.db.backends.postgresql",
203
        "NAME": os.environ.get("RDS_DB_NAME"),
204
        "USER": "wcivf",
205
        "PASSWORD": os.environ.get("RDS_DB_PASSWORD"),
206
        "HOST": os.environ.get("RDS_HOST"),
207
        "PORT": "",
208
    }
209

210
# Internationalization
211
# https://docs.djangoproject.com/en/1.8/topics/i18n/
212

213
LANGUAGE_CODE = "en-gb"
1✔
214
LANGUAGES = [
1✔
215
    ("en", "English"),
216
    ("cy", "Welsh"),
217
]
218
LOCALE_PATHS = (repo_root("locale"),)
1✔
219

220
TIME_ZONE = "UTC"
1✔
221

222
USE_I18N = True
1✔
223

224
USE_TZ = True
1✔
225

226
# Homepage feature switches
227
SHOW_GB_ID_MESSAGING = False
1✔
228
SHOW_RESULTS_CHART = False
1✔
229

230
# Static files (CSS, JavaScript, Images)
231
# https://docs.djangoproject.com/en/1.8/howto/static-files/
232

233
STATIC_URL = "/static/"
1✔
234

235
STATICFILES_DIRS = (root("assets"),)
1✔
236
STATIC_ROOT = root("static")
1✔
237

238
PIPELINE = get_pipeline_settings(
1✔
239
    extra_css=["scss/style.scss"],
240
    extra_js=["feedback/js/feedback_form.js"],
241
)
242

243
PIPELINE["SASS_ARGUMENTS"] += (
1✔
244
    " -I " + dc_design_system.DC_SYSTEM_PATH + "/system"
245
)
246

247
CACHES = {
1✔
248
    "default": {
249
        "BACKEND": "django_redis.cache.RedisCache",
250
        "LOCATION": "redis://127.0.0.1:6379/1",
251
        "OPTIONS": {"CLIENT_CLASS": "django_redis.client.DefaultClient"},
252
    }
253
}
254
SESSION_ENGINE = "django.contrib.sessions.backends.signed_cookies"
1✔
255
SESSION_CACHE_ALIAS = "default"
1✔
256

257
YNR_API_KEY = os.environ.get("YNR_API_KEY", None)
1✔
258
YNR_BASE = "https://candidates.democracyclub.org.uk"
1✔
259
YNR_UTM_QUERY_STRING = "utm_source=who&utm_campaign=ynr_cta"
1✔
260
EE_BASE = "https://elections.democracyclub.org.uk"
1✔
261
DEVS_DC_BASE = os.environ.get(
1✔
262
    "DEVS_DC_BASE", "https://developers.democracyclub.org.uk"
263
)
264
DEVS_DC_API_KEY = os.environ.get("DEVS_DC_API_KEY", None)
1✔
265

266
WDIV_BASE = "http://wheredoivote.co.uk"
1✔
267
WDIV_API = "/api/beta"
1✔
268

269
CANONICAL_URL = "https://whocanivotefor.co.uk"
1✔
270
ROBOTS_USE_HOST = False
1✔
271
USE_X_FORWARDED_HOST = True
1✔
272

273
EMAIL_SIGNUP_BACKEND = "event_bridge"
1✔
274
EMAIL_SIGNUP_BACKEND_KWARGS = {
1✔
275
    "source": "WCIVF",
276
    "bus_arn": os.environ.get("EMAIL_SIGNUP_EVENT_BRIDGE_ARN"),
277
}
278

279
# DC Base Theme settings
280
SITE_TITLE = "Who Can I Vote For?"
1✔
281

282
AKISMET_API_KEY = os.environ.get("AKISMET_API_KEY")
1✔
283

284
AKISMET_BLOG_URL = CANONICAL_URL
1✔
285

286
REST_FRAMEWORK = {
1✔
287
    # Use Django's standard `django.contrib.auth` permissions,
288
    # or allow read-only access for unauthenticated users.
289
    "DEFAULT_PERMISSION_CLASSES": ["api.permissions.ReadOnly"],
290
    "DEFAULT_RENDERER_CLASSES": (
291
        "rest_framework.renderers.JSONRenderer",
292
        "rest_framework.renderers.BrowsableAPIRenderer",
293
        "rest_framework_jsonp.renderers.JSONPRenderer",
294
    ),
295
    "TEST_REQUEST_DEFAULT_FORMAT": "json",
296
}
297

298
PARTY_LIST_VOTING_TYPES = ["PR-CL", "AMS"]
1✔
299

300
WDIV_API_KEY = os.environ.get("WDIV_API_KEY")
1✔
301
SLACK_FEEDBACK_WEBHOOK_URL = os.environ.get("SLACK_FEEDBACK_WEBHOOK_URL")  # noqa
1✔
302

303
CHECK_HOST_DIRTY = False
1✔
304
DIRTY_FILE_PATH = "~/server_dirty"
1✔
305

306
if os.environ.get("DC_ENVIRONMENT"):
1✔
307
    CHECK_HOST_DIRTY = True
×
308

309
    import sentry_sdk
×
310
    from sentry_sdk.integrations import aws_lambda, django
×
311
    from sentry_sdk.integrations.logging import ignore_logger
×
312

313
    ignore_logger("django.security.DisallowedHost")
×
314

315
    sentry_sdk.init(
×
316
        dsn=os.environ.get("SENTRY_DSN"),
317
        integrations=[
318
            django.DjangoIntegration(),
319
            aws_lambda.AwsLambdaIntegration(timeout_warning=True),
320
        ],
321
        environment=os.environ.get("DC_ENVIRONMENT"),
322
    )
323

324

325
# DC Logging Client
326
LOGGER_ARN = os.environ.get("LOGGER_ARN", None)
1✔
327
firehose_args = {"function_arn": LOGGER_ARN} if LOGGER_ARN else {"fake": True}
1✔
328
POSTCODE_LOGGER = DCWidePostcodeLoggingClient(**firehose_args)
1✔
329

330
SHOW_HUSTINGS_CTA = False
1✔
331
ENABLE_LAYERS_OF_STATE_FEATURE = os.environ.get(
1✔
332
    "ENABLE_LAYERS_OF_STATE_FEATURE", False
333
)
334

335
BASIC_AUTH_ALLOWLIST = ["/_status_check/"]
1✔
336

337
with contextlib.suppress(ImportError):
1✔
338
    # .local.py overrides all the common settings.
339
    from .local import *  # noqa
1✔
340

341
    if DEBUG:
×
342
        INSTALLED_APPS += ("debug_toolbar",)
×
343
        MIDDLEWARE += ("debug_toolbar.middleware.DebugToolbarMiddleware",)
×
344

345
if os.environ.get("CIRCLECI"):
1✔
346
    with contextlib.suppress(ImportError):
1✔
347
        from .ci import *  # noqa
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc