def _summarize_review_request(self, request, review_request, commit=None): """Returns a dict summarizing a ReviewRequest object. Example return value for a child request (a parent looks the same but without a 'commit' key): { 'commit': 'ece2029d013af68f9f32aa0a6199fcb2201d5aae', 'id': 3, 'issue_open_count': 0, 'last_updated': '2015-04-13T18:58:25Z', 'links': { 'self': { 'href': 'http://127.0.0.1:50936/api/extensions/mozreview.extension.MozReviewExtension/summary/3/', 'method': 'GET' } }, 'reviewers': [ 'jrandom' ], 'reviewers_status': { 'jrandom': { 'ship_it': True } }, 'status': 'pending', 'submitter': 'mcote', 'summary': 'Bug 1 - Update README.md.' } """ reviewers = list(review_request.target_people.all()) d = {} for field in ('id', 'summary', 'last_updated', 'issue_open_count'): d[field] = getattr(review_request, field) # TODO: 'submitter' and 'submitter_bmo_id' should be combined into one # attribute, likewise with 'reviewers' and 'reviewers_bmo_ids'. See # bug 1164756. d['submitter'] = review_request.submitter.username d['submitter_bmo_id'] = BugzillaUserMap.objects.get( user_id=review_request.submitter.id).bugzilla_user_id d['status'] = status_to_string(review_request.status) d['reviewers'] = [reviewer.username for reviewer in reviewers] # If we have a commit (i.e. we are on a child) add reviewer_status. if commit: d['reviewers_status'] = get_reviewers_status(review_request, reviewers) d['reviewers_bmo_ids'] = [bzuser.bugzilla_user_id for bzuser in BugzillaUserMap.objects.filter(user_id__in=[ reviewer.id for reviewer in reviewers])] d['links'] = self.get_links(obj=review_request, request=request) if commit: d['commit'] = commit return d
def get_review_request_data(rr): """Obtain a dictionary containing review request metadata. The dict consists of plain types (as opposed to ReviewBoard types). Some values may be unicode, not str. """ rd = { 'status': status_to_string(rr.status), } thing = rr try: thing = rr.draft.get() rd['public'] = False except ReviewRequestDraft.DoesNotExist: rd['public'] = rr.public rd['reviewers'] = [p.username for p in thing.target_people.all()] return rd
def serialize_status_field(self, obj, **kwargs): return status_to_string(obj.status)
def review_detail(request, review_request_id, local_site_name=None, template_name="reviews/review_detail.html"): """ Main view for review requests. This covers the review request information and all the reviews on it. """ # If there's a local_site passed in the URL, we want to look up the review # request based on the local_id instead of the pk. This allows each # local_site configured to have its own review request ID namespace # starting from 1. review_request, response = \ _find_review_request(request, review_request_id, local_site_name) if not review_request: return response reviews = review_request.get_public_reviews() review = review_request.get_pending_review(request.user) review_timestamp = 0 last_visited = 0 starred = False if request.user.is_authenticated(): # If the review request is public and pending review and if the user # is logged in, mark that they've visited this review request. if review_request.public and review_request.status == "P": visited, visited_is_new = ReviewRequestVisit.objects.get_or_create( user=request.user, review_request=review_request) last_visited = visited.timestamp visited.timestamp = datetime.now() visited.save() profile, profile_is_new = Profile.objects.get_or_create(user=request.user) starred = review_request in profile.starred_review_requests.all() # Unlike review above, this covers replies as well. try: last_draft_review = Review.objects.filter( review_request=review_request, user=request.user, public=False).latest() review_timestamp = last_draft_review.timestamp except Review.DoesNotExist: pass draft = review_request.get_draft(request.user) # Find out if we can bail early. Generate an ETag for this. last_activity_time, updated_object = review_request.get_last_activity() if draft: draft_timestamp = draft.last_updated else: draft_timestamp = "" etag = "%s:%s:%s:%s:%s:%s" % (request.user, last_activity_time, draft_timestamp, review_timestamp, int(starred), settings.AJAX_SERIAL) if etag_if_none_match(request, etag): return HttpResponseNotModified() changedescs = review_request.changedescs.filter(public=True) latest_changedesc = None try: latest_changedesc = changedescs.latest() latest_timestamp = latest_changedesc.timestamp except ChangeDescription.DoesNotExist: latest_timestamp = None entries = [] for temp_review in reviews: temp_review.ordered_comments = \ temp_review.comments.order_by('filediff', 'first_line') state = '' # Mark as collapsed if the review is older than the latest change if latest_timestamp and temp_review.timestamp < latest_timestamp: state = 'collapsed' try: latest_reply = temp_review.public_replies().latest('timestamp').timestamp except Review.DoesNotExist: latest_reply = None # Mark as expanded if there is a reply newer than last_visited if latest_reply and last_visited and last_visited < latest_reply: state = '' entries.append({ 'review': temp_review, 'timestamp': temp_review.timestamp, 'class': state, }) for changedesc in changedescs: fields_changed = [] for name, info in changedesc.fields_changed.items(): multiline = False if 'added' in info or 'removed' in info: change_type = 'add_remove' # We don't hard-code URLs in the bug info, since the # tracker may move, but we can do it here. if (name == "bugs_closed" and review_request.repository.bug_tracker): bug_url = review_request.repository.bug_tracker for field in info: for i, buginfo in enumerate(info[field]): try: full_bug_url = bug_url % buginfo[0] info[field][i] = (buginfo[0], full_bug_url) except TypeError: logging.warning("Invalid bugtracker url format") elif 'old' in info or 'new' in info: change_type = 'changed' multiline = (name == "description" or name == "testing_done") # Branch text is allowed to have entities, so mark it safe. if name == "branch": if 'old' in info: info['old'][0] = mark_safe(info['old'][0]) if 'new' in info: info['new'][0] = mark_safe(info['new'][0]) # Make status human readable. if name == 'status': if 'old' in info: info['old'][0] = status_to_string(info['old'][0]) if 'new' in info: info['new'][0] = status_to_string(info['new'][0]) elif name == "screenshot_captions": change_type = 'screenshot_captions' elif name == "file_captions": change_type = 'file_captions' else: # No clue what this is. Bail. continue fields_changed.append({ 'title': fields_changed_name_map.get(name, name), 'multiline': multiline, 'info': info, 'type': change_type, }) # Expand the latest review change state = '' # Mark as collapsed if the change is older than a newer change if latest_timestamp and changedesc.timestamp < latest_timestamp: state = 'collapsed' entries.append({ 'changeinfo': fields_changed, 'changedesc': changedesc, 'timestamp': changedesc.timestamp, 'class': state, }) entries.sort(key=lambda item: item['timestamp']) response = render_to_response( template_name, RequestContext(request, _make_review_request_context(review_request, { 'draft': draft, 'review_request_details': draft or review_request, 'entries': entries, 'last_activity_time': last_activity_time, 'review': review, 'request': request, 'latest_changedesc': latest_changedesc, 'PRE_CREATION': PRE_CREATION, }))) set_etag(response, etag) return response
def review_detail(request, review_request_id, local_site_name=None, template_name="reviews/review_detail.html"): """ Main view for review requests. This covers the review request information and all the reviews on it. """ # If there's a local_site passed in the URL, we want to look up the review # request based on the local_id instead of the pk. This allows each # local_site configured to have its own review request ID namespace # starting from 1. review_request, response = \ _find_review_request(request, review_request_id, local_site_name) if not review_request: return response reviews = review_request.get_public_reviews() review = review_request.get_pending_review(request.user) review_timestamp = 0 last_visited = 0 starred = False if request.user.is_authenticated(): # If the review request is public and pending review and if the user # is logged in, mark that they've visited this review request. if review_request.public and review_request.status == "P": visited, visited_is_new = ReviewRequestVisit.objects.get_or_create( user=request.user, review_request=review_request) last_visited = visited.timestamp visited.timestamp = datetime.now() visited.save() profile, profile_is_new = Profile.objects.get_or_create( user=request.user) starred = review_request in profile.starred_review_requests.all() # Unlike review above, this covers replies as well. try: last_draft_review = Review.objects.filter( review_request=review_request, user=request.user, public=False).latest() review_timestamp = last_draft_review.timestamp except Review.DoesNotExist: pass draft = review_request.get_draft(request.user) # Find out if we can bail early. Generate an ETag for this. last_activity_time, updated_object = review_request.get_last_activity() if draft: draft_timestamp = draft.last_updated else: draft_timestamp = "" etag = "%s:%s:%s:%s:%s:%s" % (request.user, last_activity_time, draft_timestamp, review_timestamp, int(starred), settings.AJAX_SERIAL) if etag_if_none_match(request, etag): return HttpResponseNotModified() changedescs = review_request.changedescs.filter(public=True) latest_changedesc = None try: latest_changedesc = changedescs.latest() latest_timestamp = latest_changedesc.timestamp except ChangeDescription.DoesNotExist: latest_timestamp = None entries = [] for temp_review in reviews: temp_review.ordered_comments = \ temp_review.comments.order_by('filediff', 'first_line') state = '' # Mark as collapsed if the review is older than the latest change if latest_timestamp and temp_review.timestamp < latest_timestamp: state = 'collapsed' try: latest_reply = temp_review.public_replies().latest( 'timestamp').timestamp except Review.DoesNotExist: latest_reply = None # Mark as expanded if there is a reply newer than last_visited if latest_reply and last_visited and last_visited < latest_reply: state = '' entries.append({ 'review': temp_review, 'timestamp': temp_review.timestamp, 'class': state, }) for changedesc in changedescs: fields_changed = [] for name, info in changedesc.fields_changed.items(): multiline = False if 'added' in info or 'removed' in info: change_type = 'add_remove' # We don't hard-code URLs in the bug info, since the # tracker may move, but we can do it here. if (name == "bugs_closed" and review_request.repository.bug_tracker): bug_url = review_request.repository.bug_tracker for field in info: for i, buginfo in enumerate(info[field]): try: full_bug_url = bug_url % buginfo[0] info[field][i] = (buginfo[0], full_bug_url) except TypeError: logging.warning( "Invalid bugtracker url format") elif 'old' in info or 'new' in info: change_type = 'changed' multiline = (name == "description" or name == "testing_done") # Branch text is allowed to have entities, so mark it safe. if name == "branch": if 'old' in info: info['old'][0] = mark_safe(info['old'][0]) if 'new' in info: info['new'][0] = mark_safe(info['new'][0]) # Make status human readable. if name == 'status': if 'old' in info: info['old'][0] = status_to_string(info['old'][0]) if 'new' in info: info['new'][0] = status_to_string(info['new'][0]) elif name == "screenshot_captions": change_type = 'screenshot_captions' elif name == "file_captions": change_type = 'file_captions' else: # No clue what this is. Bail. continue fields_changed.append({ 'title': fields_changed_name_map.get(name, name), 'multiline': multiline, 'info': info, 'type': change_type, }) # Expand the latest review change state = '' # Mark as collapsed if the change is older than a newer change if latest_timestamp and changedesc.timestamp < latest_timestamp: state = 'collapsed' entries.append({ 'changeinfo': fields_changed, 'changedesc': changedesc, 'timestamp': changedesc.timestamp, 'class': state, }) entries.sort(key=lambda item: item['timestamp']) close_description = '' if latest_changedesc and 'status' in latest_changedesc.fields_changed: status = latest_changedesc.fields_changed['status']['new'][0] if status in (ReviewRequest.DISCARDED, ReviewRequest.SUBMITTED): close_description = latest_changedesc.text issues = {'total': 0, 'open': 0, 'resolved': 0, 'dropped': 0} for entry in entries: if 'review' in entry: for comment in entry['review'].get_all_comments(issue_opened=True): issues['total'] += 1 issues[BaseComment.issue_status_to_string( comment.issue_status)] += 1 response = render_to_response( template_name, RequestContext( request, _make_review_request_context( review_request, { 'draft': draft, 'detail_hooks': ReviewRequestDetailHook.hooks, 'review_request_details': draft or review_request, 'entries': entries, 'last_activity_time': last_activity_time, 'review': review, 'request': request, 'latest_changedesc': latest_changedesc, 'close_description': close_description, 'PRE_CREATION': PRE_CREATION, 'issues': issues, }))) set_etag(response, etag) return response
def _summarize_review_request(self, request, review_request, commit=None): """Returns a dict summarizing a ReviewRequest object. Example return value for a child request (a parent looks the same but without a 'commit' key): { 'commit': 'ece2029d013af68f9f32aa0a6199fcb2201d5aae', 'diff': { 'insert': 15, 'delete': 20 }, 'has_draft': False, 'id': 3, 'issue_open_count': 0, 'last_updated': '2015-04-13T18:58:25Z', 'links': { 'self': { 'href': 'http://127.0.0.1:50936/api/extensions/mozreview.extension.MozReviewExtension/summary/3/', 'method': 'GET' } }, 'reviewers': [ 'jrandom' ], 'reviewers_status': { 'jrandom': { 'ship_it': True } }, 'status': 'pending', 'submitter': 'mcote', 'summary': 'Bug 1 - Update README.md.' } """ reviewers = list(review_request.target_people.all()) d = {} for field in ('id', 'summary', 'last_updated', 'issue_open_count'): d[field] = getattr(review_request, field) # TODO: 'submitter' and 'submitter_bmo_id' should be combined into one # attribute, likewise with 'reviewers' and 'reviewers_bmo_ids'. See # bug 1164756. d['submitter'] = review_request.submitter.username d['submitter_bmo_id'] = BugzillaUserMap.objects.get( user_id=review_request.submitter.id).bugzilla_user_id d['status'] = status_to_string(review_request.status) d['reviewers'] = [reviewer.username for reviewer in reviewers] d['diff'] = get_diffstats(review_request, request.user) # If we have a commit (i.e. we are on a child) add reviewer_status. if commit: d['reviewers_status'] = get_reviewers_status(review_request, reviewers) d['reviewers_bmo_ids'] = [bzuser.bugzilla_user_id for bzuser in BugzillaUserMap.objects.filter(user_id__in=[ reviewer.id for reviewer in reviewers])] d['links'] = self.get_links(obj=review_request, request=request) if commit: d['commit'] = commit d['has_draft'] = review_request.get_draft() is not None return d
def review_detail(request, review_request_id, local_site_name=None, template_name="reviews/review_detail.html"): """ Main view for review requests. This covers the review request information and all the reviews on it. """ # If there's a local_site passed in the URL, we want to look up the review # request based on the local_id instead of the pk. This allows each # local_site configured to have its own review request ID namespace # starting from 1. review_request, response = _find_review_request(request, review_request_id, local_site_name) if not review_request: return response reviews = review_request.get_public_reviews() review = review_request.get_pending_review(request.user) review_timestamp = 0 last_visited = 0 starred = False if request.user.is_authenticated(): # If the review request is public and pending review and if the user # is logged in, mark that they've visited this review request. if review_request.public and review_request.status == "P": visited, visited_is_new = ReviewRequestVisit.objects.get_or_create( user=request.user, review_request=review_request ) last_visited = visited.timestamp visited.timestamp = datetime.now() visited.save() profile, profile_is_new = Profile.objects.get_or_create(user=request.user) starred = review_request in profile.starred_review_requests.all() # Unlike review above, this covers replies as well. try: last_draft_review = Review.objects.filter( review_request=review_request, user=request.user, public=False ).latest() review_timestamp = last_draft_review.timestamp except Review.DoesNotExist: pass draft = review_request.get_draft(request.user) # Find out if we can bail early. Generate an ETag for this. last_activity_time, updated_object = review_request.get_last_activity() if draft: draft_timestamp = draft.last_updated else: draft_timestamp = "" etag = "%s:%s:%s:%s:%s:%s" % ( request.user, last_activity_time, draft_timestamp, review_timestamp, int(starred), settings.AJAX_SERIAL, ) if etag_if_none_match(request, etag): return HttpResponseNotModified() changedescs = review_request.changedescs.filter(public=True) latest_changedesc = None try: latest_changedesc = changedescs.latest() latest_timestamp = latest_changedesc.timestamp except ChangeDescription.DoesNotExist: latest_timestamp = None entries = [] for temp_review in reviews: temp_review.ordered_comments = temp_review.comments.order_by("filediff", "first_line") state = "" # Mark as collapsed if the review is older than the latest change if latest_timestamp and temp_review.timestamp < latest_timestamp: state = "collapsed" try: latest_reply = temp_review.public_replies().latest("timestamp").timestamp except Review.DoesNotExist: latest_reply = None # Mark as expanded if there is a reply newer than last_visited if latest_reply and last_visited and last_visited < latest_reply: state = "" entries.append({"review": temp_review, "timestamp": temp_review.timestamp, "class": state}) for changedesc in changedescs: fields_changed = [] for name, info in changedesc.fields_changed.items(): multiline = False if "added" in info or "removed" in info: change_type = "add_remove" # We don't hard-code URLs in the bug info, since the # tracker may move, but we can do it here. if name == "bugs_closed" and review_request.repository.bug_tracker: bug_url = review_request.repository.bug_tracker for field in info: for i, buginfo in enumerate(info[field]): try: full_bug_url = bug_url % buginfo[0] info[field][i] = (buginfo[0], full_bug_url) except TypeError: logging.warning("Invalid bugtracker url format") elif "old" in info or "new" in info: change_type = "changed" multiline = name == "description" or name == "testing_done" # Branch text is allowed to have entities, so mark it safe. if name == "branch": if "old" in info: info["old"][0] = mark_safe(info["old"][0]) if "new" in info: info["new"][0] = mark_safe(info["new"][0]) # Make status human readable. if name == "status": if "old" in info: info["old"][0] = status_to_string(info["old"][0]) if "new" in info: info["new"][0] = status_to_string(info["new"][0]) elif name == "screenshot_captions": change_type = "screenshot_captions" elif name == "file_captions": change_type = "file_captions" else: # No clue what this is. Bail. continue fields_changed.append( { "title": fields_changed_name_map.get(name, name), "multiline": multiline, "info": info, "type": change_type, } ) # Expand the latest review change state = "" # Mark as collapsed if the change is older than a newer change if latest_timestamp and changedesc.timestamp < latest_timestamp: state = "collapsed" entries.append( {"changeinfo": fields_changed, "changedesc": changedesc, "timestamp": changedesc.timestamp, "class": state} ) entries.sort(key=lambda item: item["timestamp"]) close_description = "" if latest_changedesc and "status" in latest_changedesc.fields_changed: status = latest_changedesc.fields_changed["status"]["new"][0] if status in (ReviewRequest.DISCARDED, ReviewRequest.SUBMITTED): close_description = latest_changedesc.text response = render_to_response( template_name, RequestContext( request, _make_review_request_context( review_request, { "draft": draft, "detail_hooks": ReviewRequestDetailHook.hooks, "review_request_details": draft or review_request, "entries": entries, "last_activity_time": last_activity_time, "review": review, "request": request, "latest_changedesc": latest_changedesc, "close_description": close_description, "PRE_CREATION": PRE_CREATION, }, ), ), ) set_etag(response, etag) return response