21 '"Todd Larsen" <tlarsen@google.com>', |
21 '"Todd Larsen" <tlarsen@google.com>', |
22 '"Pawel Solyga" <pawel.solyga@gmail.com>', |
22 '"Pawel Solyga" <pawel.solyga@gmail.com>', |
23 ] |
23 ] |
24 |
24 |
25 |
25 |
26 import soc.models.club |
26 # start with ASCII digit or lowercase |
27 import soc.models.group |
27 # (additional ASCII digit or lowercase |
28 import soc.models.organization |
28 # -OR- |
29 import soc.models.school |
29 # underscore and ASCII digit or lowercase) |
30 import soc.models.sponsor |
30 # zero or more of OR group |
31 import soc.models.document |
31 LINKNAME_PATTERN_CORE = r'[0-9a-z](?:[0-9a-z]|_[0-9a-z])*' |
32 import soc.models.site_settings |
32 |
33 import soc.models.user |
33 LINKNAME_PATTERN = r'^%s$' % LINKNAME_PATTERN_CORE |
|
34 LINKNAME_ARG_PATTERN = r'(?P<linkname>%s)' % LINKNAME_PATTERN_CORE |
|
35 |
|
36 |
|
37 # partial path is multiple linkname chunks, |
|
38 # each separated by a trailing / |
|
39 # (at least 1) |
|
40 # followed by a single linkname with no trailing / |
|
41 WORK_PATH_LINKNAME_ARGS_PATTERN = ( |
|
42 r'(?P<partial_path>%(linkname)s(?:/%(linkname)s)*)/' |
|
43 '(?P<linkname>%(linkname)s)' % { |
|
44 'linkname': LINKNAME_PATTERN_CORE}) |
|
45 |
|
46 WORK_PATH_LINKNAME_PATTERN = r'^%s$' % WORK_PATH_LINKNAME_ARGS_PATTERN |
|
47 |
|
48 |
|
49 class Error(Exception): |
|
50 """Base class for all exceptions raised by this module.""" |
|
51 pass |
|
52 |
|
53 |
|
54 def getFullClassName(cls): |
|
55 """Returns fully-qualified module.class name string.""" |
|
56 return '%s.%s' % (cls.__module__, cls.__name__) |
|
57 |
|
58 |
|
59 def combinePath(path_parts): |
|
60 """Returns path components combined into a single string. |
|
61 |
|
62 Args: |
|
63 path_parts: a single path string, or a list of path part strings, |
|
64 or a nested list of path part strings (where the zeroeth element in |
|
65 the list is itself a list); for example: |
|
66 'a/complete/path/in/one/string' |
|
67 ['some', 'path', 'parts'] |
|
68 [['path', 'parts', 'and', 'a'], 'link name'] |
|
69 |
|
70 Returns: |
|
71 None if path_parts is False (None, empty string, etc.) or if |
|
72 any list elements are False (an empty list, empty string, etc.); |
|
73 otherwise, the combined string with the necessary separators. |
|
74 """ |
|
75 if not path_parts: |
|
76 # completely empty input, so return early |
|
77 return None |
|
78 |
|
79 if not isinstance(path_parts, (list, tuple)): |
|
80 # a single path string, so just return it as-is (nothing to do) |
|
81 return path_parts |
|
82 |
|
83 flattened_parts = [] |
|
84 |
|
85 for part in path_parts: |
|
86 if not part: |
|
87 # encountered a "False" element, which invalidates everything else |
|
88 return None |
|
89 |
|
90 if isinstance(part, (list, tuple)): |
|
91 flattened_parts.extend(part) |
|
92 else: |
|
93 flattened_parts.append(part) |
|
94 |
|
95 return '/'.join(flattened_parts) |
|
96 |
|
97 |
|
98 def nameDocument(partial_path, link_name=None): |
|
99 """Returns a Document key name constructed from a path and link name. |
|
100 |
|
101 Args: |
|
102 partial_path: the first portion of the path to the Document that uniquely |
|
103 identifies it |
|
104 link_name: optional link name to append to path (when omitted, |
|
105 partial_path is actually the entire path, with the link_name already |
|
106 appended) |
|
107 |
|
108 Raises: |
|
109 Error if partial_path and link_Name produce a "False" path (None, |
|
110 empty string, etc.) |
|
111 """ |
|
112 path = [partial_path] |
|
113 |
|
114 if link_name: |
|
115 path.append(link_name) |
|
116 |
|
117 path = combinePath(path) |
|
118 |
|
119 if not path: |
|
120 raise Error('"path" must be non-False: "%s"' % path) |
|
121 |
|
122 return 'Document:%s' % path |
34 |
123 |
35 |
124 |
36 def nameSiteSettings(path): |
125 def nameSiteSettings(path): |
37 """Returns a SiteSettings key name constructed from a supplied path.""" |
126 """Returns a SiteSettings key name constructed from a supplied path. |
38 return '%(type)s:%(path)s' % { |
127 |
39 'type': soc.models.site_settings.SiteSettings.__name__, |
128 Raises: |
40 'path': path, |
129 Error if path is "False" (None, empty string, etc.) |
41 } |
130 """ |
42 |
131 if not path: |
43 |
132 raise Error('"path" must be non-False: "%s"' % path) |
44 def nameDocument(path, link_name): |
133 |
45 """Returns a Document key name constructed from a path and link name.""" |
134 return 'SiteSettings:%s' % path |
46 return '%(type)s:%(path)s/%(link_name)s' % { |
|
47 'type': soc.models.document.Document.__name__, |
|
48 'path': path, |
|
49 'link_name': link_name, |
|
50 } |
|
51 |
135 |
52 |
136 |
53 def nameUser(email): |
137 def nameUser(email): |
54 """Returns a User key name constructed from a supplied email address.""" |
138 """Returns a User key name constructed from a supplied email address. |
55 return '%(type)s:%(email)s' % { |
139 |
56 'type': soc.models.user.User.__name__, |
140 Raises: |
57 'email': email, |
141 Error if email is "False" (None, empty string, etc.) |
58 } |
142 """ |
|
143 if not email: |
|
144 raise Error('"email" must be non-False: "%s"' % email) |
|
145 |
|
146 return 'User:%s' % email |
59 |
147 |
60 |
148 |
61 def nameSponsor(link_name): |
149 def nameSponsor(link_name): |
62 """Returns a Sponsor key name constructed from a supplied link name.""" |
150 """Returns a Sponsor key name constructed from a supplied link name. |
63 return '%(group)s/%(type)s:%(link_name)s' % { |
151 |
64 'group': soc.models.group.Group.__name__, |
152 Raises: |
65 'type': soc.models.sponsor.Sponsor.__name__, |
153 Error if link_name is "False" (None, empty string, etc.) |
66 'link_name': link_name, |
154 """ |
67 } |
155 if not link_name: |
|
156 raise Error('"link_name" must be non-False: "%s"' % link_name) |
|
157 |
|
158 return 'Group/Sponsor:%s' % link_name |
68 |
159 |
69 |
160 |
70 def nameSchool(sponsor_ln, program_ln, link_name): |
161 def nameSchool(sponsor_ln, program_ln, link_name): |
71 """Returns a School key name constructed from a supplied sponsor, |
162 """Returns a School key name constructed from link names. |
72 program and school link names. |
163 |
73 """ |
164 Args: |
74 return '%(group)s/%(type)s:%(sponsor)s/%(program)s/%(link_name)s' % { |
165 sponsor_ln: Sponsor link name |
75 'group': soc.models.group.Group.__name__, |
166 program_ln: Program link name |
76 'type': soc.models.school.School.__name__, |
167 link_name: School link name |
77 'sponsor': sponsor_ln, |
168 |
78 'program': program_ln, |
169 Raises: |
79 'link_name': link_name, |
170 Error if sponsor_ln, program_ln, and link_Name combine to produce |
80 } |
171 a "False" path (None, empty string, etc.) |
|
172 """ |
|
173 path = combinePath([[sponsor_ln, program_ln], link_name]) |
|
174 |
|
175 if not path: |
|
176 raise Error('"path" must be non-False: "%s"' % path) |
|
177 |
|
178 return 'Group/School:%s' % path |
81 |
179 |
82 |
180 |
83 def nameOrganization(sponsor_ln, program_ln, link_name): |
181 def nameOrganization(sponsor_ln, program_ln, link_name): |
84 """Returns a Organization key name constructed from a supplied sponsor, |
182 """Returns a Organization key name constructed from link names. |
85 program and organization link names. |
183 |
86 """ |
184 Args: |
87 return '%(group)s/%(type)s:%(sponsor)s/%(program)s/%(link_name)s' % { |
185 sponsor_ln: Sponsor link name |
88 'group': soc.models.group.Group.__name__, |
186 program_ln: Program link name |
89 'type': soc.models.organization.Organization.__name__, |
187 link_name: Organization link name |
90 'sponsor': sponsor_ln, |
188 |
91 'program': program_ln, |
189 Raises: |
92 'link_name': link_name, |
190 Error if sponsor_ln, program_ln, and link_Name combine to produce |
93 } |
191 a "False" path (None, empty string, etc.) |
|
192 """ |
|
193 path = combinePath([[sponsor_ln, program_ln], link_name]) |
|
194 |
|
195 if not path: |
|
196 raise Error('"path" must be non-False: "%s"' % path) |
|
197 |
|
198 return 'Group/Organization:%s' % path |
94 |
199 |
95 |
200 |
96 def nameClub(link_name): |
201 def nameClub(link_name): |
97 """Returns a Club key name constructed from a supplied link name.""" |
202 """Returns a Club key name constructed from a supplied link name. |
98 return '%(group)s/%(type)s:%(link_name)s' % { |
203 |
99 'group': soc.models.group.Group.__name__, |
204 Raises: |
100 'type': soc.models.sponsor.Sponsor.__name__, |
205 Error if link_name is "False" (None, empty string, etc.) |
101 'link_name': link_name, |
206 """ |
102 } |
207 if not link_name: |
103 |
208 raise Error('"link_name" must be non-False: "%s"' % link_name) |
|
209 |
|
210 return 'Group/Club:%s' % link_name |