Re: [PATCH v2 2/2] docs: Note new requirement to include a SPDX line

2018-09-17 Thread Stephen Finucane
On Mon, 2018-09-17 at 13:34 -0400, Veronika Kabatova wrote:
> 
> - Original Message -
> > From: "Stephen Finucane" 
> > To: patchwork@lists.ozlabs.org
> > Sent: Monday, September 17, 2018 7:19:45 PM
> > Subject: Re: [PATCH v2 2/2] docs: Note new requirement to include a SPDX 
> > line
> > 
> > On Mon, 2018-09-17 at 18:17 +0100, Stephen Finucane wrote:
> > > Add some wording around the requirement to include this line instead
> > > of
> > > the license header. Also note the requirement that all code be
> > > GPLv2-licensed and add a CONTRIBUTING document, which GitHub likes.
> > > 
> > > Signed-off-by: Stephen Finucane 
> > > Cc: Daniel Axtens 
> > 
> > Looks like patch 1/2 (or the earlier v1 rendition) didn't make it to
> > the list. It's basically the following diff for all files:
> > 
> >-# 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
> >+# SPDX-License-Identifier: GPL-2.0
> > 
> 
> This seems to be the same problem why my first tagging patch didn't make it
> to the list - the email is too large and doesn't fit the mailing list
> thresholds. Given how many files contain the preamble, the patch would need
> to be split a lot to get it to the list.

Yup, that's what I'm thinking. It's trivial though so unless anyone
else wants to review this though, I'll just wait for Daniel to take a
look and then merge it.

Stephen

> Veronika
> 
> > Stephen
> > 
> > ___
> > Patchwork mailing list
> > Patchwork@lists.ozlabs.org
> > https://lists.ozlabs.org/listinfo/patchwork
> > 


___
Patchwork mailing list
Patchwork@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/patchwork


Re: [PATCH v2 2/2] docs: Note new requirement to include a SPDX line

2018-09-17 Thread Veronika Kabatova



- Original Message -
> From: "Stephen Finucane" 
> To: patchwork@lists.ozlabs.org
> Sent: Monday, September 17, 2018 7:19:45 PM
> Subject: Re: [PATCH v2 2/2] docs: Note new requirement to include a SPDX line
> 
> On Mon, 2018-09-17 at 18:17 +0100, Stephen Finucane wrote:
> > Add some wording around the requirement to include this line instead
> > of
> > the license header. Also note the requirement that all code be
> > GPLv2-licensed and add a CONTRIBUTING document, which GitHub likes.
> > 
> > Signed-off-by: Stephen Finucane 
> > Cc: Daniel Axtens 
> 
> Looks like patch 1/2 (or the earlier v1 rendition) didn't make it to
> the list. It's basically the following diff for all files:
> 
>-# 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
>+# SPDX-License-Identifier: GPL-2.0
> 

This seems to be the same problem why my first tagging patch didn't make it
to the list - the email is too large and doesn't fit the mailing list
thresholds. Given how many files contain the preamble, the patch would need
to be split a lot to get it to the list.

Veronika

> Stephen
> 
> ___
> Patchwork mailing list
> Patchwork@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/patchwork
> 
___
Patchwork mailing list
Patchwork@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/patchwork


Re: [PATCH v2 2/2] docs: Note new requirement to include a SPDX line

2018-09-17 Thread Stephen Finucane
On Mon, 2018-09-17 at 18:17 +0100, Stephen Finucane wrote:
> Add some wording around the requirement to include this line instead
> of
> the license header. Also note the requirement that all code be
> GPLv2-licensed and add a CONTRIBUTING document, which GitHub likes.
> 
> Signed-off-by: Stephen Finucane 
> Cc: Daniel Axtens 

Looks like patch 1/2 (or the earlier v1 rendition) didn't make it to
the list. It's basically the following diff for all files:

   -# 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
   +# SPDX-License-Identifier: GPL-2.0

Stephen

___
Patchwork mailing list
Patchwork@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/patchwork


[PATCH v2 2/2] docs: Note new requirement to include a SPDX line

2018-09-17 Thread Stephen Finucane
Add some wording around the requirement to include this line instead of
the license header. Also note the requirement that all code be
GPLv2-licensed and add a CONTRIBUTING document, which GitHub likes.

Signed-off-by: Stephen Finucane 
Cc: Daniel Axtens 
---
 CONTRIBUTING.rst  |  6 ++
 docs/development/contributing.rst | 20 +---
 2 files changed, 23 insertions(+), 3 deletions(-)
 create mode 100644 CONTRIBUTING.rst

diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst
new file mode 100644
index ..131e2dcb
--- /dev/null
+++ b/CONTRIBUTING.rst
@@ -0,0 +1,6 @@
+Contributing
+
+
+For guidelines on contributing, refer to the `contributors documentation`__.
+
+__ https://patchwork.readthedocs.io/en/latest/development/contributing/
diff --git a/docs/development/contributing.rst 
b/docs/development/contributing.rst
index 7e2a72cf..bada3938 100644
--- a/docs/development/contributing.rst
+++ b/docs/development/contributing.rst
@@ -4,13 +4,25 @@ Contributing
 Coding Standards
 
 
-**Follow PEP8**. All code is currently PEP8 compliant and it should stay this
-way.
+**Follow PEP8**. All code is currently `PEP 8`_ compliant and it should stay
+this way.
+
+All code must be GPLv2 licensed and must have a `SPDX License Identifier`_
+stating this. A copyright line should be included on new files and may be added
+for significant changes to existing files.
+
+.. code-block:: python
+
+   # Patchwork - automated patch tracking system
+   # Copyright (C) 2000 Jane Doe 
+   # Copyright (C) 2001 Joe Bloggs 
+   #
+   # SPDX-License-Identifier: GPL-2.0
 
 Changes that fix semantic issues will be generally be happily received, but
 please keep such changes separate from functional changes.
 
-`pep8` targets are provided via tox. Refer to the :ref:`testing` section
+``pep8`` targets are provided via tox. Refer to the :ref:`testing` section
 below for more information on usage of this tool.
 
 .. _testing:
@@ -148,6 +160,8 @@ announcements.
 Further information about the Patchwork mailing list is available can be found 
on
 `lists.ozlabs.org`_.
 
+.. _PEP 8: https://pep8.org/
+.. _SPDX License Identifier: https://spdx.org/using-spdx-license-identifier
 .. _tox: https://tox.readthedocs.io/en/latest/
 .. _reno: https://docs.openstack.org/developer/reno/
 .. _QEMU guidelines: http://wiki.qemu.org/Contribute/SubmitAPatch
-- 
2.17.1

___
Patchwork mailing list
Patchwork@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/patchwork


[PATCH v2 2/4] tagging: add tags and related filters to REST API

2018-09-17 Thread vkabatov
From: Veronika Kabatova 

Signed-off-by: Veronika Kabatova 
---
 patchwork/api/comment.py  | 12 +-
 patchwork/api/cover.py| 14 ++-
 patchwork/api/filters.py  | 42 ++-
 patchwork/api/patch.py| 13 +++---
 patchwork/tests/api/test_patch.py |  3 +-
 .../tagging-rework-9907e9dc3f835566.yaml  | 11 +
 6 files changed, 85 insertions(+), 10 deletions(-)

diff --git a/patchwork/api/comment.py b/patchwork/api/comment.py
index 5a5adb1d..a328e2a8 100644
--- a/patchwork/api/comment.py
+++ b/patchwork/api/comment.py
@@ -26,6 +26,7 @@ from patchwork.api.base import BaseHyperlinkedModelSerializer
 from patchwork.api.base import PatchworkPermission
 from patchwork.api.embedded import PersonSerializer
 from patchwork.models import Comment
+from patchwork.models import SubmissionTag
 
 
 class CommentListSerializer(BaseHyperlinkedModelSerializer):
@@ -34,6 +35,7 @@ class CommentListSerializer(BaseHyperlinkedModelSerializer):
 subject = SerializerMethodField()
 headers = SerializerMethodField()
 submitter = PersonSerializer(read_only=True)
+tags = SerializerMethodField()
 
 def get_web_url(self, instance):
 request = self.context.get('request')
@@ -43,6 +45,13 @@ class CommentListSerializer(BaseHyperlinkedModelSerializer):
 return email.parser.Parser().parsestr(comment.headers,
   True).get('Subject', '')
 
+def get_tags(self, instance):
+tags = {}
+for tag_object in instance.all_tags:
+tags[tag_object.name] = instance.all_tags[tag_object]
+
+return tags
+
 def get_headers(self, comment):
 headers = {}
 
@@ -60,10 +69,11 @@ class CommentListSerializer(BaseHyperlinkedModelSerializer):
 class Meta:
 model = Comment
 fields = ('id', 'web_url', 'msgid', 'date', 'subject', 'submitter',
-  'content', 'headers')
+  'content', 'headers', 'tags')
 read_only_fields = fields
 versioned_fields = {
 '1.1': ('web_url', ),
+'1.2': ('tags', ),
 }
 
 
diff --git a/patchwork/api/cover.py b/patchwork/api/cover.py
index 3a9fc003..191b8418 100644
--- a/patchwork/api/cover.py
+++ b/patchwork/api/cover.py
@@ -30,6 +30,7 @@ from patchwork.api.embedded import PersonSerializer
 from patchwork.api.embedded import ProjectSerializer
 from patchwork.api.embedded import SeriesSerializer
 from patchwork.models import CoverLetter
+from patchwork.models import SubmissionTag
 
 
 class CoverLetterListSerializer(BaseHyperlinkedModelSerializer):
@@ -40,6 +41,7 @@ class 
CoverLetterListSerializer(BaseHyperlinkedModelSerializer):
 mbox = SerializerMethodField()
 series = SeriesSerializer(read_only=True)
 comments = SerializerMethodField()
+tags = SerializerMethodField()
 
 def get_web_url(self, instance):
 request = self.context.get('request')
@@ -53,6 +55,13 @@ class 
CoverLetterListSerializer(BaseHyperlinkedModelSerializer):
 return self.context.get('request').build_absolute_uri(
 reverse('api-cover-comment-list', kwargs={'pk': cover.id}))
 
+def get_tags(self, instance):
+tags = {}
+for tag_object in instance.all_tags:
+tags[tag_object.name] = instance.all_tags[tag_object]
+
+return tags
+
 def to_representation(self, instance):
 # NOTE(stephenfin): This is here to ensure our API looks the same even
 # after we changed the series-patch relationship from M:N to 1:N. It
@@ -65,10 +74,11 @@ class 
CoverLetterListSerializer(BaseHyperlinkedModelSerializer):
 class Meta:
 model = CoverLetter
 fields = ('id', 'url', 'web_url', 'project', 'msgid', 'date', 'name',
-  'submitter', 'mbox', 'series', 'comments')
+  'submitter', 'mbox', 'series', 'comments', 'tags')
 read_only_fields = fields
 versioned_fields = {
 '1.1': ('web_url', 'mbox', 'comments'),
+'1.2': ('tags', ),
 }
 extra_kwargs = {
 'url': {'view_name': 'api-cover-detail'},
@@ -113,6 +123,7 @@ class CoverLetterList(ListAPIView):
 
 def get_queryset(self):
 return CoverLetter.objects.all()\
+.prefetch_related('tags')\
 .select_related('project', 'submitter', 'series')\
 .defer('content', 'headers')
 
@@ -124,4 +135,5 @@ class CoverLetterDetail(RetrieveAPIView):
 
 def get_queryset(self):
 return CoverLetter.objects.all()\
+.prefetch_related('tags')\
 .select_related('project', 'submitter', 'series')
diff --git a/patchwork/api/filters.py b/patchwork/api/filters.py
index ddf527fd..416136e4 100644
--- a/patchwork/api/filters.py
+++ b/patchwork/api/filters.py
@@ -21,6 +21,7 @@ from django.contrib.auth.models import User
 from django.core.exceptions 

[PATCH v2 4/4] tagging: change wording in documentation

2018-09-17 Thread vkabatov
From: Veronika Kabatova 

All submissions can have tags associated with them now and the
documentation text should reflect it.

Signed-off-by: Veronika Kabatova 
---
 docs/usage/overview.rst | 9 +
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/docs/usage/overview.rst b/docs/usage/overview.rst
index e84e13d9..91d710c0 100644
--- a/docs/usage/overview.rst
+++ b/docs/usage/overview.rst
@@ -119,10 +119,11 @@ one delegate can be assigned to a patch.
 Tags
 
 
-Tags are specially formatted metadata appended to the foot the body of a patch
-or a comment on a patch. Patchwork extracts these tags at parse time and
-associates them with the patch. You add extra tags to an email by replying to
-the email. The following tags are available on a standard Patchwork install:
+Tags are specially formatted metadata appended to the foot the body of a patch,
+cover letter or a comment related to them. Patchwork extracts these tags at
+parse time and associates them with the submissions. You add extra tags to an
+email by replying to the email. The following tags are available on a standard
+Patchwork install:
 
 ``Acked-by:``
   For example::
-- 
2.17.1

___
Patchwork mailing list
Patchwork@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/patchwork


[PATCH v2 3/4] tagging: use tag infrastructure to create tags in mboxes

2018-09-17 Thread vkabatov
From: Veronika Kabatova 

Signed-off-by: Veronika Kabatova 
---
 patchwork/models.py   | 12 
 patchwork/tests/test_mboxviews.py | 19 ---
 patchwork/views/utils.py  |  9 ++---
 .../tagging-rework-9907e9dc3f835566.yaml  |  3 +++
 4 files changed, 25 insertions(+), 18 deletions(-)

diff --git a/patchwork/models.py b/patchwork/models.py
index 5caf7641..a7c75e63 100644
--- a/patchwork/models.py
+++ b/patchwork/models.py
@@ -284,18 +284,6 @@ class EmailMixin(models.Model):
 submitter = models.ForeignKey(Person, on_delete=models.CASCADE)
 content = models.TextField(null=True, blank=True)
 
-response_re = re.compile(
-r'^(Tested|Reviewed|Acked|Signed-off|Nacked|Reported)-by:.*$',
-re.M | re.I)
-
-@property
-def patch_responses(self):
-if not self.content:
-return ''
-
-return ''.join([match.group(0) + '\n' for match in
-self.response_re.finditer(self.content)])
-
 def _extract_tags(self, tags):
 found_tags = {}
 if not self.content:
diff --git a/patchwork/tests/test_mboxviews.py 
b/patchwork/tests/test_mboxviews.py
index 9d941bf8..f7be7b0e 100644
--- a/patchwork/tests/test_mboxviews.py
+++ b/patchwork/tests/test_mboxviews.py
@@ -36,9 +36,10 @@ from patchwork.tests.utils import create_user
 
 
 class MboxPatchResponseTest(TestCase):
-
 """Test that the mbox view appends the Acked-by from a patch comment."""
 
+fixtures = ['default_tags']
+
 def setUp(self):
 self.project = create_project()
 self.person = create_person()
@@ -53,7 +54,9 @@ class MboxPatchResponseTest(TestCase):
 submitter=self.person,
 content='comment 2 text\nAcked-by: 2\n')
 response = self.client.get(reverse('patch-mbox', args=[patch.id]))
-self.assertContains(response, 'Acked-by: 1\nAcked-by: 2\n')
+# Can't guarantee the order in which the tags are returned
+self.assertContains(response, 'Acked-by: 1\n')
+self.assertContains(response, 'Acked-by: 2\n')
 
 def test_patch_utf8_nbsp(self):
 patch = create_patch(
@@ -73,6 +76,8 @@ class MboxPatchSplitResponseTest(TestCase):
 """Test that the mbox view appends the Acked-by from a patch comment,
and places it before an '---' update line."""
 
+fixtures = ['default_tags']
+
 def setUp(self):
 project = create_project()
 self.person = create_person()
@@ -88,7 +93,15 @@ class MboxPatchSplitResponseTest(TestCase):
 
 def test_patch_response(self):
 response = self.client.get(reverse('patch-mbox', args=[self.patch.id]))
-self.assertContains(response, 'Acked-by: 1\nAcked-by: 2\n')
+# Can't guarantee the order in which the tags are returned
+self.assertContains(response, 'Acked-by: 1\n')
+self.assertContains(response, 'Acked-by: 2\n')
+# We need to check for 3 Acked-by strings, one comes from the body of
+# the patch and the other two are the tags themselves.
+self.assertRegex(
+response.content.decode(),
+'(?s).*Acked-by: 1\n.*Acked-by.*Acked-by.*---\nupdate.*'
+)
 
 
 class MboxHeaderTest(TestCase):
diff --git a/patchwork/views/utils.py b/patchwork/views/utils.py
index 4644c621..0586265b 100644
--- a/patchwork/views/utils.py
+++ b/patchwork/views/utils.py
@@ -27,11 +27,13 @@ import email.utils
 import re
 
 from django.conf import settings
+from django.db.models import Q
 from django.http import Http404
 from django.utils import six
 
 from patchwork.models import Comment
 from patchwork.models import Patch
+from patchwork.models import SubmissionTag
 
 if settings.ENABLE_REST_API:
 from rest_framework.authtoken.models import Token
@@ -74,9 +76,10 @@ def _submission_to_mbox(submission):
 else:
 postscript = ''
 
-# TODO(stephenfin): Make this use the tags infrastructure
-for comment in Comment.objects.filter(submission=submission):
-body += comment.patch_responses
+for (tagname, value) in SubmissionTag.objects.filter(
+Q(submission=submission) | Q(series=submission.series)
+).values_list('tag__name', 'value').distinct():
+body += '%s: %s\n' % (tagname, value)
 
 if postscript:
 body += '---\n' + postscript + '\n'
diff --git a/releasenotes/notes/tagging-rework-9907e9dc3f835566.yaml 
b/releasenotes/notes/tagging-rework-9907e9dc3f835566.yaml
index fdfd39f0..7fd64184 100644
--- a/releasenotes/notes/tagging-rework-9907e9dc3f835566.yaml
+++ b/releasenotes/notes/tagging-rework-9907e9dc3f835566.yaml
@@ -24,3 +24,6 @@ upgrade:
 the actual tag data will be created by the command, to make the migration  
 itself faster. Please note that this will take a lot of time and based on  
 the size of the data in question, might be useful to run in batches.  
+other:
+  - |
+The tagging feature is now used to 

[PATCH v2 1/4] Rework tagging infrastructure

2018-09-17 Thread vkabatov
From: Veronika Kabatova 

Solve #113 and #57 GitHub issues, keep track of tag origin to be able
to add tags to comments in the API later.

Use relations Tag-Patch and Tag-CoverLetter to avoid duplication of
tags for each patch in series, and use `series` attribute of
SubmissionTag as a notion of a tag which is related to each patch in the
series (because it comes from cover letter or it's comments)

Signed-off-by: Veronika Kabatova 
---
Rebased on top of 'Convert Series-Patch relationship to 1:N' series.

Stephen, I split up the patch to separate out API, mbox and documentation
changes as you suggested; and implemented your comments (simplified the
migration in favor of running the retag comment, moved the tag retrieval from
the API into a property in models.py, added comment and tag prefetching,
increased the API version where needed, added wildcard to API filter and
simplified it and some other minor things). The series-patch cleanup definitely
helped with some cleanup, but let me know if there are other optimizations that
would help with regards to DB performance.
---
 patchwork/management/commands/retag.py|  15 +-
 patchwork/migrations/0034_rework_tagging.py   |  66 +++
 patchwork/models.py   | 175 --
 patchwork/templatetags/patch.py   |   3 +-
 patchwork/tests/test_parser.py|  18 +-
 patchwork/tests/test_tags.py  |  64 +++
 patchwork/views/__init__.py   |   3 -
 .../tagging-rework-9907e9dc3f835566.yaml  |  15 ++
 8 files changed, 202 insertions(+), 157 deletions(-)
 create mode 100644 patchwork/migrations/0034_rework_tagging.py
 create mode 100644 releasenotes/notes/tagging-rework-9907e9dc3f835566.yaml

diff --git a/patchwork/management/commands/retag.py 
b/patchwork/management/commands/retag.py
index 8617ff41..95b2cc1f 100644
--- a/patchwork/management/commands/retag.py
+++ b/patchwork/management/commands/retag.py
@@ -19,15 +19,15 @@
 
 from django.core.management.base import BaseCommand
 
-from patchwork.models import Patch
+from patchwork.models import Submission
 
 
 class Command(BaseCommand):
-help = 'Update the tag (Ack/Review/Test) counts on existing patches'
-args = '[...]'
+help = 'Update tags on existing submissions and associated comments'
+args = '[...]'
 
 def handle(self, *args, **options):
-query = Patch.objects
+query = Submission.objects.prefetch_related('comments')
 
 if args:
 query = query.filter(id__in=args)
@@ -36,8 +36,11 @@ class Command(BaseCommand):
 
 count = query.count()
 
-for i, patch in enumerate(query.iterator()):
-patch.refresh_tag_counts()
+for i, submission in enumerate(query.iterator()):
+submission.refresh_tags()
+for comment in submission.comments.all():
+comment.refresh_tags()
+
 if (i % 10) == 0:
 self.stdout.write('%06d/%06d\r' % (i, count), ending='')
 self.stdout.flush()
diff --git a/patchwork/migrations/0034_rework_tagging.py 
b/patchwork/migrations/0034_rework_tagging.py
new file mode 100644
index ..580a4fd0
--- /dev/null
+++ b/patchwork/migrations/0034_rework_tagging.py
@@ -0,0 +1,66 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+dependencies = [
+('patchwork', '0033_remove_patch_series_model'),
+]
+
+operations = [
+migrations.CreateModel(
+name='SubmissionTag',
+fields=[
+('id', models.AutoField(auto_created=True,
+primary_key=True,
+serialize=False,
+verbose_name='ID')),
+('value', models.CharField(max_length=255)),
+('comment', models.ForeignKey(
+on_delete=django.db.models.deletion.CASCADE,
+to='patchwork.Comment',
+null=True
+)),
+('submission', models.ForeignKey(
+on_delete=django.db.models.deletion.CASCADE,
+to='patchwork.Submission'
+)),
+('tag', models.ForeignKey(
+on_delete=django.db.models.deletion.CASCADE,
+to='patchwork.Tag'
+)),
+('series', models.ForeignKey(
+on_delete=django.db.models.deletion.CASCADE,
+to='patchwork.Series',
+null=True
+)),
+],
+),
+migrations.AlterUniqueTogether(
+name='patchtag',
+unique_together=set([]),
+),
+migrations.RemoveField(model_name='patchtag', name='patch',),
+

[PATCH v2 1/4] Rework tagging infrastructure

2018-09-17 Thread vkabatov
From: Veronika Kabatova 

Solve #113 and #57 GitHub issues, keep track of tag origin to be able
to add tags to comments in the API later.

Use relations Tag-Patch and Tag-CoverLetter to avoid duplication of
tags for each patch in series, and use `series` attribute of
SubmissionTag as a notion of a tag which is related to each patch in the
series (because it comes from cover letter or it's comments)

Signed-off-by: Veronika Kabatova 
---
Rebased on top of 'Convert Series-Patch relationship to 1:N' series.

Stephen, I split up the patch to separate out API, mbox and documentation
changes as you suggested; and implemented your comments (simplified the
migration in favor of running the retag comment, moved the tag retrieval from
the API into a property in models.py, added comment and tag prefetching,
increased the API version where needed, added wildcard to API filter and
simplified it and some other minor things). The series-patch cleanup definitely
helped with some cleanup, but let me know if there are other optimizations that
would help with regards to DB performance.
---
 patchwork/management/commands/retag.py|  15 +-
 patchwork/migrations/0034_rework_tagging.py   |  66 +++
 patchwork/models.py   | 175 --
 patchwork/templatetags/patch.py   |   3 +-
 patchwork/tests/test_parser.py|  18 +-
 patchwork/tests/test_tags.py  |  64 +++
 patchwork/views/__init__.py   |   3 -
 .../tagging-rework-9907e9dc3f835566.yaml  |  15 ++
 8 files changed, 202 insertions(+), 157 deletions(-)
 create mode 100644 patchwork/migrations/0034_rework_tagging.py
 create mode 100644 releasenotes/notes/tagging-rework-9907e9dc3f835566.yaml

diff --git a/patchwork/management/commands/retag.py 
b/patchwork/management/commands/retag.py
index 8617ff41..95b2cc1f 100644
--- a/patchwork/management/commands/retag.py
+++ b/patchwork/management/commands/retag.py
@@ -19,15 +19,15 @@
 
 from django.core.management.base import BaseCommand
 
-from patchwork.models import Patch
+from patchwork.models import Submission
 
 
 class Command(BaseCommand):
-help = 'Update the tag (Ack/Review/Test) counts on existing patches'
-args = '[...]'
+help = 'Update tags on existing submissions and associated comments'
+args = '[...]'
 
 def handle(self, *args, **options):
-query = Patch.objects
+query = Submission.objects.prefetch_related('comments')
 
 if args:
 query = query.filter(id__in=args)
@@ -36,8 +36,11 @@ class Command(BaseCommand):
 
 count = query.count()
 
-for i, patch in enumerate(query.iterator()):
-patch.refresh_tag_counts()
+for i, submission in enumerate(query.iterator()):
+submission.refresh_tags()
+for comment in submission.comments.all():
+comment.refresh_tags()
+
 if (i % 10) == 0:
 self.stdout.write('%06d/%06d\r' % (i, count), ending='')
 self.stdout.flush()
diff --git a/patchwork/migrations/0034_rework_tagging.py 
b/patchwork/migrations/0034_rework_tagging.py
new file mode 100644
index ..580a4fd0
--- /dev/null
+++ b/patchwork/migrations/0034_rework_tagging.py
@@ -0,0 +1,66 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+dependencies = [
+('patchwork', '0033_remove_patch_series_model'),
+]
+
+operations = [
+migrations.CreateModel(
+name='SubmissionTag',
+fields=[
+('id', models.AutoField(auto_created=True,
+primary_key=True,
+serialize=False,
+verbose_name='ID')),
+('value', models.CharField(max_length=255)),
+('comment', models.ForeignKey(
+on_delete=django.db.models.deletion.CASCADE,
+to='patchwork.Comment',
+null=True
+)),
+('submission', models.ForeignKey(
+on_delete=django.db.models.deletion.CASCADE,
+to='patchwork.Submission'
+)),
+('tag', models.ForeignKey(
+on_delete=django.db.models.deletion.CASCADE,
+to='patchwork.Tag'
+)),
+('series', models.ForeignKey(
+on_delete=django.db.models.deletion.CASCADE,
+to='patchwork.Series',
+null=True
+)),
+],
+),
+migrations.AlterUniqueTogether(
+name='patchtag',
+unique_together=set([]),
+),
+migrations.RemoveField(model_name='patchtag', name='patch',),
+

[PATCH v2 1/4] Rework tagging infrastructure

2018-09-17 Thread vkabatov
From: Veronika Kabatova 

Solve #113 and #57 GitHub issues, keep track of tag origin to be able
to add tags to comments in the API later.

Use relations Tag-Patch and Tag-CoverLetter to avoid duplication of
tags for each patch in series, and use `series` attribute of
SubmissionTag as a notion of a tag which is related to each patch in the
series (because it comes from cover letter or it's comments)

Signed-off-by: Veronika Kabatova 
---
Rebased on top of 'Convert Series-Patch relationship to 1:N' series.

Stephen, I split up the patch to separate out API, mbox and documentation
changes as you suggested; and implemented your comments (simplified the
migration in favor of running the retag comment, moved the tag retrieval from
the API into a property in models.py, added comment and tag prefetching,
increased the API version where needed, added wildcard to API filter and
simplified it and some other minor things). The series-patch cleanup definitely
helped with some cleanup, but let me know if there are other optimizations that
would help with regards to DB performance.
---
 patchwork/management/commands/retag.py|  15 +-
 patchwork/migrations/0034_rework_tagging.py   |  66 +++
 patchwork/models.py   | 175 --
 patchwork/templatetags/patch.py   |   3 +-
 patchwork/tests/test_parser.py|  18 +-
 patchwork/tests/test_tags.py  |  64 +++
 patchwork/views/__init__.py   |   3 -
 .../tagging-rework-9907e9dc3f835566.yaml  |  15 ++
 8 files changed, 202 insertions(+), 157 deletions(-)
 create mode 100644 patchwork/migrations/0034_rework_tagging.py
 create mode 100644 releasenotes/notes/tagging-rework-9907e9dc3f835566.yaml

diff --git a/patchwork/management/commands/retag.py 
b/patchwork/management/commands/retag.py
index 8617ff41..95b2cc1f 100644
--- a/patchwork/management/commands/retag.py
+++ b/patchwork/management/commands/retag.py
@@ -19,15 +19,15 @@
 
 from django.core.management.base import BaseCommand
 
-from patchwork.models import Patch
+from patchwork.models import Submission
 
 
 class Command(BaseCommand):
-help = 'Update the tag (Ack/Review/Test) counts on existing patches'
-args = '[...]'
+help = 'Update tags on existing submissions and associated comments'
+args = '[...]'
 
 def handle(self, *args, **options):
-query = Patch.objects
+query = Submission.objects.prefetch_related('comments')
 
 if args:
 query = query.filter(id__in=args)
@@ -36,8 +36,11 @@ class Command(BaseCommand):
 
 count = query.count()
 
-for i, patch in enumerate(query.iterator()):
-patch.refresh_tag_counts()
+for i, submission in enumerate(query.iterator()):
+submission.refresh_tags()
+for comment in submission.comments.all():
+comment.refresh_tags()
+
 if (i % 10) == 0:
 self.stdout.write('%06d/%06d\r' % (i, count), ending='')
 self.stdout.flush()
diff --git a/patchwork/migrations/0034_rework_tagging.py 
b/patchwork/migrations/0034_rework_tagging.py
new file mode 100644
index ..580a4fd0
--- /dev/null
+++ b/patchwork/migrations/0034_rework_tagging.py
@@ -0,0 +1,66 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+dependencies = [
+('patchwork', '0033_remove_patch_series_model'),
+]
+
+operations = [
+migrations.CreateModel(
+name='SubmissionTag',
+fields=[
+('id', models.AutoField(auto_created=True,
+primary_key=True,
+serialize=False,
+verbose_name='ID')),
+('value', models.CharField(max_length=255)),
+('comment', models.ForeignKey(
+on_delete=django.db.models.deletion.CASCADE,
+to='patchwork.Comment',
+null=True
+)),
+('submission', models.ForeignKey(
+on_delete=django.db.models.deletion.CASCADE,
+to='patchwork.Submission'
+)),
+('tag', models.ForeignKey(
+on_delete=django.db.models.deletion.CASCADE,
+to='patchwork.Tag'
+)),
+('series', models.ForeignKey(
+on_delete=django.db.models.deletion.CASCADE,
+to='patchwork.Series',
+null=True
+)),
+],
+),
+migrations.AlterUniqueTogether(
+name='patchtag',
+unique_together=set([]),
+),
+migrations.RemoveField(model_name='patchtag', name='patch',),
+

[PATCH 6/6] views: Add error handling for user registration

2018-09-17 Thread Stephen Finucane
This was already present for registration confirmation but missing for
initial registration. Resolve this.

Signed-off-by: Stephen Finucane 
---
 patchwork/views/user.py | 15 +--
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/patchwork/views/user.py b/patchwork/views/user.py
index 6348bed6..9876da96 100644
--- a/patchwork/views/user.py
+++ b/patchwork/views/user.py
@@ -64,6 +64,8 @@ def register(request):
  email=user.email)
 conf.save()
 
+context['confirmation'] = conf
+
 # send email
 subject = render_to_string(
 'patchwork/mails/activation-subject.txt')
@@ -71,12 +73,13 @@ def register(request):
 'patchwork/mails/activation.txt',
 {'site': Site.objects.get_current(), 'confirmation': conf})
 
-# TODO(stephenfin): Should this be surrounded by a try-except?
-send_mail(subject, message, settings.DEFAULT_FROM_EMAIL,
-  [conf.email])
-
-# setting 'confirmation' in the template indicates success
-context['confirmation'] = conf
+try:
+send_mail(subject, message, settings.DEFAULT_FROM_EMAIL,
+  [conf.email])
+except smtplib.SMTPException:
+context['confirmation'] = None
+context['error'] = ('An error occurred during registration. '
+'Please try again later')
 else:
 form = RegistrationForm()
 
-- 
2.17.1

___
Patchwork mailing list
Patchwork@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/patchwork


[PATCH 5/6] templates: Remove 'email_sent' attribute

2018-09-17 Thread Stephen Finucane
Further normalization to ensure all related code paths use similar code.

Signed-off-by: Stephen Finucane 
---
 patchwork/templates/patchwork/optin-request.html  | 2 +-
 patchwork/templates/patchwork/optout-request.html | 2 +-
 patchwork/tests/test_mail_settings.py | 8 
 patchwork/views/mail.py   | 7 +++
 4 files changed, 9 insertions(+), 10 deletions(-)

diff --git a/patchwork/templates/patchwork/optin-request.html 
b/patchwork/templates/patchwork/optin-request.html
index dfc104e8..90963e65 100644
--- a/patchwork/templates/patchwork/optin-request.html
+++ b/patchwork/templates/patchwork/optin-request.html
@@ -4,7 +4,7 @@
 {% block heading %}Opt-in{% endblock %}
 
 {% block body %}
-{% if email_sent %}
+{% if confirmation %}
 Opt-in confirmation email sent
 An opt-in confirmation mail has been sent to
 {{confirmation.email}}, containing a link. Please click on
diff --git a/patchwork/templates/patchwork/optout-request.html 
b/patchwork/templates/patchwork/optout-request.html
index eae05e62..659af773 100644
--- a/patchwork/templates/patchwork/optout-request.html
+++ b/patchwork/templates/patchwork/optout-request.html
@@ -4,7 +4,7 @@
 {% block heading %}Opt-out{% endblock %}
 
 {% block body %}
-{% if email_sent %}
+{% if confirmation %}
 Opt-out confirmation email sent
 An opt-out confirmation mail has been sent to
 {{confirmation.email}}, containing a link. Please click on
diff --git a/patchwork/tests/test_mail_settings.py 
b/patchwork/tests/test_mail_settings.py
index 70e135d5..8844212e 100644
--- a/patchwork/tests/test_mail_settings.py
+++ b/patchwork/tests/test_mail_settings.py
@@ -108,7 +108,7 @@ class OptoutRequestTest(TestCase):
 self.assertFormError(response, 'form', 'email',
  'This field is required.')
 self.assertTrue(response.context['error'])
-self.assertNotIn('email_sent', response.context)
+self.assertNotIn('confirmation', response.context)
 self.assertEqual(len(mail.outbox), 0)
 
 def test_post_non_email(self):
@@ -116,7 +116,7 @@ class OptoutRequestTest(TestCase):
 self.assertEqual(response.status_code, 200)
 self.assertFormError(response, 'form', 'email', error_strings['email'])
 self.assertTrue(response.context['error'])
-self.assertNotIn('email_sent', response.context)
+self.assertNotIn('confirmation', response.context)
 self.assertEqual(len(mail.outbox), 0)
 
 
@@ -189,7 +189,7 @@ class OptinRequestTest(TestCase):
 self.assertFormError(response, 'form', 'email',
  'This field is required.')
 self.assertTrue(response.context['error'])
-self.assertNotIn('email_sent', response.context)
+self.assertNotIn('confirmation', response.context)
 self.assertEqual(len(mail.outbox), 0)
 
 def test_post_non_email(self):
@@ -197,7 +197,7 @@ class OptinRequestTest(TestCase):
 self.assertEqual(response.status_code, 200)
 self.assertFormError(response, 'form', 'email', error_strings['email'])
 self.assertTrue(response.context['error'])
-self.assertNotIn('email_sent', response.context)
+self.assertNotIn('confirmation', response.context)
 self.assertEqual(len(mail.outbox), 0)
 
 
diff --git a/patchwork/views/mail.py b/patchwork/views/mail.py
index 1ce37736..6a3c1c25 100644
--- a/patchwork/views/mail.py
+++ b/patchwork/views/mail.py
@@ -97,8 +97,8 @@ def _optinout(request, action):
 return render(request, html_template, context)
 
 email = form.cleaned_data['email']
-if action == 'optin' and \
-EmailOptout.objects.filter(email=email).count() == 0:
+if action == 'optin' and EmailOptout.objects.filter(
+email=email).count() == 0:
 context['error'] = ("The email address %s is not on the patchwork "
 "opt-out list, so you don't need to opt back in" %
 email)
@@ -115,9 +115,8 @@ def _optinout(request, action):
 
 try:
 send_mail(subject, message, conf_settings.DEFAULT_FROM_EMAIL, [email])
-# TODO(stephenfin): This is unnecessary and can be removed
-context['email_sent'] = True
 except smtplib.SMTPException:
+context['confirmation'] = None
 context['error'] = ('An error occurred during confirmation . '
 'Please try again later.')
 context['admins'] = conf_settings.ADMINS
-- 
2.17.1

___
Patchwork mailing list
Patchwork@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/patchwork


[PATCH 4/6] templates: Move additional email subjects to templates

2018-09-17 Thread Stephen Finucane
Use a uniform pattern for this stuff.

Signed-off-by: Stephen Finucane 
---
 .../patchwork/mails/optin-request-subject.txt |  1 +
 .../mails/optout-request-subject.txt  |  1 +
 .../patchwork/mails/user-link-subject.txt |  1 +
 patchwork/views/mail.py   | 19 +++
 patchwork/views/user.py   |  2 +-
 5 files changed, 15 insertions(+), 9 deletions(-)
 create mode 100644 
patchwork/templates/patchwork/mails/optin-request-subject.txt
 create mode 100644 
patchwork/templates/patchwork/mails/optout-request-subject.txt
 create mode 100644 patchwork/templates/patchwork/mails/user-link-subject.txt

diff --git a/patchwork/templates/patchwork/mails/optin-request-subject.txt 
b/patchwork/templates/patchwork/mails/optin-request-subject.txt
new file mode 100644
index ..9733b6f3
--- /dev/null
+++ b/patchwork/templates/patchwork/mails/optin-request-subject.txt
@@ -0,0 +1 @@
+Patchwork opt-in request
\ No newline at end of file
diff --git a/patchwork/templates/patchwork/mails/optout-request-subject.txt 
b/patchwork/templates/patchwork/mails/optout-request-subject.txt
new file mode 100644
index ..377dfc89
--- /dev/null
+++ b/patchwork/templates/patchwork/mails/optout-request-subject.txt
@@ -0,0 +1 @@
+Patchwork opt-out confirmation
\ No newline at end of file
diff --git a/patchwork/templates/patchwork/mails/user-link-subject.txt 
b/patchwork/templates/patchwork/mails/user-link-subject.txt
new file mode 100644
index ..8ac4d1d4
--- /dev/null
+++ b/patchwork/templates/patchwork/mails/user-link-subject.txt
@@ -0,0 +1 @@
+Patchwork email address confirmation
\ No newline at end of file
diff --git a/patchwork/views/mail.py b/patchwork/views/mail.py
index 12825a13..1ce37736 100644
--- a/patchwork/views/mail.py
+++ b/patchwork/views/mail.py
@@ -80,9 +80,10 @@ def optin_confirm(request, conf):
 return render(request, 'patchwork/optin.html', context)
 
 
-def _optinout(request, action, description):
+def _optinout(request, action):
 context = {}
 mail_template = 'patchwork/mails/%s-request.txt' % action
+mail_subject_template = 'patchwork/mails/%s-request-subject.txt' % action
 html_template = 'patchwork/%s-request.html' % action
 
 if request.method != 'POST':
@@ -90,8 +91,8 @@ def _optinout(request, action, description):
 
 form = EmailForm(data=request.POST)
 if not form.is_valid():
-context['error'] = ('There was an error in the %s form. Please '
-'review the form and re-submit.' % description)
+context['error'] = ('There was an error in the form. Please review '
+'and re-submit.')
 context['form'] = form
 return render(request, html_template, context)
 
@@ -108,11 +109,13 @@ def _optinout(request, action, description):
 conf.save()
 
 context['confirmation'] = conf
-mail = render_to_string(mail_template, context, request=request)
+
+subject = render_to_string(mail_subject_template)
+message = render_to_string(mail_template, context, request=request)
 
 try:
-send_mail('Patchwork %s confirmation' % description, mail,
-  conf_settings.DEFAULT_FROM_EMAIL, [email])
+send_mail(subject, message, conf_settings.DEFAULT_FROM_EMAIL, [email])
+# TODO(stephenfin): This is unnecessary and can be removed
 context['email_sent'] = True
 except smtplib.SMTPException:
 context['error'] = ('An error occurred during confirmation . '
@@ -123,8 +126,8 @@ def _optinout(request, action, description):
 
 
 def optout(request):
-return _optinout(request, 'optout', 'opt-out')
+return _optinout(request, 'optout')
 
 
 def optin(request):
-return _optinout(request, 'optin', 'opt-in')
+return _optinout(request, 'optin')
diff --git a/patchwork/views/user.py b/patchwork/views/user.py
index cb8e61af..6348bed6 100644
--- a/patchwork/views/user.py
+++ b/patchwork/views/user.py
@@ -151,7 +151,7 @@ def link(request):
 
 context['confirmation'] = conf
 
-subject = 'Patchwork email address confirmation',
+subject = render_to_string('patchwork/mails/user-link-subject.txt')
 message = render_to_string('patchwork/mails/user-link.txt',
context, request=request)
 try:
-- 
2.17.1

___
Patchwork mailing list
Patchwork@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/patchwork


[PATCH 2/6] templates: Rename additional templates

2018-09-17 Thread Stephen Finucane
Make ALL the things consistent.

Signed-off-by: Stephen Finucane 
---
 .../{download_buttons.html => download-buttons.html}  | 0
 patchwork/templates/patchwork/{mail-form.html => mail.html}   | 0
 .../patchwork/{registration_form.html => registration.html}   | 0
 patchwork/templates/patchwork/submission.html | 4 ++--
 patchwork/tests/test_mail_settings.py | 4 ++--
 patchwork/tests/test_registration.py  | 2 +-
 patchwork/views/mail.py   | 2 +-
 patchwork/views/user.py   | 2 +-
 8 files changed, 7 insertions(+), 7 deletions(-)
 rename patchwork/templates/patchwork/{download_buttons.html => 
download-buttons.html} (100%)
 rename patchwork/templates/patchwork/{mail-form.html => mail.html} (100%)
 rename patchwork/templates/patchwork/{registration_form.html => 
registration.html} (100%)

diff --git a/patchwork/templates/patchwork/download_buttons.html 
b/patchwork/templates/patchwork/download-buttons.html
similarity index 100%
rename from patchwork/templates/patchwork/download_buttons.html
rename to patchwork/templates/patchwork/download-buttons.html
diff --git a/patchwork/templates/patchwork/mail-form.html 
b/patchwork/templates/patchwork/mail.html
similarity index 100%
rename from patchwork/templates/patchwork/mail-form.html
rename to patchwork/templates/patchwork/mail.html
diff --git a/patchwork/templates/patchwork/registration_form.html 
b/patchwork/templates/patchwork/registration.html
similarity index 100%
rename from patchwork/templates/patchwork/registration_form.html
rename to patchwork/templates/patchwork/registration.html
diff --git a/patchwork/templates/patchwork/submission.html 
b/patchwork/templates/patchwork/submission.html
index f03e1408..6e189b27 100644
--- a/patchwork/templates/patchwork/submission.html
+++ b/patchwork/templates/patchwork/submission.html
@@ -28,7 +28,7 @@ function toggle_div(link_id, headers_id)
 
 
 {{ submission.name }}
-{% include "patchwork/download_buttons.html" %}
+{% include "patchwork/download-buttons.html" %}
 
 
 
@@ -285,7 +285,7 @@ function toggle_div(link_id, headers_id)
 {% if submission.diff %}
 
  Patch
- {% include "patchwork/download_buttons.html" %}
+ {% include "patchwork/download-buttons.html" %}
 
 
 
diff --git a/patchwork/tests/test_mail_settings.py 
b/patchwork/tests/test_mail_settings.py
index 6d56f5a8..70e135d5 100644
--- a/patchwork/tests/test_mail_settings.py
+++ b/patchwork/tests/test_mail_settings.py
@@ -46,14 +46,14 @@ class MailSettingsTest(TestCase):
 def test_post_empty(self):
 response = self.client.post(reverse('mail-settings'), {'email': ''})
 self.assertEqual(response.status_code, 200)
-self.assertTemplateUsed(response, 'patchwork/mail-form.html')
+self.assertTemplateUsed(response, 'patchwork/mail.html')
 self.assertFormError(response, 'form', 'email',
  'This field is required.')
 
 def test_post_invalid(self):
 response = self.client.post(reverse('mail-settings'), {'email': 'foo'})
 self.assertEqual(response.status_code, 200)
-self.assertTemplateUsed(response, 'patchwork/mail-form.html')
+self.assertTemplateUsed(response, 'patchwork/mail.html')
 self.assertFormError(response, 'form', 'email', error_strings['email'])
 
 def test_post_optin(self):
diff --git a/patchwork/tests/test_registration.py 
b/patchwork/tests/test_registration.py
index 616254d2..ad8ead23 100644
--- a/patchwork/tests/test_registration.py
+++ b/patchwork/tests/test_registration.py
@@ -55,7 +55,7 @@ class RegistrationTest(TestCase):
 def test_registration_form(self):
 response = self.client.get('/register/')
 self.assertEqual(response.status_code, 200)
-self.assertTemplateUsed(response, 'patchwork/registration_form.html')
+self.assertTemplateUsed(response, 'patchwork/registration.html')
 
 def test_blank_fields(self):
 for field in ['username', 'email', 'password']:
diff --git a/patchwork/views/mail.py b/patchwork/views/mail.py
index 45283eba..12825a13 100644
--- a/patchwork/views/mail.py
+++ b/patchwork/views/mail.py
@@ -48,7 +48,7 @@ def settings(request):
 'form': form,
 }
 
-return render(request, 'patchwork/mail-form.html', context)
+return render(request, 'patchwork/mail.html', context)
 
 
 def optout_confirm(request, conf):
diff --git a/patchwork/views/user.py b/patchwork/views/user.py
index 848f86e5..cb8e61af 100644
--- a/patchwork/views/user.py
+++ b/patchwork/views/user.py
@@ -82,7 +82,7 @@ def register(request):
 
 context['form'] = form
 
-return render(request, 'patchwork/registration_form.html', context)
+return render(request, 'patchwork/registration.html', context)
 
 
 def register_confirm(request, conf):
-- 
2.17.1

___
Patchwork mailing list
Patchwork@lists.ozlabs.org

[PATCH 3/6] templates: Keep only whole templates in the top-level

2018-09-17 Thread Stephen Finucane
Again, this should make this a little more understandable as it ensures
a rough mapping exists between views and template names.

Signed-off-by: Stephen Finucane 
---
 patchwork/templates/patchwork/bundle.html   | 2 +-
 patchwork/templates/patchwork/list.html | 2 +-
 .../patchwork/{ => partials}/download-buttons.html  | 0
 patchwork/templates/patchwork/{ => partials}/filters.html   | 0
 .../templates/patchwork/{ => partials}/pagination.html  | 0
 .../templates/patchwork/{ => partials}/patch-list.html  | 6 +++---
 patchwork/templates/patchwork/submission.html   | 4 ++--
 patchwork/templates/patchwork/todo-list.html| 2 +-
 8 files changed, 8 insertions(+), 8 deletions(-)
 rename patchwork/templates/patchwork/{ => partials}/download-buttons.html 
(100%)
 rename patchwork/templates/patchwork/{ => partials}/filters.html (100%)
 rename patchwork/templates/patchwork/{ => partials}/pagination.html (100%)
 rename patchwork/templates/patchwork/{ => partials}/patch-list.html (98%)

diff --git a/patchwork/templates/patchwork/bundle.html 
b/patchwork/templates/patchwork/bundle.html
index 2042cb96..b5c9f90a 100644
--- a/patchwork/templates/patchwork/bundle.html
+++ b/patchwork/templates/patchwork/bundle.html
@@ -40,6 +40,6 @@ project.
 
 {% endif %}
 
-{% include "patchwork/patch-list.html" %}
+{% include "patchwork/partials/patch-list.html" %}
 
 {% endblock %}
diff --git a/patchwork/templates/patchwork/list.html 
b/patchwork/templates/patchwork/list.html
index 180c5607..5d3d82aa 100644
--- a/patchwork/templates/patchwork/list.html
+++ b/patchwork/templates/patchwork/list.html
@@ -18,6 +18,6 @@ while updating patches:
 
 {% endif %}
 
-{% include "patchwork/patch-list.html" %}
+{% include "patchwork/partials/patch-list.html" %}
 
 {% endblock %}
diff --git a/patchwork/templates/patchwork/download-buttons.html 
b/patchwork/templates/patchwork/partials/download-buttons.html
similarity index 100%
rename from patchwork/templates/patchwork/download-buttons.html
rename to patchwork/templates/patchwork/partials/download-buttons.html
diff --git a/patchwork/templates/patchwork/filters.html 
b/patchwork/templates/patchwork/partials/filters.html
similarity index 100%
rename from patchwork/templates/patchwork/filters.html
rename to patchwork/templates/patchwork/partials/filters.html
diff --git a/patchwork/templates/patchwork/pagination.html 
b/patchwork/templates/patchwork/partials/pagination.html
similarity index 100%
rename from patchwork/templates/patchwork/pagination.html
rename to patchwork/templates/patchwork/partials/pagination.html
diff --git a/patchwork/templates/patchwork/patch-list.html 
b/patchwork/templates/patchwork/partials/patch-list.html
similarity index 98%
rename from patchwork/templates/patchwork/patch-list.html
rename to patchwork/templates/patchwork/partials/patch-list.html
index 71c1ba92..53d577de 100644
--- a/patchwork/templates/patchwork/patch-list.html
+++ b/patchwork/templates/patchwork/partials/patch-list.html
@@ -4,9 +4,9 @@
 {% load project %}
 {% load static %}
 
-{% include "patchwork/filters.html" %}
+{% include "patchwork/partials/filters.html" %}
 
-{% include "patchwork/pagination.html" %}
+{% include "patchwork/partials/pagination.html" %}
 
 {% if order.editable %}
 
@@ -218,7 +218,7 @@ $(document).ready(function() {
 
 
 {% if page.paginator.count %}
-{% include "patchwork/pagination.html" %}
+{% include "patchwork/partials/pagination.html" %}
 
 
 
diff --git a/patchwork/templates/patchwork/submission.html 
b/patchwork/templates/patchwork/submission.html
index 6e189b27..eb5e3583 100644
--- a/patchwork/templates/patchwork/submission.html
+++ b/patchwork/templates/patchwork/submission.html
@@ -28,7 +28,7 @@ function toggle_div(link_id, headers_id)
 
 
 {{ submission.name }}
-{% include "patchwork/download-buttons.html" %}
+{% include "patchwork/partials/download-buttons.html" %}
 
 
 
@@ -285,7 +285,7 @@ function toggle_div(link_id, headers_id)
 {% if submission.diff %}
 
  Patch
- {% include "patchwork/download-buttons.html" %}
+ {% include "patchwork/partials/download-buttons.html" %}
 
 
 
diff --git a/patchwork/templates/patchwork/todo-list.html 
b/patchwork/templates/patchwork/todo-list.html
index 444baa01..1ec2713d 100644
--- a/patchwork/templates/patchwork/todo-list.html
+++ b/patchwork/templates/patchwork/todo-list.html
@@ -12,6 +12,6 @@ are in an "action required" state
 ({% for state in action_required_states %}{% if forloop.last and not 
forloop.first %} or {% endif %}{{ state }}{% if not forloop.last and not 
forloop.first %}, {%endif %}{% endfor %}), and are not archived.
 
 
-{% include "patchwork/patch-list.html" %}
+{% include "patchwork/partials/patch-list.html" %}
 
 {% endblock %}
-- 
2.17.1

___
Patchwork mailing list
Patchwork@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/patchwork


[PATCH 1/6] templates: Move mails to separate directory

2018-09-17 Thread Stephen Finucane
This makes things a little easier to parse. A couple of templates are
renamed and the 'register.mail' template, which appears to be unused
since commit f1e089f7, is removed.

Signed-off-by: Stephen Finucane 
---
 patchwork/notifications.py |  7 ---
 .../activation-subject.txt}|  0
 .../{activation_email.txt => mails/activation.txt} |  0
 .../optin-request.txt} |  0
 .../optout-request.txt}|  0
 .../patch-change-notification-subject.txt} |  0
 .../patch-change-notification.txt} |  0
 .../{user-link.mail => mails/user-link.txt}|  0
 patchwork/templates/patchwork/register.mail| 11 ---
 patchwork/views/mail.py|  2 +-
 patchwork/views/user.py| 14 +-
 11 files changed, 14 insertions(+), 20 deletions(-)
 rename patchwork/templates/patchwork/{activation_email_subject.txt => 
mails/activation-subject.txt} (100%)
 rename patchwork/templates/patchwork/{activation_email.txt => 
mails/activation.txt} (100%)
 rename patchwork/templates/patchwork/{optin-request.mail => 
mails/optin-request.txt} (100%)
 rename patchwork/templates/patchwork/{optout-request.mail => 
mails/optout-request.txt} (100%)
 rename patchwork/templates/patchwork/{patch-change-notification-subject.text 
=> mails/patch-change-notification-subject.txt} (100%)
 rename patchwork/templates/patchwork/{patch-change-notification.mail => 
mails/patch-change-notification.txt} (100%)
 rename patchwork/templates/patchwork/{user-link.mail => mails/user-link.txt} 
(100%)
 delete mode 100644 patchwork/templates/patchwork/register.mail

diff --git a/patchwork/notifications.py b/patchwork/notifications.py
index 3ddd806b..45c081b9 100644
--- a/patchwork/notifications.py
+++ b/patchwork/notifications.py
@@ -76,10 +76,11 @@ def send_notifications():
 }
 
 subject = render_to_string(
-'patchwork/patch-change-notification-subject.text',
+'patchwork/mails/patch-change-notification-subject.txt',
 context).strip()
-content = render_to_string('patchwork/patch-change-notification.mail',
-   context)
+content = render_to_string(
+'patchwork/mails/patch-change-notification.txt',
+context)
 
 message = EmailMessage(subject=subject, body=content,
from_email=settings.NOTIFICATION_FROM_EMAIL,
diff --git a/patchwork/templates/patchwork/activation_email_subject.txt 
b/patchwork/templates/patchwork/mails/activation-subject.txt
similarity index 100%
rename from patchwork/templates/patchwork/activation_email_subject.txt
rename to patchwork/templates/patchwork/mails/activation-subject.txt
diff --git a/patchwork/templates/patchwork/activation_email.txt 
b/patchwork/templates/patchwork/mails/activation.txt
similarity index 100%
rename from patchwork/templates/patchwork/activation_email.txt
rename to patchwork/templates/patchwork/mails/activation.txt
diff --git a/patchwork/templates/patchwork/optin-request.mail 
b/patchwork/templates/patchwork/mails/optin-request.txt
similarity index 100%
rename from patchwork/templates/patchwork/optin-request.mail
rename to patchwork/templates/patchwork/mails/optin-request.txt
diff --git a/patchwork/templates/patchwork/optout-request.mail 
b/patchwork/templates/patchwork/mails/optout-request.txt
similarity index 100%
rename from patchwork/templates/patchwork/optout-request.mail
rename to patchwork/templates/patchwork/mails/optout-request.txt
diff --git 
a/patchwork/templates/patchwork/patch-change-notification-subject.text 
b/patchwork/templates/patchwork/mails/patch-change-notification-subject.txt
similarity index 100%
rename from patchwork/templates/patchwork/patch-change-notification-subject.text
rename to 
patchwork/templates/patchwork/mails/patch-change-notification-subject.txt
diff --git a/patchwork/templates/patchwork/patch-change-notification.mail 
b/patchwork/templates/patchwork/mails/patch-change-notification.txt
similarity index 100%
rename from patchwork/templates/patchwork/patch-change-notification.mail
rename to patchwork/templates/patchwork/mails/patch-change-notification.txt
diff --git a/patchwork/templates/patchwork/user-link.mail 
b/patchwork/templates/patchwork/mails/user-link.txt
similarity index 100%
rename from patchwork/templates/patchwork/user-link.mail
rename to patchwork/templates/patchwork/mails/user-link.txt
diff --git a/patchwork/templates/patchwork/register.mail 
b/patchwork/templates/patchwork/register.mail
deleted file mode 100644
index 51f3adfa..
--- a/patchwork/templates/patchwork/register.mail
+++ /dev/null
@@ -1,11 +0,0 @@
-Hi,
-
-This email is to confirm your account on the Patchwork patch-tracking
-system. You can activate your account by visiting the url:
-
- http://{{site.domain}}{% url 

[PATCH] Remove '__future__.absolute_import' imports

2018-09-17 Thread Stephen Finucane
These were added as part of the Python 3 support series but are not
required and can be safely removed.

Signed-off-by: Stephen Finucane 
---
 patchwork/admin.py   | 2 --
 patchwork/fields.py  | 2 --
 patchwork/filters.py | 2 --
 patchwork/models.py  | 2 --
 patchwork/paginator.py   | 2 --
 patchwork/settings/dev.py| 2 --
 patchwork/settings/production.example.py | 2 --
 patchwork/templatetags/listurl.py| 2 --
 patchwork/templatetags/patch.py  | 2 --
 patchwork/templatetags/person.py | 2 --
 patchwork/templatetags/project.py| 2 --
 patchwork/templatetags/syntax.py | 2 --
 patchwork/tests/test_bundles.py  | 2 --
 patchwork/tests/test_completion.py   | 2 --
 patchwork/tests/test_detail.py   | 2 --
 patchwork/tests/test_list.py | 2 --
 patchwork/views/xmlrpc.py| 2 --
 17 files changed, 34 deletions(-)

diff --git a/patchwork/admin.py b/patchwork/admin.py
index d5b9887e..a0799011 100644
--- a/patchwork/admin.py
+++ b/patchwork/admin.py
@@ -16,8 +16,6 @@
 # Patchwork; if not, write to the Free Software Foundation, Inc., 51 Franklin
 # Street, Fifth Floor, Boston, MA, 02110-1335, USA
 
-from __future__ import absolute_import
-
 from django.contrib import admin
 from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
 from django.contrib.auth.models import User
diff --git a/patchwork/fields.py b/patchwork/fields.py
index e229d5be..9ad2c3c7 100644
--- a/patchwork/fields.py
+++ b/patchwork/fields.py
@@ -17,8 +17,6 @@
 # Patchwork; if not, write to the Free Software Foundation, Inc., 51 Franklin
 # Street, Fifth Floor, Boston, MA, 02110-1335, USA
 
-from __future__ import absolute_import
-
 import hashlib
 
 from django.db import models
diff --git a/patchwork/filters.py b/patchwork/filters.py
index 778b0bbd..2bcf26a8 100644
--- a/patchwork/filters.py
+++ b/patchwork/filters.py
@@ -16,8 +16,6 @@
 # Patchwork; if not, write to the Free Software Foundation, Inc., 51 Franklin
 # Street, Fifth Floor, Boston, MA, 02110-1335, USA
 
-from __future__ import absolute_import
-
 from django.contrib.auth.models import User
 from django.utils.html import escape
 from django.utils.safestring import mark_safe
diff --git a/patchwork/models.py b/patchwork/models.py
index 734abce6..4e925160 100644
--- a/patchwork/models.py
+++ b/patchwork/models.py
@@ -17,8 +17,6 @@
 # Patchwork; if not, write to the Free Software Foundation, Inc., 51 Franklin
 # Street, Fifth Floor, Boston, MA, 02110-1335, USA
 
-from __future__ import absolute_import
-
 from collections import Counter
 from collections import OrderedDict
 import datetime
diff --git a/patchwork/paginator.py b/patchwork/paginator.py
index 6acc9030..0cc0ad20 100644
--- a/patchwork/paginator.py
+++ b/patchwork/paginator.py
@@ -16,8 +16,6 @@
 # Patchwork; if not, write to the Free Software Foundation, Inc., 51 Franklin
 # Street, Fifth Floor, Boston, MA, 02110-1335, USA
 
-from __future__ import absolute_import
-
 from django.conf import settings
 from django.core import paginator
 
diff --git a/patchwork/settings/dev.py b/patchwork/settings/dev.py
index 79148803..4bb5a93c 100644
--- a/patchwork/settings/dev.py
+++ b/patchwork/settings/dev.py
@@ -7,8 +7,6 @@ Design based on:
 http://www.revsys.com/blog/2014/nov/21/recommended-django-project-layout/
 """
 
-from __future__ import absolute_import
-
 from .base import *  # noqa
 
 #
diff --git a/patchwork/settings/production.example.py 
b/patchwork/settings/production.example.py
index 0c7a88c0..f58896fc 100644
--- a/patchwork/settings/production.example.py
+++ b/patchwork/settings/production.example.py
@@ -7,8 +7,6 @@ Design based on:
 http://www.revsys.com/blog/2014/nov/21/recommended-django-project-layout/
 """
 
-from __future__ import absolute_import
-
 import os
 
 from .base import *  # noqa
diff --git a/patchwork/templatetags/listurl.py 
b/patchwork/templatetags/listurl.py
index a0981dd3..dc76b157 100644
--- a/patchwork/templatetags/listurl.py
+++ b/patchwork/templatetags/listurl.py
@@ -16,8 +16,6 @@
 # Patchwork; if not, write to the Free Software Foundation, Inc., 51 Franklin
 # Street, Fifth Floor, Boston, MA, 02110-1335, USA
 
-from __future__ import absolute_import
-
 from django.conf import settings
 from django import template
 from django.urls import reverse
diff --git a/patchwork/templatetags/patch.py b/patchwork/templatetags/patch.py
index b97d492c..27d0bce7 100644
--- a/patchwork/templatetags/patch.py
+++ b/patchwork/templatetags/patch.py
@@ -17,8 +17,6 @@
 # Patchwork; if not, write to the Free Software Foundation, Inc., 51 Franklin
 # Street, Fifth Floor, Boston, MA, 02110-1335, USA
 
-from __future__ import absolute_import
-
 from django import template
 from django.utils.safestring import mark_safe
 from django.template.defaultfilters import stringfilter
diff --git a/patchwork/templatetags/person.py