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))
示例#2
0
 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)
示例#3
0
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
示例#4
0
    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)
示例#6
0
 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)
示例#7
0
 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
示例#8
0
    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)
示例#9
0
    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
示例#11
0
    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),
        }
示例#12
0
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
示例#13
0
    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)
示例#14
0
    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)
示例#15
0
    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
示例#16
0
    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
示例#17
0
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))
示例#19
0
    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),
        }
示例#20
0
  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))
示例#22
0
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))