Skip to content

Commit 03f3b2c

Browse files
Move the speed.pypy.org only views into speed_pypy/
1 parent 14f0215 commit 03f3b2c

6 files changed

Lines changed: 92 additions & 21 deletions

File tree

‎codespeed/urls.py‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
]
1515

1616
urlpatterns += [
17-
re_path(r'^embed/comparison/$', views.embed_comparison, name='embed-comparison'),
1817
re_path(r'^historical/json/$', views.gethistoricaldata, name='gethistoricaldata'),
1918
re_path(r'^reports/$', views.reports, name='reports'),
2019
re_path(r'^changes/$', views.changes, name='changes'),

‎codespeed/views.py‎

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
from django.views.decorators.cache import cache_page
1818
from django.views.decorators.http import require_GET, require_POST
1919
from django.views.decorators.csrf import csrf_exempt
20-
from django.views.decorators.clickjacking import xframe_options_exempt
2120
from django.views.generic.base import TemplateView
2221

2322
from .auth import basic_auth_required
@@ -100,24 +99,6 @@ def get_context_data(self, **kwargs):
10099
return context
101100

102101

103-
@require_GET
104-
@xframe_options_exempt
105-
def embed_comparison(request):
106-
"""Frame-exempt page rendering only the baseline-comparison
107-
for embedding on pypy.org"""
108-
context = {}
109-
try:
110-
context['baseline'] = Executable.objects.get(
111-
name=settings.DEF_BASELINES[0]['executable'])
112-
def_name = settings.DEF_EXECUTABLES[0]['name']
113-
def_project = Project.objects.get(name=settings.DEF_EXECUTABLES[0]['project'])
114-
context['default_exe'] = Executable.objects.get(
115-
name=def_name, project=def_project)
116-
except Exception as e:
117-
logger.error('embed_comparison: %s', e)
118-
return render(request, 'embed_comparison.html', context)
119-
120-
121102
# The historical comparison only changes when new results are saved, which
122103
# happens at most a few times a day, yet computing it costs ~2s of database
123104
# time per request. Cache the rendered JSON server-side and let browsers

‎speed_pypy/tests.py‎

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
"""Tests for the speed.pypy.org specific views.
2+
3+
Run with: python manage.py test codespeed speed_pypy --settings=codespeed.tests.settings
4+
"""
5+
import os
6+
7+
from django.contrib.auth.models import User
8+
from django.test import TestCase, override_settings
9+
from django.urls import reverse
10+
11+
from codespeed.models import Executable, Project
12+
13+
SITE_DIR = os.path.dirname(os.path.abspath(__file__))
14+
# The test settings are site independent; render this site's templates instead.
15+
SITE_TEMPLATES = [{
16+
'BACKEND': 'django.template.backends.django.DjangoTemplates',
17+
'DIRS': [os.path.join(SITE_DIR, 'templates')],
18+
'APP_DIRS': True,
19+
'OPTIONS': {'context_processors': [
20+
'django.template.context_processors.request',
21+
'django.contrib.auth.context_processors.auth',
22+
'django.contrib.messages.context_processors.messages',
23+
]},
24+
}]
25+
26+
27+
@override_settings(
28+
ROOT_URLCONF='speed_pypy.urls',
29+
TEMPLATES=SITE_TEMPLATES,
30+
DEF_BASELINES=[{'executable': 'cpython', 'revision': '3.12.4'}],
31+
DEF_EXECUTABLES=[{'name': 'pypy3.11-jit-64', 'project': 'PyPy3.11'}])
32+
class TestEmbedComparison(TestCase):
33+
34+
def setUp(self):
35+
cpython = Project.objects.create(name='CPython', default_branch='main')
36+
pypy = Project.objects.create(name='PyPy3.11', default_branch='main')
37+
Executable.objects.create(name='cpython', project=cpython)
38+
Executable.objects.create(name='pypy3.11-jit-64', project=pypy)
39+
40+
def test_renders_frame_exempt(self):
41+
response = self.client.get(reverse('embed-comparison'))
42+
self.assertEqual(response.status_code, 200)
43+
# Served inside an iframe on pypy.org, so clickjacking protection is off
44+
self.assertNotIn('X-Frame-Options', response)
45+
self.assertEqual(response.context['default_exe'].name, 'pypy3.11-jit-64')
46+
47+
48+
@override_settings(ROOT_URLCONF='speed_pypy.urls', TEMPLATES=SITE_TEMPLATES)
49+
class TestDownloadDb(TestCase):
50+
51+
def test_requires_staff(self):
52+
response = self.client.get(reverse('admin-download-db'))
53+
self.assertEqual(response.status_code, 302)
54+
self.assertIn('/admin/login/', response['Location'])
55+
56+
def test_staff_gets_sqlite_file(self):
57+
User.objects.create_user('admin', 'a@example.com', 'pw', is_staff=True)
58+
self.client.login(username='admin', password='pw')
59+
response = self.client.get(reverse('admin-download-db'))
60+
self.assertEqual(response.status_code, 200)
61+
self.assertIn('attachment', response['Content-Disposition'])

‎speed_pypy/urls.py‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@
44
from django.urls import include, re_path
55
from django.contrib import admin
66

7-
from codespeed import admin_views
7+
from . import admin_views, views
88

99
urlpatterns = [
1010
re_path(r'^admin/download-db/$', admin_views.download_db, name='admin-download-db'),
1111
re_path(r'^admin/', admin.site.urls),
12+
re_path(r'^embed/comparison/$', views.embed_comparison, name='embed-comparison'),
1213
re_path(r'^', include('codespeed.urls'))
1314
]
1415

‎speed_pypy/views.py‎

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
"""Views specific to speed.pypy.org."""
2+
import logging
3+
4+
from django.conf import settings
5+
from django.shortcuts import render
6+
from django.views.decorators.clickjacking import xframe_options_exempt
7+
from django.views.decorators.http import require_GET
8+
9+
from codespeed.models import Executable, Project
10+
11+
logger = logging.getLogger(__name__)
12+
13+
14+
@require_GET
15+
@xframe_options_exempt
16+
def embed_comparison(request):
17+
"""Frame-exempt page rendering only the baseline-comparison
18+
for embedding on pypy.org"""
19+
context = {}
20+
try:
21+
context['baseline'] = Executable.objects.get(
22+
name=settings.DEF_BASELINES[0]['executable'])
23+
def_name = settings.DEF_EXECUTABLES[0]['name']
24+
def_project = Project.objects.get(name=settings.DEF_EXECUTABLES[0]['project'])
25+
context['default_exe'] = Executable.objects.get(
26+
name=def_name, project=def_project)
27+
except Exception as e:
28+
logger.error('embed_comparison: %s', e)
29+
return render(request, 'embed_comparison.html', context)

0 commit comments

Comments
 (0)