diff options
-rw-r--r-- | patchwork/templates/patchwork/filters.html | 2 | ||||
-rw-r--r-- | patchwork/templates/patchwork/help/pwclient.html | 4 | ||||
-rw-r--r-- | patchwork/templates/patchwork/project.html | 4 | ||||
-rw-r--r-- | patchwork/templatetags/person.py | 8 | ||||
-rw-r--r-- | patchwork/tests/test_confirm.py | 3 | ||||
-rw-r--r-- | patchwork/tests/test_mail_settings.py | 3 | ||||
-rw-r--r-- | patchwork/tests/test_registration.py | 3 | ||||
-rw-r--r-- | patchwork/tests/test_user.py | 3 | ||||
-rw-r--r-- | patchwork/tests/test_xmlrpc.py | 2 | ||||
-rw-r--r-- | patchwork/urls.py | 10 | ||||
-rw-r--r-- | patchwork/views/__init__.py | 39 | ||||
-rw-r--r-- | patchwork/views/api.py | 54 | ||||
-rw-r--r-- | patchwork/views/base.py | 138 | ||||
-rw-r--r-- | patchwork/views/help.py | 43 | ||||
-rw-r--r-- | patchwork/views/project.py | 16 | ||||
-rw-r--r-- | patchwork/views/pwclient.py | 50 | ||||
-rw-r--r-- | patchwork/views/xmlrpc.py | 6 | ||||
-rw-r--r-- | templates/base.html | 6 |
18 files changed, 227 insertions, 167 deletions
diff --git a/patchwork/templates/patchwork/filters.html b/patchwork/templates/patchwork/filters.html index 65fd6bf..acb9375 100644 --- a/patchwork/templates/patchwork/filters.html +++ b/patchwork/templates/patchwork/filters.html @@ -70,7 +70,7 @@ $(document).ready(function() { return callback(); req = $.ajax({ - url: '{% url 'patchwork.views.submitter_complete' %}?q=' + + url: '{% url 'patchwork.views.api.submitters' %}?q=' + encodeURIComponent(query) + '&l=10', error: function() { callback(); diff --git a/patchwork/templates/patchwork/help/pwclient.html b/patchwork/templates/patchwork/help/pwclient.html index 7101ec1..793cf73 100644 --- a/patchwork/templates/patchwork/help/pwclient.html +++ b/patchwork/templates/patchwork/help/pwclient.html @@ -11,13 +11,13 @@ and applying patches.</p> <p>To use pwclient, you will need:</p> <ul> - <li>The <a href="{% url 'patchwork.views.pwclient' %}">pwclient</a> + <li>The <a href="{% url 'patchwork.views.pwclient.pwclient' %}">pwclient</a> program (11kB, python script)</li> <li>(optional) a <code>.pwclientrc</code> file in your home directory.</li> </ul> <p>You can create your own <code>.pwclientrc</code> file. Each -<a href="{% url 'patchwork.views.projects' %}">patchwork project</a> +<a href="{% url 'patchwork.views.project.list' %}">patchwork project</a> provides a sample linked from the 'project info' page.</p> {% endblock %} diff --git a/patchwork/templates/patchwork/project.html b/patchwork/templates/patchwork/project.html index be8cadc..e1cf3f5 100644 --- a/patchwork/templates/patchwork/project.html +++ b/patchwork/templates/patchwork/project.html @@ -49,9 +49,9 @@ </table> {% if settings.ENABLE_XMLRPC %} -<p>Sample <a href="{% url 'patchwork.views.help' "pwclient/" %}">patchwork +<p>Sample <a href="{% url 'patchwork.views.help.help' "pwclient/" %}">patchwork client</a> configuration for this project: <a -href="{% url 'patchwork.views.pwclientrc' project.linkname %}" +href="{% url 'patchwork.views.pwclient.pwclientrc' project.linkname %}" >.pwclientrc</a>.</p> {% endif %} diff --git a/patchwork/templatetags/person.py b/patchwork/templatetags/person.py index 6829019..d35203b 100644 --- a/patchwork/templatetags/person.py +++ b/patchwork/templatetags/person.py @@ -38,9 +38,9 @@ def personify(person, project): else: linktext = escape(person.email) - url = reverse( - 'patchwork.views.patch.list', kwargs={'project_id': project.linkname}) - str = '<a href="%s?%s=%s">%s</a>' % \ - (url, SubmitterFilter.param, escape(person.id), linktext) + url = reverse('patchwork.views.patch.list', + kwargs={'project_id': project.linkname}) + str = '<a href="%s?%s=%s">%s</a>' % ( + url, SubmitterFilter.param, escape(person.id), linktext) return mark_safe(str) diff --git a/patchwork/tests/test_confirm.py b/patchwork/tests/test_confirm.py index 4c14e56..7ef922e 100644 --- a/patchwork/tests/test_confirm.py +++ b/patchwork/tests/test_confirm.py @@ -25,7 +25,8 @@ from patchwork.models import EmailConfirmation, Person def _confirmation_url(conf): - return reverse('patchwork.views.confirm', kwargs={'key': conf.key}) + return reverse('patchwork.views.confirm', + kwargs={'key': conf.key}) class TestUser(object): diff --git a/patchwork/tests/test_mail_settings.py b/patchwork/tests/test_mail_settings.py index b9f1dd9..02205aa 100644 --- a/patchwork/tests/test_mail_settings.py +++ b/patchwork/tests/test_mail_settings.py @@ -188,7 +188,8 @@ class OptinRequestTest(TestCase): self.assertContains(response, self.email) # check email - url = reverse('patchwork.views.confirm', kwargs={'key': conf.key}) + url = reverse('patchwork.views.confirm', + kwargs={'key': conf.key}) self.assertEqual(len(mail.outbox), 1) msg = mail.outbox[0] self.assertEqual(msg.to, [self.email]) diff --git a/patchwork/tests/test_registration.py b/patchwork/tests/test_registration.py index b5eacef..b5f5bb4 100644 --- a/patchwork/tests/test_registration.py +++ b/patchwork/tests/test_registration.py @@ -28,7 +28,8 @@ from patchwork.tests.utils import create_user def _confirmation_url(conf): - return reverse('patchwork.views.confirm', kwargs={'key': conf.key}) + return reverse('patchwork.views.confirm', + kwargs={'key': conf.key}) class TestUser(object): diff --git a/patchwork/tests/test_user.py b/patchwork/tests/test_user.py index e9d1822..3df5ffa 100644 --- a/patchwork/tests/test_user.py +++ b/patchwork/tests/test_user.py @@ -28,7 +28,8 @@ from patchwork.tests.utils import defaults, error_strings def _confirmation_url(conf): - return reverse('patchwork.views.confirm', kwargs={'key': conf.key}) + return reverse('patchwork.views.confirm', + kwargs={'key': conf.key}) class TestUser(object): diff --git a/patchwork/tests/test_xmlrpc.py b/patchwork/tests/test_xmlrpc.py index d8c77f0..d8e1d98 100644 --- a/patchwork/tests/test_xmlrpc.py +++ b/patchwork/tests/test_xmlrpc.py @@ -42,7 +42,7 @@ class XMLRPCTest(LiveServerTestCase): def testGetRedirect(self): response = self.client.patch(self.url) self.assertRedirects(response, - reverse('patchwork.views.help', + reverse('patchwork.views.help.help', kwargs={'path': 'pwclient/'})) def testList(self): diff --git a/patchwork/urls.py b/patchwork/urls.py index 81a571a..5be286a 100644 --- a/patchwork/urls.py +++ b/patchwork/urls.py @@ -29,7 +29,7 @@ urlpatterns = patterns( '', url(r'^admin/', include(admin.site.urls)), - (r'^$', 'patchwork.views.projects'), + (r'^$', 'patchwork.views.project.list'), (r'^project/(?P<project_id>[^/]+)/list/$', 'patchwork.views.patch.list'), (r'^project/(?P<project_id>[^/]+)/$', 'patchwork.views.project.project'), @@ -85,7 +85,7 @@ urlpatterns = patterns( (r'^confirm/(?P<key>[0-9a-f]+)/$', 'patchwork.views.confirm'), # submitter autocomplete - (r'^submitter/$', 'patchwork.views.submitter_complete'), + (r'^submitter/$', 'patchwork.views.api.submitters'), # email setup (r'^mail/$', 'patchwork.views.mail.settings'), @@ -93,16 +93,16 @@ urlpatterns = patterns( (r'^mail/optin/$', 'patchwork.views.mail.optin'), # help! - (r'^help/(?P<path>.*)$', 'patchwork.views.help'), + (r'^help/(?P<path>.*)$', 'patchwork.views.help.help'), ) if settings.ENABLE_XMLRPC: urlpatterns += patterns( '', (r'xmlrpc/$', 'patchwork.views.xmlrpc.xmlrpc'), - (r'^pwclient/$', 'patchwork.views.pwclient'), + (r'^pwclient/$', 'patchwork.views.pwclient.pwclient'), (r'^project/(?P<project_id>[^/]+)/pwclientrc/$', - 'patchwork.views.pwclientrc'), + 'patchwork.views.pwclient.pwclientrc'), ) # redirect from old urls diff --git a/patchwork/views/__init__.py b/patchwork/views/__init__.py index 0a12b41..4cfbc2c 100644 --- a/patchwork/views/__init__.py +++ b/patchwork/views/__init__.py @@ -27,11 +27,14 @@ from email.parser import HeaderParser import email.utils import re -from .base import * # noqa -from patchwork.utils import Order, get_patch_ids, bundle_actions, set_bundle -from patchwork.paginator import Paginator +from django.http import Http404 +from django.shortcuts import render_to_response, get_object_or_404 + from patchwork.forms import MultiplePatchForm -from patchwork.models import Comment, Patch +from patchwork.models import Comment, Patch, EmailConfirmation +from patchwork.paginator import Paginator +from patchwork.requestcontext import PatchworkRequestContext +from patchwork.utils import Order, get_patch_ids, bundle_actions, set_bundle def generic_list(request, project, view, @@ -222,3 +225,31 @@ def patch_to_mbox(patch): mail['Date'] = email.utils.formatdate(utc_timestamp) return mail + + +def confirm(request, key): + import patchwork.views.user + import patchwork.views.mail + + views = { + 'userperson': patchwork.views.user.link_confirm, + 'registration': patchwork.views.user.register_confirm, + 'optout': patchwork.views.mail.optout_confirm, + 'optin': patchwork.views.mail.optin_confirm, + } + + conf = get_object_or_404(EmailConfirmation, key=key) + if conf.type not in views: + raise Http404 + + if conf.active and conf.is_valid(): + return views[conf.type](request, conf) + + context = PatchworkRequestContext(request) + context['conf'] = conf + if not conf.active: + context['error'] = 'inactive' + elif not conf.is_valid(): + context['error'] = 'expired' + + return render_to_response('patchwork/confirm-error.html', context) diff --git a/patchwork/views/api.py b/patchwork/views/api.py new file mode 100644 index 0000000..91f4f3d --- /dev/null +++ b/patchwork/views/api.py @@ -0,0 +1,54 @@ +# Patchwork - automated patch tracking system +# Copyright (C) 2008 Jeremy Kerr <jk@ozlabs.org> +# +# This file is part of the Patchwork package. +# +# Patchwork is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# Patchwork is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Patchwork; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +import json + +from django.db.models import Q +from django.http import HttpResponse + +from patchwork.models import Person + + +def submitters(request): + search = request.GET.get('q', '') + limit = request.GET.get('l', None) + + if len(search) <= 3: + return HttpResponse(content_type="application/json") + + queryset = Person.objects.filter(Q(name__icontains=search) | + Q(email__icontains=search)) + if limit is not None: + try: + limit = int(limit) + except ValueError: + limit = None + + if limit is not None and limit > 0: + queryset = queryset[:limit] + + data = [] + for submitter in queryset: + item = {} + item['pk'] = submitter.id + item['name'] = submitter.name + item['email'] = submitter.email + data.append(item) + + return HttpResponse(json.dumps(data), content_type="application/json") diff --git a/patchwork/views/base.py b/patchwork/views/base.py deleted file mode 100644 index cd9c43f..0000000 --- a/patchwork/views/base.py +++ /dev/null @@ -1,138 +0,0 @@ -# Patchwork - automated patch tracking system -# Copyright (C) 2008 Jeremy Kerr <jk@ozlabs.org> -# -# This file is part of the Patchwork package. -# -# Patchwork is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Patchwork is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Patchwork; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -from __future__ import absolute_import - -import json - -from django.conf import settings -from django.core import urlresolvers -from django.db.models import Q -from django.http import HttpResponse, HttpResponseRedirect, Http404 -from django.shortcuts import render_to_response, get_object_or_404 -from django.template.loader import render_to_string - -from patchwork.models import Project, Person, EmailConfirmation -from patchwork.requestcontext import PatchworkRequestContext - - -def projects(request): - context = PatchworkRequestContext(request) - projects = Project.objects.all() - - if projects.count() == 1: - return HttpResponseRedirect( - urlresolvers.reverse('patchwork.views.patch.list', - kwargs={'project_id': projects[0].linkname})) - - context['projects'] = projects - return render_to_response('patchwork/projects.html', context) - - -def pwclientrc(request, project_id): - project = get_object_or_404(Project, linkname=project_id) - context = PatchworkRequestContext(request) - context.project = project - if settings.FORCE_HTTPS_LINKS or request.is_secure(): - context['scheme'] = 'https' - else: - context['scheme'] = 'http' - response = HttpResponse(content_type="text/plain") - response['Content-Disposition'] = 'attachment; filename=.pwclientrc' - response.write(render_to_string('patchwork/pwclientrc', context)) - return response - - -def pwclient(request): - context = PatchworkRequestContext(request) - response = HttpResponse(content_type="text/x-python") - response['Content-Disposition'] = 'attachment; filename=pwclient' - response.write(render_to_string('patchwork/pwclient', context)) - return response - - -def confirm(request, key): - import patchwork.views.user - import patchwork.views.mail - views = { - 'userperson': patchwork.views.user.link_confirm, - 'registration': patchwork.views.user.register_confirm, - 'optout': patchwork.views.mail.optout_confirm, - 'optin': patchwork.views.mail.optin_confirm, - } - - conf = get_object_or_404(EmailConfirmation, key=key) - if conf.type not in views: - raise Http404 - - if conf.active and conf.is_valid(): - return views[conf.type](request, conf) - - context = PatchworkRequestContext(request) - context['conf'] = conf - if not conf.active: - context['error'] = 'inactive' - elif not conf.is_valid(): - context['error'] = 'expired' - - return render_to_response('patchwork/confirm-error.html', context) - - -def submitter_complete(request): - search = request.GET.get('q', '') - limit = request.GET.get('l', None) - - if len(search) <= 3: - return HttpResponse(content_type="application/json") - - queryset = Person.objects.filter(Q(name__icontains=search) | - Q(email__icontains=search)) - if limit is not None: - try: - limit = int(limit) - except ValueError: - limit = None - - if limit is not None and limit > 0: - queryset = queryset[:limit] - - data = [] - for submitter in queryset: - item = {} - item['pk'] = submitter.id - item['name'] = submitter.name - item['email'] = submitter.email - data.append(item) - - return HttpResponse(json.dumps(data), content_type="application/json") - -help_pages = {'': 'index.html', - 'about/': 'about.html', - } - -if settings.ENABLE_XMLRPC: - help_pages['pwclient/'] = 'pwclient.html' - - -def help(request, path): - context = PatchworkRequestContext(request) - if path in help_pages: - return render_to_response( - 'patchwork/help/' + help_pages[path], context) - raise Http404 diff --git a/patchwork/views/help.py b/patchwork/views/help.py new file mode 100644 index 0000000..cf14fe2 --- /dev/null +++ b/patchwork/views/help.py @@ -0,0 +1,43 @@ +# Patchwork - automated patch tracking system +# Copyright (C) 2008 Jeremy Kerr <jk@ozlabs.org> +# +# This file is part of the Patchwork package. +# +# Patchwork is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# Patchwork is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Patchwork; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from __future__ import absolute_import + +from django.conf import settings +from django.http import Http404 +from django.shortcuts import render_to_response + +from patchwork.requestcontext import PatchworkRequestContext + + +help_pages = { + '': 'index.html', + 'about/': 'about.html', +} + +if settings.ENABLE_XMLRPC: + help_pages['pwclient/'] = 'pwclient.html' + + +def help(request, path): + context = PatchworkRequestContext(request) + if path in help_pages: + return render_to_response( + 'patchwork/help/' + help_pages[path], context) + raise Http404 diff --git a/patchwork/views/project.py b/patchwork/views/project.py index 82103d4..e3f3747 100644 --- a/patchwork/views/project.py +++ b/patchwork/views/project.py @@ -20,12 +20,28 @@ from __future__ import absolute_import from django.contrib.auth.models import User +from django.core import urlresolvers +from django.http import HttpResponseRedirect from django.shortcuts import render_to_response, get_object_or_404 from patchwork.models import Patch, Project from patchwork.requestcontext import PatchworkRequestContext +def list(request): + context = PatchworkRequestContext(request) + projects = Project.objects.all() + + if projects.count() == 1: + return HttpResponseRedirect( + urlresolvers.reverse('patchwork.views.patch.list', + kwargs={'project_id': projects[0].linkname})) + + context['projects'] = projects + + return render_to_response('patchwork/projects.html', context) + + def project(request, project_id): context = PatchworkRequestContext(request) project = get_object_or_404(Project, linkname=project_id) diff --git a/patchwork/views/pwclient.py b/patchwork/views/pwclient.py new file mode 100644 index 0000000..b3e0052 --- /dev/null +++ b/patchwork/views/pwclient.py @@ -0,0 +1,50 @@ +# Patchwork - automated patch tracking system +# Copyright (C) 2008 Jeremy Kerr <jk@ozlabs.org> +# +# This file is part of the Patchwork package. +# +# Patchwork is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# Patchwork is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Patchwork; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from __future__ import absolute_import + +from django.conf import settings +from django.http import HttpResponse +from django.shortcuts import get_object_or_404 +from django.template.loader import render_to_string + +from patchwork.models import Project +from patchwork.requestcontext import PatchworkRequestContext + + +def pwclientrc(request, project_id): + project = get_object_or_404(Project, linkname=project_id) + context = PatchworkRequestContext(request) + context.project = project + if settings.FORCE_HTTPS_LINKS or request.is_secure(): + context['scheme'] = 'https' + else: + context['scheme'] = 'http' + response = HttpResponse(content_type="text/plain") + response['Content-Disposition'] = 'attachment; filename=.pwclientrc' + response.write(render_to_string('patchwork/pwclientrc', context)) + return response + + +def pwclient(request): + context = PatchworkRequestContext(request) + response = HttpResponse(content_type="text/x-python") + response['Content-Disposition'] = 'attachment; filename=pwclient' + response.write(render_to_string('patchwork/pwclient', context)) + return response diff --git a/patchwork/views/xmlrpc.py b/patchwork/views/xmlrpc.py index b9514a4..d928400 100644 --- a/patchwork/views/xmlrpc.py +++ b/patchwork/views/xmlrpc.py @@ -30,7 +30,7 @@ except ImportError: from xmlrpc.server import XMLRPCDocGenerator import sys -from django.core import urlresolvers +from django.core.urlresolvers import reverse from django.contrib.auth import authenticate from django.http import ( HttpResponse, HttpResponseRedirect, HttpResponseServerError) @@ -136,8 +136,8 @@ dispatcher = PatchworkXMLRPCDispatcher() @csrf_exempt def xmlrpc(request): if request.method not in ['POST', 'GET']: - return HttpResponseRedirect(urlresolvers.reverse( - 'patchwork.views.help', kwargs={'path': 'pwclient/'})) + return HttpResponseRedirect(reverse('patchwork.views.help.help', + kwargs={'path': 'pwclient/'})) response = HttpResponse() diff --git a/templates/base.html b/templates/base.html index 2e0b487..b6f7056 100644 --- a/templates/base.html +++ b/templates/base.html @@ -34,7 +34,7 @@ <span class="icon-bar"></span> </button> <span class="navbar-brand"><a - href="{% url 'patchwork.views.projects' %}">Patchwork</a> + href="{% url 'patchwork.views.project.list' %}">Patchwork</a> {% block heading %}{% endblock %}</span> </div> <div class="collapse navbar-collapse" id="navbar-collapse"> @@ -72,7 +72,7 @@ {% if project %} <div id="breadcrumb"> <div id="breadcrumb-left"> - <a href="{% url 'patchwork.views.projects' %}">All projects</a> + <a href="{% url 'patchwork.views.project.list' %}">All projects</a> → {% block breadcrumb %} <a href="{% url 'patchwork.views.patch.list' project_id=project.linkname %}" @@ -96,7 +96,7 @@ <div id="footer"> <a href="http://jk.ozlabs.org/projects/patchwork/">patchwork</a> patch tracking system | <a - href="{% url 'patchwork.views.help' path="about/" %}">about patchwork</a> + href="{% url 'patchwork.views.help.help' path="about/" %}">about patchwork</a> </div> </body> </html> |