# HG changeset patch # User Todd Larsen # Date 1222894359 0 # Node ID 8f23804302d0cf770b7bd1f987f35af85d13a5e7 # Parent 4d7bf6bdcd8fdcfdcbc4973b651be65e7cc5d181 Move path and link_name related functions and regex patterns to a new soc/logic/path_linkname.py module, and fix all dependencies. path/link_name functionality is becoming the generic way to identify entities in the Datastore in a URL-compatible way. diff -r 4d7bf6bdcd8f -r 8f23804302d0 app/soc/logic/document.py --- a/app/soc/logic/document.py Wed Oct 01 20:48:58 2008 +0000 +++ b/app/soc/logic/document.py Wed Oct 01 20:52:39 2008 +0000 @@ -19,6 +19,7 @@ __authors__ = [ '"Pawel Solyga" ', + '"Todd Larsen" ', ] @@ -36,24 +37,6 @@ import soc.models.work -WORK_PATH_LINKNAME_REGEX = re.compile(key_name.WORK_PATH_LINKNAME_PATTERN) - -def getPartsFromPath(path): - """Splits path string into partial_path and link_name. - - Returns: - {'partial_path': 'everything/but', - 'link_name': 'link_name'} - or {} (empty dict) if string did not match WORK_PATH_LINKNAME_PATTERN. - """ - path_linkname_match = WORK_PATH_LINKNAME_REGEX.match(path) - - if not path_linkname_match: - return {} - - return path_linkname_match.groupdict() - - def getDocument(path, link_name=None): """Returns Document entity for a given path, or None if not found. diff -r 4d7bf6bdcd8f -r 8f23804302d0 app/soc/logic/key_name.py --- a/app/soc/logic/key_name.py Wed Oct 01 20:48:58 2008 +0000 +++ b/app/soc/logic/key_name.py Wed Oct 01 20:52:39 2008 +0000 @@ -23,27 +23,7 @@ ] -# 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 +from soc.logic import path_linkname class Error(Exception): @@ -56,45 +36,6 @@ 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. @@ -114,7 +55,7 @@ if link_name: path.append(link_name) - path = combinePath(path) + path = path_linkname.combinePath(path) if not path: raise Error('"path" must be non-False: "%s"' % path) @@ -170,7 +111,7 @@ Error if sponsor_ln, program_ln, and link_Name combine to produce a "False" path (None, empty string, etc.) """ - path = combinePath([[sponsor_ln, program_ln], link_name]) + path = path_linkname.combinePath([[sponsor_ln, program_ln], link_name]) if not path: raise Error('"path" must be non-False: "%s"' % path) @@ -190,7 +131,7 @@ Error if sponsor_ln, program_ln, and link_Name combine to produce a "False" path (None, empty string, etc.) """ - path = combinePath([[sponsor_ln, program_ln], link_name]) + path = path_linkname.combinePath([[sponsor_ln, program_ln], link_name]) if not path: raise Error('"path" must be non-False: "%s"' % path) diff -r 4d7bf6bdcd8f -r 8f23804302d0 app/soc/logic/path_linkname.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/soc/logic/path_linkname.py Wed Oct 01 20:52:39 2008 +0000 @@ -0,0 +1,103 @@ +#!/usr/bin/python2.5 +# +# Copyright 2008 the Melange authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Path and link name manipulation functions. +""" + +__authors__ = [ + '"Todd Larsen" ', + ] + + +import re + + +# 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_ARG_PATTERN = r'(?P%s)' % LINKNAME_PATTERN_CORE +LINKNAME_PATTERN = r'^%s$' % LINKNAME_PATTERN_CORE +LINKNAME_REGEX = re.compile(LINKNAME_PATTERN) + +# partial path is multiple linkname chunks, +# each separated by a trailing / +# (at least 1) +# followed by a single linkname with no trailing / +PATH_LINKNAME_ARGS_PATTERN = ( + r'(?P%(linkname)s(?:/%(linkname)s)*)/' + '(?P%(linkname)s)' % { + 'linkname': LINKNAME_PATTERN_CORE}) + +PATH_LINKNAME_PATTERN = r'^%s$' % PATH_LINKNAME_ARGS_PATTERN +PATH_LINKNAME_REGEX = re.compile(PATH_LINKNAME_PATTERN) + + +def getPartsFromPath(path): + """Splits path string into partial_path and link_name. + + Returns: + {'partial_path': 'everything/but', + 'link_name': 'link_name'} + or {} (empty dict) if string did not match PATH_LINKNAME_PATTERN. + """ + path_linkname_match = PATH_LINKNAME_REGEX.match(path) + + if not path_linkname_match: + return {} + + return path_linkname_match.groupdict() + + +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) diff -r 4d7bf6bdcd8f -r 8f23804302d0 app/soc/logic/validate.py --- a/app/soc/logic/validate.py Wed Oct 01 20:48:58 2008 +0000 +++ b/app/soc/logic/validate.py Wed Oct 01 20:52:39 2008 +0000 @@ -28,6 +28,8 @@ import feedparser +from soc.logic import path_linkname + def isFeedURLValid(feed_url=None): """Returns True if provided url is valid ATOM or RSS. @@ -44,25 +46,12 @@ return False -LINKNAME_PATTERN = r'''(?x) - ^ - [0-9a-z] # start with ASCII digit or lowercase - ( - [0-9a-z] # additional ASCII digit or lowercase - | # -OR- - _[0-9a-z] # underscore and ASCII digit or lowercase - )* # zero or more of OR group - $ -''' - -LINKNAME_REGEX = re.compile(LINKNAME_PATTERN) - def isLinkNameFormatValid(link_name): """Returns True if link_name is in a valid format. Args: link_name: link name used in URLs for identification """ - if LINKNAME_REGEX.match(link_name): + if path_linkname.LINKNAME_REGEX.match(link_name): return True return False \ No newline at end of file diff -r 4d7bf6bdcd8f -r 8f23804302d0 app/soc/views/site/docs/edit.py --- a/app/soc/views/site/docs/edit.py Wed Oct 01 20:48:58 2008 +0000 +++ b/app/soc/views/site/docs/edit.py Wed Oct 01 20:52:39 2008 +0000 @@ -29,8 +29,8 @@ from django.utils.translation import ugettext_lazy from soc.logic import document -from soc.logic import key_name from soc.logic import out_of_band +from soc.logic import path_linkname from soc.logic.site import id_user from soc.views import simple from soc.views.helpers import custom_widgets @@ -76,7 +76,10 @@ Args: request: the standard django request object - path: the Document's site-unique "path" extracted from the URL + partial_path: the Document's site-unique "path" extracted from the URL, + minus the trailing link_name + link_name: the last portion of the Document's site-unique "path" + extracted from the URL template: the "sibling" template (or a search list of such templates) from which to construct the public.html template name (or names) @@ -115,7 +118,7 @@ doc = None # assume that no Document entity will be found - path = key_name.combinePath([partial_path, linkname]) + path = path_linkname.combinePath([partial_path, linkname]) # try to fetch Document entity corresponding to path if one exists try: @@ -145,7 +148,7 @@ if not doc: return http.HttpResponseRedirect('/') - new_path = key_name.combinePath([new_partial_path, new_linkname]) + new_path = path_linkname.combinePath([new_partial_path, new_linkname]) # redirect to new /site/docs/edit/new_path?s=0 # (causes 'Profile saved' message to be displayed) @@ -263,8 +266,7 @@ if not doc: return http.HttpResponseRedirect('/') - new_path = key_name.combinePathAndLinkName( - new_partial_path, new_linkname) + new_path = path_linkname.combinePath([new_partial_path, new_linkname]) # redirect to new /site/docs/edit/new_path?s=0 # (causes 'Profile saved' message to be displayed)