# HG changeset patch # User Todd Larsen # Date 1222821678 0 # Node ID 63e5f42e2e836691fdc316afbdc0c9a0c1bf5f67 # Parent 9cca97feadaa1c4340d47f5966c57aa1198cfd46 Add lots of new functions to key_name.py, including path/link_name processing. Copy various link_name related regex patterns to key_name.py and use them. Add error checking that raises a key_name.Error exception when name...() functions are given empty arguments. Hard-code class names, since they match what was typed into the module.class.__name__ to get the name anyway. This eliminates dependencies on any modules by key_name.py. diff -r 9cca97feadaa -r 63e5f42e2e83 app/soc/logic/key_name.py --- a/app/soc/logic/key_name.py Wed Oct 01 00:35:29 2008 +0000 +++ b/app/soc/logic/key_name.py Wed Oct 01 00:41:18 2008 +0000 @@ -23,81 +23,188 @@ ] -import soc.models.club -import soc.models.group -import soc.models.organization -import soc.models.school -import soc.models.sponsor -import soc.models.document -import soc.models.site_settings -import soc.models.user +# start with ASCII digit or lowercase +# (additional ASCII digit or lowercase +# -OR- +# underscore and ASCII digit or lowercase) +# zero or more of OR group +LINKNAME_PATTERN_CORE = r'[0-9a-z](?:[0-9a-z]|_[0-9a-z])*' + +LINKNAME_PATTERN = r'^%s$' % LINKNAME_PATTERN_CORE +LINKNAME_ARG_PATTERN = r'(?P%s)' % LINKNAME_PATTERN_CORE + + +# partial path is multiple linkname chunks, +# each separated by a trailing / +# (at least 1) +# followed by a single linkname with no trailing / +WORK_PATH_LINKNAME_ARGS_PATTERN = ( + r'(?P%(linkname)s(?:/%(linkname)s)*)/' + '(?P%(linkname)s)' % { + 'linkname': LINKNAME_PATTERN_CORE}) + +WORK_PATH_LINKNAME_PATTERN = r'^%s$' % WORK_PATH_LINKNAME_ARGS_PATTERN + + +class Error(Exception): + """Base class for all exceptions raised by this module.""" + pass + + +def getFullClassName(cls): + """Returns fully-qualified module.class name string.""" + return '%s.%s' % (cls.__module__, cls.__name__) + + +def combinePath(path_parts): + """Returns path components combined into a single string. + + Args: + path_parts: a single path string, or a list of path part strings, + or a nested list of path part strings (where the zeroeth element in + the list is itself a list); for example: + 'a/complete/path/in/one/string' + ['some', 'path', 'parts'] + [['path', 'parts', 'and', 'a'], 'link name'] + + Returns: + None if path_parts is False (None, empty string, etc.) or if + any list elements are False (an empty list, empty string, etc.); + otherwise, the combined string with the necessary separators. + """ + if not path_parts: + # completely empty input, so return early + return None + + if not isinstance(path_parts, (list, tuple)): + # a single path string, so just return it as-is (nothing to do) + return path_parts + + flattened_parts = [] + + for part in path_parts: + if not part: + # encountered a "False" element, which invalidates everything else + return None + + if isinstance(part, (list, tuple)): + flattened_parts.extend(part) + else: + flattened_parts.append(part) + + return '/'.join(flattened_parts) + + +def nameDocument(partial_path, link_name=None): + """Returns a Document key name constructed from a path and link name. + + Args: + partial_path: the first portion of the path to the Document that uniquely + identifies it + link_name: optional link name to append to path (when omitted, + partial_path is actually the entire path, with the link_name already + appended) + + Raises: + Error if partial_path and link_Name produce a "False" path (None, + empty string, etc.) + """ + path = [partial_path] + + if link_name: + path.append(link_name) + + path = combinePath(path) + + if not path: + raise Error('"path" must be non-False: "%s"' % path) + + return 'Document:%s' % path def nameSiteSettings(path): - """Returns a SiteSettings key name constructed from a supplied path.""" - return '%(type)s:%(path)s' % { - 'type': soc.models.site_settings.SiteSettings.__name__, - 'path': path, - } - + """Returns a SiteSettings key name constructed from a supplied path. + + Raises: + Error if path is "False" (None, empty string, etc.) + """ + if not path: + raise Error('"path" must be non-False: "%s"' % path) -def nameDocument(path, link_name): - """Returns a Document key name constructed from a path and link name.""" - return '%(type)s:%(path)s/%(link_name)s' % { - 'type': soc.models.document.Document.__name__, - 'path': path, - 'link_name': link_name, - } + return 'SiteSettings:%s' % path def nameUser(email): - """Returns a User key name constructed from a supplied email address.""" - return '%(type)s:%(email)s' % { - 'type': soc.models.user.User.__name__, - 'email': email, - } + """Returns a User key name constructed from a supplied email address. + + Raises: + Error if email is "False" (None, empty string, etc.) + """ + if not email: + raise Error('"email" must be non-False: "%s"' % email) + + return 'User:%s' % email def nameSponsor(link_name): - """Returns a Sponsor key name constructed from a supplied link name.""" - return '%(group)s/%(type)s:%(link_name)s' % { - 'group': soc.models.group.Group.__name__, - 'type': soc.models.sponsor.Sponsor.__name__, - 'link_name': link_name, - } + """Returns a Sponsor key name constructed from a supplied link name. + + Raises: + Error if link_name is "False" (None, empty string, etc.) + """ + if not link_name: + raise Error('"link_name" must be non-False: "%s"' % link_name) + + return 'Group/Sponsor:%s' % link_name def nameSchool(sponsor_ln, program_ln, link_name): - """Returns a School key name constructed from a supplied sponsor, - program and school link names. + """Returns a School key name constructed from link names. + + Args: + sponsor_ln: Sponsor link name + program_ln: Program link name + link_name: School link name + + Raises: + Error if sponsor_ln, program_ln, and link_Name combine to produce + a "False" path (None, empty string, etc.) """ - return '%(group)s/%(type)s:%(sponsor)s/%(program)s/%(link_name)s' % { - 'group': soc.models.group.Group.__name__, - 'type': soc.models.school.School.__name__, - 'sponsor': sponsor_ln, - 'program': program_ln, - 'link_name': link_name, - } + path = combinePath([[sponsor_ln, program_ln], link_name]) + + if not path: + raise Error('"path" must be non-False: "%s"' % path) + + return 'Group/School:%s' % path def nameOrganization(sponsor_ln, program_ln, link_name): - """Returns a Organization key name constructed from a supplied sponsor, - program and organization link names. + """Returns a Organization key name constructed from link names. + + Args: + sponsor_ln: Sponsor link name + program_ln: Program link name + link_name: Organization link name + + Raises: + Error if sponsor_ln, program_ln, and link_Name combine to produce + a "False" path (None, empty string, etc.) """ - return '%(group)s/%(type)s:%(sponsor)s/%(program)s/%(link_name)s' % { - 'group': soc.models.group.Group.__name__, - 'type': soc.models.organization.Organization.__name__, - 'sponsor': sponsor_ln, - 'program': program_ln, - 'link_name': link_name, - } + path = combinePath([[sponsor_ln, program_ln], link_name]) + + if not path: + raise Error('"path" must be non-False: "%s"' % path) + + return 'Group/Organization:%s' % path def nameClub(link_name): - """Returns a Club key name constructed from a supplied link name.""" - return '%(group)s/%(type)s:%(link_name)s' % { - 'group': soc.models.group.Group.__name__, - 'type': soc.models.sponsor.Sponsor.__name__, - 'link_name': link_name, - } - \ No newline at end of file + """Returns a Club key name constructed from a supplied link name. + + Raises: + Error if link_name is "False" (None, empty string, etc.) + """ + if not link_name: + raise Error('"link_name" must be non-False: "%s"' % link_name) + + return 'Group/Club:%s' % link_name