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 # start with ASCII digit or lowercase |
26 from soc.logic import path_linkname |
27 # (additional ASCII digit or lowercase |
|
28 # -OR- |
|
29 # underscore and ASCII digit or lowercase) |
|
30 # zero or more of OR group |
|
31 LINKNAME_PATTERN_CORE = r'[0-9a-z](?:[0-9a-z]|_[0-9a-z])*' |
|
32 |
|
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 |
27 |
48 |
28 |
49 class Error(Exception): |
29 class Error(Exception): |
50 """Base class for all exceptions raised by this module.""" |
30 """Base class for all exceptions raised by this module.""" |
51 pass |
31 pass |
52 |
32 |
53 |
33 |
54 def getFullClassName(cls): |
34 def getFullClassName(cls): |
55 """Returns fully-qualified module.class name string.""" |
35 """Returns fully-qualified module.class name string.""" |
56 return '%s.%s' % (cls.__module__, cls.__name__) |
36 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 |
37 |
97 |
38 |
98 def nameDocument(partial_path, link_name=None): |
39 def nameDocument(partial_path, link_name=None): |
99 """Returns a Document key name constructed from a path and link name. |
40 """Returns a Document key name constructed from a path and link name. |
100 |
41 |
168 |
109 |
169 Raises: |
110 Raises: |
170 Error if sponsor_ln, program_ln, and link_Name combine to produce |
111 Error if sponsor_ln, program_ln, and link_Name combine to produce |
171 a "False" path (None, empty string, etc.) |
112 a "False" path (None, empty string, etc.) |
172 """ |
113 """ |
173 path = combinePath([[sponsor_ln, program_ln], link_name]) |
114 path = path_linkname.combinePath([[sponsor_ln, program_ln], link_name]) |
174 |
115 |
175 if not path: |
116 if not path: |
176 raise Error('"path" must be non-False: "%s"' % path) |
117 raise Error('"path" must be non-False: "%s"' % path) |
177 |
118 |
178 return 'Group/School:%s' % path |
119 return 'Group/School:%s' % path |
188 |
129 |
189 Raises: |
130 Raises: |
190 Error if sponsor_ln, program_ln, and link_Name combine to produce |
131 Error if sponsor_ln, program_ln, and link_Name combine to produce |
191 a "False" path (None, empty string, etc.) |
132 a "False" path (None, empty string, etc.) |
192 """ |
133 """ |
193 path = combinePath([[sponsor_ln, program_ln], link_name]) |
134 path = path_linkname.combinePath([[sponsor_ln, program_ln], link_name]) |
194 |
135 |
195 if not path: |
136 if not path: |
196 raise Error('"path" must be non-False: "%s"' % path) |
137 raise Error('"path" must be non-False: "%s"' % path) |
197 |
138 |
198 return 'Group/Organization:%s' % path |
139 return 'Group/Organization:%s' % path |