Review Board

beta

Clean up several aspects of the models

Updated 6 months ago

Christian Hammond Reviewers
trunk reviewboard
None Review Board SVN
Cleaned up some of the models by giving all relationship fields explicit related_name fields, rather than using Django's pre-generated defaults. This makes for more natural names and is something we'd want to do before extensions land later on.

This also moves error types and the custom Manager in reviews to their own files.
All unit tests pass.
/trunk/reviewboard/accounts/views.py
Revision 1384 New Change
35
                    request.user.password = newpassword
35
                    request.user.password = newpassword
36
36
37
                request.user.first_name = form.cleaned_data['first_name']
37
                request.user.first_name = form.cleaned_data['first_name']
38
                request.user.last_name = form.cleaned_data['last_name']
38
                request.user.last_name = form.cleaned_data['last_name']
39
                request.user.email = form.cleaned_data['email']
39
                request.user.email = form.cleaned_data['email']
40
            request.user.group_set = form.cleaned_data['groups']
40
            request.user.review_groups = form.cleaned_data['groups']
41
            request.user.save()
41
            request.user.save()
42
42
43
            profile.first_time_setup_done = True
43
            profile.first_time_setup_done = True
44
            profile.syntax_highlighting = \
44
            profile.syntax_highlighting = \
45
                form.cleaned_data['syntax_highlighting']
45
                form.cleaned_data['syntax_highlighting']
52
            'redirect_to': redirect_to,
52
            'redirect_to': redirect_to,
53
            'first_name': request.user.first_name,
53
            'first_name': request.user.first_name,
54
            'last_name': request.user.last_name,
54
            'last_name': request.user.last_name,
55
            'email': request.user.email,
55
            'email': request.user.email,
56
            'syntax_highlighting': profile.syntax_highlighting,
56
            'syntax_highlighting': profile.syntax_highlighting,
57
            'groups': [g.id for g in request.user.group_set.all()],
57
            'groups': [g.id for g in request.user.review_groups.all()],
58
        })
58
        })
59
59
60
    return render_to_response(template_name, RequestContext(request, {
60
    return render_to_response(template_name, RequestContext(request, {
61
        'form': form,
61
        'form': form,
62
        'settings': settings,
62
        'settings': settings,
63
        'must_configure': must_configure,
63
        'must_configure': must_configure,
64
    }))
64
    }))
/trunk/reviewboard/contrib/db/db2wiki.py
Revision 1384 New Change
81
            ('target_groups', [g.name for g in o.target_groups.all()]),
81
            ('target_groups', [g.name for g in o.target_groups.all()]),
82
            ('target_people', [u.username for u in o.target_people.all()]),
82
            ('target_people', [u.username for u in o.target_people.all()]),
83
            ('bugs_closed', o.get_bug_list()),
83
            ('bugs_closed', o.get_bug_list()),
84
            ('public', o.public),
84
            ('public', o.public),
85
            ('status', o.status),
85
            ('status', o.status),
86
            ('diff', o.diffset_history.diffset_set.latest().name),
86
            ('diff', o.diffset_history.diffsets.latest().name),
87
            ('reviews', [(review.user.username, get_object_info(review))
87
            ('reviews', [(review.user.username, get_object_info(review))
88
                         for review in o.review_set.all()]),
88
                         for review in o.reviews.all()]),
89
        ]
89
        ]
90
    elif isinstance(o, Review):
90
    elif isinstance(o, Review):
91
        info = [
91
        info = [
92
            ('user', o.user.username),
92
            ('user', o.user.username),
93
        ]
93
        ]
/trunk/reviewboard/diffviewer/models.py
Revision 1384 New Change
52
    name = models.CharField(_('name'), max_length=256, core=True)
52
    name = models.CharField(_('name'), max_length=256, core=True)
53
    revision = models.IntegerField(_("revision"), core=True)
53
    revision = models.IntegerField(_("revision"), core=True)
54
    timestamp = models.DateTimeField(_("timestamp"), default=datetime.now)
54
    timestamp = models.DateTimeField(_("timestamp"), default=datetime.now)
55
    history = models.ForeignKey('DiffSetHistory', null=True, core=True,
55
    history = models.ForeignKey('DiffSetHistory', null=True, core=True,
56
                                raw_id_admin=True,
56
                                raw_id_admin=True,
57
                                related_name="diffsets",
57
                                verbose_name=_("diff set history"))
58
                                verbose_name=_("diff set history"))
58
    repository = models.ForeignKey(Repository, verbose_name=_("repository"))
59
    repository = models.ForeignKey(Repository, related_name="diffsets",
60
                                   verbose_name=_("repository"))
59
    diffcompat = models.IntegerField(
61
    diffcompat = models.IntegerField(
60
        _('differ compatibility version'),
62
        _('differ compatibility version'),
61
        default=0,
63
        default=0,
62
        help_text=_("The diff generator compatibility version to use. "
64
        help_text=_("The diff generator compatibility version to use. "
63
                    "This can and should be ignored."))
65
                    "This can and should be ignored."))
69
        This will set an initial revision of 1 if this is the first diffset
71
        This will set an initial revision of 1 if this is the first diffset
70
        in the history, and will set it to on more than the most recent
72
        in the history, and will set it to on more than the most recent
71
        diffset otherwise.
73
        diffset otherwise.
72
        """
74
        """
73
        if self.revision == 0 and self.history != None:
75
        if self.revision == 0 and self.history != None:
74
            if self.history.diffset_set.count() == 0:
76
            if self.history.diffsets.count() == 0:
75
                # Start on revision 1. It's more human-grokable.
77
                # Start on revision 1. It's more human-grokable.
76
                self.revision = 1
78
                self.revision = 1
77
            else:
79
            else:
78
                self.revision = self.history.diffset_set.latest().revision + 1
80
                self.revision = self.history.diffsets.latest().revision + 1
79
81
80
        super(DiffSet, self).save()
82
        super(DiffSet, self).save()
81
83
82
    def __unicode__(self):
84
    def __unicode__(self):
83
        return u"[%s] %s r%s" % (self.id, self.name, self.revision)
85
        return u"[%s] %s r%s" % (self.id, self.name, self.revision)
99
    """
101
    """
100
    name = models.CharField(_('name'), max_length=256)
102
    name = models.CharField(_('name'), max_length=256)
101
    timestamp = models.DateTimeField(_("timestamp"), default=datetime.now)
103
    timestamp = models.DateTimeField(_("timestamp"), default=datetime.now)
102
104
103
    def __unicode__(self):
105
    def __unicode__(self):
104
        return u'Diff Set History (%s revisions)' % (self.diffset_set.count())
106
        return u'Diff Set History (%s revisions)' % self.diffsets.count()
105
107
106
    class Admin:
108
    class Admin:
107
        pass
109
        pass
/trunk/reviewboard/diffviewer/templatetags/difftags.py
Revision 1384 New Change
124
    """
124
    """
125
    Returns a list of revisions in the specified diffset history, indicating
125
    Returns a list of revisions in the specified diffset history, indicating
126
    which of the revisions is already selected, as determined by the current
126
    which of the revisions is already selected, as determined by the current
127
    diffset pair.
127
    diffset pair.
128
    """
128
    """
129
    for diffset in history.diffset_set.all():
129
    for diffset in history.diffsets.all():
130
        yield {
130
        yield {
131
            'revision': diffset.revision,
131
            'revision': diffset.revision,
132
            'is_current': current_pair[0] == diffset and
132
            'is_current': current_pair[0] == diffset and
133
                          current_pair[1] == None
133
                          current_pair[1] == None
134
        }
134
        }
135
135
136
136
137
@register.filter
137
@register.filter
138
def interdiff_link_list(history, current_pair):
138
def interdiff_link_list(history, current_pair):
139
    """
139
    """
140
    Returns a list of revisions in the specified diffset history based on
140
    Returns a list of revisions in the specified diffset history based on
141
    the passed interdiff pair.
141
    the passed interdiff pair.
142
    """
142
    """
143
    for diffset in history.diffset_set.all():
143
    for diffset in history.diffsets.all():
144
        if current_pair[0].revision < diffset.revision:
144
        if current_pair[0].revision < diffset.revision:
145
            path = "%s-%s" % (current_pair[0].revision, diffset.revision)
145
            path = "%s-%s" % (current_pair[0].revision, diffset.revision)
146
        else:
146
        else:
147
            path = "%s-%s" % (diffset.revision, current_pair[0].revision)
147
            path = "%s-%s" % (diffset.revision, current_pair[0].revision)
148
148
/trunk/reviewboard/reviews/datagrids.py
Revision 1384 New Change
76
76
77
    def render_data(self, review_request):
77
    def render_data(self, review_request):
78
        user = self.datagrid.request.user
78
        user = self.datagrid.request.user
79
        image_url = None
79
        image_url = None
80
        image_alt = None
80
        image_alt = None
81
        reviews = review_request.review_set.filter(user=user)
81
        reviews = review_request.reviews.filter(user=user)
82
82
83
        if reviews.filter(public=False).count() > 0:
83
        if reviews.filter(public=False).count() > 0:
84
            # Remind about drafts over finished comments
84
            # Remind about drafts over finished comments
85
            image_url = self.image_url
85
            image_url = self.image_url
86
            image_alt = _("Comments drafted")
86
            image_alt = _("Comments drafted")
133
        if not summary:
133
        if not summary:
134
            summary = '&nbsp;<i>No Summary</i>'
134
            summary = '&nbsp;<i>No Summary</i>'
135
135
136
        if review_request.submitter == self.datagrid.request.user:
136
        if review_request.submitter == self.datagrid.request.user:
137
            try:
137
            try:
138
                draft = review_request.reviewrequestdraft_set.get()
138
                draft = review_request.draft.get()
139
                summary = conditional_escape(draft.summary)
139
                return "<span class=\"draftlabel\">[Draft]</span> " + \
140
                return "<span class=\"draftlabel\">[Draft]</span> " + \
140
                       summary
141
                       summary
141
            except ReviewRequestDraft.DoesNotExist:
142
            except ReviewRequestDraft.DoesNotExist:
142
                pass
143
                pass
143
144
160
    """
161
    """
161
    def __init__(self, *args, **kwargs):
162
    def __init__(self, *args, **kwargs):
162
        Column.__init__(self, *args, **kwargs)
163
        Column.__init__(self, *args, **kwargs)
163
164
164
    def render_data(self, obj):
165
    def render_data(self, obj):
165
        return str(obj.reviewrequest_set.filter(public=True,
166
        return str(getattr(obj, self.field_name).filter(public=True,
166
                                                status='P').count())
167
                                                        status='P').count())
167
168
168
169
169
class ReviewCountColumn(Column):
170
class ReviewCountColumn(Column):
170
    """
171
    """
353
    A datagrid showing a list of submitters.
354
    A datagrid showing a list of submitters.
354
    """
355
    """
355
    username      = Column(_("Username"), link=True, sortable=True)
356
    username      = Column(_("Username"), link=True, sortable=True)
356
    fullname      = Column(_("Full Name"), field_name="get_full_name",
357
    fullname      = Column(_("Full Name"), field_name="get_full_name",
357
                           link=True, expand=True)
358
                           link=True, expand=True)
358
    pending_count = PendingCountColumn(_("Pending Reviews"), shrink=True)
359
    pending_count = PendingCountColumn(_("Pending Reviews"),
360
                                       field_name="directed_review_requests",
361
                                       shrink=True)
359
362
360
    def __init__(self, request):
363
    def __init__(self, request):
361
        DataGrid.__init__(self, request, User.objects.filter(is_active=True),
364
        DataGrid.__init__(self, request, User.objects.filter(is_active=True),
362
                          _("All submitters"))
365
                          _("All submitters"))
363
        self.default_sort = ["username"]
366
        self.default_sort = ["username"]
364
        self.profile_sort_field = 'sort_submitter_columns'
367
        self.profile_sort_field = 'sort_submitter_columns'
365
        self.profile_columns_field = 'submitter_columns'
368
        self.profile_columns_field = 'submitter_columns'
366
        self.default_columns = [
369
        self.default_columns = [
367
            "username", "fullname", "pending_reviews"
370
            "username", "fullname", "pending_count"
368
        ]
371
        ]
369
372
370
    @staticmethod
373
    @staticmethod
371
    def link_to_object(obj, value):
374
    def link_to_object(obj, value):
372
        return reverse("user", args=[obj.username])
375
        return reverse("user", args=[obj.username])
378
    """
381
    """
379
    star          = StarColumn()
382
    star          = StarColumn()
380
    name          = Column(_("Group ID"), link=True, sortable=True)
383
    name          = Column(_("Group ID"), link=True, sortable=True)
381
    displayname   = Column(_("Group Name"), field_name="display_name",
384
    displayname   = Column(_("Group Name"), field_name="display_name",
382
                           link=True, expand=True)
385
                           link=True, expand=True)
383
    pending_count = PendingCountColumn(_("Pending Reviews"), shrink=True)
386
    pending_count = PendingCountColumn(_("Pending Reviews"),
387
                                       field_name="review_requests",
388
                                       shrink=True)
384
389
385
    def __init__(self, request, title=_("All groups")):
390
    def __init__(self, request, title=_("All groups")):
386
        DataGrid.__init__(self, request, Group.objects.all(), title)
391
        DataGrid.__init__(self, request, Group.objects.all(), title)
387
        self.profile_sort_field = 'sort_group_columns'
392
        self.profile_sort_field = 'sort_group_columns'
388
        self.profile_columns_field = 'group_columns'
393
        self.profile_columns_field = 'group_columns'
389
        self.default_sort = ["name"]
394
        self.default_sort = ["name"]
390
        self.default_columns = [
395
        self.default_columns = [
391
            "star", "name", "displayname", "pending_reviews"
396
            "star", "name", "displayname", "pending_count"
392
        ]
397
        ]
393
398
394
399
395
class WatchedGroupDataGrid(GroupDataGrid):
400
class WatchedGroupDataGrid(GroupDataGrid):
396
    """
401
    """
/trunk/reviewboard/reviews/email.py
Revision 1384 New Change
113
    Returns a list of all people who have been involved in a discussion on
113
    Returns a list of all people who have been involved in a discussion on
114
    a review request.
114
    a review request.
115
    """
115
    """
116
    # See the comment in harvest_people_from_review for this list
116
    # See the comment in harvest_people_from_review for this list
117
    # comprehension.
117
    # comprehension.
118
    return [u for review in review_request.review_set.all()
118
    return [u for review in review_request.reviews.all()
119
              for u in harvest_people_from_review(review)]
119
              for u in harvest_people_from_review(review)]
120
120
121
121
122
def mail_review_request(user, review_request, changes=None):
122
def mail_review_request(user, review_request, changes=None):
123
    """Send an e-mail representing the supplied review request.
123
    """Send an e-mail representing the supplied review request.
/trunk/reviewboard/reviews/errors.py
New File
1
class InvalidChangeNumberError(Exception):
2
    def __init__(self):
3
        Exception.__init__(self, None)
4
5
6
class ChangeNumberInUseError(Exception):
7
    def __init__(self, review_request=None):
8
        Exception.__init__(self, None)
9
        self.review_request = review_request
10
11
12
class ChangeSetError(ValueError):
13
    pass
14
15
16
class OwnershipError(ValueError):
17
    pass
/trunk/reviewboard/reviews/forms.py
Revision 1384 New Change
1
import re
1
import re
2
2
3
from django import newforms as forms
3
from django import newforms as forms
4
from django.utils.translation import ugettext as _
4
from django.utils.translation import ugettext as _
5
from PIL import Image
5
from PIL import Image
6
6
7
from reviewboard.diffviewer.forms import UploadDiffForm, EmptyDiffError
7
from reviewboard.diffviewer.forms import UploadDiffForm, EmptyDiffError
8
from reviewboard.reviews.errors import ChangeNumberInUseError, \
9
                                       ChangeSetError, \
10
                                       OwnershipError
8
from reviewboard.reviews.models import ReviewRequest, \
11
from reviewboard.reviews.models import ReviewRequest, \
9
                                       ReviewRequestDraft, Screenshot, \
12
                                       ReviewRequestDraft, Screenshot
10
                                       ChangeNumberInUseError
11
from reviewboard.scmtools.models import Repository
13
from reviewboard.scmtools.models import Repository
12
14
13
15
14
class ChangeSetError(ValueError):
15
    pass
16
17
18
class OwnershipError(ValueError):
19
    pass
20
21
22
class NewReviewRequestForm(forms.Form):
16
class NewReviewRequestForm(forms.Form):
23
    """
17
    """
24
    A form that handles creationg of new review requests. These take
18
    A form that handles creationg of new review requests. These take
25
    information on the diffs, the repository the diffs are against, and
19
    information on the diffs, the repository the diffs are against, and
26
    optionally a changelist number (for use in certain repository types
20
    optionally a changelist number (for use in certain repository types
/trunk/reviewboard/reviews/managers.py
New File
1
from django.contrib.auth.models import User
2
from django.db.models import Q
3
4
from djblets.util.db import ConcurrencyManager
5
6
from reviewboard.diffviewer.models import DiffSetHistory