def testFindFieldDef_Normal(self): config = tracker_bizobj.MakeDefaultProjectIssueConfig(789) fd = tracker_pb2.FieldDef(field_name='EstDays') config.field_defs = [fd] self.assertEqual(fd, tracker_bizobj.FindFieldDef('EstDays', config)) self.assertEqual(fd, tracker_bizobj.FindFieldDef('ESTDAYS', config)) self.assertIsNone(tracker_bizobj.FindFieldDef('Unknown', config))
def testProcessFormData_Delete(self): post_data = fake.PostData(name=['CPU'], deletefield=['Submit']) url = self.servlet.ProcessFormData(self.mr, post_data) self.assertTrue('/adminLabels?deleted=1&' in url) fd = tracker_bizobj.FindFieldDef('CPU', self.config) self.assertEqual('CPU', fd.field_name) self.assertTrue(fd.is_deleted)
def _ParseChoicesIntoWellKnownLabels( choices_text, field_name, config, field_type_str): """Parse a field's possible choices and integrate them into the config. Args: choices_text: string with one label and optional docstring per line. field_name: string name of the field definition being edited. config: ProjectIssueConfig PB of the current project. field_type_str: string name of the new field's type. None if an existing field is being updated Returns: A revised list of labels that can be used to update the config. """ fd = tracker_bizobj.FindFieldDef(field_name, config) matches = framework_constants.IDENTIFIER_DOCSTRING_RE.findall(choices_text) maskingFieldNames = [] # wkls should only be masked by the field if it is an enum_type. if (field_type_str == 'enum_type') or ( fd and fd.field_type is tracker_pb2.FieldTypes.ENUM_TYPE): maskingFieldNames.append(field_name.lower()) new_labels = [ ('%s-%s' % (field_name, label), choice_docstring.strip(), False) for label, choice_docstring in matches] kept_labels = [ (wkl.label, wkl.label_docstring, wkl.deprecated) for wkl in config.well_known_labels if not tracker_bizobj.LabelIsMaskedByField( wkl.label, maskingFieldNames)] revised_labels = kept_labels + new_labels return revised_labels
def testProcessEditField_Reject(self): post_data = fake.PostData(name=['CPU'], field_type=['INT_TYPE'], min_value=['4'], max_value=['1'], admin_names=['']) self.mox.StubOutWithMock(self.servlet, 'PleaseCorrect') self.servlet.PleaseCorrect(self.mr, field_def=mox.IgnoreArg(), initial_applicable_type='', initial_choices='', initial_admins='', initial_approvers='') self.mox.ReplayAll() url = self.servlet._ProcessEditField(self.mr, post_data, self.config, self.fd) self.assertEqual('Minimum value must be less than maximum.', self.mr.errors.min_value) self.assertIsNone(url) fd = tracker_bizobj.FindFieldDef('CPU', self.config) self.assertIsNone(fd.min_value) self.assertIsNone(fd.max_value)
def testProcessFormData(self): post_data = fake.PostData(name=['somefield'], field_type=['INT_TYPE'], min_value=['1'], max_value=['99'], notify_on=['any_comment'], importance=['required'], is_multivalued=['Yes'], docstring=['It is just some field'], applicable_type=['Defect'], date_action=['no_action'], admin_names=['']) url = self.servlet.ProcessFormData(self.mr, post_data) self.assertTrue('/adminLabels?saved=1&' in url) config = self.services.config.GetProjectConfig(self.mr.cnxn, self.mr.project_id) fd = tracker_bizobj.FindFieldDef('somefield', config) self.assertEqual('somefield', fd.field_name) self.assertEqual(tracker_pb2.FieldTypes.INT_TYPE, fd.field_type) self.assertEqual(1, fd.min_value) self.assertEqual(99, fd.max_value) self.assertEqual(tracker_pb2.NotifyTriggers.ANY_COMMENT, fd.notify_on) self.assertTrue(fd.is_required) self.assertFalse(fd.is_niche) self.assertTrue(fd.is_multivalued) self.assertEqual('It is just some field', fd.docstring) self.assertEqual('Defect', fd.applicable_type) self.assertEqual('', fd.applicable_predicate) self.assertEqual([], fd.admin_ids)
def testProcessEditField_Normal(self): post_data = fake.PostData(name=['CPU'], field_type=['INT_TYPE'], min_value=['2'], admin_names=['']) self.servlet._ProcessEditField(self.mr, post_data, self.config, self.fd) fd = tracker_bizobj.FindFieldDef('CPU', self.config) self.assertEqual('CPU', fd.field_name) self.assertEqual(2, fd.min_value)
def _GetFieldDef(self, mr): """Get the config and field definition to be viewed or edited.""" # TODO(jrobbins): since so many requests get the config object, and # it is usually cached in RAM, just always get it and include it # in the MonorailRequest, mr. config = self.services.config.GetProjectConfig( mr.cnxn, mr.project_id) field_def = tracker_bizobj.FindFieldDef(mr.field_name, config) if not field_def: self.abort(404, 'custom field not found') return config, field_def
def testProcessFormData_Cancel(self): post_data = fake.PostData(name=['CPU'], cancel=['Submit'], max_value=['200']) url = self.servlet.ProcessFormData(self.mr, post_data) logging.info(url) self.assertTrue('/adminLabels?ts=' in url) config = self.services.config.GetProjectConfig(self.mr.cnxn, self.mr.project_id) fd = tracker_bizobj.FindFieldDef('CPU', config) self.assertIsNone(fd.max_value) self.assertIsNone(fd.min_value)
def __init__(self, art, col=None, config=None, **_kw): explicit_values = [] for av in art.approval_values: fd = tracker_bizobj.FindFieldDef(col, config) ad = tracker_bizobj.FindApprovalDef(col, config) if not (ad and fd): logging.warn('Issue ID %r has undefined field value %r', art.issue_id, av) elif av.approval_id == fd.field_id: explicit_values.append(av.status.name) break TableCell.__init__(self, CELL_TYPE_ATTR, explicit_values)
def ChooseCellFactory(col, cell_factories, config): """Return the CellFactory to use for the given column.""" if col in cell_factories: return cell_factories[col] if '/' in col: return CompositeTableCell(col.split('/'), cell_factories) fd = tracker_bizobj.FindFieldDef(col, config) if fd: return _CUSTOM_FIELD_CELL_FACTORIES[fd.field_type] return TableCellKeyLabels
def UndoConversion(self, mr): with work_env.WorkEnv(mr, self.services) as we: pipeline = we.ListIssues('Type=FLT-Launch FLT=Conversion', ['chromium'], mr.auth.user_id, CONVERT_NUM, CONVERT_START, [], 2, GROUP_BY_SPEC, SORT_SPEC, False) project = self.services.project.GetProjectByName(mr.cnxn, 'chromium') config = self.services.config.GetProjectConfig(mr.cnxn, project.project_id) pm_id = tracker_bizobj.FindFieldDef('PM', config).field_id tl_id = tracker_bizobj.FindFieldDef('TL', config).field_id te_id = tracker_bizobj.FindFieldDef('TE', config).field_id ux_id = tracker_bizobj.FindFieldDef('UX', config).field_id for possible_stale_issue in pipeline.visible_results: issue = self.services.issue.GetIssue(mr.cnxn, possible_stale_issue.issue_id, use_cache=False) issue.approval_values = [] issue.phases = [] issue.field_values = [ fv for fv in issue.field_values if fv.phase_id is None ] issue.field_values = [ fv for fv in issue.field_values if fv.field_id not in [pm_id, tl_id, te_id, ux_id] ] issue.labels.remove('Type-FLT-Launch') issue.labels.remove('FLT-Conversion') issue.labels.append('Type-Launch') self.services.issue._UpdateIssuesApprovals(mr.cnxn, issue) self.services.issue.UpdateIssue(mr.cnxn, issue) return { 'deleting': [issue.local_id for issue in pipeline.visible_results], 'num': len(pipeline.visible_results), }
def SortGridHeadings(col_name, heading_value_list, users_by_id, config, asc_accessors): """Sort the grid headings according to well-known status and label order. Args: col_name: String column name that is used on that grid axis. heading_value_list: List of grid row or column heading values. users_by_id: Dict mapping user_ids to UserViews. config: ProjectIssueConfig PB for the current project. asc_accessors: Dict (col_name -> function()) for special columns. Returns: The same heading values, but sorted in a logical order. """ decorated_list = [] fd = tracker_bizobj.FindFieldDef(col_name, config) if fd and fd.field_type != tracker_pb2.FieldTypes.ENUM_TYPE: # Handle fields. for value in heading_value_list: field_value = tracker_bizobj.GetFieldValueWithRawValue( fd.field_type, None, users_by_id, value) decorated_list.append([field_value, field_value]) elif col_name == 'status': wk_statuses = [ wks.status.lower() for wks in config.well_known_statuses ] decorated_list = [(_WKSortingValue(value.lower(), wk_statuses), value) for value in heading_value_list] elif col_name in asc_accessors: # Special cols still sort alphabetically. decorated_list = [(value, value) for value in heading_value_list] else: # Anything else is assumed to be a label prefix col_name_dash = col_name + '-' wk_labels = [] for wkl in config.well_known_labels: lab_lower = wkl.label.lower() if lab_lower.startswith(col_name_dash): wk_labels.append(lab_lower.split('-', 1)[-1]) decorated_list = [(_WKSortingValue(value.lower(), wk_labels), value) for value in heading_value_list] decorated_list.sort() result = [decorated_tuple[1] for decorated_tuple in decorated_list] logging.info('Headers for %s are: %r', col_name, result) return result
def __init__(self, art, col=None, config=None, users_by_id=None, **_kw): explicit_values = [] approval_name = col[:-len(tracker_constants.APPROVER_COL_SUFFIX)] for av in art.approval_values: fd = tracker_bizobj.FindFieldDef(approval_name, config) ad = tracker_bizobj.FindApprovalDef(approval_name, config) if not (ad and fd): logging.warn('Issue ID %r has undefined field value %r', art.issue_id, av) elif av.approval_id == fd.field_id: explicit_values = [ users_by_id.get(approver_id).display_name for approver_id in av.approver_ids if users_by_id.get(approver_id) ] break TableCell.__init__(self, CELL_TYPE_ATTR, explicit_values)
def testProcessFormData_Edit(self): post_data = fake.PostData(name=['CPU'], field_type=['INT_TYPE'], min_value=['2'], max_value=['98'], notify_on=['never'], is_required=[], is_multivalued=[], docstring=['It is just some field'], applicable_type=['Defect'], admin_names=['']) url = self.servlet.ProcessFormData(self.mr, post_data) self.assertTrue('/fields/detail?field=CPU&saved=1&' in url) config = self.services.config.GetProjectConfig(self.mr.cnxn, self.mr.project_id) fd = tracker_bizobj.FindFieldDef('CPU', config) self.assertEqual('CPU', fd.field_name) self.assertEqual(2, fd.min_value) self.assertEqual(98, fd.max_value)
def BulkUpdateApprovals(self, mc, request): """Update multiple issues' approval and return the updated issue_refs.""" if not request.issue_refs: raise exceptions.InputException('Param `issue_refs` empty.') project, issue_ids, config = self._GetProjectIssueIDsAndConfig( mc, request.issue_refs) approval_fd = tracker_bizobj.FindFieldDef(request.field_ref.field_name, config) if not approval_fd: raise exceptions.NoSuchFieldDefException() if request.HasField('approval_delta'): approval_delta = converters.IngestApprovalDelta( mc.cnxn, self.services.user, request.approval_delta, mc.auth.user_id, config) else: approval_delta = tracker_pb2.ApprovalDelta() # No bulk adding approval attachments for now. with work_env.WorkEnv(mc, self.services, phase='updating approvals') as we: updated_issue_ids = we.BulkUpdateIssueApprovals( issue_ids, approval_fd.field_id, project, approval_delta, request.comment_content, send_email=request.send_email) with mc.profiler.Phase('converting to response objects'): issue_ref_pairs = we.GetIssueRefs(updated_issue_ids) issue_refs = [ converters.ConvertIssueRef(pair) for pair in issue_ref_pairs.values() ] response = issues_pb2.BulkUpdateApprovalsResponse( issue_refs=issue_refs) return response
def UpdateApproval(self, mc, request): """Update an approval and return the updated approval in a reponse proto.""" project, issue, config = self._GetProjectIssueAndConfig( mc, request.issue_ref, use_cache=False) approval_fd = tracker_bizobj.FindFieldDef(request.field_ref.field_name, config) if not approval_fd: raise exceptions.NoSuchFieldDefException() if request.HasField('approval_delta'): approval_delta = converters.IngestApprovalDelta( mc.cnxn, self.services.user, request.approval_delta, mc.auth.user_id, config) else: approval_delta = tracker_pb2.ApprovalDelta() attachments = converters.IngestAttachmentUploads(request.uploads) with work_env.WorkEnv(mc, self.services) as we: av, _comment = we.UpdateIssueApproval( issue.issue_id, approval_fd.field_id, approval_delta, request.comment_content, request.is_description, attachments=attachments, send_email=request.send_email, kept_attachments=list(request.kept_attachments)) with mc.profiler.Phase('converting to response objects'): users_by_id = framework_views.MakeAllUserViews( mc.cnxn, self.services.user, av.approver_ids, [av.setter_id]) framework_views.RevealAllEmailsToMembers(mc.auth, project, users_by_id) response = issues_pb2.UpdateApprovalResponse() response.approval.CopyFrom( converters.ConvertApproval(av, users_by_id, config)) return response
def ChooseCellFactory(col, cell_factories, config): """Return the CellFactory to use for the given column.""" if col in cell_factories: return cell_factories[col] if '/' in col: return CompositeColTableCell(col.split('/'), cell_factories, config) is_approver_col = False possible_field_name = col if col.endswith(tracker_constants.APPROVER_COL_SUFFIX): possible_field_name = col[:-len(tracker_constants.APPROVER_COL_SUFFIX)] is_approver_col = True # Check if col represents a phase field value in the form <phase>.<field> elif '.' in possible_field_name: possible_field_name = possible_field_name.split('.')[-1] fd = tracker_bizobj.FindFieldDef(possible_field_name, config) if fd: # We cannot assume that non-enum_type field defs do not share their # names with label prefixes. So we need to group them with # TableCellKeyLabels to make sure we catch appropriate labels values. if fd.field_type == tracker_pb2.FieldTypes.APPROVAL_TYPE: if is_approver_col: # Combined cell for 'FieldName-approver' to hold approvers # belonging to FieldName and values belonging to labels with # 'FieldName-approver' as the key. return CompositeFactoryTableCell([(TableCellApprovalApprover, col), (TableCellKeyLabels, col)]) return CompositeFactoryTableCell([(TableCellApprovalStatus, col), (TableCellKeyLabels, col)]) elif fd.field_type != tracker_pb2.FieldTypes.ENUM_TYPE: return CompositeFactoryTableCell([(TableCellCustom, col), (TableCellKeyLabels, col)]) return TableCellKeyLabels
def testFindFieldDef_Default(self): config = tracker_bizobj.MakeDefaultProjectIssueConfig(789) self.assertIsNone(tracker_bizobj.FindFieldDef('EstDays', config))
def VerifyConversion(self, mr): """Verify that all FLT-Conversion issues were converted correctly.""" with work_env.WorkEnv(mr, self.services) as we: pipeline = we.ListIssues('FLT=Conversion', ['chromium'], mr.auth.user_id, VERIFY_NUM, CONVERT_START, [], 2, GROUP_BY_SPEC, SORT_SPEC, False) project = self.services.project.GetProjectByName(mr.cnxn, 'chromium') config = self.services.config.GetProjectConfig(mr.cnxn, project.project_id) browser_approval_names = { fd.field_id: fd.field_name for fd in config.field_defs if fd.field_name in BROWSER_APPROVALS_TO_LABELS.keys() } os_approval_names = { fd.field_id: fd.field_name for fd in config.field_defs if (fd.field_name in OS_APPROVALS_TO_LABELS.keys()) or fd.field_name == 'ChromeOS-Enterprise' } pm_id = tracker_bizobj.FindFieldDef('PM', config).field_id tl_id = tracker_bizobj.FindFieldDef('TL', config).field_id te_id = tracker_bizobj.FindFieldDef('TE', config).field_id ux_id = tracker_bizobj.FindFieldDef('UX', config).field_id mapproved_id = tracker_bizobj.FindFieldDef('M-Approved', config).field_id mtarget_id = tracker_bizobj.FindFieldDef('M-Target', config).field_id problems = [] for possible_stale_issue in pipeline.allowed_results: issue = self.services.issue.GetIssue(mr.cnxn, possible_stale_issue.issue_id, use_cache=False) # Check correct template used approval_names = browser_approval_names approvals_to_labels = BROWSER_APPROVALS_TO_LABELS m_labels_re = BROWSER_M_LABELS_RE label_channel_to_phase_id = { phase.name.lower(): phase.phase_id for phase in issue.phases } if [l for l in issue.labels if l.startswith('OS-')] == ['OS-Chrome']: approval_names = os_approval_names m_labels_re = OS_M_LABELS_RE approvals_to_labels = OS_APPROVALS_TO_LABELS # OS default launch if 'Rollout-Type-Default' in issue.labels: if not all(phase.name in ['Feature Freeze', 'Branch', 'Stable'] for phase in issue.phases): problems.append( (issue.local_id, 'incorrect phases for OS default launch.')) # OS finch launch elif 'Rollout-Type-Finch' in issue.labels: if not all(phase.name in ('Feature Freeze', 'Branch', 'Stable-Exp', 'Stable-Full') for phase in issue.phases): problems.append( (issue.local_id, 'incorrect phases for OS finch launch.')) else: problems.append( (issue.local_id, 'no rollout-type; should not have been converted')) # Browser default launch elif 'Rollout-Type-Default' in issue.labels: if not all(phase.name.lower() in ['beta', 'stable'] for phase in issue.phases): problems.append((issue.local_id, 'incorrect phases for Default rollout')) # Browser finch launch elif 'Rollout-Type-Finch' in issue.labels: if not all(phase.name.lower() in ['beta', 'stable-exp', 'stable-full'] for phase in issue.phases): problems.append( (issue.local_id, 'incorrect phases for Finch rollout')) else: problems.append( (issue.local_id, 'no rollout-type; should not have been converted')) # Check approval_values for av in issue.approval_values: name = approval_names.get(av.approval_id) if name == 'ChromeOS-Enterprise': if av.status != tracker_pb2.ApprovalStatus.NEEDS_REVIEW: problems.append( (issue.local_id, 'bad ChromeOS-Enterprise status')) continue label_pre = approvals_to_labels.get(name) if not label_pre: # either name was None or not found in APPROVALS_TO_LABELS problems.append( (issue.local_id, 'approval %s not recognized' % name)) continue label_value = next( (l[len(label_pre):] for l in issue.labels if l.startswith(label_pre)), None) if (not label_value or label_value == 'NotReviewed') and av.status in [ tracker_pb2.ApprovalStatus.NOT_SET, tracker_pb2.ApprovalStatus.NEEDS_REVIEW ]: continue if av.status is VALUE_TO_STATUS.get(label_value): continue # neither of the above ifs passed problems.append( (issue.local_id, 'approval %s has status %r for label value %s' % (name, av.status.name, label_value))) # Check people field_values expected_people_fvs = self.ConvertPeopleLabels( mr, issue.labels, pm_id, tl_id, te_id, ux_id) for people_fv in expected_people_fvs: if people_fv not in issue.field_values: if people_fv.field_id == tl_id: role = 'TL' elif people_fv.field_id == pm_id: role = 'PM' elif people_fv.field_id == ux_id: role = 'UX' else: role = 'TE' problems.append( (issue.local_id, 'missing a field for %s' % role)) # Check M phase field_values for label in issue.labels: match = re.match(m_labels_re, label) if match: channel = match.group('channel') if (channel.lower() == 'stable-exp' and 'Rollout-Type-Default' in issue.labels): # ignore stable-exp for default rollouts. continue milestone = match.group('m') m_type = match.group('type') m_id = mapproved_id if m_type == 'Approved' else mtarget_id phase_id = label_channel_to_phase_id.get( channel.lower(), label_channel_to_phase_id.get('stable-full')) if not next( (fv for fv in issue.field_values if fv.phase_id == phase_id and fv.field_id == m_id and fv.int_value == int(milestone)), None): problems.append( (issue.local_id, 'no phase field for label %s' % label)) return { 'problems found': ['issue %d: %s' % problem for problem in problems], 'issues verified': [ 'issue %d' % issue.local_id for issue in pipeline.allowed_results ], 'num': len(pipeline.allowed_results), }
def ProcessFormData(self, mr, post_data): """Validate and store the contents of the issues tracker admin page. Args: mr: commonly used info parsed from the request. post_data: HTML form data from the request. Returns: String URL to redirect the user to, or None if response was already sent. """ config = self.services.config.GetProjectConfig(mr.cnxn, mr.project_id) parsed = field_helpers.ParseFieldDefRequest(post_data, config) if not tracker_constants.FIELD_NAME_RE.match(parsed.field_name): mr.errors.field_name = 'Invalid field name' field_name_error_msg = FieldNameErrorMessage(parsed.field_name, config) if field_name_error_msg: mr.errors.field_name = field_name_error_msg if (parsed.min_value is not None and parsed.max_value is not None and parsed.min_value > parsed.max_value): mr.errors.min_value = 'Minimum value must be less than maximum.' if parsed.regex: try: re.compile(parsed.regex) except re.error: mr.errors.regex = 'Invalid regular expression.' admin_ids, admin_str = tracker_helpers.ParseAdminUsers( mr.cnxn, post_data['admin_names'], self.services.user) if parsed.field_type_str == 'approval_type': if parsed.approvers_str: approver_ids_dict = self.services.user.LookupUserIDs( mr.cnxn, re.split('[,;\s]+', parsed.approvers_str), autocreate=True) approver_ids = list(set(approver_ids_dict.values())) else: mr.errors.approvers = 'Please provide at least one default approver.' if mr.errors.AnyErrors(): self.PleaseCorrect( mr, initial_field_name=parsed.field_name, initial_type=parsed.field_type_str, initial_parent_approval_name=parsed.parent_approval_name, initial_field_docstring=parsed.field_docstring, initial_applicable_type=parsed.applicable_type, initial_applicable_predicate=parsed.applicable_predicate, initial_needs_member=ezt.boolean(parsed.needs_member), initial_needs_perm=parsed.needs_perm, initial_importance=parsed.importance, initial_is_multivalued=ezt.boolean(parsed.is_multivalued), initial_grants_perm=parsed.grants_perm, initial_notify_on=parsed.notify_on, initial_date_action=parsed.date_action_str, initial_choices=parsed.choices_text, initial_approvers=parsed.approvers_str, initial_survey=parsed.survey, initial_is_phase_field=parsed.is_phase_field, initial_admins=admin_str, ) return approval_id = None if parsed.parent_approval_name and ( parsed.field_type_str != 'approval_type'): approval_fd = tracker_bizobj.FindFieldDef( parsed.parent_approval_name, config) if approval_fd: approval_id = approval_fd.field_id field_id = self.services.config.CreateFieldDef( mr.cnxn, mr.project_id, parsed.field_name, parsed.field_type_str, parsed.applicable_type, parsed.applicable_predicate, parsed.is_required, parsed.is_niche, parsed.is_multivalued, parsed.min_value, parsed.max_value, parsed.regex, parsed.needs_member, parsed.needs_perm, parsed.grants_perm, parsed.notify_on, parsed.date_action_str, parsed.field_docstring, admin_ids, approval_id, parsed.is_phase_field) if parsed.field_type_str == 'approval_type': revised_approvals = field_helpers.ReviseApprovals( field_id, approver_ids, parsed.survey, config) self.services.config.UpdateConfig( mr.cnxn, mr.project, approval_defs=revised_approvals) if parsed.field_type_str == 'enum_type': self.services.config.UpdateConfig( mr.cnxn, mr.project, well_known_labels=parsed.revised_labels) return framework_helpers.FormatAbsoluteURL( mr, urls.ADMIN_LABELS, saved=1, ts=int(time.time()))
def testFindFieldDef_None(self): config = tracker_pb2.ProjectIssueConfig() self.assertIsNone(tracker_bizobj.FindFieldDef(None, config))
def GetArtifactAttr(art, attribute_name, users_by_id, label_attr_values_dict, config, related_issues, hotlist_issue_context=None): """Return the requested attribute values of the given artifact. Args: art: a tracked artifact with labels, local_id, summary, stars, and owner. attribute_name: lowercase string name of attribute to get. users_by_id: dictionary of UserViews already created. label_attr_values_dict: dictionary {'key': [value, ...], }. config: ProjectIssueConfig PB for the current project. related_issues: dict {issue_id: issue} of pre-fetched related issues. hotlist_issue_context: dict of {hotlist_issue_field: field_value,..} Returns: A list of string attribute values, or [framework_constants.NO_VALUES] if the artifact has no value for that attribute. """ if attribute_name == '--': return [] if attribute_name == 'id': return [art.local_id] if attribute_name == 'summary': return [art.summary] if attribute_name == 'status': return [tracker_bizobj.GetStatus(art)] if attribute_name == 'stars': return [art.star_count] if attribute_name == 'attachments': return [art.attachment_count] # TODO(jrobbins): support blocking if attribute_name == 'project': return [art.project_name] if attribute_name == 'mergedinto': if art.merged_into and art.merged_into != 0: return [ tracker_bizobj.FormatIssueRef( (related_issues[art.merged_into].project_name, related_issues[art.merged_into].local_id)) ] else: return [framework_constants.NO_VALUES] if attribute_name == 'blocked': return ['Yes' if art.blocked_on_iids else 'No'] if attribute_name == 'blockedon': if not art.blocked_on_iids: return [framework_constants.NO_VALUES] else: return [ tracker_bizobj.FormatIssueRef( (related_issues[blocked_on_iid].project_name, related_issues[blocked_on_iid].local_id)) for blocked_on_iid in art.blocked_on_iids ] if attribute_name == 'adder': if hotlist_issue_context: adder_id = hotlist_issue_context['adder_id'] return [users_by_id[adder_id].display_name] else: return [framework_constants.NO_VALUES] if attribute_name == 'added': if hotlist_issue_context: return [hotlist_issue_context['date_added']] else: return [framework_constants.NO_VALUES] if attribute_name == 'reporter': return [users_by_id[art.reporter_id].display_name] if attribute_name == 'owner': owner_id = tracker_bizobj.GetOwnerId(art) if not owner_id: return [framework_constants.NO_VALUES] else: return [users_by_id[owner_id].display_name] if attribute_name == 'cc': cc_ids = tracker_bizobj.GetCcIds(art) if not cc_ids: return [framework_constants.NO_VALUES] else: return [users_by_id[cc_id].display_name for cc_id in cc_ids] if attribute_name == 'component': comp_ids = list(art.component_ids) + list(art.derived_component_ids) if not comp_ids: return [framework_constants.NO_VALUES] else: paths = [] for comp_id in comp_ids: cd = tracker_bizobj.FindComponentDefByID(comp_id, config) if cd: paths.append(cd.path) return paths # Check to see if it is a field. Process as field only if it is not an enum # type because enum types are stored as key-value labels. fd = tracker_bizobj.FindFieldDef(attribute_name, config) if fd and fd.field_type != tracker_pb2.FieldTypes.ENUM_TYPE: values = [] for fv in art.field_values: if fv.field_id == fd.field_id: value = tracker_bizobj.GetFieldValueWithRawValue( fd.field_type, fv, users_by_id, None) values.append(value) return values # Since it is not a built-in attribute or a field, it must be a key-value # label. return label_attr_values_dict.get(attribute_name, [framework_constants.NO_VALUES])
def testFindFieldDef_Empty(self): config = tracker_pb2.ProjectIssueConfig() self.assertIsNone(tracker_bizobj.FindFieldDef('EstDays', config))