Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(97)

Side by Side Diff: appengine/monorail/framework/framework_bizobj.py

Issue 1868553004: Open Source Monorail (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git@master
Patch Set: Rebase Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 # Copyright 2016 The Chromium Authors. All rights reserved.
2 # Use of this source code is govered by a BSD-style
3 # license that can be found in the LICENSE file or at
4 # https://developers.google.com/open-source/licenses/bsd
5
6 """Business objects for Monorail's framework.
7
8 These are classes and functions that operate on the objects that
9 users care about in Monorail but that are not part of just one specific
10 component: e.g., projects, users, and labels.
11 """
12
13 import logging
14 import re
15 import string
16
17 import settings
18 from framework import framework_constants
19
20
21 # Pattern to match a valid project name. Users of this pattern MUST use
22 # the re.VERBOSE flag or the whitespace and comments we be considered
23 # significant and the pattern will not work. See "re" module documentation.
24 _RE_PROJECT_NAME_PATTERN_VERBOSE = r"""
25 (?=[-a-z0-9]*[a-z][-a-z0-9]*) # Lookahead to make sure there is at least
26 # one letter in the whole name.
27 [a-z0-9] # Start with a letter or digit.
28 [-a-z0-9]* # Follow with any number of valid characters.
29 [a-z0-9] # End with a letter or digit.
30 """
31
32
33 # Compiled regexp to match the project name and nothing more before or after.
34 RE_PROJECT_NAME = re.compile(
35 '^%s$' % _RE_PROJECT_NAME_PATTERN_VERBOSE, re.VERBOSE)
36
37
38 def IsValidProjectName(s):
39 """Return true if the given string is a valid project name."""
40 return (RE_PROJECT_NAME.match(s) and
41 len(s) <= framework_constants.MAX_PROJECT_NAME_LENGTH)
42
43
44 def UserOwnsProject(project, effective_ids):
45 """Return True if any of the effective_ids is a project owner."""
46 return not effective_ids.isdisjoint(project.owner_ids or set())
47
48
49 def UserIsInProject(project, effective_ids):
50 """Return True if any of the effective_ids is a project member.
51
52 Args:
53 project: Project PB for the current project.
54 effective_ids: set of int user IDs for the current user (including all
55 user groups). This will be an empty set for anonymous users.
56
57 Returns:
58 True if the user has any direct or indirect role in the project. The value
59 will actually be a set(), but it will have an ID in it if the user is in
60 the project, or it will be an empty set which is considered False.
61 """
62 return (UserOwnsProject(project, effective_ids) or
63 not effective_ids.isdisjoint(project.committer_ids or set()) or
64 not effective_ids.isdisjoint(project.contributor_ids or set()))
65
66
67 def AllProjectMembers(project):
68 """Return a list of user IDs of all members in the given project."""
69 return project.owner_ids + project.committer_ids + project.contributor_ids
70
71
72 def IsPriviledgedDomainUser(email):
73 """Return True if the user's account is from a priviledged domain."""
74 if email and '@' in email:
75 _, user_domain = email.split('@', 1)
76 return user_domain in settings.priviledged_user_domains
77
78 return False
79
80
81
82 # String translation table to catch a common typos in label names.
83 _CANONICALIZATION_TRANSLATION_TABLE = {
84 ord(delete_u_char): None
85 for delete_u_char in u'!"#$%&\'()*+,/:;<>?@[\\]^`{|}~\t\n\x0b\x0c\r '
86 }
87 _CANONICALIZATION_TRANSLATION_TABLE.update({ord(u'='): ord(u'-')})
88
89
90 def CanonicalizeLabel(user_input):
91 """Canonicalize a given label or status value.
92
93 When the user enters a string that represents a label or an enum,
94 convert it a canonical form that makes it more likely to match
95 existing values.
96
97 Args:
98 user_input: string that the user typed for a label.
99
100 Returns:
101 Canonical form of that label as a unicode string.
102 """
103 if user_input is None:
104 return user_input
105
106 if not isinstance(user_input, unicode):
107 user_input = user_input.decode('utf-8')
108
109 canon_str = user_input.translate(_CANONICALIZATION_TRANSLATION_TABLE)
110 return canon_str
111
112
113 def MergeLabels(labels_list, labels_add, labels_remove, excl_prefixes):
114 """Update a list of labels with the given add and remove label lists.
115
116 Args:
117 labels_list: list of current labels.
118 labels_add: labels that the user wants to add.
119 labels_remove: labels that the user wants to remove.
120 excl_prefixes: prefixes that can have only one value, e.g., Priority.
121
122 Returns:
123 (merged_labels, update_labels_add, update_labels_remove):
124 A new list of labels with the given labels added and removed, and
125 any exclusive label prefixes taken into account. Then two
126 lists of update strings to explain the changes that were actually
127 made.
128 """
129 old_lower_labels = [lab.lower() for lab in labels_list]
130 labels_add = [lab for lab in labels_add
131 if lab.lower() not in old_lower_labels]
132 labels_remove = [lab for lab in labels_remove
133 if lab.lower() in old_lower_labels]
134 labels_remove_lower = [lab.lower() for lab in labels_remove]
135 config_excl = [lab.lower() for lab in excl_prefixes]
136
137 # "Old minus exclusive" is the set of old label values minus any
138 # that are implictly removed by newly set exclusive labels.
139 excl_add = [] # E.g., there can be only one "Priority-*" label
140 for lab in labels_add:
141 prefix = lab.split('-')[0].lower()
142 if prefix in config_excl:
143 excl_add.append('%s-' % prefix)
144 old_minus_excl = []
145 for lab in labels_list:
146 for prefix_dash in excl_add:
147 if lab.lower().startswith(prefix_dash):
148 # Note: don't add -lab to update_labels_remove, it is implicit.
149 break
150 else:
151 old_minus_excl.append(lab)
152
153 merged_labels = [lab for lab in old_minus_excl + labels_add
154 if lab.lower() not in labels_remove_lower]
155
156 return merged_labels, labels_add, labels_remove
OLDNEW
« no previous file with comments | « appengine/monorail/framework/filecontent.py ('k') | appengine/monorail/framework/framework_constants.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698